ETH Price: $3,900.26 (-0.52%)

Token

Reo Pass (REO)
 

Overview

Max Total Supply

2,503 REO

Holders

1,686

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 REO
0x2ad267b3ff346792f0526c740aca709e40f04575
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:
TenyaReoPass

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

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

// SPDX-License-Identifier: GPL-3.0

// File: @openzeppelin/contracts/utils/math/SafeMath.sol


// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

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

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

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

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

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

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

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

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

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

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

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

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

// 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: contracts/ERC721A.sol



pragma solidity ^0.8.0;









/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata and Enumerable extension. Built to optimize for lower gas during batch mints.
 *
 * Assumes serials are sequentially minted starting at 0 (e.g. 0, 1, 2, 3..).
 *
 * Does not support burning tokens to address(0).
 *
 * Assumes that an owner cannot have more than the 2**128 - 1 (max value of uint128) of supply
 */
contract ERC721A is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
    using Address for address;
    using Strings for uint256;

    struct TokenOwnership {
        address addr;
        uint64 startTimestamp;
    }

    struct AddressData {
        uint128 balance;
        uint128 numberMinted;
    }

    uint256 internal currentIndex;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to ownership details
    // An empty struct value does not necessarily mean the token is unowned. See ownershipOf implementation for details.
    mapping(uint256 => TokenOwnership) internal _ownerships;

    // Mapping owner address to address data
    mapping(address => AddressData) private _addressData;

    // 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;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view override returns (uint256) {
        require(index < totalSupply(), 'ERC721A: global index out of bounds');
        return index;
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     * This read function is O(totalSupply). If calling from a separate contract, be sure to test gas first.
     * It may also degrade with extremely large collection sizes (e.g >> 10000), test for your use case.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
        require(index < balanceOf(owner), 'ERC721A: owner index out of bounds');
        uint256 numMintedSoFar = totalSupply();
        uint256 tokenIdsIdx;
        address currOwnershipAddr;

        // Counter overflow is impossible as the loop breaks when uint256 i is equal to another uint256 numMintedSoFar.
        unchecked {
            for (uint256 i; i < numMintedSoFar; i++) {
                TokenOwnership memory ownership = _ownerships[i];
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    if (tokenIdsIdx == index) {
                        return i;
                    }
                    tokenIdsIdx++;
                }
            }
        }

        revert('ERC721A: unable to get token of owner by index');
    }

    /**
     * @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 ||
            interfaceId == type(IERC721Enumerable).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view override returns (uint256) {
        require(owner != address(0), 'ERC721A: balance query for the zero address');
        return uint256(_addressData[owner].balance);
    }

    function _numberMinted(address owner) internal view returns (uint256) {
        require(owner != address(0), 'ERC721A: number minted query for the zero address');
        return uint256(_addressData[owner].numberMinted);
    }

    /**
     * Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around in the collection over time.
     */
    function ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) {
        require(_exists(tokenId), 'ERC721A: owner query for nonexistent token');

        unchecked {
            for (uint256 curr = tokenId; curr >= 0; curr--) {
                TokenOwnership memory ownership = _ownerships[curr];
                if (ownership.addr != address(0)) {
                    return ownership;
                }
            }
        }

        revert('ERC721A: unable to determine the owner of token');
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view override returns (address) {
        return ownershipOf(tokenId).addr;
    }

    /**
     * @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) {
        require(_exists(tokenId), 'ERC721Metadata: URI query for nonexistent token');

        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 overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return '';
    }

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

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            'ERC721A: approve caller is not owner nor approved for all'
        );

        _approve(to, tokenId, owner);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view override returns (address) {
        require(_exists(tokenId), 'ERC721A: approved query for nonexistent token');

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public override {
        require(operator != _msgSender(), 'ERC721A: approve to caller');

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_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 override {
        _transfer(from, to, tokenId);
    }

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

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public override {
        _transfer(from, to, tokenId);
        require(
            _checkOnERC721Received(from, to, tokenId, _data),
            'ERC721A: 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`),
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return tokenId < currentIndex;
    }

    function _safeMint(address to, uint256 quantity) internal {
        _safeMint(to, quantity, '');
    }

    /**
     * @dev Safely mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal {
        _mint(to, quantity, _data, true);
    }

    /**
     * @dev Mints `quantity` tokens and transfers them to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `quantity` must be greater than 0.
     *
     * Emits a {Transfer} event.
     */
    function _mint(
        address to,
        uint256 quantity,
        bytes memory _data,
        bool safe
    ) internal {
        uint256 startTokenId = currentIndex;
        require(to != address(0), 'ERC721A: mint to the zero address');
        require(quantity != 0, 'ERC721A: quantity must be greater than 0');

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        // Overflows are incredibly unrealistic.
        // balance or numberMinted overflow if current value of either + quantity > 3.4e38 (2**128) - 1
        // updatedIndex overflows if currentIndex + quantity > 1.56e77 (2**256) - 1
        unchecked {
            _addressData[to].balance += uint128(quantity);
            _addressData[to].numberMinted += uint128(quantity);

            _ownerships[startTokenId].addr = to;
            _ownerships[startTokenId].startTimestamp = uint64(block.timestamp);

            uint256 updatedIndex = startTokenId;

            for (uint256 i; i < quantity; i++) {
                emit Transfer(address(0), to, updatedIndex);
                if (safe) {
                    require(
                        _checkOnERC721Received(address(0), to, updatedIndex, _data),
                        'ERC721A: transfer to non ERC721Receiver implementer'
                    );
                }

                updatedIndex++;
            }

            currentIndex = updatedIndex;
        }

        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * 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
    ) private {
        TokenOwnership memory prevOwnership = ownershipOf(tokenId);

        bool isApprovedOrOwner = (_msgSender() == prevOwnership.addr ||
            getApproved(tokenId) == _msgSender() ||
            isApprovedForAll(prevOwnership.addr, _msgSender()));

        require(isApprovedOrOwner, 'ERC721A: transfer caller is not owner nor approved');

        require(prevOwnership.addr == from, 'ERC721A: transfer from incorrect owner');
        require(to != address(0), 'ERC721A: transfer to the zero address');

        _beforeTokenTransfers(from, to, tokenId, 1);

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

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        // Counter overflow is incredibly unrealistic as tokenId would have to be 2**256.
        unchecked {
            _addressData[from].balance -= 1;
            _addressData[to].balance += 1;

            _ownerships[tokenId].addr = to;
            _ownerships[tokenId].startTimestamp = uint64(block.timestamp);

            // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            if (_ownerships[nextTokenId].addr == address(0)) {
                if (_exists(nextTokenId)) {
                    _ownerships[nextTokenId].addr = prevOwnership.addr;
                    _ownerships[nextTokenId].startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

        emit Transfer(from, to, tokenId);
        _afterTokenTransfers(from, to, tokenId, 1);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(
        address to,
        uint256 tokenId,
        address owner
    ) private {
        _tokenApprovals[tokenId] = to;
        emit Approval(owner, to, tokenId);
    }

    /**
     * @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(to).onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert('ERC721A: transfer to non ERC721Receiver implementer');
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token ids are about to be transferred. This includes minting.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * 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`.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token ids have been transferred. This includes
     * minting.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}
}
// 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: contracts/tenya-reopass.sol


pragma solidity ^0.8.0;

contract TenyaReoPass is ERC721A, Ownable {

  using SafeMath for uint256;
  using Strings for uint256;
  string private _baseUri;
  string private _notRevealURI; 
  bool public RevealedActive = false;
  uint256 public PricePublicSale = 0.03 ether;
  uint256 public Price = 0 ether;
  uint256 public MaxToken = 4000;
  uint256 public TokenIndex = 0;
  event TokenMinted(uint256 supply);
  enum Steps {Launch, PublicMint, OGMint, WLMint, Sale, SoldOut}
  Steps public sellingStep;
  mapping (address => uint256) public MaxPublicMint;
  mapping (address => uint256) public MaxOGMint;
  mapping (address => uint256) public MaxWLMint;
  mapping (address => uint256) public MaxFinalMint;
  bytes32 public merkleRootOG;
  bytes32 public merkleRootNormalWL;

  constructor() ERC721A("Reo Pass", "REO") {sellingStep = Steps.Launch;}

  function _baseURI() internal view virtual override returns (string memory) { return _baseUri; }

  function tokenURI(uint256 tokenId) public view virtual override returns (string memory a) {
    require(_exists(tokenId), "ERC721 Metadata: URI query for nonexistent token");
    if (totalSupply() >= MaxToken || RevealedActive == true) {
      if (tokenId < MaxToken) {
        uint256 offsetId = tokenId.add(MaxToken.sub(TokenIndex)).mod(MaxToken);
        return string(abi.encodePacked(_baseURI(), "reopass-", offsetId.toString(), ".json"));
      }
    } else { return _notRevealURI; }
  }

  function mintPublic(uint8 mintAmount) public payable {
    require(sellingStep == Steps.PublicMint, "Public Mint has not started");
    require(totalSupply().add(mintAmount) <= MaxToken, "Sold Out");
    require(MaxPublicMint[msg.sender] + mintAmount <= 3, "Max NFTs Reached");
    require(mintAmount > 0, "At least one should be minted");
    MaxPublicMint[msg.sender] += mintAmount;
    require(PricePublicSale * mintAmount <= msg.value, "Not enough funds");
    if(totalSupply() + mintAmount == MaxToken) { sellingStep = Steps.SoldOut; }
    _mint(msg.sender, mintAmount);
    emit TokenMinted(totalSupply());
  }

  function mintOG(uint8 mintAmount , address _account, bytes32[] calldata _proof) public payable {
    require(sellingStep == Steps.OGMint, "OG Mint has not started");
    require(totalSupply().add(mintAmount) <= MaxToken, "Sold Out");
    require(isOGWhitelisted(_account, _proof), "Account address not eligilble(not part of OG).");
    require(isOGWhitelisted(msg.sender, _proof), "Account address is not the function caller.");
    require(mintAmount > 0, "At least one should be minted");
    require(MaxOGMint[msg.sender] + mintAmount <= 1, "Max NFTs Reached");
    MaxOGMint[msg.sender] += mintAmount;
    require(Price * mintAmount <= msg.value, "Not enough funds");
    if(totalSupply() + mintAmount == MaxToken) { sellingStep = Steps.SoldOut; }
    _mint(msg.sender, mintAmount);
    emit TokenMinted(totalSupply());
  }

  function mintWL(uint8 mintAmount , address _account, bytes32[] calldata _proof) public payable {
    require(sellingStep == Steps.WLMint, "WL Mint has not started");
    require(totalSupply().add(mintAmount) <= MaxToken, "Sold Out");
    require(isWalletWhiteListed(_account, _proof), "Account address not eligilble(not part of WL).");
    require(isWalletWhiteListed(msg.sender, _proof), "Account address is not the function caller.");
    require(mintAmount > 0, "At least one should be minted");
    require(MaxWLMint[msg.sender] + mintAmount <= 1, "Max NFTs Reached");
    MaxWLMint[msg.sender] += mintAmount;
    require(Price * mintAmount <= msg.value, "Not enough funds");
    if(totalSupply() + mintAmount == MaxToken) { sellingStep = Steps.SoldOut; }
    _mint(msg.sender, mintAmount);
    emit TokenMinted(totalSupply());
  }

  function mint(uint8 mintAmount) public payable {
    require(sellingStep != Steps.SoldOut, "Sold Out");
    require(sellingStep == Steps.Sale, "Final Sale has not started");
    require(totalSupply().add(mintAmount) <= MaxToken, "Sold Out");    
    require(mintAmount > 0, "At least one should be minted");                                                          
    require(MaxFinalMint[msg.sender] + mintAmount <= 3, "Max NFTs Reached");
    MaxFinalMint[msg.sender] += mintAmount;
    require(PricePublicSale * mintAmount <= msg.value, "Not enough funds"); 
    if(totalSupply() + mintAmount == MaxToken) { sellingStep = Steps.SoldOut; }
    _mint(msg.sender, mintAmount);
    emit TokenMinted(totalSupply());
  }

  function _mint(address recipient, uint256 quantity) internal {
    _safeMint(recipient, quantity);
  }

  function OwnerMint(uint256 num) public onlyOwner {
    require(totalSupply().add(num) <= MaxToken, "Sold Out");
    if(totalSupply().add(num) == MaxToken) { sellingStep = Steps.SoldOut; }    
    _mint(msg.sender, num);
    emit TokenMinted(totalSupply());
  }

  function Airdrop(uint256 num, address recipient) public onlyOwner {
    require(totalSupply().add(num) <= MaxToken, "Sold Out");
    if(totalSupply().add(num) == MaxToken) { sellingStep = Steps.SoldOut; }    
    _mint(recipient, num);
    emit TokenMinted(totalSupply());
  }

  function AirdropGroup(address[] memory receivers) external onlyOwner {
    require(totalSupply().add(receivers.length) <= MaxToken, "Sold Out");
    if(totalSupply().add(receivers.length) == MaxToken) { sellingStep = Steps.SoldOut; }    
    for (uint256 i = 0; i < receivers.length; i++) {
      Airdrop(1, receivers[i]);
    }
  }

  function setPublicMint() external onlyOwner {
    sellingStep = Steps.PublicMint;
  }

  function setOGMint() external onlyOwner {
    require(sellingStep == Steps.PublicMint, "Public mint is ongoing, please change state first.");
    sellingStep = Steps.OGMint;
  }

  function setWLMint() external onlyOwner {
    require(sellingStep == Steps.OGMint, "OG mint is ongoing, please change state first.");
    sellingStep = Steps.WLMint;
  }

   function setSale() external onlyOwner {
    require(sellingStep == Steps.WLMint, "WL mint is ongoing, please change state first.");
    sellingStep = Steps.Sale;
  }

  function setBaseURI(string calldata baseURI) external onlyOwner {
    _baseUri = baseURI;
  }

  function setNotRevealURI(string memory preRevealURI) external onlyOwner {
    _notRevealURI = preRevealURI;
  }

  function setPricePublicSale(uint256 _newPricePublicSale) public onlyOwner {
    PricePublicSale = _newPricePublicSale;
  }

  function setPrice(uint256 _newPrice) public onlyOwner {
    Price = _newPrice;
  }

  
  function _leaf(address account) internal pure returns(bytes32) {
    return keccak256(abi.encodePacked(account));
  }

  //// OG WHITELIST WALLETS
  function isOGWhitelisted(address account, bytes32[] calldata proof) internal view returns(bool) {
    return _verify(_leaf(account), proof);
  }

  function _verify(bytes32 leaf, bytes32[] memory proof) internal view returns(bool) {
    return MerkleProof.verify(proof, merkleRootOG, leaf);
  }

  function changeMerkleRootOG(bytes32 _newMerkleRootOG) external onlyOwner {
    merkleRootOG = _newMerkleRootOG;
  }

  //NORMAL WHITELIST WALLETS
  function isWalletWhiteListed(address account, bytes32[] calldata proof) internal view returns(bool) {
    return _verifyWL(_leaf(account), proof);
  }

  function _verifyWL(bytes32 leaf, bytes32[] memory proof) internal view returns(bool) {
        return MerkleProof.verify(proof, merkleRootNormalWL, leaf);
  }

  function changeMerkleRootNormalWL(bytes32 _newmerkleRootNormalWL) external onlyOwner {
      merkleRootNormalWL = _newmerkleRootNormalWL;
  }

  ////////////////////

  function getTokenByOwner(address _owner) public view returns (uint256[] memory) {
    uint256 tokenCount = balanceOf(_owner);
    uint256[] memory tokenIds = new uint256[](tokenCount);
    for (uint256 i; i < tokenCount; i++) {
      tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
    }
    return tokenIds;
  }

  function getOwnershipData(uint256 tokenId) external view returns (TokenOwnership memory) {
    return ownershipOf(tokenId);
  }

  function numberMinted(address owner) public view returns (uint256) {
    return _numberMinted(owner);
  }

  function TurnRevealMode() public onlyOwner {
    RevealedActive = true;
  }

  function withdraw() public payable onlyOwner {
    (bool mod, ) = payable(owner()).call{value: address(this).balance}("");
    require(mod);
  }
  
}

Contract Security Audit

Contract ABI

[{"inputs":[],"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":"uint256","name":"supply","type":"uint256"}],"name":"TokenMinted","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"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"Airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"receivers","type":"address[]"}],"name":"AirdropGroup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"MaxFinalMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"MaxOGMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"MaxPublicMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MaxToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"MaxWLMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],"name":"OwnerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"Price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PricePublicSale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RevealedActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TokenIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TurnRevealMode","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":[{"internalType":"bytes32","name":"_newmerkleRootNormalWL","type":"bytes32"}],"name":"changeMerkleRootNormalWL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_newMerkleRootOG","type":"bytes32"}],"name":"changeMerkleRootOG","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getOwnershipData","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"}],"internalType":"struct ERC721A.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getTokenByOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","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":[],"name":"merkleRootNormalWL","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRootOG","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"mintAmount","type":"uint8"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"mintAmount","type":"uint8"},{"internalType":"address","name":"_account","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"mintOG","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"mintAmount","type":"uint8"}],"name":"mintPublic","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"mintAmount","type":"uint8"},{"internalType":"address","name":"_account","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"mintWL","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"numberMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","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":[],"name":"sellingStep","outputs":[{"internalType":"enum TenyaReoPass.Steps","name":"","type":"uint8"}],"stateMutability":"view","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":"string","name":"preRevealURI","type":"string"}],"name":"setNotRevealURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setOGMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPrice","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPricePublicSale","type":"uint256"}],"name":"setPricePublicSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setPublicMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setWLMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"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":"a","type":"string"}],"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":[],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"}]

6080604052600a805460ff19169055666a94d74f430000600b556000600c819055610fa0600d55600e553480156200003657600080fd5b50604080518082018252600881526752656f205061737360c01b60208083019182528351808501909452600384526252454f60e81b90840152815191929162000082916001916200011b565b508051620000989060029060208401906200011b565b505050620000b5620000af620000c560201b60201c565b620000c9565b600f805460ff19169055620001fe565b3390565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8280546200012990620001c1565b90600052602060002090601f0160209004810192826200014d576000855562000198565b82601f106200016857805160ff191683800117855562000198565b8280016001018555821562000198579182015b82811115620001985782518255916020019190600101906200017b565b50620001a6929150620001aa565b5090565b5b80821115620001a65760008155600101620001ab565b600181811c90821680620001d657607f821691505b60208210811415620001f857634e487b7160e01b600052602260045260246000fd5b50919050565b6133b7806200020e6000396000f3fe60806040526004361061031a5760003560e01c80636ae91737116101ab578063a22cb465116100f7578063cbccefb211610095578063dc33e6811161006f578063dc33e6811461090b578063e196c5d41461092b578063e985e9c51461094b578063f2fde38b1461099457600080fd5b8063cbccefb2146108b4578063d4c76e8b146108db578063dad8d8ca146108f157600080fd5b8063b2efedab116100d1578063b2efedab14610832578063b88d4fde1461085f578063bc0ac7461461087f578063c87b56dd1461089457600080fd5b8063a22cb465146107cf578063ac090ec6146107ef578063ad6cb3191461081c57600080fd5b80638da5cb5b1161016457806394bbc4ac1161013e57806394bbc4ac1461075757806395d89b4114610777578063973a2ccd1461078c5780639dfde201146107b957600080fd5b80638da5cb5b146106cc57806391b7f5ed146106ea5780639231ab2a1461070a57600080fd5b80636ae91737146106395780636ec192081461064e5780636ecd23061461066457806370a0823114610677578063715018a6146106975780637871e154146106ac57600080fd5b80632bf79c941161026a5780634a753f48116102235780635accac99116101fd5780635accac99146105d35780636352211e146105f3578063659deed81461061357806367dce1ed1461062657600080fd5b80634a753f48146105665780634f6ccce71461059357806355f804b3146105b357600080fd5b80632bf79c94146104be5780632f745c59146104eb57806338c5426f1461050b5780633ccfd60b1461051e57806342842e0e14610526578063486835031461054657600080fd5b80631618c8df116102d757806323b872dd116102b157806323b872dd14610453578063279ad4171461047357806329723719146104935780632bc79b16146104a857600080fd5b80631618c8df1461040957806318160ddd146104295780631d9cfd6d1461043e57600080fd5b806301ffc9a71461031f57806302456aa2146103545780630353025f1461036b57806306fdde031461038f578063081812fc146103b1578063095ea7b3146103e9575b600080fd5b34801561032b57600080fd5b5061033f61033a366004612db6565b6109b4565b60405190151581526020015b60405180910390f35b34801561036057600080fd5b50610369610a21565b005b34801561037757600080fd5b50610381600e5481565b60405190815260200161034b565b34801561039b57600080fd5b506103a4610a3f565b60405161034b91906130a1565b3480156103bd57600080fd5b506103d16103cc366004612d9d565b610ad1565b6040516001600160a01b03909116815260200161034b565b3480156103f557600080fd5b50610369610404366004612cc0565b610b61565b34801561041557600080fd5b50610369610424366004612d9d565b610c79565b34801561043557600080fd5b50600054610381565b34801561044a57600080fd5b50610369610d21565b34801561045f57600080fd5b5061036961046e366004612bcd565b610dba565b34801561047f57600080fd5b5061036961048e366004612d9d565b610dc5565b34801561049f57600080fd5b50610369610dd2565b3480156104b457600080fd5b5061038160155481565b3480156104ca57600080fd5b506104de6104d9366004612b7f565b610e6f565b60405161034b9190613035565b3480156104f757600080fd5b50610381610506366004612cc0565b610f10565b610369610519366004612ee7565b61106c565b6103696112f1565b34801561053257600080fd5b50610369610541366004612bcd565b61136d565b34801561055257600080fd5b50610369610561366004612cea565b611388565b34801561057257600080fd5b50610381610581366004612b7f565b60136020526000908152604090205481565b34801561059f57600080fd5b506103816105ae366004612d9d565b61142a565b3480156105bf57600080fd5b506103696105ce366004612df0565b61148c565b3480156105df57600080fd5b506103696105ee366004612e61565b6114a0565b3480156105ff57600080fd5b506103d161060e366004612d9d565b6114bb565b610369610621366004612ee7565b6114cd565b610369610634366004612ecc565b61167d565b34801561064557600080fd5b5061036961182c565b34801561065a57600080fd5b50610381600b5481565b610369610672366004612ecc565b6118c5565b34801561068357600080fd5b50610381610692366004612b7f565b611a17565b3480156106a357600080fd5b50610369611aa8565b3480156106b857600080fd5b506103696106c7366004612ea9565b611abc565b3480156106d857600080fd5b506007546001600160a01b03166103d1565b3480156106f657600080fd5b50610369610705366004612d9d565b611b5f565b34801561071657600080fd5b5061072a610725366004612d9d565b611b6c565b6040805182516001600160a01b031681526020928301516001600160401b0316928101929092520161034b565b34801561076357600080fd5b50610369610772366004612d9d565b611b89565b34801561078357600080fd5b506103a4611b96565b34801561079857600080fd5b506103816107a7366004612b7f565b60116020526000908152604090205481565b3480156107c557600080fd5b50610381600c5481565b3480156107db57600080fd5b506103696107ea366004612c84565b611ba5565b3480156107fb57600080fd5b5061038161080a366004612b7f565b60126020526000908152604090205481565b34801561082857600080fd5b5061038160145481565b34801561083e57600080fd5b5061038161084d366004612b7f565b60106020526000908152604090205481565b34801561086b57600080fd5b5061036961087a366004612c09565b611c6a565b34801561088b57600080fd5b50610369611ca3565b3480156108a057600080fd5b506103a46108af366004612d9d565b611cba565b3480156108c057600080fd5b50600f546108ce9060ff1681565b60405161034b9190613079565b3480156108e757600080fd5b50610381600d5481565b3480156108fd57600080fd5b50600a5461033f9060ff1681565b34801561091757600080fd5b50610381610926366004612b7f565b611e56565b34801561093757600080fd5b50610369610946366004612d9d565b611e61565b34801561095757600080fd5b5061033f610966366004612b9a565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b3480156109a057600080fd5b506103696109af366004612b7f565b611e6e565b60006001600160e01b031982166380ac58cd60e01b14806109e557506001600160e01b03198216635b5e139f60e01b145b80610a0057506001600160e01b0319821663780e9d6360e01b145b80610a1b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b610a29611ee4565b600f80546001919060ff191682805b0217905550565b606060018054610a4e90613293565b80601f0160208091040260200160405190810160405280929190818152602001828054610a7a90613293565b8015610ac75780601f10610a9c57610100808354040283529160200191610ac7565b820191906000526020600020905b815481529060010190602001808311610aaa57829003601f168201915b5050505050905090565b6000610ade826000541190565b610b455760405162461bcd60e51b815260206004820152602d60248201527f455243373231413a20617070726f76656420717565727920666f72206e6f6e6560448201526c3c34b9ba32b73a103a37b5b2b760991b60648201526084015b60405180910390fd5b506000908152600560205260409020546001600160a01b031690565b6000610b6c826114bb565b9050806001600160a01b0316836001600160a01b03161415610bdb5760405162461bcd60e51b815260206004820152602260248201527f455243373231413a20617070726f76616c20746f2063757272656e74206f776e60448201526132b960f11b6064820152608401610b3c565b336001600160a01b0382161480610bf75750610bf78133610966565b610c695760405162461bcd60e51b815260206004820152603960248201527f455243373231413a20617070726f76652063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f76656420666f7220616c6c000000000000006064820152608401610b3c565b610c74838383611f3e565b505050565b610c81611ee4565b600d54610c9782610c9160005490565b90611f9a565b1115610cb55760405162461bcd60e51b8152600401610b3c90613136565b600d54610cc582610c9160005490565b1415610cd957600f805460ff191660051790555b610ce33382611fad565b7ff00d28232b285f24f2e38415deb2ceb31069e70d4505838b3911b4f02058502e610d0d60005490565b60405190815260200160405180910390a150565b610d29611ee4565b6003600f5460ff166005811115610d4257610d42613329565b14610da65760405162461bcd60e51b815260206004820152602e60248201527f574c206d696e74206973206f6e676f696e672c20706c65617365206368616e6760448201526d329039ba30ba32903334b939ba1760911b6064820152608401610b3c565b600f80546004919060ff1916600183610a38565b610c74838383611fb7565b610dcd611ee4565b600b55565b610dda611ee4565b6001600f5460ff166005811115610df357610df3613329565b14610e5b5760405162461bcd60e51b815260206004820152603260248201527f5075626c6963206d696e74206973206f6e676f696e672c20706c6561736520636044820152713430b733b29039ba30ba32903334b939ba1760711b6064820152608401610b3c565b600f80546002919060ff1916600183610a38565b60606000610e7c83611a17565b90506000816001600160401b03811115610e9857610e98613355565b604051908082528060200260200182016040528015610ec1578160200160208202803683370190505b50905060005b82811015610f0857610ed98582610f10565b828281518110610eeb57610eeb61333f565b602090810291909101015280610f00816132ce565b915050610ec7565b509392505050565b6000610f1b83611a17565b8210610f745760405162461bcd60e51b815260206004820152602260248201527f455243373231413a206f776e657220696e646578206f7574206f6620626f756e604482015261647360f01b6064820152608401610b3c565b600080549080805b8381101561100c576000818152600360209081526040918290208251808401909352546001600160a01b038116808452600160a01b9091046001600160401b03169183019190915215610fce57805192505b876001600160a01b0316836001600160a01b031614156110035786841415610ffc57509350610a1b92505050565b6001909301925b50600101610f7c565b5060405162461bcd60e51b815260206004820152602e60248201527f455243373231413a20756e61626c6520746f2067657420746f6b656e206f662060448201526d0deeedccae440c4f240d2dcc8caf60931b6064820152608401610b3c565b6003600f5460ff16600581111561108557611085613329565b146110d25760405162461bcd60e51b815260206004820152601760248201527f574c204d696e7420686173206e6f7420737461727465640000000000000000006044820152606401610b3c565b600d546110e58560ff16610c9160005490565b11156111035760405162461bcd60e51b8152600401610b3c90613136565b61110e83838361229a565b6111715760405162461bcd60e51b815260206004820152602e60248201527f4163636f756e742061646472657373206e6f7420656c6967696c626c65286e6f60448201526d3a103830b93a1037b3102ba6149760911b6064820152608401610b3c565b61117c33838361229a565b6111985760405162461bcd60e51b8152600401610b3c906130eb565b60008460ff16116111bb5760405162461bcd60e51b8152600401610b3c906130b4565b336000908152601260205260409020546001906111dc9060ff871690613205565b11156111fa5760405162461bcd60e51b8152600401610b3c90613158565b336000908152601260205260408120805460ff8716929061121c908490613205565b9091555050600c5434906112349060ff871690613231565b11156112755760405162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f7567682066756e647360801b6044820152606401610b3c565b600d548460ff1661128560005490565b61128f9190613205565b14156112a357600f805460ff191660051790555b6112b0338560ff16611fad565b7ff00d28232b285f24f2e38415deb2ceb31069e70d4505838b3911b4f02058502e6112da60005490565b60405190815260200160405180910390a150505050565b6112f9611ee4565b600061130d6007546001600160a01b031690565b6001600160a01b03164760405160006040518083038185875af1925050503d8060008114611357576040519150601f19603f3d011682016040523d82523d6000602084013e61135c565b606091505b505090508061136a57600080fd5b50565b610c7483838360405180602001604052806000815250611c6a565b611390611ee4565b600d546113a18251610c9160005490565b11156113bf5760405162461bcd60e51b8152600401610b3c90613136565b600d546113d08251610c9160005490565b14156113e457600f805460ff191660051790555b60005b81518110156114265761141460018383815181106114075761140761333f565b6020026020010151611abc565b8061141e816132ce565b9150506113e7565b5050565b6000805482106114885760405162461bcd60e51b815260206004820152602360248201527f455243373231413a20676c6f62616c20696e646578206f7574206f6620626f756044820152626e647360e81b6064820152608401610b3c565b5090565b611494611ee4565b610c74600883836129f7565b6114a8611ee4565b8051611426906009906020840190612a77565b60006114c6826122e9565b5192915050565b6002600f5460ff1660058111156114e6576114e6613329565b146115335760405162461bcd60e51b815260206004820152601760248201527f4f47204d696e7420686173206e6f7420737461727465640000000000000000006044820152606401610b3c565b600d546115468560ff16610c9160005490565b11156115645760405162461bcd60e51b8152600401610b3c90613136565b61156f8383836123bf565b6115d25760405162461bcd60e51b815260206004820152602e60248201527f4163636f756e742061646472657373206e6f7420656c6967696c626c65286e6f60448201526d3a103830b93a1037b31027a3949760911b6064820152608401610b3c565b6115dd3383836123bf565b6115f95760405162461bcd60e51b8152600401610b3c906130eb565b60008460ff161161161c5760405162461bcd60e51b8152600401610b3c906130b4565b3360009081526011602052604090205460019061163d9060ff871690613205565b111561165b5760405162461bcd60e51b8152600401610b3c90613158565b336000908152601160205260408120805460ff8716929061121c908490613205565b6001600f5460ff16600581111561169657611696613329565b146116e35760405162461bcd60e51b815260206004820152601b60248201527f5075626c6963204d696e7420686173206e6f74207374617274656400000000006044820152606401610b3c565b600d546116f68260ff16610c9160005490565b11156117145760405162461bcd60e51b8152600401610b3c90613136565b336000908152601060205260409020546003906117359060ff841690613205565b11156117535760405162461bcd60e51b8152600401610b3c90613158565b60008160ff16116117765760405162461bcd60e51b8152600401610b3c906130b4565b336000908152601060205260408120805460ff84169290611798908490613205565b9091555050600b5434906117b09060ff841690613231565b11156117f15760405162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f7567682066756e647360801b6044820152606401610b3c565b600d548160ff1661180160005490565b61180b9190613205565b141561181f57600f805460ff191660051790555b610ce3338260ff16611fad565b611834611ee4565b6002600f5460ff16600581111561184d5761184d613329565b146118b15760405162461bcd60e51b815260206004820152602e60248201527f4f47206d696e74206973206f6e676f696e672c20706c65617365206368616e6760448201526d329039ba30ba32903334b939ba1760911b6064820152608401610b3c565b600f80546003919060ff1916600183610a38565b6005600f5460ff1660058111156118de576118de613329565b14156118fc5760405162461bcd60e51b8152600401610b3c90613136565b6004600f5460ff16600581111561191557611915613329565b146119625760405162461bcd60e51b815260206004820152601a60248201527f46696e616c2053616c6520686173206e6f7420737461727465640000000000006044820152606401610b3c565b600d546119758260ff16610c9160005490565b11156119935760405162461bcd60e51b8152600401610b3c90613136565b60008160ff16116119b65760405162461bcd60e51b8152600401610b3c906130b4565b336000908152601360205260409020546003906119d79060ff841690613205565b11156119f55760405162461bcd60e51b8152600401610b3c90613158565b336000908152601360205260408120805460ff84169290611798908490613205565b60006001600160a01b038216611a835760405162461bcd60e51b815260206004820152602b60248201527f455243373231413a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b6064820152608401610b3c565b506001600160a01b03166000908152600460205260409020546001600160801b031690565b611ab0611ee4565b611aba6000612406565b565b611ac4611ee4565b600d54611ad483610c9160005490565b1115611af25760405162461bcd60e51b8152600401610b3c90613136565b600d54611b0283610c9160005490565b1415611b1657600f805460ff191660051790555b611b208183611fad565b7ff00d28232b285f24f2e38415deb2ceb31069e70d4505838b3911b4f02058502e611b4a60005490565b60405190815260200160405180910390a15050565b611b67611ee4565b600c55565b6040805180820190915260008082526020820152610a1b826122e9565b611b91611ee4565b601555565b606060028054610a4e90613293565b6001600160a01b038216331415611bfe5760405162461bcd60e51b815260206004820152601a60248201527f455243373231413a20617070726f766520746f2063616c6c65720000000000006044820152606401610b3c565b3360008181526006602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611c75848484611fb7565b611c8184848484612458565b611c9d5760405162461bcd60e51b8152600401610b3c90613182565b50505050565b611cab611ee4565b600a805460ff19166001179055565b6060611cc7826000541190565b611d2c5760405162461bcd60e51b815260206004820152603060248201527f455243373231204d657461646174613a2055524920717565727920666f72206e60448201526f37b732bc34b9ba32b73a103a37b5b2b760811b6064820152608401610b3c565b600d54600054101580611d465750600a5460ff1615156001145b15611dc457600d54821015611dbf576000611d84600d54611d7e611d77600e54600d5461256590919063ffffffff16565b8690611f9a565b90612571565b9050611d8e61257d565b611d978261258c565b604051602001611da8929190612fa3565b604051602081830303815290604052915050919050565b919050565b60098054611dd190613293565b80601f0160208091040260200160405190810160405280929190818152602001828054611dfd90613293565b8015611e4a5780601f10611e1f57610100808354040283529160200191611e4a565b820191906000526020600020905b815481529060010190602001808311611e2d57829003601f168201915b50505050509050919050565b6000610a1b82612689565b611e69611ee4565b601455565b611e76611ee4565b6001600160a01b038116611edb5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b3c565b61136a81612406565b6007546001600160a01b03163314611aba5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b3c565b60008281526005602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000611fa68284613205565b9392505050565b6114268282612727565b6000611fc2826122e9565b80519091506000906001600160a01b0316336001600160a01b03161480611ff9575033611fee84610ad1565b6001600160a01b0316145b8061200b5750815161200b9033610966565b9050806120755760405162461bcd60e51b815260206004820152603260248201527f455243373231413a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b6064820152608401610b3c565b846001600160a01b031682600001516001600160a01b0316146120e95760405162461bcd60e51b815260206004820152602660248201527f455243373231413a207472616e736665722066726f6d20696e636f72726563746044820152651037bbb732b960d11b6064820152608401610b3c565b6001600160a01b03841661214d5760405162461bcd60e51b815260206004820152602560248201527f455243373231413a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b6064820152608401610b3c565b61215d6000848460000151611f3e565b6001600160a01b03858116600090815260046020908152604080832080546001600160801b03198082166001600160801b03928316600019018316179092558986168086528386208054938416938316600190810190931693909317909255888552600390935281842080546001600160e01b031916909117600160a01b426001600160401b03160217905590860180835291205490911661225057612204816000541190565b1561225057825160008281526003602090815260409091208054918601516001600160401b0316600160a01b026001600160e01b03199092166001600160a01b03909316929092171790555b5082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b5050505050565b60006122e16122a885612741565b84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061278092505050565b949350505050565b6040805180820190915260008082526020820152612308826000541190565b6123675760405162461bcd60e51b815260206004820152602a60248201527f455243373231413a206f776e657220717565727920666f72206e6f6e657869736044820152693a32b73a103a37b5b2b760b11b6064820152608401610b3c565b815b6000818152600360209081526040918290208251808401909352546001600160a01b038116808452600160a01b9091046001600160401b031691830191909152156123b5579392505050565b5060001901612369565b60006122e16123cd85612741565b84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061278f92505050565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006001600160a01b0384163b1561255a57604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061249c903390899088908890600401612ff8565b602060405180830381600087803b1580156124b657600080fd5b505af19250505080156124e6575060408051601f3d908101601f191682019092526124e391810190612dd3565b60015b612540573d808015612514576040519150601f19603f3d011682016040523d82523d6000602084013e612519565b606091505b5080516125385760405162461bcd60e51b8152600401610b3c90613182565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506122e1565b506001949350505050565b6000611fa68284613250565b6000611fa682846132e9565b606060088054610a4e90613293565b6060816125b05750506040805180820190915260018152600360fc1b602082015290565b8160005b81156125da57806125c4816132ce565b91506125d39050600a8361321d565b91506125b4565b6000816001600160401b038111156125f4576125f4613355565b6040519080825280601f01601f19166020018201604052801561261e576020820181803683370190505b5090505b84156122e157612633600183613250565b9150612640600a866132e9565b61264b906030613205565b60f81b8183815181106126605761266061333f565b60200101906001600160f81b031916908160001a905350612682600a8661321d565b9450612622565b60006001600160a01b0382166126fb5760405162461bcd60e51b815260206004820152603160248201527f455243373231413a206e756d626572206d696e74656420717565727920666f7260448201527020746865207a65726f206164647265737360781b6064820152608401610b3c565b506001600160a01b0316600090815260046020526040902054600160801b90046001600160801b031690565b61142682826040518060200160405280600081525061279e565b6040516bffffffffffffffffffffffff19606083901b166020820152600090603401604051602081830303815290604052805190602001209050919050565b6000611fa682601554856127ab565b6000611fa682601454856127ab565b610c7483838360016127c1565b6000826127b88584612983565b14949350505050565b6000546001600160a01b0385166128245760405162461bcd60e51b815260206004820152602160248201527f455243373231413a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610b3c565b836128825760405162461bcd60e51b815260206004820152602860248201527f455243373231413a207175616e74697479206d75737420626520677265617465604482015267072207468616e20360c41b6064820152608401610b3c565b6001600160a01b03851660008181526004602090815260408083208054600160801b6001600160801b031982166001600160801b039283168c01831690811782900483168c01909216021790558483526003909152812080546001600160e01b031916909217600160a01b426001600160401b0316021790915581905b8581101561297a5760405182906001600160a01b038916906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4831561296e576129526000888488612458565b61296e5760405162461bcd60e51b8152600401610b3c90613182565b600191820191016128ff565b50600055612293565b600081815b8451811015610f08576129b4828683815181106129a7576129a761333f565b60200260200101516129c8565b9150806129c0816132ce565b915050612988565b60008183106129e4576000828152602084905260409020611fa6565b6000838152602083905260409020611fa6565b828054612a0390613293565b90600052602060002090601f016020900481019282612a255760008555612a6b565b82601f10612a3e5782800160ff19823516178555612a6b565b82800160010185558215612a6b579182015b82811115612a6b578235825591602001919060010190612a50565b50611488929150612aeb565b828054612a8390613293565b90600052602060002090601f016020900481019282612aa55760008555612a6b565b82601f10612abe57805160ff1916838001178555612a6b565b82800160010185558215612a6b579182015b82811115612a6b578251825591602001919060010190612ad0565b5b808211156114885760008155600101612aec565b60006001600160401b03831115612b1957612b19613355565b612b2c601f8401601f19166020016131d5565b9050828152838383011115612b4057600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b0381168114611dbf57600080fd5b803560ff81168114611dbf57600080fd5b600060208284031215612b9157600080fd5b611fa682612b57565b60008060408385031215612bad57600080fd5b612bb683612b57565b9150612bc460208401612b57565b90509250929050565b600080600060608486031215612be257600080fd5b612beb84612b57565b9250612bf960208501612b57565b9150604084013590509250925092565b60008060008060808587031215612c1f57600080fd5b612c2885612b57565b9350612c3660208601612b57565b92506040850135915060608501356001600160401b03811115612c5857600080fd5b8501601f81018713612c6957600080fd5b612c7887823560208401612b00565b91505092959194509250565b60008060408385031215612c9757600080fd5b612ca083612b57565b915060208301358015158114612cb557600080fd5b809150509250929050565b60008060408385031215612cd357600080fd5b612cdc83612b57565b946020939093013593505050565b60006020808385031215612cfd57600080fd5b82356001600160401b0380821115612d1457600080fd5b818501915085601f830112612d2857600080fd5b813581811115612d3a57612d3a613355565b8060051b9150612d4b8483016131d5565b8181528481019084860184860187018a1015612d6657600080fd5b600095505b83861015612d9057612d7c81612b57565b835260019590950194918601918601612d6b565b5098975050505050505050565b600060208284031215612daf57600080fd5b5035919050565b600060208284031215612dc857600080fd5b8135611fa68161336b565b600060208284031215612de557600080fd5b8151611fa68161336b565b60008060208385031215612e0357600080fd5b82356001600160401b0380821115612e1a57600080fd5b818501915085601f830112612e2e57600080fd5b813581811115612e3d57600080fd5b866020828501011115612e4f57600080fd5b60209290920196919550909350505050565b600060208284031215612e7357600080fd5b81356001600160401b03811115612e8957600080fd5b8201601f81018413612e9a57600080fd5b6122e184823560208401612b00565b60008060408385031215612ebc57600080fd5b82359150612bc460208401612b57565b600060208284031215612ede57600080fd5b611fa682612b6e565b60008060008060608587031215612efd57600080fd5b612f0685612b6e565b9350612f1460208601612b57565b925060408501356001600160401b0380821115612f3057600080fd5b818701915087601f830112612f4457600080fd5b813581811115612f5357600080fd5b8860208260051b8501011115612f6857600080fd5b95989497505060200194505050565b60008151808452612f8f816020860160208601613267565b601f01601f19169290920160200192915050565b60008351612fb5818460208801613267565b6772656f706173732d60c01b9083019081528351612fda816008840160208801613267565b64173539b7b760d91b60089290910191820152600d01949350505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061302b90830184612f77565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561306d57835183529284019291840191600101613051565b50909695505050505050565b602081016006831061309b57634e487b7160e01b600052602160045260246000fd5b91905290565b602081526000611fa66020830184612f77565b6020808252601d908201527f4174206c65617374206f6e652073686f756c64206265206d696e746564000000604082015260600190565b6020808252602b908201527f4163636f756e742061646472657373206973206e6f74207468652066756e637460408201526a34b7b71031b0b63632b91760a91b606082015260800190565b60208082526008908201526714dbdb190813dd5d60c21b604082015260600190565b60208082526010908201526f13585e081391951cc814995858da195960821b604082015260600190565b60208082526033908201527f455243373231413a207472616e7366657220746f206e6f6e204552433732315260408201527232b1b2b4bb32b91034b6b83632b6b2b73a32b960691b606082015260800190565b604051601f8201601f191681016001600160401b03811182821017156131fd576131fd613355565b604052919050565b60008219821115613218576132186132fd565b500190565b60008261322c5761322c613313565b500490565b600081600019048311821515161561324b5761324b6132fd565b500290565b600082821015613262576132626132fd565b500390565b60005b8381101561328257818101518382015260200161326a565b83811115611c9d5750506000910152565b600181811c908216806132a757607f821691505b602082108114156132c857634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156132e2576132e26132fd565b5060010190565b6000826132f8576132f8613313565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b03198116811461136a57600080fdfea26469706673582212209b5e20ba6e5011cb764aca4805a1187d0e5f19045804611fce51df5cb2fd3c3764736f6c63430008070033

Deployed Bytecode

0x60806040526004361061031a5760003560e01c80636ae91737116101ab578063a22cb465116100f7578063cbccefb211610095578063dc33e6811161006f578063dc33e6811461090b578063e196c5d41461092b578063e985e9c51461094b578063f2fde38b1461099457600080fd5b8063cbccefb2146108b4578063d4c76e8b146108db578063dad8d8ca146108f157600080fd5b8063b2efedab116100d1578063b2efedab14610832578063b88d4fde1461085f578063bc0ac7461461087f578063c87b56dd1461089457600080fd5b8063a22cb465146107cf578063ac090ec6146107ef578063ad6cb3191461081c57600080fd5b80638da5cb5b1161016457806394bbc4ac1161013e57806394bbc4ac1461075757806395d89b4114610777578063973a2ccd1461078c5780639dfde201146107b957600080fd5b80638da5cb5b146106cc57806391b7f5ed146106ea5780639231ab2a1461070a57600080fd5b80636ae91737146106395780636ec192081461064e5780636ecd23061461066457806370a0823114610677578063715018a6146106975780637871e154146106ac57600080fd5b80632bf79c941161026a5780634a753f48116102235780635accac99116101fd5780635accac99146105d35780636352211e146105f3578063659deed81461061357806367dce1ed1461062657600080fd5b80634a753f48146105665780634f6ccce71461059357806355f804b3146105b357600080fd5b80632bf79c94146104be5780632f745c59146104eb57806338c5426f1461050b5780633ccfd60b1461051e57806342842e0e14610526578063486835031461054657600080fd5b80631618c8df116102d757806323b872dd116102b157806323b872dd14610453578063279ad4171461047357806329723719146104935780632bc79b16146104a857600080fd5b80631618c8df1461040957806318160ddd146104295780631d9cfd6d1461043e57600080fd5b806301ffc9a71461031f57806302456aa2146103545780630353025f1461036b57806306fdde031461038f578063081812fc146103b1578063095ea7b3146103e9575b600080fd5b34801561032b57600080fd5b5061033f61033a366004612db6565b6109b4565b60405190151581526020015b60405180910390f35b34801561036057600080fd5b50610369610a21565b005b34801561037757600080fd5b50610381600e5481565b60405190815260200161034b565b34801561039b57600080fd5b506103a4610a3f565b60405161034b91906130a1565b3480156103bd57600080fd5b506103d16103cc366004612d9d565b610ad1565b6040516001600160a01b03909116815260200161034b565b3480156103f557600080fd5b50610369610404366004612cc0565b610b61565b34801561041557600080fd5b50610369610424366004612d9d565b610c79565b34801561043557600080fd5b50600054610381565b34801561044a57600080fd5b50610369610d21565b34801561045f57600080fd5b5061036961046e366004612bcd565b610dba565b34801561047f57600080fd5b5061036961048e366004612d9d565b610dc5565b34801561049f57600080fd5b50610369610dd2565b3480156104b457600080fd5b5061038160155481565b3480156104ca57600080fd5b506104de6104d9366004612b7f565b610e6f565b60405161034b9190613035565b3480156104f757600080fd5b50610381610506366004612cc0565b610f10565b610369610519366004612ee7565b61106c565b6103696112f1565b34801561053257600080fd5b50610369610541366004612bcd565b61136d565b34801561055257600080fd5b50610369610561366004612cea565b611388565b34801561057257600080fd5b50610381610581366004612b7f565b60136020526000908152604090205481565b34801561059f57600080fd5b506103816105ae366004612d9d565b61142a565b3480156105bf57600080fd5b506103696105ce366004612df0565b61148c565b3480156105df57600080fd5b506103696105ee366004612e61565b6114a0565b3480156105ff57600080fd5b506103d161060e366004612d9d565b6114bb565b610369610621366004612ee7565b6114cd565b610369610634366004612ecc565b61167d565b34801561064557600080fd5b5061036961182c565b34801561065a57600080fd5b50610381600b5481565b610369610672366004612ecc565b6118c5565b34801561068357600080fd5b50610381610692366004612b7f565b611a17565b3480156106a357600080fd5b50610369611aa8565b3480156106b857600080fd5b506103696106c7366004612ea9565b611abc565b3480156106d857600080fd5b506007546001600160a01b03166103d1565b3480156106f657600080fd5b50610369610705366004612d9d565b611b5f565b34801561071657600080fd5b5061072a610725366004612d9d565b611b6c565b6040805182516001600160a01b031681526020928301516001600160401b0316928101929092520161034b565b34801561076357600080fd5b50610369610772366004612d9d565b611b89565b34801561078357600080fd5b506103a4611b96565b34801561079857600080fd5b506103816107a7366004612b7f565b60116020526000908152604090205481565b3480156107c557600080fd5b50610381600c5481565b3480156107db57600080fd5b506103696107ea366004612c84565b611ba5565b3480156107fb57600080fd5b5061038161080a366004612b7f565b60126020526000908152604090205481565b34801561082857600080fd5b5061038160145481565b34801561083e57600080fd5b5061038161084d366004612b7f565b60106020526000908152604090205481565b34801561086b57600080fd5b5061036961087a366004612c09565b611c6a565b34801561088b57600080fd5b50610369611ca3565b3480156108a057600080fd5b506103a46108af366004612d9d565b611cba565b3480156108c057600080fd5b50600f546108ce9060ff1681565b60405161034b9190613079565b3480156108e757600080fd5b50610381600d5481565b3480156108fd57600080fd5b50600a5461033f9060ff1681565b34801561091757600080fd5b50610381610926366004612b7f565b611e56565b34801561093757600080fd5b50610369610946366004612d9d565b611e61565b34801561095757600080fd5b5061033f610966366004612b9a565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b3480156109a057600080fd5b506103696109af366004612b7f565b611e6e565b60006001600160e01b031982166380ac58cd60e01b14806109e557506001600160e01b03198216635b5e139f60e01b145b80610a0057506001600160e01b0319821663780e9d6360e01b145b80610a1b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b610a29611ee4565b600f80546001919060ff191682805b0217905550565b606060018054610a4e90613293565b80601f0160208091040260200160405190810160405280929190818152602001828054610a7a90613293565b8015610ac75780601f10610a9c57610100808354040283529160200191610ac7565b820191906000526020600020905b815481529060010190602001808311610aaa57829003601f168201915b5050505050905090565b6000610ade826000541190565b610b455760405162461bcd60e51b815260206004820152602d60248201527f455243373231413a20617070726f76656420717565727920666f72206e6f6e6560448201526c3c34b9ba32b73a103a37b5b2b760991b60648201526084015b60405180910390fd5b506000908152600560205260409020546001600160a01b031690565b6000610b6c826114bb565b9050806001600160a01b0316836001600160a01b03161415610bdb5760405162461bcd60e51b815260206004820152602260248201527f455243373231413a20617070726f76616c20746f2063757272656e74206f776e60448201526132b960f11b6064820152608401610b3c565b336001600160a01b0382161480610bf75750610bf78133610966565b610c695760405162461bcd60e51b815260206004820152603960248201527f455243373231413a20617070726f76652063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f76656420666f7220616c6c000000000000006064820152608401610b3c565b610c74838383611f3e565b505050565b610c81611ee4565b600d54610c9782610c9160005490565b90611f9a565b1115610cb55760405162461bcd60e51b8152600401610b3c90613136565b600d54610cc582610c9160005490565b1415610cd957600f805460ff191660051790555b610ce33382611fad565b7ff00d28232b285f24f2e38415deb2ceb31069e70d4505838b3911b4f02058502e610d0d60005490565b60405190815260200160405180910390a150565b610d29611ee4565b6003600f5460ff166005811115610d4257610d42613329565b14610da65760405162461bcd60e51b815260206004820152602e60248201527f574c206d696e74206973206f6e676f696e672c20706c65617365206368616e6760448201526d329039ba30ba32903334b939ba1760911b6064820152608401610b3c565b600f80546004919060ff1916600183610a38565b610c74838383611fb7565b610dcd611ee4565b600b55565b610dda611ee4565b6001600f5460ff166005811115610df357610df3613329565b14610e5b5760405162461bcd60e51b815260206004820152603260248201527f5075626c6963206d696e74206973206f6e676f696e672c20706c6561736520636044820152713430b733b29039ba30ba32903334b939ba1760711b6064820152608401610b3c565b600f80546002919060ff1916600183610a38565b60606000610e7c83611a17565b90506000816001600160401b03811115610e9857610e98613355565b604051908082528060200260200182016040528015610ec1578160200160208202803683370190505b50905060005b82811015610f0857610ed98582610f10565b828281518110610eeb57610eeb61333f565b602090810291909101015280610f00816132ce565b915050610ec7565b509392505050565b6000610f1b83611a17565b8210610f745760405162461bcd60e51b815260206004820152602260248201527f455243373231413a206f776e657220696e646578206f7574206f6620626f756e604482015261647360f01b6064820152608401610b3c565b600080549080805b8381101561100c576000818152600360209081526040918290208251808401909352546001600160a01b038116808452600160a01b9091046001600160401b03169183019190915215610fce57805192505b876001600160a01b0316836001600160a01b031614156110035786841415610ffc57509350610a1b92505050565b6001909301925b50600101610f7c565b5060405162461bcd60e51b815260206004820152602e60248201527f455243373231413a20756e61626c6520746f2067657420746f6b656e206f662060448201526d0deeedccae440c4f240d2dcc8caf60931b6064820152608401610b3c565b6003600f5460ff16600581111561108557611085613329565b146110d25760405162461bcd60e51b815260206004820152601760248201527f574c204d696e7420686173206e6f7420737461727465640000000000000000006044820152606401610b3c565b600d546110e58560ff16610c9160005490565b11156111035760405162461bcd60e51b8152600401610b3c90613136565b61110e83838361229a565b6111715760405162461bcd60e51b815260206004820152602e60248201527f4163636f756e742061646472657373206e6f7420656c6967696c626c65286e6f60448201526d3a103830b93a1037b3102ba6149760911b6064820152608401610b3c565b61117c33838361229a565b6111985760405162461bcd60e51b8152600401610b3c906130eb565b60008460ff16116111bb5760405162461bcd60e51b8152600401610b3c906130b4565b336000908152601260205260409020546001906111dc9060ff871690613205565b11156111fa5760405162461bcd60e51b8152600401610b3c90613158565b336000908152601260205260408120805460ff8716929061121c908490613205565b9091555050600c5434906112349060ff871690613231565b11156112755760405162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f7567682066756e647360801b6044820152606401610b3c565b600d548460ff1661128560005490565b61128f9190613205565b14156112a357600f805460ff191660051790555b6112b0338560ff16611fad565b7ff00d28232b285f24f2e38415deb2ceb31069e70d4505838b3911b4f02058502e6112da60005490565b60405190815260200160405180910390a150505050565b6112f9611ee4565b600061130d6007546001600160a01b031690565b6001600160a01b03164760405160006040518083038185875af1925050503d8060008114611357576040519150601f19603f3d011682016040523d82523d6000602084013e61135c565b606091505b505090508061136a57600080fd5b50565b610c7483838360405180602001604052806000815250611c6a565b611390611ee4565b600d546113a18251610c9160005490565b11156113bf5760405162461bcd60e51b8152600401610b3c90613136565b600d546113d08251610c9160005490565b14156113e457600f805460ff191660051790555b60005b81518110156114265761141460018383815181106114075761140761333f565b6020026020010151611abc565b8061141e816132ce565b9150506113e7565b5050565b6000805482106114885760405162461bcd60e51b815260206004820152602360248201527f455243373231413a20676c6f62616c20696e646578206f7574206f6620626f756044820152626e647360e81b6064820152608401610b3c565b5090565b611494611ee4565b610c74600883836129f7565b6114a8611ee4565b8051611426906009906020840190612a77565b60006114c6826122e9565b5192915050565b6002600f5460ff1660058111156114e6576114e6613329565b146115335760405162461bcd60e51b815260206004820152601760248201527f4f47204d696e7420686173206e6f7420737461727465640000000000000000006044820152606401610b3c565b600d546115468560ff16610c9160005490565b11156115645760405162461bcd60e51b8152600401610b3c90613136565b61156f8383836123bf565b6115d25760405162461bcd60e51b815260206004820152602e60248201527f4163636f756e742061646472657373206e6f7420656c6967696c626c65286e6f60448201526d3a103830b93a1037b31027a3949760911b6064820152608401610b3c565b6115dd3383836123bf565b6115f95760405162461bcd60e51b8152600401610b3c906130eb565b60008460ff161161161c5760405162461bcd60e51b8152600401610b3c906130b4565b3360009081526011602052604090205460019061163d9060ff871690613205565b111561165b5760405162461bcd60e51b8152600401610b3c90613158565b336000908152601160205260408120805460ff8716929061121c908490613205565b6001600f5460ff16600581111561169657611696613329565b146116e35760405162461bcd60e51b815260206004820152601b60248201527f5075626c6963204d696e7420686173206e6f74207374617274656400000000006044820152606401610b3c565b600d546116f68260ff16610c9160005490565b11156117145760405162461bcd60e51b8152600401610b3c90613136565b336000908152601060205260409020546003906117359060ff841690613205565b11156117535760405162461bcd60e51b8152600401610b3c90613158565b60008160ff16116117765760405162461bcd60e51b8152600401610b3c906130b4565b336000908152601060205260408120805460ff84169290611798908490613205565b9091555050600b5434906117b09060ff841690613231565b11156117f15760405162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f7567682066756e647360801b6044820152606401610b3c565b600d548160ff1661180160005490565b61180b9190613205565b141561181f57600f805460ff191660051790555b610ce3338260ff16611fad565b611834611ee4565b6002600f5460ff16600581111561184d5761184d613329565b146118b15760405162461bcd60e51b815260206004820152602e60248201527f4f47206d696e74206973206f6e676f696e672c20706c65617365206368616e6760448201526d329039ba30ba32903334b939ba1760911b6064820152608401610b3c565b600f80546003919060ff1916600183610a38565b6005600f5460ff1660058111156118de576118de613329565b14156118fc5760405162461bcd60e51b8152600401610b3c90613136565b6004600f5460ff16600581111561191557611915613329565b146119625760405162461bcd60e51b815260206004820152601a60248201527f46696e616c2053616c6520686173206e6f7420737461727465640000000000006044820152606401610b3c565b600d546119758260ff16610c9160005490565b11156119935760405162461bcd60e51b8152600401610b3c90613136565b60008160ff16116119b65760405162461bcd60e51b8152600401610b3c906130b4565b336000908152601360205260409020546003906119d79060ff841690613205565b11156119f55760405162461bcd60e51b8152600401610b3c90613158565b336000908152601360205260408120805460ff84169290611798908490613205565b60006001600160a01b038216611a835760405162461bcd60e51b815260206004820152602b60248201527f455243373231413a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b6064820152608401610b3c565b506001600160a01b03166000908152600460205260409020546001600160801b031690565b611ab0611ee4565b611aba6000612406565b565b611ac4611ee4565b600d54611ad483610c9160005490565b1115611af25760405162461bcd60e51b8152600401610b3c90613136565b600d54611b0283610c9160005490565b1415611b1657600f805460ff191660051790555b611b208183611fad565b7ff00d28232b285f24f2e38415deb2ceb31069e70d4505838b3911b4f02058502e611b4a60005490565b60405190815260200160405180910390a15050565b611b67611ee4565b600c55565b6040805180820190915260008082526020820152610a1b826122e9565b611b91611ee4565b601555565b606060028054610a4e90613293565b6001600160a01b038216331415611bfe5760405162461bcd60e51b815260206004820152601a60248201527f455243373231413a20617070726f766520746f2063616c6c65720000000000006044820152606401610b3c565b3360008181526006602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611c75848484611fb7565b611c8184848484612458565b611c9d5760405162461bcd60e51b8152600401610b3c90613182565b50505050565b611cab611ee4565b600a805460ff19166001179055565b6060611cc7826000541190565b611d2c5760405162461bcd60e51b815260206004820152603060248201527f455243373231204d657461646174613a2055524920717565727920666f72206e60448201526f37b732bc34b9ba32b73a103a37b5b2b760811b6064820152608401610b3c565b600d54600054101580611d465750600a5460ff1615156001145b15611dc457600d54821015611dbf576000611d84600d54611d7e611d77600e54600d5461256590919063ffffffff16565b8690611f9a565b90612571565b9050611d8e61257d565b611d978261258c565b604051602001611da8929190612fa3565b604051602081830303815290604052915050919050565b919050565b60098054611dd190613293565b80601f0160208091040260200160405190810160405280929190818152602001828054611dfd90613293565b8015611e4a5780601f10611e1f57610100808354040283529160200191611e4a565b820191906000526020600020905b815481529060010190602001808311611e2d57829003601f168201915b50505050509050919050565b6000610a1b82612689565b611e69611ee4565b601455565b611e76611ee4565b6001600160a01b038116611edb5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b3c565b61136a81612406565b6007546001600160a01b03163314611aba5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b3c565b60008281526005602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000611fa68284613205565b9392505050565b6114268282612727565b6000611fc2826122e9565b80519091506000906001600160a01b0316336001600160a01b03161480611ff9575033611fee84610ad1565b6001600160a01b0316145b8061200b5750815161200b9033610966565b9050806120755760405162461bcd60e51b815260206004820152603260248201527f455243373231413a207472616e736665722063616c6c6572206973206e6f74206044820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b6064820152608401610b3c565b846001600160a01b031682600001516001600160a01b0316146120e95760405162461bcd60e51b815260206004820152602660248201527f455243373231413a207472616e736665722066726f6d20696e636f72726563746044820152651037bbb732b960d11b6064820152608401610b3c565b6001600160a01b03841661214d5760405162461bcd60e51b815260206004820152602560248201527f455243373231413a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b6064820152608401610b3c565b61215d6000848460000151611f3e565b6001600160a01b03858116600090815260046020908152604080832080546001600160801b03198082166001600160801b03928316600019018316179092558986168086528386208054938416938316600190810190931693909317909255888552600390935281842080546001600160e01b031916909117600160a01b426001600160401b03160217905590860180835291205490911661225057612204816000541190565b1561225057825160008281526003602090815260409091208054918601516001600160401b0316600160a01b026001600160e01b03199092166001600160a01b03909316929092171790555b5082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b5050505050565b60006122e16122a885612741565b84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061278092505050565b949350505050565b6040805180820190915260008082526020820152612308826000541190565b6123675760405162461bcd60e51b815260206004820152602a60248201527f455243373231413a206f776e657220717565727920666f72206e6f6e657869736044820152693a32b73a103a37b5b2b760b11b6064820152608401610b3c565b815b6000818152600360209081526040918290208251808401909352546001600160a01b038116808452600160a01b9091046001600160401b031691830191909152156123b5579392505050565b5060001901612369565b60006122e16123cd85612741565b84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061278f92505050565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006001600160a01b0384163b1561255a57604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061249c903390899088908890600401612ff8565b602060405180830381600087803b1580156124b657600080fd5b505af19250505080156124e6575060408051601f3d908101601f191682019092526124e391810190612dd3565b60015b612540573d808015612514576040519150601f19603f3d011682016040523d82523d6000602084013e612519565b606091505b5080516125385760405162461bcd60e51b8152600401610b3c90613182565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506122e1565b506001949350505050565b6000611fa68284613250565b6000611fa682846132e9565b606060088054610a4e90613293565b6060816125b05750506040805180820190915260018152600360fc1b602082015290565b8160005b81156125da57806125c4816132ce565b91506125d39050600a8361321d565b91506125b4565b6000816001600160401b038111156125f4576125f4613355565b6040519080825280601f01601f19166020018201604052801561261e576020820181803683370190505b5090505b84156122e157612633600183613250565b9150612640600a866132e9565b61264b906030613205565b60f81b8183815181106126605761266061333f565b60200101906001600160f81b031916908160001a905350612682600a8661321d565b9450612622565b60006001600160a01b0382166126fb5760405162461bcd60e51b815260206004820152603160248201527f455243373231413a206e756d626572206d696e74656420717565727920666f7260448201527020746865207a65726f206164647265737360781b6064820152608401610b3c565b506001600160a01b0316600090815260046020526040902054600160801b90046001600160801b031690565b61142682826040518060200160405280600081525061279e565b6040516bffffffffffffffffffffffff19606083901b166020820152600090603401604051602081830303815290604052805190602001209050919050565b6000611fa682601554856127ab565b6000611fa682601454856127ab565b610c7483838360016127c1565b6000826127b88584612983565b14949350505050565b6000546001600160a01b0385166128245760405162461bcd60e51b815260206004820152602160248201527f455243373231413a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610b3c565b836128825760405162461bcd60e51b815260206004820152602860248201527f455243373231413a207175616e74697479206d75737420626520677265617465604482015267072207468616e20360c41b6064820152608401610b3c565b6001600160a01b03851660008181526004602090815260408083208054600160801b6001600160801b031982166001600160801b039283168c01831690811782900483168c01909216021790558483526003909152812080546001600160e01b031916909217600160a01b426001600160401b0316021790915581905b8581101561297a5760405182906001600160a01b038916906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4831561296e576129526000888488612458565b61296e5760405162461bcd60e51b8152600401610b3c90613182565b600191820191016128ff565b50600055612293565b600081815b8451811015610f08576129b4828683815181106129a7576129a761333f565b60200260200101516129c8565b9150806129c0816132ce565b915050612988565b60008183106129e4576000828152602084905260409020611fa6565b6000838152602083905260409020611fa6565b828054612a0390613293565b90600052602060002090601f016020900481019282612a255760008555612a6b565b82601f10612a3e5782800160ff19823516178555612a6b565b82800160010185558215612a6b579182015b82811115612a6b578235825591602001919060010190612a50565b50611488929150612aeb565b828054612a8390613293565b90600052602060002090601f016020900481019282612aa55760008555612a6b565b82601f10612abe57805160ff1916838001178555612a6b565b82800160010185558215612a6b579182015b82811115612a6b578251825591602001919060010190612ad0565b5b808211156114885760008155600101612aec565b60006001600160401b03831115612b1957612b19613355565b612b2c601f8401601f19166020016131d5565b9050828152838383011115612b4057600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b0381168114611dbf57600080fd5b803560ff81168114611dbf57600080fd5b600060208284031215612b9157600080fd5b611fa682612b57565b60008060408385031215612bad57600080fd5b612bb683612b57565b9150612bc460208401612b57565b90509250929050565b600080600060608486031215612be257600080fd5b612beb84612b57565b9250612bf960208501612b57565b9150604084013590509250925092565b60008060008060808587031215612c1f57600080fd5b612c2885612b57565b9350612c3660208601612b57565b92506040850135915060608501356001600160401b03811115612c5857600080fd5b8501601f81018713612c6957600080fd5b612c7887823560208401612b00565b91505092959194509250565b60008060408385031215612c9757600080fd5b612ca083612b57565b915060208301358015158114612cb557600080fd5b809150509250929050565b60008060408385031215612cd357600080fd5b612cdc83612b57565b946020939093013593505050565b60006020808385031215612cfd57600080fd5b82356001600160401b0380821115612d1457600080fd5b818501915085601f830112612d2857600080fd5b813581811115612d3a57612d3a613355565b8060051b9150612d4b8483016131d5565b8181528481019084860184860187018a1015612d6657600080fd5b600095505b83861015612d9057612d7c81612b57565b835260019590950194918601918601612d6b565b5098975050505050505050565b600060208284031215612daf57600080fd5b5035919050565b600060208284031215612dc857600080fd5b8135611fa68161336b565b600060208284031215612de557600080fd5b8151611fa68161336b565b60008060208385031215612e0357600080fd5b82356001600160401b0380821115612e1a57600080fd5b818501915085601f830112612e2e57600080fd5b813581811115612e3d57600080fd5b866020828501011115612e4f57600080fd5b60209290920196919550909350505050565b600060208284031215612e7357600080fd5b81356001600160401b03811115612e8957600080fd5b8201601f81018413612e9a57600080fd5b6122e184823560208401612b00565b60008060408385031215612ebc57600080fd5b82359150612bc460208401612b57565b600060208284031215612ede57600080fd5b611fa682612b6e565b60008060008060608587031215612efd57600080fd5b612f0685612b6e565b9350612f1460208601612b57565b925060408501356001600160401b0380821115612f3057600080fd5b818701915087601f830112612f4457600080fd5b813581811115612f5357600080fd5b8860208260051b8501011115612f6857600080fd5b95989497505060200194505050565b60008151808452612f8f816020860160208601613267565b601f01601f19169290920160200192915050565b60008351612fb5818460208801613267565b6772656f706173732d60c01b9083019081528351612fda816008840160208801613267565b64173539b7b760d91b60089290910191820152600d01949350505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061302b90830184612f77565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561306d57835183529284019291840191600101613051565b50909695505050505050565b602081016006831061309b57634e487b7160e01b600052602160045260246000fd5b91905290565b602081526000611fa66020830184612f77565b6020808252601d908201527f4174206c65617374206f6e652073686f756c64206265206d696e746564000000604082015260600190565b6020808252602b908201527f4163636f756e742061646472657373206973206e6f74207468652066756e637460408201526a34b7b71031b0b63632b91760a91b606082015260800190565b60208082526008908201526714dbdb190813dd5d60c21b604082015260600190565b60208082526010908201526f13585e081391951cc814995858da195960821b604082015260600190565b60208082526033908201527f455243373231413a207472616e7366657220746f206e6f6e204552433732315260408201527232b1b2b4bb32b91034b6b83632b6b2b73a32b960691b606082015260800190565b604051601f8201601f191681016001600160401b03811182821017156131fd576131fd613355565b604052919050565b60008219821115613218576132186132fd565b500190565b60008261322c5761322c613313565b500490565b600081600019048311821515161561324b5761324b6132fd565b500290565b600082821015613262576132626132fd565b500390565b60005b8381101561328257818101518382015260200161326a565b83811115611c9d5750506000910152565b600181811c908216806132a757607f821691505b602082108114156132c857634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156132e2576132e26132fd565b5060010190565b6000826132f8576132f8613313565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b03198116811461136a57600080fdfea26469706673582212209b5e20ba6e5011cb764aca4805a1187d0e5f19045804611fce51df5cb2fd3c3764736f6c63430008070033

Deployed Bytecode Sourcemap

56938:8533:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41047:372;;;;;;;;;;-1:-1:-1;41047:372:0;;;;;:::i;:::-;;:::i;:::-;;;9933:14:1;;9926:22;9908:41;;9896:2;9881:18;41047:372:0;;;;;;;;62475:87;;;;;;;;;;;;;:::i;:::-;;57267:29;;;;;;;;;;;;;;;;;;;10106:25:1;;;10094:2;10079:18;57267:29:0;9960:177:1;42933:100:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;44495:214::-;;;;;;;;;;-1:-1:-1;44495:214:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;8594:32:1;;;8576:51;;8564:2;8549:18;44495:214:0;8430:203:1;44016:413:0;;;;;;;;;;-1:-1:-1;44016:413:0;;;;;:::i;:::-;;:::i;61573:265::-;;;;;;;;;;-1:-1:-1;61573:265:0;;;;;:::i;:::-;;:::i;39304:100::-;;;;;;;;;;-1:-1:-1;39357:7:0;39384:12;39304:100;;62933:168;;;;;;;;;;;;;:::i;45371:162::-;;;;;;;;;;-1:-1:-1;45371:162:0;;;;;:::i;:::-;;:::i;63327:124::-;;;;;;;;;;-1:-1:-1;63327:124:0;;;;;:::i;:::-;;:::i;62568:180::-;;;;;;;;;;;;;:::i;57673:33::-;;;;;;;;;;;;;;;;64663:317;;;;;;;;;;-1:-1:-1;64663:317:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;39968:1007::-;;;;;;;;;;-1:-1:-1;39968:1007:0;;;;;:::i;:::-;;:::i;59874:847::-;;;;;;:::i;:::-;;:::i;65317:147::-;;;:::i;45604:177::-;;;;;;;;;;-1:-1:-1;45604:177:0;;;;;:::i;:::-;;:::i;62131:338::-;;;;;;;;;;-1:-1:-1;62131:338:0;;;;;:::i;:::-;;:::i;57588:48::-;;;;;;;;;;-1:-1:-1;57588:48:0;;;;;:::i;:::-;;;;;;;;;;;;;;39481:187;;;;;;;;;;-1:-1:-1;39481:187:0;;;;;:::i;:::-;;:::i;63107:95::-;;;;;;;;;;-1:-1:-1;63107:95:0;;;;;:::i;:::-;;:::i;63208:113::-;;;;;;;;;;-1:-1:-1;63208:113:0;;;;;:::i;:::-;;:::i;42742:124::-;;;;;;;;;;-1:-1:-1;42742:124:0;;;;;:::i;:::-;;:::i;59029:839::-;;;;;;:::i;:::-;;:::i;58397:626::-;;;;;;:::i;:::-;;:::i;62754:172::-;;;;;;;;;;;;;:::i;57149:43::-;;;;;;;;;;;;;;;;60727:730;;;;;;:::i;:::-;;:::i;41483:221::-;;;;;;;;;;-1:-1:-1;41483:221:0;;;;;:::i;:::-;;:::i;56052:103::-;;;;;;;;;;;;;:::i;61844:281::-;;;;;;;;;;-1:-1:-1;61844:281:0;;;;;:::i;:::-;;:::i;55404:87::-;;;;;;;;;;-1:-1:-1;55477:6:0;;-1:-1:-1;;;;;55477:6:0;55404:87;;63457:84;;;;;;;;;;-1:-1:-1;63457:84:0;;;;;:::i;:::-;;:::i;64986:129::-;;;;;;;;;;-1:-1:-1;64986:129:0;;;;;:::i;:::-;;:::i;:::-;;;;24356:13:1;;-1:-1:-1;;;;;24352:39:1;24334:58;;24452:4;24440:17;;;24434:24;-1:-1:-1;;;;;24430:49:1;24408:20;;;24401:79;;;;24307:18;64986:129:0;24124:362:1;64488:143:0;;;;;;;;;;-1:-1:-1;64488:143:0;;;;;:::i;:::-;;:::i;43102:104::-;;;;;;;;;;;;;:::i;57488:45::-;;;;;;;;;;-1:-1:-1;57488:45:0;;;;;:::i;:::-;;;;;;;;;;;;;;57197:30;;;;;;;;;;;;;;;;44781:288;;;;;;;;;;-1:-1:-1;44781:288:0;;;;;:::i;:::-;;:::i;57538:45::-;;;;;;;;;;-1:-1:-1;57538:45:0;;;;;:::i;:::-;;;;;;;;;;;;;;57641:27;;;;;;;;;;;;;;;;57434:49;;;;;;;;;;-1:-1:-1;57434:49:0;;;;;:::i;:::-;;;;;;;;;;;;;;45852:355;;;;;;;;;;-1:-1:-1;45852:355:0;;;;;:::i;:::-;;:::i;65234:77::-;;;;;;;;;;;;;:::i;57890:501::-;;;;;;;;;;-1:-1:-1;57890:501:0;;;;;:::i;:::-;;:::i;57405:24::-;;;;;;;;;;-1:-1:-1;57405:24:0;;;;;;;;;;;;;;;:::i;57232:30::-;;;;;;;;;;;;;;;;57110:34;;;;;;;;;;-1:-1:-1;57110:34:0;;;;;;;;65121:107;;;;;;;;;;-1:-1:-1;65121:107:0;;;;;:::i;:::-;;:::i;64011:117::-;;;;;;;;;;-1:-1:-1;64011:117:0;;;;;:::i;:::-;;:::i;45140:164::-;;;;;;;;;;-1:-1:-1;45140:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;45261:25:0;;;45237:4;45261:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;45140:164;56310:201;;;;;;;;;;-1:-1:-1;56310:201:0;;;;;:::i;:::-;;:::i;41047:372::-;41149:4;-1:-1:-1;;;;;;41186:40:0;;-1:-1:-1;;;41186:40:0;;:105;;-1:-1:-1;;;;;;;41243:48:0;;-1:-1:-1;;;41243:48:0;41186:105;:172;;;-1:-1:-1;;;;;;;41308:50:0;;-1:-1:-1;;;41308:50:0;41186:172;:225;;;-1:-1:-1;;;;;;;;;;29800:40:0;;;41375:36;41166:245;41047:372;-1:-1:-1;;41047:372:0:o;62475:87::-;55290:13;:11;:13::i;:::-;62526:11:::1;:30:::0;;62540:16:::1;::::0;62526:11;-1:-1:-1;;62526:30:0::1;62540:16:::0;;62526:30:::1;;;;;;62475:87::o:0;42933:100::-;42987:13;43020:5;43013:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42933:100;:::o;44495:214::-;44563:7;44591:16;44599:7;46519:4;46553:12;-1:-1:-1;46543:22:0;46462:111;44591:16;44583:74;;;;-1:-1:-1;;;44583:74:0;;23495:2:1;44583:74:0;;;23477:21:1;23534:2;23514:18;;;23507:30;23573:34;23553:18;;;23546:62;-1:-1:-1;;;23624:18:1;;;23617:43;23677:19;;44583:74:0;;;;;;;;;-1:-1:-1;44677:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;44677:24:0;;44495:214::o;44016:413::-;44089:13;44105:24;44121:7;44105:15;:24::i;:::-;44089:40;;44154:5;-1:-1:-1;;;;;44148:11:0;:2;-1:-1:-1;;;;;44148:11:0;;;44140:58;;;;-1:-1:-1;;;44140:58:0;;20323:2:1;44140:58:0;;;20305:21:1;20362:2;20342:18;;;20335:30;20401:34;20381:18;;;20374:62;-1:-1:-1;;;20452:18:1;;;20445:32;20494:19;;44140:58:0;20121:398:1;44140:58:0;37381:10;-1:-1:-1;;;;;44233:21:0;;;;:62;;-1:-1:-1;44258:37:0;44275:5;37381:10;45140:164;:::i;44258:37::-;44211:169;;;;-1:-1:-1;;;44211:169:0;;17113:2:1;44211:169:0;;;17095:21:1;17152:2;17132:18;;;17125:30;17191:34;17171:18;;;17164:62;17262:27;17242:18;;;17235:55;17307:19;;44211:169:0;16911:421:1;44211:169:0;44393:28;44402:2;44406:7;44415:5;44393:8;:28::i;:::-;44078:351;44016:413;;:::o;61573:265::-;55290:13;:11;:13::i;:::-;61663:8:::1;;61637:22;61655:3;61637:13;39357:7:::0;39384:12;;39304:100;61637:13:::1;:17:::0;::::1;:22::i;:::-;:34;;61629:55;;;;-1:-1:-1::0;;;61629:55:0::1;;;;;;;:::i;:::-;61720:8;;61694:22;61712:3;61694:13;39357:7:::0;39384:12;;39304:100;61694:22:::1;:34;61691:71;;;61732:11;:27:::0;;-1:-1:-1;;61732:27:0::1;61746:13;61732:27;::::0;;61691:71:::1;61772:22;61778:10;61790:3;61772:5;:22::i;:::-;61806:26;61818:13;39357:7:::0;39384:12;;39304:100;61818:13:::1;61806:26;::::0;10106:25:1;;;10094:2;10079:18;61806:26:0::1;;;;;;;61573:265:::0;:::o;62933:168::-;55290:13;:11;:13::i;:::-;63001:12:::1;62986:11;::::0;::::1;;:27;::::0;::::1;;;;;;:::i;:::-;;62978:86;;;::::0;-1:-1:-1;;;62978:86:0;;19134:2:1;62978:86:0::1;::::0;::::1;19116:21:1::0;19173:2;19153:18;;;19146:30;19212:34;19192:18;;;19185:62;-1:-1:-1;;;19263:18:1;;;19256:44;19317:19;;62978:86:0::1;18932:410:1::0;62978:86:0::1;63071:11;:24:::0;;63085:10:::1;::::0;63071:11;-1:-1:-1;;63071:24:0::1;::::0;63085:10;63071:24:::1;::::0;45371:162;45497:28;45507:4;45513:2;45517:7;45497:9;:28::i;63327:124::-;55290:13;:11;:13::i;:::-;63408:15:::1;:37:::0;63327:124::o;62568:180::-;55290:13;:11;:13::i;:::-;62638:16:::1;62623:11;::::0;::::1;;:31;::::0;::::1;;;;;;:::i;:::-;;62615:94;;;::::0;-1:-1:-1;;;62615:94:0;;16694:2:1;62615:94:0::1;::::0;::::1;16676:21:1::0;16733:2;16713:18;;;16706:30;16772:34;16752:18;;;16745:62;-1:-1:-1;;;16823:18:1;;;16816:48;16881:19;;62615:94:0::1;16492:414:1::0;62615:94:0::1;62716:11;:26:::0;;62730:12:::1;::::0;62716:11;-1:-1:-1;;62716:26:0::1;::::0;62730:12;62716:26:::1;::::0;64663:317;64725:16;64750:18;64771:17;64781:6;64771:9;:17::i;:::-;64750:38;;64795:25;64837:10;-1:-1:-1;;;;;64823:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64823:25:0;;64795:53;;64860:9;64855:98;64875:10;64871:1;:14;64855:98;;;64915:30;64935:6;64943:1;64915:19;:30::i;:::-;64901:8;64910:1;64901:11;;;;;;;;:::i;:::-;;;;;;;;;;:44;64887:3;;;;:::i;:::-;;;;64855:98;;;-1:-1:-1;64966:8:0;64663:317;-1:-1:-1;;;64663:317:0:o;39968:1007::-;40057:7;40093:16;40103:5;40093:9;:16::i;:::-;40085:5;:24;40077:71;;;;-1:-1:-1;;;40077:71:0;;10911:2:1;40077:71:0;;;10893:21:1;10950:2;10930:18;;;10923:30;10989:34;10969:18;;;10962:62;-1:-1:-1;;;11040:18:1;;;11033:32;11082:19;;40077:71:0;10709:398:1;40077:71:0;40159:22;39384:12;;;40159:22;;40422:466;40442:14;40438:1;:18;40422:466;;;40482:31;40516:14;;;:11;:14;;;;;;;;;40482:48;;;;;;;;;-1:-1:-1;;;;;40482:48:0;;;;;-1:-1:-1;;;40482:48:0;;;-1:-1:-1;;;;;40482:48:0;;;;;;;;40553:28;40549:111;;40626:14;;;-1:-1:-1;40549:111:0;40703:5;-1:-1:-1;;;;;40682:26:0;:17;-1:-1:-1;;;;;40682:26:0;;40678:195;;;40752:5;40737:11;:20;40733:85;;;-1:-1:-1;40793:1:0;-1:-1:-1;40786:8:0;;-1:-1:-1;;;40786:8:0;40733:85;40840:13;;;;;40678:195;-1:-1:-1;40458:3:0;;40422:466;;;-1:-1:-1;40911:56:0;;-1:-1:-1;;;40911:56:0;;22309:2:1;40911:56:0;;;22291:21:1;22348:2;22328:18;;;22321:30;22387:34;22367:18;;;22360:62;-1:-1:-1;;;22438:18:1;;;22431:44;22492:19;;40911:56:0;22107:410:1;59874:847:0;59999:12;59984:11;;;;:27;;;;;;;;:::i;:::-;;59976:63;;;;-1:-1:-1;;;59976:63:0;;20726:2:1;59976:63:0;;;20708:21:1;20765:2;20745:18;;;20738:30;20804:25;20784:18;;;20777:53;20847:18;;59976:63:0;20524:347:1;59976:63:0;60087:8;;60054:29;60072:10;60054:29;;:13;39357:7;39384:12;;39304:100;60054:29;:41;;60046:62;;;;-1:-1:-1;;;60046:62:0;;;;;;;:::i;:::-;60123:37;60143:8;60153:6;;60123:19;:37::i;:::-;60115:96;;;;-1:-1:-1;;;60115:96:0;;12851:2:1;60115:96:0;;;12833:21:1;12890:2;12870:18;;;12863:30;12929:34;12909:18;;;12902:62;-1:-1:-1;;;12980:18:1;;;12973:44;13034:19;;60115:96:0;12649:410:1;60115:96:0;60226:39;60246:10;60258:6;;60226:19;:39::i;:::-;60218:95;;;;-1:-1:-1;;;60218:95:0;;;;;;;:::i;:::-;60341:1;60328:10;:14;;;60320:56;;;;-1:-1:-1;;;60320:56:0;;;;;;;:::i;:::-;60401:10;60391:21;;;;:9;:21;;;;;;60429:1;;60391:34;;;;;;;:::i;:::-;:39;;60383:68;;;;-1:-1:-1;;;60383:68:0;;;;;;;:::i;:::-;60468:10;60458:21;;;;:9;:21;;;;;:35;;;;;;:21;:35;;;;;:::i;:::-;;;;-1:-1:-1;;60508:5:0;;60530:9;;60508:18;;;;;;;:::i;:::-;:31;;60500:60;;;;-1:-1:-1;;;60500:60:0;;14765:2:1;60500:60:0;;;14747:21:1;14804:2;14784:18;;;14777:30;-1:-1:-1;;;14823:18:1;;;14816:46;14879:18;;60500:60:0;14563:340:1;60500:60:0;60600:8;;60586:10;60570:26;;:13;39357:7;39384:12;;39304:100;60570:13;:26;;;;:::i;:::-;:38;60567:75;;;60612:11;:27;;-1:-1:-1;;60612:27:0;60626:13;60612:27;;;60567:75;60648:29;60654:10;60666;60648:29;;:5;:29::i;:::-;60689:26;60701:13;39357:7;39384:12;;39304:100;60701:13;60689:26;;10106:25:1;;;10094:2;10079:18;60689:26:0;;;;;;;59874:847;;;;:::o;65317:147::-;55290:13;:11;:13::i;:::-;65370:8:::1;65392:7;55477:6:::0;;-1:-1:-1;;;;;55477:6:0;;55404:87;65392:7:::1;-1:-1:-1::0;;;;;65384:21:0::1;65413;65384:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65369:70;;;65454:3;65446:12;;;::::0;::::1;;65362:102;65317:147::o:0;45604:177::-;45734:39;45751:4;45757:2;45761:7;45734:39;;;;;;;;;;;;:16;:39::i;62131:338::-;55290:13;:11;:13::i;:::-;62254:8:::1;;62215:35;62233:9;:16;62215:13;39357:7:::0;39384:12;;39304:100;62215:35:::1;:47;;62207:68;;;;-1:-1:-1::0;;;62207:68:0::1;;;;;;;:::i;:::-;62324:8;;62285:35;62303:9;:16;62285:13;39357:7:::0;39384:12;;39304:100;62285:35:::1;:47;62282:84;;;62336:11;:27:::0;;-1:-1:-1;;62336:27:0::1;62350:13;62336:27;::::0;;62282:84:::1;62381:9;62376:88;62400:9;:16;62396:1;:20;62376:88;;;62432:24;62440:1;62443:9;62453:1;62443:12;;;;;;;;:::i;:::-;;;;;;;62432:7;:24::i;:::-;62418:3:::0;::::1;::::0;::::1;:::i;:::-;;;;62376:88;;;;62131:338:::0;:::o;39481:187::-;39548:7;39384:12;;39576:5;:21;39568:69;;;;-1:-1:-1;;;39568:69:0;;15466:2:1;39568:69:0;;;15448:21:1;15505:2;15485:18;;;15478:30;15544:34;15524:18;;;15517:62;-1:-1:-1;;;15595:18:1;;;15588:33;15638:19;;39568:69:0;15264:399:1;39568:69:0;-1:-1:-1;39655:5:0;39481:187::o;63107:95::-;55290:13;:11;:13::i;:::-;63178:18:::1;:8;63189:7:::0;;63178:18:::1;:::i;63208:113::-:0;55290:13;:11;:13::i;:::-;63287:28;;::::1;::::0;:13:::1;::::0;:28:::1;::::0;::::1;::::0;::::1;:::i;42742:124::-:0;42806:7;42833:20;42845:7;42833:11;:20::i;:::-;:25;;42742:124;-1:-1:-1;;42742:124:0:o;59029:839::-;59154:12;59139:11;;;;:27;;;;;;;;:::i;:::-;;59131:63;;;;-1:-1:-1;;;59131:63:0;;11314:2:1;59131:63:0;;;11296:21:1;11353:2;11333:18;;;11326:30;11392:25;11372:18;;;11365:53;11435:18;;59131:63:0;11112:347:1;59131:63:0;59242:8;;59209:29;59227:10;59209:29;;:13;39357:7;39384:12;;39304:100;59209:29;:41;;59201:62;;;;-1:-1:-1;;;59201:62:0;;;;;;;:::i;:::-;59278:33;59294:8;59304:6;;59278:15;:33::i;:::-;59270:92;;;;-1:-1:-1;;;59270:92:0;;18358:2:1;59270:92:0;;;18340:21:1;18397:2;18377:18;;;18370:30;18436:34;18416:18;;;18409:62;-1:-1:-1;;;18487:18:1;;;18480:44;18541:19;;59270:92:0;18156:410:1;59270:92:0;59377:35;59393:10;59405:6;;59377:15;:35::i;:::-;59369:91;;;;-1:-1:-1;;;59369:91:0;;;;;;;:::i;:::-;59488:1;59475:10;:14;;;59467:56;;;;-1:-1:-1;;;59467:56:0;;;;;;;:::i;:::-;59548:10;59538:21;;;;:9;:21;;;;;;59576:1;;59538:34;;;;;;;:::i;:::-;:39;;59530:68;;;;-1:-1:-1;;;59530:68:0;;;;;;;:::i;:::-;59615:10;59605:21;;;;:9;:21;;;;;:35;;;;;;:21;:35;;;;;:::i;58397:626::-;58480:16;58465:11;;;;:31;;;;;;;;:::i;:::-;;58457:71;;;;-1:-1:-1;;;58457:71:0;;15110:2:1;58457:71:0;;;15092:21:1;15149:2;15129:18;;;15122:30;15188:29;15168:18;;;15161:57;15235:18;;58457:71:0;14908:351:1;58457:71:0;58576:8;;58543:29;58561:10;58543:29;;:13;39357:7;39384:12;;39304:100;58543:29;:41;;58535:62;;;;-1:-1:-1;;;58535:62:0;;;;;;;:::i;:::-;58626:10;58612:25;;;;:13;:25;;;;;;58654:1;;58612:38;;;;;;;:::i;:::-;:43;;58604:72;;;;-1:-1:-1;;;58604:72:0;;;;;;;:::i;:::-;58704:1;58691:10;:14;;;58683:56;;;;-1:-1:-1;;;58683:56:0;;;;;;;:::i;:::-;58760:10;58746:25;;;;:13;:25;;;;;:39;;;;;;:25;:39;;;;;:::i;:::-;;;;-1:-1:-1;;58800:15:0;;58832:9;;58800:28;;;;;;;:::i;:::-;:41;;58792:70;;;;-1:-1:-1;;;58792:70:0;;14765:2:1;58792:70:0;;;14747:21:1;14804:2;14784:18;;;14777:30;-1:-1:-1;;;14823:18:1;;;14816:46;14879:18;;58792:70:0;14563:340:1;58792:70:0;58902:8;;58888:10;58872:26;;:13;39357:7;39384:12;;39304:100;58872:13;:26;;;;:::i;:::-;:38;58869:75;;;58914:11;:27;;-1:-1:-1;;58914:27:0;58928:13;58914:27;;;58869:75;58950:29;58956:10;58968;58950:29;;:5;:29::i;62754:172::-;55290:13;:11;:13::i;:::-;62824:12:::1;62809:11;::::0;::::1;;:27;::::0;::::1;;;;;;:::i;:::-;;62801:86;;;::::0;-1:-1:-1;;;62801:86:0;;12024:2:1;62801:86:0::1;::::0;::::1;12006:21:1::0;12063:2;12043:18;;;12036:30;12102:34;12082:18;;;12075:62;-1:-1:-1;;;12153:18:1;;;12146:44;12207:19;;62801:86:0::1;11822:410:1::0;62801:86:0::1;62894:11;:26:::0;;62908:12:::1;::::0;62894:11;-1:-1:-1;;62894:26:0::1;::::0;62908:12;62894:26:::1;::::0;60727:730;60804:13;60789:11;;;;:28;;;;;;;;:::i;:::-;;;60781:49;;;;-1:-1:-1;;;60781:49:0;;;;;;;:::i;:::-;60860:10;60845:11;;;;:25;;;;;;;;:::i;:::-;;60837:64;;;;-1:-1:-1;;;60837:64:0;;23140:2:1;60837:64:0;;;23122:21:1;23179:2;23159:18;;;23152:30;23218:28;23198:18;;;23191:56;23264:18;;60837:64:0;22938:350:1;60837:64:0;60949:8;;60916:29;60934:10;60916:29;;:13;39357:7;39384:12;;39304:100;60916:29;:41;;60908:62;;;;-1:-1:-1;;;60908:62:0;;;;;;;:::i;:::-;61002:1;60989:10;:14;;;60981:56;;;;-1:-1:-1;;;60981:56:0;;;;;;;:::i;:::-;61123:10;61110:24;;;;:12;:24;;;;;;61151:1;;61110:37;;;;;;;:::i;:::-;:42;;61102:71;;;;-1:-1:-1;;;61102:71:0;;;;;;;:::i;:::-;61193:10;61180:24;;;;:12;:24;;;;;:38;;;;;;:24;:38;;;;;:::i;41483:221::-;41547:7;-1:-1:-1;;;;;41575:19:0;;41567:75;;;;-1:-1:-1;;;41567:75:0;;17539:2:1;41567:75:0;;;17521:21:1;17578:2;17558:18;;;17551:30;17617:34;17597:18;;;17590:62;-1:-1:-1;;;17668:18:1;;;17661:41;17719:19;;41567:75:0;17337:407:1;41567:75:0;-1:-1:-1;;;;;;41668:19:0;;;;;:12;:19;;;;;:27;-1:-1:-1;;;;;41668:27:0;;41483:221::o;56052:103::-;55290:13;:11;:13::i;:::-;56117:30:::1;56144:1;56117:18;:30::i;:::-;56052:103::o:0;61844:281::-;55290:13;:11;:13::i;:::-;61951:8:::1;;61925:22;61943:3;61925:13;39357:7:::0;39384:12;;39304:100;61925:22:::1;:34;;61917:55;;;;-1:-1:-1::0;;;61917:55:0::1;;;;;;;:::i;:::-;62008:8;;61982:22;62000:3;61982:13;39357:7:::0;39384:12;;39304:100;61982:22:::1;:34;61979:71;;;62020:11;:27:::0;;-1:-1:-1;;62020:27:0::1;62034:13;62020:27;::::0;;61979:71:::1;62060:21;62066:9;62077:3;62060:5;:21::i;:::-;62093:26;62105:13;39357:7:::0;39384:12;;39304:100;62105:13:::1;62093:26;::::0;10106:25:1;;;10094:2;10079:18;62093:26:0::1;;;;;;;61844:281:::0;;:::o;63457:84::-;55290:13;:11;:13::i;:::-;63518:5:::1;:17:::0;63457:84::o;64986:129::-;-1:-1:-1;;;;;;;;;;;;;;;;;65089:20:0;65101:7;65089:11;:20::i;64488:143::-;55290:13;:11;:13::i;:::-;64582:18:::1;:43:::0;64488:143::o;43102:104::-;43158:13;43191:7;43184:14;;;;;:::i;44781:288::-;-1:-1:-1;;;;;44876:24:0;;37381:10;44876:24;;44868:63;;;;-1:-1:-1;;;44868:63:0;;19549:2:1;44868:63:0;;;19531:21:1;19588:2;19568:18;;;19561:30;19627:28;19607:18;;;19600:56;19673:18;;44868:63:0;19347:350:1;44868:63:0;37381:10;44944:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;44944:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;44944:53:0;;;;;;;;;;45013:48;;9908:41:1;;;44944:42:0;;37381:10;45013:48;;9881:18:1;45013:48:0;;;;;;;44781:288;;:::o;45852:355::-;46011:28;46021:4;46027:2;46031:7;46011:9;:28::i;:::-;46072:48;46095:4;46101:2;46105:7;46114:5;46072:22;:48::i;:::-;46050:149;;;;-1:-1:-1;;;46050:149:0;;;;;;;:::i;:::-;45852:355;;;;:::o;65234:77::-;55290:13;:11;:13::i;:::-;65284:14:::1;:21:::0;;-1:-1:-1;;65284:21:0::1;65301:4;65284:21;::::0;;65234:77::o;57890:501::-;57963:15;57995:16;58003:7;46519:4;46553:12;-1:-1:-1;46543:22:0;46462:111;57995:16;57987:77;;;;-1:-1:-1;;;57987:77:0;;23909:2:1;57987:77:0;;;23891:21:1;23948:2;23928:18;;;23921:30;23987:34;23967:18;;;23960:62;-1:-1:-1;;;24038:18:1;;;24031:46;24094:19;;57987:77:0;23707:412:1;57987:77:0;58092:8;;39357:7;39384:12;58075:25;;:51;;;-1:-1:-1;58104:14:0;;;;:22;;:14;:22;58075:51;58071:315;;;58151:8;;58141:7;:18;58137:211;;;58172:16;58191:51;58233:8;;58191:37;58203:24;58216:10;;58203:8;;:12;;:24;;;;:::i;:::-;58191:7;;:11;:37::i;:::-;:41;;:51::i;:::-;58172:70;;58284:10;:8;:10::i;:::-;58308:19;:8;:17;:19::i;:::-;58267:70;;;;;;;;;:::i;:::-;;;;;;;;;;;;;58253:85;;;57890:501;;;:::o;58137:211::-;57890:501;;;:::o;58071:315::-;58370:13;58363:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57890:501;;;:::o;65121:107::-;65179:7;65202:20;65216:5;65202:13;:20::i;64011:117::-;55290:13;:11;:13::i;:::-;64091:12:::1;:31:::0;64011:117::o;56310:201::-;55290:13;:11;:13::i;:::-;-1:-1:-1;;;;;56399:22:0;::::1;56391:73;;;::::0;-1:-1:-1;;;56391:73:0;;13602:2:1;56391:73:0::1;::::0;::::1;13584:21:1::0;13641:2;13621:18;;;13614:30;13680:34;13660:18;;;13653:62;-1:-1:-1;;;13731:18:1;;;13724:36;13777:19;;56391:73:0::1;13400:402:1::0;56391:73:0::1;56475:28;56494:8;56475:18;:28::i;55569:132::-:0;55477:6;;-1:-1:-1;;;;;55477:6:0;37381:10;55633:23;55625:68;;;;-1:-1:-1;;;55625:68:0;;18773:2:1;55625:68:0;;;18755:21:1;;;18792:18;;;18785:30;18851:34;18831:18;;;18824:62;18903:18;;55625:68:0;18571:356:1;51382:196:0;51497:24;;;;:15;:24;;;;;;:29;;-1:-1:-1;;;;;;51497:29:0;-1:-1:-1;;;;;51497:29:0;;;;;;;;;51542:28;;51497:24;;51542:28;;;;;;;51382:196;;;:::o;2915:98::-;2973:7;3000:5;3004:1;3000;:5;:::i;:::-;2993:12;2915:98;-1:-1:-1;;;2915:98:0:o;61463:104::-;61531:30;61541:9;61552:8;61531:9;:30::i;49262:2002::-;49377:35;49415:20;49427:7;49415:11;:20::i;:::-;49490:18;;49377:58;;-1:-1:-1;49448:22:0;;-1:-1:-1;;;;;49474:34:0;37381:10;-1:-1:-1;;;;;49474:34:0;;:87;;;-1:-1:-1;37381:10:0;49525:20;49537:7;49525:11;:20::i;:::-;-1:-1:-1;;;;;49525:36:0;;49474:87;:154;;;-1:-1:-1;49595:18:0;;49578:50;;37381:10;45140:164;:::i;49578:50::-;49448:181;;49650:17;49642:80;;;;-1:-1:-1;;;49642:80:0;;19904:2:1;49642:80:0;;;19886:21:1;19943:2;19923:18;;;19916:30;19982:34;19962:18;;;19955:62;-1:-1:-1;;;20033:18:1;;;20026:48;20091:19;;49642:80:0;19702:414:1;49642:80:0;49765:4;-1:-1:-1;;;;;49743:26:0;:13;:18;;;-1:-1:-1;;;;;49743:26:0;;49735:77;;;;-1:-1:-1;;;49735:77:0;;17951:2:1;49735:77:0;;;17933:21:1;17990:2;17970:18;;;17963:30;18029:34;18009:18;;;18002:62;-1:-1:-1;;;18080:18:1;;;18073:36;18126:19;;49735:77:0;17749:402:1;49735:77:0;-1:-1:-1;;;;;49831:16:0;;49823:66;;;;-1:-1:-1;;;49823:66:0;;15870:2:1;49823:66:0;;;15852:21:1;15909:2;15889:18;;;15882:30;15948:34;15928:18;;;15921:62;-1:-1:-1;;;15999:18:1;;;15992:35;16044:19;;49823:66:0;15668:401:1;49823:66:0;50010:49;50027:1;50031:7;50040:13;:18;;;50010:8;:49::i;:::-;-1:-1:-1;;;;;50355:18:0;;;;;;;:12;:18;;;;;;;;:31;;-1:-1:-1;;;;;;50355:31:0;;;-1:-1:-1;;;;;50355:31:0;;;-1:-1:-1;;50355:31:0;;;;;;;50401:16;;;;;;;;;:29;;;;;;;;-1:-1:-1;50401:29:0;;;;;;;;;;;;;50447:20;;;:11;:20;;;;;;:30;;-1:-1:-1;;;;;;50492:61:0;;;;-1:-1:-1;;;50537:15:0;-1:-1:-1;;;;;50492:61:0;;;;;50827:11;;;50857:24;;;;;:29;50827:11;;50857:29;50853:295;;50925:20;50933:11;46519:4;46553:12;-1:-1:-1;46543:22:0;46462:111;50925:20;50921:212;;;51002:18;;;50970:24;;;:11;:24;;;;;;;;:50;;51085:28;;;;-1:-1:-1;;;;;51043:70:0;-1:-1:-1;;;51043:70:0;-1:-1:-1;;;;;;51043:70:0;;;-1:-1:-1;;;;;50970:50:0;;;51043:70;;;;;;;50921:212;50330:829;51195:7;51191:2;-1:-1:-1;;;;;51176:27:0;51185:4;-1:-1:-1;;;;;51176:27:0;;;;;;;;;;;51214:42;49366:1898;;49262:2002;;;:::o;64164:152::-;64258:4;64278:32;64288:14;64294:7;64288:5;:14::i;:::-;64304:5;;64278:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64278:9:0;;-1:-1:-1;;;64278:32:0:i;:::-;64271:39;64164:152;-1:-1:-1;;;;64164:152:0:o;42143:537::-;-1:-1:-1;;;;;;;;;;;;;;;;;42246:16:0;42254:7;46519:4;46553:12;-1:-1:-1;46543:22:0;46462:111;42246:16;42238:71;;;;-1:-1:-1;;;42238:71:0;;14009:2:1;42238:71:0;;;13991:21:1;14048:2;14028:18;;;14021:30;14087:34;14067:18;;;14060:62;-1:-1:-1;;;14138:18:1;;;14131:40;14188:19;;42238:71:0;13807:406:1;42238:71:0;42367:7;42347:245;42414:31;42448:17;;;:11;:17;;;;;;;;;42414:51;;;;;;;;;-1:-1:-1;;;;;42414:51:0;;;;;-1:-1:-1;;;42414:51:0;;;-1:-1:-1;;;;;42414:51:0;;;;;;;;42488:28;42484:93;;42548:9;42143:537;-1:-1:-1;;;42143:537:0:o;42484:93::-;-1:-1:-1;;;42387:6:0;42347:245;;63705:146;63795:4;63815:30;63823:14;63829:7;63823:5;:14::i;:::-;63839:5;;63815:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63815:7:0;;-1:-1:-1;;;63815:30:0:i;56671:191::-;56764:6;;;-1:-1:-1;;;;;56781:17:0;;;-1:-1:-1;;;;;;56781:17:0;;;;;;;56814:40;;56764:6;;;56781:17;56764:6;;56814:40;;56745:16;;56814:40;56734:128;56671:191;:::o;52143:804::-;52298:4;-1:-1:-1;;;;;52319:13:0;;19830:19;:23;52315:625;;52355:72;;-1:-1:-1;;;52355:72:0;;-1:-1:-1;;;;;52355:36:0;;;;;:72;;37381:10;;52406:4;;52412:7;;52421:5;;52355:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52355:72:0;;;;;;;;-1:-1:-1;;52355:72:0;;;;;;;;;;;;:::i;:::-;;;52351:534;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52601:13:0;;52597:273;;52644:61;;-1:-1:-1;;;52644:61:0;;;;;;;:::i;52597:273::-;52820:6;52814:13;52805:6;52801:2;52797:15;52790:38;52351:534;-1:-1:-1;;;;;;52478:55:0;-1:-1:-1;;;52478:55:0;;-1:-1:-1;52471:62:0;;52315:625;-1:-1:-1;52924:4:0;52143:804;;;;;;:::o;3296:98::-;3354:7;3381:5;3385:1;3381;:5;:::i;4617:98::-;4675:7;4702:5;4706:1;4702;:5;:::i;57789:95::-;57849:13;57873:8;57866:15;;;;;:::i;16235:723::-;16291:13;16512:10;16508:53;;-1:-1:-1;;16539:10:0;;;;;;;;;;;;-1:-1:-1;;;16539:10:0;;;;;16235:723::o;16508:53::-;16586:5;16571:12;16627:78;16634:9;;16627:78;;16660:8;;;;:::i;:::-;;-1:-1:-1;16683:10:0;;-1:-1:-1;16691:2:0;16683:10;;:::i;:::-;;;16627:78;;;16715:19;16747:6;-1:-1:-1;;;;;16737:17:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16737:17:0;;16715:39;;16765:154;16772:10;;16765:154;;16799:11;16809:1;16799:11;;:::i;:::-;;-1:-1:-1;16868:10:0;16876:2;16868:5;:10;:::i;:::-;16855:24;;:2;:24;:::i;:::-;16842:39;;16825:6;16832;16825:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;16825:56:0;;;;;;;;-1:-1:-1;16896:11:0;16905:2;16896:11;;:::i;:::-;;;16765:154;;41712:229;41773:7;-1:-1:-1;;;;;41801:19:0;;41793:81;;;;-1:-1:-1;;;41793:81:0;;16276:2:1;41793:81:0;;;16258:21:1;16315:2;16295:18;;;16288:30;16354:34;16334:18;;;16327:62;-1:-1:-1;;;16405:18:1;;;16398:47;16462:19;;41793:81:0;16074:413:1;41793:81:0;-1:-1:-1;;;;;;41900:19:0;;;;;:12;:19;;;;;:32;-1:-1:-1;;;41900:32:0;;-1:-1:-1;;;;;41900:32:0;;41712:229::o;46581:104::-;46650:27;46660:2;46664:8;46650:27;;;;;;;;;;;;:9;:27::i;63551:119::-;63638:25;;-1:-1:-1;;7350:2:1;7346:15;;;7342:53;63638:25:0;;;7330:66:1;63605:7:0;;7412:12:1;;63638:25:0;;;;;;;;;;;;63628:36;;;;;;63621:43;;63551:119;;;:::o;64322:160::-;64401:4;64425:51;64444:5;64451:18;;64471:4;64425:18;:51::i;63857:148::-;63934:4;63954:45;63973:5;63980:12;;63994:4;63954:18;:45::i;47048:163::-;47171:32;47177:2;47181:8;47191:5;47198:4;47171:5;:32::i;8299:190::-;8424:4;8477;8448:25;8461:5;8468:4;8448:12;:25::i;:::-;:33;;8299:190;-1:-1:-1;;;;8299:190:0:o;47470:1538::-;47609:20;47632:12;-1:-1:-1;;;;;47663:16:0;;47655:62;;;;-1:-1:-1;;;47655:62:0;;21498:2:1;47655:62:0;;;21480:21:1;21537:2;21517:18;;;21510:30;21576:34;21556:18;;;21549:62;-1:-1:-1;;;21627:18:1;;;21620:31;21668:19;;47655:62:0;21296:397:1;47655:62:0;47736:13;47728:66;;;;-1:-1:-1;;;47728:66:0;;21900:2:1;47728:66:0;;;21882:21:1;21939:2;21919:18;;;21912:30;21978:34;21958:18;;;21951:62;-1:-1:-1;;;22029:18:1;;;22022:38;22077:19;;47728:66:0;21698:404:1;47728:66:0;-1:-1:-1;;;;;48146:16:0;;;;;;:12;:16;;;;;;;;:45;;-1:-1:-1;;;;;;;;;48146:45:0;;-1:-1:-1;;;;;48146:45:0;;;;;;;;;;48206:50;;;;;;;;;;;;;;48273:25;;;:11;:25;;;;;:35;;-1:-1:-1;;;;;;48323:66:0;;;;-1:-1:-1;;;48373:15:0;-1:-1:-1;;;;;48323:66:0;;;;;;48273:25;;48458:415;48478:8;48474:1;:12;48458:415;;;48517:38;;48542:12;;-1:-1:-1;;;;;48517:38:0;;;48534:1;;48517:38;;48534:1;;48517:38;48578:4;48574:249;;;48641:59;48672:1;48676:2;48680:12;48694:5;48641:22;:59::i;:::-;48607:196;;;;-1:-1:-1;;;48607:196:0;;;;;;;:::i;:::-;48843:14;;;;;48488:3;48458:415;;;-1:-1:-1;48889:12:0;:27;48940:60;45852:355;9166:296;9249:7;9292:4;9249:7;9307:118;9331:5;:12;9327:1;:16;9307:118;;;9380:33;9390:12;9404:5;9410:1;9404:8;;;;;;;;:::i;:::-;;;;;;;9380:9;:33::i;:::-;9365:48;-1:-1:-1;9345:3:0;;;;:::i;:::-;;;;9307:118;;15373:149;15436:7;15467:1;15463;:5;:51;;15598:13;15692:15;;;15728:4;15721:15;;;15775:4;15759:21;;15463:51;;;15598:13;15692:15;;;15728:4;15721:15;;;15775:4;15759:21;;15471:20;15530:268;-1:-1:-1;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:406:1;78:5;-1:-1:-1;;;;;104:6:1;101:30;98:56;;;134:18;;:::i;:::-;172:57;217:2;196:15;;-1:-1:-1;;192:29:1;223:4;188:40;172:57;:::i;:::-;163:66;;252:6;245:5;238:21;292:3;283:6;278:3;274:16;271:25;268:45;;;309:1;306;299:12;268:45;358:6;353:3;346:4;339:5;335:16;322:43;412:1;405:4;396:6;389:5;385:18;381:29;374:40;14:406;;;;;:::o;425:173::-;493:20;;-1:-1:-1;;;;;542:31:1;;532:42;;522:70;;588:1;585;578:12;603:156;669:20;;729:4;718:16;;708:27;;698:55;;749:1;746;739:12;764:186;823:6;876:2;864:9;855:7;851:23;847:32;844:52;;;892:1;889;882:12;844:52;915:29;934:9;915:29;:::i;955:260::-;1023:6;1031;1084:2;1072:9;1063:7;1059:23;1055:32;1052:52;;;1100:1;1097;1090:12;1052:52;1123:29;1142:9;1123:29;:::i;:::-;1113:39;;1171:38;1205:2;1194:9;1190:18;1171:38;:::i;:::-;1161:48;;955:260;;;;;:::o;1220:328::-;1297:6;1305;1313;1366:2;1354:9;1345:7;1341:23;1337:32;1334:52;;;1382:1;1379;1372:12;1334:52;1405:29;1424:9;1405:29;:::i;:::-;1395:39;;1453:38;1487:2;1476:9;1472:18;1453:38;:::i;:::-;1443:48;;1538:2;1527:9;1523:18;1510:32;1500:42;;1220:328;;;;;:::o;1553:666::-;1648:6;1656;1664;1672;1725:3;1713:9;1704:7;1700:23;1696:33;1693:53;;;1742:1;1739;1732:12;1693:53;1765:29;1784:9;1765:29;:::i;:::-;1755:39;;1813:38;1847:2;1836:9;1832:18;1813:38;:::i;:::-;1803:48;;1898:2;1887:9;1883:18;1870:32;1860:42;;1953:2;1942:9;1938:18;1925:32;-1:-1:-1;;;;;1972:6:1;1969:30;1966:50;;;2012:1;2009;2002:12;1966:50;2035:22;;2088:4;2080:13;;2076:27;-1:-1:-1;2066:55:1;;2117:1;2114;2107:12;2066:55;2140:73;2205:7;2200:2;2187:16;2182:2;2178;2174:11;2140:73;:::i;:::-;2130:83;;;1553:666;;;;;;;:::o;2224:347::-;2289:6;2297;2350:2;2338:9;2329:7;2325:23;2321:32;2318:52;;;2366:1;2363;2356:12;2318:52;2389:29;2408:9;2389:29;:::i;:::-;2379:39;;2468:2;2457:9;2453:18;2440:32;2515:5;2508:13;2501:21;2494:5;2491:32;2481:60;;2537:1;2534;2527:12;2481:60;2560:5;2550:15;;;2224:347;;;;;:::o;2576:254::-;2644:6;2652;2705:2;2693:9;2684:7;2680:23;2676:32;2673:52;;;2721:1;2718;2711:12;2673:52;2744:29;2763:9;2744:29;:::i;:::-;2734:39;2820:2;2805:18;;;;2792:32;;-1:-1:-1;;;2576:254:1:o;2835:963::-;2919:6;2950:2;2993;2981:9;2972:7;2968:23;2964:32;2961:52;;;3009:1;3006;2999:12;2961:52;3049:9;3036:23;-1:-1:-1;;;;;3119:2:1;3111:6;3108:14;3105:34;;;3135:1;3132;3125:12;3105:34;3173:6;3162:9;3158:22;3148:32;;3218:7;3211:4;3207:2;3203:13;3199:27;3189:55;;3240:1;3237;3230:12;3189:55;3276:2;3263:16;3298:2;3294;3291:10;3288:36;;;3304:18;;:::i;:::-;3350:2;3347:1;3343:10;3333:20;;3373:28;3397:2;3393;3389:11;3373:28;:::i;:::-;3435:15;;;3466:12;;;;3498:11;;;3528;;;3524:20;;3521:33;-1:-1:-1;3518:53:1;;;3567:1;3564;3557:12;3518:53;3589:1;3580:10;;3599:169;3613:2;3610:1;3607:9;3599:169;;;3670:23;3689:3;3670:23;:::i;:::-;3658:36;;3631:1;3624:9;;;;;3714:12;;;;3746;;3599:169;;;-1:-1:-1;3787:5:1;2835:963;-1:-1:-1;;;;;;;;2835:963:1:o;3803:180::-;3862:6;3915:2;3903:9;3894:7;3890:23;3886:32;3883:52;;;3931:1;3928;3921:12;3883:52;-1:-1:-1;3954:23:1;;3803:180;-1:-1:-1;3803:180:1:o;3988:245::-;4046:6;4099:2;4087:9;4078:7;4074:23;4070:32;4067:52;;;4115:1;4112;4105:12;4067:52;4154:9;4141:23;4173:30;4197:5;4173:30;:::i;4238:249::-;4307:6;4360:2;4348:9;4339:7;4335:23;4331:32;4328:52;;;4376:1;4373;4366:12;4328:52;4408:9;4402:16;4427:30;4451:5;4427:30;:::i;4492:592::-;4563:6;4571;4624:2;4612:9;4603:7;4599:23;4595:32;4592:52;;;4640:1;4637;4630:12;4592:52;4680:9;4667:23;-1:-1:-1;;;;;4750:2:1;4742:6;4739:14;4736:34;;;4766:1;4763;4756:12;4736:34;4804:6;4793:9;4789:22;4779:32;;4849:7;4842:4;4838:2;4834:13;4830:27;4820:55;;4871:1;4868;4861:12;4820:55;4911:2;4898:16;4937:2;4929:6;4926:14;4923:34;;;4953:1;4950;4943:12;4923:34;4998:7;4993:2;4984:6;4980:2;4976:15;4972:24;4969:37;4966:57;;;5019:1;5016;5009:12;4966:57;5050:2;5042:11;;;;;5072:6;;-1:-1:-1;4492:592:1;;-1:-1:-1;;;;4492:592:1:o;5089:450::-;5158:6;5211:2;5199:9;5190:7;5186:23;5182:32;5179:52;;;5227:1;5224;5217:12;5179:52;5267:9;5254:23;-1:-1:-1;;;;;5292:6:1;5289:30;5286:50;;;5332:1;5329;5322:12;5286:50;5355:22;;5408:4;5400:13;;5396:27;-1:-1:-1;5386:55:1;;5437:1;5434;5427:12;5386:55;5460:73;5525:7;5520:2;5507:16;5502:2;5498;5494:11;5460:73;:::i;5729:254::-;5797:6;5805;5858:2;5846:9;5837:7;5833:23;5829:32;5826:52;;;5874:1;5871;5864:12;5826:52;5910:9;5897:23;5887:33;;5939:38;5973:2;5962:9;5958:18;5939:38;:::i;5988:182::-;6045:6;6098:2;6086:9;6077:7;6073:23;6069:32;6066:52;;;6114:1;6111;6104:12;6066:52;6137:27;6154:9;6137:27;:::i;6175:759::-;6277:6;6285;6293;6301;6354:2;6342:9;6333:7;6329:23;6325:32;6322:52;;;6370:1;6367;6360:12;6322:52;6393:27;6410:9;6393:27;:::i;:::-;6383:37;;6439:38;6473:2;6462:9;6458:18;6439:38;:::i;:::-;6429:48;;6528:2;6517:9;6513:18;6500:32;-1:-1:-1;;;;;6592:2:1;6584:6;6581:14;6578:34;;;6608:1;6605;6598:12;6578:34;6646:6;6635:9;6631:22;6621:32;;6691:7;6684:4;6680:2;6676:13;6672:27;6662:55;;6713:1;6710;6703:12;6662:55;6753:2;6740:16;6779:2;6771:6;6768:14;6765:34;;;6795:1;6792;6785:12;6765:34;6848:7;6843:2;6833:6;6830:1;6826:14;6822:2;6818:23;6814:32;6811:45;6808:65;;;6869:1;6866;6859:12;6808:65;6175:759;;;;-1:-1:-1;;6900:2:1;6892:11;;-1:-1:-1;;;6175:759:1:o;6939:257::-;6980:3;7018:5;7012:12;7045:6;7040:3;7033:19;7061:63;7117:6;7110:4;7105:3;7101:14;7094:4;7087:5;7083:16;7061:63;:::i;:::-;7178:2;7157:15;-1:-1:-1;;7153:29:1;7144:39;;;;7185:4;7140:50;;6939:257;-1:-1:-1;;6939:257:1:o;7435:780::-;7816:3;7854:6;7848:13;7870:53;7916:6;7911:3;7904:4;7896:6;7892:17;7870:53;:::i;:::-;-1:-1:-1;;;7945:16:1;;;7970:25;;;8020:13;;8042:65;8020:13;8094:1;8083:13;;8076:4;8064:17;;8042:65;:::i;:::-;-1:-1:-1;;;8170:1:1;8126:20;;;;8162:10;;;8155:27;8206:2;8198:11;;7435:780;-1:-1:-1;;;;7435:780:1:o;8638:488::-;-1:-1:-1;;;;;8907:15:1;;;8889:34;;8959:15;;8954:2;8939:18;;8932:43;9006:2;8991:18;;8984:34;;;9054:3;9049:2;9034:18;;9027:31;;;8832:4;;9075:45;;9100:19;;9092:6;9075:45;:::i;:::-;9067:53;8638:488;-1:-1:-1;;;;;;8638:488:1:o;9131:632::-;9302:2;9354:21;;;9424:13;;9327:18;;;9446:22;;;9273:4;;9302:2;9525:15;;;;9499:2;9484:18;;;9273:4;9568:169;9582:6;9579:1;9576:13;9568:169;;;9643:13;;9631:26;;9712:15;;;;9677:12;;;;9604:1;9597:9;9568:169;;;-1:-1:-1;9754:3:1;;9131:632;-1:-1:-1;;;;;;9131:632:1:o;10142:338::-;10284:2;10269:18;;10317:1;10306:13;;10296:144;;10362:10;10357:3;10353:20;10350:1;10343:31;10397:4;10394:1;10387:15;10425:4;10422:1;10415:15;10296:144;10449:25;;;10142:338;:::o;10485:219::-;10634:2;10623:9;10616:21;10597:4;10654:44;10694:2;10683:9;10679:18;10671:6;10654:44;:::i;11464:353::-;11666:2;11648:21;;;11705:2;11685:18;;;11678:30;11744:31;11739:2;11724:18;;11717:59;11808:2;11793:18;;11464:353::o;12237:407::-;12439:2;12421:21;;;12478:2;12458:18;;;12451:30;12517:34;12512:2;12497:18;;12490:62;-1:-1:-1;;;12583:2:1;12568:18;;12561:41;12634:3;12619:19;;12237:407::o;13064:331::-;13266:2;13248:21;;;13305:1;13285:18;;;13278:29;-1:-1:-1;;;13338:2:1;13323:18;;13316:38;13386:2;13371:18;;13064:331::o;14218:340::-;14420:2;14402:21;;;14459:2;14439:18;;;14432:30;-1:-1:-1;;;14493:2:1;14478:18;;14471:46;14549:2;14534:18;;14218:340::o;20876:415::-;21078:2;21060:21;;;21117:2;21097:18;;;21090:30;21156:34;21151:2;21136:18;;21129:62;-1:-1:-1;;;21222:2:1;21207:18;;21200:49;21281:3;21266:19;;20876:415::o;24673:275::-;24744:2;24738:9;24809:2;24790:13;;-1:-1:-1;;24786:27:1;24774:40;;-1:-1:-1;;;;;24829:34:1;;24865:22;;;24826:62;24823:88;;;24891:18;;:::i;:::-;24927:2;24920:22;24673:275;;-1:-1:-1;24673:275:1:o;24953:128::-;24993:3;25024:1;25020:6;25017:1;25014:13;25011:39;;;25030:18;;:::i;:::-;-1:-1:-1;25066:9:1;;24953:128::o;25086:120::-;25126:1;25152;25142:35;;25157:18;;:::i;:::-;-1:-1:-1;25191:9:1;;25086:120::o;25211:168::-;25251:7;25317:1;25313;25309:6;25305:14;25302:1;25299:21;25294:1;25287:9;25280:17;25276:45;25273:71;;;25324:18;;:::i;:::-;-1:-1:-1;25364:9:1;;25211:168::o;25384:125::-;25424:4;25452:1;25449;25446:8;25443:34;;;25457:18;;:::i;:::-;-1:-1:-1;25494:9:1;;25384:125::o;25514:258::-;25586:1;25596:113;25610:6;25607:1;25604:13;25596:113;;;25686:11;;;25680:18;25667:11;;;25660:39;25632:2;25625:10;25596:113;;;25727:6;25724:1;25721:13;25718:48;;;-1:-1:-1;;25762:1:1;25744:16;;25737:27;25514:258::o;25777:380::-;25856:1;25852:12;;;;25899;;;25920:61;;25974:4;25966:6;25962:17;25952:27;;25920:61;26027:2;26019:6;26016:14;25996:18;25993:38;25990:161;;;26073:10;26068:3;26064:20;26061:1;26054:31;26108:4;26105:1;26098:15;26136:4;26133:1;26126:15;25990:161;;25777:380;;;:::o;26162:135::-;26201:3;-1:-1:-1;;26222:17:1;;26219:43;;;26242:18;;:::i;:::-;-1:-1:-1;26289:1:1;26278:13;;26162:135::o;26302:112::-;26334:1;26360;26350:35;;26365:18;;:::i;:::-;-1:-1:-1;26399:9:1;;26302:112::o;26419:127::-;26480:10;26475:3;26471:20;26468:1;26461:31;26511:4;26508:1;26501:15;26535:4;26532:1;26525:15;26551:127;26612:10;26607:3;26603:20;26600:1;26593:31;26643:4;26640:1;26633:15;26667:4;26664:1;26657:15;26683:127;26744:10;26739:3;26735:20;26732:1;26725:31;26775:4;26772:1;26765:15;26799:4;26796:1;26789:15;26815:127;26876:10;26871:3;26867:20;26864:1;26857:31;26907:4;26904:1;26897:15;26931:4;26928:1;26921:15;26947:127;27008:10;27003:3;26999:20;26996:1;26989:31;27039:4;27036:1;27029:15;27063:4;27060:1;27053:15;27079:131;-1:-1:-1;;;;;;27153:32:1;;27143:43;;27133:71;;27200:1;27197;27190:12

Swarm Source

ipfs://9b5e20ba6e5011cb764aca4805a1187d0e5f19045804611fce51df5cb2fd3c37
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.