ETH Price: $3,373.95 (-3.22%)
Gas: 5.84 Gwei

Token

Okay Humans NFT (OKHM)
 

Overview

Max Total Supply

3,333 OKHM

Holders

771

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
sergim.eth
Balance
1 OKHM
0x5f14AB8732b970fCbECEebC1449132042949E9Ac
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
OkayHumans

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-09-30
*/

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

// File: @openzeppelin/contracts/utils/structs/EnumerableSet.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

            return true;
        } else {
            return false;
        }
    }

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

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

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

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

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

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

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

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

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

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

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

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

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

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

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

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

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

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

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

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

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

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

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

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

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

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

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

        return result;
    }
}

// File: @openzeppelin/contracts/utils/Counters.sol


// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

// File: @openzeppelin/contracts/utils/cryptography/MerkleProof.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Calldata version of {verify}
     *
     * _Available since v4.7._
     */
    function verifyCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Calldata version of {processProof}
     *
     * _Available since v4.7._
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be proved to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and the sibling nodes in `proof`,
     * consuming from one or the other at each step according to the instructions given by
     * `proofFlags`.
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

// File: @openzeppelin/contracts/utils/Strings.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

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

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

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

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

// File: @openzeppelin/contracts/utils/Address.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

// File: @openzeppelin/contracts/utils/introspection/ERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;


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

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol


// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

// File: @openzeppelin/contracts/utils/Context.sol


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

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

// File: @openzeppelin/contracts/token/ERC721/ERC721.sol


// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;








/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: address zero is not a valid owner");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not token owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
        _safeTransfer(from, to, tokenId, data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

        _afterTokenTransfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.0;



/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return _ownedTokens[owner][index];
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _allTokens.length;
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
        return _allTokens[index];
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);

        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = ERC721.balanceOf(to);
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^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 Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// File: @openzeppelin/contracts/security/Pausable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;


/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// File: contracts/OkayHuman/OkayHumanNFT.sol



pragma solidity ^0.8.0;










contract OkayHumans is ReentrancyGuard, Pausable, ERC721Enumerable, Ownable, IERC721Receiver {
    using Counters for Counters.Counter;
    using Strings for uint256;
    using EnumerableSet for EnumerableSet.UintSet;

    /* ------------------------ NFT Minting ------------------------- */
    address payable private _PaymentAddress;
    address payable private _DevAddress;

    uint256 public MAX_SUPPLY = 3333;
    uint256 public FREE_SUPPLY = 888;
    uint256 public PUBLIC_PRICE = 0.033 ether;
    
    uint256 public PRESALE_MINT_LIMIT = 1;
    uint256 public PUBLIC_MINT_LIMIT = 20;
    
    bytes32 public _whitelistRoot;
    mapping (address => bool) public MAP_WHITELIST;
    mapping(address => uint256) public MAP_PRESALE_MINT_COUNT;
    mapping(address => uint256) public MAP_PUBLIC_MINT_COUNT;

    uint256 public SALE_STEP = 0; // 0: NONE, 1: PRSALE, 2: PUBLIC
    bool public _revealEnabled = false;
    
    string private _tokenBaseURI = "";
    string private _unrevealURI = "";
    
    Counters.Counter internal _publicCounter;

    /* ------------------------ NFT Staking ------------------------- */
    struct UserInfo {
        uint256 balance;
        uint256 rewards;
        uint256 lastUpdated;
    }
    mapping(address => UserInfo) public userInfo;
    mapping(address => EnumerableSet.UintSet) private userBlanaces;
    address[] public stakerList;

    IERC20 public rewardToken;
    uint256 public dailyTokenRewards = 0.5 ether;
    uint256 public minterTokenRewards = 300 ether;
    /* --------------------------------------------------------------------------------- */
    
    constructor(address _rewardToken, address _paymentAddress) ERC721("Okay Humans NFT", "OKHM") {
        _PaymentAddress = payable(_paymentAddress);
        _DevAddress = payable(msg.sender);
        rewardToken = IERC20(_rewardToken);
    }

    function setPaymentAddress(address paymentAddress) external onlyOwner {
        _PaymentAddress = payable(paymentAddress);
    }

    function setRewardToken(address rewardTokenAddress) external onlyOwner {
        rewardToken = IERC20(rewardTokenAddress);
    }

    function setRewardsAmount(uint256 dailyRewards, uint256 minterRewards) external onlyOwner {
        dailyTokenRewards = dailyRewards;
        minterTokenRewards = minterRewards;
    }

    function setSaleStep(uint256 _saleStep) external onlyOwner {
        SALE_STEP = _saleStep;
    }

    function setRevealEnabled(bool bEnable) external onlyOwner {
        _revealEnabled = bEnable;
    }

    function setWhiteListRoot(bytes32 root) external onlyOwner {
        _whitelistRoot = root;
    }

    function setWhiteList(address[] memory airdropAddress, bool bFlag) external onlyOwner {
        for (uint256 k = 0; k < airdropAddress.length; k++) {
            MAP_WHITELIST[airdropAddress[k]] = bFlag;
        }
    }

    // Verify that a given leaf is in the tree.
    function isWhiteListed(bytes32 _leafNode, bytes32[] memory proof) internal view returns (bool) {
        return MerkleProof.verify(proof, _whitelistRoot, _leafNode);
    }

    // Generate the leaf node (just the hash of tokenID concatenated with the account address)
    function toLeaf(address account, uint256 index, uint256 amount) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(index, account, amount));
    }

    function setMintPrice(uint256 publicMintPrice) external onlyOwner {
        PUBLIC_PRICE = publicMintPrice;
    }

    function setMaxSupply(uint256 maxSupply, uint256 freeSupply) external onlyOwner {
        MAX_SUPPLY = maxSupply;
        FREE_SUPPLY = freeSupply;
    }

    function setMintLimit(uint256 presaleMintLimit, uint256 publicMintLimit) external onlyOwner {
        PRESALE_MINT_LIMIT = presaleMintLimit;
        PUBLIC_MINT_LIMIT = publicMintLimit;
    }

    function setUnrevealURI(string memory unrevealURI) external onlyOwner {
        _unrevealURI = unrevealURI;
    }

    function setBaseURI(string memory baseURI) external onlyOwner {
        _tokenBaseURI = baseURI;
    }

    function airdrop(address[] memory airdropAddress, uint256 numberOfTokens) external onlyOwner {
        require(_publicCounter.current() + airdropAddress.length * numberOfTokens <= MAX_SUPPLY,"Purchase would exceed MAX_SUPPLY");

        for (uint256 k = 0; k < airdropAddress.length; k++) {
            for (uint256 i = 0; i < numberOfTokens; i++) {
                uint256 tokenId = _publicCounter.current();
                _publicCounter.increment();
                if (!_exists(tokenId)) {
                    _safeMint(airdropAddress[k], tokenId);
                }
            }
        }
    }

    function purchase(uint256 numberOfTokens) external payable {
        require(_publicCounter.current() + numberOfTokens <= MAX_SUPPLY,"Purchase would exceed MAX_SUPPLY");

        require(SALE_STEP == 2,"Public Mint is not activated.");

        require(PUBLIC_PRICE * numberOfTokens <= msg.value,"ETH amount is not sufficient");

        MAP_PUBLIC_MINT_COUNT[_msgSender()] = MAP_PUBLIC_MINT_COUNT[_msgSender()] + numberOfTokens;
        
        require(MAP_PUBLIC_MINT_COUNT[_msgSender()] <= PUBLIC_MINT_LIMIT,"Overflow for PUBLIC_MINT_LIMIT");

        uint256 devFee = msg.value / 20;
        _DevAddress.transfer(devFee);
        _PaymentAddress.transfer(msg.value - devFee);
        
        for (uint256 i = 0; i < numberOfTokens; i++) {
            uint256 tokenId = _publicCounter.current();
            _publicCounter.increment();
            if (!_exists(tokenId)) {
                _safeMint(_msgSender(), tokenId);
            }
        }

        rewardToken.transfer(_msgSender(), numberOfTokens * minterTokenRewards);
    }

    function presale(uint256 numberOfTokens, uint256 index, uint256 amount, bytes32[] calldata proof) external {
        require(_publicCounter.current() + numberOfTokens <= FREE_SUPPLY,"Purchase would exceed FREE_SUPPLY");

        require(isWhiteListed(toLeaf(_msgSender(), index, amount), proof) || MAP_WHITELIST[_msgSender()], "Invalid proof");

        require(SALE_STEP == 1,"Presale Round is not activated.");

        MAP_PRESALE_MINT_COUNT[_msgSender()] = MAP_PRESALE_MINT_COUNT[_msgSender()] + numberOfTokens;
        
        require(MAP_PRESALE_MINT_COUNT[_msgSender()] <= PRESALE_MINT_LIMIT,"Overflow for PRESALE_MINT_LIMIT");

        for (uint256 i = 0; i < numberOfTokens; i++) {
            uint256 tokenId = _publicCounter.current();
            _publicCounter.increment();
            if (!_exists(tokenId)) {
                _safeMint(_msgSender(), tokenId);
            }
        }

        rewardToken.transfer(_msgSender(), numberOfTokens * minterTokenRewards);
    }

    function tokenURI(uint256 tokenId) public view override(ERC721) returns (string memory) {
        require(_exists(tokenId), "Token does not exist");

        if (_revealEnabled) {
            return string(abi.encodePacked(_tokenBaseURI, tokenId.toString()));
        }

        return _unrevealURI;
    }

    function withdraw() external onlyOwner {
        uint256 balance = address(this).balance;
        payable(_msgSender()).transfer(balance);
    }

    function withdrawToken() external onlyOwner {
        uint256 balance = rewardToken.balanceOf(address(this));
        rewardToken.transfer(_msgSender(), balance);
    }

    function userHoldNFTs(address _owner) public view returns(uint256[] memory){
        uint256 tokenCount = balanceOf(_owner);
        uint256[] memory result = new uint256[](tokenCount);
        for (uint256 index = 0; index < tokenCount; index++) {
            result[index] = tokenOfOwnerByIndex(_owner, index);
        }
        return result;
    }

    /* --------------------------------------------------------------------- */
    function addStakerList(address _user) internal{
        for (uint256 i = 0; i < stakerList.length; i++) {
            if (stakerList[i] == _user)
                return;
        }
        stakerList.push(_user);
    }

    function userStakeInfo(address _owner) external view returns(UserInfo memory){
         return userInfo[_owner];
    }
    
    function userStakedNFTs(address _owner) public view returns(uint256[] memory){
        uint256 tokenCount = userBlanaces[_owner].length();
        uint256[] memory result = new uint256[](tokenCount);
        for (uint256 index = 0; index < tokenCount; index++) {
            result[index] = userBlanaces[_owner].at(index);
        }
        return result;
    }

    function userStakedNFTCount(address _owner) public view returns(uint256){
         return userBlanaces[_owner].length();
    }

    function isStaked( address account ,uint256 tokenId) public view returns (bool) {
        return userBlanaces[account].contains(tokenId);
    }

    function earned(address account) public view returns (uint256) {
        uint256 blockTime = block.timestamp;

        UserInfo memory user = userInfo[account];

        uint256 amount = (blockTime - user.lastUpdated) * userStakedNFTCount(account) * dailyTokenRewards / 1 days;

        return user.rewards + amount;
    }

    function totalEarned() public view returns (uint256) {
        uint256 totalEarning = 0;
        for (uint256 i = 0; i < stakerList.length; i++) {
            totalEarning += earned(stakerList[i]);
        }
        return totalEarning;
    }

    function totalStakedCount() public view returns (uint256) {
        uint256 totalCount = 0;
        for (uint256 i = 0; i < stakerList.length; i++) {
            totalCount += userStakedNFTCount(stakerList[i]);
        }
        return totalCount;
    }

    function totalStakedMembers() public view returns (uint256) {
        uint256 totalMembers = 0;
        for (uint256 i = 0; i < stakerList.length; i++) {
            if (userStakedNFTCount(stakerList[i]) > 0) totalMembers += 1;
        }
        return totalMembers;
    }

    function stake( uint256[] memory  tokenIdList) public nonReentrant whenNotPaused {
        UserInfo storage user = userInfo[_msgSender()];
        user.rewards = earned(_msgSender());
        user.lastUpdated = block.timestamp;

        addStakerList(_msgSender());

        for (uint256 i = 0; i < tokenIdList.length; i++) {
            safeTransferFrom(_msgSender(), address(this), tokenIdList[i]);

            userBlanaces[_msgSender()].add(tokenIdList[i]);
        }
    }

    function unstake( uint256[] memory  tokenIdList) public nonReentrant {
        UserInfo storage user = userInfo[_msgSender()];
        user.rewards = earned(_msgSender());
        user.lastUpdated = block.timestamp;

        for (uint256 i = 0; i < tokenIdList.length; i++) {

            require(isStaked(_msgSender(), tokenIdList[i]), "Not staked this nft");        

            _safeTransfer(address(this) , _msgSender(), tokenIdList[i], "");

            userBlanaces[_msgSender()].remove(tokenIdList[i]);
        }
    }

    function harvest() public nonReentrant {
        require(earned(_msgSender()) > 0, "Nothing Rewards");
        
        rewardToken.transfer(_msgSender(), earned(_msgSender()));

        UserInfo storage user = userInfo[_msgSender()];
        user.rewards = 0;
        user.lastUpdated = block.timestamp;
    }

    function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
        return this.onERC721Received.selector;
    }

    receive() external payable {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_rewardToken","type":"address"},{"internalType":"address","name":"_paymentAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","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":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"FREE_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"MAP_PRESALE_MINT_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"MAP_PUBLIC_MINT_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"MAP_WHITELIST","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRESALE_MINT_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_MINT_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SALE_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_revealEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_whitelistRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"airdropAddress","type":"address[]"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dailyTokenRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isStaked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterTokenRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"presale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"purchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"freeSupply","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"presaleMintLimit","type":"uint256"},{"internalType":"uint256","name":"publicMintLimit","type":"uint256"}],"name":"setMintLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"publicMintPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"paymentAddress","type":"address"}],"name":"setPaymentAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"bEnable","type":"bool"}],"name":"setRevealEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rewardTokenAddress","type":"address"}],"name":"setRewardToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"dailyRewards","type":"uint256"},{"internalType":"uint256","name":"minterRewards","type":"uint256"}],"name":"setRewardsAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_saleStep","type":"uint256"}],"name":"setSaleStep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"unrevealURI","type":"string"}],"name":"setUnrevealURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"airdropAddress","type":"address[]"},{"internalType":"bool","name":"bFlag","type":"bool"}],"name":"setWhiteList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"setWhiteListRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIdList","type":"uint256[]"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakerList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalEarned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedMembers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIdList","type":"uint256[]"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"userHoldNFTs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"rewards","type":"uint256"},{"internalType":"uint256","name":"lastUpdated","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"userStakeInfo","outputs":[{"components":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"rewards","type":"uint256"},{"internalType":"uint256","name":"lastUpdated","type":"uint256"}],"internalType":"struct OkayHumans.UserInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"userStakedNFTCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"userStakedNFTs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

