ETH Price: $3,334.14 (-1.59%)
Gas: 21 Gwei

Contract

0x00000000000076A84feF008CDAbe6409d2FE638B
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Transaction Hash
Method
Block
From
To
Value
0x483e9471661ab33960eb475fa0bdd4b3b6d05aaa348c993f0011796dda2f6815 Delegate For All(pending)2024-06-25 17:21:5323 hrs ago1719336113IN
delegate.xyz v1
0 ETH(Pending)(Pending)
0x4954cddd865869e50e676dc934e29c640746062c7c64aa02d7fa7c4af97ec2c4 Delegate For All(pending)2024-06-23 4:30:303 days ago1719117030IN
delegate.xyz v1
0 ETH(Pending)(Pending)
0xaf0c7e3e4a21a462483ff666eb4acffca774e5d01157e77cfc59daacedde1b96 Delegate For All(pending)2024-06-23 3:20:233 days ago1719112823IN
delegate.xyz v1
0 ETH(Pending)(Pending)
0xda2eb34f32d40d482b8c7856a6d2c108e4d45e39b527c36f6eafcd087c26a24c Delegate For All(pending)2024-06-23 3:19:503 days ago1719112790IN
delegate.xyz v1
0 ETH(Pending)(Pending)
0x181bd7587182d7d53d04aa46e90fb1750c91472d2fe795587e34ba35c0a340b3 Delegate For All(pending)2024-06-23 2:49:523 days ago1719110992IN
delegate.xyz v1
0 ETH(Pending)(Pending)
Delegate For All201756932024-06-26 11:53:595 hrs ago1719402839IN
delegate.xyz v1
0 ETH0.000734043.46722437
Delegate For All201736802024-06-26 5:09:4712 hrs ago1719378587IN
delegate.xyz v1
0 ETH0.000420821.98776994
Delegate For All201707612024-06-25 19:23:2321 hrs ago1719343403IN
delegate.xyz v1
0 ETH0.0022250310.50985187
Delegate For Tok...201699392024-06-25 16:37:4724 hrs ago1719333467IN
delegate.xyz v1
0 ETH0.0007459811.39888744
Delegate For All201685112024-06-25 11:50:5929 hrs ago1719316259IN
delegate.xyz v1
0 ETH0.000276174.6164488
Delegate For All201627682024-06-24 16:34:352 days ago1719246875IN
delegate.xyz v1
0 ETH0.0009977414.6264363
Delegate For All201626832024-06-24 16:17:352 days ago1719245855IN
delegate.xyz v1
0 ETH0.001701158.74139411
Delegate For All201587182024-06-24 2:59:232 days ago1719197963IN
delegate.xyz v1
0 ETH0.000184263.08011775
Delegate For All201549952024-06-23 14:30:113 days ago1719153011IN
delegate.xyz v1
0 ETH0.0007673.62294412
Delegate For All201531652024-06-23 8:20:353 days ago1719130835IN
delegate.xyz v1
0 ETH0.00019873.32157004
Delegate For All201531492024-06-23 8:17:233 days ago1719130643IN
delegate.xyz v1
0 ETH0.000735783.47544706
Delegate For All201531462024-06-23 8:16:473 days ago1719130607IN
delegate.xyz v1
0 ETH0.000203433.40055959
Delegate For All201531162024-06-23 8:10:233 days ago1719130223IN
delegate.xyz v1
0 ETH0.000679253.20860398
Delegate For All201531042024-06-23 8:07:593 days ago1719130079IN
delegate.xyz v1
0 ETH0.000228553.82037702
Delegate For All201508122024-06-23 0:27:113 days ago1719102431IN
delegate.xyz v1
0 ETH0.000524362.69445057
Delegate For All201462672024-06-22 9:11:234 days ago1719047483IN
delegate.xyz v1
0 ETH0.000156992.30154504
Delegate For All201462482024-06-22 9:07:354 days ago1719047255IN
delegate.xyz v1
0 ETH0.000442172.27213301
Delegate For All201459612024-06-22 8:09:594 days ago1719043799IN
delegate.xyz v1
0 ETH0.000605152.85843925
Delegate For All201449302024-06-22 4:41:594 days ago1719031319IN
delegate.xyz v1
0 ETH0.000568632.68592773
Delegate For All201433162024-06-21 23:16:474 days ago1719011807IN
delegate.xyz v1
0 ETH0.0001732.89182265
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To Value
155966232022-09-23 14:24:23642 days ago1663943063  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DelegationRegistry

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 5 : DelegationRegistry.sol
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.17;

import {IDelegationRegistry} from "./IDelegationRegistry.sol";
import {EnumerableSet} from "openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol";
import {ERC165} from "openzeppelin-contracts/contracts/utils/introspection/ERC165.sol";

