ETH Price: $3,326.03 (-4.08%)

Contract

0x410Ef532C1e4957806508d2B3928aaD73F3caA71
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Unstake Nft165999852023-02-10 17:56:11684 days ago1676051771IN
0x410Ef532...73F3caA71
0 ETH0.0029314129.43185292
Unstake Nft165999802023-02-10 17:55:11684 days ago1676051711IN
0x410Ef532...73F3caA71
0 ETH0.0029372729.49075927
Unstake Nft165999662023-02-10 17:52:23684 days ago1676051543IN
0x410Ef532...73F3caA71
0 ETH0.004742129.37341395
Unstake Nft152282612022-07-28 2:21:06882 days ago1658974866IN
0x410Ef532...73F3caA71
0 ETH0.00099610
Unstake Nft152282612022-07-28 2:21:06882 days ago1658974866IN
0x410Ef532...73F3caA71
0 ETH0.00099610
Unstake Nft152282612022-07-28 2:21:06882 days ago1658974866IN
0x410Ef532...73F3caA71
0 ETH0.00099610
Unstake Nft152282612022-07-28 2:21:06882 days ago1658974866IN
0x410Ef532...73F3caA71
0 ETH0.00099610
Unstake Nft152282612022-07-28 2:21:06882 days ago1658974866IN
0x410Ef532...73F3caA71
0 ETH0.00099610
Unstake Nft152282612022-07-28 2:21:06882 days ago1658974866IN
0x410Ef532...73F3caA71
0 ETH0.00099610
Unstake Nft152282302022-07-28 2:14:28882 days ago1658974468IN
0x410Ef532...73F3caA71
0 ETH0.000922519.26222898
Unstake Nft152282182022-07-28 2:12:43882 days ago1658974363IN
0x410Ef532...73F3caA71
0 ETH0.0014434210
Unstake Nft152156112022-07-26 3:03:52884 days ago1658804632IN
0x410Ef532...73F3caA71
0 ETH0.0024273417.45401698
Unstake Nft152110572022-07-25 10:06:22885 days ago1658743582IN
0x410Ef532...73F3caA71
0 ETH0.000609566.12014152
Unstake Nft152110572022-07-25 10:06:22885 days ago1658743582IN
0x410Ef532...73F3caA71
0 ETH0.000552955.55178248
Unstake Nft152110572022-07-25 10:06:22885 days ago1658743582IN
0x410Ef532...73F3caA71
0 ETH0.000552955.55178248
Unstake Nft152110262022-07-25 9:59:16885 days ago1658743156IN
0x410Ef532...73F3caA71
0 ETH0.000614816.17289021
Unstake Nft152110212022-07-25 9:57:37885 days ago1658743057IN
0x410Ef532...73F3caA71
0 ETH0.000428354.30072952
Claim Rewards152110132022-07-25 9:55:26885 days ago1658742926IN
0x410Ef532...73F3caA71
0 ETH0.001270083.48477387
Unstake Nft152110082022-07-25 9:54:37885 days ago1658742877IN
0x410Ef532...73F3caA71
0 ETH0.000580983.59872449
Unstake Nft152046262022-07-24 9:53:17886 days ago1658656397IN
0x410Ef532...73F3caA71
0 ETH0.000464094.65960275
Unstake Nft152046242022-07-24 9:53:12886 days ago1658656392IN
0x410Ef532...73F3caA71
0 ETH0.000539825.41997474
Unstake Nft152046192022-07-24 9:52:35886 days ago1658656355IN
0x410Ef532...73F3caA71
0 ETH0.00059535.97692145
Unstake Nft152046162022-07-24 9:52:03886 days ago1658656323IN
0x410Ef532...73F3caA71
0 ETH0.00065036.52919683
Unstake Nft152046112022-07-24 9:51:12886 days ago1658656272IN
0x410Ef532...73F3caA71
0 ETH0.000647666.5026966
Unstake Nft152046082022-07-24 9:50:58886 days ago1658656258IN
0x410Ef532...73F3caA71
0 ETH0.000979186.78375406
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DeltaTimeStaking2021

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 2000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-12-08
*/

// Sources flattened with hardhat v2.6.6 https://hardhat.org

// File @animoca/ethereum-contracts-core/contracts/utils/types/[email protected]

// SPDX-License-Identifier: MIT

// Partially derived from OpenZeppelin:
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/406c83649bd6169fc1b578e08506d78f0873b276/contracts/utils/Address.sol

pragma solidity >=0.7.6 <0.8.0;

/**
 * @dev Upgrades the address type to check if it is a contract.
 */