610d05600f5561037860105566753d533d96800060115560016012556014601355600060188190556019805460ff1916905560a06040526080908152601a906200004a908262000278565b50604080516020810190915260008152601b9062000069908262000278565b506706f05b59d3b20000602155681043561a88293000006022553480156200009057600080fd5b5060405162003f6738038062003f67833981016040819052620000b39162000361565b604080518082018252600f81526e13dad85e48121d5b585b9cc8139195608a1b602080830191909152825180840190935260048352634f4b484d60e01b9083015260016000819055805460ff1916905590600262000112838262000278565b50600362000121828262000278565b5050506200013e620001386200017d60201b60201c565b62000181565b600d80546001600160a01b039283166001600160a01b031991821617909155600e80548216331790556020805493909216921691909117905562000399565b3390565b600c80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620001fe57607f821691505b6020821081036200021f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200027357600081815260208120601f850160051c810160208610156200024e5750805b601f850160051c820191505b818110156200026f578281556001016200025a565b5050505b505050565b81516001600160401b03811115620002945762000294620001d3565b620002ac81620002a58454620001e9565b8462000225565b602080601f831160018114620002e45760008415620002cb5750858301515b600019600386901b1c1916600185901b1785556200026f565b600085815260208120601f198616915b828110156200031557888601518255948401946001909101908401620002f4565b5085821015620003345787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516001600160a01b03811681146200035c57600080fd5b919050565b600080604083850312156200037557600080fd5b620003808362000344565b9150620003906020840162000344565b90509250929050565b613bbe80620003a96000396000f3fe6080604052600436106103dc5760003560e01c80636dfa8d99116101fd578063b88d4fde11610118578063e43f696e116100ab578063f2fde38b1161007a578063f2fde38b14610bd4578063f4a0a52814610bf4578063f5ebec8014610c14578063f7c618c114610c2a578063ff01f73614610c4a57600080fd5b8063e43f696e14610b38578063e449f34114610b58578063e985e9c514610b78578063efef39a114610bc157600080fd5b8063c87b56dd116100e7578063c87b56dd14610ac3578063ca628c7814610ae3578063cd0559eb14610af8578063d05611f714610b1857600080fd5b8063b88d4fde14610a4d578063bb7850f014610a6d578063bceae77b14610a8d578063c204642c14610aa357600080fd5b806384b9a4a51161019057806395d89b411161015f57806395d89b41146109e257806397bc411c146109f75780639858cf1914610a17578063a22cb46514610a2d57600080fd5b806384b9a4a5146109795780638aee81271461098f5780638da5cb5b146109af578063920387b4146109cd57600080fd5b806370a08231116101cc57806370a082311461090e578063715018a61461092e578063799efeaa14610943578063848da3b91461095957600080fd5b80636dfa8d99146108a35780636f3a43c4146108b85780636fad40d5146108ce578063709182a9146108ee57600080fd5b8063348e50c6116102f85780634ead43271161028b57806355f804b31161025a57806355f804b3146108155780635c975abb146108355780635e1e10041461084d578063611f3f101461086d5780636352211e1461088357600080fd5b80634ead4327146107735780634f6ccce7146107b557806353e90cbd146107d55780635451da1b146107f557600080fd5b806344f9f627116102c757806344f9f627146106e157806345149bb31461070e5780634641257d1461072e5780634d861e821461074357600080fd5b8063348e50c61461066c57806337da577c1461068c5780633ccfd60b146106ac57806342842e0e146106c157600080fd5b80631959a002116103705780632b691f221161033f5780632b691f22146105f35780632eb48656146106205780632f745c591461063657806332cb6b0c1461065657600080fd5b80631959a002146105355780631d95fa561461058c57806323b872dd146105a657806323eeb661146105c657600080fd5b8063095ea7b3116103ac578063095ea7b3146104a55780630fbf0a93146104c7578063150b7a02146104e757806318160ddd1461052057600080fd5b80628cc262146103e857806301ffc9a71461041b57806306fdde031461044b578063081812fc1461046d57600080fd5b366103e357005b600080fd5b3480156103f457600080fd5b506104086104033660046131c2565b610c5f565b6040519081526020015b60405180910390f35b34801561042757600080fd5b5061043b6104363660046131f3565b610cf8565b6040519015158152602001610412565b34801561045757600080fd5b50610460610d23565b6040516104129190613260565b34801561047957600080fd5b5061048d610488366004613273565b610db5565b6040516001600160a01b039091168152602001610412565b3480156104b157600080fd5b506104c56104c036600461328c565b610ddc565b005b3480156104d357600080fd5b506104c56104e236600461331f565b610ef6565b3480156104f357600080fd5b5061050761050236600461340b565b610fe6565b6040516001600160e01b03199091168152602001610412565b34801561052c57600080fd5b50600a54610408565b34801561054157600080fd5b506105716105503660046131c2565b601d6020526000908152604090208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610412565b34801561059857600080fd5b5060195461043b9060ff1681565b3480156105b257600080fd5b506104c56105c1366004613486565b610ff7565b3480156105d257600080fd5b506104086105e13660046131c2565b60176020526000908152604090205481565b3480156105ff57600080fd5b5061040861060e3660046131c2565b60166020526000908152604090205481565b34801561062c57600080fd5b5061040860145481565b34801561064257600080fd5b5061040861065136600461328c565b611028565b34801561066257600080fd5b50610408600f5481565b34801561067857600080fd5b5061048d610687366004613273565b6110be565b34801561069857600080fd5b506104c56106a73660046134c2565b6110e8565b3480156106b857600080fd5b506104c56110fb565b3480156106cd57600080fd5b506104c56106dc366004613486565b611136565b3480156106ed57600080fd5b506107016106fc3660046131c2565b611151565b60405161041291906134e4565b34801561071a57600080fd5b506104c5610729366004613273565b611222565b34801561073a57600080fd5b506104c561122f565b34801561074f57600080fd5b5061043b61075e3660046131c2565b60156020526000908152604090205460ff1681565b34801561077f57600080fd5b5061079361078e3660046131c2565b611350565b6040805182518152602080840151908201529181015190820152606001610412565b3480156107c157600080fd5b506104086107d0366004613273565b6113b6565b3480156107e157600080fd5b506104c56107f0366004613273565b611449565b34801561080157600080fd5b5061043b61081036600461328c565b611456565b34801561082157600080fd5b506104c5610830366004613528565b61147f565b34801561084157600080fd5b5060015460ff1661043b565b34801561085957600080fd5b506104c56108683660046131c2565b611493565b34801561087957600080fd5b5061040860115481565b34801561088f57600080fd5b5061048d61089e366004613273565b6114bd565b3480156108af57600080fd5b5061040861151d565b3480156108c457600080fd5b5061040860225481565b3480156108da57600080fd5b506104c56108e93660046134c2565b611580565b3480156108fa57600080fd5b506107016109093660046131c2565b611593565b34801561091a57600080fd5b506104086109293660046131c2565b61162c565b34801561093a57600080fd5b506104c56116b2565b34801561094f57600080fd5b5061040860215481565b34801561096557600080fd5b506104c5610974366004613570565b6116c6565b34801561098557600080fd5b5061040860185481565b34801561099b57600080fd5b506104c56109aa3660046131c2565b6119c2565b3480156109bb57600080fd5b50600c546001600160a01b031661048d565b3480156109d957600080fd5b506104086119ec565b3480156109ee57600080fd5b50610460611a49565b348015610a0357600080fd5b506104c5610a12366004613528565b611a58565b348015610a2357600080fd5b5061040860105481565b348015610a3957600080fd5b506104c5610a4836600461360d565b611a6c565b348015610a5957600080fd5b506104c5610a6836600461340b565b611a77565b348015610a7957600080fd5b506104c5610a883660046134c2565b611aaf565b348015610a9957600080fd5b5061040860135481565b348015610aaf57600080fd5b506104c5610abe3660046136b1565b611ac2565b348015610acf57600080fd5b50610460610ade366004613273565b611bbd565b348015610aef57600080fd5b506104c5611cda565b348015610b0457600080fd5b50610408610b133660046131c2565b611dd5565b348015610b2457600080fd5b506104c5610b333660046136f5565b611df6565b348015610b4457600080fd5b506104c5610b53366004613712565b611e11565b348015610b6457600080fd5b506104c5610b7336600461331f565b611e80565b348015610b8457600080fd5b5061043b610b93366004613758565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b6104c5610bcf366004613273565b611fcb565b348015610be057600080fd5b506104c5610bef3660046131c2565b6122c6565b348015610c0057600080fd5b506104c5610c0f366004613273565b61233f565b348015610c2057600080fd5b5061040860125481565b348015610c3657600080fd5b5060205461048d906001600160a01b031681565b348015610c5657600080fd5b5061040861234c565b6001600160a01b0381166000908152601d60209081526040808320815160608101835281548152600182015493810193909352600201549082015260215442919083906201518090610cb087611dd5565b6040850151610cbf90876137a1565b610cc991906137b4565b610cd391906137b4565b610cdd91906137e1565b9050808260200151610cef91906137f5565b95945050505050565b60006001600160e01b0319821663780e9d6360e01b1480610d1d5750610d1d82612399565b92915050565b606060028054610d3290613808565b80601f0160208091040260200160405190810160405280929190818152602001828054610d5e90613808565b8015610dab5780601f10610d8057610100808354040283529160200191610dab565b820191906000526020600020905b815481529060010190602001808311610d8e57829003601f168201915b5050505050905090565b6000610dc0826123e9565b506000908152600660205260409020546001600160a01b031690565b6000610de7826114bd565b9050806001600160a01b0316836001600160a01b031603610e595760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610e755750610e758133610b93565b610ee75760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610e50565b610ef18383612439565b505050565b600260005403610f185760405162461bcd60e51b8152600401610e509061383c565b6002600055610f256124a7565b336000818152601d6020526040902090610f3e90610c5f565b6001820155426002820155610f52336124ed565b60005b8251811015610fdc57610f823330858481518110610f7557610f75613873565b6020026020010151611136565b610fc9838281518110610f9757610f97613873565b6020026020010151601e6000610faa3390565b6001600160a01b0316815260208101919091526040016000209061259a565b5080610fd481613889565b915050610f55565b5050600160005550565b630a85bd0160e11b5b949350505050565b61100133826125a6565b61101d5760405162461bcd60e51b8152600401610e50906138a2565b610ef1838383612624565b60006110338361162c565b82106110955760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610e50565b506001600160a01b03919091166000908152600860209081526040808320938352929052205490565b601f81815481106110ce57600080fd5b6000918252602090912001546001600160a01b0316905081565b6110f06127cb565b600f91909155601055565b6111036127cb565b6040514790339082156108fc029083906000818181858888f19350505050158015611132573d6000803e3d6000fd5b5050565b610ef183838360405180602001604052806000815250611a77565b6001600160a01b0381166000908152601e602052604081206060919061117690612825565b90506000816001600160401b03811115611192576111926132b6565b6040519080825280602002602001820160405280156111bb578160200160208202803683370190505b50905060005b8281101561121a576001600160a01b0385166000908152601e602052604090206111eb908261282f565b8282815181106111fd576111fd613873565b60209081029190910101528061121281613889565b9150506111c1565b509392505050565b61122a6127cb565b601455565b6002600054036112515760405162461bcd60e51b8152600401610e509061383c565b6002600090815561126133610c5f565b116112a05760405162461bcd60e51b815260206004820152600f60248201526e4e6f7468696e67205265776172647360881b6044820152606401610e50565b6020546001600160a01b031663a9059cbb336112bb33610c5f565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611306573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132a91906138f0565b50336000908152601d602052604081206001808201839055426002909201919091559055565b61137460405180606001604052806000815260200160008152602001600081525090565b506001600160a01b03166000908152601d6020908152604091829020825160608101845281548152600182015492810192909252600201549181019190915290565b60006113c1600a5490565b82106114245760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610e50565b600a828154811061143757611437613873565b90600052602060002001549050919050565b6114516127cb565b601855565b6001600160a01b0382166000908152601e60205260408120611478908361283b565b9392505050565b6114876127cb565b601a6111328282613953565b61149b6127cb565b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600460205260408120546001600160a01b031680610d1d5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e50565b600080805b601f5481101561157a5761155c601f828154811061154257611542613873565b6000918252602090912001546001600160a01b0316610c5f565b61156690836137f5565b91508061157281613889565b915050611522565b50919050565b6115886127cb565b601291909155601355565b606060006115a08361162c565b90506000816001600160401b038111156115bc576115bc6132b6565b6040519080825280602002602001820160405280156115e5578160200160208202803683370190505b50905060005b8281101561121a576115fd8582611028565b82828151811061160f5761160f613873565b60209081029190910101528061162481613889565b9150506115eb565b60006001600160a01b0382166116965760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610e50565b506001600160a01b031660009081526005602052604090205490565b6116ba6127cb565b6116c46000612853565b565b601054856116d3601c5490565b6116dd91906137f5565b11156117355760405162461bcd60e51b815260206004820152602160248201527f507572636861736520776f756c642065786365656420465245455f535550504c6044820152605960f81b6064820152608401610e50565b6040805160208082018790526bffffffffffffffffffffffff193360601b1682840152605480830187905283518084039091018152607490920190925280519101206117b4908383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506128a592505050565b806117ce57503360009081526015602052604090205460ff165b61180a5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b6044820152606401610e50565b60185460011461185c5760405162461bcd60e51b815260206004820152601f60248201527f50726573616c6520526f756e64206973206e6f74206163746976617465642e006044820152606401610e50565b336000908152601660205260409020546118779086906137f5565b33600090815260166020526040902081905560125410156118da5760405162461bcd60e51b815260206004820152601f60248201527f4f766572666c6f7720666f722050524553414c455f4d494e545f4c494d4954006044820152606401610e50565b60005b8581101561192b5760006118f0601c5490565b9050611900601c80546001019055565b611909816128b4565b61191857611918335b826128d1565b508061192381613889565b9150506118dd565b506020546001600160a01b031663a9059cbb3360225461194b90896137b4565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611996573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ba91906138f0565b505050505050565b6119ca6127cb565b602080546001600160a01b0319166001600160a01b0392909216919091179055565b600080805b601f5481101561157a57611a2b601f8281548110611a1157611a11613873565b6000918252602090912001546001600160a01b0316611dd5565b611a3590836137f5565b915080611a4181613889565b9150506119f1565b606060038054610d3290613808565b611a606127cb565b601b6111328282613953565b6111323383836128eb565b611a8133836125a6565b611a9d5760405162461bcd60e51b8152600401610e50906138a2565b611aa9848484846129b9565b50505050565b611ab76127cb565b602191909155602255565b611aca6127cb565b600f54818351611ada91906137b4565b601c54611ae791906137f5565b1115611b355760405162461bcd60e51b815260206004820181905260248201527f507572636861736520776f756c6420657863656564204d41585f535550504c596044820152606401610e50565b60005b8251811015610ef15760005b82811015611baa576000611b57601c5490565b9050611b67601c80546001019055565b611b70816128b4565b611b9757611b97858481518110611b8957611b89613873565b6020026020010151826128d1565b5080611ba281613889565b915050611b44565b5080611bb581613889565b915050611b38565b6060611bc8826128b4565b611c0b5760405162461bcd60e51b8152602060048201526014602482015273151bdad95b88191bd95cc81b9bdd08195e1a5cdd60621b6044820152606401610e50565b60195460ff1615611c4857601a611c21836129ec565b604051602001611c32929190613a12565b6040516020818303038152906040529050919050565b601b8054611c5590613808565b80601f0160208091040260200160405190810160405280929190818152602001828054611c8190613808565b8015611cce5780601f10611ca357610100808354040283529160200191611cce565b820191906000526020600020905b815481529060010190602001808311611cb157829003601f168201915b50505050509050919050565b611ce26127cb565b6020546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015611d2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d4f9190613a99565b6020549091506001600160a01b031663a9059cbb336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015611db1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113291906138f0565b6001600160a01b0381166000908152601e60205260408120610d1d90612825565b611dfe6127cb565b6019805460ff1916911515919091179055565b611e196127cb565b60005b8251811015610ef1578160156000858481518110611e3c57611e3c613873565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580611e7881613889565b915050611e1c565b600260005403611ea25760405162461bcd60e51b8152600401610e509061383c565b6002600090815533808252601d602052604090912090611ec190610c5f565b600182015542600282015560005b8251811015610fdc57611efb33848381518110611eee57611eee613873565b6020026020010151611456565b611f3d5760405162461bcd60e51b8152602060048201526013602482015272139bdd081cdd185ad959081d1a1a5cc81b999d606a1b6044820152606401610e50565b611f713033858481518110611f5457611f54613873565b6020026020010151604051806020016040528060008152506129b9565b611fb8838281518110611f8657611f86613873565b6020026020010151601e6000611f993390565b6001600160a01b03168152602081019190915260400160002090612aec565b5080611fc381613889565b915050611ecf565b600f5481611fd8601c5490565b611fe291906137f5565b11156120305760405162461bcd60e51b815260206004820181905260248201527f507572636861736520776f756c6420657863656564204d41585f535550504c596044820152606401610e50565b6018546002146120825760405162461bcd60e51b815260206004820152601d60248201527f5075626c6963204d696e74206973206e6f74206163746976617465642e0000006044820152606401610e50565b348160115461209191906137b4565b11156120df5760405162461bcd60e51b815260206004820152601c60248201527f45544820616d6f756e74206973206e6f742073756666696369656e74000000006044820152606401610e50565b336000908152601760205260409020546120fa9082906137f5565b336000908152601760205260409020819055601354101561215d5760405162461bcd60e51b815260206004820152601e60248201527f4f766572666c6f7720666f72205055424c49435f4d494e545f4c494d495400006044820152606401610e50565b600061216a6014346137e1565b600e546040519192506001600160a01b03169082156108fc029083906000818181858888f193505050501580156121a5573d6000803e3d6000fd5b50600d546001600160a01b03166108fc6121bf83346137a1565b6040518115909202916000818181858888f193505050501580156121e7573d6000803e3d6000fd5b5060005b828110156122375760006121fe601c5490565b905061220e601c80546001019055565b612217816128b4565b6122245761222433611912565b508061222f81613889565b9150506121eb565b506020546001600160a01b031663a9059cbb3360225461225790866137b4565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af11580156122a2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef191906138f0565b6122ce6127cb565b6001600160a01b0381166123335760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e50565b61233c81612853565b50565b6123476127cb565b601155565b600080805b601f5481101561157a576000612373601f8381548110611a1157611a11613873565b1115612387576123846001836137f5565b91505b8061239181613889565b915050612351565b60006001600160e01b031982166380ac58cd60e01b14806123ca57506001600160e01b03198216635b5e139f60e01b145b80610d1d57506301ffc9a760e01b6001600160e01b0319831614610d1d565b6123f2816128b4565b61233c5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e50565b600081815260066020526040902080546001600160a01b0319166001600160a01b038416908117909155819061246e826114bd565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60015460ff16156116c45760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610e50565b60005b601f5481101561254757816001600160a01b0316601f828154811061251757612517613873565b6000918252602090912001546001600160a01b031603612535575050565b8061253f81613889565b9150506124f0565b50601f80546001810182556000919091527fa03837a25210ee280c2113ff4b77ca23440b19d4866cca721c801278fd08d8070180546001600160a01b0319166001600160a01b0392909216919091179055565b60006114788383612af8565b6000806125b2836114bd565b9050806001600160a01b0316846001600160a01b031614806125f957506001600160a01b0380821660009081526007602090815260408083209388168352929052205460ff165b80610fef5750836001600160a01b031661261284610db5565b6001600160a01b031614949350505050565b826001600160a01b0316612637826114bd565b6001600160a01b03161461269b5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610e50565b6001600160a01b0382166126fd5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610e50565b612708838383612b47565b612713600082612439565b6001600160a01b038316600090815260056020526040812080546001929061273c9084906137a1565b90915550506001600160a01b038216600090815260056020526040812080546001929061276a9084906137f5565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600c546001600160a01b031633146116c45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e50565b6000610d1d825490565b60006114788383612bff565b60008181526001830160205260408120541515611478565b600c80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006114788260145485612c29565b6000908152600460205260409020546001600160a01b0316151590565b611132828260405180602001604052806000815250612c3f565b816001600160a01b0316836001600160a01b03160361294c5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610e50565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6129c4848484612624565b6129d084848484612c72565b611aa95760405162461bcd60e51b8152600401610e5090613ab2565b606081600003612a135750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612a3d5780612a2781613889565b9150612a369050600a836137e1565b9150612a17565b6000816001600160401b03811115612a5757612a576132b6565b6040519080825280601f01601f191660200182016040528015612a81576020820181803683370190505b5090505b8415610fef57612a966001836137a1565b9150612aa3600a86613b04565b612aae9060306137f5565b60f81b818381518110612ac357612ac3613873565b60200101906001600160f81b031916908160001a905350612ae5600a866137e1565b9450612a85565b60006114788383612d70565b6000818152600183016020526040812054612b3f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d1d565b506000610d1d565b6001600160a01b038316612ba257612b9d81600a80546000838152600b60205260408120829055600182018355919091527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80155565b612bc5565b816001600160a01b0316836001600160a01b031614612bc557612bc58382612e63565b6001600160a01b038216612bdc57610ef181612f00565b826001600160a01b0316826001600160a01b031614610ef157610ef18282612faf565b6000826000018281548110612c1657612c16613873565b9060005260206000200154905092915050565b600082612c368584612ff3565b14949350505050565b612c498383613038565b612c566000848484612c72565b610ef15760405162461bcd60e51b8152600401610e5090613ab2565b60006001600160a01b0384163b15612d6857604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612cb6903390899088908890600401613b18565b6020604051808303816000875af1925050508015612cf1575060408051601f3d908101601f19168201909252612cee91810190613b55565b60015b612d4e573d808015612d1f576040519150601f19603f3d011682016040523d82523d6000602084013e612d24565b606091505b508051600003612d465760405162461bcd60e51b8152600401610e5090613ab2565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610fef565b506001610fef565b60008181526001830160205260408120548015612e59576000612d946001836137a1565b8554909150600090612da8906001906137a1565b9050818114612e0d576000866000018281548110612dc857612dc8613873565b9060005260206000200154905080876000018481548110612deb57612deb613873565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612e1e57612e1e613b72565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d1d565b6000915050610d1d565b60006001612e708461162c565b612e7a91906137a1565b600083815260096020526040902054909150808214612ecd576001600160a01b03841660009081526008602090815260408083208584528252808320548484528184208190558352600990915290208190555b5060009182526009602090815260408084208490556001600160a01b039094168352600881528383209183525290812055565b600a54600090612f12906001906137a1565b6000838152600b6020526040812054600a8054939450909284908110612f3a57612f3a613873565b9060005260206000200154905080600a8381548110612f5b57612f5b613873565b6000918252602080832090910192909255828152600b9091526040808220849055858252812055600a805480612f9357612f93613b72565b6001900381819060005260206000200160009055905550505050565b6000612fba8361162c565b6001600160a01b039093166000908152600860209081526040808320868452825280832085905593825260099052919091209190915550565b600081815b845181101561121a576130248286838151811061301757613017613873565b6020026020010151613177565b91508061303081613889565b915050612ff8565b6001600160a01b03821661308e5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610e50565b613097816128b4565b156130e45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e50565b6130f060008383612b47565b6001600160a01b03821660009081526005602052604081208054600192906131199084906137f5565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000818310613193576000828152602084905260409020611478565b6000838152602083905260409020611478565b80356001600160a01b03811681146131bd57600080fd5b919050565b6000602082840312156131d457600080fd5b611478826131a6565b6001600160e01b03198116811461233c57600080fd5b60006020828403121561320557600080fd5b8135611478816131dd565b60005b8381101561322b578181015183820152602001613213565b50506000910152565b6000815180845261324c816020860160208601613210565b601f01601f19169290920160200192915050565b6020815260006114786020830184613234565b60006020828403121561328557600080fd5b5035919050565b6000806040838503121561329f57600080fd5b6132a8836131a6565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156132f4576132f46132b6565b604052919050565b60006001600160401b03821115613315576133156132b6565b5060051b60200190565b6000602080838503121561333257600080fd5b82356001600160401b0381111561334857600080fd5b8301601f8101851361335957600080fd5b803561336c613367826132fc565b6132cc565b81815260059190911b8201830190838101908783111561338b57600080fd5b928401925b828410156133a957833582529284019290840190613390565b979650505050505050565b60006001600160401b038311156133cd576133cd6132b6565b6133e0601f8401601f19166020016132cc565b90508281528383830111156133f457600080fd5b828260208301376000602084830101529392505050565b6000806000806080858703121561342157600080fd5b61342a856131a6565b9350613438602086016131a6565b92506040850135915060608501356001600160401b0381111561345a57600080fd5b8501601f8101871361346b57600080fd5b61347a878235602084016133b4565b91505092959194509250565b60008060006060848603121561349b57600080fd5b6134a4846131a6565b92506134b2602085016131a6565b9150604084013590509250925092565b600080604083850312156134d557600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b8181101561351c57835183529284019291840191600101613500565b50909695505050505050565b60006020828403121561353a57600080fd5b81356001600160401b0381111561355057600080fd5b8201601f8101841361356157600080fd5b610fef848235602084016133b4565b60008060008060006080868803121561358857600080fd5b85359450602086013593506040860135925060608601356001600160401b03808211156135b457600080fd5b818801915088601f8301126135c857600080fd5b8135818111156135d757600080fd5b8960208260051b85010111156135ec57600080fd5b9699959850939650602001949392505050565b801515811461233c57600080fd5b6000806040838503121561362057600080fd5b613629836131a6565b91506020830135613639816135ff565b809150509250929050565b600082601f83011261365557600080fd5b81356020613665613367836132fc565b82815260059290921b8401810191818101908684111561368457600080fd5b8286015b848110156136a657613699816131a6565b8352918301918301613688565b509695505050505050565b600080604083850312156136c457600080fd5b82356001600160401b038111156136da57600080fd5b6136e685828601613644565b95602094909401359450505050565b60006020828403121561370757600080fd5b8135611478816135ff565b6000806040838503121561372557600080fd5b82356001600160401b0381111561373b57600080fd5b61374785828601613644565b9250506020830135613639816135ff565b6000806040838503121561376b57600080fd5b613774836131a6565b9150613782602084016131a6565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610d1d57610d1d61378b565b8082028115828204841417610d1d57610d1d61378b565b634e487b7160e01b600052601260045260246000fd5b6000826137f0576137f06137cb565b500490565b80820180821115610d1d57610d1d61378b565b600181811c9082168061381c57607f821691505b60208210810361157a57634e487b7160e01b600052602260045260246000fd5b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60006001820161389b5761389b61378b565b5060010190565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b60006020828403121561390257600080fd5b8151611478816135ff565b601f821115610ef157600081815260208120601f850160051c810160208610156139345750805b601f850160051c820191505b818110156119ba57828155600101613940565b81516001600160401b0381111561396c5761396c6132b6565b6139808161397a8454613808565b8461390d565b602080601f8311600181146139b5576000841561399d5750858301515b600019600386901b1c1916600185901b1785556119ba565b600085815260208120601f198616915b828110156139e4578886015182559484019460019091019084016139c5565b5085821015613a025787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000808454613a2081613808565b60018281168015613a385760018114613a4d57613a7c565b60ff1984168752821515830287019450613a7c565b8860005260208060002060005b85811015613a735781548a820152908401908201613a5a565b50505082870194505b505050508351613a90818360208801613210565b01949350505050565b600060208284031215613aab57600080fd5b5051919050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600082613b1357613b136137cb565b500690565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613b4b90830184613234565b9695505050505050565b600060208284031215613b6757600080fd5b8151611478816131dd565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220db883ffdd07a25bbaefe28372168bdb77af22e0b8e79cff448e29069c3a8316964736f6c634300081100330000000000000000000000003c286dfec4bed13cf66a76129427a76b8f18de3e000000000000000000000000f1c7d373e1aa5d899ac454ae49512d25505de003

