MATIC Price: $0.356391 (-20.98%)
 

Overview

MATIC Balance

Polygon PoS Chain LogoPolygon PoS Chain LogoPolygon PoS Chain Logo0 MATIC

MATIC Value

$0.00

Token Holdings

Sponsored

Transaction Hash
Method
Block
From
To
Claim Tokens602215292024-08-05 11:54:1653 secs ago1722858856IN
0x163F88bE...E51a03283
0 MATIC0.0054242288.32803289
Claim Tokens602215282024-08-05 11:54:1455 secs ago1722858854IN
0x163F88bE...E51a03283
0 MATIC0.0075526796.20014123
Claim Tokens602215202024-08-05 11:53:581 min ago1722858838IN
0x163F88bE...E51a03283
0 MATIC0.0050067581.51406951
Claim Tokens602215202024-08-05 11:53:581 min ago1722858838IN
0x163F88bE...E51a03283
0 MATIC0.0055884490.98446065
Claim Tokens602215202024-08-05 11:53:581 min ago1722858838IN
0x163F88bE...E51a03283
0 MATIC0.00663357108
Claim Tokens602215192024-08-05 11:53:541 min ago1722858834IN
0x163F88bE...E51a03283
0 MATIC0.0050669582.51030752
Claim Tokens602215172024-08-05 11:53:501 min ago1722858830IN
0x163F88bE...E51a03283
0 MATIC0.0064358781.96273941
Claim Tokens602215162024-08-05 11:53:481 min ago1722858828IN
0x163F88bE...E51a03283
0 MATIC0.0052687285.77909601
Claim Tokens602215152024-08-05 11:53:461 min ago1722858826IN
0x163F88bE...E51a03283
0 MATIC0.0053683487.40099214
Claim Tokens602215132024-08-05 11:53:421 min ago1722858822IN
0x163F88bE...E51a03283
0 MATIC0.0069310288.26861727
Claim Tokens602215052024-08-05 11:53:261 min ago1722858806IN
0x163F88bE...E51a03283
0 MATIC0.00626133101.93961998
Claim Tokens602215002024-08-05 11:53:141 min ago1722858794IN
0x163F88bE...E51a03283
0 MATIC0.0055752590.76964896
Claim Tokens602215002024-08-05 11:53:141 min ago1722858794IN
0x163F88bE...E51a03283
0 MATIC0.0058074194.54942485
Claim Tokens602214932024-08-05 11:53:002 mins ago1722858780IN
0x163F88bE...E51a03283
0 MATIC0.01307166212.81731782
Claim Tokens602214882024-08-05 11:52:502 mins ago1722858770IN
0x163F88bE...E51a03283
0 MATIC0.0053444587.01205798
Claim Tokens602214802024-08-05 11:52:322 mins ago1722858752IN
0x163F88bE...E51a03283
0 MATIC0.00525885.62132146
Claim Tokens602214792024-08-05 11:52:302 mins ago1722858750IN
0x163F88bE...E51a03283
0 MATIC0.0051838584.39736687
Claim Tokens602214772024-08-05 11:52:262 mins ago1722858746IN
0x163F88bE...E51a03283
0 MATIC0.0050435682.11334007
Claim Tokens602214772024-08-05 11:52:262 mins ago1722858746IN
0x163F88bE...E51a03283
0 MATIC0.00504882.20171583
Claim Tokens602214742024-08-05 11:52:202 mins ago1722858740IN
0x163F88bE...E51a03283
0 MATIC0.0050163881.67086729
Claim Tokens602214722024-08-05 11:52:162 mins ago1722858736IN
0x163F88bE...E51a03283
0 MATIC0.0050331481.94365059
Claim Tokens602214722024-08-05 11:52:162 mins ago1722858736IN
0x163F88bE...E51a03283
0 MATIC0.0059475596.83097364
Claim Tokens602214632024-08-05 11:51:563 mins ago1722858716IN
0x163F88bE...E51a03283
0 MATIC0.0068687987.48941859
Claim Tokens602214602024-08-05 11:51:503 mins ago1722858710IN
0x163F88bE...E51a03283
0 MATIC0.0056564992.09229435
Claim Tokens602214572024-08-05 11:51:443 mins ago1722858704IN
0x163F88bE...E51a03283
0 MATIC0.0054931789.43338499
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TokenClaim

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 99999 runs

Other Settings:
default evmVersion, MIT license
File 1 of 28 : TokenClaim.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {IORBNFT} from "./interface/IORBNFT.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {AccessControlStorage} from "@animoca/ethereum-contracts/contracts/access/libraries/AccessControlStorage.sol";
import {Pause, PauseStorage, ContractOwnership} from "@animoca/ethereum-contracts/contracts/lifecycle/Pause.sol";
import {ContractOwnershipStorage} from "@animoca/ethereum-contracts/contracts/access/libraries/ContractOwnershipStorage.sol";
import {TokenRecovery} from "@animoca/ethereum-contracts/contracts/security/TokenRecovery.sol";

/// @title TokenClaim Contract
/// @notice Allows users to claim tokens based on a signature verification process.
contract TokenClaim is Pause, TokenRecovery {
    using ECDSA for bytes32;
    using PauseStorage for PauseStorage.Layout;
    using ContractOwnershipStorage for ContractOwnershipStorage.Layout;

    // underscore is added to prevent naming conflict with contract.signer (from hardhat)
    address public messageSigner;
    IORBNFT public immutable ORB_INVENTORY;

    mapping(address => uint256) private _nonces;

    event TokensClaimed(address to, uint256[] orbIds, uint256[] orbCount, uint256[] xp, uint256 nonce);
    event MessageSignerUpdated(address oldMessageSigner, address newMessageSigner);

    /// @notice Contract constructor.
    /// @param inventory_ The address of the OrbInventory contract.
    /// @param messageSigner_ The initial signer address.
    constructor(address inventory_, address messageSigner_) Pause(false) ContractOwnership(msg.sender) {
        require(inventory_ != address(0), "TokenClaim: invalid inventory");
        require(messageSigner_ != address(0), "TokenClaim: invalid signer");

        ORB_INVENTORY = IORBNFT(inventory_);
        messageSigner = messageSigner_;

        emit MessageSignerUpdated(address(0), messageSigner_);
    }

    /// @notice Updates the signer address.
    /// @dev Only the contract owner can call this function.
    /// @param newMessageSigner The new signer address.
    function setMessageSigner(address newMessageSigner) external {
        ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender());
        require(newMessageSigner != address(0), "TokenClaim: invalid signer");

        emit MessageSignerUpdated(messageSigner, newMessageSigner);

        messageSigner = newMessageSigner;
    }

    /// @notice Gets the nonce for the specified user.
    /// @param user The user's address.
    /// @return The nonce value.
    function getNonce(address user) public view returns (uint256) {
        return _nonces[user];
    }

    /// @notice Recovers the signer address from the provided parameters and signature.
    /// @param to The recipient address.
    /// @param orbIds The array of Orb IDs.
    /// @param xp The array of experience values.
    /// @param nonce The nonce value.
    /// @param orbCount The array of Orb count values.
    /// @param signature The signature to recover the signer from.
    /// @return The recovered signer address.
    function _recoverSigner(
        address to,
        uint256[] calldata orbIds,
        uint256[] calldata xp,
        uint256 nonce,
        uint256[] calldata orbCount,
        bytes calldata signature
    ) internal view returns (address) {
        bytes32 hash_ = keccak256(abi.encodePacked(to, orbIds, xp, nonce, orbCount, block.chainid));
        return hash_.toEthSignedMessageHash().recover(signature);
    }

    /// @notice Claims tokens for the specified user.
    /// @dev ReentrancyGuard is used to prevent reentrancy attacks.
    /// @param to The recipient address.
    /// @param orbIds The array of Orb IDs.
    /// @param xp The array of experience values.
    /// @param orbCount The array of Orb count values.
    /// @param signature The signature for verification.
    function claimTokens(address to, uint256[] calldata orbIds, uint256[] calldata xp, uint256[] calldata orbCount, bytes calldata signature) public {
        PauseStorage.layout().enforceIsNotPaused();
        uint256 nonce = _nonces[to];

        require(_recoverSigner(to, orbIds, xp, nonce, orbCount, signature) == messageSigner, "TokenClaim: invalid signature");

        _nonces[to]++;

        ORB_INVENTORY.safeBatchMint(to, orbIds, orbCount, "");

        emit TokensClaimed(to, orbIds, orbCount, xp, nonce);
    }
}

