Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
7.44 ETH
Eth Value
$24,475.41 (@ $3,289.71/ETH)Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 16,694 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Delegate All | 21463273 | 9 mins ago | IN | 0 ETH | 0.00061346 | ||||
Delegate ERC721 | 21463032 | 58 mins ago | IN | 0 ETH | 0.00085252 | ||||
Delegate All | 21462802 | 1 hr ago | IN | 0 ETH | 0.00016979 | ||||
Delegate ERC721 | 21462521 | 2 hrs ago | IN | 0 ETH | 0.00029446 | ||||
Delegate All | 21462515 | 2 hrs ago | IN | 0 ETH | 0.00136138 | ||||
Delegate ERC721 | 21462465 | 2 hrs ago | IN | 0 ETH | 0.00145865 | ||||
Delegate All | 21462140 | 3 hrs ago | IN | 0.005 ETH | 0.00084728 | ||||
Delegate All | 21462117 | 4 hrs ago | IN | 0.005 ETH | 0.00057753 | ||||
Delegate All | 21462089 | 4 hrs ago | IN | 0.005 ETH | 0.0005829 | ||||
Delegate All | 21462030 | 4 hrs ago | IN | 0.005 ETH | 0.00062832 | ||||
Delegate All | 21461994 | 4 hrs ago | IN | 0.005 ETH | 0.0006292 | ||||
Delegate All | 21461971 | 4 hrs ago | IN | 0.005 ETH | 0.00068766 | ||||
Delegate All | 21461907 | 4 hrs ago | IN | 0.005 ETH | 0.00061372 | ||||
Delegate All | 21461826 | 5 hrs ago | IN | 0.005 ETH | 0.00060548 | ||||
Delegate All | 21461739 | 5 hrs ago | IN | 0.005 ETH | 0.00064531 | ||||
Delegate All | 21461618 | 5 hrs ago | IN | 0.005 ETH | 0.00062405 | ||||
Delegate All | 21461551 | 5 hrs ago | IN | 0 ETH | 0.00016381 | ||||
Delegate All | 21461545 | 5 hrs ago | IN | 0.005 ETH | 0.00089218 | ||||
Delegate ERC721 | 21461536 | 5 hrs ago | IN | 0 ETH | 0.00081304 | ||||
Delegate All | 21461461 | 6 hrs ago | IN | 0.005 ETH | 0.00060049 | ||||
Delegate All | 21461356 | 6 hrs ago | IN | 0.005 ETH | 0.00062594 | ||||
Delegate All | 21461170 | 7 hrs ago | IN | 0.005 ETH | 0.00074381 | ||||
Delegate All | 21461157 | 7 hrs ago | IN | 0.005 ETH | 0.00078375 | ||||
Delegate All | 21461039 | 7 hrs ago | IN | 0.005 ETH | 0.00108915 | ||||
Delegate All | 21460893 | 8 hrs ago | IN | 0 ETH | 0.0002227 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21396625 | 9 days ago | 0.005 ETH | ||||
21386979 | 10 days ago | 0.005 ETH | ||||
21375823 | 12 days ago | 0.005 ETH | ||||
21365204 | 13 days ago | 0.005 ETH | ||||
21328339 | 18 days ago | 0.005 ETH | ||||
21200616 | 36 days ago | 0.005 ETH | ||||
21071680 | 54 days ago | 0.005 ETH | ||||
20986348 | 66 days ago | 0.005 ETH | ||||
20956710 | 70 days ago | 0.005 ETH | ||||
20947232 | 72 days ago | 0.005 ETH | ||||
20944244 | 72 days ago | 0.005 ETH | ||||
20936373 | 73 days ago | 0.005 ETH | ||||
20878465 | 81 days ago | 0.005 ETH | ||||
20837433 | 87 days ago | 0.005 ETH | ||||
20812395 | 90 days ago | 0.005 ETH | ||||
20685927 | 108 days ago | 1.475 ETH | ||||
20672041 | 110 days ago | 0.005 ETH | ||||
20646588 | 114 days ago | 0.005 ETH | ||||
20646560 | 114 days ago | 0.005 ETH | ||||
20646498 | 114 days ago | 0.005 ETH | ||||
20633109 | 115 days ago | 0.005 ETH | ||||
20629545 | 116 days ago | 0.005 ETH | ||||
20615447 | 118 days ago | 0.005 ETH | ||||
20615447 | 118 days ago | 0.005 ETH | ||||
20593201 | 121 days ago | 0.005 ETH |
Loading...
Loading
Contract Name:
DelegateRegistry
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 9999999 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.21; import {IDelegateRegistry as IDelegateRegistry} from "./IDelegateRegistry.sol"; import {RegistryHashes as Hashes} from "./libraries/RegistryHashes.sol"; import {RegistryStorage as Storage} from "./libraries/RegistryStorage.sol"; import {RegistryOps as Ops} from "./libraries/RegistryOps.sol"; /** * @title DelegateRegistry * @custom:version 2.0 * @custom:coauthor foobar (0xfoobar) * @custom:coauthor mireynolds * @notice A standalone immutable registry storing delegated permissions from one address to another */ contract DelegateRegistry is IDelegateRegistry { /// @dev Only this mapping should be used to verify delegations; the other mapping arrays are for enumerations mapping(bytes32 delegationHash => bytes32[5] delegationStorage) internal delegations; /// @dev Vault delegation enumeration outbox, for pushing new hashes only mapping(address from => bytes32[] delegationHashes) internal outgoingDelegationHashes; /// @dev Delegate enumeration inbox, for pushing new hashes only mapping(address to => bytes32[] delegationHashes) internal incomingDelegationHashes; /** * ----------- WRITE ----------- */ /// @inheritdoc IDelegateRegistry function multicall(bytes[] calldata data) external payable override returns (bytes[] memory results) { results = new bytes[](data.length); bool success; unchecked { for (uint256 i = 0; i < data.length; ++i) { //slither-disable-next-line calls-loop,delegatecall-loop (success, results[i]) = address(this).delegatecall(data[i]); if (!success) revert MulticallFailed(); } } } /// @inheritdoc IDelegateRegistry function delegateAll(address to, bytes32 rights, bool enable) external payable override returns (bytes32 hash) { hash = Hashes.allHash(msg.sender, rights, to); bytes32 location = Hashes.location(hash); address loadedFrom = _loadFrom(location); if (enable) { if (loadedFrom == Storage.DELEGATION_EMPTY) { _pushDelegationHashes(msg.sender, to, hash); _writeDelegationAddresses(location, msg.sender, to, address(0)); if (rights != "") _writeDelegation(location, Storage.POSITIONS_RIGHTS, rights); } else if (loadedFrom == Storage.DELEGATION_REVOKED) { _updateFrom(location, msg.sender); } } else if (loadedFrom == msg.sender) { _updateFrom(location, Storage.DELEGATION_REVOKED); } emit DelegateAll(msg.sender, to, rights, enable); } /// @inheritdoc IDelegateRegistry function delegateContract(address to, address contract_, bytes32 rights, bool enable) external payable override returns (bytes32 hash) { hash = Hashes.contractHash(msg.sender, rights, to, contract_); bytes32 location = Hashes.location(hash); address loadedFrom = _loadFrom(location); if (enable) { if (loadedFrom == Storage.DELEGATION_EMPTY) { _pushDelegationHashes(msg.sender, to, hash); _writeDelegationAddresses(location, msg.sender, to, contract_); if (rights != "") _writeDelegation(location, Storage.POSITIONS_RIGHTS, rights); } else if (loadedFrom == Storage.DELEGATION_REVOKED) { _updateFrom(location, msg.sender); } } else if (loadedFrom == msg.sender) { _updateFrom(location, Storage.DELEGATION_REVOKED); } emit DelegateContract(msg.sender, to, contract_, rights, enable); } /// @inheritdoc IDelegateRegistry function delegateERC721(address to, address contract_, uint256 tokenId, bytes32 rights, bool enable) external payable override returns (bytes32 hash) { hash = Hashes.erc721Hash(msg.sender, rights, to, tokenId, contract_); bytes32 location = Hashes.location(hash); address loadedFrom = _loadFrom(location); if (enable) { if (loadedFrom == Storage.DELEGATION_EMPTY) { _pushDelegationHashes(msg.sender, to, hash); _writeDelegationAddresses(location, msg.sender, to, contract_); _writeDelegation(location, Storage.POSITIONS_TOKEN_ID, tokenId); if (rights != "") _writeDelegation(location, Storage.POSITIONS_RIGHTS, rights); } else if (loadedFrom == Storage.DELEGATION_REVOKED) { _updateFrom(location, msg.sender); } } else if (loadedFrom == msg.sender) { _updateFrom(location, Storage.DELEGATION_REVOKED); } emit DelegateERC721(msg.sender, to, contract_, tokenId, rights, enable); } // @inheritdoc IDelegateRegistry function delegateERC20(address to, address contract_, bytes32 rights, uint256 amount) external payable override returns (bytes32 hash) { hash = Hashes.erc20Hash(msg.sender, rights, to, contract_); bytes32 location = Hashes.location(hash); address loadedFrom = _loadFrom(location); if (amount != 0) { if (loadedFrom == Storage.DELEGATION_EMPTY) { _pushDelegationHashes(msg.sender, to, hash); _writeDelegationAddresses(location, msg.sender, to, contract_); _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount); if (rights != "") _writeDelegation(location, Storage.POSITIONS_RIGHTS, rights); } else if (loadedFrom == Storage.DELEGATION_REVOKED) { _updateFrom(location, msg.sender); _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount); } else if (loadedFrom == msg.sender) { _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount); } } else if (loadedFrom == msg.sender) { _updateFrom(location, Storage.DELEGATION_REVOKED); _writeDelegation(location, Storage.POSITIONS_AMOUNT, uint256(0)); } emit DelegateERC20(msg.sender, to, contract_, rights, amount); } /// @inheritdoc IDelegateRegistry function delegateERC1155(address to, address contract_, uint256 tokenId, bytes32 rights, uint256 amount) external payable override returns (bytes32 hash) { hash = Hashes.erc1155Hash(msg.sender, rights, to, tokenId, contract_); bytes32 location = Hashes.location(hash); address loadedFrom = _loadFrom(location); if (amount != 0) { if (loadedFrom == Storage.DELEGATION_EMPTY) { _pushDelegationHashes(msg.sender, to, hash); _writeDelegationAddresses(location, msg.sender, to, contract_); _writeDelegation(location, Storage.POSITIONS_TOKEN_ID, tokenId); _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount); if (rights != "") _writeDelegation(location, Storage.POSITIONS_RIGHTS, rights); } else if (loadedFrom == Storage.DELEGATION_REVOKED) { _updateFrom(location, msg.sender); _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount); } else if (loadedFrom == msg.sender) { _writeDelegation(location, Storage.POSITIONS_AMOUNT, amount); } } else if (loadedFrom == msg.sender) { _updateFrom(location, Storage.DELEGATION_REVOKED); _writeDelegation(location, Storage.POSITIONS_AMOUNT, uint256(0)); } emit DelegateERC1155(msg.sender, to, contract_, tokenId, rights, amount); } /// @dev Transfer native token out function sweep() external { assembly ("memory-safe") { // This hardcoded address is a CREATE2 factory counterfactual smart contract wallet that will always accept native token transfers let result := call(gas(), 0x000000dE1E80ea5a234FB5488fee2584251BC7e8, selfbalance(), 0, 0, 0, 0) } } /** * ----------- CHECKS ----------- */ /// @inheritdoc IDelegateRegistry function checkDelegateForAll(address to, address from, bytes32 rights) external view override returns (bool valid) { if (!_invalidFrom(from)) { valid = _validateFrom(Hashes.allLocation(from, "", to), from); if (!Ops.or(rights == "", valid)) valid = _validateFrom(Hashes.allLocation(from, rights, to), from); } assembly ("memory-safe") { // Only first 32 bytes of scratch space is accessed mstore(0, iszero(iszero(valid))) // Compiler cleans dirty booleans on the stack to 1, so do the same here return(0, 32) // Direct return, skips Solidity's redundant copying to save gas } } /// @inheritdoc IDelegateRegistry function checkDelegateForContract(address to, address from, address contract_, bytes32 rights) external view override returns (bool valid) { if (!_invalidFrom(from)) { valid = _validateFrom(Hashes.allLocation(from, "", to), from) || _validateFrom(Hashes.contractLocation(from, "", to, contract_), from); if (!Ops.or(rights == "", valid)) { valid = _validateFrom(Hashes.allLocation(from, rights, to), from) || _validateFrom(Hashes.contractLocation(from, rights, to, contract_), from); } } assembly ("memory-safe") { // Only first 32 bytes of scratch space is accessed mstore(0, iszero(iszero(valid))) // Compiler cleans dirty booleans on the stack to 1, so do the same here return(0, 32) // Direct return, skips Solidity's redundant copying to save gas } } /// @inheritdoc IDelegateRegistry function checkDelegateForERC721(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view override returns (bool valid) { if (!_invalidFrom(from)) { valid = _validateFrom(Hashes.allLocation(from, "", to), from) || _validateFrom(Hashes.contractLocation(from, "", to, contract_), from) || _validateFrom(Hashes.erc721Location(from, "", to, tokenId, contract_), from); if (!Ops.or(rights == "", valid)) { valid = _validateFrom(Hashes.allLocation(from, rights, to), from) || _validateFrom(Hashes.contractLocation(from, rights, to, contract_), from) || _validateFrom(Hashes.erc721Location(from, rights, to, tokenId, contract_), from); } } assembly ("memory-safe") { // Only first 32 bytes of scratch space is accessed mstore(0, iszero(iszero(valid))) // Compiler cleans dirty booleans on the stack to 1, so do the same here return(0, 32) // Direct return, skips Solidity's redundant copying to save gas } } /// @inheritdoc IDelegateRegistry function checkDelegateForERC20(address to, address from, address contract_, bytes32 rights) external view override returns (uint256 amount) { if (!_invalidFrom(from)) { amount = (_validateFrom(Hashes.allLocation(from, "", to), from) || _validateFrom(Hashes.contractLocation(from, "", to, contract_), from)) ? type(uint256).max : _loadDelegationUint(Hashes.erc20Location(from, "", to, contract_), Storage.POSITIONS_AMOUNT); if (!Ops.or(rights == "", amount == type(uint256).max)) { uint256 rightsBalance = (_validateFrom(Hashes.allLocation(from, rights, to), from) || _validateFrom(Hashes.contractLocation(from, rights, to, contract_), from)) ? type(uint256).max : _loadDelegationUint(Hashes.erc20Location(from, rights, to, contract_), Storage.POSITIONS_AMOUNT); amount = Ops.max(rightsBalance, amount); } } assembly ("memory-safe") { mstore(0, amount) // Only first 32 bytes of scratch space being accessed return(0, 32) // Direct return, skips Solidity's redundant copying to save gas } } /// @inheritdoc IDelegateRegistry function checkDelegateForERC1155(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view override returns (uint256 amount) { if (!_invalidFrom(from)) { amount = (_validateFrom(Hashes.allLocation(from, "", to), from) || _validateFrom(Hashes.contractLocation(from, "", to, contract_), from)) ? type(uint256).max : _loadDelegationUint(Hashes.erc1155Location(from, "", to, tokenId, contract_), Storage.POSITIONS_AMOUNT); if (!Ops.or(rights == "", amount == type(uint256).max)) { uint256 rightsBalance = (_validateFrom(Hashes.allLocation(from, rights, to), from) || _validateFrom(Hashes.contractLocation(from, rights, to, contract_), from)) ? type(uint256).max : _loadDelegationUint(Hashes.erc1155Location(from, rights, to, tokenId, contract_), Storage.POSITIONS_AMOUNT); amount = Ops.max(rightsBalance, amount); } } assembly ("memory-safe") { mstore(0, amount) // Only first 32 bytes of scratch space is accessed return(0, 32) // Direct return, skips Solidity's redundant copying to save gas } } /** * ----------- ENUMERATIONS ----------- */ /// @inheritdoc IDelegateRegistry function getIncomingDelegations(address to) external view override returns (Delegation[] memory delegations_) { delegations_ = _getValidDelegationsFromHashes(incomingDelegationHashes[to]); } /// @inheritdoc IDelegateRegistry function getOutgoingDelegations(address from) external view returns (Delegation[] memory delegations_) { delegations_ = _getValidDelegationsFromHashes(outgoingDelegationHashes[from]); } /// @inheritdoc IDelegateRegistry function getIncomingDelegationHashes(address to) external view returns (bytes32[] memory delegationHashes) { delegationHashes = _getValidDelegationHashesFromHashes(incomingDelegationHashes[to]); } /// @inheritdoc IDelegateRegistry function getOutgoingDelegationHashes(address from) external view returns (bytes32[] memory delegationHashes) { delegationHashes = _getValidDelegationHashesFromHashes(outgoingDelegationHashes[from]); } /// @inheritdoc IDelegateRegistry function getDelegationsFromHashes(bytes32[] calldata hashes) external view returns (Delegation[] memory delegations_) { delegations_ = new Delegation[](hashes.length); unchecked { for (uint256 i = 0; i < hashes.length; ++i) { bytes32 location = Hashes.location(hashes[i]); address from = _loadFrom(location); if (_invalidFrom(from)) { delegations_[i] = Delegation({type_: DelegationType.NONE, to: address(0), from: address(0), rights: "", amount: 0, contract_: address(0), tokenId: 0}); } else { (, address to, address contract_) = _loadDelegationAddresses(location); delegations_[i] = Delegation({ type_: Hashes.decodeType(hashes[i]), to: to, from: from, rights: _loadDelegationBytes32(location, Storage.POSITIONS_RIGHTS), amount: _loadDelegationUint(location, Storage.POSITIONS_AMOUNT), contract_: contract_, tokenId: _loadDelegationUint(location, Storage.POSITIONS_TOKEN_ID) }); } } } } /** * ----------- EXTERNAL STORAGE ACCESS ----------- */ function readSlot(bytes32 location) external view returns (bytes32 contents) { assembly { contents := sload(location) } } function readSlots(bytes32[] calldata locations) external view returns (bytes32[] memory contents) { uint256 length = locations.length; contents = new bytes32[](length); bytes32 tempLocation; bytes32 tempValue; unchecked { for (uint256 i = 0; i < length; ++i) { tempLocation = locations[i]; assembly { tempValue := sload(tempLocation) } contents[i] = tempValue; } } } /** * ----------- ERC165 ----------- */ /// @notice Query if a contract implements an ERC-165 interface /// @param interfaceId The interface identifier /// @return valid Whether the queried interface is supported function supportsInterface(bytes4 interfaceId) external pure returns (bool) { return Ops.or(interfaceId == type(IDelegateRegistry).interfaceId, interfaceId == 0x01ffc9a7); } /** * ----------- INTERNAL ----------- */ /// @dev Helper function to push new delegation hashes to the incoming and outgoing hashes mappings function _pushDelegationHashes(address from, address to, bytes32 delegationHash) internal { outgoingDelegationHashes[from].push(delegationHash); incomingDelegationHashes[to].push(delegationHash); } /// @dev Helper function that writes bytes32 data to delegation data location at array position function _writeDelegation(bytes32 location, uint256 position, bytes32 data) internal { assembly { sstore(add(location, position), data) } } /// @dev Helper function that writes uint256 data to delegation data location at array position function _writeDelegation(bytes32 location, uint256 position, uint256 data) internal { assembly { sstore(add(location, position), data) } } /// @dev Helper function that writes addresses according to the packing rule for delegation storage function _writeDelegationAddresses(bytes32 location, address from, address to, address contract_) internal { (bytes32 firstSlot, bytes32 secondSlot) = Storage.packAddresses(from, to, contract_); uint256 firstPacked = Storage.POSITIONS_FIRST_PACKED; uint256 secondPacked = Storage.POSITIONS_SECOND_PACKED; assembly { sstore(add(location, firstPacked), firstSlot) sstore(add(location, secondPacked), secondSlot) } } /// @dev Helper function that writes `from` while preserving the rest of the storage slot function _updateFrom(bytes32 location, address from) internal { uint256 firstPacked = Storage.POSITIONS_FIRST_PACKED; uint256 cleanAddress = Storage.CLEAN_ADDRESS; uint256 cleanUpper12Bytes = type(uint256).max << 160; assembly { let slot := and(sload(add(location, firstPacked)), cleanUpper12Bytes) sstore(add(location, firstPacked), or(slot, and(from, cleanAddress))) } } /// @dev Helper function that takes an array of delegation hashes and returns an array of Delegation structs with their onchain information function _getValidDelegationsFromHashes(bytes32[] storage hashes) internal view returns (Delegation[] memory delegations_) { uint256 count = 0; uint256 hashesLength = hashes.length; bytes32 hash; bytes32[] memory filteredHashes = new bytes32[](hashesLength); unchecked { for (uint256 i = 0; i < hashesLength; ++i) { hash = hashes[i]; if (_invalidFrom(_loadFrom(Hashes.location(hash)))) continue; filteredHashes[count++] = hash; } delegations_ = new Delegation[](count); bytes32 location; for (uint256 i = 0; i < count; ++i) { hash = filteredHashes[i]; location = Hashes.location(hash); (address from, address to, address contract_) = _loadDelegationAddresses(location); delegations_[i] = Delegation({ type_: Hashes.decodeType(hash), to: to, from: from, rights: _loadDelegationBytes32(location, Storage.POSITIONS_RIGHTS), amount: _loadDelegationUint(location, Storage.POSITIONS_AMOUNT), contract_: contract_, tokenId: _loadDelegationUint(location, Storage.POSITIONS_TOKEN_ID) }); } } } /// @dev Helper function that takes an array of delegation hashes and returns an array of valid delegation hashes function _getValidDelegationHashesFromHashes(bytes32[] storage hashes) internal view returns (bytes32[] memory validHashes) { uint256 count = 0; uint256 hashesLength = hashes.length; bytes32 hash; bytes32[] memory filteredHashes = new bytes32[](hashesLength); unchecked { for (uint256 i = 0; i < hashesLength; ++i) { hash = hashes[i]; if (_invalidFrom(_loadFrom(Hashes.location(hash)))) continue; filteredHashes[count++] = hash; } validHashes = new bytes32[](count); for (uint256 i = 0; i < count; ++i) { validHashes[i] = filteredHashes[i]; } } } /// @dev Helper function that loads delegation data from a particular array position and returns as bytes32 function _loadDelegationBytes32(bytes32 location, uint256 position) internal view returns (bytes32 data) { assembly { data := sload(add(location, position)) } } /// @dev Helper function that loads delegation data from a particular array position and returns as uint256 function _loadDelegationUint(bytes32 location, uint256 position) internal view returns (uint256 data) { assembly { data := sload(add(location, position)) } } // @dev Helper function that loads the from address from storage according to the packing rule for delegation storage function _loadFrom(bytes32 location) internal view returns (address) { bytes32 data; uint256 firstPacked = Storage.POSITIONS_FIRST_PACKED; assembly { data := sload(add(location, firstPacked)) } return Storage.unpackAddress(data); } /// @dev Helper function to establish whether a delegation is enabled function _validateFrom(bytes32 location, address from) internal view returns (bool) { return (from == _loadFrom(location)); } /// @dev Helper function that loads the address for the delegation according to the packing rule for delegation storage function _loadDelegationAddresses(bytes32 location) internal view returns (address from, address to, address contract_) { bytes32 firstSlot; bytes32 secondSlot; uint256 firstPacked = Storage.POSITIONS_FIRST_PACKED; uint256 secondPacked = Storage.POSITIONS_SECOND_PACKED; assembly { firstSlot := sload(add(location, firstPacked)) secondSlot := sload(add(location, secondPacked)) } (from, to, contract_) = Storage.unpackAddresses(firstSlot, secondSlot); } function _invalidFrom(address from) internal pure returns (bool) { return Ops.or(from == Storage.DELEGATION_EMPTY, from == Storage.DELEGATION_REVOKED); } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity >=0.8.13; /** * @title IDelegateRegistry * @custom:version 2.0 * @custom:author foobar (0xfoobar) * @notice A standalone immutable registry storing delegated permissions from one address to another */ interface IDelegateRegistry { /// @notice Delegation type, NONE is used when a delegation does not exist or is revoked enum DelegationType { NONE, ALL, CONTRACT, ERC721, ERC20, ERC1155 } /// @notice Struct for returning delegations struct Delegation { DelegationType type_; address to; address from; bytes32 rights; address contract_; uint256 tokenId; uint256 amount; } /// @notice Emitted when an address delegates or revokes rights for their entire wallet event DelegateAll(address indexed from, address indexed to, bytes32 rights, bool enable); /// @notice Emitted when an address delegates or revokes rights for a contract address event DelegateContract(address indexed from, address indexed to, address indexed contract_, bytes32 rights, bool enable); /// @notice Emitted when an address delegates or revokes rights for an ERC721 tokenId event DelegateERC721(address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, bool enable); /// @notice Emitted when an address delegates or revokes rights for an amount of ERC20 tokens event DelegateERC20(address indexed from, address indexed to, address indexed contract_, bytes32 rights, uint256 amount); /// @notice Emitted when an address delegates or revokes rights for an amount of an ERC1155 tokenId event DelegateERC1155(address indexed from, address indexed to, address indexed contract_, uint256 tokenId, bytes32 rights, uint256 amount); /// @notice Thrown if multicall calldata is malformed error MulticallFailed(); /** * ----------- WRITE ----------- */ /** * @notice Call multiple functions in the current contract and return the data from all of them if they all succeed * @param data The encoded function data for each of the calls to make to this contract * @return results The results from each of the calls passed in via data */ function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); /** * @notice Allow the delegate to act on behalf of `msg.sender` for all contracts * @param to The address to act as delegate * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights * @param enable Whether to enable or disable this delegation, true delegates and false revokes * @return delegationHash The unique identifier of the delegation */ function delegateAll(address to, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash); /** * @notice Allow the delegate to act on behalf of `msg.sender` for a specific contract * @param to The address to act as delegate * @param contract_ The contract whose rights are being delegated * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights * @param enable Whether to enable or disable this delegation, true delegates and false revokes * @return delegationHash The unique identifier of the delegation */ function delegateContract(address to, address contract_, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash); /** * @notice Allow the delegate to act on behalf of `msg.sender` for a specific ERC721 token * @param to The address to act as delegate * @param contract_ The contract whose rights are being delegated * @param tokenId The token id to delegate * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights * @param enable Whether to enable or disable this delegation, true delegates and false revokes * @return delegationHash The unique identifier of the delegation */ function delegateERC721(address to, address contract_, uint256 tokenId, bytes32 rights, bool enable) external payable returns (bytes32 delegationHash); /** * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC20 tokens * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound) * @param to The address to act as delegate * @param contract_ The address for the fungible token contract * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights * @param amount The amount to delegate, > 0 delegates and 0 revokes * @return delegationHash The unique identifier of the delegation */ function delegateERC20(address to, address contract_, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash); /** * @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC1155 tokens * @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound) * @param to The address to act as delegate * @param contract_ The address of the contract that holds the token * @param tokenId The token id to delegate * @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights * @param amount The amount of that token id to delegate, > 0 delegates and 0 revokes * @return delegationHash The unique identifier of the delegation */ function delegateERC1155(address to, address contract_, uint256 tokenId, bytes32 rights, uint256 amount) external payable returns (bytes32 delegationHash); /** * ----------- CHECKS ----------- */ /** * @notice Check if `to` is a delegate of `from` for the entire wallet * @param to The potential delegate address * @param from The potential address who delegated rights * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only * @return valid Whether delegate is granted to act on the from's behalf */ function checkDelegateForAll(address to, address from, bytes32 rights) external view returns (bool); /** * @notice Check if `to` is a delegate of `from` for the specified `contract_` or the entire wallet * @param to The delegated address to check * @param contract_ The specific contract address being checked * @param from The cold wallet who issued the delegation * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only * @return valid Whether delegate is granted to act on from's behalf for entire wallet or that specific contract */ function checkDelegateForContract(address to, address from, address contract_, bytes32 rights) external view returns (bool); /** * @notice Check if `to` is a delegate of `from` for the specific `contract` and `tokenId`, the entire `contract_`, or the entire wallet * @param to The delegated address to check * @param contract_ The specific contract address being checked * @param tokenId The token id for the token to delegating * @param from The wallet that issued the delegation * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only * @return valid Whether delegate is granted to act on from's behalf for entire wallet, that contract, or that specific tokenId */ function checkDelegateForERC721(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (bool); /** * @notice Returns the amount of ERC20 tokens the delegate is granted rights to act on the behalf of * @param to The delegated address to check * @param contract_ The address of the token contract * @param from The cold wallet who issued the delegation * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only * @return balance The delegated balance, which will be 0 if the delegation does not exist */ function checkDelegateForERC20(address to, address from, address contract_, bytes32 rights) external view returns (uint256); /** * @notice Returns the amount of a ERC1155 tokens the delegate is granted rights to act on the behalf of * @param to The delegated address to check * @param contract_ The address of the token contract * @param tokenId The token id to check the delegated amount of * @param from The cold wallet who issued the delegation * @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only * @return balance The delegated balance, which will be 0 if the delegation does not exist */ function checkDelegateForERC1155(address to, address from, address contract_, uint256 tokenId, bytes32 rights) external view returns (uint256); /** * ----------- ENUMERATIONS ----------- */ /** * @notice Returns all enabled delegations a given delegate has received * @param to The address to retrieve delegations for * @return delegations Array of Delegation structs */ function getIncomingDelegations(address to) external view returns (Delegation[] memory delegations); /** * @notice Returns all enabled delegations an address has given out * @param from The address to retrieve delegations for * @return delegations Array of Delegation structs */ function getOutgoingDelegations(address from) external view returns (Delegation[] memory delegations); /** * @notice Returns all hashes associated with enabled delegations an address has received * @param to The address to retrieve incoming delegation hashes for * @return delegationHashes Array of delegation hashes */ function getIncomingDelegationHashes(address to) external view returns (bytes32[] memory delegationHashes); /** * @notice Returns all hashes associated with enabled delegations an address has given out * @param from The address to retrieve outgoing delegation hashes for * @return delegationHashes Array of delegation hashes */ function getOutgoingDelegationHashes(address from) external view returns (bytes32[] memory delegationHashes); /** * @notice Returns the delegations for a given array of delegation hashes * @param delegationHashes is an array of hashes that correspond to delegations * @return delegations Array of Delegation structs, return empty structs for nonexistent or revoked delegations */ function getDelegationsFromHashes(bytes32[] calldata delegationHashes) external view returns (Delegation[] memory delegations); /** * ----------- STORAGE ACCESS ----------- */ /** * @notice Allows external contracts to read arbitrary storage slots */ function readSlot(bytes32 location) external view returns (bytes32); /** * @notice Allows external contracts to read an arbitrary array of storage slots */ function readSlots(bytes32[] calldata locations) external view returns (bytes32[] memory); }
// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.21; import {IDelegateRegistry} from "../IDelegateRegistry.sol"; /** * @title Library for calculating the hashes and storage locations used in the delegate registry * * The encoding for the 5 types of delegate registry hashes should be as follows: * * ALL: keccak256(abi.encodePacked(rights, from, to)) * CONTRACT: keccak256(abi.encodePacked(rights, from, to, contract_)) * ERC721: keccak256(abi.encodePacked(rights, from, to, contract_, tokenId)) * ERC20: keccak256(abi.encodePacked(rights, from, to, contract_)) * ERC1155: keccak256(abi.encodePacked(rights, from, to, contract_, tokenId)) * * To avoid collisions between the hashes with respect to type, the hash is shifted left by one byte * and the last byte is then encoded with a unique number for the delegation type * */ library RegistryHashes { /// @dev Used to delete everything but the last byte of a 32 byte word with and(word, EXTRACT_LAST_BYTE) uint256 internal constant EXTRACT_LAST_BYTE = 0xff; /// @dev Constants for the delegate registry delegation type enumeration uint256 internal constant ALL_TYPE = 1; uint256 internal constant CONTRACT_TYPE = 2; uint256 internal constant ERC721_TYPE = 3; uint256 internal constant ERC20_TYPE = 4; uint256 internal constant ERC1155_TYPE = 5; /// @dev Constant for the location of the delegations array in the delegate registry, defined to be zero uint256 internal constant DELEGATION_SLOT = 0; /** * @notice Helper function to decode last byte of a delegation hash into its delegation type enum * @param inputHash The bytehash to decode the type from * @return decodedType The delegation type */ function decodeType(bytes32 inputHash) internal pure returns (IDelegateRegistry.DelegationType decodedType) { assembly { decodedType := and(inputHash, EXTRACT_LAST_BYTE) } } /** * @notice Helper function that computes the storage location of a particular delegation array * @dev Storage keys further down the array can be obtained by adding computedLocation with the element position * @dev Follows the solidity storage location encoding for a mapping(bytes32 => fixedArray) at the position of the delegationSlot * @param inputHash The bytehash to decode the type from * @return computedLocation is the storage key of the delegation array at position 0 */ function location(bytes32 inputHash) internal pure returns (bytes32 computedLocation) { assembly ("memory-safe") { // This block only allocates memory in the scratch space mstore(0, inputHash) mstore(32, DELEGATION_SLOT) computedLocation := keccak256(0, 64) // Run keccak256 over bytes in scratch space to obtain the storage key } } /** * @notice Helper function to compute delegation hash for `DelegationType.ALL` * @dev Equivalent to `keccak256(abi.encodePacked(rights, from, to))` then left-shift by 1 byte and write the delegation type to the cleaned last byte * @dev Will not revert if `from` or `to` are > uint160, any input larger than uint160 for `from` and `to` will be cleaned to its lower 20 bytes * @param from The address making the delegation * @param rights The rights specified by the delegation * @param to The address receiving the delegation * @return hash The delegation parameters encoded with ALL_TYPE */ function allHash(address from, bytes32 rights, address to) internal pure returns (bytes32 hash) { assembly ("memory-safe") { // This block only allocates memory after the free memory pointer let ptr := mload(64) // Load the free memory pointer // Lay out the variables from last to first, agnostic to upper 96 bits of address words. mstore(add(ptr, 40), to) mstore(add(ptr, 20), from) mstore(ptr, rights) hash := or(shl(8, keccak256(ptr, 72)), ALL_TYPE) // Keccak-hashes the packed encoding, left-shifts by one byte, then writes type to the lowest-order byte } } /** * @notice Helper function to compute delegation location for `DelegationType.ALL` * @dev Equivalent to `location(allHash(rights, from, to))` * @dev Will not revert if `from` or `to` are > uint160, any input larger than uint160 for `from` and `to` will be cleaned to its lower 20 bytes * @param from The address making the delegation * @param rights The rights specified by the delegation * @param to The address receiving the delegation * @return computedLocation The storage location of the all delegation with those parameters in the delegations mapping */ function allLocation(address from, bytes32 rights, address to) internal pure returns (bytes32 computedLocation) { assembly ("memory-safe") { // This block only allocates memory after the free memory pointer and in the scratch space let ptr := mload(64) // Load the free memory pointer // Lay out the variables from last to first, agnostic to upper 96 bits of address words. mstore(add(ptr, 40), to) mstore(add(ptr, 20), from) mstore(ptr, rights) mstore(0, or(shl(8, keccak256(ptr, 72)), ALL_TYPE)) // Computes `allHash`, then stores the result in scratch space mstore(32, DELEGATION_SLOT) computedLocation := keccak256(0, 64) // Runs keccak over the scratch space to obtain the storage key } } /** * @notice Helper function to compute delegation hash for `DelegationType.CONTRACT` * @dev Equivalent to keccak256(abi.encodePacked(rights, from, to, contract_)) left-shifted by 1 then last byte overwritten with CONTRACT_TYPE * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes * @param from The address making the delegation * @param rights The rights specified by the delegation * @param to The address receiving the delegation * @param contract_ The address of the contract specified by the delegation * @return hash The delegation parameters encoded with CONTRACT_TYPE */ function contractHash(address from, bytes32 rights, address to, address contract_) internal pure returns (bytes32 hash) { assembly ("memory-safe") { // This block only allocates memory after the free memory pointer let ptr := mload(64) // Load the free memory pointer // Lay out the variables from last to first, agnostic to upper 96 bits of address words. mstore(add(ptr, 60), contract_) mstore(add(ptr, 40), to) mstore(add(ptr, 20), from) mstore(ptr, rights) hash := or(shl(8, keccak256(ptr, 92)), CONTRACT_TYPE) // Keccak-hashes the packed encoding, left-shifts by one byte, then writes type to the lowest-order byte } } /** * @notice Helper function to compute delegation location for `DelegationType.CONTRACT` * @dev Equivalent to `location(contractHash(rights, from, to, contract_))` * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes * @param from The address making the delegation * @param rights The rights specified by the delegation * @param to The address receiving the delegation * @param contract_ The address of the contract specified by the delegation * @return computedLocation The storage location of the contract delegation with those parameters in the delegations mapping */ function contractLocation(address from, bytes32 rights, address to, address contract_) internal pure returns (bytes32 computedLocation) { assembly ("memory-safe") { // This block only allocates memory after the free memory pointer and in the scratch space let ptr := mload(64) // Load free memory pointer // Lay out the variables from last to first, agnostic to upper 96 bits of address words. mstore(add(ptr, 60), contract_) mstore(add(ptr, 40), to) mstore(add(ptr, 20), from) mstore(ptr, rights) mstore(0, or(shl(8, keccak256(ptr, 92)), CONTRACT_TYPE)) // Computes `contractHash`, then stores the result in scratch space mstore(32, DELEGATION_SLOT) computedLocation := keccak256(0, 64) // Runs keccak over the scratch space to obtain the storage key } } /** * @notice Helper function to compute delegation hash for `DelegationType.ERC721` * @dev Equivalent to `keccak256(abi.encodePacked(rights, from, to, contract_, tokenId)) left-shifted by 1 then last byte overwritten with ERC721_TYPE * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes * @param from The address making the delegation * @param rights The rights specified by the delegation * @param to The address receiving the delegation * @param tokenId The id of the token specified by the delegation * @param contract_ The address of the contract specified by the delegation * @return hash The delegation parameters encoded with ERC721_TYPE */ function erc721Hash(address from, bytes32 rights, address to, uint256 tokenId, address contract_) internal pure returns (bytes32 hash) { assembly ("memory-safe") { // This block only allocates memory after the free memory pointer let ptr := mload(64) // Cache the free memory pointer. // Lay out the variables from last to first, agnostic to upper 96 bits of address words. mstore(add(ptr, 92), tokenId) mstore(add(ptr, 60), contract_) mstore(add(ptr, 40), to) mstore(add(ptr, 20), from) mstore(ptr, rights) hash := or(shl(8, keccak256(ptr, 124)), ERC721_TYPE) // Keccak-hashes the packed encoding, left-shifts by one byte, then writes type to the lowest-order byte } } /** * @notice Helper function to compute delegation location for `DelegationType.ERC721` * @dev Equivalent to `location(ERC721Hash(rights, from, to, contract_, tokenId))` * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes * @param from The address making the delegation * @param rights The rights specified by the delegation * @param to The address receiving the delegation * @param tokenId The id of the ERC721 token * @param contract_ The address of the ERC721 token contract * @return computedLocation The storage location of the ERC721 delegation with those parameters in the delegations mapping */ function erc721Location(address from, bytes32 rights, address to, uint256 tokenId, address contract_) internal pure returns (bytes32 computedLocation) { assembly ("memory-safe") { // This block only allocates memory after the free memory pointer and in the scratch space let ptr := mload(64) // Cache the free memory pointer. // Lay out the variables from last to first, agnostic to upper 96 bits of address words. mstore(add(ptr, 92), tokenId) mstore(add(ptr, 60), contract_) mstore(add(ptr, 40), to) mstore(add(ptr, 20), from) mstore(ptr, rights) mstore(0, or(shl(8, keccak256(ptr, 124)), ERC721_TYPE)) // Computes erc721Hash, then stores the result in scratch space mstore(32, DELEGATION_SLOT) computedLocation := keccak256(0, 64) // Runs keccak256 over the scratch space to obtain the storage key } } /** * @notice Helper function to compute delegation hash for `DelegationType.ERC20` * @dev Equivalent to `keccak256(abi.encodePacked(rights, from, to, contract_))` with the last byte overwritten with ERC20_TYPE * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes * @param from The address making the delegation * @param rights The rights specified by the delegation * @param to The address receiving the delegation * @param contract_ The address of the ERC20 token contract * @return hash The parameters encoded with ERC20_TYPE */ function erc20Hash(address from, bytes32 rights, address to, address contract_) internal pure returns (bytes32 hash) { assembly ("memory-safe") { // This block only allocates memory after the free memory pointer let ptr := mload(64) // Load free memory pointer // Lay out the variables from last to first, agnostic to upper 96 bits of address words. mstore(add(ptr, 60), contract_) mstore(add(ptr, 40), to) mstore(add(ptr, 20), from) mstore(ptr, rights) hash := or(shl(8, keccak256(ptr, 92)), ERC20_TYPE) // Keccak-hashes the packed encoding, left-shifts by one byte, then writes type to the lowest-order byte } } /** * @notice Helper function to compute delegation location for `DelegationType.ERC20` * @dev Equivalent to `location(ERC20Hash(rights, from, to, contract_))` * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes * @param from The address making the delegation * @param rights The rights specified by the delegation * @param to The address receiving the delegation * @param contract_ The address of the ERC20 token contract * @return computedLocation The storage location of the ERC20 delegation with those parameters in the delegations mapping */ function erc20Location(address from, bytes32 rights, address to, address contract_) internal pure returns (bytes32 computedLocation) { assembly ("memory-safe") { // This block only allocates memory after the free memory pointer and in the scratch space let ptr := mload(64) // Loads the free memory pointer // Lay out the variables from last to first, agnostic to upper 96 bits of address words. mstore(add(ptr, 60), contract_) mstore(add(ptr, 40), to) mstore(add(ptr, 20), from) mstore(ptr, rights) mstore(0, or(shl(8, keccak256(ptr, 92)), ERC20_TYPE)) // Computes erc20Hash, then stores the result in scratch space mstore(32, DELEGATION_SLOT) computedLocation := keccak256(0, 64) // Runs keccak over the scratch space to obtain the storage key } } /** * @notice Helper function to compute delegation hash for `DelegationType.ERC1155` * @dev Equivalent to keccak256(abi.encodePacked(rights, from, to, contract_, tokenId)) left-shifted with the last byte overwritten with ERC1155_TYPE * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes * @param from The address making the delegation * @param rights The rights specified by the delegation * @param to The address receiving the delegation * @param tokenId The id of the ERC1155 token * @param contract_ The address of the ERC1155 token contract * @return hash The parameters encoded with ERC1155_TYPE */ function erc1155Hash(address from, bytes32 rights, address to, uint256 tokenId, address contract_) internal pure returns (bytes32 hash) { assembly ("memory-safe") { // This block only allocates memory after the free memory pointer let ptr := mload(64) // Load the free memory pointer. // Lay out the variables from last to first, agnostic to upper 96 bits of address words. mstore(add(ptr, 92), tokenId) mstore(add(ptr, 60), contract_) mstore(add(ptr, 40), to) mstore(add(ptr, 20), from) mstore(ptr, rights) hash := or(shl(8, keccak256(ptr, 124)), ERC1155_TYPE) // Keccak-hashes the packed encoding, left-shifts by one byte, then writes type to the lowest-order byte } } /** * @notice Helper function to compute delegation location for `DelegationType.ERC1155` * @dev Equivalent to `location(ERC1155Hash(rights, from, to, contract_, tokenId))` * @dev Will not revert if `from`, `to` or `contract_` are > uint160, these inputs will be cleaned to their lower 20 bytes * @param from The address making the delegation * @param rights The rights specified by the delegation * @param to The address receiving the delegation * @param tokenId The id of the ERC1155 token * @param contract_ The address of the ERC1155 token contract * @return computedLocation The storage location of the ERC1155 delegation with those parameters in the delegations mapping */ function erc1155Location(address from, bytes32 rights, address to, uint256 tokenId, address contract_) internal pure returns (bytes32 computedLocation) { assembly ("memory-safe") { // This block only allocates memory after the free memory pointer and in the scratch space let ptr := mload(64) // Cache the free memory pointer. // Lay out the variables from last to first, agnostic to upper 96 bits of address words. mstore(add(ptr, 92), tokenId) mstore(add(ptr, 60), contract_) mstore(add(ptr, 40), to) mstore(add(ptr, 20), from) mstore(ptr, rights) mstore(0, or(shl(8, keccak256(ptr, 124)), ERC1155_TYPE)) // Computes erc1155Hash, then stores the result in scratch space mstore(32, DELEGATION_SLOT) computedLocation := keccak256(0, 64) // Runs keccak over the scratch space to obtain the storage key } } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.21; library RegistryStorage { /// @dev Standardizes `from` storage flags to prevent double-writes in the delegation in/outbox if the same delegation is revoked and rewritten address internal constant DELEGATION_EMPTY = address(0); address internal constant DELEGATION_REVOKED = address(1); /// @dev Standardizes storage positions of delegation data uint256 internal constant POSITIONS_FIRST_PACKED = 0; // | 4 bytes empty | first 8 bytes of contract address | 20 bytes of from address | uint256 internal constant POSITIONS_SECOND_PACKED = 1; // | last 12 bytes of contract address | 20 bytes of to address | uint256 internal constant POSITIONS_RIGHTS = 2; uint256 internal constant POSITIONS_TOKEN_ID = 3; uint256 internal constant POSITIONS_AMOUNT = 4; /// @dev Used to clean address types of dirty bits with `and(address, CLEAN_ADDRESS)` uint256 internal constant CLEAN_ADDRESS = 0x00ffffffffffffffffffffffffffffffffffffffff; /// @dev Used to clean everything but the first 8 bytes of an address uint256 internal constant CLEAN_FIRST8_BYTES_ADDRESS = 0xffffffffffffffff << 96; /// @dev Used to clean everything but the first 8 bytes of an address in the packed position uint256 internal constant CLEAN_PACKED8_BYTES_ADDRESS = 0xffffffffffffffff << 160; /** * @notice Helper function that packs from, to, and contract_ address to into the two slot configuration * @param from The address making the delegation * @param to The address receiving the delegation * @param contract_ The contract address associated with the delegation (optional) * @return firstPacked The firstPacked storage configured with the parameters * @return secondPacked The secondPacked storage configured with the parameters * @dev Will not revert if `from`, `to`, and `contract_` are > uint160, any inputs with dirty bits outside the last 20 bytes will be cleaned */ function packAddresses(address from, address to, address contract_) internal pure returns (bytes32 firstPacked, bytes32 secondPacked) { assembly { firstPacked := or(shl(64, and(contract_, CLEAN_FIRST8_BYTES_ADDRESS)), and(from, CLEAN_ADDRESS)) secondPacked := or(shl(160, contract_), and(to, CLEAN_ADDRESS)) } } /** * @notice Helper function that unpacks from, to, and contract_ address inside the firstPacked secondPacked storage configuration * @param firstPacked The firstPacked storage to be decoded * @param secondPacked The secondPacked storage to be decoded * @return from The address making the delegation * @return to The address receiving the delegation * @return contract_ The contract address associated with the delegation * @dev Will not revert if `from`, `to`, and `contract_` are > uint160, any inputs with dirty bits outside the last 20 bytes will be cleaned */ function unpackAddresses(bytes32 firstPacked, bytes32 secondPacked) internal pure returns (address from, address to, address contract_) { assembly { from := and(firstPacked, CLEAN_ADDRESS) to := and(secondPacked, CLEAN_ADDRESS) contract_ := or(shr(64, and(firstPacked, CLEAN_PACKED8_BYTES_ADDRESS)), shr(160, secondPacked)) } } /** * @notice Helper function that can unpack the from or to address from their respective packed slots in the registry * @param packedSlot The slot containing the from or to address * @return unpacked The `from` or `to` address * @dev Will not work if you want to obtain the contract address, use unpackAddresses */ function unpackAddress(bytes32 packedSlot) internal pure returns (address unpacked) { assembly { unpacked := and(packedSlot, CLEAN_ADDRESS) } } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.21; library RegistryOps { /// @dev `x > y ? x : y`. function max(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { // `gt(y, x)` will evaluate to 1 if `y > x`, else 0. // // If `y > x`: // `x ^ ((x ^ y) * 1) = x ^ (x ^ y) = (x ^ x) ^ y = 0 ^ y = y`. // otherwise: // `x ^ ((x ^ y) * 0) = x ^ 0 = x`. z := xor(x, mul(xor(x, y), gt(y, x))) } } /// @dev `x & y`. function and(bool x, bool y) internal pure returns (bool z) { assembly { z := and(iszero(iszero(x)), iszero(iszero(y))) // Compiler cleans dirty booleans on the stack to 1, so do the same here } } /// @dev `x | y`. function or(bool x, bool y) internal pure returns (bool z) { assembly { z := or(iszero(iszero(x)), iszero(iszero(y))) // Compiler cleans dirty booleans on the stack to 1, so do the same here } } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "murky/=lib/murky/src/", "openzeppelin/=lib/openzeppelin-contracts/contracts/" ], "optimizer": { "enabled": true, "runs": 9999999 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"MulticallFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"bytes32","name":"rights","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"enable","type":"bool"}],"name":"DelegateAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"contract_","type":"address"},{"indexed":false,"internalType":"bytes32","name":"rights","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"enable","type":"bool"}],"name":"DelegateContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"contract_","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"rights","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DelegateERC1155","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"contract_","type":"address"},{"indexed":false,"internalType":"bytes32","name":"rights","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DelegateERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"contract_","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"rights","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"enable","type":"bool"}],"name":"DelegateERC721","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"bytes32","name":"rights","type":"bytes32"}],"name":"checkDelegateForAll","outputs":[{"internalType":"bool","name":"valid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"bytes32","name":"rights","type":"bytes32"}],"name":"checkDelegateForContract","outputs":[{"internalType":"bool","name":"valid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes32","name":"rights","type":"bytes32"}],"name":"checkDelegateForERC1155","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"bytes32","name":"rights","type":"bytes32"}],"name":"checkDelegateForERC20","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes32","name":"rights","type":"bytes32"}],"name":"checkDelegateForERC721","outputs":[{"internalType":"bool","name":"valid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes32","name":"rights","type":"bytes32"},{"internalType":"bool","name":"enable","type":"bool"}],"name":"delegateAll","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"bytes32","name":"rights","type":"bytes32"},{"internalType":"bool","name":"enable","type":"bool"}],"name":"delegateContract","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes32","name":"rights","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"delegateERC1155","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"bytes32","name":"rights","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"delegateERC20","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes32","name":"rights","type":"bytes32"},{"internalType":"bool","name":"enable","type":"bool"}],"name":"delegateERC721","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"hashes","type":"bytes32[]"}],"name":"getDelegationsFromHashes","outputs":[{"components":[{"internalType":"enum IDelegateRegistry.DelegationType","name":"type_","type":"uint8"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"bytes32","name":"rights","type":"bytes32"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IDelegateRegistry.Delegation[]","name":"delegations_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"getIncomingDelegationHashes","outputs":[{"internalType":"bytes32[]","name":"delegationHashes","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"getIncomingDelegations","outputs":[{"components":[{"internalType":"enum IDelegateRegistry.DelegationType","name":"type_","type":"uint8"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"bytes32","name":"rights","type":"bytes32"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IDelegateRegistry.Delegation[]","name":"delegations_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"getOutgoingDelegationHashes","outputs":[{"internalType":"bytes32[]","name":"delegationHashes","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"}],"name":"getOutgoingDelegations","outputs":[{"components":[{"internalType":"enum IDelegateRegistry.DelegationType","name":"type_","type":"uint8"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"bytes32","name":"rights","type":"bytes32"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IDelegateRegistry.Delegation[]","name":"delegations_","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"location","type":"bytes32"}],"name":"readSlot","outputs":[{"internalType":"bytes32","name":"contents","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"locations","type":"bytes32[]"}],"name":"readSlots","outputs":[{"internalType":"bytes32[]","name":"contents","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061273e806100206000396000f3fe60806040526004361061015e5760003560e01c80638988eea9116100c0578063b9f3687411610074578063d90e73ab11610059578063d90e73ab14610383578063e839bd5314610396578063e8e834a9146103b657600080fd5b8063b9f3687414610343578063ba63c8171461036357600080fd5b8063ac9650d8116100a5578063ac9650d8146102f0578063b18e2bbb14610310578063b87058751461032357600080fd5b80638988eea9146102bd578063ab764683146102dd57600080fd5b806335faa416116101175780634705ed38116100fc5780634705ed381461025d57806351525e9a1461027d57806361451a301461029d57600080fd5b806335faa4161461021957806342f87c251461023057600080fd5b806301ffc9a71161014857806301ffc9a7146101b6578063063182a5146101e657806330ff31401461020657600080fd5b80623c2ba61461016357806301a920a014610189575b600080fd5b6101766101713660046120b4565b6103d5565b6040519081526020015b60405180910390f35b34801561019557600080fd5b506101a96101a43660046120f6565b610637565b6040516101809190612118565b3480156101c257600080fd5b506101d66101d136600461215c565b61066e565b6040519015158152602001610180565b3480156101f257600080fd5b506101a96102013660046120f6565b6106e1565b6101766102143660046121ae565b610712565b34801561022557600080fd5b5061022e6108f9565b005b34801561023c57600080fd5b5061025061024b3660046120f6565b610917565b6040516101809190612219565b34801561026957600080fd5b50610250610278366004612368565b610948565b34801561028957600080fd5b506102506102983660046120f6565b610bf0565b3480156102a957600080fd5b506101a96102b8366004612368565b610c21565b3480156102c957600080fd5b506101d66102d83660046123aa565b610cc6565b6101766102eb3660046123f5565b610dd8565b6103036102fe366004612368565b611056565b6040516101809190612442565b61017661031e366004612510565b61118d565b34801561032f57600080fd5b5061017661033e366004612567565b6113bd565b34801561034f57600080fd5b506101d661035e366004612567565b6115d8565b34801561036f57600080fd5b5061017661037e3660046123aa565b611767565b6101766103913660046125bc565b61192d565b3480156103a257600080fd5b506101d66103b1366004612609565b611b3f565b3480156103c257600080fd5b506101766103d1366004612645565b5490565b60408051603c810185905260288101869052336014820152838152605c902060081b6004176000818152602081905291909120805473ffffffffffffffffffffffffffffffffffffffff1683156105865773ffffffffffffffffffffffffffffffffffffffff81166104ec57336000818152600160208181526040808420805480850182559085528285200188905573ffffffffffffffffffffffffffffffffffffffff8c1680855260028352818520805480860182559086529290942090910187905589901b7bffffffffffffffff000000000000000000000000000000000000000016909217845560a088901b17908301556104d582600486910155565b84156104e7576104e782600287910155565b6105d4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff82160161055d5781547fffffffffffffffffffffffff000000000000000000000000000000000000000016331782556104e782600486910155565b3373ffffffffffffffffffffffffffffffffffffffff8216036104e7576104e782600486910155565b3373ffffffffffffffffffffffffffffffffffffffff8216036105d45781547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001178255600060048301555b604080518681526020810186905273ffffffffffffffffffffffffffffffffffffffff80891692908a169133917f6ebd000dfc4dc9df04f723f827bae7694230795e8f22ed4af438e074cc982d1891015b60405180910390a45050949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902060609061066890611bc2565b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083169081147f5f68bc5a0000000000000000000000000000000000000000000000000000000090911417610668565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040902060609061066890611bc2565b60408051602881018590523360148201528381526048902060081b6001176000818152602081905291909120805473ffffffffffffffffffffffffffffffffffffffff1683156108555773ffffffffffffffffffffffffffffffffffffffff81166107eb57336000818152600160208181526040808420805480850182559085528285200188905573ffffffffffffffffffffffffffffffffffffffff8b16808552600283529084208054808501825590855291909320018690559184559083015584156107e6576107e682600287910155565b61089c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff8216016107e65781547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317825561089c565b3373ffffffffffffffffffffffffffffffffffffffff82160361089c5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011782555b60408051868152851515602082015273ffffffffffffffffffffffffffffffffffffffff88169133917fda3ef6410e30373a9137f83f9781a8129962b6882532b7c229de2e39de423227910160405180910390a350509392505050565b6000806000804770de1e80ea5a234fb5488fee2584251bc7e85af150565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040902060609061066890611d41565b60608167ffffffffffffffff8111156109635761096361265e565b6040519080825280602002602001820160405280156109e857816020015b6040805160e08101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816109815790505b50905060005b82811015610be9576000610a25858584818110610a0d57610a0d61268d565b90506020020135600090815260208190526040902090565b90506000610a47825473ffffffffffffffffffffffffffffffffffffffff1690565b9050610a528161200f565b15610ab6576040805160e08101909152806000815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0909101528451859085908110610aa657610aa661268d565b6020026020010181905250610bdf565b815460018301546040805160e08101825273ffffffffffffffffffffffffffffffffffffffff83169360a09390931c9290911c73ffffffffffffffff00000000000000000000000016919091179080610b278a8a89818110610b1a57610b1a61268d565b9050602002013560ff1690565b6005811115610b3857610b386121ea565b81526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff168152602001610b80866002015490565b81526020018273ffffffffffffffffffffffffffffffffffffffff168152602001610bac866003015490565b8152602001610bbc866004015490565b815250868681518110610bd157610bd161268d565b602002602001018190525050505b50506001016109ee565b5092915050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902060609061066890611d41565b6060818067ffffffffffffffff811115610c3d57610c3d61265e565b604051908082528060200260200182016040528015610c66578160200160208202803683370190505b50915060008060005b83811015610cbc57868682818110610c8957610c8961268d565b9050602002013592508254915081858281518110610ca957610ca961268d565b6020908102919091010152600101610c6f565b5050505092915050565b6000610cd18461200f565b610dcc576040805160288101879052601481018690526000808252604890912060081b6001178152602081905220610d0a905b85612035565b80610d4a575060408051603c810185905260288101879052601481018690526000808252605c90912060081b6002178152602081905220610d4a90610d04565b9050801515821517610dcc576040805160288101879052601481018690528381526048902060081b6001176000908152602081905220610d8990610d04565b80610dc9575060408051603c81018590526028810187905260148101869052838152605c902060081b6002176000908152602081905220610dc990610d04565b90505b80151560005260206000f35b60408051605c8101859052603c810186905260288101879052336014820152838152607c902060081b6005176000818152602081905291909120805473ffffffffffffffffffffffffffffffffffffffff168315610f9c5773ffffffffffffffffffffffffffffffffffffffff8116610f0257336000818152600160208181526040808420805480850182559085528285200188905573ffffffffffffffffffffffffffffffffffffffff8d168085526002835281852080548086018255908652929094209091018790558a901b7bffffffffffffffff000000000000000000000000000000000000000016909217845560a089901b1790830155610edf82600388910155565b610eeb82600486910155565b8415610efd57610efd82600287910155565b610fea565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff821601610f735781547fffffffffffffffffffffffff00000000000000000000000000000000000000001633178255610efd82600486910155565b3373ffffffffffffffffffffffffffffffffffffffff821603610efd57610efd82600486910155565b3373ffffffffffffffffffffffffffffffffffffffff821603610fea5781547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001178255600060048301555b604080518781526020810187905290810185905273ffffffffffffffffffffffffffffffffffffffff80891691908a169033907f27ab1adc9bca76301ed7a691320766dfa4b4b1aa32c9e05cf789611be7f8c75f906060015b60405180910390a4505095945050505050565b60608167ffffffffffffffff8111156110715761107161265e565b6040519080825280602002602001820160405280156110a457816020015b606081526020019060019003908161108f5790505b5090506000805b8381101561118557308585838181106110c6576110c661268d565b90506020028101906110d891906126bc565b6040516110e6929190612721565b600060405180830381855af49150503d8060008114611121576040519150601f19603f3d011682016040523d82523d6000602084013e611126565b606091505b508483815181106111395761113961268d565b602090810291909101015291508161117d576040517f4d6a232800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016110ab565b505092915050565b60408051605c8101859052603c810186905260288101879052336014820152838152607c902060081b6003176000818152602081905291909120805473ffffffffffffffffffffffffffffffffffffffff1683156113155773ffffffffffffffffffffffffffffffffffffffff81166112ab57336000818152600160208181526040808420805480850182559085528285200188905573ffffffffffffffffffffffffffffffffffffffff8d168085526002835281852080548086018255908652929094209091018790558a901b7bffffffffffffffff000000000000000000000000000000000000000016909217845560a089901b179083015561129482600388910155565b84156112a6576112a682600287910155565b61135c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff8216016112a65781547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317825561135c565b3373ffffffffffffffffffffffffffffffffffffffff82160361135c5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011782555b60408051878152602081018790528515159181019190915273ffffffffffffffffffffffffffffffffffffffff80891691908a169033907f15e7a1bdcd507dd632d797d38e60cc5a9c0749b9a63097a215c4d006126825c690606001611043565b60006113c88561200f565b6115ce576040805160288101889052601481018790526000808252604890912060081b6001178152602081905220611401905b86612035565b80611441575060408051603c810186905260288101889052601481018790526000808252605c90912060081b6002178152602081905220611441906113fb565b61148e5760408051605c8101859052603c810186905260288101889052601481018790526000808252607c90912060081b6005178152602081905220611489905b6004015490565b6114b0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81148215176115ce576040805160288101889052601481018790528381526048902060081b60011760009081526020819052908120611513905b87612035565b80611553575060408051603c81018790526028810189905260148101889052848152605c902060081b60021760009081526020819052206115539061150d565b61159d5760408051605c8101869052603c81018790526028810189905260148101889052848152607c902060081b600517600090815260208190522061159890611482565b6115bf565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b90508181108282180281189150505b8060005260206000f35b60006115e38561200f565b610dcc576040805160288101889052601481018790526000808252604890912060081b600117815260208190522061161a906113fb565b8061165a575060408051603c810186905260288101889052601481018790526000808252605c90912060081b600217815260208190522061165a906113fb565b806116a1575060408051605c8101859052603c810186905260288101889052601481018790526000808252607c90912060081b60031781526020819052206116a1906113fb565b9050801515821517610dcc576040805160288101889052601481018790528381526048902060081b60011760009081526020819052206116e0906113fb565b80611720575060408051603c81018690526028810188905260148101879052838152605c902060081b6002176000908152602081905220611720906113fb565b80610dc9575060408051605c8101859052603c81018690526028810188905260148101879052838152607c902060081b6003176000908152602081905220610dc9906113fb565b60006117728461200f565b6115ce576040805160288101879052601481018690526000808252604890912060081b60011781526020819052206117a990610d04565b806117e9575060408051603c810185905260288101879052601481018690526000808252605c90912060081b60021781526020819052206117e990610d04565b61182c5760408051603c810185905260288101879052601481018690526000808252605c90912060081b600417815260208190522061182790611482565b61184e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81148215176115ce576040805160288101879052601481018690528381526048902060081b600117600090815260208190529081206118af906113fb565b806118ef575060408051603c81018690526028810188905260148101879052848152605c902060081b60021760009081526020819052206118ef906113fb565b61159d5760408051603c81018690526028810188905260148101879052848152605c902060081b600417600090815260208190522061159890611482565b60408051603c810185905260288101869052336014820152838152605c902060081b6002176000818152602081905291909120805473ffffffffffffffffffffffffffffffffffffffff168315611aa25773ffffffffffffffffffffffffffffffffffffffff8116611a3857336000818152600160208181526040808420805480850182559085528285200188905573ffffffffffffffffffffffffffffffffffffffff8c1680855260028352818520805480860182559086529290942090910187905589901b7bffffffffffffffff000000000000000000000000000000000000000016909217845560a088901b17908301558415611a3357611a3382600287910155565b611ae9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff821601611a335781547fffffffffffffffffffffffff00000000000000000000000000000000000000001633178255611ae9565b3373ffffffffffffffffffffffffffffffffffffffff821603611ae95781547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011782555b60408051868152851515602082015273ffffffffffffffffffffffffffffffffffffffff80891692908a169133917f021be15e24de4afc43cfb5d0ba95ca38e0783571e05c12bbe6aece8842ae82df9101610625565b6000611b4a8361200f565b610dcc576040805160288101869052601481018590526000808252604890912060081b6001178152602081905220611b83905b84612035565b9050801515821517610dcc576040805160288101869052601481018590528381526048902060081b6001176000908152602081905220610dc990611b7d565b805460609060009081808267ffffffffffffffff811115611be557611be561265e565b604051908082528060200260200182016040528015611c0e578160200160208202803683370190505b50905060005b83811015611ca757868181548110611c2e57611c2e61268d565b90600052602060002001549250611c75611c70611c5685600090815260208190526040902090565b5473ffffffffffffffffffffffffffffffffffffffff1690565b61200f565b611c9f5782828680600101975081518110611c9257611c9261268d565b6020026020010181815250505b600101611c14565b508367ffffffffffffffff811115611cc157611cc161265e565b604051908082528060200260200182016040528015611cea578160200160208202803683370190505b50945060005b84811015611d3757818181518110611d0a57611d0a61268d565b6020026020010151868281518110611d2457611d2461268d565b6020908102919091010152600101611cf0565b5050505050919050565b805460609060009081808267ffffffffffffffff811115611d6457611d6461265e565b604051908082528060200260200182016040528015611d8d578160200160208202803683370190505b50905060005b83811015611e0757868181548110611dad57611dad61268d565b90600052602060002001549250611dd5611c70611c5685600090815260208190526040902090565b611dff5782828680600101975081518110611df257611df261268d565b6020026020010181815250505b600101611d93565b508367ffffffffffffffff811115611e2157611e2161265e565b604051908082528060200260200182016040528015611ea657816020015b6040805160e08101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611e3f5790505b5094506000805b8581101561200457828181518110611ec757611ec761268d565b60200260200101519350611ee684600090815260208190526040902090565b805460018201546040805160e08101825293955073ffffffffffffffffffffffffffffffffffffffff808416949083169360a09390931c9290911c73ffffffffffffffff0000000000000000000000001691909117908060ff89166005811115611f5257611f526121ea565b81526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff168152602001611f9a876002015490565b81526020018273ffffffffffffffffffffffffffffffffffffffff168152602001611fc6876003015490565b8152602001611fd6876004015490565b8152508a8581518110611feb57611feb61268d565b6020026020010181905250505050806001019050611ead565b505050505050919050565b6000600173ffffffffffffffffffffffffffffffffffffffff8316908114901517610668565b6000612055835473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146120af57600080fd5b919050565b600080600080608085870312156120ca57600080fd5b6120d38561208b565b93506120e16020860161208b565b93969395505050506040820135916060013590565b60006020828403121561210857600080fd5b6121118261208b565b9392505050565b6020808252825182820181905260009190848201906040850190845b8181101561215057835183529284019291840191600101612134565b50909695505050505050565b60006020828403121561216e57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461211157600080fd5b803580151581146120af57600080fd5b6000806000606084860312156121c357600080fd5b6121cc8461208b565b9250602084013591506121e16040850161219e565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b8381101561230e578251805160068110612278577f4e487b710000000000000000000000000000000000000000000000000000000084526021600452602484fd5b86528088015173ffffffffffffffffffffffffffffffffffffffff1688870152868101516122bd8888018273ffffffffffffffffffffffffffffffffffffffff169052565b506060818101519087015260808082015173ffffffffffffffffffffffffffffffffffffffff169087015260a0808201519087015260c0908101519086015260e09094019391860191600101612237565b509298975050505050505050565b60008083601f84011261232e57600080fd5b50813567ffffffffffffffff81111561234657600080fd5b6020830191508360208260051b850101111561236157600080fd5b9250929050565b6000806020838503121561237b57600080fd5b823567ffffffffffffffff81111561239257600080fd5b61239e8582860161231c565b90969095509350505050565b600080600080608085870312156123c057600080fd5b6123c98561208b565b93506123d76020860161208b565b92506123e56040860161208b565b9396929550929360600135925050565b600080600080600060a0868803121561240d57600080fd5b6124168661208b565b94506124246020870161208b565b94979496505050506040830135926060810135926080909101359150565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b83811015612502577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089870301855282518051808852835b818110156124bd578281018a01518982018b015289016124a2565b508781018901849052601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690960187019550938601939186019160010161246a565b509398975050505050505050565b600080600080600060a0868803121561252857600080fd5b6125318661208b565b945061253f6020870161208b565b9350604086013592506060860135915061255b6080870161219e565b90509295509295909350565b600080600080600060a0868803121561257f57600080fd5b6125888661208b565b94506125966020870161208b565b93506125a46040870161208b565b94979396509394606081013594506080013592915050565b600080600080608085870312156125d257600080fd5b6125db8561208b565b93506125e96020860161208b565b9250604085013591506125fe6060860161219e565b905092959194509250565b60008060006060848603121561261e57600080fd5b6126278461208b565b92506126356020850161208b565b9150604084013590509250925092565b60006020828403121561265757600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126126f157600080fd5b83018035915067ffffffffffffffff82111561270c57600080fd5b60200191503681900382131561236157600080fd5b818382376000910190815291905056fea164736f6c6343000815000a
Deployed Bytecode
0x60806040526004361061015e5760003560e01c80638988eea9116100c0578063b9f3687411610074578063d90e73ab11610059578063d90e73ab14610383578063e839bd5314610396578063e8e834a9146103b657600080fd5b8063b9f3687414610343578063ba63c8171461036357600080fd5b8063ac9650d8116100a5578063ac9650d8146102f0578063b18e2bbb14610310578063b87058751461032357600080fd5b80638988eea9146102bd578063ab764683146102dd57600080fd5b806335faa416116101175780634705ed38116100fc5780634705ed381461025d57806351525e9a1461027d57806361451a301461029d57600080fd5b806335faa4161461021957806342f87c251461023057600080fd5b806301ffc9a71161014857806301ffc9a7146101b6578063063182a5146101e657806330ff31401461020657600080fd5b80623c2ba61461016357806301a920a014610189575b600080fd5b6101766101713660046120b4565b6103d5565b6040519081526020015b60405180910390f35b34801561019557600080fd5b506101a96101a43660046120f6565b610637565b6040516101809190612118565b3480156101c257600080fd5b506101d66101d136600461215c565b61066e565b6040519015158152602001610180565b3480156101f257600080fd5b506101a96102013660046120f6565b6106e1565b6101766102143660046121ae565b610712565b34801561022557600080fd5b5061022e6108f9565b005b34801561023c57600080fd5b5061025061024b3660046120f6565b610917565b6040516101809190612219565b34801561026957600080fd5b50610250610278366004612368565b610948565b34801561028957600080fd5b506102506102983660046120f6565b610bf0565b3480156102a957600080fd5b506101a96102b8366004612368565b610c21565b3480156102c957600080fd5b506101d66102d83660046123aa565b610cc6565b6101766102eb3660046123f5565b610dd8565b6103036102fe366004612368565b611056565b6040516101809190612442565b61017661031e366004612510565b61118d565b34801561032f57600080fd5b5061017661033e366004612567565b6113bd565b34801561034f57600080fd5b506101d661035e366004612567565b6115d8565b34801561036f57600080fd5b5061017661037e3660046123aa565b611767565b6101766103913660046125bc565b61192d565b3480156103a257600080fd5b506101d66103b1366004612609565b611b3f565b3480156103c257600080fd5b506101766103d1366004612645565b5490565b60408051603c810185905260288101869052336014820152838152605c902060081b6004176000818152602081905291909120805473ffffffffffffffffffffffffffffffffffffffff1683156105865773ffffffffffffffffffffffffffffffffffffffff81166104ec57336000818152600160208181526040808420805480850182559085528285200188905573ffffffffffffffffffffffffffffffffffffffff8c1680855260028352818520805480860182559086529290942090910187905589901b7bffffffffffffffff000000000000000000000000000000000000000016909217845560a088901b17908301556104d582600486910155565b84156104e7576104e782600287910155565b6105d4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff82160161055d5781547fffffffffffffffffffffffff000000000000000000000000000000000000000016331782556104e782600486910155565b3373ffffffffffffffffffffffffffffffffffffffff8216036104e7576104e782600486910155565b3373ffffffffffffffffffffffffffffffffffffffff8216036105d45781547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001178255600060048301555b604080518681526020810186905273ffffffffffffffffffffffffffffffffffffffff80891692908a169133917f6ebd000dfc4dc9df04f723f827bae7694230795e8f22ed4af438e074cc982d1891015b60405180910390a45050949350505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902060609061066890611bc2565b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083169081147f5f68bc5a0000000000000000000000000000000000000000000000000000000090911417610668565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040902060609061066890611bc2565b60408051602881018590523360148201528381526048902060081b6001176000818152602081905291909120805473ffffffffffffffffffffffffffffffffffffffff1683156108555773ffffffffffffffffffffffffffffffffffffffff81166107eb57336000818152600160208181526040808420805480850182559085528285200188905573ffffffffffffffffffffffffffffffffffffffff8b16808552600283529084208054808501825590855291909320018690559184559083015584156107e6576107e682600287910155565b61089c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff8216016107e65781547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317825561089c565b3373ffffffffffffffffffffffffffffffffffffffff82160361089c5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011782555b60408051868152851515602082015273ffffffffffffffffffffffffffffffffffffffff88169133917fda3ef6410e30373a9137f83f9781a8129962b6882532b7c229de2e39de423227910160405180910390a350509392505050565b6000806000804770de1e80ea5a234fb5488fee2584251bc7e85af150565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040902060609061066890611d41565b60608167ffffffffffffffff8111156109635761096361265e565b6040519080825280602002602001820160405280156109e857816020015b6040805160e08101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816109815790505b50905060005b82811015610be9576000610a25858584818110610a0d57610a0d61268d565b90506020020135600090815260208190526040902090565b90506000610a47825473ffffffffffffffffffffffffffffffffffffffff1690565b9050610a528161200f565b15610ab6576040805160e08101909152806000815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0909101528451859085908110610aa657610aa661268d565b6020026020010181905250610bdf565b815460018301546040805160e08101825273ffffffffffffffffffffffffffffffffffffffff83169360a09390931c9290911c73ffffffffffffffff00000000000000000000000016919091179080610b278a8a89818110610b1a57610b1a61268d565b9050602002013560ff1690565b6005811115610b3857610b386121ea565b81526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff168152602001610b80866002015490565b81526020018273ffffffffffffffffffffffffffffffffffffffff168152602001610bac866003015490565b8152602001610bbc866004015490565b815250868681518110610bd157610bd161268d565b602002602001018190525050505b50506001016109ee565b5092915050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040902060609061066890611d41565b6060818067ffffffffffffffff811115610c3d57610c3d61265e565b604051908082528060200260200182016040528015610c66578160200160208202803683370190505b50915060008060005b83811015610cbc57868682818110610c8957610c8961268d565b9050602002013592508254915081858281518110610ca957610ca961268d565b6020908102919091010152600101610c6f565b5050505092915050565b6000610cd18461200f565b610dcc576040805160288101879052601481018690526000808252604890912060081b6001178152602081905220610d0a905b85612035565b80610d4a575060408051603c810185905260288101879052601481018690526000808252605c90912060081b6002178152602081905220610d4a90610d04565b9050801515821517610dcc576040805160288101879052601481018690528381526048902060081b6001176000908152602081905220610d8990610d04565b80610dc9575060408051603c81018590526028810187905260148101869052838152605c902060081b6002176000908152602081905220610dc990610d04565b90505b80151560005260206000f35b60408051605c8101859052603c810186905260288101879052336014820152838152607c902060081b6005176000818152602081905291909120805473ffffffffffffffffffffffffffffffffffffffff168315610f9c5773ffffffffffffffffffffffffffffffffffffffff8116610f0257336000818152600160208181526040808420805480850182559085528285200188905573ffffffffffffffffffffffffffffffffffffffff8d168085526002835281852080548086018255908652929094209091018790558a901b7bffffffffffffffff000000000000000000000000000000000000000016909217845560a089901b1790830155610edf82600388910155565b610eeb82600486910155565b8415610efd57610efd82600287910155565b610fea565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff821601610f735781547fffffffffffffffffffffffff00000000000000000000000000000000000000001633178255610efd82600486910155565b3373ffffffffffffffffffffffffffffffffffffffff821603610efd57610efd82600486910155565b3373ffffffffffffffffffffffffffffffffffffffff821603610fea5781547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001178255600060048301555b604080518781526020810187905290810185905273ffffffffffffffffffffffffffffffffffffffff80891691908a169033907f27ab1adc9bca76301ed7a691320766dfa4b4b1aa32c9e05cf789611be7f8c75f906060015b60405180910390a4505095945050505050565b60608167ffffffffffffffff8111156110715761107161265e565b6040519080825280602002602001820160405280156110a457816020015b606081526020019060019003908161108f5790505b5090506000805b8381101561118557308585838181106110c6576110c661268d565b90506020028101906110d891906126bc565b6040516110e6929190612721565b600060405180830381855af49150503d8060008114611121576040519150601f19603f3d011682016040523d82523d6000602084013e611126565b606091505b508483815181106111395761113961268d565b602090810291909101015291508161117d576040517f4d6a232800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016110ab565b505092915050565b60408051605c8101859052603c810186905260288101879052336014820152838152607c902060081b6003176000818152602081905291909120805473ffffffffffffffffffffffffffffffffffffffff1683156113155773ffffffffffffffffffffffffffffffffffffffff81166112ab57336000818152600160208181526040808420805480850182559085528285200188905573ffffffffffffffffffffffffffffffffffffffff8d168085526002835281852080548086018255908652929094209091018790558a901b7bffffffffffffffff000000000000000000000000000000000000000016909217845560a089901b179083015561129482600388910155565b84156112a6576112a682600287910155565b61135c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff8216016112a65781547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317825561135c565b3373ffffffffffffffffffffffffffffffffffffffff82160361135c5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011782555b60408051878152602081018790528515159181019190915273ffffffffffffffffffffffffffffffffffffffff80891691908a169033907f15e7a1bdcd507dd632d797d38e60cc5a9c0749b9a63097a215c4d006126825c690606001611043565b60006113c88561200f565b6115ce576040805160288101889052601481018790526000808252604890912060081b6001178152602081905220611401905b86612035565b80611441575060408051603c810186905260288101889052601481018790526000808252605c90912060081b6002178152602081905220611441906113fb565b61148e5760408051605c8101859052603c810186905260288101889052601481018790526000808252607c90912060081b6005178152602081905220611489905b6004015490565b6114b0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81148215176115ce576040805160288101889052601481018790528381526048902060081b60011760009081526020819052908120611513905b87612035565b80611553575060408051603c81018790526028810189905260148101889052848152605c902060081b60021760009081526020819052206115539061150d565b61159d5760408051605c8101869052603c81018790526028810189905260148101889052848152607c902060081b600517600090815260208190522061159890611482565b6115bf565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b90508181108282180281189150505b8060005260206000f35b60006115e38561200f565b610dcc576040805160288101889052601481018790526000808252604890912060081b600117815260208190522061161a906113fb565b8061165a575060408051603c810186905260288101889052601481018790526000808252605c90912060081b600217815260208190522061165a906113fb565b806116a1575060408051605c8101859052603c810186905260288101889052601481018790526000808252607c90912060081b60031781526020819052206116a1906113fb565b9050801515821517610dcc576040805160288101889052601481018790528381526048902060081b60011760009081526020819052206116e0906113fb565b80611720575060408051603c81018690526028810188905260148101879052838152605c902060081b6002176000908152602081905220611720906113fb565b80610dc9575060408051605c8101859052603c81018690526028810188905260148101879052838152607c902060081b6003176000908152602081905220610dc9906113fb565b60006117728461200f565b6115ce576040805160288101879052601481018690526000808252604890912060081b60011781526020819052206117a990610d04565b806117e9575060408051603c810185905260288101879052601481018690526000808252605c90912060081b60021781526020819052206117e990610d04565b61182c5760408051603c810185905260288101879052601481018690526000808252605c90912060081b600417815260208190522061182790611482565b61184e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81148215176115ce576040805160288101879052601481018690528381526048902060081b600117600090815260208190529081206118af906113fb565b806118ef575060408051603c81018690526028810188905260148101879052848152605c902060081b60021760009081526020819052206118ef906113fb565b61159d5760408051603c81018690526028810188905260148101879052848152605c902060081b600417600090815260208190522061159890611482565b60408051603c810185905260288101869052336014820152838152605c902060081b6002176000818152602081905291909120805473ffffffffffffffffffffffffffffffffffffffff168315611aa25773ffffffffffffffffffffffffffffffffffffffff8116611a3857336000818152600160208181526040808420805480850182559085528285200188905573ffffffffffffffffffffffffffffffffffffffff8c1680855260028352818520805480860182559086529290942090910187905589901b7bffffffffffffffff000000000000000000000000000000000000000016909217845560a088901b17908301558415611a3357611a3382600287910155565b611ae9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff821601611a335781547fffffffffffffffffffffffff00000000000000000000000000000000000000001633178255611ae9565b3373ffffffffffffffffffffffffffffffffffffffff821603611ae95781547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011782555b60408051868152851515602082015273ffffffffffffffffffffffffffffffffffffffff80891692908a169133917f021be15e24de4afc43cfb5d0ba95ca38e0783571e05c12bbe6aece8842ae82df9101610625565b6000611b4a8361200f565b610dcc576040805160288101869052601481018590526000808252604890912060081b6001178152602081905220611b83905b84612035565b9050801515821517610dcc576040805160288101869052601481018590528381526048902060081b6001176000908152602081905220610dc990611b7d565b805460609060009081808267ffffffffffffffff811115611be557611be561265e565b604051908082528060200260200182016040528015611c0e578160200160208202803683370190505b50905060005b83811015611ca757868181548110611c2e57611c2e61268d565b90600052602060002001549250611c75611c70611c5685600090815260208190526040902090565b5473ffffffffffffffffffffffffffffffffffffffff1690565b61200f565b611c9f5782828680600101975081518110611c9257611c9261268d565b6020026020010181815250505b600101611c14565b508367ffffffffffffffff811115611cc157611cc161265e565b604051908082528060200260200182016040528015611cea578160200160208202803683370190505b50945060005b84811015611d3757818181518110611d0a57611d0a61268d565b6020026020010151868281518110611d2457611d2461268d565b6020908102919091010152600101611cf0565b5050505050919050565b805460609060009081808267ffffffffffffffff811115611d6457611d6461265e565b604051908082528060200260200182016040528015611d8d578160200160208202803683370190505b50905060005b83811015611e0757868181548110611dad57611dad61268d565b90600052602060002001549250611dd5611c70611c5685600090815260208190526040902090565b611dff5782828680600101975081518110611df257611df261268d565b6020026020010181815250505b600101611d93565b508367ffffffffffffffff811115611e2157611e2161265e565b604051908082528060200260200182016040528015611ea657816020015b6040805160e08101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611e3f5790505b5094506000805b8581101561200457828181518110611ec757611ec761268d565b60200260200101519350611ee684600090815260208190526040902090565b805460018201546040805160e08101825293955073ffffffffffffffffffffffffffffffffffffffff808416949083169360a09390931c9290911c73ffffffffffffffff0000000000000000000000001691909117908060ff89166005811115611f5257611f526121ea565b81526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff168152602001611f9a876002015490565b81526020018273ffffffffffffffffffffffffffffffffffffffff168152602001611fc6876003015490565b8152602001611fd6876004015490565b8152508a8581518110611feb57611feb61268d565b6020026020010181905250505050806001019050611ead565b505050505050919050565b6000600173ffffffffffffffffffffffffffffffffffffffff8316908114901517610668565b6000612055835473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146120af57600080fd5b919050565b600080600080608085870312156120ca57600080fd5b6120d38561208b565b93506120e16020860161208b565b93969395505050506040820135916060013590565b60006020828403121561210857600080fd5b6121118261208b565b9392505050565b6020808252825182820181905260009190848201906040850190845b8181101561215057835183529284019291840191600101612134565b50909695505050505050565b60006020828403121561216e57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461211157600080fd5b803580151581146120af57600080fd5b6000806000606084860312156121c357600080fd5b6121cc8461208b565b9250602084013591506121e16040850161219e565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b8381101561230e578251805160068110612278577f4e487b710000000000000000000000000000000000000000000000000000000084526021600452602484fd5b86528088015173ffffffffffffffffffffffffffffffffffffffff1688870152868101516122bd8888018273ffffffffffffffffffffffffffffffffffffffff169052565b506060818101519087015260808082015173ffffffffffffffffffffffffffffffffffffffff169087015260a0808201519087015260c0908101519086015260e09094019391860191600101612237565b509298975050505050505050565b60008083601f84011261232e57600080fd5b50813567ffffffffffffffff81111561234657600080fd5b6020830191508360208260051b850101111561236157600080fd5b9250929050565b6000806020838503121561237b57600080fd5b823567ffffffffffffffff81111561239257600080fd5b61239e8582860161231c565b90969095509350505050565b600080600080608085870312156123c057600080fd5b6123c98561208b565b93506123d76020860161208b565b92506123e56040860161208b565b9396929550929360600135925050565b600080600080600060a0868803121561240d57600080fd5b6124168661208b565b94506124246020870161208b565b94979496505050506040830135926060810135926080909101359150565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b83811015612502577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089870301855282518051808852835b818110156124bd578281018a01518982018b015289016124a2565b508781018901849052601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690960187019550938601939186019160010161246a565b509398975050505050505050565b600080600080600060a0868803121561252857600080fd5b6125318661208b565b945061253f6020870161208b565b9350604086013592506060860135915061255b6080870161219e565b90509295509295909350565b600080600080600060a0868803121561257f57600080fd5b6125888661208b565b94506125966020870161208b565b93506125a46040870161208b565b94979396509394606081013594506080013592915050565b600080600080608085870312156125d257600080fd5b6125db8561208b565b93506125e96020860161208b565b9250604085013591506125fe6060860161219e565b905092959194509250565b60008060006060848603121561261e57600080fd5b6126278461208b565b92506126356020850161208b565b9150604084013590509250925092565b60006020828403121561265757600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126126f157600080fd5b83018035915067ffffffffffffffff82111561270c57600080fd5b60200191503681900382131561236157600080fd5b818382376000910190815291905056fea164736f6c6343000815000a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | Ether (ETH) | 98.16% | $3,289.77 | 7.44 | $24,475.92 |
BSC | 1.42% | $659.32 | 0.5363 | $353.62 | |
POL | 0.20% | $0.474261 | 107 | $50.75 | |
LINEA | 0.11% | $3,289.77 | 0.00812 | $26.71 | |
BASE | 0.08% | $3,292.96 | 0.0063 | $20.75 | |
AVAX | 0.01% | $36.49 | 0.0713 | $2.6 | |
OP | <0.01% | $3,294.87 | 0.00058 | $1.91 | |
SCROLL | <0.01% | $3,289.77 | 0.00041 | $1.35 | |
ARB | <0.01% | $3,292.23 | 0.00019 | $0.625524 | |
BLAST | <0.01% | $3,289.44 | 0.00002 | $0.065789 | |
FTM | <0.01% | $0.968601 | 0.0184 | $0.017784 | |
MANTLE | <0.01% | $1.18 | 0.0107 | $0.01265 | |
APE | <0.01% | $1.15 | 0.00624 | $0.007204 | |
CELO | <0.01% | $0.652885 | 0.00511 | $0.003336 | |
GNO | <0.01% | $1 | 0.00323 | $0.00323 | |
GLMR | <0.01% | $0.234485 | 0.00691 | $0.00162 | |
MOVR | <0.01% | $12.6 | 0.00012 | $0.001513 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.