Deployed Bytecode

0x6080604052600436106103dc5760003560e01c80636dfa8d99116101fd578063b88d4fde11610118578063e43f696e116100ab578063f2fde38b1161007a578063f2fde38b14610bd4578063f4a0a52814610bf4578063f5ebec8014610c14578063f7c618c114610c2a578063ff01f73614610c4a57600080fd5b8063e43f696e14610b38578063e449f34114610b58578063e985e9c514610b78578063efef39a114610bc157600080fd5b8063c87b56dd116100e7578063c87b56dd14610ac3578063ca628c7814610ae3578063cd0559eb14610af8578063d05611f714610b1857600080fd5b8063b88d4fde14610a4d578063bb7850f014610a6d578063bceae77b14610a8d578063c204642c14610aa357600080fd5b806384b9a4a51161019057806395d89b411161015f57806395d89b41146109e257806397bc411c146109f75780639858cf1914610a17578063a22cb46514610a2d57600080fd5b806384b9a4a5146109795780638aee81271461098f5780638da5cb5b146109af578063920387b4146109cd57600080fd5b806370a08231116101cc57806370a082311461090e578063715018a61461092e578063799efeaa14610943578063848da3b91461095957600080fd5b80636dfa8d99146108a35780636f3a43c4146108b85780636fad40d5146108ce578063709182a9146108ee57600080fd5b8063348e50c6116102f85780634ead43271161028b57806355f804b31161025a57806355f804b3146108155780635c975abb146108355780635e1e10041461084d578063611f3f101461086d5780636352211e1461088357600080fd5b80634ead4327146107735780634f6ccce7146107b557806353e90cbd146107d55780635451da1b146107f557600080fd5b806344f9f627116102c757806344f9f627146106e157806345149bb31461070e5780634641257d1461072e5780634d861e821461074357600080fd5b8063348e50c61461066c57806337da577c1461068c5780633ccfd60b146106ac57806342842e0e146106c157600080fd5b80631959a002116103705780632b691f221161033f5780632b691f22146105f35780632eb48656146106205780632f745c591461063657806332cb6b0c1461065657600080fd5b80631959a002146105355780631d95fa561461058c57806323b872dd146105a657806323eeb661146105c657600080fd5b8063095ea7b3116103ac578063095ea7b3146104a55780630fbf0a93146104c7578063150b7a02146104e757806318160ddd1461052057600080fd5b80628cc262146103e857806301ffc9a71461041b57806306fdde031461044b578063081812fc1461046d57600080fd5b366103e357005b600080fd5b3480156103f457600080fd5b506104086104033660046131c2565b610c5f565b6040519081526020015b60405180910390f35b34801561042757600080fd5b5061043b6104363660046131f3565b610cf8565b6040519015158152602001610412565b34801561045757600080fd5b50610460610d23565b6040516104129190613260565b34801561047957600080fd5b5061048d610488366004613273565b610db5565b6040516001600160a01b039091168152602001610412565b3480156104b157600080fd5b506104c56104c036600461328c565b610ddc565b005b3480156104d357600080fd5b506104c56104e236600461331f565b610ef6565b3480156104f357600080fd5b5061050761050236600461340b565b610fe6565b6040516001600160e01b03199091168152602001610412565b34801561052c57600080fd5b50600a54610408565b34801561054157600080fd5b506105716105503660046131c2565b601d6020526000908152604090208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610412565b34801561059857600080fd5b5060195461043b9060ff1681565b3480156105b257600080fd5b506104c56105c1366004613486565b610ff7565b3480156105d257600080fd5b506104086105e13660046131c2565b60176020526000908152604090205481565b3480156105ff57600080fd5b5061040861060e3660046131c2565b60166020526000908152604090205481565b34801561062c57600080fd5b5061040860145481565b34801561064257600080fd5b5061040861065136600461328c565b611028565b34801561066257600080fd5b50610408600f5481565b34801561067857600080fd5b5061048d610687366004613273565b6110be565b34801561069857600080fd5b506104c56106a73660046134c2565b6110e8565b3480156106b857600080fd5b506104c56110fb565b3480156106cd57600080fd5b506104c56106dc366004613486565b611136565b3480156106ed57600080fd5b506107016106fc3660046131c2565b611151565b60405161041291906134e4565b34801561071a57600080fd5b506104c5610729366004613273565b611222565b34801561073a57600080fd5b506104c561122f565b34801561074f57600080fd5b5061043b61075e3660046131c2565b60156020526000908152604090205460ff1681565b34801561077f57600080fd5b5061079361078e3660046131c2565b611350565b6040805182518152602080840151908201529181015190820152606001610412565b3480156107c157600080fd5b506104086107d0366004613273565b6113b6565b3480156107e157600080fd5b506104c56107f0366004613273565b611449565b34801561080157600080fd5b5061043b61081036600461328c565b611456565b34801561082157600080fd5b506104c5610830366004613528565b61147f565b34801561084157600080fd5b5060015460ff1661043b565b34801561085957600080fd5b506104c56108683660046131c2565b611493565b34801561087957600080fd5b5061040860115481565b34801561088f57600080fd5b5061048d61089e366004613273565b6114bd565b3480156108af57600080fd5b5061040861151d565b3480156108c457600080fd5b5061040860225481565b3480156108da57600080fd5b506104c56108e93660046134c2565b611580565b3480156108fa57600080fd5b506107016109093660046131c2565b611593565b34801561091a57600080fd5b506104086109293660046131c2565b61162c565b34801561093a57600080fd5b506104c56116b2565b34801561094f57600080fd5b5061040860215481565b34801561096557600080fd5b506104c5610974366004613570565b6116c6565b34801561098557600080fd5b5061040860185481565b34801561099b57600080fd5b506104c56109aa3660046131c2565b6119c2565b3480156109bb57600080fd5b50600c546001600160a01b031661048d565b3480156109d957600080fd5b506104086119ec565b3480156109ee57600080fd5b50610460611a49565b348015610a0357600080fd5b506104c5610a12366004613528565b611a58565b348015610a2357600080fd5b5061040860105481565b348015610a3957600080fd5b506104c5610a4836600461360d565b611a6c565b348015610a5957600080fd5b506104c5610a6836600461340b565b611a77565b348015610a7957600080fd5b506104c5610a883660046134c2565b611aaf565b348015610a9957600080fd5b5061040860135481565b348015610aaf57600080fd5b506104c5610abe3660046136b1565b611ac2565b348015610acf57600080fd5b50610460610ade366004613273565b611bbd565b348015610aef57600080fd5b506104c5611cda565b348015610b0457600080fd5b50610408610b133660046131c2565b611dd5565b348015610b2457600080fd5b506104c5610b333660046136f5565b611df6565b348015610b4457600080fd5b506104c5610b53366004613712565b611e11565b348015610b6457600080fd5b506104c5610b7336600461331f565b611e80565b348015610b8457600080fd5b5061043b610b93366004613758565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b6104c5610bcf366004613273565b611fcb565b348015610be057600080fd5b506104c5610bef3660046131c2565b6122c6565b348015610c0057600080fd5b506104c5610c0f366004613273565b61233f565b348015610c2057600080fd5b5061040860125481565b348015610c3657600080fd5b5060205461048d906001600160a01b031681565b348015610c5657600080fd5b5061040861234c565b6001600160a01b0381166000908152601d60209081526040808320815160608101835281548152600182015493810193909352600201549082015260215442919083906201518090610cb087611dd5565b6040850151610cbf90876137a1565b610cc991906137b4565b610cd391906137b4565b610cdd91906137e1565b9050808260200151610cef91906137f5565b95945050505050565b60006001600160e01b0319821663780e9d6360e01b1480610d1d5750610d1d82612399565b92915050565b606060028054610d3290613808565b80601f0160208091040260200160405190810160405280929190818152602001828054610d5e90613808565b8015610dab5780601f10610d8057610100808354040283529160200191610dab565b820191906000526020600020905b815481529060010190602001808311610d8e57829003601f168201915b5050505050905090565b6000610dc0826123e9565b506000908152600660205260409020546001600160a01b031690565b6000610de7826114bd565b9050806001600160a01b0316836001600160a01b031603610e595760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610e755750610e758133610b93565b610ee75760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610e50565b610ef18383612439565b505050565b600260005403610f185760405162461bcd60e51b8152600401610e509061383c565b6002600055610f256124a7565b336000818152601d6020526040902090610f3e90610c5f565b6001820155426002820155610f52336124ed565b60005b8251811015610fdc57610f823330858481518110610f7557610f75613873565b6020026020010151611136565b610fc9838281518110610f9757610f97613873565b6020026020010151601e6000610faa3390565b6001600160a01b0316815260208101919091526040016000209061259a565b5080610fd481613889565b915050610f55565b5050600160005550565b630a85bd0160e11b5b949350505050565b61100133826125a6565b61101d5760405162461bcd60e51b8152600401610e50906138a2565b610ef1838383612624565b60006110338361162c565b82106110955760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610e50565b506001600160a01b03919091166000908152600860209081526040808320938352929052205490565b601f81815481106110ce57600080fd5b6000918252602090912001546001600160a01b0316905081565b6110f06127cb565b600f91909155601055565b6111036127cb565b6040514790339082156108fc029083906000818181858888f19350505050158015611132573d6000803e3d6000fd5b5050565b610ef183838360405180602001604052806000815250611a77565b6001600160a01b0381166000908152601e602052604081206060919061117690612825565b90506000816001600160401b03811115611192576111926132b6565b6040519080825280602002602001820160405280156111bb578160200160208202803683370190505b50905060005b8281101561121a576001600160a01b0385166000908152601e602052604090206111eb908261282f565b8282815181106111fd576111fd613873565b60209081029190910101528061121281613889565b9150506111c1565b509392505050565b61122a6127cb565b601455565b6002600054036112515760405162461bcd60e51b8152600401610e509061383c565b6002600090815561126133610c5f565b116112a05760405162461bcd60e51b815260206004820152600f60248201526e4e6f7468696e67205265776172647360881b6044820152606401610e50565b6020546001600160a01b031663a9059cbb336112bb33610c5f565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611306573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132a91906138f0565b50336000908152601d602052604081206001808201839055426002909201919091559055565b61137460405180606001604052806000815260200160008152602001600081525090565b506001600160a01b03166000908152601d6020908152604091829020825160608101845281548152600182015492810192909252600201549181019190915290565b60006113c1600a5490565b82106114245760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610e50565b600a828154811061143757611437613873565b90600052602060002001549050919050565b6114516127cb565b601855565b6001600160a01b0382166000908152601e60205260408120611478908361283b565b9392505050565b6114876127cb565b601a6111328282613953565b61149b6127cb565b600d80546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600460205260408120546001600160a01b031680610d1d5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e50565b600080805b601f5481101561157a5761155c601f828154811061154257611542613873565b6000918252602090912001546001600160a01b0316610c5f565b61156690836137f5565b91508061157281613889565b915050611522565b50919050565b6115886127cb565b601291909155601355565b606060006115a08361162c565b90506000816001600160401b038111156115bc576115bc6132b6565b6040519080825280602002602001820160405280156115e5578160200160208202803683370190505b50905060005b8281101561121a576115fd8582611028565b82828151811061160f5761160f613873565b60209081029190910101528061162481613889565b9150506115eb565b60006001600160a01b0382166116965760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610e50565b506001600160a01b031660009081526005602052604090205490565b6116ba6127cb565b6116c46000612853565b565b601054856116d3601c5490565b6116dd91906137f5565b11156117355760405162461bcd60e51b815260206004820152602160248201527f507572636861736520776f756c642065786365656420465245455f535550504c6044820152605960f81b6064820152608401610e50565b6040805160208082018790526bffffffffffffffffffffffff193360601b1682840152605480830187905283518084039091018152607490920190925280519101206117b4908383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506128a592505050565b806117ce57503360009081526015602052604090205460ff165b61180a5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b6044820152606401610e50565b60185460011461185c5760405162461bcd60e51b815260206004820152601f60248201527f50726573616c6520526f756e64206973206e6f74206163746976617465642e006044820152606401610e50565b336000908152601660205260409020546118779086906137f5565b33600090815260166020526040902081905560125410156118da5760405162461bcd60e51b815260206004820152601f60248201527f4f766572666c6f7720666f722050524553414c455f4d494e545f4c494d4954006044820152606401610e50565b60005b8581101561192b5760006118f0601c5490565b9050611900601c80546001019055565b611909816128b4565b61191857611918335b826128d1565b508061192381613889565b9150506118dd565b506020546001600160a01b031663a9059cbb3360225461194b90896137b4565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015611996573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ba91906138f0565b505050505050565b6119ca6127cb565b602080546001600160a01b0319166001600160a01b0392909216919091179055565b600080805b601f5481101561157a57611a2b601f8281548110611a1157611a11613873565b6000918252602090912001546001600160a01b0316611dd5565b611a3590836137f5565b915080611a4181613889565b9150506119f1565b606060038054610d3290613808565b611a606127cb565b601b6111328282613953565b6111323383836128eb565b611a8133836125a6565b611a9d5760405162461bcd60e51b8152600401610e50906138a2565b611aa9848484846129b9565b50505050565b611ab76127cb565b602191909155602255565b611aca6127cb565b600f54818351611ada91906137b4565b601c54611ae791906137f5565b1115611b355760405162461bcd60e51b815260206004820181905260248201527f507572636861736520776f756c6420657863656564204d41585f535550504c596044820152606401610e50565b60005b8251811015610ef15760005b82811015611baa576000611b57601c5490565b9050611b67601c80546001019055565b611b70816128b4565b611b9757611b97858481518110611b8957611b89613873565b6020026020010151826128d1565b5080611ba281613889565b915050611b44565b5080611bb581613889565b915050611b38565b6060611bc8826128b4565b611c0b5760405162461bcd60e51b8152602060048201526014602482015273151bdad95b88191bd95cc81b9bdd08195e1a5cdd60621b6044820152606401610e50565b60195460ff1615611c4857601a611c21836129ec565b604051602001611c32929190613a12565b6040516020818303038152906040529050919050565b601b8054611c5590613808565b80601f0160208091040260200160405190810160405280929190818152602001828054611c8190613808565b8015611cce5780601f10611ca357610100808354040283529160200191611cce565b820191906000526020600020905b815481529060010190602001808311611cb157829003601f168201915b50505050509050919050565b611ce26127cb565b6020546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015611d2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d4f9190613a99565b6020549091506001600160a01b031663a9059cbb336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015611db1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113291906138f0565b6001600160a01b0381166000908152601e60205260408120610d1d90612825565b611dfe6127cb565b6019805460ff1916911515919091179055565b611e196127cb565b60005b8251811015610ef1578160156000858481518110611e3c57611e3c613873565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580611e7881613889565b915050611e1c565b600260005403611ea25760405162461bcd60e51b8152600401610e509061383c565b6002600090815533808252601d602052604090912090611ec190610c5f565b600182015542600282015560005b8251811015610fdc57611efb33848381518110611eee57611eee613873565b6020026020010151611456565b611f3d5760405162461bcd60e51b8152602060048201526013602482015272139bdd081cdd185ad959081d1a1a5cc81b999d606a1b6044820152606401610e50565b611f713033858481518110611f5457611f54613873565b6020026020010151604051806020016040528060008152506129b9565b611fb8838281518110611f8657611f86613873565b6020026020010151601e6000611f993390565b6001600160a01b03168152602081019190915260400160002090612aec565b5080611fc381613889565b915050611ecf565b600f5481611fd8601c5490565b611fe291906137f5565b11156120305760405162461bcd60e51b815260206004820181905260248201527f507572636861736520776f756c6420657863656564204d41585f535550504c596044820152606401610e50565b6018546002146120825760405162461bcd60e51b815260206004820152601d60248201527f5075626c6963204d696e74206973206e6f74206163746976617465642e0000006044820152606401610e50565b348160115461209191906137b4565b11156120df5760405162461bcd60e51b815260206004820152601c60248201527f45544820616d6f756e74206973206e6f742073756666696369656e74000000006044820152606401610e50565b336000908152601760205260409020546120fa9082906137f5565b336000908152601760205260409020819055601354101561215d5760405162461bcd60e51b815260206004820152601e60248201527f4f766572666c6f7720666f72205055424c49435f4d494e545f4c494d495400006044820152606401610e50565b600061216a6014346137e1565b600e546040519192506001600160a01b03169082156108fc029083906000818181858888f193505050501580156121a5573d6000803e3d6000fd5b50600d546001600160a01b03166108fc6121bf83346137a1565b6040518115909202916000818181858888f193505050501580156121e7573d6000803e3d6000fd5b5060005b828110156122375760006121fe601c5490565b905061220e601c80546001019055565b612217816128b4565b6122245761222433611912565b508061222f81613889565b9150506121eb565b506020546001600160a01b031663a9059cbb3360225461225790866137b4565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af11580156122a2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef191906138f0565b6122ce6127cb565b6001600160a01b0381166123335760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e50565b61233c81612853565b50565b6123476127cb565b601155565b600080805b601f5481101561157a576000612373601f8381548110611a1157611a11613873565b1115612387576123846001836137f5565b91505b8061239181613889565b915050612351565b60006001600160e01b031982166380ac58cd60e01b14806123ca57506001600160e01b03198216635b5e139f60e01b145b80610d1d57506301ffc9a760e01b6001600160e01b0319831614610d1d565b6123f2816128b4565b61233c5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e50565b600081815260066020526040902080546001600160a01b0319166001600160a01b038416908117909155819061246e826114bd565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60015460ff16156116c45760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610e50565b60005b601f5481101561254757816001600160a01b0316601f828154811061251757612517613873565b6000918252602090912001546001600160a01b031603612535575050565b8061253f81613889565b9150506124f0565b50601f80546001810182556000919091527fa03837a25210ee280c2113ff4b77ca23440b19d4866cca721c801278fd08d8070180546001600160a01b0319166001600160a01b0392909216919091179055565b60006114788383612af8565b6000806125b2836114bd565b9050806001600160a01b0316846001600160a01b031614806125f957506001600160a01b0380821660009081526007602090815260408083209388168352929052205460ff165b80610fef5750836001600160a01b031661261284610db5565b6001600160a01b031614949350505050565b826001600160a01b0316612637826114bd565b6001600160a01b03161461269b5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610e50565b6001600160a01b0382166126fd5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610e50565b612708838383612b47565b612713600082612439565b6001600160a01b038316600090815260056020526040812080546001929061273c9084906137a1565b90915550506001600160a01b038216600090815260056020526040812080546001929061276a9084906137f5565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600c546001600160a01b031633146116c45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e50565b6000610d1d825490565b60006114788383612bff565b60008181526001830160205260408120541515611478565b600c80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006114788260145485612c29565b6000908152600460205260409020546001600160a01b0316151590565b611132828260405180602001604052806000815250612c3f565b816001600160a01b0316836001600160a01b03160361294c5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610e50565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6129c4848484612624565b6129d084848484612c72565b611aa95760405162461bcd60e51b8152600401610e5090613ab2565b606081600003612a135750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612a3d5780612a2781613889565b9150612a369050600a836137e1565b9150612a17565b6000816001600160401b03811115612a5757612a576132b6565b6040519080825280601f01601f191660200182016040528015612a81576020820181803683370190505b5090505b8415610fef57612a966001836137a1565b9150612aa3600a86613b04565b612aae9060306137f5565b60f81b818381518110612ac357612ac3613873565b60200101906001600160f81b031916908160001a905350612ae5600a866137e1565b9450612a85565b60006114788383612d70565b6000818152600183016020526040812054612b3f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d1d565b506000610d1d565b6001600160a01b038316612ba257612b9d81600a80546000838152600b60205260408120829055600182018355919091527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80155565b612bc5565b816001600160a01b0316836001600160a01b031614612bc557612bc58382612e63565b6001600160a01b038216612bdc57610ef181612f00565b826001600160a01b0316826001600160a01b031614610ef157610ef18282612faf565b6000826000018281548110612c1657612c16613873565b9060005260206000200154905092915050565b600082612c368584612ff3565b14949350505050565b612c498383613038565b612c566000848484612c72565b610ef15760405162461bcd60e51b8152600401610e5090613ab2565b60006001600160a01b0384163b15612d6857604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612cb6903390899088908890600401613b18565b6020604051808303816000875af1925050508015612cf1575060408051601f3d908101601f19168201909252612cee91810190613b55565b60015b612d4e573d808015612d1f576040519150601f19603f3d011682016040523d82523d6000602084013e612d24565b606091505b508051600003612d465760405162461bcd60e51b8152600401610e5090613ab2565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610fef565b506001610fef565b60008181526001830160205260408120548015612e59576000612d946001836137a1565b8554909150600090612da8906001906137a1565b9050818114612e0d576000866000018281548110612dc857612dc8613873565b9060005260206000200154905080876000018481548110612deb57612deb613873565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612e1e57612e1e613b72565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d1d565b6000915050610d1d565b60006001612e708461162c565b612e7a91906137a1565b600083815260096020526040902054909150808214612ecd576001600160a01b03841660009081526008602090815260408083208584528252808320548484528184208190558352600990915290208190555b5060009182526009602090815260408084208490556001600160a01b039094168352600881528383209183525290812055565b600a54600090612f12906001906137a1565b6000838152600b6020526040812054600a8054939450909284908110612f3a57612f3a613873565b9060005260206000200154905080600a8381548110612f5b57612f5b613873565b6000918252602080832090910192909255828152600b9091526040808220849055858252812055600a805480612f9357612f93613b72565b6001900381819060005260206000200160009055905550505050565b6000612fba8361162c565b6001600160a01b039093166000908152600860209081526040808320868452825280832085905593825260099052919091209190915550565b600081815b845181101561121a576130248286838151811061301757613017613873565b6020026020010151613177565b91508061303081613889565b915050612ff8565b6001600160a01b03821661308e5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610e50565b613097816128b4565b156130e45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e50565b6130f060008383612b47565b6001600160a01b03821660009081526005602052604081208054600192906131199084906137f5565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000818310613193576000828152602084905260409020611478565b6000838152602083905260409020611478565b80356001600160a01b03811681146131bd57600080fd5b919050565b6000602082840312156131d457600080fd5b611478826131a6565b6001600160e01b03198116811461233c57600080fd5b60006020828403121561320557600080fd5b8135611478816131dd565b60005b8381101561322b578181015183820152602001613213565b50506000910152565b6000815180845261324c816020860160208601613210565b601f01601f19169290920160200192915050565b6020815260006114786020830184613234565b60006020828403121561328557600080fd5b5035919050565b6000806040838503121561329f57600080fd5b6132a8836131a6565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156132f4576132f46132b6565b604052919050565b60006001600160401b03821115613315576133156132b6565b5060051b60200190565b6000602080838503121561333257600080fd5b82356001600160401b0381111561334857600080fd5b8301601f8101851361335957600080fd5b803561336c613367826132fc565b6132cc565b81815260059190911b8201830190838101908783111561338b57600080fd5b928401925b828410156133a957833582529284019290840190613390565b979650505050505050565b60006001600160401b038311156133cd576133cd6132b6565b6133e0601f8401601f19166020016132cc565b90508281528383830111156133f457600080fd5b828260208301376000602084830101529392505050565b6000806000806080858703121561342157600080fd5b61342a856131a6565b9350613438602086016131a6565b92506040850135915060608501356001600160401b0381111561345a57600080fd5b8501601f8101871361346b57600080fd5b61347a878235602084016133b4565b91505092959194509250565b60008060006060848603121561349b57600080fd5b6134a4846131a6565b92506134b2602085016131a6565b9150604084013590509250925092565b600080604083850312156134d557600080fd5b50508035926020909101359150565b6020808252825182820181905260009190848201906040850190845b8181101561351c57835183529284019291840191600101613500565b50909695505050505050565b60006020828403121561353a57600080fd5b81356001600160401b0381111561355057600080fd5b8201601f8101841361356157600080fd5b610fef848235602084016133b4565b60008060008060006080868803121561358857600080fd5b85359450602086013593506040860135925060608601356001600160401b03808211156135b457600080fd5b818801915088601f8301126135c857600080fd5b8135818111156135d757600080fd5b8960208260051b85010111156135ec57600080fd5b9699959850939650602001949392505050565b801515811461233c57600080fd5b6000806040838503121561362057600080fd5b613629836131a6565b91506020830135613639816135ff565b809150509250929050565b600082601f83011261365557600080fd5b81356020613665613367836132fc565b82815260059290921b8401810191818101908684111561368457600080fd5b8286015b848110156136a657613699816131a6565b8352918301918301613688565b509695505050505050565b600080604083850312156136c457600080fd5b82356001600160401b038111156136da57600080fd5b6136e685828601613644565b95602094909401359450505050565b60006020828403121561370757600080fd5b8135611478816135ff565b6000806040838503121561372557600080fd5b82356001600160401b0381111561373b57600080fd5b61374785828601613644565b9250506020830135613639816135ff565b6000806040838503121561376b57600080fd5b613774836131a6565b9150613782602084016131a6565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610d1d57610d1d61378b565b8082028115828204841417610d1d57610d1d61378b565b634e487b7160e01b600052601260045260246000fd5b6000826137f0576137f06137cb565b500490565b80820180821115610d1d57610d1d61378b565b600181811c9082168061381c57607f821691505b60208210810361157a57634e487b7160e01b600052602260045260246000fd5b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60006001820161389b5761389b61378b565b5060010190565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b60006020828403121561390257600080fd5b8151611478816135ff565b601f821115610ef157600081815260208120601f850160051c810160208610156139345750805b601f850160051c820191505b818110156119ba57828155600101613940565b81516001600160401b0381111561396c5761396c6132b6565b6139808161397a8454613808565b8461390d565b602080601f8311600181146139b5576000841561399d5750858301515b600019600386901b1c1916600185901b1785556119ba565b600085815260208120601f198616915b828110156139e4578886015182559484019460019091019084016139c5565b5085821015613a025787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000808454613a2081613808565b60018281168015613a385760018114613a4d57613a7c565b60ff1984168752821515830287019450613a7c565b8860005260208060002060005b85811015613a735781548a820152908401908201613a5a565b50505082870194505b505050508351613a90818360208801613210565b01949350505050565b600060208284031215613aab57600080fd5b5051919050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b600082613b1357613b136137cb565b500690565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613b4b90830184613234565b9695505050505050565b600060208284031215613b6757600080fd5b8151611478816131dd565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220db883ffdd07a25bbaefe28372168bdb77af22e0b8e79cff448e29069c3a8316964736f6c63430008110033

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