File 2 of 28 : ContractOwnership.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {ContractOwnershipStorage} from "./libraries/ContractOwnershipStorage.sol";
import {ContractOwnershipBase} from "./base/ContractOwnershipBase.sol";
import {InterfaceDetection} from "./../introspection/InterfaceDetection.sol";

/// @title ERC173 Contract Ownership Standard (immutable version).
/// @dev See https://eips.ethereum.org/EIPS/eip-173
/// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation.
abstract contract ContractOwnership is ContractOwnershipBase, InterfaceDetection {
    using ContractOwnershipStorage for ContractOwnershipStorage.Layout;

    /// @notice Initializes the storage with an initial contract owner.
    /// @notice Marks the following ERC165 interface(s) as supported: ERC173.
    /// @dev Emits an {OwnershipTransferred} if `initialOwner` is not the zero address.
    /// @param initialOwner the initial contract owner.
    constructor(address initialOwner) {
        ContractOwnershipStorage.layout().constructorInit(initialOwner);
    }
}

File 3 of 28 : ContractOwnershipBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {IERC173} from "./../interfaces/IERC173.sol";
import {ContractOwnershipStorage} from "./../libraries/ContractOwnershipStorage.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";

/// @title ERC173 Contract Ownership Standard (proxiable version).
/// @dev See https://eips.ethereum.org/EIPS/eip-173
/// @dev This contract is to be used via inheritance in a proxied implementation.
/// @dev Note: This contract requires ERC165 (Interface Detection Standard).
abstract contract ContractOwnershipBase is Context, IERC173 {
    using ContractOwnershipStorage for ContractOwnershipStorage.Layout;

    /// @inheritdoc IERC173
    function owner() public view virtual override returns (address) {
        return ContractOwnershipStorage.layout().owner();
    }

    /// @inheritdoc IERC173
    function transferOwnership(address newOwner) public virtual override {
        ContractOwnershipStorage.layout().transferOwnership(_msgSender(), newOwner);
    }
}

File 4 of 28 : IERC173.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

/// @title ERC-173 Contract Ownership Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-173
/// @dev Note: the ERC-165 identifier for this interface is 0x7f5828d0
interface IERC173 {
    /// @notice Emitted when the contract ownership changes.
    /// @param previousOwner the previous contract owner.
    /// @param newOwner the new contract owner.
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /// @notice Sets the address of the new contract owner.
    /// @dev Reverts if the sender is not the contract owner.
    /// @dev Emits an {OwnershipTransferred} event if `newOwner` is different from the current contract owner.
    /// @param newOwner The address of the new contract owner. Using the zero address means renouncing ownership.
    function transferOwnership(address newOwner) external;

    /// @notice Gets the address of the contract owner.
    /// @return contractOwner The address of the contract owner.
    function owner() external view returns (address contractOwner);
}

File 5 of 28 : AccessControlStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {Bytes32} from "./../../utils/libraries/Bytes32.sol";

library AccessControlStorage {
    using Bytes32 for bytes32;
    using AccessControlStorage for AccessControlStorage.Layout;

    struct Layout {
        mapping(bytes32 => mapping(address => bool)) roles;
    }

    bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.core.access.AccessControl.storage")) - 1);

    event RoleGranted(bytes32 role, address account, address operator);
    event RoleRevoked(bytes32 role, address account, address operator);

    /// @notice Grants a role to an account.
    /// @dev Note: Call to this function should be properly access controlled.
    /// @dev Emits a {RoleGranted} event if the account did not previously have the role.
    /// @param role The role to grant.
    /// @param account The account to grant the role to.
    /// @param operator The account requesting the role change.
    function grantRole(Layout storage s, bytes32 role, address account, address operator) internal {
        if (!s.hasRole(role, account)) {
            s.roles[role][account] = true;
            emit RoleGranted(role, account, operator);
        }
    }

    /// @notice Revokes a role from an account.
    /// @dev Note: Call to this function should be properly access controlled.
    /// @dev Emits a {RoleRevoked} event if the account previously had the role.
    /// @param role The role to revoke.
    /// @param account The account to revoke the role from.
    /// @param operator The account requesting the role change.
    function revokeRole(Layout storage s, bytes32 role, address account, address operator) internal {
        if (s.hasRole(role, account)) {
            s.roles[role][account] = false;
            emit RoleRevoked(role, account, operator);
        }
    }

    /// @notice Renounces a role by the sender.
    /// @dev Reverts if `sender` does not have `role`.
    /// @dev Emits a {RoleRevoked} event.
    /// @param sender The message sender.
    /// @param role The role to renounce.
    function renounceRole(Layout storage s, address sender, bytes32 role) internal {
        s.enforceHasRole(role, sender);
        s.roles[role][sender] = false;
        emit RoleRevoked(role, sender, sender);
    }

    /// @notice Retrieves whether an account has a role.
    /// @param role The role.
    /// @param account The account.
    /// @return whether `account` has `role`.
    function hasRole(Layout storage s, bytes32 role, address account) internal view returns (bool) {
        return s.roles[role][account];
    }

    /// @notice Ensures that an account has a role.
    /// @dev Reverts if `account` does not have `role`.
    /// @param role The role.
    /// @param account The account.
    function enforceHasRole(Layout storage s, bytes32 role, address account) internal view {
        if (!s.hasRole(role, account)) {
            revert(string(abi.encodePacked("AccessControl: missing '", role.toASCIIString(), "' role")));
        }
    }

    function layout() internal pure returns (Layout storage s) {
        bytes32 position = LAYOUT_STORAGE_SLOT;
        assembly {
            s.slot := position
        }
    }
}

File 6 of 28 : ContractOwnershipStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {IERC173} from "./../interfaces/IERC173.sol";
import {ProxyInitialization} from "./../../proxy/libraries/ProxyInitialization.sol";
import {InterfaceDetectionStorage} from "./../../introspection/libraries/InterfaceDetectionStorage.sol";

