Source Code
Overview
ETH Balance
0.00103 ETH
Token Holdings
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 31 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Delegate All | 4582884 | 33 mins ago | IN | 0 ETH | 0.00001038 | ||||
Delegate All | 4582775 | 35 mins ago | IN | 0 ETH | 0.00001075 | ||||
Delegate All | 4582629 | 38 mins ago | IN | 0 ETH | 0.00000794 | ||||
Delegate All | 4553904 | 9 hrs ago | IN | 0.00002 ETH | 0.00003338 | ||||
Delegate All | 4549658 | 10 hrs ago | IN | 0 ETH | 0.00000211 | ||||
Delegate All | 4549550 | 10 hrs ago | IN | 0.00001 ETH | 0.0000064 | ||||
Delegate All | 4539174 | 14 hrs ago | IN | 0 ETH | 0.00009318 | ||||
Delegate All | 4538067 | 14 hrs ago | IN | 0 ETH | 0.00000443 | ||||
Delegate All | 4537047 | 15 hrs ago | IN | 0 ETH | 0.0000907 | ||||
Delegate All | 4537042 | 15 hrs ago | IN | 0 ETH | 0.00006904 | ||||
Delegate All | 4536969 | 15 hrs ago | IN | 0 ETH | 0.00006929 | ||||
Delegate All | 4536871 | 15 hrs ago | IN | 0 ETH | 0.00006887 | ||||
Delegate All | 4536446 | 15 hrs ago | IN | 0 ETH | 0.00009419 | ||||
Delegate All | 4534283 | 16 hrs ago | IN | 0 ETH | 0.00000451 | ||||
Delegate All | 4532605 | 17 hrs ago | IN | 0 ETH | 0.00000556 | ||||
Multicall | 4531383 | 17 hrs ago | IN | 0 ETH | 0.00000229 | ||||
Delegate All | 4531103 | 18 hrs ago | IN | 0 ETH | 0.00000586 | ||||
Delegate ERC721 | 4531034 | 18 hrs ago | IN | 0 ETH | 0.00000211 | ||||
Delegate ERC721 | 4531015 | 18 hrs ago | IN | 0 ETH | 0.00000413 | ||||
Delegate Contrac... | 4530999 | 18 hrs ago | IN | 0 ETH | 0.00000383 | ||||
Delegate All | 4530972 | 18 hrs ago | IN | 0 ETH | 0.00000479 | ||||
Delegate All | 4529107 | 18 hrs ago | IN | 0 ETH | 0.00009385 | ||||
Delegate All | 4528967 | 18 hrs ago | IN | 0 ETH | 0.00009945 | ||||
Delegate All | 4521790 | 20 hrs ago | IN | 0 ETH | 0.00000211 | ||||
Delegate All | 4521683 | 20 hrs ago | IN | 0 ETH | 0.00000633 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
4582884 | 33 mins ago | 0 ETH | ||||
4582884 | 33 mins ago | 0 ETH | ||||
4582884 | 33 mins ago | 0 ETH | ||||
4582884 | 33 mins ago | 0 ETH | ||||
4582884 | 33 mins ago | 0 ETH | ||||
4582884 | 33 mins ago | 0 ETH | ||||
4582884 | 33 mins ago | 0 ETH | ||||
4582884 | 33 mins ago | 0 ETH | ||||
4582775 | 35 mins ago | 0 ETH | ||||
4582775 | 35 mins ago | 0 ETH | ||||
4582775 | 35 mins ago | 0 ETH | ||||
4582775 | 35 mins ago | 0 ETH | ||||
4582775 | 35 mins ago | 0 ETH | ||||
4582775 | 35 mins ago | 0 ETH | ||||
4582775 | 35 mins ago | 0 ETH | ||||
4582775 | 35 mins ago | 0 ETH | ||||
4582629 | 38 mins ago | 0 ETH | ||||
4582629 | 38 mins ago | 0 ETH | ||||
4582629 | 38 mins ago | 0 ETH | ||||
4582629 | 38 mins ago | 0 ETH | ||||
4582629 | 38 mins ago | 0 ETH | ||||
4582629 | 38 mins ago | 0 ETH | ||||
4582629 | 38 mins ago | 0 ETH | ||||
4582629 | 38 mins ago | 0 ETH | ||||
4553904 | 9 hrs ago | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
DelegateRegistry
Compiler Version
v0.8.21+commit.d9974bed
ZkSolc Version
v1.5.7
Optimization Enabled:
Yes with Mode 3
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(), 0x000000aA2a733BB7bB003b0339859907d5D87320, 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 } } }
{ "viaIR": false, "codegen": "yul", "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/", "era-contracts/=lib/era-contracts/" ], "evmVersion": "paris", "outputSelection": { "*": { "*": [ "abi", "metadata" ], "": [ "ast" ] } }, "optimizer": { "enabled": true, "mode": "3", "fallback_to_optimizing_for_size": false, "disable_system_request_memoization": true }, "metadata": {}, "libraries": {}, "enableEraVMExtensions": false, "forceEVMLA": false }
[{"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
3cda3351000000000000000000000000000000000000000077151a04325c7971a80c00a00100034bc37f01247f7d9d4a68689cb85a2ed69a44166f6a085b75aae50942cd00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x0003000000000002000b000000000002000000000301034f00020000000103550000006001100270000003040010019d0000008004000039000000400040043f00000001002001900000005a0000c13d0000030401100197000700000001001d000000040010008c000009c60000413d0000000701300360000000000203043b000000e002200270000003060020009c000000620000213d000003140020009c0000013b0000213d0000031b0020009c000001940000a13d0000031c0020009c000002470000613d0000031d0020009c000002590000613d0000031e0020009c000009c60000c13d0000000701000029000000640010008c000009c60000413d0000000401300370000000000101043b000700000001001d000003220010009c000009c60000213d0000002401300370000000000101043b000600000001001d0000004401300370000000000201043b000000000002004b0000000001000039000000010100c039000500000002001d000000000012004b000009c60000c13d0000000701000029000000a80010043f0000000001000411000000940010043f0000000601000029000000800010043f0000000001000414000003040010009c0000030401008041000000c00110021000000323011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000400000001001d000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000401043b000000000104041a0000000503000029000000000003004b0000052d0000c13d00000322021001970000000005000411000000000052004b000005350000c13d000003280110019700000001011001bf000005340000013d0000000001000416000000000001004b000009c60000c13d000000200100003900000100001004430000012000000443000003050100004100000c0e0001042e000003070020009c000001800000213d0000030e0020009c000001a50000a13d0000030f0020009c0000026f0000613d000003100020009c0000029a0000613d000003110020009c000009c60000c13d0000000701000029000000a40010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000700000001001d000003220010009c000009c60000213d0000002401300370000000000101043b000600000001001d000003220010009c000009c60000213d0000004401300370000000000101043b000500000001001d000003220010009c000009c60000213d0000008401300370000000000401043b0000006401300370000000000101043b0000000602000029000000020020008c0000000003000019000002440000413d000400000001001d000300000004001d0000000701000029000000a80010043f000000940020043f000000800000043f0000000001000414000003040010009c0000030401008041000000c00110021000000323011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d00000000020004150000000b0220008a0000000502200210000000000101043b000000000101041a00000322011001970000000604000029000000000014004b000002410000613d000000400100043d0000003c0210003900000005030000290000000000320435000000280210003900000007030000290000000000320435000000140210003900000000004204350000000000010435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032b011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000002011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d00000000020004150000000a0220008a0000000502200210000000000101043b000000000101041a00000322011001970000000604000029000000000014004b000002410000613d000000400100043d0000003c0210003900000005030000290000000000320435000000280210003900000007030000290000000000320435000000140210003900000000004204350000005c02100039000000040300002900000000003204350000000000010435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032c011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000005011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b0000000401100039000000000101041a000200000001001d000000030000006b0000090b0000613d000000010200008a000100000002001d000000020020006b0000090b0000613d000000400100043d00000028021000390000000703000029000000000032043500000014021000390000000603000029000000000032043500000003020000290000000000210435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f00000325011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a0000032201100197000000060010006b000009130000c13d000000020300002900000001010000290000078c0000013d000003150020009c000001ec0000a13d000003160020009c000002e30000613d000003170020009c000003090000613d000003180020009c000009c60000c13d0000000702000029000000240020008c000009c60000413d0000000002000416000000000002004b000009c60000c13d0000000402300370000000000502043b000003300050009c000009c60000213d0000002302500039000000070020006c000009c60000813d0000000402500039000000000223034f000000000202043b000003300020009c000009c60000213d000000240550003900000005062002100000000007560019000000070070006c000009c60000213d0000003f046000390000033104400197000003320040009c0000062a0000213d0000008004400039000000400040043f000000800020043f0000001f0460018f000000000006004b0000016a0000613d000000a006600039000000a007000039000000001801043c0000000007870436000000000067004b000001660000c13d000000000004004b000000000002004b0000017b0000613d0000000001000019000000800400043d000000000014004b000008c40000a13d00000005041002100000000006540019000000000663034f000000000606043b000000000606041a000000a00440003900000000006404350000000101100039000000000021004b0000016e0000413d000000400100043d000700000001001d00000080020000390c0d09c80000040f0000031e0000013d000003080020009c000001fd0000a13d000003090020009c000003280000613d0000030a0020009c0000036c0000613d0000030b0020009c000009c60000c13d0000000701000029000000240010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000000000101041a000000800010043f000003210100004100000c0e0001042e0000031f0020009c000003d30000613d000003200020009c000009c60000c13d0000000701000029000000240010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000003220010009c000009c60000213d000000000010043f0000000101000039000002650000013d000003120020009c000004110000613d000003130020009c000009c60000c13d0000000701000029000000a40010008c000009c60000413d0000000401300370000000000101043b000700000001001d000003220010009c000009c60000213d0000002401300370000000000101043b000600000001001d000003220010009c000009c60000213d0000008401300370000000000101043b000500000001001d0000006401300370000000000201043b0000004401300370000000000101043b000300000001001d000000dc0010043f0000000601000029000000bc0010043f0000000701000029000000a80010043f0000000001000411000000940010043f000400000002001d000000800020043f0000000001000414000003040010009c0000030401008041000000c0011002100000032d011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000005011001bf000200000001001d000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000801043b000000000108041a00000322021001970000000506000029000000000006004b0000054d0000c13d0000000005000411000000000052004b000000040400002900000003070000290000055c0000c13d0000000103000039000005550000013d000003190020009c000004c70000613d0000031a0020009c000009c60000c13d0000000701000029000000240010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000003220010009c000009c60000213d000000000010043f0000000201000039000003150000013d0000030c0020009c000004e70000613d0000030d0020009c000009c60000c13d0000000701000029000000840010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000700000001001d000003220010009c000009c60000213d0000002401300370000000000101043b000600000001001d000003220010009c000009c60000213d0000004401300370000000000101043b000500000001001d000003220010009c000009c60000213d0000006401300370000000000101043b0000000602000029000000020020008c0000000003000019000002440000413d000400000001001d0000000701000029000000a80010043f000000940020043f000000800000043f0000000001000414000003040010009c0000030401008041000000c00110021000000323011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d0000000002000415000000090220008a0000000502200210000000000101043b000000000101041a00000322011001970000000604000029000000000014004b000007040000c13d000000010300008a0000000501200270000000000103001f000000000030043f000003260100004100000c0e0001042e0000000701000029000000240010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b0000034100100198000009c60000c13d000003420010009c00000000020000390000000102006039000003430010009c00000001022061bf000000800020043f000003210100004100000c0e0001042e0000000701000029000000240010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000003220010009c000009c60000213d000000000010043f0000000201000039000000200010043f000000400200003900000000010000190c0d0be90000040f0c0d0b490000040f0000000002010019000000400100043d000700000001001d0c0d09c80000040f0000031e0000013d0000000702000029000000240020008c000009c60000413d0000000402300370000000000c02043b0000033000c0009c000009c60000213d0000002302c00039000000070020006c000009c60000813d0000000402c00039000000000223034f000000000202043b000400000002001d000003300020009c000009c60000213d000000240dc00039000000040200002900000005052002100000000002d50019000000070020006c000009c60000213d0000003f025000390000033102200197000003320020009c0000062a0000213d0000008002200039000000400020043f0000000406000029000000800060043f000000000006004b0000056f0000c13d00000020010000390000000003120436000000800100043d0000000000130435000000400320003900000005041002100000000007340019000000000001004b0000064f0000c13d0000000001270049000003200000013d0000000701000029000000a40010008c000009c60000413d0000000401300370000000000101043b000700000001001d000003220010009c000009c60000213d0000002401300370000000000101043b000600000001001d000003220010009c000009c60000213d0000006401300370000000000101043b000500000001001d0000004401300370000000000101043b000400000001001d0000008401300370000000000201043b000000000002004b0000000001000039000000010100c039000300000002001d000000000012004b000009c60000c13d0000000401000029000000dc0010043f0000000601000029000000bc0010043f0000000701000029000000a80010043f0000000001000411000000940010043f0000000501000029000000800010043f0000000001000414000003040010009c0000030401008041000000c0011002100000032d011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000003011001bf000200000001001d000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000401043b000000000104041a0000000303000029000000000003004b0000066b0000c13d00000322021001970000000005000411000000000052004b000006730000c13d000003280110019700000001011001bf000006720000013d0000000701000029000000240010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000003300010009c000009c60000213d0000002302100039000000070020006c000009c60000813d0000000402100039000000000223034f000000000202043b000400000002001d000003300020009c000009c60000213d000300240010003d000000040100002900000005041002100000000302400029000000070020006c000009c60000213d0000003f024000390000033102200197000003320020009c0000062a0000213d0000008001200039000000400010043f0000000403000029000000800030043f000000000003004b000006100000c13d000700000001001d00000080020000390000031d0000013d0000000701000029000000240010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000003220010009c000009c60000213d000000000010043f0000000101000039000000200010043f000000400200003900000000010000190c0d0be90000040f0c0d0a5a0000040f0000000002010019000000400100043d000700000001001d0c0d09d70000040f00000007020000290000000001210049000003040010009c00000304010080410000006001100210000003040020009c00000304020080410000004002200210000000000121019f00000c0e0001042e0000000701000029000000840010008c000009c60000413d0000000401300370000000000101043b000700000001001d000003220010009c000009c60000213d0000002401300370000000000101043b000600000001001d000003220010009c000009c60000213d0000004401300370000000000101043b000500000001001d0000006401300370000000000201043b000000000002004b0000000001000039000000010100c039000400000002001d000000000012004b000009c60000c13d0000000601000029000000bc0010043f0000000701000029000000a80010043f0000000001000411000000940010043f0000000501000029000000800010043f0000000001000414000003040010009c0000030401008041000000c00110021000000327011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000002011001bf000300000001001d000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000401043b000000000104041a0000000403000029000000000003004b0000068f0000c13d00000322021001970000000005000411000000000052004b000006970000c13d000003280110019700000001011001bf000006960000013d0000000701000029000000640010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000700000001001d000003220010009c000009c60000213d0000002401300370000000000101043b000600000001001d000003220010009c000009c60000213d0000004401300370000000000301043b0000000602000029000000020020008c0000000001000019000005280000413d000500000003001d0000000701000029000000a80010043f000000940020043f000000800000043f0000000001000414000003040010009c0000030401008041000000c00110021000000323011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a00000322021001970000000603000029000000000023004b000000000100003900000001010060390000000505000029000000000005004b000005280000613d000000000023004b000005280000613d000000400100043d000000280210003900000007040000290000000000420435000000140210003900000000003204350000000000510435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f00000325011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a0000032201100197000000060010006b00000000010000390000000101006039000005280000013d0000000701000029000000840010008c000009c60000413d0000000401300370000000000101043b000700000001001d000003220010009c000009c60000213d0000002401300370000000000101043b000600000001001d000003220010009c000009c60000213d0000006401300370000000000101043b000500000001001d0000004401300370000000000201043b0000000601000029000000bc0010043f0000000701000029000000a80010043f0000000001000411000000940010043f000400000002001d000000800020043f0000000001000414000003040010009c0000030401008041000000c00110021000000327011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000004011001bf000300000001001d000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000701043b000000000107041a00000322021001970000000504000029000000000004004b000006300000c13d0000000005000411000000000052004b00000004060000290000063e0000c13d0000000103000039000006370000013d0000000701000029000000840010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000700000001001d000003220010009c000009c60000213d0000002401300370000000000101043b000600000001001d000003220010009c000009c60000213d0000004401300370000000000101043b000500000001001d000003220010009c000009c60000213d0000006401300370000000000301043b0000000602000029000000020020008c0000000001000019000005280000413d000400000003001d0000000701000029000000a80010043f000000940020043f000000800000043f0000000001000414000003040010009c0000030401008041000000c00110021000000323011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a00000322011001970000000603000029000000000013004b000005270000613d000000400100043d0000003c0210003900000005040000290000000000420435000000280210003900000007040000290000000000420435000000140210003900000000003204350000000000010435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032b011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000002011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a0000032202100197000000060020006b00000000010000390000000101006039000000040000006b000005280000613d0000000603000029000000000023004b0000000405000029000005280000613d000000400100043d000000280210003900000007040000290000000000420435000000140210003900000000003204350000000000510435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f00000325011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a00000322011001970000000603000029000000000013004b00000001010000390000000405000029000005280000613d000000400100043d0000003c0210003900000005040000290000000000420435000000280210003900000007040000290000000000420435000000140210003900000000003204350000000000510435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032b011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000002011001bf000000000010043f000000200000043f0000000001000414000003c40000013d0000000001000416000000000001004b000009c60000c13d0000033c010000410000000000100443000000000100041000000004001004430000000001000414000003040010009c0000030401008041000000c0011002100000033d011001c70000800a020000390c0d0c030000040f00000001002001900000052c0000613d000000000301043b0000000001000414000003040010009c0000030401008041000000c001100210000000000003004b0000033e0110c1c700008009020000390000033f020060410000033f0400004100000000050000190c0d0bfe0000040f0000006001100270000103040010019d000000000100001900000c0e0001042e0000000701000029000000a40010008c000009c60000413d0000000001000416000000000001004b000009c60000c13d0000000401300370000000000101043b000700000001001d000003220010009c000009c60000213d0000002401300370000000000101043b000600000001001d000003220010009c000009c60000213d0000004401300370000000000101043b000500000001001d000003220010009c000009c60000213d0000008401300370000000000401043b0000006401300370000000000301043b0000000602000029000000020020008c0000000001000019000005280000413d000400000003001d000300000004001d0000000701000029000000a80010043f000000940020043f000000800000043f0000000001000414000003040010009c0000030401008041000000c00110021000000323011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a00000322011001970000000603000029000000000013004b000007910000c13d0000000101000039000000010110018f000000000010043f000003260100004100000c0e0001042e000000000001042f00000322021001980000000005000411000006b50000613d000000010020008c000005350000c13d0000032801100197000000000151019f000000000014041b000000400100043d0000002002100039000000000032043500000006020000290000000000210435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000112019f00000324011001c70000800d020000390000000303000039000003400400004100000007060000290c0d0bfe0000040f0000000100200190000009c60000613d000000400100043d0000000402000029000006af0000013d000000000002004b0000000005000411000006c70000613d000000010020008c000000000305001900000004040000290000000307000029000006e40000c13d0000032801100197000000000113019f000000000018041b000000040100003900000000020600190000000001810019000000000021041b000000400100043d00000040021000390000000000620435000000200210003900000000004204350000000000710435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000112019f0000032e011001c70000800d0200003900000004030000390000033604000041000006870000013d000000600e0000390000000002000019000000a0062000390000000000e604350000002002200039000000000052004b000005710000413d000000200f00008a000000000400001900030000000c001d00020000000d001d0000000705c00069000600000004001d00050005004002180000000502d00029000000000223034f000000000202043b000000430550008a00000333065001970000033307200197000000000867013f000000000067004b00000000060000190000033306002041000000000052004b00000000050000190000033305004041000003330080009c000000000605c019000000000006004b000009c60000613d0000000005d20019000000000253034f000000000402043b000003300040009c000009c60000213d0000000706400069000000200550003900000333076001970000033308500197000000000978013f000000000078004b00000000070000190000033307004041000000000065004b00000000060000190000033306002041000003330090009c000000000706c019000000000007004b000009c60000c13d000000000753034f0000000008f40170000000400500043d0000000006850019000005ad0000613d000000000907034f000000000a050019000000009b09043c000000000aba043600000000006a004b000005a90000c13d0000001f09400190000005ba0000613d000000000787034f0000000308900210000000000906043300000000098901cf000000000989022f000000000707043b0000010008800089000000000787022f00000000078701cf000000000797019f00000000007604350000000006450019000000000006043500000000060004140000000002000410000000040020008c000005c30000c13d00000001050000310000000102000039000005d90000013d000003040040009c00000304040080410000006001400210000003040050009c00000304050080410000004003500210000000000113019f000003040060009c0000030406008041000000c003600210000000000113019f0c0d0c080000040f000000200f00008a000000600e000039000000020d000029000000030c00002900070000000000350000000203000367000000010220018f0000006005100270000103040050019d00000304055001970000000604000029000000000005004b00000000060e0019000006030000613d000003300050009c0000062a0000213d0000001f065000390000000006f6016f0000003f066000390000000007f6016f000000400600043d0000000007760019000000000067004b00000000080000390000000108004039000003300070009c0000062a0000213d00000001008001900000062a0000c13d000000400070043f00000000095604360000000008f501700000000007890019000005f60000613d000000000a01034f00000000ab0a043c0000000009b90436000000000079004b000005f20000c13d0000001f05500190000006030000613d000000000881034f0000000305500210000000000907043300000000095901cf000000000959022f000000000808043b0000010005500089000000000858022f00000000055801cf000000000595019f0000000000570435000000800500043d000000000045004b000008c40000a13d0000000505000029000000a0055000390000000000650435000000000002004b000008fd0000613d0000000104400039000000040040006c0000057a0000413d000000400200043d0000028f0000013d000003370020009c0000062a0000213d0000000002000019000000e003100039000000400030043f000000c0031000390000000000030435000000a0031000390000000000030435000000800310003900000000000304350000006003100039000000000003043500000040031000390000000000030435000000200310003900000000000304350000000000010435000000a00320003900000000001304350000002002200039000000000042004b000008670000813d000000400100043d000003380010009c000006130000a13d0000033a01000041000000000010043f0000004101000039000000040010043f0000033b0100004100000c0f00010430000000000002004b0000000005000411000006e70000613d000000010020008c00000000030500190000000406000029000007010000c13d0000032801100197000000000113019f000000000017041b000000040100003900000000020400190000000001710019000000000021041b000000400100043d000000200210003900000000004204350000000000610435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000112019f00000324011001c70000800d0200003900000004030000390000034404000041000006a80000013d000000a00400003900000000060000190000065a0000013d0000001f0980003900000345099001970000000008870019000000000008043500000000079700190000000106600039000000000016004b000002980000813d0000000008270049000000400880008a0000000003830436000000004804043400000000980804340000000007870436000000000008004b000006520000613d000000000a000019000000000b7a0019000000000ca90019000000000c0c04330000000000cb0435000000200aa0003900000000008a004b000006630000413d000006520000013d0000032202100198000008ca0000613d000000010020008c0000000005000411000006730000c13d0000032801100197000000000151019f000000000014041b000000400100043d0000004002100039000000000032043500000020021000390000000503000029000000000032043500000004020000290000000000210435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000112019f0000032e011001c70000800d0200003900000004030000390000032f04000041000000070600002900000006070000290c0d0bfe0000040f0000000100200190000009c60000613d000000400100043d0000000202000029000006af0000013d0000032202100198000008e50000613d000000010020008c0000000005000411000006970000c13d0000032801100197000000000151019f000000000014041b000000400100043d0000002002100039000000000032043500000005020000290000000000210435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000112019f00000324011001c70000800d0200003900000004030000390000032a04000041000000070600002900000006070000290c0d0bfe0000040f0000000100200190000009c60000613d000000400100043d00000003020000290000000000210435000003040010009c0000030401008041000000400110021000000326011001c700000c0e0001042e000000000105001900000007020000290000000403000029000300000004001d0c0d0a090000040f000000030200002900000005030000290000000005000411000000000052041b00000001012000390000000704000029000000000041041b000000060000006b000005350000613d00000002012000390000000602000029000000000021041b000005350000013d000000000105001900000007020000290000000203000029000100000008001d0c0d0a090000040f0000000108000029000000050600002900000000050004110000032201500197000000060300002900000040023002100000032902200197000000000121019f000000000018041b000000a00130021000000007011001af0000000102800039000000000012041b00000003018000390000000307000029000000000071041b0000000401800039000000000061041b0000000404000029000000000004004b0000055c0000613d000000020100003900000000020400190000055a0000013d000000000052004b000005580000613d0000055c0000013d000000000105001900000007020000290000000303000029000200000007001d0c0d0a090000040f0000000207000029000000050400002900000000050004110000032201500197000000060300002900000040023002100000032902200197000000000121019f000000000017041b000000a00130021000000007011001af0000000102700039000000000012041b0000000401700039000000000041041b0000000406000029000000000006004b0000063e0000613d000000020100003900000000020600190000063c0000013d000000000052004b0000063a0000613d0000063e0000013d000000400100043d0000003c0210003900000005030000290000000000320435000000280210003900000007030000290000000000320435000000140210003900000000004204350000000000010435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032b011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000002011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d0000000002000415000000080220008a0000000502200210000000000101043b000000000101041a00000322011001970000000604000029000000000014004b000002410000613d000000400100043d0000003c0210003900000005030000290000000000320435000000280210003900000007030000290000000000320435000000140210003900000000004204350000000000010435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032b011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000004011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b0000000401100039000000000101041a000300000001001d000000040000006b0000090f0000613d000000010200008a000200000002001d000000030020006b0000090f0000613d000000400100043d00000028021000390000000703000029000000000032043500000014021000390000000603000029000000000032043500000004020000290000000000210435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f00000325011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a0000032201100197000000060010006b0000096e0000c13d00000003030000290000000201000029000000000013004b000000000301a019000000000030043f000003260100004100000c0e0001042e000000400100043d0000003c0210003900000005040000290000000000420435000000280210003900000007040000290000000000420435000000140210003900000000003204350000000000010435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032b011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000002011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a0000032201100197000000060010006b000005270000613d000000400100043d0000003c02100039000000050300002900000000003204350000002802100039000000070300002900000000003204350000001402100039000000060300002900000000003204350000005c02100039000000040300002900000000003204350000000000010435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032c011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000003011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a0000032202100197000000060020006b00000000010000390000000101006039000000030000006b000005280000613d0000000603000029000000000023004b0000000305000029000005280000613d000000400100043d000000280210003900000007040000290000000000420435000000140210003900000000003204350000000000510435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f00000325011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000001011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a0000032201100197000000060010006b000005270000613d000000400100043d0000003c021000390000000503000029000000000032043500000028021000390000000703000029000000000032043500000014021000390000000603000029000000000032043500000003020000290000000000210435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032b011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000002011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a00000322011001970000000603000029000000000013004b000000010100003900000003050000290000000406000029000005280000613d000000400100043d0000003c0210003900000005040000290000000000420435000000280210003900000007040000290000000000420435000000140210003900000000003204350000005c0210003900000000006204350000000000510435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032c011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000003011001bf000000000010043f000000200000043f0000000001000414000003c40000013d0000000003000019000700000003001d0000000502300210000600000002001d0000000301200029000500000001001d0000000201100367000000000101043b000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000400200043d000000000401043b000000000304041a0000032201300197000000010010008c000008a40000a13d0000000105400039000000000605041a0000000305400039000000000505041a0000000407400039000000000807041a0000000204400039000000000404041a00000005070000290000000207700367000000000707043b000003380020009c0000062a0000213d000000ff0770018f000000e009200039000000400090043f000000060070008c000009050000813d00000040033002700000033903300197000000a009600270000000000339019f0000032206600197000000c0092000390000000000890435000000a008200039000000000058043500000080052000390000000000350435000000600320003900000000004304350000004003200039000000000013043500000000017204360000000000610435000008b50000013d000003380020009c0000062a0000213d000000e001200039000000400010043f000000c0012000390000000000010435000000a0012000390000000000010435000000800120003900000000000104350000006001200039000000000001043500000040012000390000000000010435000000200120003900000000000104350000000000020435000000800100043d0000000703000029000000000031004b000008c40000a13d0000000601000029000000a0011000390000000000210435000000800100043d000000000031004b000008c40000a13d0000000103300039000000040030006c000008680000413d000000400100043d000003060000013d0000033a01000041000000000010043f0000003201000039000000040010043f0000033b0100004100000c0f00010430000000000100041100000007020000290000000203000029000100000004001d0c0d0a090000040f000000010400002900000000050004110000032201500197000000060300002900000040023002100000032902200197000000000121019f000000000014041b000000a001300210000000030300002900000007011001af0000000102400039000000000012041b00000003014000390000000402000029000000000021041b000000050000006b000006730000613d00000002014000390000000502000029000000000021041b000006730000013d000000000100041100000007020000290000000303000029000200000004001d0c0d0a090000040f000000020400002900000000050004110000032201500197000000060300002900000040023002100000032902200197000000000121019f000000000014041b000000a001300210000000040300002900000007011001af0000000102400039000000000012041b000000050000006b000006970000613d00000002014000390000000502000029000000000021041b000006970000013d000000400100043d00000334020000410000000000210435000003040010009c0000030401008041000000400110021000000335011001c700000c0f000104300000033a01000041000000000010043f0000002101000039000000040010043f0000033b0100004100000c0f000104300000000203000029000000000030043f000003260100004100000c0e0001042e0000000303000029000000000030043f000003260100004100000c0e0001042e000000400100043d0000003c021000390000000503000029000000000032043500000028021000390000000703000029000000000032043500000014021000390000000603000029000000000032043500000003020000290000000000210435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032b011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000002011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a0000032201100197000000060010006b000001380000613d000000400100043d0000003c02100039000000050300002900000000003204350000002802100039000000070300002900000000003204350000001402100039000000060300002900000000003204350000005c021000390000000403000029000000000032043500000003020000290000000000210435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032c011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000005011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b0000000401100039000000000101041a000100000001001d000001380000013d000000400100043d0000003c021000390000000503000029000000000032043500000028021000390000000703000029000000000032043500000014021000390000000603000029000000000032043500000004020000290000000000210435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032b011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000002011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000000101041a0000032201100197000000060010006b0000078a0000613d000000400100043d0000003c021000390000000503000029000000000032043500000028021000390000000703000029000000000032043500000014021000390000000603000029000000000032043500000004020000290000000000210435000003040010009c000003040100804100000040011002100000000002000414000003040020009c0000030402008041000000c002200210000000000121019f0000032b011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b000000080110021000000004011001bf000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f0000000100200190000009c60000613d000000000101043b0000000401100039000000000101041a000200000001001d0000078a0000013d000000000100001900000c0f0001043000000020030000390000000004310436000000000302043300000000003404350000004001100039000000000003004b000009d60000613d00000000040000190000002002200039000000000502043300000000015104360000000104400039000000000034004b000009d00000413d000000000001042d00000020030000390000000004310436000000000302043300000000003404350000004001100039000000000003004b00000a020000613d0000000004000019000000200220003900000000050204330000000067050434000000050070008c00000a030000213d000000000771043600000000060604330000032206600197000000000067043500000040065000390000000006060433000003220660019700000040071000390000000000670435000000600650003900000000060604330000006007100039000000000067043500000080065000390000000006060433000003220660019700000080071000390000000000670435000000a0065000390000000006060433000000a0071000390000000000670435000000c0055000390000000005050433000000c0061000390000000000560435000000e0011000390000000104400039000000000034004b000009df0000413d000000000001042d0000033a01000041000000000010043f0000002101000039000000040010043f0000033b0100004100000c0f000104300003000000000002000300000003001d000200000002001d0000032201100197000000000010043f0000000101000039000000200010043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f000000010020019000000a520000613d000000000101043b000000000201041a000003460020009c00000a540000813d000100000002001d0000000102200039000000000021041b000000000010043f0000000001000414000003040010009c0000030401008041000000c00110021000000347011001c700008010020000390c0d0c030000040f000000010020019000000a520000613d000000000101043b00000001011000290000000302000029000000000021041b00000002010000290000032201100197000000000010043f0000000201000039000000200010043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f000000010020019000000a520000613d000000000101043b000000000201041a000003300020009c00000a540000213d000200000002001d0000000102200039000000000021041b000000000010043f0000000001000414000003040010009c0000030401008041000000c00110021000000347011001c700008010020000390c0d0c030000040f000000010020019000000a520000613d000000000101043b00000002011000290000000302000029000000000021041b000000000001042d000000000100001900000c0f000104300000033a01000041000000000010043f0000004101000039000000040010043f0000033b0100004100000c0f000104300008000000000002000000000201041a000500000002001d000003460020009c00000b3d0000813d000000050200002900000005052002100000003f025000390000033102200197000000400300043d0000000002230019000400000003001d000000000032004b00000000030000390000000103004039000003300020009c00000b3d0000213d000000010030019000000b3d0000c13d000000400020043f000000040200002900000005030000290000000002320436000300000002001d0000001f0250018f000000000005004b00000a7d0000613d0000000304000029000000000654001900000000030000310000000203300367000000003503043c0000000004540436000000000064004b00000a790000c13d000000000002004b000000050000006b00000abd0000613d00008010050000390000000006000019000800000000001d000200000001001d00000a8a0000013d000000020100002900000007060000290000000106600039000000050060006c00000ab90000813d000000000201041a000000000062004b00000b350000a13d000700000006001d000000000010043f0000000001000414000003040010009c0000030401008041000000c00110021000000347011001c700000000020500190c0d0c030000040f000000010020019000000b3b0000613d000000000101043b0000000701100029000000000101041a000600000001001d000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f000000010020019000000b3b0000613d0000801005000039000000000101043b000000000101041a000003480010019800000a850000613d00000004010000290000000001010433000000080010006c0000000201000029000000070600002900000b350000a13d00000008030000290000000504300210000000030240002900000006040000290000000000420435000800010030003d00000a870000013d0000000801000029000003300010009c00000abe0000a13d00000b3d0000013d000800000000001d000000080100002900000005011002100000003f021000390000034902200197000000400a00043d00000000022a00190000000000a2004b00000000030000390000000103004039000003300020009c00000b3d0000213d000000010030019000000b3d0000c13d000000400020043f0000000802000029000000000b2a0436000000000002004b00000b330000613d0000000002000019000000400300043d000003380030009c00000b3d0000213d000000e004300039000000400040043f000000c0043000390000000000040435000000a004300039000000000004043500000080043000390000000000040435000000600430003900000000000404350000004004300039000000000004043500000020043000390000000000040435000000000003043500000000042b001900000000003404350000002002200039000000000012004b00000ad10000413d000000000300001900020000000a001d00010000000b001d00000004010000290000000001010433000000000031004b00000b350000a13d000600000003001d0000000502300210000500000002001d00000003012000290000000001010433000700000001001d000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f000000010020019000000b3b0000613d000000000201043b000000400100043d000003380010009c000000020a000029000000010b00002900000b3d0000213d000000000502041a0000000103200039000000000603041a0000000303200039000000000303041a0000000404200039000000000704041a0000000202200039000000000202041a000000e004100039000000400040043f0000000704000029000000ff0440018f000000060040008c00000b430000813d00000040085002700000033908800197000000a009600270000000000898019f00000322055001970000032206600197000000c0091000390000000000790435000000a00710003900000000003704350000008003100039000000000083043500000060031000390000000000230435000000400210003900000000005204350000000002410436000000000062043500000000020a04330000000603000029000000000032004b00000b350000a13d0000000502b00029000000000012043500000000010a0433000000000031004b00000b350000a13d0000000103300039000000080030006c00000aeb0000413d00000000010a0019000000000001042d0000033a01000041000000000010043f0000003201000039000000040010043f0000033b0100004100000c0f00010430000000000100001900000c0f000104300000033a01000041000000000010043f0000004101000039000000040010043f0000033b0100004100000c0f000104300000033a01000041000000000010043f0000002101000039000000040010043f0000033b0100004100000c0f000104300007000000000002000000000201041a000200000002001d000003460020009c00000be20000813d000000020200002900000005052002100000003f025000390000033102200197000000400300043d0000000002230019000500000003001d000000000032004b00000000030000390000000103004039000003300020009c00000be20000213d000000010030019000000be20000c13d000000400020043f000000050200002900000002030000290000000002320436000400000002001d0000001f0250018f000000000005004b00000b6c0000613d0000000404000029000000000654001900000000030000310000000203300367000000003503043c0000000004540436000000000064004b00000b680000c13d000000000002004b000000020000006b00000bac0000613d000080100400003900000000050000190000000008000019000100000001001d00000b790000013d000000010100002900000007050000290000000105500039000000020050006c00000ba90000813d000000000201041a000000000052004b00000bda0000a13d000700000005001d000600000008001d000000000010043f0000000001000414000003040010009c0000030401008041000000c00110021000000347011001c700000000020400190c0d0c030000040f000000010020019000000be00000613d000000000101043b0000000701100029000000000101041a000300000001001d000000000010043f000000200000043f0000000001000414000003040010009c0000030401008041000000c00110021000000324011001c700008010020000390c0d0c030000040f000000010020019000000be00000613d0000801004000039000000000101043b000000000101041a0000034800100198000000060800002900000b740000613d00000005010000290000000001010433000000000081004b0000000101000029000000070500002900000bda0000a13d0000000503800210000000040230002900000003030000290000000000320435000000010880003900000b760000013d000003300080009c00000bad0000a13d00000be20000013d000000000800001900000005038002100000003f013000390000034902100197000000400100043d0000000002210019000000000012004b00000000040000390000000104004039000003300020009c00000be20000213d000000010040019000000be20000c13d000000400020043f00000000028104360000001f0430018f000000000003004b00000bc60000613d0000000003320019000000000500003100000002055003670000000006020019000000005705043c0000000006760436000000000036004b00000bc20000c13d000000000004004b000000000008004b00000bd90000613d000000000300001900000005040000290000000004040433000000000034004b00000bda0000a13d0000000004010433000000000034004b00000bda0000a13d000000050430021000000000052400190000000404400029000000000404043300000000004504350000000103300039000000000083004b00000bca0000413d000000000001042d0000033a01000041000000000010043f0000003201000039000000040010043f0000033b0100004100000c0f00010430000000000100001900000c0f000104300000033a01000041000000000010043f0000004101000039000000040010043f0000033b0100004100000c0f00010430000000000001042f000003040010009c00000304010080410000004001100210000003040020009c00000304020080410000006002200210000000000112019f0000000002000414000003040020009c0000030402008041000000c002200210000000000112019f0000033e011001c700008010020000390c0d0c030000040f000000010020019000000bfc0000613d000000000101043b000000000001042d000000000100001900000c0f0001043000000c01002104210000000102000039000000000001042d0000000002000019000000000001042d00000c06002104230000000102000039000000000001042d0000000002000019000000000001042d00000c0b002104250000000102000039000000000001042d0000000002000019000000000001042d00000c0d0000043200000c0e0001042e00000c0f0001043000000000000000000000000000000000000000000000000000000000ffffffff0000000200000000000000000000000000000040000001000000000000000000000000000000000000000000000000000000000000000000000000008988eea800000000000000000000000000000000000000000000000000000000b9f3687300000000000000000000000000000000000000000000000000000000d90e73aa00000000000000000000000000000000000000000000000000000000d90e73ab00000000000000000000000000000000000000000000000000000000e839bd5300000000000000000000000000000000000000000000000000000000e8e834a900000000000000000000000000000000000000000000000000000000b9f3687400000000000000000000000000000000000000000000000000000000ba63c81700000000000000000000000000000000000000000000000000000000ac9650d700000000000000000000000000000000000000000000000000000000ac9650d800000000000000000000000000000000000000000000000000000000b18e2bbb00000000000000000000000000000000000000000000000000000000b8705875000000000000000000000000000000000000000000000000000000008988eea900000000000000000000000000000000000000000000000000000000ab7646830000000000000000000000000000000000000000000000000000000035faa415000000000000000000000000000000000000000000000000000000004705ed37000000000000000000000000000000000000000000000000000000004705ed380000000000000000000000000000000000000000000000000000000051525e9a0000000000000000000000000000000000000000000000000000000061451a300000000000000000000000000000000000000000000000000000000035faa4160000000000000000000000000000000000000000000000000000000042f87c250000000000000000000000000000000000000000000000000000000001ffc9a60000000000000000000000000000000000000000000000000000000001ffc9a700000000000000000000000000000000000000000000000000000000063182a50000000000000000000000000000000000000000000000000000000030ff314000000000000000000000000000000000000000000000000000000000003c2ba60000000000000000000000000000000000000000000000000000000001a920a00000000000000000000000000000000000000020000000800000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0200000000000000000000000000000000000048000000800000000000000000020000000000000000000000000000000000004000000000000000000000000002000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000020000000000000000000000000020000000000000000000000000000000000005c000000800000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff0000000000000000000000000000000000000000021be15e24de4afc43cfb5d0ba95ca38e0783571e05c12bbe6aece8842ae82df020000000000000000000000000000000000005c000000000000000000000000020000000000000000000000000000000000007c000000000000000000000000020000000000000000000000000000000000007c000000800000000000000000020000000000000000000000000000000000006000000000000000000000000015e7a1bdcd507dd632d797d38e60cc5a9c0749b9a63097a215c4d006126825c6000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffff7f80000000000000000000000000000000000000000000000000000000000000004d6a232800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000027ab1adc9bca76301ed7a691320766dfa4b4b1aa32c9e05cf789611be7f8c75f000000000000000000000000000000000000000000000000fffffffffffffe9f000000000000000000000000000000000000000000000000ffffffffffffff1f000000000000000000000000ffffffffffffffff0000000000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000009cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f3902000002000000000000000000000000000000240000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aa2a733bb7bb003b0339859907d5d87320da3ef6410e30373a9137f83f9781a8129962b6882532b7c229de2e39de42322700000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff01ffc9a7000000000000000000000000000000000000000000000000000000005f68bc5a000000000000000000000000000000000000000000000000000000006ebd000dfc4dc9df04f723f827bae7694230795e8f22ed4af438e074cc982d18ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000100000000000000000200000000000000000000000000000000000020000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffe00000000000000000000000000000000000000000000003fffffffffffffffe0cfaa52e864a0086ea64c512703fea615e9f17fd2018cb9fb14e0cd14e20de5b1
Loading...
Loading
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.