0000000000000000000000003c286dfec4bed13cf66a76129427a76b8f18de3e000000000000000000000000f1c7d373e1aa5d899ac454ae49512d25505de003

-----Decoded View---------------
Arg [0] : _rewardToken (address): 0x3C286DfeC4bED13cF66A76129427a76b8F18de3e
Arg [1] : _paymentAddress (address): 0xF1c7D373E1aA5D899AC454Ae49512D25505De003

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000003c286dfec4bed13cf66a76129427a76b8f18de3e
Arg [1] : 000000000000000000000000f1c7d373e1aa5d899ac454ae49512d25505de003


Deployed Bytecode Sourcemap

77828:11725:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86832:330;;;;;;;;;;-1:-1:-1;86832:330:0;;;;;:::i;:::-;;:::i;:::-;;;529:25:1;;;517:2;502:18;86832:330:0;;;;;;;;63468:224;;;;;;;;;;-1:-1:-1;63468:224:0;;;;;:::i;:::-;;:::i;:::-;;;1116:14:1;;1109:22;1091:41;;1079:2;1064:18;63468:224:0;951:187:1;50202:100:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;51715:171::-;;;;;;;;;;-1:-1:-1;51715:171:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;2248:32:1;;;2230:51;;2218:2;2203:18;51715:171:0;2084:203:1;51232:417:0;;;;;;;;;;-1:-1:-1;51232:417:0;;;;;:::i;:::-;;:::i;:::-;;87979:489;;;;;;;;;;-1:-1:-1;87979:489:0;;;;;:::i;:::-;;:::i;89349:164::-;;;;;;;;;;-1:-1:-1;89349:164:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;;5291:33:1;;;5273:52;;5261:2;5246:18;89349:164:0;5129:202:1;64108:113:0;;;;;;;;;;-1:-1:-1;64196:10:0;:17;64108:113;;79099:44;;;;;;;;;;-1:-1:-1;79099:44:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5538:25:1;;;5594:2;5579:18;;5572:34;;;;5622:18;;;5615:34;5526:2;5511:18;79099:44:0;5336:319:1;78732:34:0;;;;;;;;;;-1:-1:-1;78732:34:0;;;;;;;;52415:336;;;;;;;;;;-1:-1:-1;52415:336:0;;;;;:::i;:::-;;:::i;78599:56::-;;;;;;;;;;-1:-1:-1;78599:56:0;;;;;:::i;:::-;;;;;;;;;;;;;;78535:57;;;;;;;;;;-1:-1:-1;78535:57:0;;;;;:::i;:::-;;;;;;;;;;;;;;78446:29;;;;;;;;;;;;;;;;63776:256;;;;;;;;;;-1:-1:-1;63776:256:0;;;;;:::i;:::-;;:::i;78220:32::-;;;;;;;;;;;;;;;;79219:27;;;;;;;;;;-1:-1:-1;79219:27:0;;;;;:::i;:::-;;:::i;81395:156::-;;;;;;;;;;-1:-1:-1;81395:156:0;;;;;:::i;:::-;;:::i;85023:147::-;;;;;;;;;;;;;:::i;52822:185::-;;;;;;;;;;-1:-1:-1;52822:185:0;;;;;:::i;:::-;;:::i;86167:368::-;;;;;;;;;;-1:-1:-1;86167:368:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;80427:99::-;;;;;;;;;;-1:-1:-1;80427:99:0;;;;;:::i;:::-;;:::i;89023:318::-;;;;;;;;;;;;;:::i;78482:46::-;;;;;;;;;;-1:-1:-1;78482:46:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;86035:120;;;;;;;;;;-1:-1:-1;86035:120:0;;;;;:::i;:::-;;:::i;:::-;;;;7466:13:1;;7448:32;;7536:4;7524:17;;;7518:24;7496:20;;;7489:54;7587:17;;;7581:24;7559:20;;;7552:54;7436:2;7421:18;86035:120:0;7250:362:1;64298:233:0;;;;;;;;;;-1:-1:-1;64298:233:0;;;;;:::i;:::-;;:::i;80210:99::-;;;;;;;;;;-1:-1:-1;80210:99:0;;;;;:::i;:::-;;:::i;86679:145::-;;;;;;;;;;-1:-1:-1;86679:145:0;;;;;:::i;:::-;;:::i;81884:104::-;;;;;;;;;;-1:-1:-1;81884:104:0;;;;;:::i;:::-;;:::i;73989:86::-;;;;;;;;;;-1:-1:-1;74060:7:0;;;;73989:86;;79740:130;;;;;;;;;;-1:-1:-1;79740:130:0;;;;;:::i;:::-;;:::i;78298:41::-;;;;;;;;;;;;;;;;49913:222;;;;;;;;;;-1:-1:-1;49913:222:0;;;;;:::i;:::-;;:::i;87170:248::-;;;;;;;;;;;;;:::i;79338:45::-;;;;;;;;;;;;;;;;81559:194;;;;;;;;;;-1:-1:-1;81559:194:0;;;;;:::i;:::-;;:::i;85357:358::-;;;;;;;;;;-1:-1:-1;85357:358:0;;;;;:::i;:::-;;:::i;49644:207::-;;;;;;;;;;-1:-1:-1;49644:207:0;;;;;:::i;:::-;;:::i;71499:103::-;;;;;;;;;;;;;:::i;79287:44::-;;;;;;;;;;;;;;;;83688:1006;;;;;;;;;;-1:-1:-1;83688:1006:0;;;;;:::i;:::-;;:::i;78664:28::-;;;;;;;;;;;;;;;;79878:130;;;;;;;;;;-1:-1:-1;79878:130:0;;;;;:::i;:::-;;:::i;70851:87::-;;;;;;;;;;-1:-1:-1;70924:6:0;;-1:-1:-1;;;;;70924:6:0;70851:87;;87426:259;;;;;;;;;;;;;:::i;50371:104::-;;;;;;;;;;;;;:::i;81761:115::-;;;;;;;;;;-1:-1:-1;81761:115:0;;;;;:::i;:::-;;:::i;78259:32::-;;;;;;;;;;;;;;;;51958:155;;;;;;;;;;-1:-1:-1;51958:155:0;;;;;:::i;:::-;;:::i;53078:323::-;;;;;;;;;;-1:-1:-1;53078:323:0;;;;;:::i;:::-;;:::i;80016:186::-;;;;;;;;;;-1:-1:-1;80016:186:0;;;;;:::i;:::-;;:::i;78396:37::-;;;;;;;;;;;;;;;;81996:613;;;;;;;;;;-1:-1:-1;81996:613:0;;;;;:::i;:::-;;:::i;84702:313::-;;;;;;;;;;-1:-1:-1;84702:313:0;;;;;:::i;:::-;;:::i;85178:171::-;;;;;;;;;;;;;:::i;86543:128::-;;;;;;;;;;-1:-1:-1;86543:128:0;;;;;:::i;:::-;;:::i;80317:102::-;;;;;;;;;;-1:-1:-1;80317:102:0;;;;;:::i;:::-;;:::i;80534:223::-;;;;;;;;;;-1:-1:-1;80534:223:0;;;;;:::i;:::-;;:::i;88476:539::-;;;;;;;;;;-1:-1:-1;88476:539:0;;;;;:::i;:::-;;:::i;52184:164::-;;;;;;;;;;-1:-1:-1;52184:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;52305:25:0;;;52281:4;52305:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;52184:164;82617:1063;;;;;;:::i;:::-;;:::i;71757:201::-;;;;;;;;;;-1:-1:-1;71757:201:0;;;;;:::i;:::-;;:::i;81272:115::-;;;;;;;;;;-1:-1:-1;81272:115:0;;;;;:::i;:::-;;:::i;78352:37::-;;;;;;;;;;;;;;;;79255:25;;;;;;;;;;-1:-1:-1;79255:25:0;;;;-1:-1:-1;;;;;79255:25:0;;;87693:278;;;;;;;;;;;;;:::i;86832:330::-;-1:-1:-1;;;;;86977:17:0;;86886:7;86977:17;;;:8;:17;;;;;;;;86954:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87087:17;;86926:15;;86954:40;86886:7;;87107:6;;87057:27;86986:7;87057:18;:27::i;:::-;87037:16;;;;87025:28;;:9;:28;:::i;:::-;87024:60;;;;:::i;:::-;:80;;;;:::i;:::-;:89;;;;:::i;:::-;87007:106;;87148:6;87133:4;:12;;;:21;;;;:::i;:::-;87126:28;86832:330;-1:-1:-1;;;;;86832:330:0:o;63468:224::-;63570:4;-1:-1:-1;;;;;;63594:50:0;;-1:-1:-1;;;63594:50:0;;:90;;;63648:36;63672:11;63648:23;:36::i;:::-;63587:97;63468:224;-1:-1:-1;;63468:224:0:o;50202:100::-;50256:13;50289:5;50282:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50202:100;:::o;51715:171::-;51791:7;51811:23;51826:7;51811:14;:23::i;:::-;-1:-1:-1;51854:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;51854:24:0;;51715:171::o;51232:417::-;51313:13;51329:23;51344:7;51329:14;:23::i;:::-;51313:39;;51377:5;-1:-1:-1;;;;;51371:11:0;:2;-1:-1:-1;;;;;51371:11:0;;51363:57;;;;-1:-1:-1;;;51363:57:0;;13060:2:1;51363:57:0;;;13042:21:1;13099:2;13079:18;;;13072:30;13138:34;13118:18;;;13111:62;-1:-1:-1;;;13189:18:1;;;13182:31;13230:19;;51363:57:0;;;;;;;;;47734:10;-1:-1:-1;;;;;51455:21:0;;;;:62;;-1:-1:-1;51480:37:0;51497:5;47734:10;52184:164;:::i;51480:37::-;51433:174;;;;-1:-1:-1;;;51433:174:0;;13462:2:1;51433:174:0;;;13444:21:1;13501:2;13481:18;;;13474:30;13540:34;13520:18;;;13513:62;13611:32;13591:18;;;13584:60;13661:19;;51433:174:0;13260:426:1;51433:174:0;51620:21;51629:2;51633:7;51620:8;:21::i;:::-;51302:347;51232:417;;:::o;87979:489::-;76783:1;77381:7;;:19;77373:63;;;;-1:-1:-1;;;77373:63:0;;;;;;;:::i;:::-;76783:1;77514:7;:18;73594:19:::1;:17;:19::i;:::-;47734:10:::0;88071:21:::2;88095:22:::0;;;:8:::2;:22;::::0;;;;;88143:20:::2;::::0;86832:330;:::i;88143:20::-:2;88128:12;::::0;::::2;:35:::0;88193:15:::2;88174:16;::::0;::::2;:34:::0;88221:27:::2;47734:10:::0;88221:13:::2;:27::i;:::-;88266:9;88261:200;88285:11;:18;88281:1;:22;88261:200;;;88325:61;47734:10:::0;88364:4:::2;88371:11;88383:1;88371:14;;;;;;;;:::i;:::-;;;;;;;88325:16;:61::i;:::-;88403:46;88434:11;88446:1;88434:14;;;;;;;;:::i;:::-;;;;;;;88403:12;:26;88416:12;47734:10:::0;;47654:98;88416:12:::2;-1:-1:-1::0;;;;;88403:26:0::2;::::0;;::::2;::::0;::::2;::::0;;;;;;-1:-1:-1;88403:26:0;;:30:::2;:46::i;:::-;-1:-1:-1::0;88305:3:0;::::2;::::0;::::2;:::i;:::-;;;;88261:200;;;-1:-1:-1::0;;76739:1:0;77693:7;:22;-1:-1:-1;87979:489:0:o;89349:164::-;-1:-1:-1;;;89349:164:0;;;;;;;:::o;52415:336::-;52610:41;47734:10;52643:7;52610:18;:41::i;:::-;52602:100;;;;-1:-1:-1;;;52602:100:0;;;;;;;:::i;:::-;52715:28;52725:4;52731:2;52735:7;52715:9;:28::i;63776:256::-;63873:7;63909:23;63926:5;63909:16;:23::i;:::-;63901:5;:31;63893:87;;;;-1:-1:-1;;;63893:87:0;;14940:2:1;63893:87:0;;;14922:21:1;14979:2;14959:18;;;14952:30;15018:34;14998:18;;;14991:62;-1:-1:-1;;;15069:18:1;;;15062:41;15120:19;;63893:87:0;14738:407:1;63893:87:0;-1:-1:-1;;;;;;63998:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;63776:256::o;79219:27::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;79219:27:0;;-1:-1:-1;79219:27:0;:::o;81395:156::-;70737:13;:11;:13::i;:::-;81486:10:::1;:22:::0;;;;81519:11:::1;:24:::0;81395:156::o;85023:147::-;70737:13;:11;:13::i;:::-;85123:39:::1;::::0;85091:21:::1;::::0;47734:10;;85123:39;::::1;;;::::0;85091:21;;85123:39:::1;::::0;;;85091:21;47734:10;85123:39;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;85062:108;85023:147::o:0;52822:185::-;52960:39;52977:4;52983:2;52987:7;52960:39;;;;;;;;;;;;:16;:39::i;86167:368::-;-1:-1:-1;;;;;86276:20:0;;86255:18;86276:20;;;:12;:20;;;;;86227:16;;86255:18;86276:29;;:27;:29::i;:::-;86255:50;;86316:23;86356:10;-1:-1:-1;;;;;86342:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;86342:25:0;;86316:51;;86383:13;86378:126;86410:10;86402:5;:18;86378:126;;;-1:-1:-1;;;;;86462:20:0;;;;;;:12;:20;;;;;:30;;86486:5;86462:23;:30::i;:::-;86446:6;86453:5;86446:13;;;;;;;;:::i;:::-;;;;;;;;;;:46;86422:7;;;;:::i;:::-;;;;86378:126;;;-1:-1:-1;86521:6:0;86167:368;-1:-1:-1;;;86167:368:0:o;80427:99::-;70737:13;:11;:13::i;:::-;80497:14:::1;:21:::0;80427:99::o;89023:318::-;76783:1;77381:7;;:19;77373:63;;;;-1:-1:-1;;;77373:63:0;;;;;;;:::i;:::-;76783:1;77514:7;:18;;;89081:20:::1;47734:10:::0;86832:330;:::i;89081:20::-:1;:24;89073:52;;;::::0;-1:-1:-1;;;89073:52:0;;15352:2:1;89073:52:0::1;::::0;::::1;15334:21:1::0;15391:2;15371:18;;;15364:30;-1:-1:-1;;;15410:18:1;;;15403:45;15465:18;;89073:52:0::1;15150:339:1::0;89073:52:0::1;89146:11;::::0;-1:-1:-1;;;;;89146:11:0::1;:20;47734:10:::0;89181:20:::1;47734:10:::0;86832:330;:::i;89181:20::-:1;89146:56;::::0;-1:-1:-1;;;;;;89146:56:0::1;::::0;;;;;;-1:-1:-1;;;;;15686:32:1;;;89146:56:0::1;::::0;::::1;15668:51:1::0;15735:18;;;15728:34;15641:18;;89146:56:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;47734:10:0;89215:21:::1;89239:22:::0;;;:8:::1;:22;::::0;;;;89272:12:::1;::::0;;::::1;:16:::0;;;89318:15:::1;89299:16;::::0;;::::1;:34:::0;;;;77693:22;;89023:318::o;86035:120::-;86096:15;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;86096:15:0;-1:-1:-1;;;;;;86131:16:0;;;;;:8;:16;;;;;;;;;86124:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86035:120::o;64298:233::-;64373:7;64409:30;64196:10;:17;;64108:113;64409:30;64401:5;:38;64393:95;;;;-1:-1:-1;;;64393:95:0;;16225:2:1;64393:95:0;;;16207:21:1;16264:2;16244:18;;;16237:30;16303:34;16283:18;;;16276:62;-1:-1:-1;;;16354:18:1;;;16347:42;16406:19;;64393:95:0;16023:408:1;64393:95:0;64506:10;64517:5;64506:17;;;;;;;;:::i;:::-;;;;;;;;;64499:24;;64298:233;;;:::o;80210:99::-;70737:13;:11;:13::i;:::-;80280:9:::1;:21:::0;80210:99::o;86679:145::-;-1:-1:-1;;;;;86777:21:0;;86753:4;86777:21;;;:12;:21;;;;;:39;;86808:7;86777:30;:39::i;:::-;86770:46;86679:145;-1:-1:-1;;;86679:145:0:o;81884:104::-;70737:13;:11;:13::i;:::-;81957::::1;:23;81973:7:::0;81957:13;:23:::1;:::i;79740:130::-:0;70737:13;:11;:13::i;:::-;79821:15:::1;:41:::0;;-1:-1:-1;;;;;;79821:41:0::1;-1:-1:-1::0;;;;;79821:41:0;;;::::1;::::0;;;::::1;::::0;;79740:130::o;49913:222::-;49985:7;50021:16;;;:7;:16;;;;;;-1:-1:-1;;;;;50021:16:0;;50048:56;;;;-1:-1:-1;;;50048:56:0;;18842:2:1;50048:56:0;;;18824:21:1;18881:2;18861:18;;;18854:30;-1:-1:-1;;;18900:18:1;;;18893:54;18964:18;;50048:56:0;18640:348:1;87170:248:0;87214:7;;;87269:112;87293:10;:17;87289:21;;87269:112;;;87348:21;87355:10;87366:1;87355:13;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;87355:13:0;87348:6;:21::i;:::-;87332:37;;;;:::i;:::-;;-1:-1:-1;87312:3:0;;;;:::i;:::-;;;;87269:112;;;-1:-1:-1;87398:12:0;87170:248;-1:-1:-1;87170:248:0:o;81559:194::-;70737:13;:11;:13::i;:::-;81662:18:::1;:37:::0;;;;81710:17:::1;:35:::0;81559:194::o;85357:358::-;85415:16;85443:18;85464:17;85474:6;85464:9;:17::i;:::-;85443:38;;85492:23;85532:10;-1:-1:-1;;;;;85518:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85518:25:0;;85492:51;;85559:13;85554:130;85586:10;85578:5;:18;85554:130;;;85638:34;85658:6;85666:5;85638:19;:34::i;:::-;85622:6;85629:5;85622:13;;;;;;;;:::i;:::-;;;;;;;;;;:50;85598:7;;;;:::i;:::-;;;;85554:130;;49644:207;49716:7;-1:-1:-1;;;;;49744:19:0;;49736:73;;;;-1:-1:-1;;;49736:73:0;;19195:2:1;49736:73:0;;;19177:21:1;19234:2;19214:18;;;19207:30;19273:34;19253:18;;;19246:62;-1:-1:-1;;;19324:18:1;;;19317:39;19373:19;;49736:73:0;18993:405:1;49736:73:0;-1:-1:-1;;;;;;49827:16:0;;;;;:9;:16;;;;;;;49644:207::o;71499:103::-;70737:13;:11;:13::i;:::-;71564:30:::1;71591:1;71564:18;:30::i;:::-;71499:103::o:0;83688:1006::-;83859:11;;83841:14;83814:24;:14;16932;;16840:114;83814:24;:41;;;;:::i;:::-;:56;;83806:101;;;;-1:-1:-1;;;83806:101:0;;19605:2:1;83806:101:0;;;19587:21:1;19644:2;19624:18;;;19617:30;19683:34;19663:18;;;19656:62;-1:-1:-1;;;19734:18:1;;;19727:31;19775:19;;83806:101:0;19403:397:1;83806:101:0;81215:40;;;;;;;26322:19:1;;;-1:-1:-1;;47734:10:0;26379:2:1;26375:15;26371:53;26357:12;;;26350:75;26441:12;;;;26434:28;;;81215:40:0;;;;;;;;;;26478:12:1;;;;81215:40:0;;;81205:51;;;;;83928:57;;83979:5;;83928:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;83928:13:0;;-1:-1:-1;;;83928:57:0:i;:::-;:88;;;-1:-1:-1;47734:10:0;83989:27;;;;:13;:27;;;;;;;;83928:88;83920:114;;;;-1:-1:-1;;;83920:114:0;;20007:2:1;83920:114:0;;;19989:21:1;20046:2;20026:18;;;20019:30;-1:-1:-1;;;20065:18:1;;;20058:43;20118:18;;83920:114:0;19805:337:1;83920:114:0;84055:9;;84068:1;84055:14;84047:57;;;;-1:-1:-1;;;84047:57:0;;20349:2:1;84047:57:0;;;20331:21:1;20388:2;20368:18;;;20361:30;20427:33;20407:18;;;20400:61;20478:18;;84047:57:0;20147:355:1;84047:57:0;47734:10;84156:36;;;;:22;:36;;;;;;:53;;84195:14;;84156:53;:::i;:::-;47734:10;84117:36;;;;:22;:36;;;;;:92;;;84278:18;;-1:-1:-1;84238:58:0;84230:101;;;;-1:-1:-1;;;84230:101:0;;20709:2:1;84230:101:0;;;20691:21:1;20748:2;20728:18;;;20721:30;20787:33;20767:18;;;20760:61;20838:18;;84230:101:0;20507:355:1;84230:101:0;84349:9;84344:259;84368:14;84364:1;:18;84344:259;;;84404:15;84422:24;:14;16932;;16840:114;84422:24;84404:42;;84461:26;:14;17051:19;;17069:1;17051:19;;;16962:127;84461:26;84507:16;84515:7;84507;:16::i;:::-;84502:90;;84544:32;47734:10;84554:12;84568:7;84544:9;:32::i;:::-;-1:-1:-1;84384:3:0;;;;:::i;:::-;;;;84344:259;;;-1:-1:-1;84615:11:0;;-1:-1:-1;;;;;84615:11:0;:20;47734:10;84667:18;;84650:35;;:14;:35;:::i;:::-;84615:71;;-1:-1:-1;;;;;;84615:71:0;;;;;;;-1:-1:-1;;;;;15686:32:1;;;84615:71:0;;;15668:51:1;15735:18;;;15728:34;15641:18;;84615:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;83688:1006;;;;;:::o;79878:130::-;70737:13;:11;:13::i;:::-;79960:11:::1;:40:::0;;-1:-1:-1;;;;;;79960:40:0::1;-1:-1:-1::0;;;;;79960:40:0;;;::::1;::::0;;;::::1;::::0;;79878:130::o;87426:259::-;87475:7;;;87528:122;87552:10;:17;87548:21;;87528:122;;;87605:33;87624:10;87635:1;87624:13;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;87624:13:0;87605:18;:33::i;:::-;87591:47;;;;:::i;:::-;;-1:-1:-1;87571:3:0;;;;:::i;:::-;;;;87528:122;;50371:104;50427:13;50460:7;50453:14;;;;;:::i;81761:115::-;70737:13;:11;:13::i;:::-;81842:12:::1;:26;81857:11:::0;81842:12;:26:::1;:::i;51958:155::-:0;52053:52;47734:10;52086:8;52096;52053:18;:52::i;53078:323::-;53252:41;47734:10;53285:7;53252:18;:41::i;:::-;53244:100;;;;-1:-1:-1;;;53244:100:0;;;;;;;:::i;:::-;53355:38;53369:4;53375:2;53379:7;53388:4;53355:13;:38::i;:::-;53078:323;;;;:::o;80016:186::-;70737:13;:11;:13::i;:::-;80117:17:::1;:32:::0;;;;80160:18:::1;:34:::0;80016:186::o;81996:613::-;70737:13;:11;:13::i;:::-;82177:10:::1;;82159:14;82135;:21;:38;;;;:::i;:::-;82108:14;16932::::0;82108:65:::1;;;;:::i;:::-;:79;;82100:123;;;::::0;-1:-1:-1;;;82100:123:0;;21069:2:1;82100:123:0::1;::::0;::::1;21051:21:1::0;;;21088:18;;;21081:30;21147:34;21127:18;;;21120:62;21199:18;;82100:123:0::1;20867:356:1::0;82100:123:0::1;82241:9;82236:366;82260:14;:21;82256:1;:25;82236:366;;;82308:9;82303:288;82327:14;82323:1;:18;82303:288;;;82367:15;82385:24;:14;16932::::0;;16840:114;82385:24:::1;82367:42;;82428:26;:14;17051:19:::0;;17069:1;17051:19;;;16962:127;82428:26:::1;82478:16;82486:7;82478;:16::i;:::-;82473:103;;82519:37;82529:14;82544:1;82529:17;;;;;;;;:::i;:::-;;;;;;;82548:7;82519:9;:37::i;:::-;-1:-1:-1::0;82343:3:0;::::1;::::0;::::1;:::i;:::-;;;;82303:288;;;-1:-1:-1::0;82283:3:0;::::1;::::0;::::1;:::i;:::-;;;;82236:366;;84702:313:::0;84775:13;84809:16;84817:7;84809;:16::i;:::-;84801:49;;;;-1:-1:-1;;;84801:49:0;;21430:2:1;84801:49:0;;;21412:21:1;21469:2;21449:18;;;21442:30;-1:-1:-1;;;21488:18:1;;;21481:50;21548:18;;84801:49:0;21228:344:1;84801:49:0;84867:14;;;;84863:113;;;84929:13;84944:18;:7;:16;:18::i;:::-;84912:51;;;;;;;;;:::i;:::-;;;;;;;;;;;;;84898:66;;84702:313;;;:::o;84863:113::-;84995:12;84988:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84702:313;;;:::o;85178:171::-;70737:13;:11;:13::i;:::-;85251:11:::1;::::0;:36:::1;::::0;-1:-1:-1;;;85251:36:0;;85281:4:::1;85251:36;::::0;::::1;2230:51:1::0;85233:15:0::1;::::0;-1:-1:-1;;;;;85251:11:0::1;::::0;:21:::1;::::0;2203:18:1;;85251:36:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;85298:11;::::0;85233:54;;-1:-1:-1;;;;;;85298:11:0::1;:20;47734:10:::0;85298:43:::1;::::0;-1:-1:-1;;;;;;85298:43:0::1;::::0;;;;;;-1:-1:-1;;;;;15686:32:1;;;85298:43:0::1;::::0;::::1;15668:51:1::0;15735:18;;;15728:34;;;15641:18;;85298:43:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;86543:128::-:0;-1:-1:-1;;;;;86634:20:0;;86607:7;86634:20;;;:12;:20;;;;;:29;;:27;:29::i;80317:102::-;70737:13;:11;:13::i;:::-;80387:14:::1;:24:::0;;-1:-1:-1;;80387:24:0::1;::::0;::::1;;::::0;;;::::1;::::0;;80317:102::o;80534:223::-;70737:13;:11;:13::i;:::-;80636:9:::1;80631:119;80655:14;:21;80651:1;:25;80631:119;;;80733:5;80698:13;:32;80712:14;80727:1;80712:17;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;;;80698:32:0::1;::::0;;;::::1;::::0;;;;;;-1:-1:-1;80698:32:0;:40;;-1:-1:-1;;80698:40:0::1;::::0;::::1;;::::0;;;::::1;::::0;;80678:3;::::1;::::0;::::1;:::i;:::-;;;;80631:119;;88476:539:::0;76783:1;77381:7;;:19;77373:63;;;;-1:-1:-1;;;77373:63:0;;;;;;;:::i;:::-;76783:1;77514:7;:18;;;47734:10;88580:22;;;:8:::1;:22;::::0;;;;;;88628:20:::1;::::0;86832:330;:::i;88628:20::-:1;88613:12;::::0;::::1;:35:::0;88678:15:::1;88659:16;::::0;::::1;:34:::0;-1:-1:-1;88706:302:0::1;88730:11;:18;88726:1;:22;88706:302;;;88780:38;47734:10:::0;88803:11:::1;88815:1;88803:14;;;;;;;;:::i;:::-;;;;;;;88780:8;:38::i;:::-;88772:70;;;::::0;-1:-1:-1;;;88772:70:0;;22993:2:1;88772:70:0::1;::::0;::::1;22975:21:1::0;23032:2;23012:18;;;23005:30;-1:-1:-1;;;23051:18:1;;;23044:49;23110:18;;88772:70:0::1;22791:343:1::0;88772:70:0::1;88867:63;88889:4;47734:10:::0;88911:11:::1;88923:1;88911:14;;;;;;;;:::i;:::-;;;;;;;88867:63;;;;;;;;;;;::::0;:13:::1;:63::i;:::-;88947:49;88981:11;88993:1;88981:14;;;;;;;;:::i;:::-;;;;;;;88947:12;:26;88960:12;47734:10:::0;;47654:98;88960:12:::1;-1:-1:-1::0;;;;;88947:26:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;88947:26:0;;:33:::1;:49::i;:::-;-1:-1:-1::0;88750:3:0;::::1;::::0;::::1;:::i;:::-;;;;88706:302;;82617:1063:::0;82740:10;;82722:14;82695:24;:14;16932;;16840:114;82695:24;:41;;;;:::i;:::-;:55;;82687:99;;;;-1:-1:-1;;;82687:99:0;;21069:2:1;82687:99:0;;;21051:21:1;;;21088:18;;;21081:30;21147:34;21127:18;;;21120:62;21199:18;;82687:99:0;20867:356:1;82687:99:0;82807:9;;82820:1;82807:14;82799:55;;;;-1:-1:-1;;;82799:55:0;;23341:2:1;82799:55:0;;;23323:21:1;23380:2;23360:18;;;23353:30;23419:31;23399:18;;;23392:59;23468:18;;82799:55:0;23139:353:1;82799:55:0;82908:9;82890:14;82875:12;;:29;;;;:::i;:::-;:42;;82867:82;;;;-1:-1:-1;;;82867:82:0;;23699:2:1;82867:82:0;;;23681:21:1;23738:2;23718:18;;;23711:30;23777;23757:18;;;23750:58;23825:18;;82867:82:0;23497:352:1;82867:82:0;47734:10;83000:35;;;;:21;:35;;;;;;:52;;83038:14;;83000:52;:::i;:::-;47734:10;82962:35;;;;:21;:35;;;;;:90;;;83120:17;;-1:-1:-1;83081:56:0;83073:98;;;;-1:-1:-1;;;83073:98:0;;24056:2:1;83073:98:0;;;24038:21:1;24095:2;24075:18;;;24068:30;24134:32;24114:18;;;24107:60;24184:18;;83073:98:0;23854:354:1;83073:98:0;83184:14;83201;83213:2;83201:9;:14;:::i;:::-;83226:11;;:28;;83184:31;;-1:-1:-1;;;;;;83226:11:0;;:28;;;;;83184:31;;83226:11;:28;:11;:28;83184:31;83226:11;:28;;;;;;;;;;;;;;;;;;;;-1:-1:-1;83265:15:0;;-1:-1:-1;;;;;83265:15:0;:44;83290:18;83302:6;83290:9;:18;:::i;:::-;83265:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83335:9;83330:259;83354:14;83350:1;:18;83330:259;;;83390:15;83408:24;:14;16932;;16840:114;83408:24;83390:42;;83447:26;:14;17051:19;;17069:1;17051:19;;;16962:127;83447:26;83493:16;83501:7;83493;:16::i;:::-;83488:90;;83530:32;47734:10;83540:12;47654:98;83530:32;-1:-1:-1;83370:3:0;;;;:::i;:::-;;;;83330:259;;;-1:-1:-1;83601:11:0;;-1:-1:-1;;;;;83601:11:0;:20;47734:10;83653:18;;83636:35;;:14;:35;:::i;:::-;83601:71;;-1:-1:-1;;;;;;83601:71:0;;;;;;;-1:-1:-1;;;;;15686:32:1;;;83601:71:0;;;15668:51:1;15735:18;;;15728:34;15641:18;;83601:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;71757:201::-;70737:13;:11;:13::i;:::-;-1:-1:-1;;;;;71846:22:0;::::1;71838:73;;;::::0;-1:-1:-1;;;71838:73:0;;24415:2:1;71838:73:0::1;::::0;::::1;24397:21:1::0;24454:2;24434:18;;;24427:30;24493:34;24473:18;;;24466:62;-1:-1:-1;;;24544:18:1;;;24537:36;24590:19;;71838:73:0::1;24213:402:1::0;71838:73:0::1;71922:28;71941:8;71922:18;:28::i;:::-;71757:201:::0;:::o;81272:115::-;70737:13;:11;:13::i;:::-;81349:12:::1;:30:::0;81272:115::o;87693:278::-;87744:7;;;87799:135;87823:10;:17;87819:21;;87799:135;;;87902:1;87866:33;87885:10;87896:1;87885:13;;;;;;;;:::i;87866:33::-;:37;87862:60;;;87905:17;87921:1;87905:17;;:::i;:::-;;;87862:60;87842:3;;;;:::i;:::-;;;;87799:135;;49275:305;49377:4;-1:-1:-1;;;;;;49414:40:0;;-1:-1:-1;;;49414:40:0;;:105;;-1:-1:-1;;;;;;;49471:48:0;;-1:-1:-1;;;49471:48:0;49414:105;:158;;;-1:-1:-1;;;;;;;;;;40153:40:0;;;49536:36;40044:157;59690:135;59772:16;59780:7;59772;:16::i;:::-;59764:53;;;;-1:-1:-1;;;59764:53:0;;18842:2:1;59764:53:0;;;18824:21:1;18881:2;18861:18;;;18854:30;-1:-1:-1;;;18900:18:1;;;18893:54;18964:18;;59764:53:0;18640:348:1;58969:174:0;59044:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;59044:29:0;-1:-1:-1;;;;;59044:29:0;;;;;;;;:24;;59098:23;59044:24;59098:14;:23::i;:::-;-1:-1:-1;;;;;59089:46:0;;;;;;;;;;;58969:174;;:::o;74148:108::-;74060:7;;;;74218:9;74210:38;;;;-1:-1:-1;;;74210:38:0;;24822:2:1;74210:38:0;;;24804:21:1;24861:2;24841:18;;;24834:30;-1:-1:-1;;;24880:18:1;;;24873:46;24936:18;;74210:38:0;24620:340:1;85804:223:0;85866:9;85861:126;85885:10;:17;85881:21;;85861:126;;;85945:5;-1:-1:-1;;;;;85928:22:0;:10;85939:1;85928:13;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;85928:13:0;:22;85924:52;;85969:7;85804:223;:::o;85924:52::-;85904:3;;;;:::i;:::-;;;;85861:126;;;-1:-1:-1;85997:10:0;:22;;;;;;;-1:-1:-1;85997:22:0;;;;;;;;-1:-1:-1;;;;;;85997:22:0;-1:-1:-1;;;;;85997:22:0;;;;;;;;;;85804:223::o;13737:131::-;13804:4;13828:32;13833:3;13853:5;13828:4;:32::i;55202:264::-;55295:4;55312:13;55328:23;55343:7;55328:14;:23::i;:::-;55312:39;;55381:5;-1:-1:-1;;;;;55370:16:0;:7;-1:-1:-1;;;;;55370:16:0;;:52;;;-1:-1:-1;;;;;;52305:25:0;;;52281:4;52305:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;55390:32;55370:87;;;;55450:7;-1:-1:-1;;;;;55426:31:0;:20;55438:7;55426:11;:20::i;:::-;-1:-1:-1;;;;;55426:31:0;;55362:96;55202:264;-1:-1:-1;;;;55202:264:0:o;58225:625::-;58384:4;-1:-1:-1;;;;;58357:31:0;:23;58372:7;58357:14;:23::i;:::-;-1:-1:-1;;;;;58357:31:0;;58349:81;;;;-1:-1:-1;;;58349:81:0;;25167:2:1;58349:81:0;;;25149:21:1;25206:2;25186:18;;;25179:30;25245:34;25225:18;;;25218:62;-1:-1:-1;;;25296:18:1;;;25289:35;25341:19;;58349:81:0;24965:401:1;58349:81:0;-1:-1:-1;;;;;58449:16:0;;58441:65;;;;-1:-1:-1;;;58441:65:0;;25573:2:1;58441:65:0;;;25555:21:1;25612:2;25592:18;;;25585:30;25651:34;25631:18;;;25624:62;-1:-1:-1;;;25702:18:1;;;25695:34;25746:19;;58441:65:0;25371:400:1;58441:65:0;58519:39;58540:4;58546:2;58550:7;58519:20;:39::i;:::-;58623:29;58640:1;58644:7;58623:8;:29::i;:::-;-1:-1:-1;;;;;58665:15:0;;;;;;:9;:15;;;;;:20;;58684:1;;58665:15;:20;;58684:1;;58665:20;:::i;:::-;;;;-1:-1:-1;;;;;;;58696:13:0;;;;;;:9;:13;;;;;:18;;58713:1;;58696:13;:18;;58713:1;;58696:18;:::i;:::-;;;;-1:-1:-1;;58725:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;58725:21:0;-1:-1:-1;;;;;58725:21:0;;;;;;;;;58764:27;;58725:16;;58764:27;;;;;;;51302:347;51232:417;;:::o;71016:132::-;70924:6;;-1:-1:-1;;;;;70924:6:0;47734:10;71080:23;71072:68;;;;-1:-1:-1;;;71072:68:0;;25978:2:1;71072:68:0;;;25960:21:1;;;25997:18;;;25990:30;26056:34;26036:18;;;26029:62;26108:18;;71072:68:0;25776:356:1;14499:114:0;14559:7;14586:19;14594:3;7484:18;;7401:109;14967:137;15038:7;15073:22;15077:3;15089:5;15073:3;:22::i;14267:146::-;14344:4;7283:19;;;:12;;;:19;;;;;;:24;;14368:37;7186:129;72118:191;72211:6;;;-1:-1:-1;;;;;72228:17:0;;;-1:-1:-1;;;;;;72228:17:0;;;;;;;72261:40;;72211:6;;;72228:17;72211:6;;72261:40;;72192:16;;72261:40;72181:128;72118:191;:::o;80814:173::-;80903:4;80927:52;80946:5;80953:14;;80969:9;80927:18;:52::i;54908:127::-;54973:4;54997:16;;;:7;:16;;;;;;-1:-1:-1;;;;;54997:16:0;:30;;;54908:127::o;55808:110::-;55884:26;55894:2;55898:7;55884:26;;;;;;;;;;;;:9;:26::i;59286:315::-;59441:8;-1:-1:-1;;;;;59432:17:0;:5;-1:-1:-1;;;;;59432:17:0;;59424:55;;;;-1:-1:-1;;;59424:55:0;;26703:2:1;59424:55:0;;;26685:21:1;26742:2;26722:18;;;26715:30;26781:27;26761:18;;;26754:55;26826:18;;59424:55:0;26501:349:1;59424:55:0;-1:-1:-1;;;;;59490:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;59490:46:0;;;;;;;;;;59552:41;;1091::1;;;59552::0;;1064:18:1;59552:41:0;;;;;;;59286:315;;;:::o;54282:313::-;54438:28;54448:4;54454:2;54458:7;54438:9;:28::i;:::-;54485:47;54508:4;54514:2;54518:7;54527:4;54485:22;:47::i;:::-;54477:110;;;;-1:-1:-1;;;54477:110:0;;;;;;;:::i;26588:723::-;26644:13;26865:5;26874:1;26865:10;26861:53;;-1:-1:-1;;26892:10:0;;;;;;;;;;;;-1:-1:-1;;;26892:10:0;;;;;26588:723::o;26861:53::-;26939:5;26924:12;26980:78;26987:9;;26980:78;;27013:8;;;;:::i;:::-;;-1:-1:-1;27036:10:0;;-1:-1:-1;27044:2:0;27036:10;;:::i;:::-;;;26980:78;;;27068:19;27100:6;-1:-1:-1;;;;;27090:17:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27090:17:0;;27068:39;;27118:154;27125:10;;27118:154;;27152:11;27162:1;27152:11;;:::i;:::-;;-1:-1:-1;27221:10:0;27229:2;27221:5;:10;:::i;:::-;27208:24;;:2;:24;:::i;:::-;27195:39;;27178:6;27185;27178:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;27178:56:0;;;;;;;;-1:-1:-1;27249:11:0;27258:2;27249:11;;:::i;:::-;;;27118:154;;14044:137;14114:4;14138:35;14146:3;14166:5;14138:7;:35::i;5090:414::-;5153:4;7283:19;;;:12;;;:19;;;;;;5170:327;;-1:-1:-1;5213:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;5396:18;;5374:19;;;:12;;;:19;;;;;;:40;;;;5429:11;;5170:327;-1:-1:-1;5480:5:0;5473:12;;65144:589;-1:-1:-1;;;;;65350:18:0;;65346:187;;65385:40;65417:7;66560:10;:17;;66533:24;;;;:15;:24;;;;;:44;;;66588:24;;;;;;;;;;;;66456:164;65385:40;65346:187;;;65455:2;-1:-1:-1;;;;;65447:10:0;:4;-1:-1:-1;;;;;65447:10:0;;65443:90;;65474:47;65507:4;65513:7;65474:32;:47::i;:::-;-1:-1:-1;;;;;65547:16:0;;65543:183;;65580:45;65617:7;65580:36;:45::i;65543:183::-;65653:4;-1:-1:-1;;;;;65647:10:0;:2;-1:-1:-1;;;;;65647:10:0;;65643:83;;65674:40;65702:2;65706:7;65674:27;:40::i;7864:120::-;7931:7;7958:3;:11;;7970:5;7958:18;;;;;;;;:::i;:::-;;;;;;;;;7951:25;;7864:120;;;;:::o;18652:190::-;18777:4;18830;18801:25;18814:5;18821:4;18801:12;:25::i;:::-;:33;;18652:190;-1:-1:-1;;;;18652:190:0:o;56145:319::-;56274:18;56280:2;56284:7;56274:5;:18::i;:::-;56325:53;56356:1;56360:2;56364:7;56373:4;56325:22;:53::i;:::-;56303:153;;;;-1:-1:-1;;;56303:153:0;;;;;;;:::i;60389:853::-;60543:4;-1:-1:-1;;;;;60564:13:0;;30183:19;:23;60560:675;;60600:71;;-1:-1:-1;;;60600:71:0;;-1:-1:-1;;;;;60600:36:0;;;;;:71;;47734:10;;60651:4;;60657:7;;60666:4;;60600:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;60600:71:0;;;;;;;;-1:-1:-1;;60600:71:0;;;;;;;;;;;;:::i;:::-;;;60596:584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60841:6;:13;60858:1;60841:18;60837:328;;60884:60;;-1:-1:-1;;;60884:60:0;;;;;;;:::i;60837:328::-;61115:6;61109:13;61100:6;61096:2;61092:15;61085:38;60596:584;-1:-1:-1;;;;;;60722:51:0;-1:-1:-1;;;60722:51:0;;-1:-1:-1;60715:58:0;;60560:675;-1:-1:-1;61219:4:0;61212:11;;5680:1420;5746:4;5885:19;;;:12;;;:19;;;;;;5921:15;;5917:1176;;6296:21;6320:14;6333:1;6320:10;:14;:::i;:::-;6369:18;;6296:38;;-1:-1:-1;6349:17:0;;6369:22;;6390:1;;6369:22;:::i;:::-;6349:42;;6425:13;6412:9;:26;6408:405;;6459:17;6479:3;:11;;6491:9;6479:22;;;;;;;;:::i;:::-;;;;;;;;;6459:42;;6633:9;6604:3;:11;;6616:13;6604:26;;;;;;;;:::i;:::-;;;;;;;;;;;;:38;;;;6718:23;;;:12;;;:23;;;;;:36;;;6408:405;6894:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;6989:3;:12;;:19;7002:5;6989:19;;;;;;;;;;;6982:26;;;7032:4;7025:11;;;;;;;5917:1176;7076:5;7069:12;;;;;67247:988;67513:22;67563:1;67538:22;67555:4;67538:16;:22::i;:::-;:26;;;;:::i;:::-;67575:18;67596:26;;;:17;:26;;;;;;67513:51;;-1:-1:-1;67729:28:0;;;67725:328;;-1:-1:-1;;;;;67796:18:0;;67774:19;67796:18;;;:12;:18;;;;;;;;:34;;;;;;;;;67847:30;;;;;;:44;;;67964:30;;:17;:30;;;;;:43;;;67725:328;-1:-1:-1;68149:26:0;;;;:17;:26;;;;;;;;68142:33;;;-1:-1:-1;;;;;68193:18:0;;;;;:12;:18;;;;;:34;;;;;;;68186:41;67247:988::o;68530:1079::-;68808:10;:17;68783:22;;68808:21;;68828:1;;68808:21;:::i;:::-;68840:18;68861:24;;;:15;:24;;;;;;69234:10;:26;;68783:46;;-1:-1:-1;68861:24:0;;68783:46;;69234:26;;;;;;:::i;:::-;;;;;;;;;69212:48;;69298:11;69273:10;69284;69273:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;69378:28;;;:15;:28;;;;;;;:41;;;69550:24;;;;;69543:31;69585:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;68601:1008;;;68530:1079;:::o;66034:221::-;66119:14;66136:20;66153:2;66136:16;:20::i;:::-;-1:-1:-1;;;;;66167:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;66212:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;66034:221:0:o;19519:296::-;19602:7;19645:4;19602:7;19660:118;19684:5;:12;19680:1;:16;19660:118;;;19733:33;19743:12;19757:5;19763:1;19757:8;;;;;;;;:::i;:::-;;;;;;;19733:9;:33::i;:::-;19718:48;-1:-1:-1;19698:3:0;;;;:::i;:::-;;;;19660:118;;56800:439;-1:-1:-1;;;;;56880:16:0;;56872:61;;;;-1:-1:-1;;;56872:61:0;;28473:2:1;56872:61:0;;;28455:21:1;;;28492:18;;;28485:30;28551:34;28531:18;;;28524:62;28603:18;;56872:61:0;28271:356:1;56872:61:0;56953:16;56961:7;56953;:16::i;:::-;56952:17;56944:58;;;;-1:-1:-1;;;56944:58:0;;28834:2:1;56944:58:0;;;28816:21:1;28873:2;28853:18;;;28846:30;28912;28892:18;;;28885:58;28960:18;;56944:58:0;28632:352:1;56944:58:0;57015:45;57044:1;57048:2;57052:7;57015:20;:45::i;:::-;-1:-1:-1;;;;;57073:13:0;;;;;;:9;:13;;;;;:18;;57090:1;;57073:13;:18;;57090:1;;57073:18;:::i;:::-;;;;-1:-1:-1;;57102:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;57102:21:0;-1:-1:-1;;;;;57102:21:0;;;;;;;;57141:33;;57102:16;;;57141:33;;57102:16;;57141:33;85123:39:::1;85062:108;85023:147::o:0;25726:149::-;25789:7;25820:1;25816;:5;:51;;25951:13;26045:15;;;26081:4;26074:15;;;26128:4;26112:21;;25816:51;;;25951:13;26045:15;;;26081:4;26074:15;;;26128:4;26112:21;;25824:20;25883:268;14:173:1;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:186::-;251:6;304:2;292:9;283:7;279:23;275:32;272:52;;;320:1;317;310:12;272:52;343:29;362:9;343:29;:::i;565:131::-;-1:-1:-1;;;;;;639:32:1;;629:43;;619:71;;686:1;683;676:12;701:245;759:6;812:2;800:9;791:7;787:23;783:32;780:52;;;828:1;825;818:12;780:52;867:9;854:23;886:30;910:5;886:30;:::i;1143:250::-;1228:1;1238:113;1252:6;1249:1;1246:13;1238:113;;;1328:11;;;1322:18;1309:11;;;1302:39;1274:2;1267:10;1238:113;;;-1:-1:-1;;1385:1:1;1367:16;;1360:27;1143:250::o;1398:271::-;1440:3;1478:5;1472:12;1505:6;1500:3;1493:19;1521:76;1590:6;1583:4;1578:3;1574:14;1567:4;1560:5;1556:16;1521:76;:::i;:::-;1651:2;1630:15;-1:-1:-1;;1626:29:1;1617:39;;;;1658:4;1613:50;;1398:271;-1:-1:-1;;1398:271:1:o;1674:220::-;1823:2;1812:9;1805:21;1786:4;1843:45;1884:2;1873:9;1869:18;1861:6;1843:45;:::i;1899:180::-;1958:6;2011:2;1999:9;1990:7;1986:23;1982:32;1979:52;;;2027:1;2024;2017:12;1979:52;-1:-1:-1;2050:23:1;;1899:180;-1:-1:-1;1899:180:1:o;2292:254::-;2360:6;2368;2421:2;2409:9;2400:7;2396:23;2392:32;2389:52;;;2437:1;2434;2427:12;2389:52;2460:29;2479:9;2460:29;:::i;:::-;2450:39;2536:2;2521:18;;;;2508:32;;-1:-1:-1;;;2292:254:1:o;2551:127::-;2612:10;2607:3;2603:20;2600:1;2593:31;2643:4;2640:1;2633:15;2667:4;2664:1;2657:15;2683:275;2754:2;2748:9;2819:2;2800:13;;-1:-1:-1;;2796:27:1;2784:40;;-1:-1:-1;;;;;2839:34:1;;2875:22;;;2836:62;2833:88;;;2901:18;;:::i;:::-;2937:2;2930:22;2683:275;;-1:-1:-1;2683:275:1:o;2963:183::-;3023:4;-1:-1:-1;;;;;3048:6:1;3045:30;3042:56;;;3078:18;;:::i;:::-;-1:-1:-1;3123:1:1;3119:14;3135:4;3115:25;;2963:183::o;3151:891::-;3235:6;3266:2;3309;3297:9;3288:7;3284:23;3280:32;3277:52;;;3325:1;3322;3315:12;3277:52;3365:9;3352:23;-1:-1:-1;;;;;3390:6:1;3387:30;3384:50;;;3430:1;3427;3420:12;3384:50;3453:22;;3506:4;3498:13;;3494:27;-1:-1:-1;3484:55:1;;3535:1;3532;3525:12;3484:55;3571:2;3558:16;3594:60;3610:43;3650:2;3610:43;:::i;:::-;3594:60;:::i;:::-;3688:15;;;3770:1;3766:10;;;;3758:19;;3754:28;;;3719:12;;;;3794:19;;;3791:39;;;3826:1;3823;3816:12;3791:39;3850:11;;;;3870:142;3886:6;3881:3;3878:15;3870:142;;;3952:17;;3940:30;;3903:12;;;;3990;;;;3870:142;;;4031:5;3151:891;-1:-1:-1;;;;;;;3151:891:1:o;4047:406::-;4111:5;-1:-1:-1;;;;;4137:6:1;4134:30;4131:56;;;4167:18;;:::i;:::-;4205:57;4250:2;4229:15;;-1:-1:-1;;4225:29:1;4256:4;4221:40;4205:57;:::i;:::-;4196:66;;4285:6;4278:5;4271:21;4325:3;4316:6;4311:3;4307:16;4304:25;4301:45;;;4342:1;4339;4332:12;4301:45;4391:6;4386:3;4379:4;4372:5;4368:16;4355:43;4445:1;4438:4;4429:6;4422:5;4418:18;4414:29;4407:40;4047:406;;;;;:::o;4458:666::-;4553:6;4561;4569;4577;4630:3;4618:9;4609:7;4605:23;4601:33;4598:53;;;4647:1;4644;4637:12;4598:53;4670:29;4689:9;4670:29;:::i;:::-;4660:39;;4718:38;4752:2;4741:9;4737:18;4718:38;:::i;:::-;4708:48;;4803:2;4792:9;4788:18;4775:32;4765:42;;4858:2;4847:9;4843:18;4830:32;-1:-1:-1;;;;;4877:6:1;4874:30;4871:50;;;4917:1;4914;4907:12;4871:50;4940:22;;4993:4;4985:13;;4981:27;-1:-1:-1;4971:55:1;;5022:1;5019;5012:12;4971:55;5045:73;5110:7;5105:2;5092:16;5087:2;5083;5079:11;5045:73;:::i;:::-;5035:83;;;4458:666;;;;;;;:::o;5660:328::-;5737:6;5745;5753;5806:2;5794:9;5785:7;5781:23;5777:32;5774:52;;;5822:1;5819;5812:12;5774:52;5845:29;5864:9;5845:29;:::i;:::-;5835:39;;5893:38;5927:2;5916:9;5912:18;5893:38;:::i;:::-;5883:48;;5978:2;5967:9;5963:18;5950:32;5940:42;;5660:328;;;;;:::o;6175:248::-;6243:6;6251;6304:2;6292:9;6283:7;6279:23;6275:32;6272:52;;;6320:1;6317;6310:12;6272:52;-1:-1:-1;;6343:23:1;;;6413:2;6398:18;;;6385:32;;-1:-1:-1;6175:248:1:o;6428:632::-;6599:2;6651:21;;;6721:13;;6624:18;;;6743:22;;;6570:4;;6599:2;6822:15;;;;6796:2;6781:18;;;6570:4;6865:169;6879:6;6876:1;6873:13;6865:169;;;6940:13;;6928:26;;7009:15;;;;6974:12;;;;6901:1;6894:9;6865:169;;;-1:-1:-1;7051:3:1;;6428:632;-1:-1:-1;;;;;;6428:632:1:o;7617:450::-;7686:6;7739:2;7727:9;7718:7;7714:23;7710:32;7707:52;;;7755:1;7752;7745:12;7707:52;7795:9;7782:23;-1:-1:-1;;;;;7820:6:1;7817:30;7814:50;;;7860:1;7857;7850:12;7814:50;7883:22;;7936:4;7928:13;;7924:27;-1:-1:-1;7914:55:1;;7965:1;7962;7955:12;7914:55;7988:73;8053:7;8048:2;8035:16;8030:2;8026;8022:11;7988:73;:::i;8072:820::-;8185:6;8193;8201;8209;8217;8270:3;8258:9;8249:7;8245:23;8241:33;8238:53;;;8287:1;8284;8277:12;8238:53;8323:9;8310:23;8300:33;;8380:2;8369:9;8365:18;8352:32;8342:42;;8431:2;8420:9;8416:18;8403:32;8393:42;;8486:2;8475:9;8471:18;8458:32;-1:-1:-1;;;;;8550:2:1;8542:6;8539:14;8536:34;;;8566:1;8563;8556:12;8536:34;8604:6;8593:9;8589:22;8579:32;;8649:7;8642:4;8638:2;8634:13;8630:27;8620:55;;8671:1;8668;8661:12;8620:55;8711:2;8698:16;8737:2;8729:6;8726:14;8723:34;;;8753:1;8750;8743:12;8723:34;8806:7;8801:2;8791:6;8788:1;8784:14;8780:2;8776:23;8772:32;8769:45;8766:65;;;8827:1;8824;8817:12;8766:65;8072:820;;;;-1:-1:-1;8072:820:1;;-1:-1:-1;8858:2:1;8850:11;;8880:6;8072:820;-1:-1:-1;;;8072:820:1:o;8897:118::-;8983:5;8976:13;8969:21;8962:5;8959:32;8949:60;;9005:1;9002;8995:12;9020:315;9085:6;9093;9146:2;9134:9;9125:7;9121:23;9117:32;9114:52;;;9162:1;9159;9152:12;9114:52;9185:29;9204:9;9185:29;:::i;:::-;9175:39;;9264:2;9253:9;9249:18;9236:32;9277:28;9299:5;9277:28;:::i;:::-;9324:5;9314:15;;;9020:315;;;;;:::o;9340:668::-;9394:5;9447:3;9440:4;9432:6;9428:17;9424:27;9414:55;;9465:1;9462;9455:12;9414:55;9501:6;9488:20;9527:4;9551:60;9567:43;9607:2;9567:43;:::i;9551:60::-;9645:15;;;9731:1;9727:10;;;;9715:23;;9711:32;;;9676:12;;;;9755:15;;;9752:35;;;9783:1;9780;9773:12;9752:35;9819:2;9811:6;9807:15;9831:148;9847:6;9842:3;9839:15;9831:148;;;9913:23;9932:3;9913:23;:::i;:::-;9901:36;;9957:12;;;;9864;;9831:148;;;-1:-1:-1;9997:5:1;9340:668;-1:-1:-1;;;;;;9340:668:1:o;10013:416::-;10106:6;10114;10167:2;10155:9;10146:7;10142:23;10138:32;10135:52;;;10183:1;10180;10173:12;10135:52;10223:9;10210:23;-1:-1:-1;;;;;10248:6:1;10245:30;10242:50;;;10288:1;10285;10278:12;10242:50;10311:61;10364:7;10355:6;10344:9;10340:22;10311:61;:::i;:::-;10301:71;10419:2;10404:18;;;;10391:32;;-1:-1:-1;;;;10013:416:1:o;10434:241::-;10490:6;10543:2;10531:9;10522:7;10518:23;10514:32;10511:52;;;10559:1;10556;10549:12;10511:52;10598:9;10585:23;10617:28;10639:5;10617:28;:::i;10680:477::-;10770:6;10778;10831:2;10819:9;10810:7;10806:23;10802:32;10799:52;;;10847:1;10844;10837:12;10799:52;10887:9;10874:23;-1:-1:-1;;;;;10912:6:1;10909:30;10906:50;;;10952:1;10949;10942:12;10906:50;10975:61;11028:7;11019:6;11008:9;11004:22;10975:61;:::i;:::-;10965:71;;;11086:2;11075:9;11071:18;11058:32;11099:28;11121:5;11099:28;:::i;11162:260::-;11230:6;11238;11291:2;11279:9;11270:7;11266:23;11262:32;11259:52;;;11307:1;11304;11297:12;11259:52;11330:29;11349:9;11330:29;:::i;:::-;11320:39;;11378:38;11412:2;11401:9;11397:18;11378:38;:::i;:::-;11368:48;;11162:260;;;;;:::o;11648:127::-;11709:10;11704:3;11700:20;11697:1;11690:31;11740:4;11737:1;11730:15;11764:4;11761:1;11754:15;11780:128;11847:9;;;11868:11;;;11865:37;;;11882:18;;:::i;11913:168::-;11986:9;;;12017;;12034:15;;;12028:22;;12014:37;12004:71;;12055:18;;:::i;12086:127::-;12147:10;12142:3;12138:20;12135:1;12128:31;12178:4;12175:1;12168:15;12202:4;12199:1;12192:15;12218:120;12258:1;12284;12274:35;;12289:18;;:::i;:::-;-1:-1:-1;12323:9:1;;12218:120::o;12343:125::-;12408:9;;;12429:10;;;12426:36;;;12442:18;;:::i;12473:380::-;12552:1;12548:12;;;;12595;;;12616:61;;12670:4;12662:6;12658:17;12648:27;;12616:61;12723:2;12715:6;12712:14;12692:18;12689:38;12686:161;;12769:10;12764:3;12760:20;12757:1;12750:31;12804:4;12801:1;12794:15;12832:4;12829:1;12822:15;13691:355;13893:2;13875:21;;;13932:2;13912:18;;;13905:30;13971:33;13966:2;13951:18;;13944:61;14037:2;14022:18;;13691:355::o;14051:127::-;14112:10;14107:3;14103:20;14100:1;14093:31;14143:4;14140:1;14133:15;14167:4;14164:1;14157:15;14183:135;14222:3;14243:17;;;14240:43;;14263:18;;:::i;:::-;-1:-1:-1;14310:1:1;14299:13;;14183:135::o;14323:410::-;14525:2;14507:21;;;14564:2;14544:18;;;14537:30;14603:34;14598:2;14583:18;;14576:62;-1:-1:-1;;;14669:2:1;14654:18;;14647:44;14723:3;14708:19;;14323:410::o;15773:245::-;15840:6;15893:2;15881:9;15872:7;15868:23;15864:32;15861:52;;;15909:1;15906;15899:12;15861:52;15941:9;15935:16;15960:28;15982:5;15960:28;:::i;16562:545::-;16664:2;16659:3;16656:11;16653:448;;;16700:1;16725:5;16721:2;16714:17;16770:4;16766:2;16756:19;16840:2;16828:10;16824:19;16821:1;16817:27;16811:4;16807:38;16876:4;16864:10;16861:20;16858:47;;;-1:-1:-1;16899:4:1;16858:47;16954:2;16949:3;16945:12;16942:1;16938:20;16932:4;16928:31;16918:41;;17009:82;17027:2;17020:5;17017:13;17009:82;;;17072:17;;;17053:1;17042:13;17009:82;;17283:1352;17409:3;17403:10;-1:-1:-1;;;;;17428:6:1;17425:30;17422:56;;;17458:18;;:::i;:::-;17487:97;17577:6;17537:38;17569:4;17563:11;17537:38;:::i;:::-;17531:4;17487:97;:::i;:::-;17639:4;;17703:2;17692:14;;17720:1;17715:663;;;;18422:1;18439:6;18436:89;;;-1:-1:-1;18491:19:1;;;18485:26;18436:89;-1:-1:-1;;17240:1:1;17236:11;;;17232:24;17228:29;17218:40;17264:1;17260:11;;;17215:57;18538:81;;17685:944;;17715:663;16509:1;16502:14;;;16546:4;16533:18;;-1:-1:-1;;17751:20:1;;;17869:236;17883:7;17880:1;17877:14;17869:236;;;17972:19;;;17966:26;17951:42;;18064:27;;;;18032:1;18020:14;;;;17899:19;;17869:236;;;17873:3;18133:6;18124:7;18121:19;18118:201;;;18194:19;;;18188:26;-1:-1:-1;;18277:1:1;18273:14;;;18289:3;18269:24;18265:37;18261:42;18246:58;18231:74;;18118:201;-1:-1:-1;;;;;18365:1:1;18349:14;;;18345:22;18332:36;;-1:-1:-1;17283:1352:1:o;21577:1020::-;21753:3;21782:1;21815:6;21809:13;21845:36;21871:9;21845:36;:::i;:::-;21900:1;21917:18;;;21944:133;;;;22091:1;22086:356;;;;21910:532;;21944:133;-1:-1:-1;;21977:24:1;;21965:37;;22050:14;;22043:22;22031:35;;22022:45;;;-1:-1:-1;21944:133:1;;22086:356;22117:6;22114:1;22107:17;22147:4;22192:2;22189:1;22179:16;22217:1;22231:165;22245:6;22242:1;22239:13;22231:165;;;22323:14;;22310:11;;;22303:35;22366:16;;;;22260:10;;22231:165;;;22235:3;;;22425:6;22420:3;22416:16;22409:23;;21910:532;;;;;22473:6;22467:13;22489:68;22548:8;22543:3;22536:4;22528:6;22524:17;22489:68;:::i;:::-;22573:18;;21577:1020;-1:-1:-1;;;;21577:1020:1:o;22602:184::-;22672:6;22725:2;22713:9;22704:7;22700:23;22696:32;22693:52;;;22741:1;22738;22731:12;22693:52;-1:-1:-1;22764:16:1;;22602:184;-1:-1:-1;22602:184:1:o;26855:414::-;27057:2;27039:21;;;27096:2;27076:18;;;27069:30;27135:34;27130:2;27115:18;;27108:62;-1:-1:-1;;;27201:2:1;27186:18;;27179:48;27259:3;27244:19;;26855:414::o;27274:112::-;27306:1;27332;27322:35;;27337:18;;:::i;:::-;-1:-1:-1;27371:9:1;;27274:112::o;27391:489::-;-1:-1:-1;;;;;27660:15:1;;;27642:34;;27712:15;;27707:2;27692:18;;27685:43;27759:2;27744:18;;27737:34;;;27807:3;27802:2;27787:18;;27780:31;;;27585:4;;27828:46;;27854:19;;27846:6;27828:46;:::i;:::-;27820:54;27391:489;-1:-1:-1;;;;;;27391:489:1:o;27885:249::-;27954:6;28007:2;27995:9;27986:7;27982:23;27978:32;27975:52;;;28023:1;28020;28013:12;27975:52;28055:9;28049:16;28074:30;28098:5;28074:30;:::i;28139:127::-;28200:10;28195:3;28191:20;28188:1;28181:31;28231:4;28228:1;28221:15;28255:4;28252:1;28245:15

Swarm Source

ipfs://db883ffdd07a25bbaefe28372168bdb77af22e0b8e79cff448e29069c3a83169
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.