Description:
Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Vyper",
"sources": {
"src/eip7702_utils.vy": {
"content": "# pragma version ~=0.4.3
# pragma nonreentrancy off
"""
@title EIP-7702 Utility Functions
@custom:contract-name eip7702_utils
@license GNU Affero General Public License v3.0 only
@author pcaversaccio
@notice These functions can be used to interact with accounts that conform
to the EIP-7702 (https://eips.ethereum.org/EIPS/eip-7702) specification.
The implementation is inspired by OpenZeppelin's implementation here:
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/account/utils/EIP7702Utils.sol.
"""
# @dev The 3-byte EIP-7702 delegation prefix.
_DELEGATION_PREFIX: constant(bytes3) = 0xef0100
@deploy
@payable
def __init__():
"""
@dev To omit the opcodes for checking the `msg.value`
in the creation-time EVM bytecode, the constructor
is declared as `payable`.
"""
pass
@internal
@view
def _fetch_delegate(account: address) -> address:
"""
@dev Returns the current EIP-7702 delegation contract
for `account` if one has been set via a set code
transaction, or the zero address `empty(address)`
otherwise.
@notice Note that an `account` can revoke its delegation
at any time by setting the delegation contract to
the zero address `empty(address)` via a set code
transaction. However, this does not delete the
`account`'s storage, which remains intact.
@param account The 20-byte account address.
@return address The 20-byte delegation contract address.
"""
# For the special case where the code size does not equal 23 bytes,
# we already return `empty(address)` here in order not to iterate
# through the remaining code.
if account.codesize != 23:
return empty(address)
# Per EIP-7702, the delegation indicator is 23 bytes long, consisting
# of the prefix `0xef0100` followed by the 20-byte delegation address.
delegation: Bytes[23] = slice(account.code, 0, 23)
delegation_bytes32: bytes32 = convert(delegation, bytes32)
if convert(convert(delegation_bytes32 >> 232, uint24), bytes3) != _DELEGATION_PREFIX:
return empty(address)
return convert(convert(delegation_bytes32 << 24, bytes20), address)
@internal
@view
def _fetch_implementation(account: address) -> (bool, address):
"""
@dev Returns the delegated implementation for an EIP-7702 account.
@param account The 20-byte account address.
@return (bool, address)
bool - Whether the implementation could be resolved.
address - The delegated implementation address if resolution succeeded,
otherwise `empty(address)`.
"""
delegate: address = self._fetch_delegate(account)
if delegate == empty(address):
return False, empty(address)
if delegate.codesize == 0:
return False, empty(address)
response: Bytes[32] = raw_call(
delegate,
b"",
max_outsize=32,
is_static_call=True,
)
if len(response) != 32:
return False, empty(address)
implementation_bytes32: bytes32 = convert(response, bytes32)
implementation: address = convert(implementation_bytes32, address)
if implementation == empty(address):
return False, empty(address)
return True, implementation
",
"sha256sum": "cffc2b8a8536c4972673200abdc8474ad14bc96f1e0e65504876dbe62fb72a84"
},
"src/PortoENSRegistrar.vy": {
"content": "# pragma version ^0.4.3
from . import eip7702_utils
interface INameWrapper:
def setSubnodeOwner(parentNode: bytes32, label: String[32], owner: address, fuses: uint32, expiry: uint64): nonpayable
def setSubnodeRecord(parentNode: bytes32, label: String[32], owner: address, resolver: address, ttl: uint64, fuses: uint32, expiry: uint64): nonpayable
def ownerOf(tokenId: uint256) -> address: view
interface IPublicResolver:
def setAddr(node: bytes32, addr: address): nonpayable
interface IOrchestrator:
def accountImplementationOf(eoa: address) -> address: view
# Mainnet Namewrapper: 0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401
NameWrapper: immutable(INameWrapper)
PublicResolver: immutable(IPublicResolver) # Mainnet 0xF29100983E058B709F3D539b0c765937B804AC15
Orchestrator: constant(IOrchestrator) = IOrchestrator(0xB447BA5a2Fb841406cdac4585Fdc28027d7Ae503) # Mainnet
ITHACA_ACCOUNT_CODEHASH: constant(bytes32) = 0x17ba2f39f19a3928101a07252251d0a18889ce16033d33349df3b87a432242dd
ZERO_ADDR: constant(address) = empty(address)
CODE_ZERO_OFFSET_ONE: constant(uint256) = 6
CODE_ZERO_OFFSET_TWO: constant(uint256) = 39
CODE_ZERO_LENGTH: constant(uint256) = 32
CODE_PREFIX_LENGTH: constant(uint256) = 442
registered_node_by_address: public(HashMap[address, bytes32])
node_owner: HashMap[bytes32, address]
node_parent: HashMap[bytes32, bytes32]
node_label: HashMap[bytes32, String[32]]
@deploy
def __init__(namewrapper: INameWrapper, resolver: IPublicResolver):
NameWrapper = namewrapper
PublicResolver = resolver
@external
def register(parent_node: bytes32, label: String[32]):
assert self._checkIsPorto(msg.sender), "Account is not a valid Porto account"
node: bytes32 = keccak256(concat(parent_node, keccak256(label)))
token_id: uint256 = convert(node, uint256)
owner: address = staticcall NameWrapper.ownerOf(token_id)
assert owner == ZERO_ADDR or owner == self, "Subdomain already registered"
existing_node: bytes32 = self.registered_node_by_address[msg.sender]
if existing_node != empty(bytes32) and existing_node != node:
existing_parent: bytes32 = self.node_parent[existing_node]
existing_label: String[32] = self.node_label[existing_node]
if existing_parent != empty(bytes32) and len(existing_label) > 0:
extcall NameWrapper.setSubnodeOwner(
existing_parent,
existing_label,
self,
0,
max_value(uint64)
)
extcall PublicResolver.setAddr(existing_node, ZERO_ADDR)
self.node_owner[existing_node] = ZERO_ADDR
self.node_parent[existing_node] = empty(bytes32)
self.node_label[existing_node] = ""
extcall NameWrapper.setSubnodeOwner(
parent_node,
label,
self,
0,
max_value(uint64)
)
extcall PublicResolver.setAddr(node, msg.sender)
extcall NameWrapper.setSubnodeRecord(
parent_node,
label,
msg.sender,
PublicResolver.address,
0,
0,
max_value(uint64)
)
self.registered_node_by_address[msg.sender] = node
self.node_owner[node] = msg.sender
self.node_parent[node] = parent_node
self.node_label[node] = label
@internal
@view
def _checkIsPorto(account: address) -> bool:
success: bool = False
implementation: address = ZERO_ADDR
success, implementation = eip7702_utils._fetch_implementation(account)
if not success:
return False
implementation_code: Bytes[CODE_PREFIX_LENGTH] = slice(implementation.code, 0, CODE_PREFIX_LENGTH)
if len(implementation_code) != CODE_PREFIX_LENGTH:
return False
prefix_head: Bytes[CODE_ZERO_OFFSET_ONE] = slice(implementation_code, 0, CODE_ZERO_OFFSET_ONE)
interstitial: Bytes[CODE_ZERO_OFFSET_TWO - (CODE_ZERO_OFFSET_ONE + CODE_ZERO_LENGTH)] = slice(
implementation_code,
CODE_ZERO_OFFSET_ONE + CODE_ZERO_LENGTH,
CODE_ZERO_OFFSET_TWO - (CODE_ZERO_OFFSET_ONE + CODE_ZERO_LENGTH)
)
suffix: Bytes[CODE_PREFIX_LENGTH - (CODE_ZERO_OFFSET_TWO + CODE_ZERO_LENGTH)] = slice(
implementation_code,
CODE_ZERO_OFFSET_TWO + CODE_ZERO_LENGTH,
CODE_PREFIX_LENGTH - (CODE_ZERO_OFFSET_TWO + CODE_ZERO_LENGTH)
)
zeroed_code: Bytes[CODE_PREFIX_LENGTH] = concat(
prefix_head,
empty(bytes32),
interstitial,
empty(bytes32),
suffix
)
if keccak256(zeroed_code) != ITHACA_ACCOUNT_CODEHASH:
return False
return True
# ERC1155 Receiver functions
@external
def onERC1155Received(operator: address, from_: address, id: uint256,
_value: uint256, data: Bytes[1024]) -> bytes4:
return method_id("onERC1155Received(address,address,uint256,uint256,bytes)", output_type=bytes4)
@external
def onERC1155BatchReceived(operator: address, from_: address, ids: uint256,
values: uint256, data: Bytes[1024]) -> bytes4:
return method_id("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)", output_type=bytes4)
@external
def supportsInterface(interfaceID: bytes4) -> bool:
return interfaceID == 0x4e2312e0 or interfaceID == 0x01ffc9a7
",
"sha256sum": "e9cb0426ef0c955cb28acef131f7e1e1cb891379f8de060acd43ef58d501a676"
}
},
"settings": {
"outputSelection": {
"src/PortoENSRegistrar.vy": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
},
"search_paths": [
"."
]
},
"compiler_version": "v0.4.3+commit.bff19ea2",
"integrity": "a95673a402a5e090ee50302903c2ba7bbde24b613457e7beae36e93bc916cb01"
}}
Submitted on: 2025-09-20 13:34:11
Comments
Log in to comment.
No comments yet.