DelegationRegistry
Signup to DeployContract Information
The following smart contract is a Delegation Registry that allows users to delegate certain actions to other addresses. It includes functions for delegating actions for all, a specific contract, or a specific token. It also includes functions for revoking delegates and checking if an address is a delegate for a specific action. The contract uses the OpenZeppelin library for EnumerableSet and ERC165.
More Info
## Public Information
- `delegations`: a mapping of delegations by vault and version.
- `vaultVersion`: a mapping of vault versions.
- `delegateVersion`: a mapping of delegate versions by vault and delegate.
- `delegationHashes`: a mapping of delegation hashes by delegate.
- `delegationInfo`: a mapping of delegation information by delegation hash.
## Public or external functions
- `delegateForAll`: sets a delegation for all contracts for a given delegate.
- `delegateForContract`: sets a delegation for a specific contract for a given delegate.
- `delegateForToken`: sets a delegation for a specific token for a given delegate.
- `revokeAllDelegates`: revokes all delegations for the calling vault.
- `revokeDelegate`: revokes a specific delegation for the calling vault.
- `revokeSelf`: revokes all delegations for the calling delegate and vault.
- `getDelegationsByDelegate`: returns an array of delegation information for a given delegate.
- `getDelegatesForAll`: returns an array of delegates for all contracts for a given vault.
- `getDelegatesForContract`: returns an array of delegates for a specific contract for a given vault.
- `getDelegatesForToken`: returns an array of delegates for a specific token for a given vault.
- `getContractLevelDelegations`: returns an array of contract-level delegations for a given vault.
- `getTokenLevelDelegations`: returns an array of token-level delegations for a given vault.
- `checkDelegateForAll`: checks if a delegate has a delegation for all contracts for a given vault.
- `checkDelegateForContract`: checks if a delegate has a delegation for a specific contract for a given vault.
- `checkDelegateForToken`: checks if a delegate has a delegation for a specific token for a given vault.
## Events
- `DelegateForAll`: emitted when a delegation for all contracts is set.
- `DelegateForContract`: emitted when a delegation for a specific contract is set.
- `DelegateForToken`: emitted when a delegation for a specific token is set.
- `RevokeAllDelegates`: emitted when all delegations are revoked for a vault.
- `RevokeDelegate`: emitted when a specific delegation is revoked for a vault.
## Inherits
- `ERC165`: provides support for interface detection.
- `delegations`: a mapping of delegations by vault and version.
- `vaultVersion`: a mapping of vault versions.
- `delegateVersion`: a mapping of delegate versions by vault and delegate.
- `delegationHashes`: a mapping of delegation hashes by delegate.
- `delegationInfo`: a mapping of delegation information by delegation hash.
## Public or external functions
- `delegateForAll`: sets a delegation for all contracts for a given delegate.
- `delegateForContract`: sets a delegation for a specific contract for a given delegate.
- `delegateForToken`: sets a delegation for a specific token for a given delegate.
- `revokeAllDelegates`: revokes all delegations for the calling vault.
- `revokeDelegate`: revokes a specific delegation for the calling vault.
- `revokeSelf`: revokes all delegations for the calling delegate and vault.
- `getDelegationsByDelegate`: returns an array of delegation information for a given delegate.
- `getDelegatesForAll`: returns an array of delegates for all contracts for a given vault.
- `getDelegatesForContract`: returns an array of delegates for a specific contract for a given vault.
- `getDelegatesForToken`: returns an array of delegates for a specific token for a given vault.
- `getContractLevelDelegations`: returns an array of contract-level delegations for a given vault.
- `getTokenLevelDelegations`: returns an array of token-level delegations for a given vault.
- `checkDelegateForAll`: checks if a delegate has a delegation for all contracts for a given vault.
- `checkDelegateForContract`: checks if a delegate has a delegation for a specific contract for a given vault.
- `checkDelegateForToken`: checks if a delegate has a delegation for a specific token for a given vault.
## Events
- `DelegateForAll`: emitted when a delegation for all contracts is set.
- `DelegateForContract`: emitted when a delegation for a specific contract is set.
- `DelegateForToken`: emitted when a delegation for a specific token is set.
- `RevokeAllDelegates`: emitted when all delegations are revoked for a vault.
- `RevokeDelegate`: emitted when a specific delegation is revoked for a vault.
## Inherits
- `ERC165`: provides support for interface detection.
{{
"language": "Solidity",
"sources": {
"src/DelegationRegistry.sol": {
"content": "// SPDX-License-Identifier: CC0-1.0\npragma solidity ^0.8.17;\n\nimport {IDelegationRegistry} from \"./IDelegationRegistry.sol\";\nimport {EnumerableSet} from \"openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\";\nimport {ERC165} from \"openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\";\n\n/**\n * @title DelegationRegistry\n * @custom:version 1.0\n * @notice An immutable registry contract to be deployed as a standalone primitive.\n * @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations\n * from here and integrate those permissions into their flow.\n * @custom:coauthor foobar (0xfoobar)\n * @custom:coauthor wwchung (manifoldxyz)\n * @custom:coauthor purplehat (artblocks)\n * @custom:coauthor ryley-o (artblocks)\n * @custom:coauthor andy8052 (tessera)\n * @custom:coauthor punk6529 (open metaverse)\n * @custom:coauthor loopify (loopiverse)\n * @custom:coauthor emiliano (nftrentals)\n * @custom:coauthor arran (proof)\n * @custom:coauthor james (collabland)\n * @custom:coauthor john (gnosis safe)\n * @custom:coauthor 0xrusowsky\n */\ncontract DelegationRegistry is IDelegationRegistry, ERC165 {\n using EnumerableSet for EnumerableSet.AddressSet;\n using EnumerableSet for EnumerableSet.Bytes32Set;\n\n /// @notice The global mapping and single source of truth for delegations\n /// @dev vault -> vaultVersion -> delegationHash\n mapping(address => mapping(uint256 => EnumerableSet.Bytes32Set)) internal delegations;\n\n /// @notice A mapping of wallets to versions (for cheap revocation)\n mapping(address => uint256) internal vaultVersion;\n\n /// @notice A mapping of wallets to delegates to versions (for cheap revocation)\n mapping(address => mapping(address => uint256)) internal delegateVersion;\n\n /// @notice A secondary mapping to return onchain enumerability of delegations that a given address can perform\n /// @dev delegate -> delegationHashes\n mapping(address => EnumerableSet.Bytes32Set) internal delegationHashes;\n\n /// @notice A secondary mapping used to return delegation information about a delegation\n /// @dev delegationHash -> DelegateInfo\n mapping(bytes32 => IDelegationRegistry.DelegationInfo) internal delegationInfo;\n\n /**\n * @inheritdoc ERC165\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override (ERC165) returns (bool) {\n return interfaceId == type(IDelegationRegistry).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * ----------- WRITE -----------\n */\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function delegateForAll(address delegate, bool value) external override {\n bytes32 delegationHash = _computeAllDelegationHash(msg.sender, delegate);\n _setDelegationValues(\n delegate, delegationHash, value, IDelegationRegistry.DelegationType.ALL, msg.sender, address(0), 0\n );\n emit IDelegationRegistry.DelegateForAll(msg.sender, delegate, value);\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function delegateForContract(address delegate, address contract_, bool value) external override {\n bytes32 delegationHash = _computeContractDelegationHash(msg.sender, delegate, contract_);\n _setDelegationValues(\n delegate, delegationHash, value, IDelegationRegistry.DelegationType.CONTRACT, msg.sender, contract_, 0\n );\n emit IDelegationRegistry.DelegateForContract(msg.sender, delegate, contract_, value);\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external override {\n bytes32 delegationHash = _computeTokenDelegationHash(msg.sender, delegate, contract_, tokenId);\n _setDelegationValues(\n delegate, delegationHash, value, IDelegationRegistry.DelegationType.TOKEN, msg.sender, contract_, tokenId\n );\n emit IDelegationRegistry.DelegateForToken(msg.sender, delegate, contract_, tokenId, value);\n }\n\n /**\n * @dev Helper function to set all delegation values and enumeration sets\n */\n function _setDelegationValues(\n address delegate,\n bytes32 delegateHash,\n bool value,\n IDelegationRegistry.DelegationType type_,\n address vault,\n address contract_,\n uint256 tokenId\n ) internal {\n if (value) {\n delegations[vault][vaultVersion[vault]].add(delegateHash);\n delegationHashes[delegate].add(delegateHash);\n delegationInfo[delegateHash] =\n DelegationInfo({vault: vault, delegate: delegate, type_: type_, contract_: contract_, tokenId: tokenId});\n } else {\n delegations[vault][vaultVersion[vault]].remove(delegateHash);\n delegationHashes[delegate].remove(delegateHash);\n delete delegationInfo[delegateHash];\n }\n }\n\n /**\n * @dev Helper function to compute delegation hash for wallet delegation\n */\n function _computeAllDelegationHash(address vault, address delegate) internal view returns (bytes32) {\n uint256 vaultVersion_ = vaultVersion[vault];\n uint256 delegateVersion_ = delegateVersion[vault][delegate];\n return keccak256(abi.encode(delegate, vault, vaultVersion_, delegateVersion_));\n }\n\n /**\n * @dev Helper function to compute delegation hash for contract delegation\n */\n function _computeContractDelegationHash(address vault, address delegate, address contract_)\n internal\n view\n returns (bytes32)\n {\n uint256 vaultVersion_ = vaultVersion[vault];\n uint256 delegateVersion_ = delegateVersion[vault][delegate];\n return keccak256(abi.encode(delegate, vault, contract_, vaultVersion_, delegateVersion_));\n }\n\n /**\n * @dev Helper function to compute delegation hash for token delegation\n */\n function _computeTokenDelegationHash(address vault, address delegate, address contract_, uint256 tokenId)\n internal\n view\n returns (bytes32)\n {\n uint256 vaultVersion_ = vaultVersion[vault];\n uint256 delegateVersion_ = delegateVersion[vault][delegate];\n return keccak256(abi.encode(delegate, vault, contract_, tokenId, vaultVersion_, delegateVersion_));\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function revokeAllDelegates() external override {\n ++vaultVersion[msg.sender];\n emit IDelegationRegistry.RevokeAllDelegates(msg.sender);\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function revokeDelegate(address delegate) external override {\n _revokeDelegate(delegate, msg.sender);\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function revokeSelf(address vault) external override {\n _revokeDelegate(msg.sender, vault);\n }\n\n /**\n * @dev Revoke the `delegate` hotwallet from the `vault` coldwallet.\n */\n function _revokeDelegate(address delegate, address vault) internal {\n ++delegateVersion[vault][delegate];\n // For enumerations, filter in the view functions\n emit IDelegationRegistry.RevokeDelegate(vault, msg.sender);\n }\n\n /**\n * ----------- READ -----------\n */\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function getDelegationsByDelegate(address delegate)\n external\n view\n returns (IDelegationRegistry.DelegationInfo[] memory info)\n {\n EnumerableSet.Bytes32Set storage potentialDelegationHashes = delegationHashes[delegate];\n uint256 potentialDelegationHashesLength = potentialDelegationHashes.length();\n uint256 delegationCount = 0;\n info = new IDelegationRegistry.DelegationInfo[](potentialDelegationHashesLength);\n for (uint256 i = 0; i < potentialDelegationHashesLength;) {\n bytes32 delegateHash = potentialDelegationHashes.at(i);\n IDelegationRegistry.DelegationInfo memory delegationInfo_ = delegationInfo[delegateHash];\n address vault = delegationInfo_.vault;\n IDelegationRegistry.DelegationType type_ = delegationInfo_.type_;\n bool valid = false;\n if (type_ == IDelegationRegistry.DelegationType.ALL) {\n if (delegateHash == _computeAllDelegationHash(vault, delegate)) {\n valid = true;\n }\n } else if (type_ == IDelegationRegistry.DelegationType.CONTRACT) {\n if (delegateHash == _computeContractDelegationHash(vault, delegate, delegationInfo_.contract_)) {\n valid = true;\n }\n } else if (type_ == IDelegationRegistry.DelegationType.TOKEN) {\n if (\n delegateHash\n == _computeTokenDelegationHash(vault, delegate, delegationInfo_.contract_, delegationInfo_.tokenId)\n ) {\n valid = true;\n }\n }\n if (valid) {\n info[delegationCount++] = delegationInfo_;\n }\n unchecked {\n ++i;\n }\n }\n if (potentialDelegationHashesLength > delegationCount) {\n assembly {\n let decrease := sub(potentialDelegationHashesLength, delegationCount)\n mstore(info, sub(mload(info), decrease))\n }\n }\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function getDelegatesForAll(address vault) external view returns (address[] memory delegates) {\n return _getDelegatesForLevel(vault, IDelegationRegistry.DelegationType.ALL, address(0), 0);\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function getDelegatesForContract(address vault, address contract_)\n external\n view\n override\n returns (address[] memory delegates)\n {\n return _getDelegatesForLevel(vault, IDelegationRegistry.DelegationType.CONTRACT, contract_, 0);\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function getDelegatesForToken(address vault, address contract_, uint256 tokenId)\n external\n view\n override\n returns (address[] memory delegates)\n {\n return _getDelegatesForLevel(vault, IDelegationRegistry.DelegationType.TOKEN, contract_, tokenId);\n }\n\n function _getDelegatesForLevel(\n address vault,\n IDelegationRegistry.DelegationType delegationType,\n address contract_,\n uint256 tokenId\n ) internal view returns (address[] memory delegates) {\n EnumerableSet.Bytes32Set storage delegationHashes_ = delegations[vault][vaultVersion[vault]];\n uint256 potentialDelegatesLength = delegationHashes_.length();\n uint256 delegatesCount = 0;\n delegates = new address[](potentialDelegatesLength);\n for (uint256 i = 0; i < potentialDelegatesLength;) {\n bytes32 delegationHash = delegationHashes_.at(i);\n DelegationInfo storage delegationInfo_ = delegationInfo[delegationHash];\n if (delegationInfo_.type_ == delegationType) {\n if (delegationType == IDelegationRegistry.DelegationType.ALL) {\n // check delegate version by validating the hash\n if (delegationHash == _computeAllDelegationHash(vault, delegationInfo_.delegate)) {\n delegates[delegatesCount++] = delegationInfo_.delegate;\n }\n } else if (delegationType == IDelegationRegistry.DelegationType.CONTRACT) {\n if (delegationInfo_.contract_ == contract_) {\n // check delegate version by validating the hash\n if (\n delegationHash == _computeContractDelegationHash(vault, delegationInfo_.delegate, contract_)\n ) {\n delegates[delegatesCount++] = delegationInfo_.delegate;\n }\n }\n } else if (delegationType == IDelegationRegistry.DelegationType.TOKEN) {\n if (delegationInfo_.contract_ == contract_ && delegationInfo_.tokenId == tokenId) {\n // check delegate version by validating the hash\n if (\n delegationHash\n == _computeTokenDelegationHash(vault, delegationInfo_.delegate, contract_, tokenId)\n ) {\n delegates[delegatesCount++] = delegationInfo_.delegate;\n }\n }\n }\n }\n unchecked {\n ++i;\n }\n }\n if (potentialDelegatesLength > delegatesCount) {\n assembly {\n let decrease := sub(potentialDelegatesLength, delegatesCount)\n mstore(delegates, sub(mload(delegates), decrease))\n }\n }\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function getContractLevelDelegations(address vault)\n external\n view\n returns (IDelegationRegistry.ContractDelegation[] memory contractDelegations)\n {\n EnumerableSet.Bytes32Set storage delegationHashes_ = delegations[vault][vaultVersion[vault]];\n uint256 potentialLength = delegationHashes_.length();\n uint256 delegationCount = 0;\n contractDelegations = new IDelegationRegistry.ContractDelegation[](potentialLength);\n for (uint256 i = 0; i < potentialLength;) {\n bytes32 delegationHash = delegationHashes_.at(i);\n DelegationInfo storage delegationInfo_ = delegationInfo[delegationHash];\n if (delegationInfo_.type_ == IDelegationRegistry.DelegationType.CONTRACT) {\n // check delegate version by validating the hash\n if (\n delegationHash\n == _computeContractDelegationHash(vault, delegationInfo_.delegate, delegationInfo_.contract_)\n ) {\n contractDelegations[delegationCount++] = IDelegationRegistry.ContractDelegation({\n contract_: delegationInfo_.contract_,\n delegate: delegationInfo_.delegate\n });\n }\n }\n unchecked {\n ++i;\n }\n }\n if (potentialLength > delegationCount) {\n assembly {\n let decrease := sub(potentialLength, delegationCount)\n mstore(contractDelegations, sub(mload(contractDelegations), decrease))\n }\n }\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function getTokenLevelDelegations(address vault)\n external\n view\n returns (IDelegationRegistry.TokenDelegation[] memory tokenDelegations)\n {\n EnumerableSet.Bytes32Set storage delegationHashes_ = delegations[vault][vaultVersion[vault]];\n uint256 potentialLength = delegationHashes_.length();\n uint256 delegationCount = 0;\n tokenDelegations = new IDelegationRegistry.TokenDelegation[](potentialLength);\n for (uint256 i = 0; i < potentialLength;) {\n bytes32 delegationHash = delegationHashes_.at(i);\n DelegationInfo storage delegationInfo_ = delegationInfo[delegationHash];\n if (delegationInfo_.type_ == IDelegationRegistry.DelegationType.TOKEN) {\n // check delegate version by validating the hash\n if (\n delegationHash\n == _computeTokenDelegationHash(\n vault, delegationInfo_.delegate, delegationInfo_.contract_, delegationInfo_.tokenId\n )\n ) {\n tokenDelegations[delegationCount++] = IDelegationRegistry.TokenDelegation({\n contract_: delegationInfo_.contract_,\n tokenId: delegationInfo_.tokenId,\n delegate: delegationInfo_.delegate\n });\n }\n }\n unchecked {\n ++i;\n }\n }\n if (potentialLength > delegationCount) {\n assembly {\n let decrease := sub(potentialLength, delegationCount)\n mstore(tokenDelegations, sub(mload(tokenDelegations), decrease))\n }\n }\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function checkDelegateForAll(address delegate, address vault) public view override returns (bool) {\n bytes32 delegateHash =\n keccak256(abi.encode(delegate, vault, vaultVersion[vault], delegateVersion[vault][delegate]));\n return delegations[vault][vaultVersion[vault]].contains(delegateHash);\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function checkDelegateForContract(address delegate, address vault, address contract_)\n public\n view\n override\n returns (bool)\n {\n bytes32 delegateHash =\n keccak256(abi.encode(delegate, vault, contract_, vaultVersion[vault], delegateVersion[vault][delegate]));\n return delegations[vault][vaultVersion[vault]].contains(delegateHash)\n ? true\n : checkDelegateForAll(delegate, vault);\n }\n\n /**\n * @inheritdoc IDelegationRegistry\n */\n function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId)\n public\n view\n override\n returns (bool)\n {\n bytes32 delegateHash = keccak256(\n abi.encode(delegate, vault, contract_, tokenId, vaultVersion[vault], delegateVersion[vault][delegate])\n );\n return delegations[vault][vaultVersion[vault]].contains(delegateHash)\n ? true\n : checkDelegateForContract(delegate, vault, contract_);\n }\n}\n"
},
"src/IDelegationRegistry.sol": {
"content": "// SPDX-License-Identifier: CC0-1.0\npragma solidity ^0.8.17;\n\n/**\n * @title An immutable registry contract to be deployed as a standalone primitive\n * @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations\n * from here and integrate those permissions into their flow\n */\ninterface IDelegationRegistry {\n /// @notice Delegation type\n enum DelegationType {\n NONE,\n ALL,\n CONTRACT,\n TOKEN\n }\n\n /// @notice Info about a single delegation, used for onchain enumeration\n struct DelegationInfo {\n DelegationType type_;\n address vault;\n address delegate;\n address contract_;\n uint256 tokenId;\n }\n\n /// @notice Info about a single contract-level delegation\n struct ContractDelegation {\n address contract_;\n address delegate;\n }\n\n /// @notice Info about a single token-level delegation\n struct TokenDelegation {\n address contract_;\n uint256 tokenId;\n address delegate;\n }\n\n /// @notice Emitted when a user delegates their entire wallet\n event DelegateForAll(address vault, address delegate, bool value);\n\n /// @notice Emitted when a user delegates a specific contract\n event DelegateForContract(address vault, address delegate, address contract_, bool value);\n\n /// @notice Emitted when a user delegates a specific token\n event DelegateForToken(address vault, address delegate, address contract_, uint256 tokenId, bool value);\n\n /// @notice Emitted when a user revokes all delegations\n event RevokeAllDelegates(address vault);\n\n /// @notice Emitted when a user revoes all delegations for a given delegate\n event RevokeDelegate(address vault, address delegate);\n\n /**\n * ----------- WRITE -----------\n */\n\n /**\n * @notice Allow the delegate to act on your behalf for all contracts\n * @param delegate The hotwallet to act on your behalf\n * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking\n */\n function delegateForAll(address delegate, bool value) external;\n\n /**\n * @notice Allow the delegate to act on your behalf for a specific contract\n * @param delegate The hotwallet to act on your behalf\n * @param contract_ The address for the contract you're delegating\n * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking\n */\n function delegateForContract(address delegate, address contract_, bool value) external;\n\n /**\n * @notice Allow the delegate to act on your behalf for a specific token\n * @param delegate The hotwallet to act on your behalf\n * @param contract_ The address for the contract you're delegating\n * @param tokenId The token id for the token you're delegating\n * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking\n */\n function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external;\n\n /**\n * @notice Revoke all delegates\n */\n function revokeAllDelegates() external;\n\n /**\n * @notice Revoke a specific delegate for all their permissions\n * @param delegate The hotwallet to revoke\n */\n function revokeDelegate(address delegate) external;\n\n /**\n * @notice Remove yourself as a delegate for a specific vault\n * @param vault The vault which delegated to the msg.sender, and should be removed\n */\n function revokeSelf(address vault) external;\n\n /**\n * ----------- READ -----------\n */\n\n /**\n * @notice Returns all active delegations a given delegate is able to claim on behalf of\n * @param delegate The delegate that you would like to retrieve delegations for\n * @return info Array of DelegationInfo structs\n */\n function getDelegationsByDelegate(address delegate) external view returns (DelegationInfo[] memory);\n\n /**\n * @notice Returns an array of wallet-level delegates for a given vault\n * @param vault The cold wallet who issued the delegation\n * @return addresses Array of wallet-level delegates for a given vault\n */\n function getDelegatesForAll(address vault) external view returns (address[] memory);\n\n /**\n * @notice Returns an array of contract-level delegates for a given vault and contract\n * @param vault The cold wallet who issued the delegation\n * @param contract_ The address for the contract you're delegating\n * @return addresses Array of contract-level delegates for a given vault and contract\n */\n function getDelegatesForContract(address vault, address contract_) external view returns (address[] memory);\n\n /**\n * @notice Returns an array of contract-level delegates for a given vault's token\n * @param vault The cold wallet who issued the delegation\n * @param contract_ The address for the contract holding the token\n * @param tokenId The token id for the token you're delegating\n * @return addresses Array of contract-level delegates for a given vault's token\n */\n function getDelegatesForToken(address vault, address contract_, uint256 tokenId)\n external\n view\n returns (address[] memory);\n\n /**\n * @notice Returns all contract-level delegations for a given vault\n * @param vault The cold wallet who issued the delegations\n * @return delegations Array of ContractDelegation structs\n */\n function getContractLevelDelegations(address vault)\n external\n view\n returns (ContractDelegation[] memory delegations);\n\n /**\n * @notice Returns all token-level delegations for a given vault\n * @param vault The cold wallet who issued the delegations\n * @return delegations Array of TokenDelegation structs\n */\n function getTokenLevelDelegations(address vault) external view returns (TokenDelegation[] memory delegations);\n\n /**\n * @notice Returns true if the address is delegated to act on the entire vault\n * @param delegate The hotwallet to act on your behalf\n * @param vault The cold wallet who issued the delegation\n */\n function checkDelegateForAll(address delegate, address vault) external view returns (bool);\n\n /**\n * @notice Returns true if the address is delegated to act on your behalf for a token contract or an entire vault\n * @param delegate The hotwallet to act on your behalf\n * @param contract_ The address for the contract you're delegating\n * @param vault The cold wallet who issued the delegation\n */\n function checkDelegateForContract(address delegate, address vault, address contract_)\n external\n view\n returns (bool);\n\n /**\n * @notice Returns true if the address is delegated to act on your behalf for a specific token, the token's contract or an entire vault\n * @param delegate The hotwallet to act on your behalf\n * @param contract_ The address for the contract you're delegating\n * @param tokenId The token id for the token you're delegating\n * @param vault The cold wallet who issued the delegation\n */\n function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId)\n external\n view\n returns (bool);\n}\n"
},
"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n return _values(set._inner);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n"
},
"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n"
},
"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
}
},
"settings": {
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"libraries": {}
}
}}
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"DelegateForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"address","name":"contract_","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"DelegateForContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"address","name":"contract_","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"DelegateForToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"}],"name":"RevokeAllDelegates","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"delegate","type":"address"}],"name":"RevokeDelegate","type":"event"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"vault","type":"address"}],"name":"checkDelegateForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"contract_","type":"address"}],"name":"checkDelegateForContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"checkDelegateForToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"delegateForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"delegateForContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"value","type":"bool"}],"name":"delegateForToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"getContractLevelDelegations","outputs":[{"components":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"address","name":"delegate","type":"address"}],"internalType":"struct IDelegationRegistry.ContractDelegation[]","name":"contractDelegations","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"getDelegatesForAll","outputs":[{"internalType":"address[]","name":"delegates","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"contract_","type":"address"}],"name":"getDelegatesForContract","outputs":[{"internalType":"address[]","name":"delegates","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getDelegatesForToken","outputs":[{"internalType":"address[]","name":"delegates","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"getDelegationsByDelegate","outputs":[{"components":[{"internalType":"enum IDelegationRegistry.DelegationType","name":"type_","type":"uint8"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct IDelegationRegistry.DelegationInfo[]","name":"info","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"getTokenLevelDelegations","outputs":[{"components":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"delegate","type":"address"}],"internalType":"struct IDelegationRegistry.TokenDelegation[]","name":"tokenDelegations","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revokeAllDelegates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"revokeDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"revokeSelf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"DelegateForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"address","name":"contract_","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"DelegateForContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"address","name":"contract_","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"DelegateForToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"}],"name":"RevokeAllDelegates","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"delegate","type":"address"}],"name":"RevokeDelegate","type":"event"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"vault","type":"address"}],"name":"checkDelegateForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"contract_","type":"address"}],"name":"checkDelegateForContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"checkDelegateForToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"delegateForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"delegateForContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"value","type":"bool"}],"name":"delegateForToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"getContractLevelDelegations","outputs":[{"components":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"address","name":"delegate","type":"address"}],"internalType":"struct IDelegationRegistry.ContractDelegation[]","name":"contractDelegations","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"getDelegatesForAll","outputs":[{"internalType":"address[]","name":"delegates","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"contract_","type":"address"}],"name":"getDelegatesForContract","outputs":[{"internalType":"address[]","name":"delegates","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getDelegatesForToken","outputs":[{"internalType":"address[]","name":"delegates","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"getDelegationsByDelegate","outputs":[{"components":[{"internalType":"enum IDelegationRegistry.DelegationType","name":"type_","type":"uint8"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct IDelegationRegistry.DelegationInfo[]","name":"info","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"getTokenLevelDelegations","outputs":[{"components":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"delegate","type":"address"}],"internalType":"struct IDelegationRegistry.TokenDelegation[]","name":"tokenDelegations","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revokeAllDelegates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"revokeDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"revokeSelf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
608060405234801561001057600080fd5b50611856806100206000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063685ee3e811610097578063aba69cf811610066578063aba69cf81461021c578063ed4b878e1461022f578063f956cf9414610242578063fa352c001461026257600080fd5b8063685ee3e8146101c35780636f007d87146101d657806390c9a2d0146101f65780639c395bc21461020957600080fd5b806336137872116100d3578063361378721461017557806349c95d291461017d5780634fc6928214610190578063537a5c3d146101b057600080fd5b806301ffc9a7146101055780631221156b1461012d5780631b61f6751461014d578063219044b014610160575b600080fd5b61011861011336600461138f565b610275565b60405190151581526020015b60405180910390f35b61014061013b3660046113d5565b6102ac565b6040516101249190611411565b61014061015b36600461145e565b6102c3565b61017361016e36600461145e565b6102d3565b005b6101736102e0565b61017361018b366004611489565b610336565b6101a361019e36600461145e565b6103ad565b60405161012491906114e2565b6101736101be36600461157f565b6105e8565b6101736101d13660046115cc565b610667565b6101e96101e436600461145e565b6106d4565b60405161012491906115ff565b610118610204366004611665565b61084d565b61011861021736600461169f565b6108f8565b61011861022a3660046116c9565b61097e565b61014061023d36600461169f565b610a33565b61025561025036600461145e565b610a4a565b6040516101249190611714565b61017361027036600461145e565b610baa565b60006001600160e01b03198216630596d3d560e01b14806102a657506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606102bb8460038585610bb4565b949350505050565b60606102a6826001600080610bb4565b6102dd3382610e2e565b50565b33600090815260016020526040812080549091906102fd90611779565b909155506040513381527f32d74befd0b842e19694e3e3af46263e18bcce41352c8b600ff0002b49edf6629060200160405180910390a1565b6000610343338585610eac565b9050610356848284600233886000610f1e565b604080513381526001600160a01b038681166020830152851681830152831515606082015290517f8d6b2f5255b8d815cc368855b2251146e003bf4e2fcccaec66145fff5c174b4f9181900360800190a150505050565b6001600160a01b03811660009081526003602052604081206060916103d182611100565b905060008167ffffffffffffffff8111156103ee576103ee611792565b60405190808252806020026020018201604052801561044757816020015b6040805160a08101825260008082526020808301829052928201819052606082018190526080820152825260001990920191018161040c5790505b50935060005b828110156105cd576000610461858361110a565b600081815260046020526040808220815160a0810190925280549394509192909190829060ff166003811115610499576104996114cc565b60038111156104aa576104aa6114cc565b815281546001600160a01b03610100909104811660208084019190915260018085015483166040850152600285015490921660608401526003909301546080909201919091529082015182519293509190600090826003811115610510576105106114cc565b0361052e5761051f838c611116565b8503610529575060015b61058d565b6002826003811115610542576105426114cc565b036105565761051f838c8660600151610eac565b600382600381111561056a5761056a6114cc565b0361058d57610583838c86606001518760800151611184565b850361058d575060015b80156105bd57838a8861059f81611779565b9950815181106105b1576105b16117a8565b60200260200101819052505b856001019550505050505061044d565b50808211156105e0578351818303900384525b505050919050565b60006105f633868686611184565b90506106088582846003338989610f1e565b604080513381526001600160a01b03878116602083015286168183015260608101859052831515608082015290517fe89c6ba1e8957285aed22618f52aa1dcb9d5bb64e1533d8b55136c72fcf5aa5d9181900360a00190a15050505050565b60006106733384611116565b9050610686838284600133600080610f1e565b604080513381526001600160a01b03851660208201528315158183015290517f58781eab4a0743ab1c285a238be846a235f06cdb5b968030573a635e5f8c92fa9181900360600190a1505050565b6001600160a01b03811660009081526020818152604080832060018352818420548452909152812060609161070882611100565b905060008167ffffffffffffffff81111561072557610725611792565b60405190808252806020026020018201604052801561077057816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107435790505b50935060005b828110156105cd57600061078a858361110a565b60008181526004602052604090209091506003815460ff1660038111156107b3576107b36114cc565b03610843576001810154600282015460038301546107e1928b926001600160a01b0391821692911690611184565b8203610843576040805160608101825260028301546001600160a01b0390811682526003840154602083015260018401541691810191909152878561082581611779565b965081518110610837576108376117a8565b60200260200101819052505b5050600101610776565b6001600160a01b03828116600081815260016020908152604080832054600283528184208987168086529084528285205483518086019290925281840187905296881660608201526080810182905260a0808201979097528251808203909701875260c00182528551958301959095209383528282528083209483529390529182206108d990826111f3565b6108ec576108e785856108f8565b6108ef565b60015b95945050505050565b6001600160a01b038181166000818152600160209081526040808320546002835281842095881680855295835281842054825180850197909752868301869052606087018290526080808801919091528251808803909101815260a090960182528551958301959095209383528282528083209483529390529182206102bb90826111f3565b6001600160a01b03808416600090815260016020908152604080832054600283528184209489168452938252808320549051929384936109c9938a938a938a938a93919291016117be565b60408051601f1981840301815291815281516020928301206001600160a01b0388166000908152808452828120600185528382205482529093529120909150610a1290826111f3565b610a2657610a2186868661084d565b610a29565b60015b9695505050505050565b6060610a43836002846000610bb4565b9392505050565b6001600160a01b038116600090815260208181526040808320600183528184205484529091528120606091610a7e82611100565b905060008167ffffffffffffffff811115610a9b57610a9b611792565b604051908082528060200260200182016040528015610ae057816020015b6040805180820190915260008082526020820152815260200190600190039081610ab95790505b50935060005b828110156105cd576000610afa858361110a565b60008181526004602052604090209091506002815460ff166003811115610b2357610b236114cc565b03610ba05760018101546002820154610b4a918a916001600160a01b039182169116610eac565b8203610ba0576040805180820190915260028201546001600160a01b03908116825260018301541660208201528785610b8281611779565b965081518110610b9457610b946117a8565b60200260200101819052505b5050600101610ae6565b6102dd8133610e2e565b6001600160a01b038416600090815260208181526040808320600183528184205484529091528120606091610be882611100565b905060008167ffffffffffffffff811115610c0557610c05611792565b604051908082528060200260200182016040528015610c2e578160200160208202803683370190505b50935060005b82811015610e10576000610c48858361110a565b6000818152600460205260409020909150896003811115610c6b57610c6b6114cc565b815460ff166003811115610c8157610c816114cc565b03610e065760018a6003811115610c9a57610c9a6114cc565b03610d0f576001810154610cb8908c906001600160a01b0316611116565b8203610d0a5760018101546001600160a01b03168785610cd781611779565b965081518110610ce957610ce96117a8565b60200260200101906001600160a01b031690816001600160a01b0316815250505b610e06565b60028a6003811115610d2357610d236114cc565b03610d595760028101546001600160a01b03808b16911603610d0a576001810154610cb8908c906001600160a01b03168b610eac565b60038a6003811115610d6d57610d6d6114cc565b03610e065760028101546001600160a01b038a81169116148015610d945750878160030154145b15610e06576001810154610db4908c906001600160a01b03168b8b611184565b8203610e065760018101546001600160a01b03168785610dd381611779565b965081518110610de557610de56117a8565b60200260200101906001600160a01b031690816001600160a01b0316815250505b5050600101610c34565b5080821115610e23578351818303900384525b505050949350505050565b6001600160a01b03808216600090815260026020908152604080832093861683529290529081208054909190610e6390611779565b90915550604080516001600160a01b03831681523360208201527f3e34a3ee53064fb79c0ee57448f03774a627a9270b0c41286efb7d8e32dcde93910160405180910390a15050565b6001600160a01b0392831660008181526001602090815260408083205460028352818420968816808552968352928190205481518084019790975286820194909452939095166060850152608084015260a0808401919091528151808403909101815260c09092019052805191012090565b8415611060576001600160a01b038316600090815260208181526040808320600183528184205484529091529020610f56908761120b565b506001600160a01b0387166000908152600360205260409020610f79908761120b565b506040518060a00160405280856003811115610f9757610f976114cc565b81526001600160a01b038086166020808401919091528a82166040808501919091529186166060840152608090920184905260008981526004909252902081518154829060ff19166001836003811115610ff357610ff36114cc565b0217905550602082015181546001600160a01b0391821661010002610100600160a81b031990911617825560408301516001830180549183166001600160a01b031992831617905560608401516002840180549190931691161790556080909101516003909101556110f7565b6001600160a01b0383166000908152602081815260408083206001835281842054845290915290206110929087611217565b506001600160a01b03871660009081526003602052604090206110b59087611217565b50600086815260046020526040812080546001600160a81b03191681556001810180546001600160a01b03199081169091556002820180549091169055600301555b50505050505050565b60006102a6825490565b6000610a438383611223565b6001600160a01b03918216600081815260016020908152604080832054600283528184209590961680845294825291829020548251808301959095528483019390935260608401949094526080808401929092528051808403909201825260a0909201909152805191012090565b6001600160a01b0380851660009081526001602090815260408083205460028352818420948816845293825280832054905192939290916111d19188918a918991899188918891016117be565b6040516020818303038152906040528051906020012092505050949350505050565b60008181526001830160205260408120541515610a43565b6000610a43838361124d565b6000610a43838361129c565b600082600001828154811061123a5761123a6117a8565b9060005260206000200154905092915050565b6000818152600183016020526040812054611294575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102a6565b5060006102a6565b600081815260018301602052604081205480156113855760006112c06001836117f7565b85549091506000906112d4906001906117f7565b90508181146113395760008660000182815481106112f4576112f46117a8565b9060005260206000200154905080876000018481548110611317576113176117a8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061134a5761134a61180a565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102a6565b60009150506102a6565b6000602082840312156113a157600080fd5b81356001600160e01b031981168114610a4357600080fd5b80356001600160a01b03811681146113d057600080fd5b919050565b6000806000606084860312156113ea57600080fd5b6113f3846113b9565b9250611401602085016113b9565b9150604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b818110156114525783516001600160a01b03168352928401929184019160010161142d565b50909695505050505050565b60006020828403121561147057600080fd5b610a43826113b9565b803580151581146113d057600080fd5b60008060006060848603121561149e57600080fd5b6114a7846113b9565b92506114b5602085016113b9565b91506114c360408501611479565b90509250925092565b634e487b7160e01b600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b838110156115715782518051600480821061152857634e487b7160e01b855260218152602485fd5b508652808801516001600160a01b039081168988015287820151811688880152606080830151909116908701526080908101519086015260a09094019391860191600101611500565b509298975050505050505050565b6000806000806080858703121561159557600080fd5b61159e856113b9565b93506115ac602086016113b9565b9250604085013591506115c160608601611479565b905092959194509250565b600080604083850312156115df57600080fd5b6115e8836113b9565b91506115f660208401611479565b90509250929050565b602080825282518282018190526000919060409081850190868401855b8281101561165857815180516001600160a01b03908116865287820151888701529086015116858501526060909301929085019060010161161c565b5091979650505050505050565b60008060006060848603121561167a57600080fd5b611683846113b9565b9250611691602085016113b9565b91506114c3604085016113b9565b600080604083850312156116b257600080fd5b6116bb836113b9565b91506115f6602084016113b9565b600080600080608085870312156116df57600080fd5b6116e8856113b9565b93506116f6602086016113b9565b9250611704604086016113b9565b9396929550929360600135925050565b602080825282518282018190526000919060409081850190868401855b8281101561165857815180516001600160a01b0390811686529087015116868501529284019290850190600101611731565b634e487b7160e01b600052601160045260246000fd5b60006001820161178b5761178b611763565b5060010190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b818103818111156102a6576102a6611763565b634e487b7160e01b600052603160045260246000fdfea26469706673582212206b0b0a636b8da72fa85cb1817045c30ca104b227b960f8aae85f0c81f76bd66764736f6c63430008110033
608060405234801561001057600080fd5b50611856806100206000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063685ee3e811610097578063aba69cf811610066578063aba69cf81461021c578063ed4b878e1461022f578063f956cf9414610242578063fa352c001461026257600080fd5b8063685ee3e8146101c35780636f007d87146101d657806390c9a2d0146101f65780639c395bc21461020957600080fd5b806336137872116100d3578063361378721461017557806349c95d291461017d5780634fc6928214610190578063537a5c3d146101b057600080fd5b806301ffc9a7146101055780631221156b1461012d5780631b61f6751461014d578063219044b014610160575b600080fd5b61011861011336600461138f565b610275565b60405190151581526020015b60405180910390f35b61014061013b3660046113d5565b6102ac565b6040516101249190611411565b61014061015b36600461145e565b6102c3565b61017361016e36600461145e565b6102d3565b005b6101736102e0565b61017361018b366004611489565b610336565b6101a361019e36600461145e565b6103ad565b60405161012491906114e2565b6101736101be36600461157f565b6105e8565b6101736101d13660046115cc565b610667565b6101e96101e436600461145e565b6106d4565b60405161012491906115ff565b610118610204366004611665565b61084d565b61011861021736600461169f565b6108f8565b61011861022a3660046116c9565b61097e565b61014061023d36600461169f565b610a33565b61025561025036600461145e565b610a4a565b6040516101249190611714565b61017361027036600461145e565b610baa565b60006001600160e01b03198216630596d3d560e01b14806102a657506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606102bb8460038585610bb4565b949350505050565b60606102a6826001600080610bb4565b6102dd3382610e2e565b50565b33600090815260016020526040812080549091906102fd90611779565b909155506040513381527f32d74befd0b842e19694e3e3af46263e18bcce41352c8b600ff0002b49edf6629060200160405180910390a1565b6000610343338585610eac565b9050610356848284600233886000610f1e565b604080513381526001600160a01b038681166020830152851681830152831515606082015290517f8d6b2f5255b8d815cc368855b2251146e003bf4e2fcccaec66145fff5c174b4f9181900360800190a150505050565b6001600160a01b03811660009081526003602052604081206060916103d182611100565b905060008167ffffffffffffffff8111156103ee576103ee611792565b60405190808252806020026020018201604052801561044757816020015b6040805160a08101825260008082526020808301829052928201819052606082018190526080820152825260001990920191018161040c5790505b50935060005b828110156105cd576000610461858361110a565b600081815260046020526040808220815160a0810190925280549394509192909190829060ff166003811115610499576104996114cc565b60038111156104aa576104aa6114cc565b815281546001600160a01b03610100909104811660208084019190915260018085015483166040850152600285015490921660608401526003909301546080909201919091529082015182519293509190600090826003811115610510576105106114cc565b0361052e5761051f838c611116565b8503610529575060015b61058d565b6002826003811115610542576105426114cc565b036105565761051f838c8660600151610eac565b600382600381111561056a5761056a6114cc565b0361058d57610583838c86606001518760800151611184565b850361058d575060015b80156105bd57838a8861059f81611779565b9950815181106105b1576105b16117a8565b60200260200101819052505b856001019550505050505061044d565b50808211156105e0578351818303900384525b505050919050565b60006105f633868686611184565b90506106088582846003338989610f1e565b604080513381526001600160a01b03878116602083015286168183015260608101859052831515608082015290517fe89c6ba1e8957285aed22618f52aa1dcb9d5bb64e1533d8b55136c72fcf5aa5d9181900360a00190a15050505050565b60006106733384611116565b9050610686838284600133600080610f1e565b604080513381526001600160a01b03851660208201528315158183015290517f58781eab4a0743ab1c285a238be846a235f06cdb5b968030573a635e5f8c92fa9181900360600190a1505050565b6001600160a01b03811660009081526020818152604080832060018352818420548452909152812060609161070882611100565b905060008167ffffffffffffffff81111561072557610725611792565b60405190808252806020026020018201604052801561077057816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107435790505b50935060005b828110156105cd57600061078a858361110a565b60008181526004602052604090209091506003815460ff1660038111156107b3576107b36114cc565b03610843576001810154600282015460038301546107e1928b926001600160a01b0391821692911690611184565b8203610843576040805160608101825260028301546001600160a01b0390811682526003840154602083015260018401541691810191909152878561082581611779565b965081518110610837576108376117a8565b60200260200101819052505b5050600101610776565b6001600160a01b03828116600081815260016020908152604080832054600283528184208987168086529084528285205483518086019290925281840187905296881660608201526080810182905260a0808201979097528251808203909701875260c00182528551958301959095209383528282528083209483529390529182206108d990826111f3565b6108ec576108e785856108f8565b6108ef565b60015b95945050505050565b6001600160a01b038181166000818152600160209081526040808320546002835281842095881680855295835281842054825180850197909752868301869052606087018290526080808801919091528251808803909101815260a090960182528551958301959095209383528282528083209483529390529182206102bb90826111f3565b6001600160a01b03808416600090815260016020908152604080832054600283528184209489168452938252808320549051929384936109c9938a938a938a938a93919291016117be565b60408051601f1981840301815291815281516020928301206001600160a01b0388166000908152808452828120600185528382205482529093529120909150610a1290826111f3565b610a2657610a2186868661084d565b610a29565b60015b9695505050505050565b6060610a43836002846000610bb4565b9392505050565b6001600160a01b038116600090815260208181526040808320600183528184205484529091528120606091610a7e82611100565b905060008167ffffffffffffffff811115610a9b57610a9b611792565b604051908082528060200260200182016040528015610ae057816020015b6040805180820190915260008082526020820152815260200190600190039081610ab95790505b50935060005b828110156105cd576000610afa858361110a565b60008181526004602052604090209091506002815460ff166003811115610b2357610b236114cc565b03610ba05760018101546002820154610b4a918a916001600160a01b039182169116610eac565b8203610ba0576040805180820190915260028201546001600160a01b03908116825260018301541660208201528785610b8281611779565b965081518110610b9457610b946117a8565b60200260200101819052505b5050600101610ae6565b6102dd8133610e2e565b6001600160a01b038416600090815260208181526040808320600183528184205484529091528120606091610be882611100565b905060008167ffffffffffffffff811115610c0557610c05611792565b604051908082528060200260200182016040528015610c2e578160200160208202803683370190505b50935060005b82811015610e10576000610c48858361110a565b6000818152600460205260409020909150896003811115610c6b57610c6b6114cc565b815460ff166003811115610c8157610c816114cc565b03610e065760018a6003811115610c9a57610c9a6114cc565b03610d0f576001810154610cb8908c906001600160a01b0316611116565b8203610d0a5760018101546001600160a01b03168785610cd781611779565b965081518110610ce957610ce96117a8565b60200260200101906001600160a01b031690816001600160a01b0316815250505b610e06565b60028a6003811115610d2357610d236114cc565b03610d595760028101546001600160a01b03808b16911603610d0a576001810154610cb8908c906001600160a01b03168b610eac565b60038a6003811115610d6d57610d6d6114cc565b03610e065760028101546001600160a01b038a81169116148015610d945750878160030154145b15610e06576001810154610db4908c906001600160a01b03168b8b611184565b8203610e065760018101546001600160a01b03168785610dd381611779565b965081518110610de557610de56117a8565b60200260200101906001600160a01b031690816001600160a01b0316815250505b5050600101610c34565b5080821115610e23578351818303900384525b505050949350505050565b6001600160a01b03808216600090815260026020908152604080832093861683529290529081208054909190610e6390611779565b90915550604080516001600160a01b03831681523360208201527f3e34a3ee53064fb79c0ee57448f03774a627a9270b0c41286efb7d8e32dcde93910160405180910390a15050565b6001600160a01b0392831660008181526001602090815260408083205460028352818420968816808552968352928190205481518084019790975286820194909452939095166060850152608084015260a0808401919091528151808403909101815260c09092019052805191012090565b8415611060576001600160a01b038316600090815260208181526040808320600183528184205484529091529020610f56908761120b565b506001600160a01b0387166000908152600360205260409020610f79908761120b565b506040518060a00160405280856003811115610f9757610f976114cc565b81526001600160a01b038086166020808401919091528a82166040808501919091529186166060840152608090920184905260008981526004909252902081518154829060ff19166001836003811115610ff357610ff36114cc565b0217905550602082015181546001600160a01b0391821661010002610100600160a81b031990911617825560408301516001830180549183166001600160a01b031992831617905560608401516002840180549190931691161790556080909101516003909101556110f7565b6001600160a01b0383166000908152602081815260408083206001835281842054845290915290206110929087611217565b506001600160a01b03871660009081526003602052604090206110b59087611217565b50600086815260046020526040812080546001600160a81b03191681556001810180546001600160a01b03199081169091556002820180549091169055600301555b50505050505050565b60006102a6825490565b6000610a438383611223565b6001600160a01b03918216600081815260016020908152604080832054600283528184209590961680845294825291829020548251808301959095528483019390935260608401949094526080808401929092528051808403909201825260a0909201909152805191012090565b6001600160a01b0380851660009081526001602090815260408083205460028352818420948816845293825280832054905192939290916111d19188918a918991899188918891016117be565b6040516020818303038152906040528051906020012092505050949350505050565b60008181526001830160205260408120541515610a43565b6000610a43838361124d565b6000610a43838361129c565b600082600001828154811061123a5761123a6117a8565b9060005260206000200154905092915050565b6000818152600183016020526040812054611294575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102a6565b5060006102a6565b600081815260018301602052604081205480156113855760006112c06001836117f7565b85549091506000906112d4906001906117f7565b90508181146113395760008660000182815481106112f4576112f46117a8565b9060005260206000200154905080876000018481548110611317576113176117a8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061134a5761134a61180a565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102a6565b60009150506102a6565b6000602082840312156113a157600080fd5b81356001600160e01b031981168114610a4357600080fd5b80356001600160a01b03811681146113d057600080fd5b919050565b6000806000606084860312156113ea57600080fd5b6113f3846113b9565b9250611401602085016113b9565b9150604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b818110156114525783516001600160a01b03168352928401929184019160010161142d565b50909695505050505050565b60006020828403121561147057600080fd5b610a43826113b9565b803580151581146113d057600080fd5b60008060006060848603121561149e57600080fd5b6114a7846113b9565b92506114b5602085016113b9565b91506114c360408501611479565b90509250925092565b634e487b7160e01b600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b838110156115715782518051600480821061152857634e487b7160e01b855260218152602485fd5b508652808801516001600160a01b039081168988015287820151811688880152606080830151909116908701526080908101519086015260a09094019391860191600101611500565b509298975050505050505050565b6000806000806080858703121561159557600080fd5b61159e856113b9565b93506115ac602086016113b9565b9250604085013591506115c160608601611479565b905092959194509250565b600080604083850312156115df57600080fd5b6115e8836113b9565b91506115f660208401611479565b90509250929050565b602080825282518282018190526000919060409081850190868401855b8281101561165857815180516001600160a01b03908116865287820151888701529086015116858501526060909301929085019060010161161c565b5091979650505050505050565b60008060006060848603121561167a57600080fd5b611683846113b9565b9250611691602085016113b9565b91506114c3604085016113b9565b600080604083850312156116b257600080fd5b6116bb836113b9565b91506115f6602084016113b9565b600080600080608085870312156116df57600080fd5b6116e8856113b9565b93506116f6602086016113b9565b9250611704604086016113b9565b9396929550929360600135925050565b602080825282518282018190526000919060409081850190868401855b8281101561165857815180516001600160a01b0390811686529087015116868501529284019290850190600101611731565b634e487b7160e01b600052601160045260246000fd5b60006001820161178b5761178b611763565b5060010190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b818103818111156102a6576102a6611763565b634e487b7160e01b600052603160045260246000fdfea26469706673582212206b0b0a636b8da72fa85cb1817045c30ca104b227b960f8aae85f0c81f76bd66764736f6c63430008110033