library ContractOwnershipStorage {
    using ContractOwnershipStorage for ContractOwnershipStorage.Layout;
    using InterfaceDetectionStorage for InterfaceDetectionStorage.Layout;

    struct Layout {
        address contractOwner;
    }

    bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.core.access.ContractOwnership.storage")) - 1);
    bytes32 internal constant PROXY_INIT_PHASE_SLOT = bytes32(uint256(keccak256("animoca.core.access.ContractOwnership.phase")) - 1);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /// @notice Initializes the storage with an initial contract owner (immutable version).
    /// @notice Marks the following ERC165 interface(s) as supported: ERC173.
    /// @dev Note: This function should be called ONLY in the constructor of an immutable (non-proxied) contract.
    /// @dev Emits an {OwnershipTransferred} if `initialOwner` is not the zero address.
    /// @param initialOwner The initial contract owner.
    function constructorInit(Layout storage s, address initialOwner) internal {
        if (initialOwner != address(0)) {
            s.contractOwner = initialOwner;
            emit OwnershipTransferred(address(0), initialOwner);
        }
        InterfaceDetectionStorage.layout().setSupportedInterface(type(IERC173).interfaceId, true);
    }

    /// @notice Initializes the storage with an initial contract owner (proxied version).
    /// @notice Sets the proxy initialization phase to `1`.
    /// @notice Marks the following ERC165 interface(s) as supported: ERC173.
    /// @dev Note: This function should be called ONLY in the init function of a proxied contract.
    /// @dev Reverts if the proxy initialization phase is set to `1` or above.
    /// @dev Emits an {OwnershipTransferred} if `initialOwner` is not the zero address.
    /// @param initialOwner The initial contract owner.
    function proxyInit(Layout storage s, address initialOwner) internal {
        ProxyInitialization.setPhase(PROXY_INIT_PHASE_SLOT, 1);
        s.constructorInit(initialOwner);
    }

    /// @notice Sets the address of the new contract owner.
    /// @dev Reverts if `sender` is not the contract owner.
    /// @dev Emits an {OwnershipTransferred} event if `newOwner` is different from the current contract owner.
    /// @param newOwner The address of the new contract owner. Using the zero address means renouncing ownership.
    function transferOwnership(Layout storage s, address sender, address newOwner) internal {
        address previousOwner = s.contractOwner;
        require(sender == previousOwner, "Ownership: not the owner");
        if (previousOwner != newOwner) {
            s.contractOwner = newOwner;
            emit OwnershipTransferred(previousOwner, newOwner);
        }
    }

    /// @notice Gets the address of the contract owner.
    /// @return contractOwner The address of the contract owner.
    function owner(Layout storage s) internal view returns (address contractOwner) {
        return s.contractOwner;
    }

    /// @notice Ensures that an account is the contract owner.
    /// @dev Reverts if `account` is not the contract owner.
    /// @param account The account.
    function enforceIsContractOwner(Layout storage s, address account) internal view {
        require(account == s.contractOwner, "Ownership: not the owner");
    }

    function layout() internal pure returns (Layout storage s) {
        bytes32 position = LAYOUT_STORAGE_SLOT;
        assembly {
            s.slot := position
        }
    }
}

File 7 of 28 : InterfaceDetection.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {IERC165} from "./interfaces/IERC165.sol";
import {InterfaceDetectionStorage} from "./libraries/InterfaceDetectionStorage.sol";

/// @title ERC165 Interface Detection Standard (immutable or proxiable version).
/// @dev This contract is to be used via inheritance in an immutable (non-proxied) or proxied implementation.
abstract contract InterfaceDetection is IERC165 {
    using InterfaceDetectionStorage for InterfaceDetectionStorage.Layout;

    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) external view override returns (bool) {
        return InterfaceDetectionStorage.layout().supportsInterface(interfaceId);
    }
}

File 8 of 28 : IERC165.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

/// @title ERC165 Interface Detection Standard.
/// @dev See https://eips.ethereum.org/EIPS/eip-165.
/// @dev Note: The ERC-165 identifier for this interface is 0x01ffc9a7.
interface IERC165 {
    /// @notice Returns whether this contract implements a given interface.
    /// @dev Note: This function call must use less than 30 000 gas.
    /// @param interfaceId the interface identifier to test.
    /// @return supported True if the interface is supported, false if `interfaceId` is `0xffffffff` or if the interface is not supported.
    function supportsInterface(bytes4 interfaceId) external view returns (bool supported);
}

File 9 of 28 : InterfaceDetectionStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {IERC165} from "./../interfaces/IERC165.sol";

library InterfaceDetectionStorage {
    struct Layout {
        mapping(bytes4 => bool) supportedInterfaces;
    }

    bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.core.introspection.InterfaceDetection.storage")) - 1);

    bytes4 internal constant ILLEGAL_INTERFACE_ID = 0xffffffff;

    /// @notice Sets or unsets an ERC165 interface.
    /// @dev Reverts if `interfaceId` is `0xffffffff`.
    /// @param interfaceId the interface identifier.
    /// @param supported True to set the interface, false to unset it.
    function setSupportedInterface(Layout storage s, bytes4 interfaceId, bool supported) internal {
        require(interfaceId != ILLEGAL_INTERFACE_ID, "InterfaceDetection: wrong value");
        s.supportedInterfaces[interfaceId] = supported;
    }

    /// @notice Returns whether this contract implements a given interface.
    /// @dev Note: This function call must use less than 30 000 gas.
    /// @param interfaceId The interface identifier to test.
    /// @return supported True if the interface is supported, false if `interfaceId` is `0xffffffff` or if the interface is not supported.
    function supportsInterface(Layout storage s, bytes4 interfaceId) internal view returns (bool supported) {
        if (interfaceId == ILLEGAL_INTERFACE_ID) {
            return false;
        }
        if (interfaceId == type(IERC165).interfaceId) {
            return true;
        }
        return s.supportedInterfaces[interfaceId];
    }

    function layout() internal pure returns (Layout storage s) {
        bytes32 position = LAYOUT_STORAGE_SLOT;
        assembly {
            s.slot := position
        }
    }
}

File 10 of 28 : Pause.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {PauseStorage} from "./libraries/PauseStorage.sol";
import {PauseBase} from "./base/PauseBase.sol";
import {ContractOwnership} from "../access/ContractOwnership.sol";

/// @title Pausing mechanism (immutable version).
/// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation.
abstract contract Pause is PauseBase, ContractOwnership {
    using PauseStorage for PauseStorage.Layout;

    /// @notice Initializes the storage with an initial pause state.
    /// @dev Emits a {Paused} event if `isPaused` is true.
    /// @param isPaused The initial pause state.
    constructor(bool isPaused) {
        PauseStorage.layout().constructorInit(isPaused);
    }
}

File 11 of 28 : PauseBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {PauseStorage} from "./../libraries/PauseStorage.sol";
import {ContractOwnershipStorage} from "./../../access/libraries/ContractOwnershipStorage.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";

/// @title Pausing mechanism (proxiable version).
/// @dev This contract is to be used via inheritance in a proxied implementation.
/// @dev Note: This contract requires ERC173 (Contract Ownership standard).
abstract contract PauseBase is Context {
    using PauseStorage for PauseStorage.Layout;
    using ContractOwnershipStorage for ContractOwnershipStorage.Layout;

    /// @notice Emitted when the pause is triggered.
    event Paused();

    /// @notice Emitted when the pause is lifted.
    event Unpaused();

    /// @notice Pauses the contract.
    /// @dev Reverts if the sender is not the contract owner.
    /// @dev Reverts if the contract is paused.
    /// @dev Emits a {Paused} event.
    function pause() external {
        ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender());
        PauseStorage.layout().pause();
    }

    /// @notice Unpauses the contract.
    /// @dev Reverts if the sender is not the contract owner.
    /// @dev Reverts if the contract is not paused.
    /// @dev Emits an {Unpaused} event.
    function unpause() external {
        ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender());
        PauseStorage.layout().unpause();
    }

    /// @notice Gets the paused state of the contract.
    /// @return isPaused The paused state of the contract.
    function paused() external view returns (bool) {
        return PauseStorage.layout().paused();
    }
}

File 12 of 28 : PauseStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {ProxyInitialization} from "./../../proxy/libraries/ProxyInitialization.sol";

