ETH Price: $3,800.15 (+0.88%)
Gas: 6 Gwei

Contract

0x00000000000076A84feF008CDAbe6409d2FE638B
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Transaction Hash
Method
Block
From
To
Value
Delegate For All199294502024-05-23 1:58:1125 hrs ago1716429491IN
delegate.xyz v1
0 ETH0.001868899.60331201
Delegate For All199261852024-05-22 15:02:3536 hrs ago1716390155IN
delegate.xyz v1
0 ETH0.0038822718.33779405
Delegate For All199253862024-05-22 12:21:3539 hrs ago1716380495IN
delegate.xyz v1
0 ETH0.0007453710.9268397
Delegate For All199253692024-05-22 12:17:5939 hrs ago1716380279IN
delegate.xyz v1
0 ETH0.000574828.42670211
Delegate For All199253512024-05-22 12:14:2339 hrs ago1716380063IN
delegate.xyz v1
0 ETH0.000570079.52920148
Delegate For Tok...199215172024-05-21 23:18:472 days ago1716333527IN
delegate.xyz v1
0 ETH0.000436726.67331138
Delegate For All199177812024-05-21 10:47:352 days ago1716288455IN
delegate.xyz v1
0 ETH0.000554888.1343308
Delegate For All199100292024-05-20 8:44:593 days ago1716194699IN
delegate.xyz v1
0 ETH0.000177352.96458983
Delegate For All199086942024-05-20 4:16:113 days ago1716178571IN
delegate.xyz v1
0 ETH0.000174822.92226821
Delegate For All199052322024-05-19 16:39:594 days ago1716136799IN
delegate.xyz v1
0 ETH0.000993444.69251684
Delegate For All199007832024-05-19 1:43:595 days ago1716083039IN
delegate.xyz v1
0 ETH0.000970684.58501422
Delegate For All198991562024-05-18 20:17:115 days ago1716063431IN
delegate.xyz v1
0 ETH0.00063543.26504171
Delegate For Tok...198986422024-05-18 18:32:595 days ago1716057179IN
delegate.xyz v1
0 ETH0.000783983.09970408
Delegate For All198952352024-05-18 7:06:235 days ago1716015983IN
delegate.xyz v1
0 ETH0.000622953.50944807
Delegate For Tok...198910722024-05-17 17:06:236 days ago1715965583IN
delegate.xyz v1
0 ETH0.001975117.80883307
Delegate For All198891642024-05-17 10:42:236 days ago1715942543IN
delegate.xyz v1
0 ETH0.001689147.97907865
Delegate For All198854872024-05-16 22:21:477 days ago1715898107IN
delegate.xyz v1
0 ETH0.000693063.5613432
Delegate For All198854242024-05-16 22:09:117 days ago1715897351IN
delegate.xyz v1
0 ETH0.000915724.32540912
Delegate For All198853832024-05-16 22:00:597 days ago1715896859IN
delegate.xyz v1
0 ETH0.000691223.26498226
Delegate For All198840282024-05-16 17:28:237 days ago1715880503IN
delegate.xyz v1
0 ETH0.001727488.15970674
Delegate For All198836822024-05-16 16:18:117 days ago1715876291IN
delegate.xyz v1
0 ETH0.001302846.15395321
Delegate For All198835982024-05-16 16:01:237 days ago1715875283IN
delegate.xyz v1
0 ETH0.001468566.93672868
Delegate For All198820502024-05-16 10:50:117 days ago1715856611IN
delegate.xyz v1
0 ETH0.000341145.70251868
Delegate For All198798262024-05-16 3:22:118 days ago1715829731IN
delegate.xyz v1
0 ETH0.001153435.44820972
Delegate For All198768622024-05-15 17:25:478 days ago1715793947IN
delegate.xyz v1
0 ETH0.000450387.52842062
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To Value
155966232022-09-23 14:24:23608 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 3 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 4 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 5 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 6 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.