/**
 * @title DelegationRegistry
 * @custom:version 1.0
 * @notice An immutable registry contract to be deployed as a standalone primitive.
 * @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations
 * from here and integrate those permissions into their flow.
 * @custom:coauthor foobar (0xfoobar)
 * @custom:coauthor wwchung (manifoldxyz)
 * @custom:coauthor purplehat (artblocks)
 * @custom:coauthor ryley-o (artblocks)
 * @custom:coauthor andy8052 (tessera)
 * @custom:coauthor punk6529 (open metaverse)
 * @custom:coauthor loopify (loopiverse)
 * @custom:coauthor emiliano (nftrentals)
 * @custom:coauthor arran (proof)
 * @custom:coauthor james (collabland)
 * @custom:coauthor john (gnosis safe)
 * @custom:coauthor 0xrusowsky
 */
contract DelegationRegistry is IDelegationRegistry, ERC165 {
    using EnumerableSet for EnumerableSet.AddressSet;
    using EnumerableSet for EnumerableSet.Bytes32Set;

    /// @notice The global mapping and single source of truth for delegations
    /// @dev vault -> vaultVersion -> delegationHash
    mapping(address => mapping(uint256 => EnumerableSet.Bytes32Set)) internal delegations;

    /// @notice A mapping of wallets to versions (for cheap revocation)
    mapping(address => uint256) internal vaultVersion;

    /// @notice A mapping of wallets to delegates to versions (for cheap revocation)
    mapping(address => mapping(address => uint256)) internal delegateVersion;

    /// @notice A secondary mapping to return onchain enumerability of delegations that a given address can perform
    /// @dev delegate -> delegationHashes
    mapping(address => EnumerableSet.Bytes32Set) internal delegationHashes;

    /// @notice A secondary mapping used to return delegation information about a delegation
    /// @dev delegationHash -> DelegateInfo
    mapping(bytes32 => IDelegationRegistry.DelegationInfo) internal delegationInfo;

    /**
     * @inheritdoc ERC165
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override (ERC165) returns (bool) {
        return interfaceId == type(IDelegationRegistry).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * -----------  WRITE -----------
     */

    /**
     * @inheritdoc IDelegationRegistry
     */
    function delegateForAll(address delegate, bool value) external override {
        bytes32 delegationHash = _computeAllDelegationHash(msg.sender, delegate);
        _setDelegationValues(
            delegate, delegationHash, value, IDelegationRegistry.DelegationType.ALL, msg.sender, address(0), 0
        );
        emit IDelegationRegistry.DelegateForAll(msg.sender, delegate, value);
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function delegateForContract(address delegate, address contract_, bool value) external override {
        bytes32 delegationHash = _computeContractDelegationHash(msg.sender, delegate, contract_);
        _setDelegationValues(
            delegate, delegationHash, value, IDelegationRegistry.DelegationType.CONTRACT, msg.sender, contract_, 0
        );
        emit IDelegationRegistry.DelegateForContract(msg.sender, delegate, contract_, value);
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external override {
        bytes32 delegationHash = _computeTokenDelegationHash(msg.sender, delegate, contract_, tokenId);
        _setDelegationValues(
            delegate, delegationHash, value, IDelegationRegistry.DelegationType.TOKEN, msg.sender, contract_, tokenId
        );
        emit IDelegationRegistry.DelegateForToken(msg.sender, delegate, contract_, tokenId, value);
    }

    /**
     * @dev Helper function to set all delegation values and enumeration sets
     */
    function _setDelegationValues(
        address delegate,
        bytes32 delegateHash,
        bool value,
        IDelegationRegistry.DelegationType type_,
        address vault,
        address contract_,
        uint256 tokenId
    ) internal {
        if (value) {
            delegations[vault][vaultVersion[vault]].add(delegateHash);
            delegationHashes[delegate].add(delegateHash);
            delegationInfo[delegateHash] =
                DelegationInfo({vault: vault, delegate: delegate, type_: type_, contract_: contract_, tokenId: tokenId});
        } else {
            delegations[vault][vaultVersion[vault]].remove(delegateHash);
            delegationHashes[delegate].remove(delegateHash);
            delete delegationInfo[delegateHash];
        }
    }

    /**
     * @dev Helper function to compute delegation hash for wallet delegation
     */
    function _computeAllDelegationHash(address vault, address delegate) internal view returns (bytes32) {
        uint256 vaultVersion_ = vaultVersion[vault];
        uint256 delegateVersion_ = delegateVersion[vault][delegate];
        return keccak256(abi.encode(delegate, vault, vaultVersion_, delegateVersion_));
    }

    /**
     * @dev Helper function to compute delegation hash for contract delegation
     */
    function _computeContractDelegationHash(address vault, address delegate, address contract_)
        internal
        view
        returns (bytes32)
    {
        uint256 vaultVersion_ = vaultVersion[vault];
        uint256 delegateVersion_ = delegateVersion[vault][delegate];
        return keccak256(abi.encode(delegate, vault, contract_, vaultVersion_, delegateVersion_));
    }

    /**
     * @dev Helper function to compute delegation hash for token delegation
     */
    function _computeTokenDelegationHash(address vault, address delegate, address contract_, uint256 tokenId)
        internal
        view
        returns (bytes32)
    {
        uint256 vaultVersion_ = vaultVersion[vault];
        uint256 delegateVersion_ = delegateVersion[vault][delegate];
        return keccak256(abi.encode(delegate, vault, contract_, tokenId, vaultVersion_, delegateVersion_));
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function revokeAllDelegates() external override {
        ++vaultVersion[msg.sender];
        emit IDelegationRegistry.RevokeAllDelegates(msg.sender);
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function revokeDelegate(address delegate) external override {
        _revokeDelegate(delegate, msg.sender);
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function revokeSelf(address vault) external override {
        _revokeDelegate(msg.sender, vault);
    }

    /**
     * @dev Revoke the `delegate` hotwallet from the `vault` coldwallet.
     */
    function _revokeDelegate(address delegate, address vault) internal {
        ++delegateVersion[vault][delegate];
        // For enumerations, filter in the view functions
        emit IDelegationRegistry.RevokeDelegate(vault, msg.sender);
    }

    /**
     * -----------  READ -----------
     */

    /**
     * @inheritdoc IDelegationRegistry
     */
    function getDelegationsByDelegate(address delegate)
        external
        view
        returns (IDelegationRegistry.DelegationInfo[] memory info)
    {
        EnumerableSet.Bytes32Set storage potentialDelegationHashes = delegationHashes[delegate];
        uint256 potentialDelegationHashesLength = potentialDelegationHashes.length();
        uint256 delegationCount = 0;
        info = new IDelegationRegistry.DelegationInfo[](potentialDelegationHashesLength);
        for (uint256 i = 0; i < potentialDelegationHashesLength;) {
            bytes32 delegateHash = potentialDelegationHashes.at(i);
            IDelegationRegistry.DelegationInfo memory delegationInfo_ = delegationInfo[delegateHash];
            address vault = delegationInfo_.vault;
            IDelegationRegistry.DelegationType type_ = delegationInfo_.type_;
            bool valid = false;
            if (type_ == IDelegationRegistry.DelegationType.ALL) {
                if (delegateHash == _computeAllDelegationHash(vault, delegate)) {
                    valid = true;
                }
            } else if (type_ == IDelegationRegistry.DelegationType.CONTRACT) {
                if (delegateHash == _computeContractDelegationHash(vault, delegate, delegationInfo_.contract_)) {
                    valid = true;
                }
            } else if (type_ == IDelegationRegistry.DelegationType.TOKEN) {
                if (
                    delegateHash
                        == _computeTokenDelegationHash(vault, delegate, delegationInfo_.contract_, delegationInfo_.tokenId)
                ) {
                    valid = true;
                }
            }
            if (valid) {
                info[delegationCount++] = delegationInfo_;
            }
            unchecked {
                ++i;
            }
        }
        if (potentialDelegationHashesLength > delegationCount) {
            assembly {
                let decrease := sub(potentialDelegationHashesLength, delegationCount)
                mstore(info, sub(mload(info), decrease))
            }
        }
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function getDelegatesForAll(address vault) external view returns (address[] memory delegates) {
        return _getDelegatesForLevel(vault, IDelegationRegistry.DelegationType.ALL, address(0), 0);
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function getDelegatesForContract(address vault, address contract_)
        external
        view
        override
        returns (address[] memory delegates)
    {
        return _getDelegatesForLevel(vault, IDelegationRegistry.DelegationType.CONTRACT, contract_, 0);
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function getDelegatesForToken(address vault, address contract_, uint256 tokenId)
        external
        view
        override
        returns (address[] memory delegates)
    {
        return _getDelegatesForLevel(vault, IDelegationRegistry.DelegationType.TOKEN, contract_, tokenId);
    }

    function _getDelegatesForLevel(
        address vault,
        IDelegationRegistry.DelegationType delegationType,
        address contract_,
        uint256 tokenId
    ) internal view returns (address[] memory delegates) {
        EnumerableSet.Bytes32Set storage delegationHashes_ = delegations[vault][vaultVersion[vault]];
        uint256 potentialDelegatesLength = delegationHashes_.length();
        uint256 delegatesCount = 0;
        delegates = new address[](potentialDelegatesLength);
        for (uint256 i = 0; i < potentialDelegatesLength;) {
            bytes32 delegationHash = delegationHashes_.at(i);
            DelegationInfo storage delegationInfo_ = delegationInfo[delegationHash];
            if (delegationInfo_.type_ == delegationType) {
                if (delegationType == IDelegationRegistry.DelegationType.ALL) {
                    // check delegate version by validating the hash
                    if (delegationHash == _computeAllDelegationHash(vault, delegationInfo_.delegate)) {
                        delegates[delegatesCount++] = delegationInfo_.delegate;
                    }
                } else if (delegationType == IDelegationRegistry.DelegationType.CONTRACT) {
                    if (delegationInfo_.contract_ == contract_) {
                        // check delegate version by validating the hash
                        if (
                            delegationHash == _computeContractDelegationHash(vault, delegationInfo_.delegate, contract_)
                        ) {
                            delegates[delegatesCount++] = delegationInfo_.delegate;
                        }
                    }
                } else if (delegationType == IDelegationRegistry.DelegationType.TOKEN) {
                    if (delegationInfo_.contract_ == contract_ && delegationInfo_.tokenId == tokenId) {
                        // check delegate version by validating the hash
                        if (
                            delegationHash
                                == _computeTokenDelegationHash(vault, delegationInfo_.delegate, contract_, tokenId)
                        ) {
                            delegates[delegatesCount++] = delegationInfo_.delegate;
                        }
                    }
                }
            }
            unchecked {
                ++i;
            }
        }
        if (potentialDelegatesLength > delegatesCount) {
            assembly {
                let decrease := sub(potentialDelegatesLength, delegatesCount)
                mstore(delegates, sub(mload(delegates), decrease))
            }
        }
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function getContractLevelDelegations(address vault)
        external
        view
        returns (IDelegationRegistry.ContractDelegation[] memory contractDelegations)
    {
        EnumerableSet.Bytes32Set storage delegationHashes_ = delegations[vault][vaultVersion[vault]];
        uint256 potentialLength = delegationHashes_.length();
        uint256 delegationCount = 0;
        contractDelegations = new IDelegationRegistry.ContractDelegation[](potentialLength);
        for (uint256 i = 0; i < potentialLength;) {
            bytes32 delegationHash = delegationHashes_.at(i);
            DelegationInfo storage delegationInfo_ = delegationInfo[delegationHash];
            if (delegationInfo_.type_ == IDelegationRegistry.DelegationType.CONTRACT) {
                // check delegate version by validating the hash
                if (
                    delegationHash
                        == _computeContractDelegationHash(vault, delegationInfo_.delegate, delegationInfo_.contract_)
                ) {
                    contractDelegations[delegationCount++] = IDelegationRegistry.ContractDelegation({
                        contract_: delegationInfo_.contract_,
                        delegate: delegationInfo_.delegate
                    });
                }
            }
            unchecked {
                ++i;
            }
        }
        if (potentialLength > delegationCount) {
            assembly {
                let decrease := sub(potentialLength, delegationCount)
                mstore(contractDelegations, sub(mload(contractDelegations), decrease))
            }
        }
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function getTokenLevelDelegations(address vault)
        external
        view
        returns (IDelegationRegistry.TokenDelegation[] memory tokenDelegations)
    {
        EnumerableSet.Bytes32Set storage delegationHashes_ = delegations[vault][vaultVersion[vault]];
        uint256 potentialLength = delegationHashes_.length();
        uint256 delegationCount = 0;
        tokenDelegations = new IDelegationRegistry.TokenDelegation[](potentialLength);
        for (uint256 i = 0; i < potentialLength;) {
            bytes32 delegationHash = delegationHashes_.at(i);
            DelegationInfo storage delegationInfo_ = delegationInfo[delegationHash];
            if (delegationInfo_.type_ == IDelegationRegistry.DelegationType.TOKEN) {
                // check delegate version by validating the hash
                if (
                    delegationHash
                        == _computeTokenDelegationHash(
                            vault, delegationInfo_.delegate, delegationInfo_.contract_, delegationInfo_.tokenId
                        )
                ) {
                    tokenDelegations[delegationCount++] = IDelegationRegistry.TokenDelegation({
                        contract_: delegationInfo_.contract_,
                        tokenId: delegationInfo_.tokenId,
                        delegate: delegationInfo_.delegate
                    });
                }
            }
            unchecked {
                ++i;
            }
        }
        if (potentialLength > delegationCount) {
            assembly {
                let decrease := sub(potentialLength, delegationCount)
                mstore(tokenDelegations, sub(mload(tokenDelegations), decrease))
            }
        }
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function checkDelegateForAll(address delegate, address vault) public view override returns (bool) {
        bytes32 delegateHash =
            keccak256(abi.encode(delegate, vault, vaultVersion[vault], delegateVersion[vault][delegate]));
        return delegations[vault][vaultVersion[vault]].contains(delegateHash);
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function checkDelegateForContract(address delegate, address vault, address contract_)
        public
        view
        override
        returns (bool)
    {
        bytes32 delegateHash =
            keccak256(abi.encode(delegate, vault, contract_, vaultVersion[vault], delegateVersion[vault][delegate]));
        return delegations[vault][vaultVersion[vault]].contains(delegateHash)
            ? true
            : checkDelegateForAll(delegate, vault);
    }

    /**
     * @inheritdoc IDelegationRegistry
     */
    function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId)
        public
        view
        override
        returns (bool)
    {
        bytes32 delegateHash = keccak256(
            abi.encode(delegate, vault, contract_, tokenId, vaultVersion[vault], delegateVersion[vault][delegate])
        );
        return delegations[vault][vaultVersion[vault]].contains(delegateHash)
            ? true
            : checkDelegateForContract(delegate, vault, contract_);
    }
}

File 2 of 5 : IDelegationRegistry.sol
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.17;

/**
 * @title An immutable registry contract to be deployed as a standalone primitive
 * @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations
 * from here and integrate those permissions into their flow
 */
interface IDelegationRegistry {
    /// @notice Delegation type
    enum DelegationType {
        NONE,
        ALL,
        CONTRACT,
        TOKEN
    }

    /// @notice Info about a single delegation, used for onchain enumeration
    struct DelegationInfo {
        DelegationType type_;
        address vault;
        address delegate;
        address contract_;
        uint256 tokenId;
    }

    /// @notice Info about a single contract-level delegation
    struct ContractDelegation {
        address contract_;
        address delegate;
    }

    /// @notice Info about a single token-level delegation
    struct TokenDelegation {
        address contract_;
        uint256 tokenId;
        address delegate;
    }

    /// @notice Emitted when a user delegates their entire wallet
    event DelegateForAll(address vault, address delegate, bool value);

    /// @notice Emitted when a user delegates a specific contract
    event DelegateForContract(address vault, address delegate, address contract_, bool value);

    /// @notice Emitted when a user delegates a specific token
    event DelegateForToken(address vault, address delegate, address contract_, uint256 tokenId, bool value);

    /// @notice Emitted when a user revokes all delegations
    event RevokeAllDelegates(address vault);

    /// @notice Emitted when a user revoes all delegations for a given delegate
    event RevokeDelegate(address vault, address delegate);

    /**
     * -----------  WRITE -----------
     */

    /**
     * @notice Allow the delegate to act on your behalf for all contracts
     * @param delegate The hotwallet to act on your behalf
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForAll(address delegate, bool value) external;

    /**
     * @notice Allow the delegate to act on your behalf for a specific contract
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForContract(address delegate, address contract_, bool value) external;

    /**
     * @notice Allow the delegate to act on your behalf for a specific token
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param tokenId The token id for the token you're delegating
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external;

    /**
     * @notice Revoke all delegates
     */
    function revokeAllDelegates() external;

    /**
     * @notice Revoke a specific delegate for all their permissions
     * @param delegate The hotwallet to revoke
     */
    function revokeDelegate(address delegate) external;

    /**
     * @notice Remove yourself as a delegate for a specific vault
     * @param vault The vault which delegated to the msg.sender, and should be removed
     */
    function revokeSelf(address vault) external;

    /**
     * -----------  READ -----------
     */

    /**
     * @notice Returns all active delegations a given delegate is able to claim on behalf of
     * @param delegate The delegate that you would like to retrieve delegations for
     * @return info Array of DelegationInfo structs
     */
    function getDelegationsByDelegate(address delegate) external view returns (DelegationInfo[] memory);

    /**
     * @notice Returns an array of wallet-level delegates for a given vault
     * @param vault The cold wallet who issued the delegation
     * @return addresses Array of wallet-level delegates for a given vault
     */
    function getDelegatesForAll(address vault) external view returns (address[] memory);

    /**
     * @notice Returns an array of contract-level delegates for a given vault and contract
     * @param vault The cold wallet who issued the delegation
     * @param contract_ The address for the contract you're delegating
     * @return addresses Array of contract-level delegates for a given vault and contract
     */
    function getDelegatesForContract(address vault, address contract_) external view returns (address[] memory);

    /**
     * @notice Returns an array of contract-level delegates for a given vault's token
     * @param vault The cold wallet who issued the delegation
     * @param contract_ The address for the contract holding the token
     * @param tokenId The token id for the token you're delegating
     * @return addresses Array of contract-level delegates for a given vault's token
     */
    function getDelegatesForToken(address vault, address contract_, uint256 tokenId)
        external
        view
        returns (address[] memory);

    /**
     * @notice Returns all contract-level delegations for a given vault
     * @param vault The cold wallet who issued the delegations
     * @return delegations Array of ContractDelegation structs
     */
    function getContractLevelDelegations(address vault)
        external
        view
        returns (ContractDelegation[] memory delegations);

    /**
     * @notice Returns all token-level delegations for a given vault
     * @param vault The cold wallet who issued the delegations
     * @return delegations Array of TokenDelegation structs
     */
    function getTokenLevelDelegations(address vault) external view returns (TokenDelegation[] memory delegations);

    /**
     * @notice Returns true if the address is delegated to act on the entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForAll(address delegate, address vault) external view returns (bool);

    /**
     * @notice Returns true if the address is delegated to act on your behalf for a token contract or an entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForContract(address delegate, address vault, address contract_)
        external
        view
        returns (bool);

    /**
     * @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
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you're delegating
     * @param tokenId The token id for the token you're delegating
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId)
        external
        view
        returns (bool);
}

File 3 of 5 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 *  Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.
 *  See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 *  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.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastValue;
                // Update the index for the moved value
                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        return _values(set._inner);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

File 4 of 5 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 5 of 5 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

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": {}
}

Contract Security Audit

Contract ABI

[{"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

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101005760003560e01c8063685ee3e811610097578063aba69cf811610066578063aba69cf81461021c578063ed4b878e1461022f578063f956cf9414610242578063fa352c001461026257600080fd5b8063685ee3e8146101c35780636f007d87146101d657806390c9a2d0146101f65780639c395bc21461020957600080fd5b806336137872116100d3578063361378721461017557806349c95d291461017d5780634fc6928214610190578063537a5c3d146101b057600080fd5b806301ffc9a7146101055780631221156b1461012d5780631b61f6751461014d578063219044b014610160575b600080fd5b61011861011336600461138f565b610275565b60405190151581526020015b60405180910390f35b61014061013b3660046113d5565b6102ac565b6040516101249190611411565b61014061015b36600461145e565b6102c3565b61017361016e36600461145e565b6102d3565b005b6101736102e0565b61017361018b366004611489565b610336565b6101a361019e36600461145e565b6103ad565b60405161012491906114e2565b6101736101be36600461157f565b6105e8565b6101736101d13660046115cc565b610667565b6101e96101e436600461145e565b6106d4565b60405161012491906115ff565b610118610204366004611665565b61084d565b61011861021736600461169f565b6108f8565b61011861022a3660046116c9565b61097e565b61014061023d36600461169f565b610a33565b61025561025036600461145e565b610a4a565b6040516101249190611714565b61017361027036600461145e565b610baa565b60006001600160e01b03198216630596d3d560e01b14806102a657506301ffc9a760e01b6001600160e01b03198316145b92915050565b60606102bb8460038585610bb4565b949350505050565b60606102a6826001600080610bb4565b6102dd3382610e2e565b50565b33600090815260016020526040812080549091906102fd90611779565b909155506040513381527f32d74befd0b842e19694e3e3af46263e18bcce41352c8b600ff0002b49edf6629060200160405180910390a1565b6000610343338585610eac565b9050610356848284600233886000610f1e565b604080513381526001600160a01b038681166020830152851681830152831515606082015290517f8d6b2f5255b8d815cc368855b2251146e003bf4e2fcccaec66145fff5c174b4f9181900360800190a150505050565b6001600160a01b03811660009081526003602052604081206060916103d182611100565b905060008167ffffffffffffffff8111156103ee576103ee611792565b60405190808252806020026020018201604052801561044757816020015b6040805160a08101825260008082526020808301829052928201819052606082018190526080820152825260001990920191018161040c5790505b50935060005b828110156105cd576000610461858361110a565b600081815260046020526040808220815160a0810190925280549394509192909190829060ff166003811115610499576104996114cc565b60038111156104aa576104aa6114cc565b815281546001600160a01b03610100909104811660208084019190915260018085015483166040850152600285015490921660608401526003909301546080909201919091529082015182519293509190600090826003811115610510576105106114cc565b0361052e5761051f838c611116565b8503610529575060015b61058d565b6002826003811115610542576105426114cc565b036105565761051f838c8660600151610eac565b600382600381111561056a5761056a6114cc565b0361058d57610583838c86606001518760800151611184565b850361058d575060015b80156105bd57838a8861059f81611779565b9950815181106105b1576105b16117a8565b60200260200101819052505b856001019550505050505061044d565b50808211156105e0578351818303900384525b505050919050565b60006105f633868686611184565b90506106088582846003338989610f1e565b604080513381526001600160a01b03878116602083015286168183015260608101859052831515608082015290517fe89c6ba1e8957285aed22618f52aa1dcb9d5bb64e1533d8b55136c72fcf5aa5d9181900360a00190a15050505050565b60006106733384611116565b9050610686838284600133600080610f1e565b604080513381526001600160a01b03851660208201528315158183015290517f58781eab4a0743ab1c285a238be846a235f06cdb5b968030573a635e5f8c92fa9181900360600190a1505050565b6001600160a01b03811660009081526020818152604080832060018352818420548452909152812060609161070882611100565b905060008167ffffffffffffffff81111561072557610725611792565b60405190808252806020026020018201604052801561077057816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816107435790505b50935060005b828110156105cd57600061078a858361110a565b60008181526004602052604090209091506003815460ff1660038111156107b3576107b36114cc565b03610843576001810154600282015460038301546107e1928b926001600160a01b0391821692911690611184565b8203610843576040805160608101825260028301546001600160a01b0390811682526003840154602083015260018401541691810191909152878561082581611779565b965081518110610837576108376117a8565b60200260200101819052505b5050600101610776565b6001600160a01b03828116600081815260016020908152604080832054600283528184208987168086529084528285205483518086019290925281840187905296881660608201526080810182905260a0808201979097528251808203909701875260c00182528551958301959095209383528282528083209483529390529182206108d990826111f3565b6108ec576108e785856108f8565b6108ef565b60015b95945050505050565b6001600160a01b038181166000818152600160209081526040808320546002835281842095881680855295835281842054825180850197909752868301869052606087018290526080808801919091528251808803909101815260a090960182528551958301959095209383528282528083209483529390529182206102bb90826111f3565b6001600160a01b03808416600090815260016020908152604080832054600283528184209489168452938252808320549051929384936109c9938a938a938a938a93919291016117be565b60408051601f1981840301815291815281516020928301206001600160a01b0388166000908152808452828120600185528382205482529093529120909150610a1290826111f3565b610a2657610a2186868661084d565b610a29565b60015b9695505050505050565b6060610a43836002846000610bb4565b9392505050565b6001600160a01b038116600090815260208181526040808320600183528184205484529091528120606091610a7e82611100565b905060008167ffffffffffffffff811115610a9b57610a9b611792565b604051908082528060200260200182016040528015610ae057816020015b6040805180820190915260008082526020820152815260200190600190039081610ab95790505b50935060005b828110156105cd576000610afa858361110a565b60008181526004602052604090209091506002815460ff166003811115610b2357610b236114cc565b03610ba05760018101546002820154610b4a918a916001600160a01b039182169116610eac565b8203610ba0576040805180820190915260028201546001600160a01b03908116825260018301541660208201528785610b8281611779565b965081518110610b9457610b946117a8565b60200260200101819052505b5050600101610ae6565b6102dd8133610e2e565b6001600160a01b038416600090815260208181526040808320600183528184205484529091528120606091610be882611100565b905060008167ffffffffffffffff811115610c0557610c05611792565b604051908082528060200260200182016040528015610c2e578160200160208202803683370190505b50935060005b82811015610e10576000610c48858361110a565b6000818152600460205260409020909150896003811115610c6b57610c6b6114cc565b815460ff166003811115610c8157610c816114cc565b03610e065760018a6003811115610c9a57610c9a6114cc565b03610d0f576001810154610cb8908c906001600160a01b0316611116565b8203610d0a5760018101546001600160a01b03168785610cd781611779565b965081518110610ce957610ce96117a8565b60200260200101906001600160a01b031690816001600160a01b0316815250505b610e06565b60028a6003811115610d2357610d236114cc565b03610d595760028101546001600160a01b03808b16911603610d0a576001810154610cb8908c906001600160a01b03168b610eac565b60038a6003811115610d6d57610d6d6114cc565b03610e065760028101546001600160a01b038a81169116148015610d945750878160030154145b15610e06576001810154610db4908c906001600160a01b03168b8b611184565b8203610e065760018101546001600160a01b03168785610dd381611779565b965081518110610de557610de56117a8565b60200260200101906001600160a01b031690816001600160a01b0316815250505b5050600101610c34565b5080821115610e23578351818303900384525b505050949350505050565b6001600160a01b03808216600090815260026020908152604080832093861683529290529081208054909190610e6390611779565b90915550604080516001600160a01b03831681523360208201527f3e34a3ee53064fb79c0ee57448f03774a627a9270b0c41286efb7d8e32dcde93910160405180910390a15050565b6001600160a01b0392831660008181526001602090815260408083205460028352818420968816808552968352928190205481518084019790975286820194909452939095166060850152608084015260a0808401919091528151808403909101815260c09092019052805191012090565b8415611060576001600160a01b038316600090815260208181526040808320600183528184205484529091529020610f56908761120b565b506001600160a01b0387166000908152600360205260409020610f79908761120b565b506040518060a00160405280856003811115610f9757610f976114cc565b81526001600160a01b038086166020808401919091528a82166040808501919091529186166060840152608090920184905260008981526004909252902081518154829060ff19166001836003811115610ff357610ff36114cc565b0217905550602082015181546001600160a01b0391821661010002610100600160a81b031990911617825560408301516001830180549183166001600160a01b031992831617905560608401516002840180549190931691161790556080909101516003909101556110f7565b6001600160a01b0383166000908152602081815260408083206001835281842054845290915290206110929087611217565b506001600160a01b03871660009081526003602052604090206110b59087611217565b50600086815260046020526040812080546001600160a81b03191681556001810180546001600160a01b03199081169091556002820180549091169055600301555b50505050505050565b60006102a6825490565b6000610a438383611223565b6001600160a01b03918216600081815260016020908152604080832054600283528184209590961680845294825291829020548251808301959095528483019390935260608401949094526080808401929092528051808403909201825260a0909201909152805191012090565b6001600160a01b0380851660009081526001602090815260408083205460028352818420948816845293825280832054905192939290916111d19188918a918991899188918891016117be565b6040516020818303038152906040528051906020012092505050949350505050565b60008181526001830160205260408120541515610a43565b6000610a43838361124d565b6000610a43838361129c565b600082600001828154811061123a5761123a6117a8565b9060005260206000200154905092915050565b6000818152600183016020526040812054611294575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102a6565b5060006102a6565b600081815260018301602052604081205480156113855760006112c06001836117f7565b85549091506000906112d4906001906117f7565b90508181146113395760008660000182815481106112f4576112f46117a8565b9060005260206000200154905080876000018481548110611317576113176117a8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061134a5761134a61180a565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102a6565b60009150506102a6565b6000602082840312156113a157600080fd5b81356001600160e01b031981168114610a4357600080fd5b80356001600160a01b03811681146113d057600080fd5b919050565b6000806000606084860312156113ea57600080fd5b6113f3846113b9565b9250611401602085016113b9565b9150604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b818110156114525783516001600160a01b03168352928401929184019160010161142d565b50909695505050505050565b60006020828403121561147057600080fd5b610a43826113b9565b803580151581146113d057600080fd5b60008060006060848603121561149e57600080fd5b6114a7846113b9565b92506114b5602085016113b9565b91506114c360408501611479565b90509250925092565b634e487b7160e01b600052602160045260246000fd5b60208082528251828201819052600091906040908185019086840185805b838110156115715782518051600480821061152857634e487b7160e01b855260218152602485fd5b508652808801516001600160a01b039081168988015287820151811688880152606080830151909116908701526080908101519086015260a09094019391860191600101611500565b509298975050505050505050565b6000806000806080858703121561159557600080fd5b61159e856113b9565b93506115ac602086016113b9565b9250604085013591506115c160608601611479565b905092959194509250565b600080604083850312156115df57600080fd5b6115e8836113b9565b91506115f660208401611479565b90509250929050565b602080825282518282018190526000919060409081850190868401855b8281101561165857815180516001600160a01b03908116865287820151888701529086015116858501526060909301929085019060010161161c565b5091979650505050505050565b60008060006060848603121561167a57600080fd5b611683846113b9565b9250611691602085016113b9565b91506114c3604085016113b9565b600080604083850312156116b257600080fd5b6116bb836113b9565b91506115f6602084016113b9565b600080600080608085870312156116df57600080fd5b6116e8856113b9565b93506116f6602086016113b9565b9250611704604086016113b9565b9396929550929360600135925050565b602080825282518282018190526000919060409081850190868401855b8281101561165857815180516001600160a01b0390811686529087015116868501529284019290850190600101611731565b634e487b7160e01b600052601160045260246000fd5b60006001820161178b5761178b611763565b5060010190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03968716815294861660208601529290941660408401526060830152608082019290925260a081019190915260c00190565b818103818111156102a6576102a6611763565b634e487b7160e01b600052603160045260246000fdfea26469706673582212206b0b0a636b8da72fa85cb1817045c30ca104b227b960f8aae85f0c81f76bd66764736f6c63430008110033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.