library AddressIsContract {
    /**
     * @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
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }
}


// File @animoca/ethereum-contracts-core/contracts/utils/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/**
 * @title ERC20Wrapper
 * Wraps ERC20 functions to support non-standard implementations which do not return a bool value.
 * Calls to the wrapped functions revert only if they throw or if they return false.
 */
library ERC20Wrapper {
    using AddressIsContract for address;

    function wrappedTransfer(
        IWrappedERC20 token,
        address to,
        uint256 value
    ) internal {
        _callWithOptionalReturnData(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function wrappedTransferFrom(
        IWrappedERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callWithOptionalReturnData(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function wrappedApprove(
        IWrappedERC20 token,
        address spender,
        uint256 value
    ) internal {
        _callWithOptionalReturnData(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function _callWithOptionalReturnData(IWrappedERC20 token, bytes memory callData) internal {
        address target = address(token);
        require(target.isContract(), "ERC20Wrapper: non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory data) = target.call(callData);
        if (success) {
            if (data.length != 0) {
                require(abi.decode(data, (bool)), "ERC20Wrapper: operation failed");
            }
        } else {
            // revert using a standard revert message
            if (data.length == 0) {
                revert("ERC20Wrapper: operation failed");
            }

            // revert using the revert message coming from the call
            assembly {
                let size := mload(data)
                revert(add(32, data), size)
            }
        }
    }
}

interface IWrappedERC20 {
    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function approve(address spender, uint256 value) external returns (bool);
}


// File @openzeppelin/contracts/utils/[email protected]

pragma solidity >=0.6.0 <0.8.0;


/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128) {
        require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits");
        return int128(value);
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64) {
        require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits");
        return int64(value);
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32) {
        require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits");
        return int32(value);
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16) {
        require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits");
        return int16(value);
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits.
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8) {
        require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits");
        return int8(value);
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        require(value < 2**255, "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}


// File @openzeppelin/contracts/math/[email protected]

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}


// File @openzeppelin/contracts/math/[email protected]

pragma solidity >=0.6.0 <0.8.0;

/**
 * @title SignedSafeMath
 * @dev Signed math operations with safety checks that revert on error.
 */
library SignedSafeMath {
    int256 constant private _INT256_MIN = -2**255;

    /**
     * @dev Returns the multiplication of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");

        int256 c = a * b;
        require(c / a == b, "SignedSafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two signed integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        require(b != 0, "SignedSafeMath: division by zero");
        require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");

        int256 c = a / b;

        return c;
    }

    /**
     * @dev Returns the subtraction of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a - b;
        require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");

        return c;
    }

    /**
     * @dev Returns the addition of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a + b;
        require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");

        return c;
    }
}


// File @animoca/ethereum-contracts-core/contracts/introspection/[email protected]

pragma solidity >=0.7.6 <0.8.0;

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


// File @animoca/ethereum-contracts-assets/contracts/token/ERC1155/interfaces/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/**
 * @title ERC1155 Multi Token Standard, Tokens Receiver.
 * Interface for any contract that wants to support transfers from ERC1155 asset contracts.
 * @dev See https://eips.ethereum.org/EIPS/eip-1155
 * @dev Note: The ERC-165 identifier for this interface is 0x4e2312e0.
 */
interface IERC1155TokenReceiver {
    /**
     * @notice Handle the receipt of a single ERC1155 token type.
     * An ERC1155 contract MUST call this function on a recipient contract, at the end of a `safeTransferFrom` after the balance update.
     * This function MUST return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     *  (i.e. 0xf23a6e61) to accept the transfer.
     * Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
     * @param operator  The address which initiated the transfer (i.e. msg.sender)
     * @param from      The address which previously owned the token
     * @param id        The ID of the token being transferred
     * @param value     The amount of tokens being transferred
     * @param data      Additional data with no specified format
     * @return bytes4   `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @notice Handle the receipt of multiple ERC1155 token types.
     * An ERC1155 contract MUST call this function on a recipient contract, at the end of a `safeBatchTransferFrom` after the balance updates.
     * This function MUST return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     *  (i.e. 0xbc197c81) if to accept the transfer(s).
     * Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
     * @param operator  The address which initiated the batch transfer (i.e. msg.sender)
     * @param from      The address which previously owned the token
     * @param ids       An array containing ids of each token being transferred (order and length must match _values array)
     * @param values    An array containing amounts of each token being transferred (order and length must match _ids array)
     * @param data      Additional data with no specified format
     * @return          `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}


// File @animoca/ethereum-contracts-assets/contracts/token/ERC1155/[email protected]

pragma solidity >=0.7.6 <0.8.0;


/**
 * @title ERC1155 Transfers Receiver Contract.
 * @dev The functions `onERC1155Received(address,address,uint256,uint256,bytes)`
 *  and `onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)` need to be implemented by a child contract.
 */
abstract contract ERC1155TokenReceiver is IERC165, IERC1155TokenReceiver {
    // bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))
    bytes4 internal constant _ERC1155_RECEIVED = 0xf23a6e61;

    // bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))
    bytes4 internal constant _ERC1155_BATCH_RECEIVED = 0xbc197c81;

    bytes4 internal constant _ERC1155_REJECTED = 0xffffffff;

    //======================================================= ERC165 ========================================================//

    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId || interfaceId == type(IERC1155TokenReceiver).interfaceId;
    }
}


// File @animoca/ethereum-contracts-core/contracts/metatx/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/*
 * 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.
 */
abstract contract ManagedIdentity {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

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


// File @animoca/ethereum-contracts-core/contracts/access/[email protected]

pragma solidity >=0.7.6 <0.8.0;

/**
 * @title ERC-173 Contract Ownership Standard
 * Note: the ERC-165 identifier for this interface is 0x7f5828d0
 */
interface IERC173 {
    /**
     * Event emited when ownership of a contract changes.
     * @param previousOwner the previous owner.
     * @param newOwner the new owner.
     */
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * Get the address of the owner
     * @return The address of the owner.
     */
    function owner() external view returns (address);

    /**
     * Set the address of the new owner of the contract
     * Set newOwner to address(0) to renounce any ownership.
     * @dev Emits an {OwnershipTransferred} event.
     * @param newOwner The address of the new owner of the contract. Using the zero address means renouncing ownership.
     */
    function transferOwnership(address newOwner) external;
}


// File @animoca/ethereum-contracts-core/contracts/access/[email protected]

pragma solidity >=0.7.6 <0.8.0;


/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is ManagedIdentity, IERC173 {
    address internal _owner;

    /**
     * Initializes the contract, setting the deployer as the initial owner.
     * @dev Emits an {IERC173-OwnershipTransferred(address,address)} event.
     */
    constructor(address owner_) {
        _owner = owner_;
        emit OwnershipTransferred(address(0), owner_);
    }

    /**
     * Gets the address of the current contract owner.
     */
    function owner() public view virtual override returns (address) {
        return _owner;
    }

    /**
     * See {IERC173-transferOwnership(address)}
     * @dev Reverts if the sender is not the current contract owner.
     * @param newOwner the address of the new owner. Use the zero address to renounce the ownership.
     */
    function transferOwnership(address newOwner) public virtual override {
        _requireOwnership(_msgSender());
        _owner = newOwner;
        emit OwnershipTransferred(_owner, newOwner);
    }

    /**
     * @dev Reverts if `account` is not the contract owner.
     * @param account the account to test.
     */
    function _requireOwnership(address account) internal virtual {
        require(account == this.owner(), "Ownable: not the owner");
    }
}


// File contracts/staking/DeltaTimeStaking2021.sol

pragma solidity >=0.7.6 <0.8.0;




/**
 * @title Delta Time Staking 2021
 * Distribute REVV rewards over discrete-time schedules for the staking of Car NFTs.
 * This contract is designed on a self-service model, where users will stake NFTs, unstake NFTs and claim rewards through their own transactions only.
 */
contract DeltaTimeStaking2021 is ERC1155TokenReceiver, Ownable {
    using ERC20Wrapper for IWrappedERC20;
    using SafeCast for uint256;
    using SafeMath for uint256;
    using SignedSafeMath for int256;

    event RewardsAdded(uint256 startPeriod, uint256 endPeriod, uint256 rewardsPerCycle);

    event Started();

    event NftStaked(address staker, uint256 cycle, uint256 tokenId, uint256 weight);

    event NftUnstaked(address staker, uint256 cycle, uint256 tokenId, uint256 weight);

    event RewardsClaimed(address staker, uint256 cycle, uint256 startPeriod, uint256 periods, uint256 amount);

    event HistoriesUpdated(address staker, uint256 startCycle, uint256 stakerStake, uint256 globalStake);

    event Disabled();

    /**
     * Used to represent the current staking status of an NFT.
     * Optimised for use in storage.
     */
    struct TokenInfo {
        address owner;
        uint64 weight;
        uint16 depositCycle;
        uint16 withdrawCycle;
    }

    /**
     * Used as a historical record of change of stake.
     * Stake represents an aggregation of staked token weights.
     * Optimised for use in storage.
     */
    struct Snapshot {
        uint128 stake;
        uint128 startCycle;
    }

    /**
     * Used to represent a staker's information about the next claim.
     * Optimised for use in storage.
     */
    struct NextClaim {
        uint16 period;
        uint64 globalSnapshotIndex;
        uint64 stakerSnapshotIndex;
    }

    /**
     * Used as a container to hold result values from computing rewards.
     */
    struct ComputedClaim {
        uint16 startPeriod;
        uint16 periods;
        uint256 amount;
    }

    bool public enabled = true;

    uint256 public totalRewardsPool;

    uint256 public startTimestamp;

    IWrappedERC20 public immutable rewardsTokenContract;
    IWhitelistedNftContract public immutable whitelistedNftContract;

    uint32 public immutable cycleLengthInSeconds;
    uint16 public immutable periodLengthInCycles;

    Snapshot[] public globalHistory;

    mapping(uint256 => uint64) public weightsByRarity;

    /* staker => snapshots*/
    mapping(address => Snapshot[]) public stakerHistories;

    /* staker => next claim */
    mapping(address => NextClaim) public nextClaims;

    /* tokenId => token info */
    mapping(uint256 => TokenInfo) public tokenInfos;

    /* period => rewardsPerCycle */
    mapping(uint256 => uint256) public rewardsSchedule;

    modifier hasStarted() {
        require(startTimestamp != 0, "NftStaking: staking not started");
        _;
    }

    modifier hasNotStarted() {
        require(startTimestamp == 0, "NftStaking: staking has started");
        _;
    }

    modifier isEnabled() {
        // solhint-disable-next-line reason-string
        require(enabled, "NftStaking: contract is not enabled");
        _;
    }

    modifier isNotEnabled() {
        require(!enabled, "NftStaking: contract is enabled");
        _;
    }

    /**
     * Constructor.
     * @dev Reverts if the period length value is zero.
     * @dev Reverts if the cycle length value is zero.
     * @dev Warning: cycles and periods need to be calibrated carefully.
     *  Small values will increase computation load while estimating and claiming rewards.
     *  Big values will increase the time to wait before a new period becomes claimable.
     * @param cycleLengthInSeconds_ The length of a cycle, in seconds.
     * @param periodLengthInCycles_ The length of a period, in cycles.
     * @param whitelistedNftContract_ The ERC1155-compliant (optional ERC721-compliance) contract from which staking is accepted.
     * @param rewardsTokenContract_ The ERC20-based token used as staking rewards.
     */
    constructor(
        uint32 cycleLengthInSeconds_,
        uint16 periodLengthInCycles_,
        IWhitelistedNftContract whitelistedNftContract_,
        IWrappedERC20 rewardsTokenContract_,
        uint256[] memory rarities,
        uint64[] memory weights
    ) Ownable(msg.sender) {
        require(rarities.length == weights.length, "NftStaking: wrong arguments");

        // solhint-disable-next-line reason-string
        require(cycleLengthInSeconds_ >= 1 minutes, "NftStaking: invalid cycle length");
        // solhint-disable-next-line reason-string
        require(periodLengthInCycles_ >= 2, "NftStaking: invalid period length");

        cycleLengthInSeconds = cycleLengthInSeconds_;
        periodLengthInCycles = periodLengthInCycles_;
        whitelistedNftContract = whitelistedNftContract_;
        rewardsTokenContract = rewardsTokenContract_;

        for (uint256 i = 0; i < rarities.length; ++i) {
            weightsByRarity[rarities[i]] = weights[i];
        }
    }

    /*                                            Admin Public Functions                                            */

    /**
     * Adds `rewardsPerCycle` reward amount for the period range from `startPeriod` to `endPeriod`, inclusive, to the rewards schedule.
     * The necessary amount of reward tokens is transferred to the contract. Cannot be used for past periods.
     * Can only be used to add rewards and not to remove them.
     * @dev Reverts if not called by the owner.
     * @dev Reverts if the start period is zero.
     * @dev Reverts if the end period precedes the start period.
     * @dev Reverts if attempting to add rewards for a period earlier than the current, after staking has started.
     * @dev Reverts if the reward tokens transfer fails.
     * @dev The rewards token contract emits an ERC20 Transfer event for the reward tokens transfer.
     * @dev Emits a RewardsAdded event.
     * @param startPeriod The starting period (inclusive).
     * @param endPeriod The ending period (inclusive).
     * @param rewardsPerCycle The reward amount to add for each cycle within range.
     */
    function addRewardsForPeriods(
        uint16 startPeriod,
        uint16 endPeriod,
        uint256 rewardsPerCycle
    ) external {
        _requireOwnership(msg.sender);
        require(startPeriod != 0 && startPeriod <= endPeriod, "NftStaking: wrong period range");

        uint16 periodLengthInCycles_ = periodLengthInCycles;

        if (startTimestamp != 0) {
            // solhint-disable-next-line reason-string
            require(startPeriod >= _getCurrentPeriod(periodLengthInCycles_), "NftStaking: already committed reward schedule");
        }

        for (uint256 period = startPeriod; period <= endPeriod; ++period) {
            rewardsSchedule[period] = rewardsSchedule[period].add(rewardsPerCycle);
        }

        uint256 addedRewards = rewardsPerCycle.mul(periodLengthInCycles_).mul(endPeriod - startPeriod + 1);

        totalRewardsPool = totalRewardsPool.add(addedRewards);

        rewardsTokenContract.wrappedTransferFrom(msg.sender, address(this), addedRewards);

        emit RewardsAdded(startPeriod, endPeriod, rewardsPerCycle);
    }

    /**
     * Starts the first cycle of staking, enabling users to stake NFTs.
     * @dev Reverts if not called by the owner.
     * @dev Reverts if the staking has already started.
     * @dev Emits a Started event.
     */
    function start() public hasNotStarted {
        _requireOwnership(msg.sender);
        startTimestamp = block.timestamp;
        emit Started();
    }

    /**
     * Permanently disables all staking and claiming.
     * This is an emergency recovery feature which is NOT part of the normal contract operation.
     * @dev Reverts if not called by the owner.
     * @dev Emits a Disabled event.
     */
    function disable() public {
        _requireOwnership(msg.sender);
        enabled = false;
        emit Disabled();
    }

    /**
     * Withdraws a specified amount of reward tokens from the contract it has been disabled.
     * @dev Reverts if not called by the owner.
     * @dev Reverts if the contract has not been disabled.
     * @dev Reverts if the reward tokens transfer fails.
     * @dev The rewards token contract emits an ERC20 Transfer event for the reward tokens transfer.
     * @param amount The amount to withdraw.
     */
    function withdrawRewardsPool(uint256 amount) public isNotEnabled {
        _requireOwnership(msg.sender);
        rewardsTokenContract.wrappedTransfer(msg.sender, amount);
    }

    /*                                             ERC1155TokenReceiver                                             */

    function onERC1155Received(
        address, /*operator*/
        address from,
        uint256 id,
        uint256, /*value*/
        bytes calldata /*data*/
    ) external virtual override returns (bytes4) {
        _stakeNft(id, from);
        return _ERC1155_RECEIVED;
    }

    function onERC1155BatchReceived(
        address, /*operator*/
        address from,
        uint256[] calldata ids,
        uint256[] calldata, /*values*/
        bytes calldata /*data*/
    ) external virtual override returns (bytes4) {
        for (uint256 i = 0; i < ids.length; ++i) {
            _stakeNft(ids[i], from);
        }
        return _ERC1155_BATCH_RECEIVED;
    }

    /*                                            Staking Public Functions                                            */

    /**
     * Unstakes a deposited NFT from the contract and updates the histories accordingly.
     * The NFT's weight will not count for the current cycle.
     * @dev Reverts if the caller is not the original owner of the NFT.
     * @dev While the contract is enabled, reverts if the NFT is still frozen.
     * @dev Reverts if the NFT transfer back to the original owner fails.
     * @dev If ERC1155 safe transfers are supported by the receiver wallet,
     *  the whitelisted NFT contract emits an ERC1155 TransferSingle event for the NFT transfer back to the staker.
     * @dev If ERC1155 safe transfers are not supported by the receiver wallet,
     *  the whitelisted NFT contract emits an ERC721 Transfer event for the NFT transfer back to the staker.
     * @dev While the contract is enabled, emits a HistoriesUpdated event.
     * @dev Emits a NftUnstaked event.
     * @param tokenId The token identifier, referencing the NFT being unstaked.
     */
    function unstakeNft(uint256 tokenId) external {
        TokenInfo memory tokenInfo = tokenInfos[tokenId];

        // solhint-disable-next-line reason-string
        require(tokenInfo.owner == msg.sender, "NftStaking: token not staked or incorrect token owner");

        uint16 currentCycle = _getCycle(block.timestamp);

        if (enabled) {
            // ensure that at least an entire cycle has elapsed before unstaking the token to avoid
            // an exploit where a full cycle would be claimable if staking just before the end
            // of a cycle and unstaking right after the start of the new cycle
            require(currentCycle - tokenInfo.depositCycle >= 2, "NftStaking: token still frozen");

            _updateHistories(msg.sender, -int128(tokenInfo.weight), currentCycle);

            // clear the token owner to ensure it cannot be unstaked again without being re-staked
            tokenInfo.owner = address(0);

            // set the withdrawal cycle to ensure it cannot be re-staked during the same cycle
            tokenInfo.withdrawCycle = currentCycle;

            tokenInfos[tokenId] = tokenInfo;
        }

        whitelistedNftContract.transferFrom(address(this), msg.sender, tokenId);

        emit NftUnstaked(msg.sender, currentCycle, tokenId, tokenInfo.weight);
    }

    /**
     * Estimates the claimable rewards for the specified maximum number of past periods, starting at the next claimable period.
     * Estimations can be done only for periods which have already ended.
     * The maximum number of periods to claim can be calibrated to chunk down claims in several transactions to accomodate gas constraints.
     * @param maxPeriods The maximum number of periods to calculate for.
     * @return startPeriod The first period on which the computation starts.
     * @return periods The number of periods computed for.
     * @return amount The total claimable rewards.
     */
    function estimateRewards(uint16 maxPeriods)
        external
        view
        isEnabled
        hasStarted
        returns (
            uint16 startPeriod,
            uint16 periods,
            uint256 amount
        )
    {
        (ComputedClaim memory claim, ) = _computeRewards(msg.sender, maxPeriods);
        startPeriod = claim.startPeriod;
        periods = claim.periods;
        amount = claim.amount;
    }

    /**
     * Claims the claimable rewards for the specified maximum number of past periods, starting at the next claimable period.
     * Claims can be done only for periods which have already ended.
     * The maximum number of periods to claim can be calibrated to chunk down claims in several transactions to accomodate gas constraints.
     * @dev Reverts if the reward tokens transfer fails.
     * @dev The rewards token contract emits an ERC20 Transfer event for the reward tokens transfer.
     * @dev Emits a RewardsClaimed event.
     * @param maxPeriods The maximum number of periods to claim for.
     */
    function claimRewards(uint16 maxPeriods) external isEnabled hasStarted {
        NextClaim memory nextClaim = nextClaims[msg.sender];

        (ComputedClaim memory claim, NextClaim memory newNextClaim) = _computeRewards(msg.sender, maxPeriods);

        // free up memory on already processed staker snapshots
        Snapshot[] storage stakerHistory = stakerHistories[msg.sender];
        while (nextClaim.stakerSnapshotIndex < newNextClaim.stakerSnapshotIndex) {
            delete stakerHistory[nextClaim.stakerSnapshotIndex++];
        }

        if (claim.periods == 0) {
            return;
        }

        if (nextClaims[msg.sender].period == 0) {
            return;
        }

        Snapshot memory lastStakerSnapshot = stakerHistory[stakerHistory.length - 1];

        uint256 lastClaimedCycle = (claim.startPeriod + claim.periods - 1) * periodLengthInCycles;
        if (
            lastClaimedCycle >= lastStakerSnapshot.startCycle && // the claim reached the last staker snapshot
            lastStakerSnapshot.stake == 0 // and nothing is staked in the last staker snapshot
        ) {
            // re-init the next claim
            delete nextClaims[msg.sender];
        } else {
            nextClaims[msg.sender] = newNextClaim;
        }

        if (claim.amount != 0) {
            rewardsTokenContract.wrappedTransfer(msg.sender, claim.amount);
        }

        emit RewardsClaimed(msg.sender, _getCycle(block.timestamp), claim.startPeriod, claim.periods, claim.amount);
    }

    /*                                            Utility Public Functions                                            */

    /**
     * Retrieves the current cycle (index-1 based).
     * @return The current cycle (index-1 based).
     */
    function getCurrentCycle() external view returns (uint16) {
        return _getCycle(block.timestamp);
    }

    /**
     * Retrieves the current period (index-1 based).
     * @return The current period (index-1 based).
     */
    function getCurrentPeriod() external view returns (uint16) {
        return _getCurrentPeriod(periodLengthInCycles);
    }

    /**
     * Retrieves the last global snapshot index, if any.
     * @dev Reverts if the global history is empty.
     * @return The last global snapshot index.
     */
    function lastGlobalSnapshotIndex() external view returns (uint256) {
        uint256 length = globalHistory.length;
        // solhint-disable-next-line reason-string
        require(length != 0, "NftStaking: empty global history");
        return length - 1;
    }

    /**
     * Retrieves the last staker snapshot index, if any.
     * @dev Reverts if the staker history is empty.
     * @return The last staker snapshot index.
     */
    function lastStakerSnapshotIndex(address staker) external view returns (uint256) {
        uint256 length = stakerHistories[staker].length;
        // solhint-disable-next-line reason-string
        require(length != 0, "NftStaking: empty staker history");
        return length - 1;
    }

    /*                                            Staking Internal Functions                                            */

    /**
     * Stakes the NFT received by the contract for its owner. The NFT's weight will count for the current cycle.
     * @dev Reverts if the caller is not the whitelisted NFT contract.
     * @dev Emits an HistoriesUpdated event.
     * @dev Emits an NftStaked event.
     * @param tokenId Identifier of the staked NFT.
     * @param tokenOwner Owner of the staked NFT.
     */
    function _stakeNft(uint256 tokenId, address tokenOwner) internal isEnabled hasStarted {
        // solhint-disable-next-line reason-string
        require(address(whitelistedNftContract) == msg.sender, "NftStaking: contract not whitelisted");

        uint64 weight = _validateAndGetNftWeight(tokenId);

        uint16 periodLengthInCycles_ = periodLengthInCycles;
        uint16 currentCycle = _getCycle(block.timestamp);

        _updateHistories(tokenOwner, int128(weight), currentCycle);

        // initialise the next claim if it was the first stake for this staker or if
        // the next claim was re-initialised (ie. rewards were claimed until the last
        // staker snapshot and the last staker snapshot has no stake)
        if (nextClaims[tokenOwner].period == 0) {
            uint16 currentPeriod = _getPeriod(currentCycle, periodLengthInCycles_);
            nextClaims[tokenOwner] = NextClaim(currentPeriod, uint64(globalHistory.length - 1), 0);
        }

        uint16 withdrawCycle = tokenInfos[tokenId].withdrawCycle;
        // solhint-disable-next-line reason-string
        require(currentCycle != withdrawCycle, "NftStaking: unstaked token cooldown");

        // set the staked token's info
        tokenInfos[tokenId] = TokenInfo(tokenOwner, weight, currentCycle, 0);

        emit NftStaked(tokenOwner, currentCycle, tokenId, weight);
    }

    /**
     * Calculates the amount of rewards for a staker over a capped number of periods.
     * @dev Processes until the specified maximum number of periods to claim is reached,
     *  or the last computable period is reached, whichever occurs first.
     * @param staker The staker for whom the rewards will be computed.
     * @param maxPeriods Maximum number of periods over which to compute the rewards.
     * @return claim the result of computation
     * @return nextClaim the next claim which can be used to update the staker's state
     */
    // solhint-disable-next-line code-complexity
    function _computeRewards(address staker, uint16 maxPeriods) internal view returns (ComputedClaim memory claim, NextClaim memory nextClaim) {
        // computing 0 periods
        if (maxPeriods == 0) {
            return (claim, nextClaim);
        }

        // the history is empty
        if (globalHistory.length == 0) {
            return (claim, nextClaim);
        }

        nextClaim = nextClaims[staker];
        claim.startPeriod = nextClaim.period;

        // nothing has been staked yet
        if (claim.startPeriod == 0) {
            return (claim, nextClaim);
        }

        uint16 periodLengthInCycles_ = periodLengthInCycles;
        uint16 endClaimPeriod = _getCurrentPeriod(periodLengthInCycles_);

        // current period is not claimable
        if (nextClaim.period == endClaimPeriod) {
            return (claim, nextClaim);
        }

        // retrieve the next snapshots if they exist
        Snapshot[] memory stakerHistory = stakerHistories[staker];

        Snapshot memory globalSnapshot = globalHistory[nextClaim.globalSnapshotIndex];
        Snapshot memory stakerSnapshot = stakerHistory[nextClaim.stakerSnapshotIndex];
        Snapshot memory nextGlobalSnapshot;
        Snapshot memory nextStakerSnapshot;

        if (nextClaim.globalSnapshotIndex != globalHistory.length - 1) {
            nextGlobalSnapshot = globalHistory[nextClaim.globalSnapshotIndex + 1];
        }
        if (nextClaim.stakerSnapshotIndex != stakerHistory.length - 1) {
            nextStakerSnapshot = stakerHistory[nextClaim.stakerSnapshotIndex + 1];
        }

        // excludes the current period
        claim.periods = endClaimPeriod - nextClaim.period;

        if (maxPeriods < claim.periods) {
            claim.periods = maxPeriods;
        }

        // re-calibrate the end claim period based on the actual number of
        // periods to claim. nextClaim.period will be updated to this value
        // after exiting the loop
        endClaimPeriod = nextClaim.period + claim.periods;

        // iterate over periods
        while (nextClaim.period != endClaimPeriod) {
            uint16 nextPeriodStartCycle = nextClaim.period * periodLengthInCycles_ + 1;
            uint256 rewardPerCycle = rewardsSchedule[nextClaim.period];
            uint256 startCycle = nextPeriodStartCycle - periodLengthInCycles_;
            uint256 endCycle = 0;

            // iterate over global snapshots
            while (endCycle != nextPeriodStartCycle) {
                // find the range-to-claim starting cycle, where the current
                // global snapshot, the current staker snapshot, and the current
                // period overlap
                if (globalSnapshot.startCycle > startCycle) {
                    startCycle = globalSnapshot.startCycle;
                }
                if (stakerSnapshot.startCycle > startCycle) {
                    startCycle = stakerSnapshot.startCycle;
                }

                // find the range-to-claim ending cycle, where the current
                // global snapshot, the current staker snapshot, and the current
                // period no longer overlap. The end cycle is exclusive of the
                // range-to-claim and represents the beginning cycle of the next
                // range-to-claim
                endCycle = nextPeriodStartCycle;
                if ((nextGlobalSnapshot.startCycle != 0) && (nextGlobalSnapshot.startCycle < endCycle)) {
                    endCycle = nextGlobalSnapshot.startCycle;
                }

                // only calculate and update the claimable rewards if there is
                // something to calculate with
                if ((globalSnapshot.stake != 0) && (stakerSnapshot.stake != 0) && (rewardPerCycle != 0)) {
                    uint256 snapshotReward = (endCycle - startCycle).mul(rewardPerCycle).mul(stakerSnapshot.stake);
                    snapshotReward /= globalSnapshot.stake;

                    claim.amount = claim.amount.add(snapshotReward);
                }

                // advance the current global snapshot to the next (if any)
                // if its cycle range has been fully processed and if the next
                // snapshot starts at most on next period first cycle
                if (nextGlobalSnapshot.startCycle == endCycle) {
                    globalSnapshot = nextGlobalSnapshot;
                    ++nextClaim.globalSnapshotIndex;

                    if (nextClaim.globalSnapshotIndex != globalHistory.length - 1) {
                        nextGlobalSnapshot = globalHistory[nextClaim.globalSnapshotIndex + 1];
                    } else {
                        nextGlobalSnapshot = Snapshot(0, 0);
                    }
                }

                // advance the current staker snapshot to the next (if any)
                // if its cycle range has been fully processed and if the next
                // snapshot starts at most on next period first cycle
                if (nextStakerSnapshot.startCycle == endCycle) {
                    stakerSnapshot = nextStakerSnapshot;
                    ++nextClaim.stakerSnapshotIndex;

                    if (nextClaim.stakerSnapshotIndex != stakerHistory.length - 1) {
                        nextStakerSnapshot = stakerHistory[nextClaim.stakerSnapshotIndex + 1];
                    } else {
                        nextStakerSnapshot = Snapshot(0, 0);
                    }
                }
            }

            ++nextClaim.period;
        }

        return (claim, nextClaim);
    }

    /**
     * Updates the global and staker histories at the current cycle with a new difference in stake.
     * @dev Emits a HistoriesUpdated event.
     * @param staker The staker who is updating the history.
     * @param stakeDelta The difference to apply to the current stake.
     * @param currentCycle The current cycle.
     */
    function _updateHistories(
        address staker,
        int128 stakeDelta,
        uint16 currentCycle
    ) internal {
        uint256 stakerSnapshotIndex = _updateHistory(stakerHistories[staker], stakeDelta, currentCycle);
        uint256 globalSnapshotIndex = _updateHistory(globalHistory, stakeDelta, currentCycle);

        emit HistoriesUpdated(staker, currentCycle, stakerHistories[staker][stakerSnapshotIndex].stake, globalHistory[globalSnapshotIndex].stake);
    }

    /**
     * Updates the history at the current cycle with a new difference in stake.
     * @dev It will update the latest snapshot if it starts at the current cycle, otherwise will create a new snapshot with the updated stake.
     * @param history The history to update.
     * @param stakeDelta The difference to apply to the current stake.
     * @param currentCycle The current cycle.
     * @return snapshotIndex Index of the snapshot that was updated or created (i.e. the latest snapshot index).
     */
    function _updateHistory(
        Snapshot[] storage history,
        int128 stakeDelta,
        uint16 currentCycle
    ) internal returns (uint256 snapshotIndex) {
        uint256 historyLength = history.length;
        uint128 snapshotStake;

        if (historyLength != 0) {
            // there is an existing snapshot
            snapshotIndex = historyLength - 1;
            Snapshot storage sSnapshot = history[snapshotIndex];
            snapshotStake = uint256(int256(sSnapshot.stake).add(stakeDelta)).toUint128();

            if (sSnapshot.startCycle == currentCycle) {
                // update the snapshot if it starts on the current cycle
                sSnapshot.stake = snapshotStake;
                return snapshotIndex;
            }

            // update the snapshot index (as a reflection that a new latest
            // snapshot will be added to the history), if there was already an
            // existing snapshot
            snapshotIndex += 1;
        } else {
            // the snapshot index (as a reflection that a new latest snapshot
            // will be added to the history) should already be initialized
            // correctly to the default value 0

            // the stake delta will not be negative, if we have no history, as
            // that would indicate that we are unstaking without having staked
            // anything first
            snapshotStake = uint128(stakeDelta);
        }

        Snapshot memory mSnapshot;
        mSnapshot.stake = snapshotStake;
        mSnapshot.startCycle = currentCycle;

        // add a new snapshot in the history
        history.push(mSnapshot);
    }

    /*                                           Utility Internal Functions                                           */

    /**
     * Retrieves the cycle (index-1 based) at the specified timestamp.
     * @param timestamp The timestamp for which the cycle is derived from.
     * @return The cycle (index-1 based) at the specified timestamp, or zero if the contract is not started yet.
     */
    function _getCycle(uint256 timestamp) internal view returns (uint16) {
        uint256 startTimestamp_ = startTimestamp;
        if (startTimestamp_ == 0) return 0;
        return (((timestamp - startTimestamp_) / uint256(cycleLengthInSeconds)) + 1).toUint16();
    }

    /**
     * Retrieves the period (index-1 based) for the specified cycle and period length.
     * @param cycle The cycle within the period to retrieve.
     * @param periodLengthInCycles_ Length of a period, in cycles.
     * @return The period (index-1 based) for the specified cycle and period length, 0r zero if `cycle` is zero.
     */
    function _getPeriod(uint16 cycle, uint16 periodLengthInCycles_) internal pure returns (uint16) {
        if (cycle == 0) {
            return 0;
        }
        return (cycle - 1) / periodLengthInCycles_ + 1;
    }

    /**
     * Retrieves the current period (index-1 based).
     * @param periodLengthInCycles_ Length of a period, in cycles.
     * @return The current period (index-1 based).
     */
    function _getCurrentPeriod(uint16 periodLengthInCycles_) internal view returns (uint16) {
        return _getPeriod(_getCycle(block.timestamp), periodLengthInCycles_);
    }

    /*                                                Internal Hooks                                                */

    /**
     * Verifies that the token is eligible and returns its associated weight.
     * @dev Reverts if the token is not a 2019 or 2020 Car NFT.
     * @param nftId uint256 token identifier of the NFT.
     * @return uint64 the weight of the NFT.
     */
    function _validateAndGetNftWeight(uint256 nftId) internal view returns (uint64) {
        // Ids bits layout specification:
        // https://github.com/animocabrands/f1dt-core_metadata/blob/v0.1.1/src/constants.js
        uint256 nonFungible = (nftId >> 255) & 1;
        uint256 tokenType = (nftId >> 240) & 0xFF;
        uint256 tokenSeason = (nftId >> 224) & 0xFF;
        uint256 tokenRarity = (nftId >> 176) & 0xFF;

        // For interpretation of values, refer to https://github.com/animocabrands/f1dt-core_metadata/blob/version-1.0.3/src/mappings/
        // Types: https://github.com/animocabrands/f1dt-core_metadata/blob/version-1.0.3/src/mappings/CommonAttributes/Type/Types.js
        // Seasons: https://github.com/animocabrands/f1dt-core_metadata/blob/version-1.0.3/src/mappings/CommonAttributes/Season/Seasons.js
        // Rarities: https://github.com/animocabrands/f1dt-core_metadata/blob/version-1.0.3/src/mappings/CommonAttributes/Rarity/Rarities.js
        require(nonFungible == 1 && tokenType == 1 && (tokenSeason == 2 || tokenSeason == 3), "NftStaking: wrong token");

        return weightsByRarity[tokenRarity];
    }
}

interface IWhitelistedNftContract {
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint32","name":"cycleLengthInSeconds_","type":"uint32"},{"internalType":"uint16","name":"periodLengthInCycles_","type":"uint16"},{"internalType":"contract IWhitelistedNftContract","name":"whitelistedNftContract_","type":"address"},{"internalType":"contract IWrappedERC20","name":"rewardsTokenContract_","type":"address"},{"internalType":"uint256[]","name":"rarities","type":"uint256[]"},{"internalType":"uint64[]","name":"weights","type":"uint64[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[],"name":"Disabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"startCycle","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakerStake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"globalStake","type":"uint256"}],"name":"HistoriesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"cycle","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"NftStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"cycle","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"weight","type":"uint256"}],"name":"NftUnstaked","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":[{"indexed":false,"internalType":"uint256","name":"startPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardsPerCycle","type":"uint256"}],"name":"RewardsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"cycle","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"periods","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[],"name":"Started","type":"event"},{"inputs":[{"internalType":"uint16","name":"startPeriod","type":"uint16"},{"internalType":"uint16","name":"endPeriod","type":"uint16"},{"internalType":"uint256","name":"rewardsPerCycle","type":"uint256"}],"name":"addRewardsForPeriods","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"maxPeriods","type":"uint16"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cycleLengthInSeconds","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"maxPeriods","type":"uint16"}],"name":"estimateRewards","outputs":[{"internalType":"uint16","name":"startPeriod","type":"uint16"},{"internalType":"uint16","name":"periods","type":"uint16"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentCycle","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentPeriod","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"globalHistory","outputs":[{"internalType":"uint128","name":"stake","type":"uint128"},{"internalType":"uint128","name":"startCycle","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastGlobalSnapshotIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"lastStakerSnapshotIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nextClaims","outputs":[{"internalType":"uint16","name":"period","type":"uint16"},{"internalType":"uint64","name":"globalSnapshotIndex","type":"uint64"},{"internalType":"uint64","name":"stakerSnapshotIndex","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodLengthInCycles","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardsSchedule","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsTokenContract","outputs":[{"internalType":"contract IWrappedERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakerHistories","outputs":[{"internalType":"uint128","name":"stake","type":"uint128"},{"internalType":"uint128","name":"startCycle","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"start","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenInfos","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint64","name":"weight","type":"uint64"},{"internalType":"uint16","name":"depositCycle","type":"uint16"},{"internalType":"uint16","name":"withdrawCycle","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRewardsPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unstakeNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"weightsByRarity","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistedNftContract","outputs":[{"internalType":"contract IWhitelistedNftContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawRewardsPool","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101006040526000805460ff60a01b1916600160a01b1790553480156200002557600080fd5b5060405162002fee38038062002fee833981810160405260c08110156200004b57600080fd5b81516020830151604080850151606086015160808701805193519597949692959194919392820192846401000000008211156200008757600080fd5b9083019060208201858111156200009d57600080fd5b8251866020820283011164010000000082111715620000bb57600080fd5b82525081516020918201928201910280838360005b83811015620000ea578181015183820152602001620000d0565b50505050905001604052602001805160405193929190846401000000008211156200011457600080fd5b9083019060208201858111156200012a57600080fd5b82518660208202830111640100000000821117156200014857600080fd5b82525081516020918201928201910280838360005b83811015620001775781810151838201526020016200015d565b50505050919091016040819052600080546001600160a01b031916339081178255955085945092507f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091508290a35080518251146200021d576040805162461bcd60e51b815260206004820152601b60248201527f4e66745374616b696e673a2077726f6e6720617267756d656e74730000000000604482015290519081900360640190fd5b603c8663ffffffff1610156200027a576040805162461bcd60e51b815260206004820181905260248201527f4e66745374616b696e673a20696e76616c6964206379636c65206c656e677468604482015290519081900360640190fd5b60028561ffff161015620002c05760405162461bcd60e51b815260040180806020018281038252602181526020018062002fcd6021913960400191505060405180910390fd5b60e086811b6001600160e01b03191660c05260f086901b6001600160f01b0319169052606084811b6001600160601b031990811660a0529084901b1660805260005b825181101562000378578181815181106200031957fe5b6020026020010151600460008584815181106200033257fe5b6020026020010151815260200190815260200160002060006101000a8154816001600160401b0302191690836001600160401b0316021790555080600101905062000302565b5050505050505060805160601c60a05160601c60c05160e01c60e05160f01c612bd5620003f86000398061081e5280610863528061118852806115f752806118dd52806120bb5250806108d15280611de6525080610d285280610f615280612047525080610e5d5280610f3d52806112ac52806116f95250612bd56000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806373a3234611610104578063bc197c81116100a2578063e6fd48bc11610071578063e6fd48bc1461068d578063f23a6e6114610695578063f2fde38b1461072a578063f81649b414610750576101cf565b8063bc197c81146104f5578063be26ed7f14610657578063be9a65551461065f578063cc60fbf114610667576101cf565b80638da5cb5b116100de5780638da5cb5b146104a05780639de2e1cb146104c45780639e7cfd49146104cc578063a522bbaa146104d4576101cf565b806373a32346146104215780637b62e0401461043e5780637c13774b14610446576101cf565b8063238dafe0116101715780634fc5b8491161014b5780634fc5b8491461034d5780635a32502d1461036a57806369628952146103b05780636b42600014610404576101cf565b8063238dafe0146103335780632ef3ff6f1461033b5780632f2770db14610343576101cf565b8063086146d2116101ad578063086146d2146102805780630bc2b269146102885780630d2cb02a146102e35780632217f16514610304576101cf565b806301ffc9a7146101d45780630320d053146102275780630503c9bb14610246575b600080fd5b610213600480360360208110156101ea57600080fd5b50357fffffffff0000000000000000000000000000000000000000000000000000000016610781565b604080519115158252519081900360200190f35b61022f61081c565b6040805161ffff9092168252519081900360200190f35b6102636004803603602081101561025c57600080fd5b5035610840565b6040805167ffffffffffffffff9092168252519081900360200190f35b61022f61085c565b6102b46004803603604081101561029e57600080fd5b506001600160a01b03813516906020013561088c565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102eb6108cf565b6040805163ffffffff9092168252519081900360200190f35b6103216004803603602081101561031a57600080fd5b50356108f3565b60408051918252519081900360200190f35b610213610905565b610321610915565b61034b61091b565b005b6102b46004803603602081101561036357600080fd5b5035610975565b61038b6004803603602081101561038057600080fd5b503561ffff166109aa565b6040805161ffff94851681529290931660208301528183015290519081900360600190f35b6103d6600480360360208110156103c657600080fd5b50356001600160a01b0316610a72565b6040805161ffff909416845267ffffffffffffffff9283166020850152911682820152519081900360600190f35b61034b6004803603602081101561041a57600080fd5b5035610aab565b61034b6004803603602081101561043757600080fd5b5035610de8565b610321610e87565b6104636004803603602081101561045c57600080fd5b5035610ee8565b604080516001600160a01b03909516855267ffffffffffffffff909316602085015261ffff91821684840152166060830152519081900360800190f35b6104a8610f2c565b604080516001600160a01b039092168252519081900360200190f35b6104a8610f3b565b6104a8610f5f565b61034b600480360360208110156104ea57600080fd5b503561ffff16610f83565b610622600480360360a081101561050b57600080fd5b6001600160a01b03823581169260208101359091169181019060608101604082013564010000000081111561053f57600080fd5b82018360208201111561055157600080fd5b8035906020019184602083028401116401000000008311171561057357600080fd5b91939092909160208101903564010000000081111561059157600080fd5b8201836020820111156105a357600080fd5b803590602001918460208302840111640100000000831117156105c557600080fd5b9193909290916020810190356401000000008111156105e357600080fd5b8201836020820111156105f557600080fd5b8035906020019184600183028401116401000000008311171561061757600080fd5b50909250905061135d565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b61022f6113bc565b61034b6113c7565b6103216004803603602081101561067d57600080fd5b50356001600160a01b0316611454565b6103216114c9565b610622600480360360a08110156106ab57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a0810160808201356401000000008111156106eb57600080fd5b8201836020820111156106fd57600080fd5b8035906020019184600183028401116401000000008311171561071f57600080fd5b5090925090506114cf565b61034b6004803603602081101561074057600080fd5b50356001600160a01b0316611507565b61034b6004803603606081101561076657600080fd5b5061ffff81358116916020810135909116906040013561157d565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000148061081457507fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e000000000000000000000000000000000000000000000000000000000145b90505b919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60046020526000908152604090205467ffffffffffffffff1681565b60006108877f000000000000000000000000000000000000000000000000000000000000000061176d565b905090565b600560205281600052604060002081815481106108a857600080fd5b6000918252602090912001546001600160801b038082169350600160801b90910416905082565b7f000000000000000000000000000000000000000000000000000000000000000081565b60086020526000908152604090205481565b600054600160a01b900460ff1681565b60015481565b61092433611781565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1681556040517f75884cdadc4a89e8b545db800057f06ec7f5338a08183c7ba515f2bfdd9fe1e19190a1565b6003818154811061098557600080fd5b6000918252602090912001546001600160801b038082169250600160801b9091041682565b6000805481908190600160a01b900460ff166109f75760405162461bcd60e51b8152600401808060200182810382526023815260200180612b5a6023913960400191505060405180910390fd5b600254610a4b576040805162461bcd60e51b815260206004820152601f60248201527f4e66745374616b696e673a207374616b696e67206e6f74207374617274656400604482015290519081900360640190fd5b6000610a573386611845565b50805160208201516040909201519097919650945092505050565b60066020526000908152604090205461ffff81169067ffffffffffffffff6201000082048116916a010000000000000000000090041683565b600081815260076020908152604091829020825160808101845290546001600160a01b03811680835267ffffffffffffffff600160a01b8304169383019390935261ffff600160e01b8204811694830194909452600160f01b900490921660608301523314610b4b5760405162461bcd60e51b8152600401808060200182810382526035815260200180612a6b6035913960400191505060405180910390fd5b6000610b5642611dcc565b600054909150600160a01b900460ff1615610ce25760028260400151820361ffff161015610bcb576040805162461bcd60e51b815260206004820152601e60248201527f4e66745374616b696e673a20746f6b656e207374696c6c2066726f7a656e0000604482015290519081900360640190fd5b610be733836020015167ffffffffffffffff1660000383611e25565b600080835261ffff808316606085019081528583526007602090815260409384902086518154928801519588015193518516600160f01b027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94909516600160e01b027fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff67ffffffffffffffff909716600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff6001600160a01b03939093167fffffffffffffffffffffffff00000000000000000000000000000000000000009095169490941791909116929092179490941617161790555b604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810185905290516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916323b872dd91606480830192600092919082900301818387803b158015610d6f57600080fd5b505af1158015610d83573d6000803e3d6000fd5b5050506020808401516040805133815261ffff86169381019390935282810187905267ffffffffffffffff9091166060830152517fa809c38c1b1d8f31236741c657ba4d5b0c25cefab4c1cbc9a0ca5f96a774a15d92509081900360800190a1505050565b600054600160a01b900460ff1615610e47576040805162461bcd60e51b815260206004820152601f60248201527f4e66745374616b696e673a20636f6e747261637420697320656e61626c656400604482015290519081900360640190fd5b610e5033611781565b610e846001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383611f24565b50565b60035460009080610edf576040805162461bcd60e51b815260206004820181905260248201527f4e66745374616b696e673a20656d70747920676c6f62616c20686973746f7279604482015290519081900360640190fd5b60001901905090565b6007602052600090815260409020546001600160a01b0381169067ffffffffffffffff600160a01b8204169061ffff600160e01b8204811691600160f01b90041684565b6000546001600160a01b031690565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160a01b900460ff16610fcb5760405162461bcd60e51b8152600401808060200182810382526023815260200180612b5a6023913960400191505060405180910390fd5b60025461101f576040805162461bcd60e51b815260206004820152601f60248201527f4e66745374616b696e673a207374616b696e67206e6f74207374617274656400604482015290519081900360640190fd5b3360008181526006602090815260408083208151606081018352905461ffff8116825267ffffffffffffffff6201000082048116948301949094526a010000000000000000000090049092169082015291819061107c9085611845565b33600090815260056020526040902091935091505b816040015167ffffffffffffffff16846040015167ffffffffffffffff1610156110fd578084604001805180919060010167ffffffffffffffff1667ffffffffffffffff1681525067ffffffffffffffff16815481106110ed57fe5b6000918252602082200155611091565b602083015161ffff166111135750505050610e84565b3360009081526006602052604090205461ffff166111345750505050610e84565b80546000908290600019810190811061114957fe5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b909104168183018190529186015186519193507f00000000000000000000000000000000000000000000000000000000000000009101600019010261ffff169081108015906111ca575081516001600160801b0316155b156112095733600090815260066020526040902080547fffffffffffffffffffffffffffff00000000000000000000000000000000000016905561128f565b3360009081526006602090815260409182902086518154928801519388015161ffff1990931661ffff9091161769ffffffffffffffff000019166201000067ffffffffffffffff94851602177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a010000000000000000000093909216929092021790555b6040850151156112d45760408501516112d4906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016903390611f24565b7f5619b8583bbbb0760d27ac9ff844cec866b333bf7ad0262c2d809ff42f22e5fc336112ff42611dcc565b87600001518860200151896040015160405180866001600160a01b031681526020018561ffff1681526020018461ffff1681526020018361ffff1681526020018281526020019550505050505060405180910390a150505050505050565b6000805b8681101561138d5761138588888381811061137857fe5b905060200201358a611fa9565b600101611361565b507fbc197c81000000000000000000000000000000000000000000000000000000009998505050505050505050565b600061088742611dcc565b6002541561141c576040805162461bcd60e51b815260206004820152601f60248201527f4e66745374616b696e673a207374616b696e6720686173207374617274656400604482015290519081900360640190fd5b61142533611781565b426002556040517fd8cea0ecd56872ff072e771658b5682ffe4de16d752947f79597d600ea56f7a990600090a1565b6001600160a01b038116600090815260056020526040812054806114bf576040805162461bcd60e51b815260206004820181905260248201527f4e66745374616b696e673a20656d707479207374616b657220686973746f7279604482015290519081900360640190fd5b6000190192915050565b60025481565b60006114db8587611fa9565b507ff23a6e61000000000000000000000000000000000000000000000000000000009695505050505050565b61151761151261239f565b611781565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821780845560405192939116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b61158633611781565b61ffff8316158015906115a157508161ffff168361ffff1611155b6115f2576040805162461bcd60e51b815260206004820152601e60248201527f4e66745374616b696e673a2077726f6e6720706572696f642072616e67650000604482015290519081900360640190fd5b6002547f0000000000000000000000000000000000000000000000000000000000000000901561166b576116258161176d565b61ffff168461ffff16101561166b5760405162461bcd60e51b815260040180806020018281038252602d815260200180612b2d602d913960400191505060405180910390fd5b61ffff84165b8361ffff1681116116ac5760008181526008602052604090205461169590846123a3565b600082815260086020526040902055600101611671565b5060006116d985850360010161ffff166116d38461ffff168661240690919063ffffffff16565b90612406565b6001549091506116e990826123a3565b6001556117216001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633308461245f565b6040805161ffff80881682528616602082015280820185905290517fbff8d5ced955e6f69a19ecc71d313996f6ddfed652cdb458859af89e2f0768359181900360600190a15050505050565b600061081461177b42611dcc565b836124ed565b306001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156117ba57600080fd5b505afa1580156117ce573d6000803e3d6000fd5b505050506040513d60208110156117e457600080fd5b50516001600160a01b03828116911614610e84576040805162461bcd60e51b815260206004820152601660248201527f4f776e61626c653a206e6f7420746865206f776e657200000000000000000000604482015290519081900360640190fd5b61184d612a0d565b611855612a0d565b61ffff831661186357611dc5565b60035461186f57611dc5565b506001600160a01b0383166000908152600660209081526040918290208251606081018452905461ffff811680835267ffffffffffffffff6201000083048116948401949094526a0100000000000000000000909104909216928101929092528083526118db57611dc5565b7f000000000000000000000000000000000000000000000000000000000000000060006119078261176d565b90508061ffff16836000015161ffff161415611924575050611dc5565b6001600160a01b038616600090815260056020908152604080832080548251818502810185019093528083529192909190849084015b828210156119a357600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b909104168183015282526001909201910161195a565b50505050905060006003856020015167ffffffffffffffff16815481106119c657fe5b6000918252602080832060408051808201825293909101546001600160801b038082168552600160801b90910416918301919091528701518451919350849167ffffffffffffffff909116908110611a1a57fe5b60200260200101519050611a2c612a2d565b611a34612a2d565b600354602089015167ffffffffffffffff1660001990910114611aa7576003886020015160010167ffffffffffffffff1681548110611a6f57fe5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b909104169181019190915291505b6001855103886040015167ffffffffffffffff1614611ae85784886040015160010167ffffffffffffffff1681518110611add57fe5b602002602001015190505b875161ffff908703811660208b01819052908b161015611b0d5761ffff8a1660208a01525b602089015188510195505b8561ffff16886000015161ffff1614611dbd57875161ffff808216600090815260086020526040812054928a0260018181019493918c90030116905b8361ffff168114611da8578188602001516001600160801b03161115611b855787602001516001600160801b031691505b8187602001516001600160801b03161115611bab5786602001516001600160801b031691505b50602085015161ffff8416906001600160801b031615801590611bda57508086602001516001600160801b0316105b15611bef575060208501516001600160801b03165b87516001600160801b031615801590611c11575086516001600160801b031615155b8015611c1c57508215155b15611c76578651600090611c3f906001600160801b03166116d385850387612406565b89519091506001600160801b03168181611c5557fe5b049050611c6f818f604001516123a390919063ffffffff16565b60408f0152505b8086602001516001600160801b03161415611d245760208c01805160010167ffffffffffffffff169081905260035496985088966000190114611d0d5760038c6020015160010167ffffffffffffffff1681548110611cd157fe5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b90910416918101919091529550611d24565b604080518082019091526000808252602082015295505b8085602001516001600160801b03161415611da35760408c01805160010167ffffffffffffffff1690819052895195975087956000190114611d8c57888c6040015160010167ffffffffffffffff1681518110611d7d57fe5b60200260200101519450611da3565b604080518082019091526000808252602082015294505b611b54565b5050895160010161ffff168a5250611b189050565b505050505050505b9250929050565b60025460009080611de1576000915050610817565b611e1e7f000000000000000000000000000000000000000000000000000000000000000063ffffffff1682850381611e1557fe5b04600101612520565b9392505050565b6001600160a01b0383166000908152600560205260408120611e48908484612567565b90506000611e5860038585612567565b90507f6b53edb1a2d26a789b4466210277239d9ab872345e93a9f6028058e71e64c186858460056000896001600160a01b03166001600160a01b031681526020019081526020016000208581548110611ead57fe5b600091825260209091200154600380546001600160801b039092169186908110611ed357fe5b60009182526020918290200154604080516001600160a01b03909616865261ffff909416918501919091526001600160801b0391821684840152166060830152519081900360800190a15050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611fa490849061269f565b505050565b600054600160a01b900460ff16611ff15760405162461bcd60e51b8152600401808060200182810382526023815260200180612b5a6023913960400191505060405180910390fd5b600254612045576040805162461bcd60e51b815260206004820152601f60248201527f4e66745374616b696e673a207374616b696e67206e6f74207374617274656400604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146120ac5760405162461bcd60e51b8152600401808060200182810382526024815260200180612ae86024913960400191505060405180910390fd5b60006120b7836128a7565b90507f000000000000000000000000000000000000000000000000000000000000000060006120e542611dcc565b90506120fc848467ffffffffffffffff1683611e25565b6001600160a01b03841660009081526006602052604090205461ffff166121df57600061212982846124ed565b6040805160608101825261ffff92831681526003546000190167ffffffffffffffff908116602080840191825260008486018181526001600160a01b038d168252600690925294909420925183549151945161ffff1990921695169490941769ffffffffffffffff000019166201000093821693909302929092177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a01000000000000000000009390921692909202179055505b60008581526007602052604090205461ffff600160f01b909104811690821681141561223c5760405162461bcd60e51b8152600401808060200182810382526023815260200180612b7d6023913960400191505060405180910390fd5b6040518060800160405280866001600160a01b031681526020018567ffffffffffffffff1681526020018361ffff168152602001600061ffff168152506007600088815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550604082015181600001601c6101000a81548161ffff021916908361ffff160217905550606082015181600001601e6101000a81548161ffff021916908361ffff1602179055509050507f233fb303155fae76e94af13009e2c90416950cf561d3cd13f807618243feda4a8583888760405180856001600160a01b031681526020018461ffff1681526020018381526020018267ffffffffffffffff16815260200194505050505060405180910390a1505050505050565b3390565b6000828201838110156123fd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b60008261241557506000612400565b8282028284828161242257fe5b04146123fd5760405162461bcd60e51b8152600401808060200182810382526021815260200180612b0c6021913960400191505060405180910390fd5b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526124e790859061269f565b50505050565b600061ffff831661250057506000612400565b8161ffff166001840361ffff168161251457fe5b04600101905092915050565b60006201000082106125635760405162461bcd60e51b8152600401808060200182810382526026815260200180612a456026913960400191505060405180910390fd5b5090565b825460009081811561262057600182039250600086848154811061258757fe5b600091825260209091200180549091506125b7906125b2906001600160801b0316600f89900b61295e565b6129c3565b81549092506001600160801b03600160801b9091041661ffff861614156126145780547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001600160801b039290921691909117905550611e1e565b60018401935050612623565b50835b61262b612a2d565b6001600160801b03918216815261ffff851660208083019182528854600181018a5560008a81529190912092519201805491518416600160801b029284167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117909216179055509392505050565b816126b26001600160a01b038216612a07565b612703576040805162461bcd60e51b815260206004820152601a60248201527f4552433230577261707065723a206e6f6e2d636f6e7472616374000000000000604482015290519081900360640190fd5b600080826001600160a01b0316846040518082805190602001908083835b6020831061275e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612721565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146127c0576040519150601f19603f3d011682016040523d82523d6000602084013e6127c5565b606091505b509150915081156128445780511561283f578080602001905160208110156127ec57600080fd5b505161283f576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b6128a0565b8051612897576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b80518082602001fd5b5050505050565b600060ff82811c9060f084901c81169060e085901c81169060b086901c166001841480156128d55750826001145b80156128eb575081600214806128eb5750816003145b61293c576040805162461bcd60e51b815260206004820152601760248201527f4e66745374616b696e673a2077726f6e6720746f6b656e000000000000000000604482015290519081900360640190fd5b60009081526004602052604090205467ffffffffffffffff1695945050505050565b60008282018183128015906129735750838112155b80612988575060008312801561298857508381125b6123fd5760405162461bcd60e51b8152600401808060200182810382526021815260200180612ac76021913960400191505060405180910390fd5b6000600160801b82106125635760405162461bcd60e51b8152600401808060200182810382526027815260200180612aa06027913960400191505060405180910390fd5b3b151590565b604080516060810182526000808252602082018190529181019190915290565b60408051808201909152600080825260208201529056fe53616665436173743a2076616c756520646f65736e27742066697420696e20313620626974734e66745374616b696e673a20746f6b656e206e6f74207374616b6564206f7220696e636f727265637420746f6b656e206f776e657253616665436173743a2076616c756520646f65736e27742066697420696e2031323820626974735369676e6564536166654d6174683a206164646974696f6e206f766572666c6f774e66745374616b696e673a20636f6e7472616374206e6f742077686974656c6973746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774e66745374616b696e673a20616c726561647920636f6d6d697474656420726577617264207363686564756c654e66745374616b696e673a20636f6e7472616374206973206e6f7420656e61626c65644e66745374616b696e673a20756e7374616b656420746f6b656e20636f6f6c646f776ea2646970667358221220b1c0a0e4ef3d5f96b1736b9b878652f2eea164408081893d8cf27a77db2926a264736f6c634300070600334e66745374616b696e673a20696e76616c696420706572696f64206c656e6774680000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000002af75676692817d85121353f0d6e8e9ae6ad5576000000000000000000000000557b933a7c2c45672b610f8954a3deb39a51a8ca00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c806373a3234611610104578063bc197c81116100a2578063e6fd48bc11610071578063e6fd48bc1461068d578063f23a6e6114610695578063f2fde38b1461072a578063f81649b414610750576101cf565b8063bc197c81146104f5578063be26ed7f14610657578063be9a65551461065f578063cc60fbf114610667576101cf565b80638da5cb5b116100de5780638da5cb5b146104a05780639de2e1cb146104c45780639e7cfd49146104cc578063a522bbaa146104d4576101cf565b806373a32346146104215780637b62e0401461043e5780637c13774b14610446576101cf565b8063238dafe0116101715780634fc5b8491161014b5780634fc5b8491461034d5780635a32502d1461036a57806369628952146103b05780636b42600014610404576101cf565b8063238dafe0146103335780632ef3ff6f1461033b5780632f2770db14610343576101cf565b8063086146d2116101ad578063086146d2146102805780630bc2b269146102885780630d2cb02a146102e35780632217f16514610304576101cf565b806301ffc9a7146101d45780630320d053146102275780630503c9bb14610246575b600080fd5b610213600480360360208110156101ea57600080fd5b50357fffffffff0000000000000000000000000000000000000000000000000000000016610781565b604080519115158252519081900360200190f35b61022f61081c565b6040805161ffff9092168252519081900360200190f35b6102636004803603602081101561025c57600080fd5b5035610840565b6040805167ffffffffffffffff9092168252519081900360200190f35b61022f61085c565b6102b46004803603604081101561029e57600080fd5b506001600160a01b03813516906020013561088c565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102eb6108cf565b6040805163ffffffff9092168252519081900360200190f35b6103216004803603602081101561031a57600080fd5b50356108f3565b60408051918252519081900360200190f35b610213610905565b610321610915565b61034b61091b565b005b6102b46004803603602081101561036357600080fd5b5035610975565b61038b6004803603602081101561038057600080fd5b503561ffff166109aa565b6040805161ffff94851681529290931660208301528183015290519081900360600190f35b6103d6600480360360208110156103c657600080fd5b50356001600160a01b0316610a72565b6040805161ffff909416845267ffffffffffffffff9283166020850152911682820152519081900360600190f35b61034b6004803603602081101561041a57600080fd5b5035610aab565b61034b6004803603602081101561043757600080fd5b5035610de8565b610321610e87565b6104636004803603602081101561045c57600080fd5b5035610ee8565b604080516001600160a01b03909516855267ffffffffffffffff909316602085015261ffff91821684840152166060830152519081900360800190f35b6104a8610f2c565b604080516001600160a01b039092168252519081900360200190f35b6104a8610f3b565b6104a8610f5f565b61034b600480360360208110156104ea57600080fd5b503561ffff16610f83565b610622600480360360a081101561050b57600080fd5b6001600160a01b03823581169260208101359091169181019060608101604082013564010000000081111561053f57600080fd5b82018360208201111561055157600080fd5b8035906020019184602083028401116401000000008311171561057357600080fd5b91939092909160208101903564010000000081111561059157600080fd5b8201836020820111156105a357600080fd5b803590602001918460208302840111640100000000831117156105c557600080fd5b9193909290916020810190356401000000008111156105e357600080fd5b8201836020820111156105f557600080fd5b8035906020019184600183028401116401000000008311171561061757600080fd5b50909250905061135d565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b61022f6113bc565b61034b6113c7565b6103216004803603602081101561067d57600080fd5b50356001600160a01b0316611454565b6103216114c9565b610622600480360360a08110156106ab57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a0810160808201356401000000008111156106eb57600080fd5b8201836020820111156106fd57600080fd5b8035906020019184600183028401116401000000008311171561071f57600080fd5b5090925090506114cf565b61034b6004803603602081101561074057600080fd5b50356001600160a01b0316611507565b61034b6004803603606081101561076657600080fd5b5061ffff81358116916020810135909116906040013561157d565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000148061081457507fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e000000000000000000000000000000000000000000000000000000000145b90505b919050565b7f000000000000000000000000000000000000000000000000000000000000001c81565b60046020526000908152604090205467ffffffffffffffff1681565b60006108877f000000000000000000000000000000000000000000000000000000000000001c61176d565b905090565b600560205281600052604060002081815481106108a857600080fd5b6000918252602090912001546001600160801b038082169350600160801b90910416905082565b7f000000000000000000000000000000000000000000000000000000000001518081565b60086020526000908152604090205481565b600054600160a01b900460ff1681565b60015481565b61092433611781565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1681556040517f75884cdadc4a89e8b545db800057f06ec7f5338a08183c7ba515f2bfdd9fe1e19190a1565b6003818154811061098557600080fd5b6000918252602090912001546001600160801b038082169250600160801b9091041682565b6000805481908190600160a01b900460ff166109f75760405162461bcd60e51b8152600401808060200182810382526023815260200180612b5a6023913960400191505060405180910390fd5b600254610a4b576040805162461bcd60e51b815260206004820152601f60248201527f4e66745374616b696e673a207374616b696e67206e6f74207374617274656400604482015290519081900360640190fd5b6000610a573386611845565b50805160208201516040909201519097919650945092505050565b60066020526000908152604090205461ffff81169067ffffffffffffffff6201000082048116916a010000000000000000000090041683565b600081815260076020908152604091829020825160808101845290546001600160a01b03811680835267ffffffffffffffff600160a01b8304169383019390935261ffff600160e01b8204811694830194909452600160f01b900490921660608301523314610b4b5760405162461bcd60e51b8152600401808060200182810382526035815260200180612a6b6035913960400191505060405180910390fd5b6000610b5642611dcc565b600054909150600160a01b900460ff1615610ce25760028260400151820361ffff161015610bcb576040805162461bcd60e51b815260206004820152601e60248201527f4e66745374616b696e673a20746f6b656e207374696c6c2066726f7a656e0000604482015290519081900360640190fd5b610be733836020015167ffffffffffffffff1660000383611e25565b600080835261ffff808316606085019081528583526007602090815260409384902086518154928801519588015193518516600160f01b027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94909516600160e01b027fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff67ffffffffffffffff909716600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff6001600160a01b03939093167fffffffffffffffffffffffff00000000000000000000000000000000000000009095169490941791909116929092179490941617161790555b604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201523360248201526044810185905290516001600160a01b037f0000000000000000000000002af75676692817d85121353f0d6e8e9ae6ad557616916323b872dd91606480830192600092919082900301818387803b158015610d6f57600080fd5b505af1158015610d83573d6000803e3d6000fd5b5050506020808401516040805133815261ffff86169381019390935282810187905267ffffffffffffffff9091166060830152517fa809c38c1b1d8f31236741c657ba4d5b0c25cefab4c1cbc9a0ca5f96a774a15d92509081900360800190a1505050565b600054600160a01b900460ff1615610e47576040805162461bcd60e51b815260206004820152601f60248201527f4e66745374616b696e673a20636f6e747261637420697320656e61626c656400604482015290519081900360640190fd5b610e5033611781565b610e846001600160a01b037f000000000000000000000000557b933a7c2c45672b610f8954a3deb39a51a8ca163383611f24565b50565b60035460009080610edf576040805162461bcd60e51b815260206004820181905260248201527f4e66745374616b696e673a20656d70747920676c6f62616c20686973746f7279604482015290519081900360640190fd5b60001901905090565b6007602052600090815260409020546001600160a01b0381169067ffffffffffffffff600160a01b8204169061ffff600160e01b8204811691600160f01b90041684565b6000546001600160a01b031690565b7f000000000000000000000000557b933a7c2c45672b610f8954a3deb39a51a8ca81565b7f0000000000000000000000002af75676692817d85121353f0d6e8e9ae6ad557681565b600054600160a01b900460ff16610fcb5760405162461bcd60e51b8152600401808060200182810382526023815260200180612b5a6023913960400191505060405180910390fd5b60025461101f576040805162461bcd60e51b815260206004820152601f60248201527f4e66745374616b696e673a207374616b696e67206e6f74207374617274656400604482015290519081900360640190fd5b3360008181526006602090815260408083208151606081018352905461ffff8116825267ffffffffffffffff6201000082048116948301949094526a010000000000000000000090049092169082015291819061107c9085611845565b33600090815260056020526040902091935091505b816040015167ffffffffffffffff16846040015167ffffffffffffffff1610156110fd578084604001805180919060010167ffffffffffffffff1667ffffffffffffffff1681525067ffffffffffffffff16815481106110ed57fe5b6000918252602082200155611091565b602083015161ffff166111135750505050610e84565b3360009081526006602052604090205461ffff166111345750505050610e84565b80546000908290600019810190811061114957fe5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b909104168183018190529186015186519193507f000000000000000000000000000000000000000000000000000000000000001c9101600019010261ffff169081108015906111ca575081516001600160801b0316155b156112095733600090815260066020526040902080547fffffffffffffffffffffffffffff00000000000000000000000000000000000016905561128f565b3360009081526006602090815260409182902086518154928801519388015161ffff1990931661ffff9091161769ffffffffffffffff000019166201000067ffffffffffffffff94851602177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a010000000000000000000093909216929092021790555b6040850151156112d45760408501516112d4906001600160a01b037f000000000000000000000000557b933a7c2c45672b610f8954a3deb39a51a8ca16903390611f24565b7f5619b8583bbbb0760d27ac9ff844cec866b333bf7ad0262c2d809ff42f22e5fc336112ff42611dcc565b87600001518860200151896040015160405180866001600160a01b031681526020018561ffff1681526020018461ffff1681526020018361ffff1681526020018281526020019550505050505060405180910390a150505050505050565b6000805b8681101561138d5761138588888381811061137857fe5b905060200201358a611fa9565b600101611361565b507fbc197c81000000000000000000000000000000000000000000000000000000009998505050505050505050565b600061088742611dcc565b6002541561141c576040805162461bcd60e51b815260206004820152601f60248201527f4e66745374616b696e673a207374616b696e6720686173207374617274656400604482015290519081900360640190fd5b61142533611781565b426002556040517fd8cea0ecd56872ff072e771658b5682ffe4de16d752947f79597d600ea56f7a990600090a1565b6001600160a01b038116600090815260056020526040812054806114bf576040805162461bcd60e51b815260206004820181905260248201527f4e66745374616b696e673a20656d707479207374616b657220686973746f7279604482015290519081900360640190fd5b6000190192915050565b60025481565b60006114db8587611fa9565b507ff23a6e61000000000000000000000000000000000000000000000000000000009695505050505050565b61151761151261239f565b611781565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821780845560405192939116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b61158633611781565b61ffff8316158015906115a157508161ffff168361ffff1611155b6115f2576040805162461bcd60e51b815260206004820152601e60248201527f4e66745374616b696e673a2077726f6e6720706572696f642072616e67650000604482015290519081900360640190fd5b6002547f000000000000000000000000000000000000000000000000000000000000001c901561166b576116258161176d565b61ffff168461ffff16101561166b5760405162461bcd60e51b815260040180806020018281038252602d815260200180612b2d602d913960400191505060405180910390fd5b61ffff84165b8361ffff1681116116ac5760008181526008602052604090205461169590846123a3565b600082815260086020526040902055600101611671565b5060006116d985850360010161ffff166116d38461ffff168661240690919063ffffffff16565b90612406565b6001549091506116e990826123a3565b6001556117216001600160a01b037f000000000000000000000000557b933a7c2c45672b610f8954a3deb39a51a8ca1633308461245f565b6040805161ffff80881682528616602082015280820185905290517fbff8d5ced955e6f69a19ecc71d313996f6ddfed652cdb458859af89e2f0768359181900360600190a15050505050565b600061081461177b42611dcc565b836124ed565b306001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156117ba57600080fd5b505afa1580156117ce573d6000803e3d6000fd5b505050506040513d60208110156117e457600080fd5b50516001600160a01b03828116911614610e84576040805162461bcd60e51b815260206004820152601660248201527f4f776e61626c653a206e6f7420746865206f776e657200000000000000000000604482015290519081900360640190fd5b61184d612a0d565b611855612a0d565b61ffff831661186357611dc5565b60035461186f57611dc5565b506001600160a01b0383166000908152600660209081526040918290208251606081018452905461ffff811680835267ffffffffffffffff6201000083048116948401949094526a0100000000000000000000909104909216928101929092528083526118db57611dc5565b7f000000000000000000000000000000000000000000000000000000000000001c60006119078261176d565b90508061ffff16836000015161ffff161415611924575050611dc5565b6001600160a01b038616600090815260056020908152604080832080548251818502810185019093528083529192909190849084015b828210156119a357600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b909104168183015282526001909201910161195a565b50505050905060006003856020015167ffffffffffffffff16815481106119c657fe5b6000918252602080832060408051808201825293909101546001600160801b038082168552600160801b90910416918301919091528701518451919350849167ffffffffffffffff909116908110611a1a57fe5b60200260200101519050611a2c612a2d565b611a34612a2d565b600354602089015167ffffffffffffffff1660001990910114611aa7576003886020015160010167ffffffffffffffff1681548110611a6f57fe5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b909104169181019190915291505b6001855103886040015167ffffffffffffffff1614611ae85784886040015160010167ffffffffffffffff1681518110611add57fe5b602002602001015190505b875161ffff908703811660208b01819052908b161015611b0d5761ffff8a1660208a01525b602089015188510195505b8561ffff16886000015161ffff1614611dbd57875161ffff808216600090815260086020526040812054928a0260018181019493918c90030116905b8361ffff168114611da8578188602001516001600160801b03161115611b855787602001516001600160801b031691505b8187602001516001600160801b03161115611bab5786602001516001600160801b031691505b50602085015161ffff8416906001600160801b031615801590611bda57508086602001516001600160801b0316105b15611bef575060208501516001600160801b03165b87516001600160801b031615801590611c11575086516001600160801b031615155b8015611c1c57508215155b15611c76578651600090611c3f906001600160801b03166116d385850387612406565b89519091506001600160801b03168181611c5557fe5b049050611c6f818f604001516123a390919063ffffffff16565b60408f0152505b8086602001516001600160801b03161415611d245760208c01805160010167ffffffffffffffff169081905260035496985088966000190114611d0d5760038c6020015160010167ffffffffffffffff1681548110611cd157fe5b6000918252602091829020604080518082019091529101546001600160801b038082168352600160801b90910416918101919091529550611d24565b604080518082019091526000808252602082015295505b8085602001516001600160801b03161415611da35760408c01805160010167ffffffffffffffff1690819052895195975087956000190114611d8c57888c6040015160010167ffffffffffffffff1681518110611d7d57fe5b60200260200101519450611da3565b604080518082019091526000808252602082015294505b611b54565b5050895160010161ffff168a5250611b189050565b505050505050505b9250929050565b60025460009080611de1576000915050610817565b611e1e7f000000000000000000000000000000000000000000000000000000000001518063ffffffff1682850381611e1557fe5b04600101612520565b9392505050565b6001600160a01b0383166000908152600560205260408120611e48908484612567565b90506000611e5860038585612567565b90507f6b53edb1a2d26a789b4466210277239d9ab872345e93a9f6028058e71e64c186858460056000896001600160a01b03166001600160a01b031681526020019081526020016000208581548110611ead57fe5b600091825260209091200154600380546001600160801b039092169186908110611ed357fe5b60009182526020918290200154604080516001600160a01b03909616865261ffff909416918501919091526001600160801b0391821684840152166060830152519081900360800190a15050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611fa490849061269f565b505050565b600054600160a01b900460ff16611ff15760405162461bcd60e51b8152600401808060200182810382526023815260200180612b5a6023913960400191505060405180910390fd5b600254612045576040805162461bcd60e51b815260206004820152601f60248201527f4e66745374616b696e673a207374616b696e67206e6f74207374617274656400604482015290519081900360640190fd5b7f0000000000000000000000002af75676692817d85121353f0d6e8e9ae6ad55766001600160a01b031633146120ac5760405162461bcd60e51b8152600401808060200182810382526024815260200180612ae86024913960400191505060405180910390fd5b60006120b7836128a7565b90507f000000000000000000000000000000000000000000000000000000000000001c60006120e542611dcc565b90506120fc848467ffffffffffffffff1683611e25565b6001600160a01b03841660009081526006602052604090205461ffff166121df57600061212982846124ed565b6040805160608101825261ffff92831681526003546000190167ffffffffffffffff908116602080840191825260008486018181526001600160a01b038d168252600690925294909420925183549151945161ffff1990921695169490941769ffffffffffffffff000019166201000093821693909302929092177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a01000000000000000000009390921692909202179055505b60008581526007602052604090205461ffff600160f01b909104811690821681141561223c5760405162461bcd60e51b8152600401808060200182810382526023815260200180612b7d6023913960400191505060405180910390fd5b6040518060800160405280866001600160a01b031681526020018567ffffffffffffffff1681526020018361ffff168152602001600061ffff168152506007600088815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550604082015181600001601c6101000a81548161ffff021916908361ffff160217905550606082015181600001601e6101000a81548161ffff021916908361ffff1602179055509050507f233fb303155fae76e94af13009e2c90416950cf561d3cd13f807618243feda4a8583888760405180856001600160a01b031681526020018461ffff1681526020018381526020018267ffffffffffffffff16815260200194505050505060405180910390a1505050505050565b3390565b6000828201838110156123fd576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b60008261241557506000612400565b8282028284828161242257fe5b04146123fd5760405162461bcd60e51b8152600401808060200182810382526021815260200180612b0c6021913960400191505060405180910390fd5b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526124e790859061269f565b50505050565b600061ffff831661250057506000612400565b8161ffff166001840361ffff168161251457fe5b04600101905092915050565b60006201000082106125635760405162461bcd60e51b8152600401808060200182810382526026815260200180612a456026913960400191505060405180910390fd5b5090565b825460009081811561262057600182039250600086848154811061258757fe5b600091825260209091200180549091506125b7906125b2906001600160801b0316600f89900b61295e565b6129c3565b81549092506001600160801b03600160801b9091041661ffff861614156126145780547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001600160801b039290921691909117905550611e1e565b60018401935050612623565b50835b61262b612a2d565b6001600160801b03918216815261ffff851660208083019182528854600181018a5560008a81529190912092519201805491518416600160801b029284167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117909216179055509392505050565b816126b26001600160a01b038216612a07565b612703576040805162461bcd60e51b815260206004820152601a60248201527f4552433230577261707065723a206e6f6e2d636f6e7472616374000000000000604482015290519081900360640190fd5b600080826001600160a01b0316846040518082805190602001908083835b6020831061275e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612721565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146127c0576040519150601f19603f3d011682016040523d82523d6000602084013e6127c5565b606091505b509150915081156128445780511561283f578080602001905160208110156127ec57600080fd5b505161283f576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b6128a0565b8051612897576040805162461bcd60e51b815260206004820152601e60248201527f4552433230577261707065723a206f7065726174696f6e206661696c65640000604482015290519081900360640190fd5b80518082602001fd5b5050505050565b600060ff82811c9060f084901c81169060e085901c81169060b086901c166001841480156128d55750826001145b80156128eb575081600214806128eb5750816003145b61293c576040805162461bcd60e51b815260206004820152601760248201527f4e66745374616b696e673a2077726f6e6720746f6b656e000000000000000000604482015290519081900360640190fd5b60009081526004602052604090205467ffffffffffffffff1695945050505050565b60008282018183128015906129735750838112155b80612988575060008312801561298857508381125b6123fd5760405162461bcd60e51b8152600401808060200182810382526021815260200180612ac76021913960400191505060405180910390fd5b6000600160801b82106125635760405162461bcd60e51b8152600401808060200182810382526027815260200180612aa06027913960400191505060405180910390fd5b3b151590565b604080516060810182526000808252602082018190529181019190915290565b60408051808201909152600080825260208201529056fe53616665436173743a2076616c756520646f65736e27742066697420696e20313620626974734e66745374616b696e673a20746f6b656e206e6f74207374616b6564206f7220696e636f727265637420746f6b656e206f776e657253616665436173743a2076616c756520646f65736e27742066697420696e2031323820626974735369676e6564536166654d6174683a206164646974696f6e206f766572666c6f774e66745374616b696e673a20636f6e7472616374206e6f742077686974656c6973746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774e66745374616b696e673a20616c726561647920636f6d6d697474656420726577617264207363686564756c654e66745374616b696e673a20636f6e7472616374206973206e6f7420656e61626c65644e66745374616b696e673a20756e7374616b656420746f6b656e20636f6f6c646f776ea2646970667358221220b1c0a0e4ef3d5f96b1736b9b878652f2eea164408081893d8cf27a77db2926a264736f6c63430007060033

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

0000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000002af75676692817d85121353f0d6e8e9ae6ad5576000000000000000000000000557b933a7c2c45672b610f8954a3deb39a51a8ca00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001

-----Decoded View---------------
Arg [0] : cycleLengthInSeconds_ (uint32): 86400
Arg [1] : periodLengthInCycles_ (uint16): 28
Arg [2] : whitelistedNftContract_ (address): 0x2aF75676692817d85121353f0D6e8E9aE6AD5576
Arg [3] : rewardsTokenContract_ (address): 0x557B933a7C2c45672B610F8954A3deB39a51A8Ca
Arg [4] : rarities (uint256[]): 0,1,2,3,4,5,6,7,8,9
Arg [5] : weights (uint64[]): 480,60,12,12,2,2,2,1,1,1

-----Encoded View---------------
28 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000015180
Arg [1] : 000000000000000000000000000000000000000000000000000000000000001c
Arg [2] : 0000000000000000000000002af75676692817d85121353f0d6e8e9ae6ad5576
Arg [3] : 000000000000000000000000557b933a7c2c45672b610f8954a3deb39a51a8ca
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000220
Arg [6] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [17] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [18] : 00000000000000000000000000000000000000000000000000000000000001e0
Arg [19] : 000000000000000000000000000000000000000000000000000000000000003c
Arg [20] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [21] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [22] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [23] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [24] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [26] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [27] : 0000000000000000000000000000000000000000000000000000000000000001


Deployed Bytecode Sourcemap

29860:31091:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25659:215;;;;;;;;;;;;;;;;-1:-1:-1;25659:215:0;;;;:::i;:::-;;;;;;;;;;;;;;;;;;31905:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;31998:49;;;;;;;;;;;;;;;;-1:-1:-1;31998:49:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;45402:124;;;:::i;32086:53::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;32086:53:0;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;32086:53:0;;;;;;-1:-1:-1;;;;;32086:53:0;;;;;;;;;;;;;;;;31854:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;32362:50;;;;;;;;;;;;;;;;-1:-1:-1;32362:50:0;;:::i;:::-;;;;;;;;;;;;;;;;31611:26;;;:::i;31646:31::-;;;:::i;37634:126::-;;;:::i;:::-;;31958:31;;;;;;;;;;;;;;;;-1:-1:-1;31958:31:0;;:::i;42285:439::-;;;;;;;;;;;;;;;;-1:-1:-1;42285:439:0;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32180:47;;;;;;;;;;;;;;;;-1:-1:-1;32180:47:0;-1:-1:-1;;;;;32180:47:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40306:1344;;;;;;;;;;;;;;;;-1:-1:-1;40306:1344:0;;:::i;38195:180::-;;;;;;;;;;;;;;;;-1:-1:-1;38195:180:0;;:::i;45711:270::-;;;:::i;32269:47::-;;;;;;;;;;;;;;;;-1:-1:-1;32269:47:0;;:::i;:::-;;;;-1:-1:-1;;;;;32269:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28660:96;;;:::i;:::-;;;;-1:-1:-1;;;;;28660:96:0;;;;;;;;;;;;;;31724:51;;;:::i;31782:63::-;;;:::i;43360:1546::-;;;;;;;;;;;;;;;;-1:-1:-1;43360:1546:0;;;;:::i;38800:393::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;38800:393:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38800:393:0;;-1:-1:-1;38800:393:0;-1:-1:-1;38800:393:0;:::i;:::-;;;;;;;;;;;;;;;;;;;45160:110;;;:::i;37215:154::-;;;:::i;46166:294::-;;;;;;;;;;;;;;;;-1:-1:-1;46166:294:0;-1:-1:-1;;;;;46166:294:0;;:::i;31686:29::-;;;:::i;38505:287::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;38505:287:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38505:287:0;;-1:-1:-1;38505:287:0;-1:-1:-1;38505:287:0;:::i;29003:201::-;;;;;;;;;;;;;;;;-1:-1:-1;29003:201:0;-1:-1:-1;;;;;29003:201:0;;:::i;35878:1096::-;;;;;;;;;;;;;;;;-1:-1:-1;35878:1096:0;;;;;;;;;;;;;;;;;;:::i;25659:215::-;25744:4;25768:40;;;25783:25;25768:40;;:98;;-1:-1:-1;25812:54:0;;;25827:39;25812:54;25768:98;25761:105;;25659:215;;;;:::o;31905:44::-;;;:::o;31998:49::-;;;;;;;;;;;;;;;:::o;45402:124::-;45453:6;45479:39;45497:20;45479:17;:39::i;:::-;45472:46;;45402:124;:::o;32086:53::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;32086:53:0;;;;-1:-1:-1;;;;32086:53:0;;;;;-1:-1:-1;32086:53:0;:::o;31854:44::-;;;:::o;32362:50::-;;;;;;;;;;;;;:::o;31611:26::-;;;-1:-1:-1;;;31611:26:0;;;;;:::o;31646:31::-;;;;:::o;37634:126::-;37671:29;37689:10;37671:17;:29::i;:::-;37721:5;37711:15;;;;;;37742:10;;;;37721:5;37742:10;37634:126::o;31958:31::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;31958:31:0;;;;-1:-1:-1;;;;31958:31:0;;;;;:::o;42285:439::-;42432:18;32764:7;;42432:18;;;;-1:-1:-1;;;32764:7:0;;;;32756:55;;;;-1:-1:-1;;;32756:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32462:14:::1;::::0;32454:63:::1;;;::::0;;-1:-1:-1;;;32454:63:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;42537:26:::2;42569:39;42585:10;42597;42569:15;:39::i;:::-;-1:-1:-1::0;42633:17:0;;42671:13:::2;::::0;::::2;::::0;42704:12:::2;::::0;;::::2;::::0;42633:17;;42671:13;;-1:-1:-1;42704:12:0;-1:-1:-1;42285:439:0;-1:-1:-1;;;42285:439:0:o;32180:47::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;40306:1344::-;40363:26;40392:19;;;:10;:19;;;;;;;;;40363:48;;;;;;;;;-1:-1:-1;;;;;40363:48:0;;;;;;-1:-1:-1;;;40363:48:0;;;;;;;;;;;-1:-1:-1;;;40363:48:0;;;;;;;;;;;-1:-1:-1;;;40363:48:0;;;;;;;;;40503:10;40484:29;40476:95;;;;-1:-1:-1;;;40476:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40584:19;40606:26;40616:15;40606:9;:26::i;:::-;40649:7;;40584:48;;-1:-1:-1;;;;40649:7:0;;;;40645:832;;;40999:1;40973:9;:22;;;40958:12;:37;:42;;;;40950:85;;;;;-1:-1:-1;;;40950:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;41052:69;41069:10;41089:9;:16;;;41082:24;;41081:25;;41108:12;41052:16;:69::i;:::-;41264:1;41238:28;;;41379:38;;;;:23;;;:38;;;41434:19;;;:10;:19;;;;;;;;;:31;;;;;;;;;;;;;;;;-1:-1:-1;;;41434:31:0;;;;;;-1:-1:-1;;;41434:31:0;;;;;;-1:-1:-1;;;41434:31:0;;-1:-1:-1;;;;;41434:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40645:832;41489:71;;;;;;41533:4;41489:71;;;;41540:10;41489:71;;;;;;;;;;;;-1:-1:-1;;;;;41489:22:0;:35;;;;:71;;;;;-1:-1:-1;;41489:71:0;;;;;;;-1:-1:-1;41489:35:0;:71;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;41625:16:0;;;;;41578:64;;;41590:10;41578:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;41578:64:0;;;;;;;;40306:1344;;;:::o;38195:180::-;32883:7;;-1:-1:-1;;;32883:7:0;;;;32882:8;32874:52;;;;;-1:-1:-1;;;32874:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;38271:29:::1;38289:10;38271:17;:29::i;:::-;38311:56;-1:-1:-1::0;;;;;38311:20:0::1;:36;38348:10;38360:6:::0;38311:36:::1;:56::i;:::-;38195:180:::0;:::o;45711:270::-;45806:13;:20;45769:7;;45897:11;45889:56;;;;;-1:-1:-1;;;45889:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;45963:10:0;;-1:-1:-1;45711:270:0;:::o;32269:47::-;;;;;;;;;;;;-1:-1:-1;;;;;32269:47:0;;;;-1:-1:-1;;;32269:47:0;;;;;-1:-1:-1;;;32269:47:0;;;;;-1:-1:-1;;;32269:47:0;;;;:::o;28660:96::-;28715:7;28742:6;-1:-1:-1;;;;;28742:6:0;28660:96;:::o;31724:51::-;;;:::o;31782:63::-;;;:::o;43360:1546::-;32764:7;;-1:-1:-1;;;32764:7:0;;;;32756:55;;;;-1:-1:-1;;;32756:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32462:14:::1;::::0;32454:63:::1;;;::::0;;-1:-1:-1;;;32454:63:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;43482:10:::2;43442:26;43471:22:::0;;;:10:::2;:22;::::0;;;;;;;43442:51;;::::2;::::0;::::2;::::0;;;;::::2;::::0;::::2;::::0;;::::2;::::0;;::::2;::::0;::::2;::::0;;::::2;::::0;;;;;;::::2;::::0;;::::2;::::0;;;;;:26;;43568:39:::2;::::0;43596:10;43568:15:::2;:39::i;:::-;43736:10;43685:32;43720:27:::0;;;:15:::2;:27;::::0;;;;43506:101;;-1:-1:-1;43506:101:0;-1:-1:-1;43758:153:0::2;43797:12;:32;;;43765:64;;:9;:29;;;:64;;;43758:153;;;43853:13;43867:9;:29;;:31;;;;;;;;;;;;;::::0;43853:46:::2;;;;;;;;;;;::::0;;;::::2;::::0;;::::2;43846:53:::0;43758:153:::2;;;43927:13;::::0;::::2;::::0;:18:::2;;43923:57;;43962:7;;;;;;43923:57;44007:10;43996:22;::::0;;;:10:::2;:22;::::0;;;;:29;::::2;;43992:73;;44047:7;;;;;;43992:73;44128:20:::0;;44077:34:::2;::::0;44114:13;;-1:-1:-1;;44128:24:0;;;44114:39;::::2;;;;;;::::0;;;::::2;::::0;;;;44077:76:::2;::::0;;;;::::2;::::0;;;44114:39;::::2;44077:76:::0;-1:-1:-1;;;;;44077:76:0;;::::2;::::0;;-1:-1:-1;;;44077:76:0;;::::2;;::::0;;::::2;::::0;;;44214:13;;::::2;::::0;44194:17;;44077:76;;-1:-1:-1;44235:20:0::2;44194:33:::0;::::2;-1:-1:-1::0;;44194:37:0;44193:62:::2;44166:89;;::::0;44284:49;::::2;::::0;::::2;::::0;:141:::2;;-1:-1:-1::0;44396:24:0;;-1:-1:-1;;;;;44396:29:0::2;::::0;44284:141:::2;44266:389;;;44562:10;44551:22;::::0;;;:10:::2;:22;::::0;;;;44544:29;;;;;;44266:389:::2;;;44617:10;44606:22;::::0;;;:10:::2;:22;::::0;;;;;;;;:37;;;;;;::::2;::::0;;;::::2;::::0;-1:-1:-1;;44606:37:0;;::::2;;::::0;;::::2;;-1:-1:-1::0;;44606:37:0::2;::::0;::::2;::::0;;::::2;;;::::0;::::2;::::0;;;;::::2;::::0;;;::::2;;::::0;;44266:389:::2;44671:12;::::0;::::2;::::0;:17;44667:112:::2;;44754:12;::::0;::::2;::::0;44705:62:::2;::::0;-1:-1:-1;;;;;44705:20:0::2;:36;::::0;44742:10:::2;::::0;44705:36:::2;:62::i;:::-;44796:102;44811:10;44823:26;44833:15;44823:9;:26::i;:::-;44851:5;:17;;;44870:5;:13;;;44885:5;:12;;;44796:102;;;;-1:-1:-1::0;;;;;44796:102:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32528:1;;;;;;43360:1546:::0;:::o;38800:393::-;39035:6;;39054:91;39074:14;;;39054:91;;;39110:23;39120:3;;39124:1;39120:6;;;;;;;;;;;;;39128:4;39110:9;:23::i;:::-;39090:3;;39054:91;;;-1:-1:-1;39162:23:0;;38800:393;-1:-1:-1;;;;;;;;;38800:393:0:o;45160:110::-;45210:6;45236:26;45246:15;45236:9;:26::i;37215:154::-;32589:14;;:19;32581:63;;;;;-1:-1:-1;;;32581:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;37264:29:::1;37282:10;37264:17;:29::i;:::-;37321:15;37304:14;:32:::0;37352:9:::1;::::0;::::1;::::0;;;::::1;37215:154::o:0;46166:294::-;-1:-1:-1;;;;;46275:23:0;;46238:7;46275:23;;;:15;:23;;;;;:30;46376:11;46368:56;;;;;-1:-1:-1;;;46368:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;46442:10:0;;46166:294;-1:-1:-1;;46166:294:0:o;31686:29::-;;;;:::o;38505:287::-;38711:6;38730:19;38740:2;38744:4;38730:9;:19::i;:::-;-1:-1:-1;38767:17:0;38505:287;;;;;;;;:::o;29003:201::-;29083:31;29101:12;:10;:12::i;:::-;29083:17;:31::i;:::-;29125:6;:17;;;;-1:-1:-1;;;;;29125:17:0;;;;;;;;;29158:38;;29125:17;;29179:6;;;29158:38;;29125:6;29158:38;29003:201;:::o;35878:1096::-;36025:29;36043:10;36025:17;:29::i;:::-;36073:16;;;;;;;:44;;;36108:9;36093:24;;:11;:24;;;;36073:44;36065:87;;;;;-1:-1:-1;;;36065:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;36233:14;;36196:20;;36233:19;36229:221;;36348:40;36366:21;36348:17;:40::i;:::-;36333:55;;:11;:55;;;;36325:113;;;;-1:-1:-1;;;36325:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36467:28;;;36462:163;36507:9;36497:19;;:6;:19;36462:163;;36569:23;;;;:15;:23;;;;;;:44;;36597:15;36569:27;:44::i;:::-;36543:23;;;;:15;:23;;;;;:70;36518:8;;36462:163;;;;36637:20;36660:75;36719:11;36707:9;:23;36733:1;36707:27;36660:75;;:42;36680:21;36660:42;;:15;:19;;:42;;;;:::i;:::-;:46;;:75::i;:::-;36767:16;;36637:98;;-1:-1:-1;36767:34:0;;36637:98;36767:20;:34::i;:::-;36748:16;:53;36814:81;-1:-1:-1;;;;;36814:20:0;:40;36855:10;36875:4;36882:12;36814:40;:81::i;:::-;36913:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35878:1096;;;;;:::o;59217:175::-;59297:6;59323:61;59334:26;59344:15;59334:9;:26::i;:::-;59362:21;59323:10;:61::i;29335:138::-;29426:4;-1:-1:-1;;;;;29426:10:0;;:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;29426:12:0;-1:-1:-1;;;;;29415:23:0;;;;;;29407:58;;;;;-1:-1:-1;;;29407:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;49011:5685;49094:26;;:::i;:::-;49122;;:::i;:::-;49197:15;;;49193:73;;49229:25;;49193:73;49315:13;:20;49311:83;;49357:25;;49311:83;-1:-1:-1;;;;;;49418:18:0;;;;;;:10;:18;;;;;;;;;49406:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49447:36;;;49536:80;;49579:25;;49536:80;49659:20;49628:28;49714:40;49659:20;49714:17;:40::i;:::-;49690:64;;49835:14;49815:34;;:9;:16;;;:34;;;49811:92;;;49866:25;;;;49811:92;-1:-1:-1;;;;;50003:23:0;;49969:31;50003:23;;;:15;:23;;;;;;;;49969:57;;;;;;;;;;;;;;;;;;;50003:23;;49969:57;:31;;:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;49969:57:0;;;;;-1:-1:-1;;;49969:57:0;;;;;;;;;;;;;;;;;;;;;;;;;50039:30;50072:13;50086:9;:29;;;50072:44;;;;;;;;;;;;;;;;;;50039:77;;;;;;;;50072:44;;;;50039:77;-1:-1:-1;;;;;50039:77:0;;;;;-1:-1:-1;;;50039:77:0;;;;;;;;;;;50174:29;;;50160:44;;50039:77;;-1:-1:-1;50160:44:0;;;;;;;;;;;;;;;;;;;50127:77;;50215:34;;:::i;:::-;50260;;:::i;:::-;50344:13;:20;50311:29;;;;:57;;-1:-1:-1;;50344:24:0;;;50311:57;50307:159;;50406:13;50420:9;:29;;;50452:1;50420:33;50406:48;;;;;;;;;;;;;;;;;;;50385:69;;;;;;;;;50406:48;;50385:69;-1:-1:-1;;;;;50385:69:0;;;;;-1:-1:-1;;;50385:69:0;;;;;;;;;;;;-1:-1:-1;50307:159:0;50536:1;50513:13;:20;:24;50480:9;:29;;;:57;;;50476:159;;50575:13;50589:9;:29;;;50621:1;50589:33;50575:48;;;;;;;;;;;;;;;;50554:69;;50476:159;50720:16;;50687:49;50703:33;;;50687:49;;:13;;;:49;;;50753:26;;;;50749:85;;;50796:26;;;:13;;;:26;50749:85;51070:13;;;;51051:16;;:32;;-1:-1:-1;51129:3522:0;51156:14;51136:34;;:9;:16;;;:34;;;51129:3522;;51217:16;;51301:33;;;;51187:27;51301:33;;;:15;:33;;;;;;51217:40;;;51260:1;51217:44;;;;51301:33;51370:44;;;;;51349:65;;51512:3093;51531:20;51519:32;;:8;:32;51512:3093;;51799:10;51771:14;:25;;;-1:-1:-1;;;;;51771:38:0;;51767:125;;;51847:14;:25;;;-1:-1:-1;;;;;51834:38:0;;;51767:125;51942:10;51914:14;:25;;;-1:-1:-1;;;;;51914:38:0;;51910:125;;;51990:14;:25;;;-1:-1:-1;;;;;51977:38:0;;;51910:125;-1:-1:-1;52465:29:0;;;;52410:31;;;;-1:-1:-1;;;;;52465:34:0;;;;;52464:82;;;52537:8;52505:18;:29;;;-1:-1:-1;;;;;52505:40:0;;52464:82;52460:171;;;-1:-1:-1;52582:29:0;;;;-1:-1:-1;;;;;52571:40:0;52460:171;52784:20;;-1:-1:-1;;;;;52784:25:0;;;;;52783:58;;-1:-1:-1;52815:20:0;;-1:-1:-1;;;;;52815:25:0;;;52783:58;:83;;;;-1:-1:-1;52846:19:0;;;52783:83;52779:359;;;52964:20;;52891:22;;52916:69;;-1:-1:-1;;;;;52916:69:0;:43;52917:21;;;52944:14;52916:27;:43::i;:69::-;53026:20;;52891:94;;-1:-1:-1;;;;;;53008:38:0;52891:94;53008:38;;;;;;;;53086:32;53103:14;53086:5;:12;;;:16;;:32;;;;:::i;:::-;53071:12;;;:47;-1:-1:-1;52779:359:0;53423:8;53390:18;:29;;;-1:-1:-1;;;;;53390:41:0;;53386:478;;;53516:29;;;53514:31;;;;;;;;;;53607:13;:20;53473:18;;-1:-1:-1;53473:18:0;;-1:-1:-1;;53607:24:0;53574:57;53570:275;;53681:13;53695:9;:29;;;53727:1;53695:33;53681:48;;;;;;;;;;;;;;;;;;;53660:69;;;;;;;;;53681:48;;53660:69;-1:-1:-1;;;;;53660:69:0;;;;;-1:-1:-1;;;53660:69:0;;;;;;;;;;;;-1:-1:-1;53570:275:0;;;53807:14;;;;;;;;;-1:-1:-1;53807:14:0;;;;;;;;-1:-1:-1;53570:275:0;54149:8;54116:18;:29;;;-1:-1:-1;;;;;54116:41:0;;54112:478;;;54242:29;;;54240:31;;;;;;;;;;54333:20;;54199:18;;-1:-1:-1;54199:18:0;;-1:-1:-1;;54333:24:0;54300:57;54296:275;;54407:13;54421:9;:29;;;54453:1;54421:33;54407:48;;;;;;;;;;;;;;;;54386:69;;54296:275;;;54533:14;;;;;;;;;-1:-1:-1;54533:14:0;;;;;;;;-1:-1:-1;54296:275:0;51512:3093;;;-1:-1:-1;;54621:18:0;;;;;;;;-1:-1:-1;51129:3522:0;;-1:-1:-1;51129:3522:0;;54663:25;;;;;;;49011:5685;;;;;;:::o;58167:271::-;58273:14;;58228:6;;58302:20;58298:34;;58331:1;58324:8;;;;;58298:34;58350:80;58392:20;58384:29;;58365:15;58353:9;:27;58352:61;;;;;;58417:1;58351:67;58350:78;:80::i;:::-;58343:87;58167:271;-1:-1:-1;;;58167:271:0:o;55049:485::-;-1:-1:-1;;;;;55230:23:0;;55185:27;55230:23;;;:15;:23;;;;;55215:65;;55255:10;55267:12;55215:14;:65::i;:::-;55185:95;;55291:27;55321:55;55336:13;55351:10;55363:12;55321:14;:55::i;:::-;55291:85;;55394:132;55411:6;55419:12;55433:15;:23;55449:6;-1:-1:-1;;;;;55433:23:0;-1:-1:-1;;;;;55433:23:0;;;;;;;;;;;;55457:19;55433:44;;;;;;;;;;;;;;;;;:50;55485:13;:34;;-1:-1:-1;;;;;55433:50:0;;;;55499:19;;55485:34;;;;;;;;;;;;;;;;:40;55394:132;;;-1:-1:-1;;;;;55394:132:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;55394:132:0;;;;;;;55485:40;55394:132;;;;;;;;;;;;;55049:485;;;;;:::o;1907:229::-;2069:58;;;-1:-1:-1;;;;;2069:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2092:23;2069:58;;;2034:94;;2062:5;;2034:27;:94::i;:::-;1907:229;;;:::o;46987:1401::-;32764:7;;-1:-1:-1;;;32764:7:0;;;;32756:55;;;;-1:-1:-1;;;32756:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32462:14:::1;::::0;32454:63:::1;;;::::0;;-1:-1:-1;;;32454:63:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;47152:22:::2;-1:-1:-1::0;;;;;47144:45:0::2;47179:10;47144:45;47136:94;;;;-1:-1:-1::0;;;47136:94:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47243:13;47259:33;47284:7;47259:24;:33::i;:::-;47243:49:::0;-1:-1:-1;47336:20:0::2;47305:28;47389:26;47399:15;47389:9;:26::i;:::-;47367:48;;47428:58;47445:10;47464:6;47457:14;;47473:12;47428:16;:58::i;:::-;-1:-1:-1::0;;;;;47747:22:0;::::2;;::::0;;;:10:::2;:22;::::0;;;;:29;::::2;;47743:238;;47798:20;47821:47;47832:12;47846:21;47821:10;:47::i;:::-;47908:61;::::0;;::::2;::::0;::::2;::::0;;::::2;::::0;;::::2;::::0;;47940:13:::2;:20:::0;-1:-1:-1;;47940:24:0;47908:61:::2;::::0;;::::2;;::::0;;::::2;::::0;;;-1:-1:-1;47908:61:0;;;;;;-1:-1:-1;;;;;47883:22:0;::::2;::::0;;:10:::2;:22:::0;;;;;;;:86;;;;;;;;-1:-1:-1;;47883:86:0;;::::2;::::0;::::2;::::0;;;::::2;-1:-1:-1::0;;47883:86:0::2;::::0;;;::::2;::::0;;;::::2;::::0;;;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;::::2;;::::0;;-1:-1:-1;47743:238:0::2;47993:20;48016:19:::0;;;:10:::2;:19;::::0;;;;:33;::::2;-1:-1:-1::0;;;48016:33:0;;::::2;::::0;::::2;::::0;48120:29;::::2;::::0;::::2;;48112:77;;;;-1:-1:-1::0;;;48112:77:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48264:46;;;;;;;;48274:10;-1:-1:-1::0;;;;;48264:46:0::2;;;;;48286:6;48264:46;;;;;;48294:12;48264:46;;;;;;48308:1;48264:46;;;;::::0;48242:10:::2;:19;48253:7;48242:19;;;;;;;;;;;:68;;;;;;;;;;;;;-1:-1:-1::0;;;;;48242:68:0::2;;;;;-1:-1:-1::0;;;;;48242:68:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48328:52;48338:10;48350:12;48364:7;48373:6;48328:52;;;;-1:-1:-1::0;;;;;48328:52:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32528:1;;;;46987:1401:::0;;:::o;26302:106::-;26390:10;26302:106;:::o;13464:179::-;13522:7;13554:5;;;13578:6;;;;13570:46;;;;;-1:-1:-1;;;13570:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;13634:1;-1:-1:-1;13464:179:0;;;;;:::o;14343:220::-;14401:7;14425:6;14421:20;;-1:-1:-1;14440:1:0;14433:8;;14421:20;14464:5;;;14468:1;14464;:5;:1;14488:5;;;;;:10;14480:56;;;;-1:-1:-1;;;14480:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2144:266;2333:68;;;-1:-1:-1;;;;;2333:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2356:27;2333:68;;;2298:104;;2326:5;;2298:27;:104::i;:::-;2144:266;;;;:::o;58796:221::-;58883:6;58906:10;;;58902:51;;-1:-1:-1;58940:1:0;58933:8;;58902:51;58984:21;58970:35;;58979:1;58971:5;:9;58970:35;;;;;;;;59008:1;58970:39;58963:46;;58796:221;;;;:::o;6464:179::-;6520:6;6555:5;6547;:13;6539:65;;;;-1:-1:-1;;;6539:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6629:5:0;6464:179::o;56064:1691::-;56266:14;;56208:21;;;56329:18;;56325:1215;;56442:1;56426:13;:17;56410:33;;56458:26;56487:7;56495:13;56487:22;;;;;;;;;;;;;;;;;56555:15;;56487:22;;-1:-1:-1;56540:60:0;;56548:39;;-1:-1:-1;;;;;56555:15:0;56548:39;;;;:27;:39::i;:::-;56540:58;:60::i;:::-;56621:20;;56524:76;;-1:-1:-1;;;;;;;;;56621:20:0;;;;:36;;;;56617:221;;;56752:31;;;;-1:-1:-1;;;;;56752:31:0;;;;;;;;;;-1:-1:-1;56802:20:0;;56617:221;57062:1;57045:18;;;;56325:1215;;;;-1:-1:-1;57517:10:0;56325:1215;57552:25;;:::i;:::-;-1:-1:-1;;;;;57588:31:0;;;;;57630:35;;;:20;;;;:35;;;57724:23;;;;;;;57588:15;57724:23;;;;;;;;;;;;;;;;;-1:-1:-1;;;57724:23:0;;;;;;;;;;;;;;;;;;-1:-1:-1;56064:1691:0;;;;;:::o;2663:892::-;2789:5;2814:19;-1:-1:-1;;;;;2814:17:0;;;:19::i;:::-;2806:58;;;;;-1:-1:-1;;;2806:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;2938:12;2952:17;2973:6;-1:-1:-1;;;;;2973:11:0;2985:8;2973:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2937:57;;;;3009:7;3005:543;;;3037:11;;:16;3033:124;;3093:4;3082:24;;;;;;;;;;;;;;;-1:-1:-1;3082:24:0;3074:67;;;;;-1:-1:-1;;;3074:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;3005:543;;;3248:11;;3244:97;;3285:40;;;-1:-1:-1;;;3285:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;3244:97;3472:4;3466:11;3517:4;3510;3506:2;3502:13;3495:27;3435:102;2663:892;;;;;:::o;59788:1160::-;59860:6;60047:3;60038:12;;;;60096:3;60087:12;;;60086:21;;;60150:3;60141:12;;;60140:21;;;60204:3;60195:12;;;60194:21;60054:1;60788:16;;:34;;;;;60808:9;60821:1;60808:14;60788:34;:76;;;;;60827:11;60842:1;60827:16;:36;;;;60847:11;60862:1;60847:16;60827:36;60780:112;;;;;-1:-1:-1;;;60780:112:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;60912:28;;;;:15;:28;;;;;;;;;59788:1160;-1:-1:-1;;;;;59788:1160:0:o;20703:215::-;20759:6;20789:5;;;20814:6;;;;;;:16;;;20829:1;20824;:6;;20814:16;20813:38;;;;20840:1;20836;:5;:14;;;;;20849:1;20845;:5;20836:14;20805:84;;;;-1:-1:-1;;;20805:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5025:184;5082:7;-1:-1:-1;;;5110:5:0;:14;5102:67;;;;-1:-1:-1;;;5102:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1100:387;1423:20;1471:8;;;1100:387::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o

Swarm Source

ipfs://b1c0a0e4ef3d5f96b1736b9b878652f2eea164408081893d8cf27a77db2926a2

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

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.