library PauseStorage {
    using PauseStorage for PauseStorage.Layout;

    struct Layout {
        bool isPaused;
    }

    bytes32 internal constant LAYOUT_STORAGE_SLOT = bytes32(uint256(keccak256("animoca.core.lifecycle.Pause.storage")) - 1);
    bytes32 internal constant PROXY_INIT_PHASE_SLOT = bytes32(uint256(keccak256("animoca.core.lifecycle.Pause.phase")) - 1);

    event Paused();
    event Unpaused();

    /// @notice Initializes the storage with an initial pause state (immutable version).
    /// @dev Note: This function should be called ONLY in the constructor of an immutable (non-proxied) contract.
    /// @dev Emits a {Paused} event if `isPaused` is true.
    /// @param isPaused The initial pause state.
    function constructorInit(Layout storage s, bool isPaused) internal {
        if (isPaused) {
            s.isPaused = true;
            emit Paused();
        }
    }

    /// @notice Initializes the storage with an initial pause state (proxied version).
    /// @notice Sets the proxy initialization phase to `1`.
    /// @dev Note: This function should be called ONLY in the init function of a proxied contract.
    /// @dev Reverts if the proxy initialization phase is set to `1` or above.
    /// @dev Emits a {Paused} event if `isPaused` is true.
    /// @param isPaused The initial pause state.
    function proxyInit(Layout storage s, bool isPaused) internal {
        ProxyInitialization.setPhase(PROXY_INIT_PHASE_SLOT, 1);
        s.constructorInit(isPaused);
    }

    /// @notice Pauses the contract.
    /// @dev Reverts if the contract is paused.
    /// @dev Emits a {Paused} event.
    function pause(Layout storage s) internal {
        s.enforceIsNotPaused();
        s.isPaused = true;
        emit Paused();
    }

    /// @notice Unpauses the contract.
    /// @dev Reverts if the contract is not paused.
    /// @dev Emits an {Unpaused} event.
    function unpause(Layout storage s) internal {
        s.enforceIsPaused();
        s.isPaused = false;
        emit Unpaused();
    }

    /// @notice Gets the paused state of the contract.
    /// @return isPaused The paused state of the contract.
    function paused(Layout storage s) internal view returns (bool isPaused) {
        return s.isPaused;
    }

    /// @notice Ensures that the contract is paused.
    /// @dev Reverts if the contract is not paused.
    function enforceIsPaused(Layout storage s) internal view {
        require(s.isPaused, "Pause: not paused");
    }

    /// @notice Ensures that the contract is not paused.
    /// @dev Reverts if the contract is paused.
    function enforceIsNotPaused(Layout storage s) internal view {
        require(!s.isPaused, "Pause: paused");
    }

    function layout() internal pure returns (Layout storage s) {
        bytes32 position = LAYOUT_STORAGE_SLOT;
        assembly {
            s.slot := position
        }
    }
}

File 13 of 28 : ProxyInitialization.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {StorageSlot} from "@openzeppelin/contracts/utils/StorageSlot.sol";

/// @notice Multiple calls protection for storage-modifying proxy initialization functions.
library ProxyInitialization {
    /// @notice Sets the initialization phase during a storage-modifying proxy initialization function.
    /// @dev Reverts if `phase` has been reached already.
    /// @param storageSlot the storage slot where `phase` is stored.
    /// @param phase the initialization phase.
    function setPhase(bytes32 storageSlot, uint256 phase) internal {
        StorageSlot.Uint256Slot storage currentVersion = StorageSlot.getUint256Slot(storageSlot);
        require(currentVersion.value < phase, "Storage: phase reached");
        currentVersion.value = phase;
    }
}

File 14 of 28 : TokenRecovery.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {TokenRecoveryBase} from "./base/TokenRecoveryBase.sol";
import {ContractOwnership} from "./../access/ContractOwnership.sol";

/// @title Recovery mechanism for ETH/ERC20/ERC721 tokens accidentally sent to this contract (immutable version).
/// @dev This contract is to be used via inheritance in an immutable (non-proxied) implementation.
abstract contract TokenRecovery is TokenRecoveryBase, ContractOwnership {

}

File 15 of 28 : TokenRecoveryBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
import {IERC721} from "./../../token/ERC721/interfaces/IERC721.sol";
import {ContractOwnershipStorage} from "./../../access/libraries/ContractOwnershipStorage.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";

/// @title Recovery mechanism for ETH/ERC20/ERC721 tokens accidentally sent to this contract (proxiable version).
/// @dev This contract is to be used via inheritance in a proxied implementation.
/// @dev Note: This contract requires ERC173 (Contract Ownership standard).
contract TokenRecoveryBase is Context {
    using ContractOwnershipStorage for ContractOwnershipStorage.Layout;
    using SafeERC20 for IERC20;
    using Address for address payable;

    /// @notice Extract ETH tokens which were accidentally sent to the contract to a list of accounts.
    /// @dev Note: While contracts can generally prevent accidental ETH transfer by implementating a reverting
    ///  `receive()` function, this can still be bypassed in a `selfdestruct(address)` scenario.
    /// @dev Warning: this function should be overriden for contracts which are supposed to hold ETH tokens
    ///  so that the extraction is limited to only amounts sent accidentally.
    /// @dev Reverts if the sender is not the contract owner.
    /// @dev Reverts if `accounts` and `amounts` do not have the same length.
    /// @dev Reverts if one of the ETH transfers fails for any reason.
    /// @param accounts the list of accounts to transfer the tokens to.
    /// @param amounts the list of token amounts to transfer.
    function recoverETH(address payable[] calldata accounts, uint256[] calldata amounts) external virtual {
        ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender());
        uint256 length = accounts.length;
        require(length == amounts.length, "Recovery: inconsistent arrays");
        unchecked {
            for (uint256 i; i != length; ++i) {
                accounts[i].sendValue(amounts[i]);
            }
        }
    }

    /// @notice Extract ERC20 tokens which were accidentally sent to the contract to a list of accounts.
    /// @dev Warning: this function should be overriden for contracts which are supposed to hold ERC20 tokens
    ///  so that the extraction is limited to only amounts sent accidentally.
    /// @dev Reverts if the sender is not the contract owner.
    /// @dev Reverts if `accounts`, `tokens` and `amounts` do not have the same length.
    /// @dev Reverts if one of the ERC20 transfers fails for any reason.
    /// @param accounts the list of accounts to transfer the tokens to.
    /// @param tokens the list of ERC20 token addresses.
    /// @param amounts the list of token amounts to transfer.
    function recoverERC20s(address[] calldata accounts, IERC20[] calldata tokens, uint256[] calldata amounts) external virtual {
        ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender());
        uint256 length = accounts.length;
        require(length == tokens.length && length == amounts.length, "Recovery: inconsistent arrays");
        unchecked {
            for (uint256 i; i != length; ++i) {
                tokens[i].safeTransfer(accounts[i], amounts[i]);
            }
        }
    }

    /// @notice Extract ERC721 tokens which were accidentally sent to the contract to a list of accounts.
    /// @dev Warning: this function should be overriden for contracts which are supposed to hold ERC721 tokens
    ///  so that the extraction is limited to only tokens sent accidentally.
    /// @dev Reverts if the sender is not the contract owner.
    /// @dev Reverts if `accounts`, `contracts` and `amounts` do not have the same length.
    /// @dev Reverts if one of the ERC721 transfers fails for any reason.
    /// @param accounts the list of accounts to transfer the tokens to.
    /// @param contracts the list of ERC721 contract addresses.
    /// @param tokenIds the list of token ids to transfer.
    function recoverERC721s(address[] calldata accounts, IERC721[] calldata contracts, uint256[] calldata tokenIds) external virtual {
        ContractOwnershipStorage.layout().enforceIsContractOwner(_msgSender());
        uint256 length = accounts.length;
        require(length == contracts.length && length == tokenIds.length, "Recovery: inconsistent arrays");
        unchecked {
            for (uint256 i; i != length; ++i) {
                contracts[i].transferFrom(address(this), accounts[i], tokenIds[i]);
            }
        }
    }
}

File 16 of 28 : IERC721.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

/// @title ERC721 Non-Fungible Token Standard, basic interface (functions).
/// @dev See https://eips.ethereum.org/EIPS/eip-721
/// @dev This interface only contains the standard functions. See IERC721Events for the events.
/// @dev Note: The ERC-165 identifier for this interface is 0x80ac58cd.
interface IERC721 {
    /// @notice Sets or unsets an approval to transfer a single token on behalf of its owner.
    /// @dev Note: There can only be one approved address per token at a given time.
    /// @dev Note: A token approval gets reset when this token is transferred, including a self-transfer.
    /// @dev Reverts if `tokenId` does not exist.
    /// @dev Reverts if `to` is the token owner.
    /// @dev Reverts if the sender is not the token owner and has not been approved by the token owner.
    /// @dev Emits an {Approval} event.
    /// @param to The address to approve, or the zero address to remove any existing approval.
    /// @param tokenId The token identifier to give approval for.
    function approve(address to, uint256 tokenId) external;

    /// @notice Sets or unsets an approval to transfer all tokens on behalf of their owner.
    /// @dev Reverts if the sender is the same as `operator`.
    /// @dev Emits an {ApprovalForAll} event.
    /// @param operator The address to approve for all tokens.
    /// @param approved True to set an approval for all tokens, false to unset it.
    function setApprovalForAll(address operator, bool approved) external;

    /// @notice Unsafely transfers the ownership of a token to a recipient.
    /// @dev Note: Usage of this method is discouraged, use `safeTransferFrom` whenever possible.
    /// @dev Resets the token approval for `tokenId`.
    /// @dev Reverts if `to` is the zero address.
    /// @dev Reverts if `from` is not the owner of `tokenId`.
    /// @dev Reverts if the sender is not `from` and has not been approved by `from` for `tokenId`.
    /// @dev Emits a {Transfer} event.
    /// @param from The current token owner.
    /// @param to The recipient of the token transfer. Self-transfers are possible.
    /// @param tokenId The identifier of the token to transfer.
    function transferFrom(address from, address to, uint256 tokenId) external;

    /// @notice Safely transfers the ownership of a token to a recipient.
    /// @dev Resets the token approval for `tokenId`.
    /// @dev Reverts if `to` is the zero address.
    /// @dev Reverts if `from` is not the owner of `tokenId`.
    /// @dev Reverts if the sender is not `from` and has not been approved by `from` for `tokenId`.
    /// @dev Reverts if `to` is a contract and the call to {IERC721Receiver-onERC721Received} fails, reverts or is rejected.
    /// @dev Emits a {Transfer} event.
    /// @param from The current token owner.
    /// @param to The recipient of the token transfer.
    /// @param tokenId The identifier of the token to transfer.
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /// @notice Safely transfers the ownership of a token to a recipient.
    /// @dev Resets the token approval for `tokenId`.
    /// @dev Reverts if `to` is the zero address.
    /// @dev Reverts if `from` is not the owner of `tokenId`.
    /// @dev Reverts if the sender is not `from` and has not been approved by `from` for `tokenId`.
    /// @dev Reverts if `to` is a contract and the call to {IERC721Receiver-onERC721Received} fails, reverts or is rejected.
    /// @dev Emits a {Transfer} event.
    /// @param from The current token owner.
    /// @param to The recipient of the token transfer.
    /// @param tokenId The identifier of the token to transfer.
    /// @param data Optional data to send along to a receiver contract.
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /// @notice Gets the balance of an address.
    /// @dev Reverts if `owner` is the zero address.
    /// @param owner The address to query the balance of.
    /// @return balance The amount owned by the owner.
    function balanceOf(address owner) external view returns (uint256 balance);

    /// @notice Gets the owner of a token.
    /// @dev Reverts if `tokenId` does not exist.
    /// @param tokenId The token identifier to query the owner of.
    /// @return tokenOwner The owner of the token identifier.
    function ownerOf(uint256 tokenId) external view returns (address tokenOwner);

    /// @notice Gets the approved address for a token.
    /// @dev Reverts if `tokenId` does not exist.
    /// @param tokenId The token identifier to query the approval of.
    /// @return approved The approved address for the token identifier, or the zero address if no approval is set.
    function getApproved(uint256 tokenId) external view returns (address approved);

    /// @notice Gets whether an operator is approved for all tokens by an owner.
    /// @param owner The address which gives the approval for all tokens.
    /// @param operator The address which receives the approval for all tokens.
    /// @return approvedForAll Whether the operator is approved for all tokens by the owner.
    function isApprovedForAll(address owner, address operator) external view returns (bool approvedForAll);
}

File 17 of 28 : Bytes32.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

library Bytes32 {
    /// @notice Converts bytes32 to base32 string.
    /// @param value value to convert.
    /// @return the converted base32 string.
    function toBase32String(bytes32 value) internal pure returns (string memory) {
        unchecked {
            bytes32 base32Alphabet = 0x6162636465666768696A6B6C6D6E6F707172737475767778797A323334353637;
            uint256 i = uint256(value);
            uint256 k = 52;
            bytes memory bstr = new bytes(k);
            bstr[--k] = base32Alphabet[uint8((i % 8) << 2)]; // uint8 s = uint8((256 - skip) % 5);  // (i % (2**s)) << (5-s)
            i /= 8;
            while (k > 0) {
                bstr[--k] = base32Alphabet[i % 32];
                i /= 32;
            }
            return string(bstr);
        }
    }

    /// @notice Converts a bytes32 value to an ASCII string, trimming the tailing zeros.
    /// @param value value to convert.
    /// @return the converted ASCII string.
    function toASCIIString(bytes32 value) internal pure returns (string memory) {
        unchecked {
            if (value == 0x00) return "";
            bytes memory bytesString = bytes(abi.encodePacked(value));
            uint256 pos = 31;
            while (true) {
                if (bytesString[pos] != 0) break;
                --pos;
            }
            bytes memory asciiString = new bytes(pos + 1);
            for (uint256 i; i <= pos; ++i) {
                asciiString[i] = bytesString[i];
            }
            return string(asciiString);
        }
    }
}

File 18 of 28 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)

pragma solidity ^0.8.0;

import "../token/ERC20/IERC20.sol";

File 19 of 28 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 20 of 28 : draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 21 of 28 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 22 of 28 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 23 of 28 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 24 of 28 : StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }
}

File 25 of 28 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

File 26 of 28 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 27 of 28 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

File 28 of 28 : IORBNFT.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface IORBNFT {
    function safeBatchMint(address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external;
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 99999
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"inventory_","type":"address"},{"internalType":"address","name":"messageSigner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldMessageSigner","type":"address"},{"indexed":false,"internalType":"address","name":"newMessageSigner","type":"address"}],"name":"MessageSignerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"orbIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"orbCount","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"xp","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"TokensClaimed","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"inputs":[],"name":"ORB_INVENTORY","outputs":[{"internalType":"contract IORBNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"orbIds","type":"uint256[]"},{"internalType":"uint256[]","name":"xp","type":"uint256[]"},{"internalType":"uint256[]","name":"orbCount","type":"uint256[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"claimTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messageSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"recoverERC20s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"contract IERC721[]","name":"contracts","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"recoverERC721s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"recoverETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMessageSigner","type":"address"}],"name":"setMessageSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b5060405162002442380380620024428339810160408190526200003491620003c1565b600033620000658162000051620001af60201b620009de1760201c565b620001e560201b62000a0c1790919060201c565b506200009481620000806200027860201b62000acd1760201c565b620002a860201b62000afb1790919060201c565b506001600160a01b038216620000f15760405162461bcd60e51b815260206004820152601d60248201527f546f6b656e436c61696d3a20696e76616c696420696e76656e746f727900000060448201526064015b60405180910390fd5b6001600160a01b038116620001495760405162461bcd60e51b815260206004820152601a60248201527f546f6b656e436c61696d3a20696e76616c6964207369676e65720000000000006044820152606401620000e8565b6001600160a01b03828116608052600080546001600160a01b03191691831691821781556040805191825260208201929092527fb0d0791e347bdc6678365d0f8c4232c168c40192108be24902c292267defafb5910160405180910390a150506200041b565b600080620001df60017fc9ed16f33ab3a66c84bfd83099ccb2a8845871e2e1c1928f63797152f0fd54cd620003f9565b92915050565b6001600160a01b038116156200023c5781546001600160a01b0319166001600160a01b03821690811783556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35b620002746307f5828d60e41b60016200025f620002e760201b62000b571760201c565b6200031760201b62000b85179092919060201c565b5050565b600080620001df60017f0186a05f63b1553398ad5ea3233c0ce68b8c9eecc47717f123c5c2b42fbd6d9f620003f9565b80156200027457815460ff191660011782556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a15050565b600080620001df60017fca9d3e17f264b0f3984e2634e94adb37fa3e6a8103f06aeae6fa59e21c769f5e620003f9565b600160e01b6001600160e01b0319831601620003765760405162461bcd60e51b815260206004820152601f60248201527f496e74657266616365446574656374696f6e3a2077726f6e672076616c7565006044820152606401620000e8565b6001600160e01b03199190911660009081526020929092526040909120805460ff1916911515919091179055565b80516001600160a01b0381168114620003bc57600080fd5b919050565b60008060408385031215620003d557600080fd5b620003e083620003a4565b9150620003f060208401620003a4565b90509250929050565b81810381811115620001df57634e487b7160e01b600052601160045260246000fd5b6080516120046200043e600039600081816101ed015261083201526120046000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638456cb591161008c578063c3666c3611610066578063c3666c361461020f578063f2fde38b14610222578063f62ded8114610235578063f7ba94bd1461024857600080fd5b80638456cb59146101d85780638da5cb5b146101e0578063b1386c89146101e857600080fd5b80633f4ba83a116100c85780633f4ba83a146101a05780634b36df53146101aa5780635c975abb146101bd57806373c8a958146101c557600080fd5b806301ffc9a7146100ef578063080387b4146101175780632d0335ab1461015c575b600080fd5b6101026100fd3660046119a7565b61025b565b60405190151581526020015b60405180910390f35b6000546101379073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010e565b61019261016a366004611a12565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205490565b60405190815260200161010e565b6101a8610275565b005b6101a86101b8366004611a12565b61029a565b6101026103c0565b6101a86101d3366004611a74565b6103d9565b6101a86104fa565b610137610513565b6101377f000000000000000000000000000000000000000000000000000000000000000081565b6101a861021d366004611a74565b61053a565b6101a8610230366004611a12565b6106dd565b6101a8610243366004611b0e565b6106f4565b6101a8610256366004611c11565b6108f2565b600061026f82610269610b57565b90610c91565b92915050565b610288335b6102826109de565b90610d6b565b610298610293610acd565b610dee565b565b6102a33361027a565b73ffffffffffffffffffffffffffffffffffffffff8116610325576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f546f6b656e436c61696d3a20696e76616c6964207369676e657200000000000060448201526064015b60405180910390fd5b6000546040805173ffffffffffffffffffffffffffffffffffffffff928316815291831660208301527fb0d0791e347bdc6678365d0f8c4232c168c40192108be24902c292267defafb5910160405180910390a1600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006103d46103cd610acd565b5460ff1690565b905090565b6103e23361027a565b8483811480156103f157508082145b610457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f5265636f766572793a20696e636f6e73697374656e7420617272617973000000604482015260640161031c565b60005b8181146104f0576104e888888381811061047657610476611c7d565b905060200201602081019061048b9190611a12565b85858481811061049d5761049d611c7d565b905060200201358888858181106104b6576104b6611c7d565b90506020020160208101906104cb9190611a12565b73ffffffffffffffffffffffffffffffffffffffff169190610e49565b60010161045a565b5050505050505050565b6105033361027a565b61029861050e610acd565b610edb565b60006103d46105206109de565b5473ffffffffffffffffffffffffffffffffffffffff1690565b6105433361027a565b84838114801561055257508082145b6105b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f5265636f766572793a20696e636f6e73697374656e7420617272617973000000604482015260640161031c565b60005b8181146104f0578585828181106105d4576105d4611c7d565b90506020020160208101906105e99190611a12565b73ffffffffffffffffffffffffffffffffffffffff166323b872dd308a8a8581811061061757610617611c7d565b905060200201602081019061062c9190611a12565b87878681811061063e5761063e611c7d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b16815273ffffffffffffffffffffffffffffffffffffffff958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b1580156106ba57600080fd5b505af11580156106ce573d6000803e3d6000fd5b505050508060010190506105bb565b6106f133826106ea6109de565b9190610f39565b50565b6107046106ff610acd565b611066565b73ffffffffffffffffffffffffffffffffffffffff808a1660009081526001602052604081205490549091166107428b8b8b8b8b878c8c8c8c6110d2565b73ffffffffffffffffffffffffffffffffffffffff16146107bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f546f6b656e436c61696d3a20696e76616c6964207369676e6174757265000000604482015260640161031c565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526001602052604081208054916107f083611cdb565b90915550506040517f0d6a5bbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690630d6a5bbb9061086f908d908d908d908b908b90600401611d5e565b600060405180830381600087803b15801561088957600080fd5b505af115801561089d573d6000803e3d6000fd5b505050507f4b9abc22f4c4dc79e3e5e71305668c0c487e00f351014a5f373472ba7e697bef8a8a8a88888c8c886040516108de989796959493929190611dbf565b60405180910390a150505050505050505050565b6108fb3361027a565b82818114610965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f5265636f766572793a20696e636f6e73697374656e7420617272617973000000604482015260640161031c565b60005b8181146109d6576109ce84848381811061098457610984611c7d565b9050602002013587878481811061099d5761099d611c7d565b90506020020160208101906109b29190611a12565b73ffffffffffffffffffffffffffffffffffffffff1690611169565b600101610968565b505050505050565b60008061026f60017fc9ed16f33ab3a66c84bfd83099ccb2a8845871e2e1c1928f63797152f0fd54cd611e2d565b73ffffffffffffffffffffffffffffffffffffffff811615610a945781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff821690811783556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35b610ac97f7f5828d0000000000000000000000000000000000000000000000000000000006001610ac2610b57565b9190610b85565b5050565b60008061026f60017f0186a05f63b1553398ad5ea3233c0ce68b8c9eecc47717f123c5c2b42fbd6d9f611e2d565b8015610ac95781547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011782556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a15050565b60008061026f60017fca9d3e17f264b0f3984e2634e94adb37fa3e6a8103f06aeae6fa59e21c769f5e611e2d565b7c01000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610c2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e74657266616365446574656374696f6e3a2077726f6e672076616c756500604482015260640161031c565b7fffffffff00000000000000000000000000000000000000000000000000000000919091166000908152602092909252604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b60007c01000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610ce15750600061026f565b7ffe003659000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610d325750600161026f565b507fffffffff00000000000000000000000000000000000000000000000000000000166000908152602091909152604090205460ff1690565b815473ffffffffffffffffffffffffffffffffffffffff828116911614610ac9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f776e6572736869703a206e6f7420746865206f776e65720000000000000000604482015260640161031c565b610df7816112c3565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a150565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610ed690849061132e565b505050565b610ee481611066565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a150565b825473ffffffffffffffffffffffffffffffffffffffff9081169083168114610fbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f776e6572736869703a206e6f7420746865206f776e65720000000000000000604482015260640161031c565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146110605783547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182178655604051908316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35b50505050565b805460ff16156106f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f50617573653a2070617573656400000000000000000000000000000000000000604482015260640161031c565b6000808b8b8b8b8b8b8b8b466040516020016110f699989796959493929190611e82565b60405160208183030381529060405280519060200120905061115984848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611153925085915061143a9050565b9061148d565b9c9b505050505050505050505050565b804710156111d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161031c565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461122d576040519150601f19603f3d011682016040523d82523d6000602084013e611232565b606091505b5050905080610ed6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161031c565b805460ff166106f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f50617573653a206e6f7420706175736564000000000000000000000000000000604482015260640161031c565b6000611390826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166114b19092919063ffffffff16565b805190915015610ed657808060200190518101906113ae9190611eec565b610ed6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161031c565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b600080600061149c85856114c8565b915091506114a98161150d565b509392505050565b60606114c084846000856116c0565b949350505050565b60008082516041036114fe5760208301516040840151606085015160001a6114f2878285856117d9565b94509450505050611506565b506000905060025b9250929050565b600081600481111561152157611521611f0e565b036115295750565b600181600481111561153d5761153d611f0e565b036115a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161031c565b60028160048111156115b8576115b8611f0e565b0361161f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161031c565b600381600481111561163357611633611f0e565b036106f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f7565000000000000000000000000000000000000000000000000000000000000606482015260840161031c565b606082471015611752576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161031c565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161177b9190611f61565b60006040518083038185875af1925050503d80600081146117b8576040519150601f19603f3d011682016040523d82523d6000602084013e6117bd565b606091505b50915091506117ce878383876118c8565b979650505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561181057506000905060036118bf565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611864573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166118b8576000600192509250506118bf565b9150600090505b94509492505050565b6060831561195e5782516000036119575773ffffffffffffffffffffffffffffffffffffffff85163b611957576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161031c565b50816114c0565b6114c083838151156119735781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031c9190611f7d565b6000602082840312156119b957600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146119e957600080fd5b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106f157600080fd5b600060208284031215611a2457600080fd5b81356119e9816119f0565b60008083601f840112611a4157600080fd5b50813567ffffffffffffffff811115611a5957600080fd5b6020830191508360208260051b850101111561150657600080fd5b60008060008060008060608789031215611a8d57600080fd5b863567ffffffffffffffff80821115611aa557600080fd5b611ab18a838b01611a2f565b90985096506020890135915080821115611aca57600080fd5b611ad68a838b01611a2f565b90965094506040890135915080821115611aef57600080fd5b50611afc89828a01611a2f565b979a9699509497509295939492505050565b600080600080600080600080600060a08a8c031215611b2c57600080fd5b8935611b37816119f0565b985060208a013567ffffffffffffffff80821115611b5457600080fd5b611b608d838e01611a2f565b909a50985060408c0135915080821115611b7957600080fd5b611b858d838e01611a2f565b909850965060608c0135915080821115611b9e57600080fd5b611baa8d838e01611a2f565b909650945060808c0135915080821115611bc357600080fd5b818c0191508c601f830112611bd757600080fd5b813581811115611be657600080fd5b8d6020828501011115611bf857600080fd5b6020830194508093505050509295985092959850929598565b60008060008060408587031215611c2757600080fd5b843567ffffffffffffffff80821115611c3f57600080fd5b611c4b88838901611a2f565b90965094506020870135915080821115611c6457600080fd5b50611c7187828801611a2f565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611d0c57611d0c611cac565b5060010190565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115611d4557600080fd5b8260051b80836020870137939093016020019392505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611d8e608083018688611d13565b8281036040840152611da1818587611d13565b83810360609094019390935250506000815260200195945050505050565b73ffffffffffffffffffffffffffffffffffffffff8916815260a060208201526000611def60a08301898b611d13565b8281036040840152611e0281888a611d13565b90508281036060840152611e17818688611d13565b9150508260808301529998505050505050505050565b8181038181111561026f5761026f611cac565b60007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115611e6f57600080fd5b8260051b80838637939093019392505050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008a60601b1681526000611ec4611ebd601484018b8d611e40565b888a611e40565b868152611ed5602082018688611e40565b938452505060209091019998505050505050505050565b600060208284031215611efe57600080fd5b815180151581146119e957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60005b83811015611f58578181015183820152602001611f40565b50506000910152565b60008251611f73818460208701611f3d565b9190910192915050565b6020815260008251806020840152611f9c816040850160208701611f3d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea26469706673582212203502dea2bf4276a9f7b1fb8e4b06e4f35b2a2984303e9e07cf3b2f792b5f847664736f6c63430008110033000000000000000000000000473989bf6409d21f8a7fdd7133a40f9251cc183900000000000000000000000016948b047861b7c71a17c002065be893b232e21d

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638456cb591161008c578063c3666c3611610066578063c3666c361461020f578063f2fde38b14610222578063f62ded8114610235578063f7ba94bd1461024857600080fd5b80638456cb59146101d85780638da5cb5b146101e0578063b1386c89146101e857600080fd5b80633f4ba83a116100c85780633f4ba83a146101a05780634b36df53146101aa5780635c975abb146101bd57806373c8a958146101c557600080fd5b806301ffc9a7146100ef578063080387b4146101175780632d0335ab1461015c575b600080fd5b6101026100fd3660046119a7565b61025b565b60405190151581526020015b60405180910390f35b6000546101379073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010e565b61019261016a366004611a12565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205490565b60405190815260200161010e565b6101a8610275565b005b6101a86101b8366004611a12565b61029a565b6101026103c0565b6101a86101d3366004611a74565b6103d9565b6101a86104fa565b610137610513565b6101377f000000000000000000000000473989bf6409d21f8a7fdd7133a40f9251cc183981565b6101a861021d366004611a74565b61053a565b6101a8610230366004611a12565b6106dd565b6101a8610243366004611b0e565b6106f4565b6101a8610256366004611c11565b6108f2565b600061026f82610269610b57565b90610c91565b92915050565b610288335b6102826109de565b90610d6b565b610298610293610acd565b610dee565b565b6102a33361027a565b73ffffffffffffffffffffffffffffffffffffffff8116610325576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f546f6b656e436c61696d3a20696e76616c6964207369676e657200000000000060448201526064015b60405180910390fd5b6000546040805173ffffffffffffffffffffffffffffffffffffffff928316815291831660208301527fb0d0791e347bdc6678365d0f8c4232c168c40192108be24902c292267defafb5910160405180910390a1600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006103d46103cd610acd565b5460ff1690565b905090565b6103e23361027a565b8483811480156103f157508082145b610457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f5265636f766572793a20696e636f6e73697374656e7420617272617973000000604482015260640161031c565b60005b8181146104f0576104e888888381811061047657610476611c7d565b905060200201602081019061048b9190611a12565b85858481811061049d5761049d611c7d565b905060200201358888858181106104b6576104b6611c7d565b90506020020160208101906104cb9190611a12565b73ffffffffffffffffffffffffffffffffffffffff169190610e49565b60010161045a565b5050505050505050565b6105033361027a565b61029861050e610acd565b610edb565b60006103d46105206109de565b5473ffffffffffffffffffffffffffffffffffffffff1690565b6105433361027a565b84838114801561055257508082145b6105b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f5265636f766572793a20696e636f6e73697374656e7420617272617973000000604482015260640161031c565b60005b8181146104f0578585828181106105d4576105d4611c7d565b90506020020160208101906105e99190611a12565b73ffffffffffffffffffffffffffffffffffffffff166323b872dd308a8a8581811061061757610617611c7d565b905060200201602081019061062c9190611a12565b87878681811061063e5761063e611c7d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b16815273ffffffffffffffffffffffffffffffffffffffff958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b1580156106ba57600080fd5b505af11580156106ce573d6000803e3d6000fd5b505050508060010190506105bb565b6106f133826106ea6109de565b9190610f39565b50565b6107046106ff610acd565b611066565b73ffffffffffffffffffffffffffffffffffffffff808a1660009081526001602052604081205490549091166107428b8b8b8b8b878c8c8c8c6110d2565b73ffffffffffffffffffffffffffffffffffffffff16146107bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f546f6b656e436c61696d3a20696e76616c6964207369676e6174757265000000604482015260640161031c565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526001602052604081208054916107f083611cdb565b90915550506040517f0d6a5bbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000473989bf6409d21f8a7fdd7133a40f9251cc18391690630d6a5bbb9061086f908d908d908d908b908b90600401611d5e565b600060405180830381600087803b15801561088957600080fd5b505af115801561089d573d6000803e3d6000fd5b505050507f4b9abc22f4c4dc79e3e5e71305668c0c487e00f351014a5f373472ba7e697bef8a8a8a88888c8c886040516108de989796959493929190611dbf565b60405180910390a150505050505050505050565b6108fb3361027a565b82818114610965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f5265636f766572793a20696e636f6e73697374656e7420617272617973000000604482015260640161031c565b60005b8181146109d6576109ce84848381811061098457610984611c7d565b9050602002013587878481811061099d5761099d611c7d565b90506020020160208101906109b29190611a12565b73ffffffffffffffffffffffffffffffffffffffff1690611169565b600101610968565b505050505050565b60008061026f60017fc9ed16f33ab3a66c84bfd83099ccb2a8845871e2e1c1928f63797152f0fd54cd611e2d565b73ffffffffffffffffffffffffffffffffffffffff811615610a945781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff821690811783556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35b610ac97f7f5828d0000000000000000000000000000000000000000000000000000000006001610ac2610b57565b9190610b85565b5050565b60008061026f60017f0186a05f63b1553398ad5ea3233c0ce68b8c9eecc47717f123c5c2b42fbd6d9f611e2d565b8015610ac95781547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011782556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a15050565b60008061026f60017fca9d3e17f264b0f3984e2634e94adb37fa3e6a8103f06aeae6fa59e21c769f5e611e2d565b7c01000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610c2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f496e74657266616365446574656374696f6e3a2077726f6e672076616c756500604482015260640161031c565b7fffffffff00000000000000000000000000000000000000000000000000000000919091166000908152602092909252604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b60007c01000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610ce15750600061026f565b7ffe003659000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610d325750600161026f565b507fffffffff00000000000000000000000000000000000000000000000000000000166000908152602091909152604090205460ff1690565b815473ffffffffffffffffffffffffffffffffffffffff828116911614610ac9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f776e6572736869703a206e6f7420746865206f776e65720000000000000000604482015260640161031c565b610df7816112c3565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a150565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610ed690849061132e565b505050565b610ee481611066565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a150565b825473ffffffffffffffffffffffffffffffffffffffff9081169083168114610fbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4f776e6572736869703a206e6f7420746865206f776e65720000000000000000604482015260640161031c565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146110605783547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182178655604051908316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35b50505050565b805460ff16156106f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f50617573653a2070617573656400000000000000000000000000000000000000604482015260640161031c565b6000808b8b8b8b8b8b8b8b466040516020016110f699989796959493929190611e82565b60405160208183030381529060405280519060200120905061115984848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611153925085915061143a9050565b9061148d565b9c9b505050505050505050505050565b804710156111d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161031c565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461122d576040519150601f19603f3d011682016040523d82523d6000602084013e611232565b606091505b5050905080610ed6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161031c565b805460ff166106f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f50617573653a206e6f7420706175736564000000000000000000000000000000604482015260640161031c565b6000611390826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166114b19092919063ffffffff16565b805190915015610ed657808060200190518101906113ae9190611eec565b610ed6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161031c565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b600080600061149c85856114c8565b915091506114a98161150d565b509392505050565b60606114c084846000856116c0565b949350505050565b60008082516041036114fe5760208301516040840151606085015160001a6114f2878285856117d9565b94509450505050611506565b506000905060025b9250929050565b600081600481111561152157611521611f0e565b036115295750565b600181600481111561153d5761153d611f0e565b036115a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161031c565b60028160048111156115b8576115b8611f0e565b0361161f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161031c565b600381600481111561163357611633611f0e565b036106f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f7565000000000000000000000000000000000000000000000000000000000000606482015260840161031c565b606082471015611752576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161031c565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161177b9190611f61565b60006040518083038185875af1925050503d80600081146117b8576040519150601f19603f3d011682016040523d82523d6000602084013e6117bd565b606091505b50915091506117ce878383876118c8565b979650505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561181057506000905060036118bf565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611864573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166118b8576000600192509250506118bf565b9150600090505b94509492505050565b6060831561195e5782516000036119575773ffffffffffffffffffffffffffffffffffffffff85163b611957576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161031c565b50816114c0565b6114c083838151156119735781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031c9190611f7d565b6000602082840312156119b957600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146119e957600080fd5b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106f157600080fd5b600060208284031215611a2457600080fd5b81356119e9816119f0565b60008083601f840112611a4157600080fd5b50813567ffffffffffffffff811115611a5957600080fd5b6020830191508360208260051b850101111561150657600080fd5b60008060008060008060608789031215611a8d57600080fd5b863567ffffffffffffffff80821115611aa557600080fd5b611ab18a838b01611a2f565b90985096506020890135915080821115611aca57600080fd5b611ad68a838b01611a2f565b90965094506040890135915080821115611aef57600080fd5b50611afc89828a01611a2f565b979a9699509497509295939492505050565b600080600080600080600080600060a08a8c031215611b2c57600080fd5b8935611b37816119f0565b985060208a013567ffffffffffffffff80821115611b5457600080fd5b611b608d838e01611a2f565b909a50985060408c0135915080821115611b7957600080fd5b611b858d838e01611a2f565b909850965060608c0135915080821115611b9e57600080fd5b611baa8d838e01611a2f565b909650945060808c0135915080821115611bc357600080fd5b818c0191508c601f830112611bd757600080fd5b813581811115611be657600080fd5b8d6020828501011115611bf857600080fd5b6020830194508093505050509295985092959850929598565b60008060008060408587031215611c2757600080fd5b843567ffffffffffffffff80821115611c3f57600080fd5b611c4b88838901611a2f565b90965094506020870135915080821115611c6457600080fd5b50611c7187828801611a2f565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611d0c57611d0c611cac565b5060010190565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115611d4557600080fd5b8260051b80836020870137939093016020019392505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611d8e608083018688611d13565b8281036040840152611da1818587611d13565b83810360609094019390935250506000815260200195945050505050565b73ffffffffffffffffffffffffffffffffffffffff8916815260a060208201526000611def60a08301898b611d13565b8281036040840152611e0281888a611d13565b90508281036060840152611e17818688611d13565b9150508260808301529998505050505050505050565b8181038181111561026f5761026f611cac565b60007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115611e6f57600080fd5b8260051b80838637939093019392505050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008a60601b1681526000611ec4611ebd601484018b8d611e40565b888a611e40565b868152611ed5602082018688611e40565b938452505060209091019998505050505050505050565b600060208284031215611efe57600080fd5b815180151581146119e957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60005b83811015611f58578181015183820152602001611f40565b50506000910152565b60008251611f73818460208701611f3d565b9190910192915050565b6020815260008251806020840152611f9c816040850160208701611f3d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea26469706673582212203502dea2bf4276a9f7b1fb8e4b06e4f35b2a2984303e9e07cf3b2f792b5f847664736f6c63430008110033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000473989bf6409d21f8a7fdd7133a40f9251cc183900000000000000000000000016948b047861b7c71a17c002065be893b232e21d

-----Decoded View---------------
Arg [0] : inventory_ (address): 0x473989BF6409D21f8A7Fdd7133a40F9251cC1839
Arg [1] : messageSigner_ (address): 0x16948B047861b7C71A17c002065bE893B232E21D

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000473989bf6409d21f8a7fdd7133a40f9251cc1839
Arg [1] : 00000000000000000000000016948b047861b7c71a17c002065be893b232e21d


Block Transaction 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
[ 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.