ETH Price: $3,885.20 (+0.07%)

Token

CATASTROPHY CLUB (CATS)
 

Overview

Max Total Supply

3,360 CATS

Holders

2,098

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
nothingels.eth
Balance
1 CATS
0x400D6cF58fcD2f537B0c455Ef9316e0e47803786
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:
CATASTROPHY

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-11-23
*/

// SPDX-License-Identifier: MIT


pragma solidity ^0.8.13;

interface IOperatorFilterRegistry {
    function isOperatorAllowed(address registrant, address operator) external view returns (bool);
    function register(address registrant) external;
    function registerAndSubscribe(address registrant, address subscription) external;
    function registerAndCopyEntries(address registrant, address registrantToCopy) external;
    function unregister(address addr) external;
    function updateOperator(address registrant, address operator, bool filtered) external;
    function updateOperators(address registrant, address[] calldata operators, bool filtered) external;
    function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;
    function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;
    function subscribe(address registrant, address registrantToSubscribe) external;
    function unsubscribe(address registrant, bool copyExistingEntries) external;
    function subscriptionOf(address addr) external returns (address registrant);
    function subscribers(address registrant) external returns (address[] memory);
    function subscriberAt(address registrant, uint256 index) external returns (address);
    function copyEntriesOf(address registrant, address registrantToCopy) external;
    function isOperatorFiltered(address registrant, address operator) external returns (bool);
    function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);
    function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);
    function filteredOperators(address addr) external returns (address[] memory);
    function filteredCodeHashes(address addr) external returns (bytes32[] memory);
    function filteredOperatorAt(address registrant, uint256 index) external returns (address);
    function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);
    function isRegistered(address addr) external returns (bool);
    function codeHashOf(address addr) external returns (bytes32);
}

// File: contracts/OperatorFilterer.sol


pragma solidity ^0.8.13;


/**
 * @title  OperatorFilterer
 * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another
 *         registrant's entries in the OperatorFilterRegistry.
 * @dev    This smart contract is meant to be inherited by token contracts so they can use the following:
 *         - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods.
 *         - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods.
 */
abstract contract OperatorFilterer {
    error OperatorNotAllowed(address operator);

    IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY =
        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

    constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
        // If an inheriting token contract is deployed to a network without the registry deployed, the modifier
        // will not revert, but the contract will need to be registered with the registry once it is deployed in
        // order for the modifier to filter addresses.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (subscribe) {
                OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
            } else {
                if (subscriptionOrRegistrantToCopy != address(0)) {
                    OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);
                } else {
                    OPERATOR_FILTER_REGISTRY.register(address(this));
                }
            }
        }
    }

    modifier onlyAllowedOperator(address from) virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            // Allow spending tokens from addresses with balance
            // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
            // from an EOA.
            if (from == msg.sender) {
                _;
                return;
            }
            if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), msg.sender)) {
                revert OperatorNotAllowed(msg.sender);
            }
        }
        _;
    }

    modifier onlyAllowedOperatorApproval(address operator) virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) {
                revert OperatorNotAllowed(operator);
            }
        }
        _;
    }
}

// File: contracts/DefaultOperatorFilterer.sol


pragma solidity ^0.8.13;


/**
 * @title  DefaultOperatorFilterer
 * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription.
 */
abstract contract DefaultOperatorFilterer is OperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

    constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {}
}

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


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

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * 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.
 * OpenZeppelin's JavaScript library generates merkle trees that are safe
 * against this attack out of the box.
 */
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 simultaneously proven to be a part of a merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _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}
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _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 sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * _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}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _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/security/ReentrancyGuard.sol


// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

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

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


// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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

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

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


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

pragma solidity ^0.8.0;

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

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

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


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

pragma solidity ^0.8.0;


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

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

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

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

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

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

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

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

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

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


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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: @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.8.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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * 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/token/ERC721/ERC721.sol


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

pragma solidity ^0.8.0;








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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        _approve(to, tokenId);
    }

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

        return _tokenApprovals[tokenId];
    }

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

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

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

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

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

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

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

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

        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
        require(!_exists(tokenId), "ERC721: token already minted");

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

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

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

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

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

        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
        owner = ERC721.ownerOf(tokenId);

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

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

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

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

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

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

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

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

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

    /**
     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
     * - When `from` is zero, the tokens will be minted for `to`.
     * - When `to` is zero, ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256, /* firstTokenId */
        uint256 batchSize
    ) internal virtual {
        if (batchSize > 1) {
            if (from != address(0)) {
                _balances[from] -= batchSize;
            }
            if (to != address(0)) {
                _balances[to] += batchSize;
            }
        }
    }

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual {}
}

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


// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.0;



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

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

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

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

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

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

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

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

    /**
     * @dev See {ERC721-_beforeTokenTransfer}.
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);

        if (batchSize > 1) {
            // Will only trigger during construction. Batch transferring (minting) is not available afterwards.
            revert("ERC721Enumerable: consecutive transfers not supported");
        }

        uint256 tokenId = firstTokenId;

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

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

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

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

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

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

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

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

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

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

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

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

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

// File: contracts/cat.sol


pragma solidity ^0.8.10;







contract CATASTROPHY is ERC721Enumerable, Ownable, ReentrancyGuard, DefaultOperatorFilterer {
    using Strings for uint256;

    uint256 private s_tokenCounter = 1748;
    uint256 private r_tokenCounter = 0;

    mapping(address => bool) public mintedPerAddress;

    bool public mintEnabled = false;
    bool public publicEnabled = false;

    bytes32 public merkleRoot;
    string private baseURI = "ipfs://QmNtxNr8pxdsr29DkB4zZQFWodZH3gzww7LFDrareMrJss/";

    constructor() ERC721("CATASTROPHY CLUB", "CATS") {}

    function setMerkleRoot(bytes32 merkleRootHash) external onlyOwner {
        merkleRoot = merkleRootHash;
    }

    function setBaseURI(string memory uri) public onlyOwner {
        baseURI = uri;
    }

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

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

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

    function reserveMint(uint256 _mintAmount, address _catastrophy_club_addr) public onlyOwner {
        require((r_tokenCounter + _mintAmount) < 361, "Club only got 360");
        require(_mintAmount > 0, "Need to mint at least 1 cat");

        for (uint256 i = 0; i < _mintAmount; i++) {
            _safeMint(_catastrophy_club_addr, i + 1388 + r_tokenCounter);
        }

        r_tokenCounter += _mintAmount;
        mintedPerAddress[_catastrophy_club_addr] = true;
    }

    function mintcat(bytes32[] calldata merkleProof) external nonReentrant {
        require(mintEnabled, "Minting is not live yet");
        require(totalSupply() <= 3000, "No more cat");
        require(msg.sender == tx.origin, "Cant mint from another contract");
        require(!mintedPerAddress[msg.sender], "You can only mint ONE cat");

        if (mintEnabled && !publicEnabled) {
            require(
                MerkleProof.verify(
                    merkleProof,
                    merkleRoot,
                    keccak256(abi.encodePacked(msg.sender))
                ),
                "Sender address is not in WhiteList"
            );
        }

        mintedPerAddress[msg.sender] = true;

        _safeMint(msg.sender, s_tokenCounter++);
    }

    function flipMint(bool status) external onlyOwner {
        mintEnabled = status;
    }

    function flipPublic(bool status) external onlyOwner {
        publicEnabled = status;
    }

    // OpenSea OperatorFilter

    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public override(IERC721, ERC721) onlyAllowedOperator(from) {
        super.transferFrom(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public override(IERC721, ERC721) onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public override(IERC721, ERC721) onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId, data);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"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":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":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","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":"bool","name":"status","type":"bool"}],"name":"flipMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"flipPublic","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":"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":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"mintcat","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintedPerAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"publicEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"},{"internalType":"address","name":"_catastrophy_club_addr","type":"address"}],"name":"reserveMint","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":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"merkleRootHash","type":"bytes32"}],"name":"setMerkleRoot","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":"","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"}]

6106d4600c556000600d55600f805461ffff1916905560e060405260366080818152906200292b60a0396011906200003890826200032e565b503480156200004657600080fd5b50733cc6cdda760b79bafa08df41ecfa224f810dceb660016040518060400160405280601081526020016f21a0aa20a9aa2927a8242c9021a62aa160811b815250604051806040016040528060048152602001634341545360e01b8152508160009081620000b591906200032e565b506001620000c482826200032e565b505050620000e1620000db6200023360201b60201c565b62000237565b6001600b556daaeb6d7670e522a718067333cd4e3b156200022b5780156200017957604051633e9f1edf60e11b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b600060405180830381600087803b1580156200015a57600080fd5b505af11580156200016f573d6000803e3d6000fd5b505050506200022b565b6001600160a01b03821615620001ca5760405163a0af290360e01b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e9063a0af2903906044016200013f565b604051632210724360e11b81523060048201526daaeb6d7670e522a718067333cd4e90634420e48690602401600060405180830381600087803b1580156200021157600080fd5b505af115801562000226573d6000803e3d6000fd5b505050505b5050620003fa565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620002b457607f821691505b602082108103620002d557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200032957600081815260208120601f850160051c81016020861015620003045750805b601f850160051c820191505b81811015620003255782815560010162000310565b5050505b505050565b81516001600160401b038111156200034a576200034a62000289565b62000362816200035b84546200029f565b84620002db565b602080601f8311600181146200039a5760008415620003815750858301515b600019600386901b1c1916600185901b17855562000325565b600085815260208120601f198616915b82811015620003cb57888601518255948401946001909101908401620003aa565b5085821015620003ea5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b612521806200040a6000396000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806370a0823111610104578063b88d4fde116100a2578063d445b97811610071578063d445b978146103d6578063e985e9c5146103f9578063f2fde38b14610435578063f55e7fc71461044857600080fd5b8063b88d4fde14610390578063c832e396146103a3578063c87b56dd146103b6578063d1239730146103c957600080fd5b80638da5cb5b116100de5780638da5cb5b1461035257806395d89b41146103635780639b001f451461036b578063a22cb4651461037d57600080fd5b806370a0823114610324578063715018a6146103375780637cb647591461033f57600080fd5b80632eb4a7ab1161017c5780634f6ccce71161014b5780634f6ccce7146102d857806355f804b3146102eb57806360b02f70146102fe5780636352211e1461031157600080fd5b80632eb4a7ab146102945780632f745c591461029d57806341f43434146102b057806342842e0e146102c557600080fd5b8063095ea7b3116101b8578063095ea7b31461024757806318160ddd1461025c57806323b872dd1461026e5780632d92c5601461028157600080fd5b806301ffc9a7146101df57806306fdde0314610207578063081812fc1461021c575b600080fd5b6101f26101ed366004611de4565b61045b565b60405190151581526020015b60405180910390f35b61020f610486565b6040516101fe9190611e51565b61022f61022a366004611e64565b610518565b6040516001600160a01b0390911681526020016101fe565b61025a610255366004611e99565b61053f565b005b6008545b6040519081526020016101fe565b61025a61027c366004611ec3565b610659565b61025a61028f366004611f0d565b610732565b61026060105481565b6102606102ab366004611e99565b61074d565b61022f6daaeb6d7670e522a718067333cd4e81565b61025a6102d3366004611ec3565b6107e3565b6102606102e6366004611e64565b6108b1565b61025a6102f9366004611fb6565b610944565b61025a61030c366004611fff565b61095c565b61022f61031f366004611e64565b610a84565b61026061033236600461202b565b610ae4565b61025a610b6a565b61025a61034d366004611e64565b610b7e565b600a546001600160a01b031661022f565b61020f610b8b565b600f546101f290610100900460ff1681565b61025a61038b366004612046565b610b9a565b61025a61039e36600461207d565b610ba5565b61025a6103b13660046120f9565b610c81565b61020f6103c4366004611e64565b610eff565b600f546101f29060ff1681565b6101f26103e436600461202b565b600e6020526000908152604090205460ff1681565b6101f261040736600461216e565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61025a61044336600461202b565b610f66565b61025a610456366004611f0d565b610fdf565b60006001600160e01b0319821663780e9d6360e01b1480610480575061048082611001565b92915050565b60606000805461049590612198565b80601f01602080910402602001604051908101604052809291908181526020018280546104c190612198565b801561050e5780601f106104e35761010080835404028352916020019161050e565b820191906000526020600020905b8154815290600101906020018083116104f157829003601f168201915b5050505050905090565b600061052382611051565b506000908152600460205260409020546001600160a01b031690565b600061054a82610a84565b9050806001600160a01b0316836001600160a01b0316036105bc5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b03821614806105d857506105d88133610407565b61064a5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c00000060648201526084016105b3565b61065483836110b0565b505050565b826daaeb6d7670e522a718067333cd4e3b1561072157336001600160a01b0382160361068f5761068a84848461111e565b61072c565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa1580156106de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070291906121d2565b61072157604051633b79c77360e21b81523360048201526024016105b3565b61072c84848461111e565b50505050565b61073a61114f565b600f805460ff1916911515919091179055565b600061075883610ae4565b82106107ba5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016105b3565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b826daaeb6d7670e522a718067333cd4e3b156108a657336001600160a01b038216036108145761068a8484846111a9565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610863573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088791906121d2565b6108a657604051633b79c77360e21b81523360048201526024016105b3565b61072c8484846111a9565b60006108bc60085490565b821061091f5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016105b3565b60088281548110610932576109326121ef565b90600052602060002001549050919050565b61094c61114f565b60116109588282612253565b5050565b61096461114f565b61016982600d546109759190612329565b106109b65760405162461bcd60e51b81526020600482015260116024820152700436c7562206f6e6c7920676f742033363607c1b60448201526064016105b3565b60008211610a065760405162461bcd60e51b815260206004820152601b60248201527f4e65656420746f206d696e74206174206c65617374203120636174000000000060448201526064016105b3565b60005b82811015610a4757610a3582600d548361056c610a269190612329565b610a309190612329565b6111c4565b80610a3f8161233c565b915050610a09565b5081600d6000828254610a5a9190612329565b90915550506001600160a01b03166000908152600e60205260409020805460ff1916600117905550565b6000818152600260205260408120546001600160a01b0316806104805760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016105b3565b60006001600160a01b038216610b4e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b60648201526084016105b3565b506001600160a01b031660009081526003602052604090205490565b610b7261114f565b610b7c60006111de565b565b610b8661114f565b601055565b60606001805461049590612198565b610958338383611230565b836daaeb6d7670e522a718067333cd4e3b15610c6e57336001600160a01b03821603610bdc57610bd7858585856112fe565b610c7a565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610c2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4f91906121d2565b610c6e57604051633b79c77360e21b81523360048201526024016105b3565b610c7a858585856112fe565b5050505050565b610c89611330565b600f5460ff16610cdb5760405162461bcd60e51b815260206004820152601760248201527f4d696e74696e67206973206e6f74206c6976652079657400000000000000000060448201526064016105b3565b610bb8610ce760085490565b1115610d235760405162461bcd60e51b815260206004820152600b60248201526a139bc81b5bdc994818d85d60aa1b60448201526064016105b3565b333214610d725760405162461bcd60e51b815260206004820152601f60248201527f43616e74206d696e742066726f6d20616e6f7468657220636f6e74726163740060448201526064016105b3565b336000908152600e602052604090205460ff1615610dd25760405162461bcd60e51b815260206004820152601960248201527f596f752063616e206f6e6c79206d696e74204f4e45206361740000000000000060448201526064016105b3565b600f5460ff168015610dec5750600f54610100900460ff16155b15610ebd57610e66828280806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506010546040516bffffffffffffffffffffffff193360601b166020820152909250603401905060405160208183030381529060405280519060200120611389565b610ebd5760405162461bcd60e51b815260206004820152602260248201527f53656e6465722061646472657373206973206e6f7420696e2057686974654c696044820152611cdd60f21b60648201526084016105b3565b336000818152600e60205260408120805460ff19166001179055600c8054610ef59392909190610eec8361233c565b919050556111c4565b6109586001600b55565b6060610f0a82611051565b6000610f1461139f565b90506000815111610f345760405180602001604052806000815250610f5f565b80610f3e846113ae565b604051602001610f4f929190612355565b6040516020818303038152906040525b9392505050565b610f6e61114f565b6001600160a01b038116610fd35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105b3565b610fdc816111de565b50565b610fe761114f565b600f80549115156101000261ff0019909216919091179055565b60006001600160e01b031982166380ac58cd60e01b148061103257506001600160e01b03198216635b5e139f60e01b145b8061048057506301ffc9a760e01b6001600160e01b0319831614610480565b6000818152600260205260409020546001600160a01b0316610fdc5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016105b3565b600081815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906110e582610a84565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6111283382611441565b6111445760405162461bcd60e51b81526004016105b390612384565b6106548383836114c0565b600a546001600160a01b03163314610b7c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105b3565b61065483838360405180602001604052806000815250610ba5565b610958828260405180602001604052806000815250611631565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316036112915760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016105b3565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6113083383611441565b6113245760405162461bcd60e51b81526004016105b390612384565b61072c84848484611664565b6002600b54036113825760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105b3565b6002600b55565b6000826113968584611697565b14949350505050565b60606011805461049590612198565b606060006113bb836116e4565b600101905060008167ffffffffffffffff8111156113db576113db611f2a565b6040519080825280601f01601f191660200182016040528015611405576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461140f57509392505050565b60008061144d83610a84565b9050806001600160a01b0316846001600160a01b0316148061149457506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b806114b85750836001600160a01b03166114ad84610518565b6001600160a01b0316145b949350505050565b826001600160a01b03166114d382610a84565b6001600160a01b0316146114f95760405162461bcd60e51b81526004016105b3906123d1565b6001600160a01b03821661155b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016105b3565b61156883838360016117bc565b826001600160a01b031661157b82610a84565b6001600160a01b0316146115a15760405162461bcd60e51b81526004016105b3906123d1565b600081815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260038552838620805460001901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b61163b83836118f0565b6116486000848484611a89565b6106545760405162461bcd60e51b81526004016105b390612416565b61166f8484846114c0565b61167b84848484611a89565b61072c5760405162461bcd60e51b81526004016105b390612416565b600081815b84518110156116dc576116c8828683815181106116bb576116bb6121ef565b6020026020010151611b8a565b9150806116d48161233c565b91505061169c565b509392505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106117235772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061174f576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061176d57662386f26fc10000830492506010015b6305f5e1008310611785576305f5e100830492506008015b612710831061179957612710830492506004015b606483106117ab576064830492506002015b600a83106104805760010192915050565b6117c884848484611bb6565b60018111156118375760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b60648201526084016105b3565b816001600160a01b0385166118935761188e81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6118b6565b836001600160a01b0316856001600160a01b0316146118b6576118b68582611c3e565b6001600160a01b0384166118cd57610bd781611cdb565b846001600160a01b0316846001600160a01b031614610c7a57610c7a8482611d8a565b6001600160a01b0382166119465760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016105b3565b6000818152600260205260409020546001600160a01b0316156119ab5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016105b3565b6119b96000838360016117bc565b6000818152600260205260409020546001600160a01b031615611a1e5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016105b3565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001600160a01b0384163b15611b7f57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611acd903390899088908890600401612468565b6020604051808303816000875af1925050508015611b08575060408051601f3d908101601f19168201909252611b05918101906124a5565b60015b611b65573d808015611b36576040519150601f19603f3d011682016040523d82523d6000602084013e611b3b565b606091505b508051600003611b5d5760405162461bcd60e51b81526004016105b390612416565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506114b8565b506001949350505050565b6000818310611ba6576000828152602084905260409020610f5f565b5060009182526020526040902090565b600181111561072c576001600160a01b03841615611bfc576001600160a01b03841660009081526003602052604081208054839290611bf69084906124c2565b90915550505b6001600160a01b0383161561072c576001600160a01b03831660009081526003602052604081208054839290611c33908490612329565b909155505050505050565b60006001611c4b84610ae4565b611c5591906124c2565b600083815260076020526040902054909150808214611ca8576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611ced906001906124c2565b60008381526009602052604081205460088054939450909284908110611d1557611d156121ef565b906000526020600020015490508060088381548110611d3657611d366121ef565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611d6e57611d6e6124d5565b6001900381819060005260206000200160009055905550505050565b6000611d9583610ae4565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160e01b031981168114610fdc57600080fd5b600060208284031215611df657600080fd5b8135610f5f81611dce565b60005b83811015611e1c578181015183820152602001611e04565b50506000910152565b60008151808452611e3d816020860160208601611e01565b601f01601f19169290920160200192915050565b602081526000610f5f6020830184611e25565b600060208284031215611e7657600080fd5b5035919050565b80356001600160a01b0381168114611e9457600080fd5b919050565b60008060408385031215611eac57600080fd5b611eb583611e7d565b946020939093013593505050565b600080600060608486031215611ed857600080fd5b611ee184611e7d565b9250611eef60208501611e7d565b9150604084013590509250925092565b8015158114610fdc57600080fd5b600060208284031215611f1f57600080fd5b8135610f5f81611eff565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115611f5b57611f5b611f2a565b604051601f8501601f19908116603f01168101908282118183101715611f8357611f83611f2a565b81604052809350858152868686011115611f9c57600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215611fc857600080fd5b813567ffffffffffffffff811115611fdf57600080fd5b8201601f81018413611ff057600080fd5b6114b884823560208401611f40565b6000806040838503121561201257600080fd5b8235915061202260208401611e7d565b90509250929050565b60006020828403121561203d57600080fd5b610f5f82611e7d565b6000806040838503121561205957600080fd5b61206283611e7d565b9150602083013561207281611eff565b809150509250929050565b6000806000806080858703121561209357600080fd5b61209c85611e7d565b93506120aa60208601611e7d565b925060408501359150606085013567ffffffffffffffff8111156120cd57600080fd5b8501601f810187136120de57600080fd5b6120ed87823560208401611f40565b91505092959194509250565b6000806020838503121561210c57600080fd5b823567ffffffffffffffff8082111561212457600080fd5b818501915085601f83011261213857600080fd5b81358181111561214757600080fd5b8660208260051b850101111561215c57600080fd5b60209290920196919550909350505050565b6000806040838503121561218157600080fd5b61218a83611e7d565b915061202260208401611e7d565b600181811c908216806121ac57607f821691505b6020821081036121cc57634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156121e457600080fd5b8151610f5f81611eff565b634e487b7160e01b600052603260045260246000fd5b601f82111561065457600081815260208120601f850160051c8101602086101561222c5750805b601f850160051c820191505b8181101561224b57828155600101612238565b505050505050565b815167ffffffffffffffff81111561226d5761226d611f2a565b6122818161227b8454612198565b84612205565b602080601f8311600181146122b6576000841561229e5750858301515b600019600386901b1c1916600185901b17855561224b565b600085815260208120601f198616915b828110156122e5578886015182559484019460019091019084016122c6565b50858210156123035787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b8082018082111561048057610480612313565b60006001820161234e5761234e612313565b5060010190565b60008351612367818460208801611e01565b83519083019061237b818360208801611e01565b01949350505050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061249b90830184611e25565b9695505050505050565b6000602082840312156124b757600080fd5b8151610f5f81611dce565b8181038181111561048057610480612313565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220971fa95e0dc1bf1934eb43edbed0fc692201d08d83d60f9ff2fad82672432fcf64736f6c63430008110033697066733a2f2f516d4e74784e723870786473723239446b42347a5a5146576f645a4833677a7777374c4644726172654d724a73732f

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806370a0823111610104578063b88d4fde116100a2578063d445b97811610071578063d445b978146103d6578063e985e9c5146103f9578063f2fde38b14610435578063f55e7fc71461044857600080fd5b8063b88d4fde14610390578063c832e396146103a3578063c87b56dd146103b6578063d1239730146103c957600080fd5b80638da5cb5b116100de5780638da5cb5b1461035257806395d89b41146103635780639b001f451461036b578063a22cb4651461037d57600080fd5b806370a0823114610324578063715018a6146103375780637cb647591461033f57600080fd5b80632eb4a7ab1161017c5780634f6ccce71161014b5780634f6ccce7146102d857806355f804b3146102eb57806360b02f70146102fe5780636352211e1461031157600080fd5b80632eb4a7ab146102945780632f745c591461029d57806341f43434146102b057806342842e0e146102c557600080fd5b8063095ea7b3116101b8578063095ea7b31461024757806318160ddd1461025c57806323b872dd1461026e5780632d92c5601461028157600080fd5b806301ffc9a7146101df57806306fdde0314610207578063081812fc1461021c575b600080fd5b6101f26101ed366004611de4565b61045b565b60405190151581526020015b60405180910390f35b61020f610486565b6040516101fe9190611e51565b61022f61022a366004611e64565b610518565b6040516001600160a01b0390911681526020016101fe565b61025a610255366004611e99565b61053f565b005b6008545b6040519081526020016101fe565b61025a61027c366004611ec3565b610659565b61025a61028f366004611f0d565b610732565b61026060105481565b6102606102ab366004611e99565b61074d565b61022f6daaeb6d7670e522a718067333cd4e81565b61025a6102d3366004611ec3565b6107e3565b6102606102e6366004611e64565b6108b1565b61025a6102f9366004611fb6565b610944565b61025a61030c366004611fff565b61095c565b61022f61031f366004611e64565b610a84565b61026061033236600461202b565b610ae4565b61025a610b6a565b61025a61034d366004611e64565b610b7e565b600a546001600160a01b031661022f565b61020f610b8b565b600f546101f290610100900460ff1681565b61025a61038b366004612046565b610b9a565b61025a61039e36600461207d565b610ba5565b61025a6103b13660046120f9565b610c81565b61020f6103c4366004611e64565b610eff565b600f546101f29060ff1681565b6101f26103e436600461202b565b600e6020526000908152604090205460ff1681565b6101f261040736600461216e565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61025a61044336600461202b565b610f66565b61025a610456366004611f0d565b610fdf565b60006001600160e01b0319821663780e9d6360e01b1480610480575061048082611001565b92915050565b60606000805461049590612198565b80601f01602080910402602001604051908101604052809291908181526020018280546104c190612198565b801561050e5780601f106104e35761010080835404028352916020019161050e565b820191906000526020600020905b8154815290600101906020018083116104f157829003601f168201915b5050505050905090565b600061052382611051565b506000908152600460205260409020546001600160a01b031690565b600061054a82610a84565b9050806001600160a01b0316836001600160a01b0316036105bc5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b03821614806105d857506105d88133610407565b61064a5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c00000060648201526084016105b3565b61065483836110b0565b505050565b826daaeb6d7670e522a718067333cd4e3b1561072157336001600160a01b0382160361068f5761068a84848461111e565b61072c565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa1580156106de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070291906121d2565b61072157604051633b79c77360e21b81523360048201526024016105b3565b61072c84848461111e565b50505050565b61073a61114f565b600f805460ff1916911515919091179055565b600061075883610ae4565b82106107ba5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016105b3565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b826daaeb6d7670e522a718067333cd4e3b156108a657336001600160a01b038216036108145761068a8484846111a9565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610863573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088791906121d2565b6108a657604051633b79c77360e21b81523360048201526024016105b3565b61072c8484846111a9565b60006108bc60085490565b821061091f5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016105b3565b60088281548110610932576109326121ef565b90600052602060002001549050919050565b61094c61114f565b60116109588282612253565b5050565b61096461114f565b61016982600d546109759190612329565b106109b65760405162461bcd60e51b81526020600482015260116024820152700436c7562206f6e6c7920676f742033363607c1b60448201526064016105b3565b60008211610a065760405162461bcd60e51b815260206004820152601b60248201527f4e65656420746f206d696e74206174206c65617374203120636174000000000060448201526064016105b3565b60005b82811015610a4757610a3582600d548361056c610a269190612329565b610a309190612329565b6111c4565b80610a3f8161233c565b915050610a09565b5081600d6000828254610a5a9190612329565b90915550506001600160a01b03166000908152600e60205260409020805460ff1916600117905550565b6000818152600260205260408120546001600160a01b0316806104805760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016105b3565b60006001600160a01b038216610b4e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b60648201526084016105b3565b506001600160a01b031660009081526003602052604090205490565b610b7261114f565b610b7c60006111de565b565b610b8661114f565b601055565b60606001805461049590612198565b610958338383611230565b836daaeb6d7670e522a718067333cd4e3b15610c6e57336001600160a01b03821603610bdc57610bd7858585856112fe565b610c7a565b604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015610c2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4f91906121d2565b610c6e57604051633b79c77360e21b81523360048201526024016105b3565b610c7a858585856112fe565b5050505050565b610c89611330565b600f5460ff16610cdb5760405162461bcd60e51b815260206004820152601760248201527f4d696e74696e67206973206e6f74206c6976652079657400000000000000000060448201526064016105b3565b610bb8610ce760085490565b1115610d235760405162461bcd60e51b815260206004820152600b60248201526a139bc81b5bdc994818d85d60aa1b60448201526064016105b3565b333214610d725760405162461bcd60e51b815260206004820152601f60248201527f43616e74206d696e742066726f6d20616e6f7468657220636f6e74726163740060448201526064016105b3565b336000908152600e602052604090205460ff1615610dd25760405162461bcd60e51b815260206004820152601960248201527f596f752063616e206f6e6c79206d696e74204f4e45206361740000000000000060448201526064016105b3565b600f5460ff168015610dec5750600f54610100900460ff16155b15610ebd57610e66828280806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506010546040516bffffffffffffffffffffffff193360601b166020820152909250603401905060405160208183030381529060405280519060200120611389565b610ebd5760405162461bcd60e51b815260206004820152602260248201527f53656e6465722061646472657373206973206e6f7420696e2057686974654c696044820152611cdd60f21b60648201526084016105b3565b336000818152600e60205260408120805460ff19166001179055600c8054610ef59392909190610eec8361233c565b919050556111c4565b6109586001600b55565b6060610f0a82611051565b6000610f1461139f565b90506000815111610f345760405180602001604052806000815250610f5f565b80610f3e846113ae565b604051602001610f4f929190612355565b6040516020818303038152906040525b9392505050565b610f6e61114f565b6001600160a01b038116610fd35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105b3565b610fdc816111de565b50565b610fe761114f565b600f80549115156101000261ff0019909216919091179055565b60006001600160e01b031982166380ac58cd60e01b148061103257506001600160e01b03198216635b5e139f60e01b145b8061048057506301ffc9a760e01b6001600160e01b0319831614610480565b6000818152600260205260409020546001600160a01b0316610fdc5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016105b3565b600081815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906110e582610a84565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6111283382611441565b6111445760405162461bcd60e51b81526004016105b390612384565b6106548383836114c0565b600a546001600160a01b03163314610b7c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105b3565b61065483838360405180602001604052806000815250610ba5565b610958828260405180602001604052806000815250611631565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316036112915760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016105b3565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6113083383611441565b6113245760405162461bcd60e51b81526004016105b390612384565b61072c84848484611664565b6002600b54036113825760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105b3565b6002600b55565b6000826113968584611697565b14949350505050565b60606011805461049590612198565b606060006113bb836116e4565b600101905060008167ffffffffffffffff8111156113db576113db611f2a565b6040519080825280601f01601f191660200182016040528015611405576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461140f57509392505050565b60008061144d83610a84565b9050806001600160a01b0316846001600160a01b0316148061149457506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b806114b85750836001600160a01b03166114ad84610518565b6001600160a01b0316145b949350505050565b826001600160a01b03166114d382610a84565b6001600160a01b0316146114f95760405162461bcd60e51b81526004016105b3906123d1565b6001600160a01b03821661155b5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016105b3565b61156883838360016117bc565b826001600160a01b031661157b82610a84565b6001600160a01b0316146115a15760405162461bcd60e51b81526004016105b3906123d1565b600081815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260038552838620805460001901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b61163b83836118f0565b6116486000848484611a89565b6106545760405162461bcd60e51b81526004016105b390612416565b61166f8484846114c0565b61167b84848484611a89565b61072c5760405162461bcd60e51b81526004016105b390612416565b600081815b84518110156116dc576116c8828683815181106116bb576116bb6121ef565b6020026020010151611b8a565b9150806116d48161233c565b91505061169c565b509392505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106117235772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061174f576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061176d57662386f26fc10000830492506010015b6305f5e1008310611785576305f5e100830492506008015b612710831061179957612710830492506004015b606483106117ab576064830492506002015b600a83106104805760010192915050565b6117c884848484611bb6565b60018111156118375760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b60648201526084016105b3565b816001600160a01b0385166118935761188e81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6118b6565b836001600160a01b0316856001600160a01b0316146118b6576118b68582611c3e565b6001600160a01b0384166118cd57610bd781611cdb565b846001600160a01b0316846001600160a01b031614610c7a57610c7a8482611d8a565b6001600160a01b0382166119465760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016105b3565b6000818152600260205260409020546001600160a01b0316156119ab5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016105b3565b6119b96000838360016117bc565b6000818152600260205260409020546001600160a01b031615611a1e5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016105b3565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001600160a01b0384163b15611b7f57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611acd903390899088908890600401612468565b6020604051808303816000875af1925050508015611b08575060408051601f3d908101601f19168201909252611b05918101906124a5565b60015b611b65573d808015611b36576040519150601f19603f3d011682016040523d82523d6000602084013e611b3b565b606091505b508051600003611b5d5760405162461bcd60e51b81526004016105b390612416565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506114b8565b506001949350505050565b6000818310611ba6576000828152602084905260409020610f5f565b5060009182526020526040902090565b600181111561072c576001600160a01b03841615611bfc576001600160a01b03841660009081526003602052604081208054839290611bf69084906124c2565b90915550505b6001600160a01b0383161561072c576001600160a01b03831660009081526003602052604081208054839290611c33908490612329565b909155505050505050565b60006001611c4b84610ae4565b611c5591906124c2565b600083815260076020526040902054909150808214611ca8576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611ced906001906124c2565b60008381526009602052604081205460088054939450909284908110611d1557611d156121ef565b906000526020600020015490508060088381548110611d3657611d366121ef565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611d6e57611d6e6124d5565b6001900381819060005260206000200160009055905550505050565b6000611d9583610ae4565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160e01b031981168114610fdc57600080fd5b600060208284031215611df657600080fd5b8135610f5f81611dce565b60005b83811015611e1c578181015183820152602001611e04565b50506000910152565b60008151808452611e3d816020860160208601611e01565b601f01601f19169290920160200192915050565b602081526000610f5f6020830184611e25565b600060208284031215611e7657600080fd5b5035919050565b80356001600160a01b0381168114611e9457600080fd5b919050565b60008060408385031215611eac57600080fd5b611eb583611e7d565b946020939093013593505050565b600080600060608486031215611ed857600080fd5b611ee184611e7d565b9250611eef60208501611e7d565b9150604084013590509250925092565b8015158114610fdc57600080fd5b600060208284031215611f1f57600080fd5b8135610f5f81611eff565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115611f5b57611f5b611f2a565b604051601f8501601f19908116603f01168101908282118183101715611f8357611f83611f2a565b81604052809350858152868686011115611f9c57600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215611fc857600080fd5b813567ffffffffffffffff811115611fdf57600080fd5b8201601f81018413611ff057600080fd5b6114b884823560208401611f40565b6000806040838503121561201257600080fd5b8235915061202260208401611e7d565b90509250929050565b60006020828403121561203d57600080fd5b610f5f82611e7d565b6000806040838503121561205957600080fd5b61206283611e7d565b9150602083013561207281611eff565b809150509250929050565b6000806000806080858703121561209357600080fd5b61209c85611e7d565b93506120aa60208601611e7d565b925060408501359150606085013567ffffffffffffffff8111156120cd57600080fd5b8501601f810187136120de57600080fd5b6120ed87823560208401611f40565b91505092959194509250565b6000806020838503121561210c57600080fd5b823567ffffffffffffffff8082111561212457600080fd5b818501915085601f83011261213857600080fd5b81358181111561214757600080fd5b8660208260051b850101111561215c57600080fd5b60209290920196919550909350505050565b6000806040838503121561218157600080fd5b61218a83611e7d565b915061202260208401611e7d565b600181811c908216806121ac57607f821691505b6020821081036121cc57634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156121e457600080fd5b8151610f5f81611eff565b634e487b7160e01b600052603260045260246000fd5b601f82111561065457600081815260208120601f850160051c8101602086101561222c5750805b601f850160051c820191505b8181101561224b57828155600101612238565b505050505050565b815167ffffffffffffffff81111561226d5761226d611f2a565b6122818161227b8454612198565b84612205565b602080601f8311600181146122b6576000841561229e5750858301515b600019600386901b1c1916600185901b17855561224b565b600085815260208120601f198616915b828110156122e5578886015182559484019460019091019084016122c6565b50858210156123035787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b8082018082111561048057610480612313565b60006001820161234e5761234e612313565b5060010190565b60008351612367818460208801611e01565b83519083019061237b818360208801611e01565b01949350505050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061249b90830184611e25565b9695505050505050565b6000602082840312156124b757600080fd5b8151610f5f81611dce565b8181038181111561048057610480612313565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220971fa95e0dc1bf1934eb43edbed0fc692201d08d83d60f9ff2fad82672432fcf64736f6c63430008110033

Deployed Bytecode Sourcemap

80593:3453:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74586:224;;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;74586:224:0;;;;;;;;58648:100;;;:::i;:::-;;;;;;;:::i;60160:171::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1697:32:1;;;1679:51;;1667:2;1652:18;60160:171:0;1533:203:1;59678:416:0;;;;;;:::i;:::-;;:::i;:::-;;75226:113;75314:10;:17;75226:113;;;2324:25:1;;;2312:2;2297:18;75226:113:0;2178:177:1;83335:214:0;;;;;;:::i;:::-;;:::i;83104:89::-;;;;;;:::i;:::-;;:::i;80950:25::-;;;;;;74894:256;;;;;;:::i;:::-;;:::i;2874:143::-;;2974:42;2874:143;;83557:222;;;;;;:::i;:::-;;:::i;75416:233::-;;;;;;:::i;:::-;;:::i;81251:88::-;;;;;;:::i;:::-;;:::i;81820:483::-;;;;;;:::i;:::-;;:::i;58358:223::-;;;;;;:::i;:::-;;:::i;58089:207::-;;;;;;:::i;:::-;;:::i;36071:103::-;;;:::i;81131:112::-;;;;;;:::i;:::-;;:::i;35423:87::-;35496:6;;-1:-1:-1;;;;;35496:6:0;35423:87;;58817:104;;;:::i;80908:33::-;;;;;;;;;;;;60403:155;;;;;;:::i;:::-;;:::i;83787:256::-;;;;;;:::i;:::-;;:::i;82311:785::-;;;;;;:::i;:::-;;:::i;81463:349::-;;;;;;:::i;:::-;;:::i;80870:31::-;;;;;;;;;80813:48;;;;;;:::i;:::-;;;;;;;;;;;;;;;;60629:164;;;;;;:::i;:::-;-1:-1:-1;;;;;60750:25:0;;;60726:4;60750:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;60629:164;36329:201;;;;;;:::i;:::-;;:::i;83201:93::-;;;;;;:::i;:::-;;:::i;74586:224::-;74688:4;-1:-1:-1;;;;;;74712:50:0;;-1:-1:-1;;;74712:50:0;;:90;;;74766:36;74790:11;74766:23;:36::i;:::-;74705:97;74586:224;-1:-1:-1;;74586:224:0:o;58648:100::-;58702:13;58735:5;58728:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58648:100;:::o;60160:171::-;60236:7;60256:23;60271:7;60256:14;:23::i;:::-;-1:-1:-1;60299:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;60299:24:0;;60160:171::o;59678:416::-;59759:13;59775:23;59790:7;59775:14;:23::i;:::-;59759:39;;59823:5;-1:-1:-1;;;;;59817:11:0;:2;-1:-1:-1;;;;;59817:11:0;;59809:57;;;;-1:-1:-1;;;59809:57:0;;7807:2:1;59809:57:0;;;7789:21:1;7846:2;7826:18;;;7819:30;7885:34;7865:18;;;7858:62;-1:-1:-1;;;7936:18:1;;;7929:31;7977:19;;59809:57:0;;;;;;;;;34054:10;-1:-1:-1;;;;;59901:21:0;;;;:62;;-1:-1:-1;59926:37:0;59943:5;34054:10;60629:164;:::i;59926:37::-;59879:173;;;;-1:-1:-1;;;59879:173:0;;8209:2:1;59879:173:0;;;8191:21:1;8248:2;8228:18;;;8221:30;8287:34;8267:18;;;8260:62;8358:31;8338:18;;;8331:59;8407:19;;59879:173:0;8007:425:1;59879:173:0;60065:21;60074:2;60078:7;60065:8;:21::i;:::-;59748:346;59678:416;;:::o;83335:214::-;83487:4;2974:42;4122:45;:49;4118:539;;4411:10;-1:-1:-1;;;;;4403:18:0;;;4399:85;;83504:37:::1;83523:4;83529:2;83533:7;83504:18;:37::i;:::-;4462:7:::0;;4399:85;4503:69;;-1:-1:-1;;;4503:69:0;;4554:4;4503:69;;;8649:34:1;4561:10:0;8699:18:1;;;8692:43;2974:42:0;;4503;;8584:18:1;;4503:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4498:148;;4600:30;;-1:-1:-1;;;4600:30:0;;4619:10;4600:30;;;1679:51:1;1652:18;;4600:30:0;1533:203:1;4498:148:0;83504:37:::1;83523:4;83529:2;83533:7;83504:18;:37::i;:::-;83335:214:::0;;;;:::o;83104:89::-;35309:13;:11;:13::i;:::-;83165:11:::1;:20:::0;;-1:-1:-1;;83165:20:0::1;::::0;::::1;;::::0;;;::::1;::::0;;83104:89::o;74894:256::-;74991:7;75027:23;75044:5;75027:16;:23::i;:::-;75019:5;:31;75011:87;;;;-1:-1:-1;;;75011:87:0;;9198:2:1;75011:87:0;;;9180:21:1;9237:2;9217:18;;;9210:30;9276:34;9256:18;;;9249:62;-1:-1:-1;;;9327:18:1;;;9320:41;9378:19;;75011:87:0;8996:407:1;75011:87:0;-1:-1:-1;;;;;;75116:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;74894:256::o;83557:222::-;83713:4;2974:42;4122:45;:49;4118:539;;4411:10;-1:-1:-1;;;;;4403:18:0;;;4399:85;;83730:41:::1;83753:4;83759:2;83763:7;83730:22;:41::i;4399:85::-:0;4503:69;;-1:-1:-1;;;4503:69:0;;4554:4;4503:69;;;8649:34:1;4561:10:0;8699:18:1;;;8692:43;2974:42:0;;4503;;8584:18:1;;4503:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4498:148;;4600:30;;-1:-1:-1;;;4600:30:0;;4619:10;4600:30;;;1679:51:1;1652:18;;4600:30:0;1533:203:1;4498:148:0;83730:41:::1;83753:4;83759:2;83763:7;83730:22;:41::i;75416:233::-:0;75491:7;75527:30;75314:10;:17;;75226:113;75527:30;75519:5;:38;75511:95;;;;-1:-1:-1;;;75511:95:0;;9610:2:1;75511:95:0;;;9592:21:1;9649:2;9629:18;;;9622:30;9688:34;9668:18;;;9661:62;-1:-1:-1;;;9739:18:1;;;9732:42;9791:19;;75511:95:0;9408:408:1;75511:95:0;75624:10;75635:5;75624:17;;;;;;;;:::i;:::-;;;;;;;;;75617:24;;75416:233;;;:::o;81251:88::-;35309:13;:11;:13::i;:::-;81318:7:::1;:13;81328:3:::0;81318:7;:13:::1;:::i;:::-;;81251:88:::0;:::o;81820:483::-;35309:13;:11;:13::i;:::-;81963:3:::1;81948:11;81931:14;;:28;;;;:::i;:::-;81930:36;81922:66;;;::::0;-1:-1:-1;;;81922:66:0;;12621:2:1;81922:66:0::1;::::0;::::1;12603:21:1::0;12660:2;12640:18;;;12633:30;-1:-1:-1;;;12679:18:1;;;12672:47;12736:18;;81922:66:0::1;12419:341:1::0;81922:66:0::1;82021:1;82007:11;:15;81999:55;;;::::0;-1:-1:-1;;;81999:55:0;;12967:2:1;81999:55:0::1;::::0;::::1;12949:21:1::0;13006:2;12986:18;;;12979:30;13045:29;13025:18;;;13018:57;13092:18;;81999:55:0::1;12765:351:1::0;81999:55:0::1;82072:9;82067:129;82091:11;82087:1;:15;82067:129;;;82124:60;82134:22;82169:14;;82158:1;82162:4;82158:8;;;;:::i;:::-;:25;;;;:::i;:::-;82124:9;:60::i;:::-;82104:3:::0;::::1;::::0;::::1;:::i;:::-;;;;82067:129;;;;82226:11;82208:14;;:29;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;;;;;;82248:40:0::1;;::::0;;;:16:::1;:40;::::0;;;;:47;;-1:-1:-1;;82248:47:0::1;82291:4;82248:47;::::0;;-1:-1:-1;81820:483:0:o;58358:223::-;58430:7;63245:16;;;:7;:16;;;;;;-1:-1:-1;;;;;63245:16:0;;58494:56;;;;-1:-1:-1;;;58494:56:0;;13463:2:1;58494:56:0;;;13445:21:1;13502:2;13482:18;;;13475:30;-1:-1:-1;;;13521:18:1;;;13514:54;13585:18;;58494:56:0;13261:348:1;58089:207:0;58161:7;-1:-1:-1;;;;;58189:19:0;;58181:73;;;;-1:-1:-1;;;58181:73:0;;13816:2:1;58181:73:0;;;13798:21:1;13855:2;13835:18;;;13828:30;13894:34;13874:18;;;13867:62;-1:-1:-1;;;13945:18:1;;;13938:39;13994:19;;58181:73:0;13614:405:1;58181:73:0;-1:-1:-1;;;;;;58272:16:0;;;;;:9;:16;;;;;;;58089:207::o;36071:103::-;35309:13;:11;:13::i;:::-;36136:30:::1;36163:1;36136:18;:30::i;:::-;36071:103::o:0;81131:112::-;35309:13;:11;:13::i;:::-;81208:10:::1;:27:::0;81131:112::o;58817:104::-;58873:13;58906:7;58899:14;;;;;:::i;60403:155::-;60498:52;34054:10;60531:8;60541;60498:18;:52::i;83787:256::-;83971:4;2974:42;4122:45;:49;4118:539;;4411:10;-1:-1:-1;;;;;4403:18:0;;;4399:85;;83988:47:::1;84011:4;84017:2;84021:7;84030:4;83988:22;:47::i;:::-;4462:7:::0;;4399:85;4503:69;;-1:-1:-1;;;4503:69:0;;4554:4;4503:69;;;8649:34:1;4561:10:0;8699:18:1;;;8692:43;2974:42:0;;4503;;8584:18:1;;4503:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4498:148;;4600:30;;-1:-1:-1;;;4600:30:0;;4619:10;4600:30;;;1679:51:1;1652:18;;4600:30:0;1533:203:1;4498:148:0;83988:47:::1;84011:4;84017:2;84021:7;84030:4;83988:22;:47::i;:::-;83787:256:::0;;;;;:::o;82311:785::-;17495:21;:19;:21::i;:::-;82401:11:::1;::::0;::::1;;82393:47;;;::::0;-1:-1:-1;;;82393:47:0;;14226:2:1;82393:47:0::1;::::0;::::1;14208:21:1::0;14265:2;14245:18;;;14238:30;14304:25;14284:18;;;14277:53;14347:18;;82393:47:0::1;14024:347:1::0;82393:47:0::1;82476:4;82459:13;75314:10:::0;:17;;75226:113;82459:13:::1;:21;;82451:45;;;::::0;-1:-1:-1;;;82451:45:0;;14578:2:1;82451:45:0::1;::::0;::::1;14560:21:1::0;14617:2;14597:18;;;14590:30;-1:-1:-1;;;14636:18:1;;;14629:41;14687:18;;82451:45:0::1;14376:335:1::0;82451:45:0::1;82515:10;82529:9;82515:23;82507:67;;;::::0;-1:-1:-1;;;82507:67:0;;14918:2:1;82507:67:0::1;::::0;::::1;14900:21:1::0;14957:2;14937:18;;;14930:30;14996:33;14976:18;;;14969:61;15047:18;;82507:67:0::1;14716:355:1::0;82507:67:0::1;82611:10;82594:28;::::0;;;:16:::1;:28;::::0;;;;;::::1;;82593:29;82585:67;;;::::0;-1:-1:-1;;;82585:67:0;;15278:2:1;82585:67:0::1;::::0;::::1;15260:21:1::0;15317:2;15297:18;;;15290:30;15356:27;15336:18;;;15329:55;15401:18;;82585:67:0::1;15076:349:1::0;82585:67:0::1;82669:11;::::0;::::1;;:29:::0;::::1;;;-1:-1:-1::0;82685:13:0::1;::::0;::::1;::::0;::::1;;;82684:14;82669:29;82665:324;;;82741:166;82782:11;;82741:166;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;;82816:10:0::1;::::0;82859:28:::1;::::0;-1:-1:-1;;82876:10:0::1;15579:2:1::0;15575:15;15571:53;82859:28:0::1;::::0;::::1;15559:66:1::0;82816:10:0;;-1:-1:-1;15641:12:1;;;-1:-1:-1;82859:28:0::1;;;;;;;;;;;;82849:39;;;;;;82741:18;:166::i;:::-;82715:262;;;::::0;-1:-1:-1;;;82715:262:0;;15866:2:1;82715:262:0::1;::::0;::::1;15848:21:1::0;15905:2;15885:18;;;15878:30;15944:34;15924:18;;;15917:62;-1:-1:-1;;;15995:18:1;;;15988:32;16037:19;;82715:262:0::1;15664:398:1::0;82715:262:0::1;83018:10;83001:28;::::0;;;:16:::1;:28;::::0;;;;:35;;-1:-1:-1;;83001:35:0::1;83032:4;83001:35;::::0;;83071:14:::1;:16:::0;;83049:39:::1;::::0;83018:10;83071:16;;:14;:16:::1;::::0;::::1;:::i;:::-;;;;;83049:9;:39::i;:::-;17539:20:::0;16933:1;18059:7;:22;17876:213;81463:349;81536:13;81562:23;81577:7;81562:14;:23::i;:::-;81598:28;81629:10;:8;:10::i;:::-;81598:41;;81701:1;81676:14;81670:28;:32;:134;;;;;;;;;;;;;;;;;81746:14;81762:18;:7;:16;:18::i;:::-;81729:52;;;;;;;;;:::i;:::-;;;;;;;;;;;;;81670:134;81650:154;81463:349;-1:-1:-1;;;81463:349:0:o;36329:201::-;35309:13;:11;:13::i;:::-;-1:-1:-1;;;;;36418:22:0;::::1;36410:73;;;::::0;-1:-1:-1;;;36410:73:0;;16770:2:1;36410:73:0::1;::::0;::::1;16752:21:1::0;16809:2;16789:18;;;16782:30;16848:34;16828:18;;;16821:62;-1:-1:-1;;;16899:18:1;;;16892:36;16945:19;;36410:73:0::1;16568:402:1::0;36410:73:0::1;36494:28;36513:8;36494:18;:28::i;:::-;36329:201:::0;:::o;83201:93::-;35309:13;:11;:13::i;:::-;83264::::1;:22:::0;;;::::1;;;;-1:-1:-1::0;;83264:22:0;;::::1;::::0;;;::::1;::::0;;83201:93::o;57720:305::-;57822:4;-1:-1:-1;;;;;;57859:40:0;;-1:-1:-1;;;57859:40:0;;:105;;-1:-1:-1;;;;;;;57916:48:0;;-1:-1:-1;;;57916:48:0;57859:105;:158;;;-1:-1:-1;;;;;;;;;;49261:40:0;;;57981:36;49152:157;69979:135;63647:4;63245:16;;;:7;:16;;;;;;-1:-1:-1;;;;;63245:16:0;70053:53;;;;-1:-1:-1;;;70053:53:0;;13463:2:1;70053:53:0;;;13445:21:1;13502:2;13482:18;;;13475:30;-1:-1:-1;;;13521:18:1;;;13514:54;13585:18;;70053:53:0;13261:348:1;69258:174:0;69333:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;69333:29:0;-1:-1:-1;;;;;69333:29:0;;;;;;;;:24;;69387:23;69333:24;69387:14;:23::i;:::-;-1:-1:-1;;;;;69378:46:0;;;;;;;;;;;69258:174;;:::o;60860:335::-;61055:41;34054:10;61088:7;61055:18;:41::i;:::-;61047:99;;;;-1:-1:-1;;;61047:99:0;;;;;;;:::i;:::-;61159:28;61169:4;61175:2;61179:7;61159:9;:28::i;35588:132::-;35496:6;;-1:-1:-1;;;;;35496:6:0;34054:10;35652:23;35644:68;;;;-1:-1:-1;;;35644:68:0;;17591:2:1;35644:68:0;;;17573:21:1;;;17610:18;;;17603:30;17669:34;17649:18;;;17642:62;17721:18;;35644:68:0;17389:356:1;61266:185:0;61404:39;61421:4;61427:2;61431:7;61404:39;;;;;;;;;;;;:16;:39::i;64483:110::-;64559:26;64569:2;64573:7;64559:26;;;;;;;;;;;;:9;:26::i;36690:191::-;36783:6;;;-1:-1:-1;;;;;36800:17:0;;;-1:-1:-1;;;;;;36800:17:0;;;;;;;36833:40;;36783:6;;;36800:17;36783:6;;36833:40;;36764:16;;36833:40;36753:128;36690:191;:::o;69575:315::-;69730:8;-1:-1:-1;;;;;69721:17:0;:5;-1:-1:-1;;;;;69721:17:0;;69713:55;;;;-1:-1:-1;;;69713:55:0;;17952:2:1;69713:55:0;;;17934:21:1;17991:2;17971:18;;;17964:30;18030:27;18010:18;;;18003:55;18075:18;;69713:55:0;17750:349:1;69713:55:0;-1:-1:-1;;;;;69779:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;69779:46:0;;;;;;;;;;69841:41;;540::1;;;69841::0;;513:18:1;69841:41:0;;;;;;;69575:315;;;:::o;61522:322::-;61696:41;34054:10;61729:7;61696:18;:41::i;:::-;61688:99;;;;-1:-1:-1;;;61688:99:0;;;;;;;:::i;:::-;61798:38;61812:4;61818:2;61822:7;61831:4;61798:13;:38::i;17575:293::-;16977:1;17709:7;;:19;17701:63;;;;-1:-1:-1;;;17701:63:0;;18306:2:1;17701:63:0;;;18288:21:1;18345:2;18325:18;;;18318:30;18384:33;18364:18;;;18357:61;18435:18;;17701:63:0;18104:355:1;17701:63:0;16977:1;17842:7;:18;17575:293::o;6811:190::-;6936:4;6989;6960:25;6973:5;6980:4;6960:12;:25::i;:::-;:33;;6811:190;-1:-1:-1;;;;6811:190:0:o;81347:108::-;81407:13;81440:7;81433:14;;;;;:::i;31401:716::-;31457:13;31508:14;31525:17;31536:5;31525:10;:17::i;:::-;31545:1;31525:21;31508:38;;31561:20;31595:6;31584:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;31584:18:0;-1:-1:-1;31561:41:0;-1:-1:-1;31726:28:0;;;31742:2;31726:28;31783:288;-1:-1:-1;;31815:5:0;-1:-1:-1;;;31952:2:0;31941:14;;31936:30;31815:5;31923:44;32013:2;32004:11;;;-1:-1:-1;32034:21:0;31783:288;32034:21;-1:-1:-1;32092:6:0;31401:716;-1:-1:-1;;;31401:716:0:o;63877:264::-;63970:4;63987:13;64003:23;64018:7;64003:14;:23::i;:::-;63987:39;;64056:5;-1:-1:-1;;;;;64045:16:0;:7;-1:-1:-1;;;;;64045:16:0;;:52;;;-1:-1:-1;;;;;;60750:25:0;;;60726:4;60750:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;64065:32;64045:87;;;;64125:7;-1:-1:-1;;;;;64101:31:0;:20;64113:7;64101:11;:20::i;:::-;-1:-1:-1;;;;;64101:31:0;;64045:87;64037:96;63877:264;-1:-1:-1;;;;63877:264:0:o;67876:1263::-;68035:4;-1:-1:-1;;;;;68008:31:0;:23;68023:7;68008:14;:23::i;:::-;-1:-1:-1;;;;;68008:31:0;;68000:81;;;;-1:-1:-1;;;68000:81:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;68100:16:0;;68092:65;;;;-1:-1:-1;;;68092:65:0;;19204:2:1;68092:65:0;;;19186:21:1;19243:2;19223:18;;;19216:30;19282:34;19262:18;;;19255:62;-1:-1:-1;;;19333:18:1;;;19326:34;19377:19;;68092:65:0;19002:400:1;68092:65:0;68170:42;68191:4;68197:2;68201:7;68210:1;68170:20;:42::i;:::-;68342:4;-1:-1:-1;;;;;68315:31:0;:23;68330:7;68315:14;:23::i;:::-;-1:-1:-1;;;;;68315:31:0;;68307:81;;;;-1:-1:-1;;;68307:81:0;;;;;;;:::i;:::-;68460:24;;;;:15;:24;;;;;;;;68453:31;;-1:-1:-1;;;;;;68453:31:0;;;;;;-1:-1:-1;;;;;68936:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;68936:20:0;;;68971:13;;;;;;;;;:18;;68453:31;68971:18;;;69011:16;;;:7;:16;;;;;;:21;;;;;;;;;;69050:27;;68476:7;;69050:27;;;59748:346;59678:416;;:::o;64820:319::-;64949:18;64955:2;64959:7;64949:5;:18::i;:::-;65000:53;65031:1;65035:2;65039:7;65048:4;65000:22;:53::i;:::-;64978:153;;;;-1:-1:-1;;;64978:153:0;;;;;;;:::i;62725:313::-;62881:28;62891:4;62897:2;62901:7;62881:9;:28::i;:::-;62928:47;62951:4;62957:2;62961:7;62970:4;62928:22;:47::i;:::-;62920:110;;;;-1:-1:-1;;;62920:110:0;;;;;;;:::i;7678:296::-;7761:7;7804:4;7761:7;7819:118;7843:5;:12;7839:1;:16;7819:118;;;7892:33;7902:12;7916:5;7922:1;7916:8;;;;;;;;:::i;:::-;;;;;;;7892:9;:33::i;:::-;7877:48;-1:-1:-1;7857:3:0;;;;:::i;:::-;;;;7819:118;;;-1:-1:-1;7954:12:0;7678:296;-1:-1:-1;;;7678:296:0:o;28267:922::-;28320:7;;-1:-1:-1;;;28398:15:0;;28394:102;;-1:-1:-1;;;28434:15:0;;;-1:-1:-1;28478:2:0;28468:12;28394:102;28523:6;28514:5;:15;28510:102;;28559:6;28550:15;;;-1:-1:-1;28594:2:0;28584:12;28510:102;28639:6;28630:5;:15;28626:102;;28675:6;28666:15;;;-1:-1:-1;28710:2:0;28700:12;28626:102;28755:5;28746;:14;28742:99;;28790:5;28781:14;;;-1:-1:-1;28824:1:0;28814:11;28742:99;28868:5;28859;:14;28855:99;;28903:5;28894:14;;;-1:-1:-1;28937:1:0;28927:11;28855:99;28981:5;28972;:14;28968:99;;29016:5;29007:14;;;-1:-1:-1;29050:1:0;29040:11;28968:99;29094:5;29085;:14;29081:66;;29130:1;29120:11;29175:6;28267:922;-1:-1:-1;;28267:922:0:o;75723:915::-;75900:61;75927:4;75933:2;75937:12;75951:9;75900:26;:61::i;:::-;75990:1;75978:9;:13;75974:222;;;76121:63;;-1:-1:-1;;;76121:63:0;;20028:2:1;76121:63:0;;;20010:21:1;20067:2;20047:18;;;20040:30;20106:34;20086:18;;;20079:62;-1:-1:-1;;;20157:18:1;;;20150:51;20218:19;;76121:63:0;19826:417:1;75974:222:0;76226:12;-1:-1:-1;;;;;76255:18:0;;76251:187;;76290:40;76322:7;77465:10;:17;;77438:24;;;;:15;:24;;;;;:44;;;77493:24;;;;;;;;;;;;77361:164;76290:40;76251:187;;;76360:2;-1:-1:-1;;;;;76352:10:0;:4;-1:-1:-1;;;;;76352:10:0;;76348:90;;76379:47;76412:4;76418:7;76379:32;:47::i;:::-;-1:-1:-1;;;;;76452:16:0;;76448:183;;76485:45;76522:7;76485:36;:45::i;76448:183::-;76558:4;-1:-1:-1;;;;;76552:10:0;:2;-1:-1:-1;;;;;76552:10:0;;76548:83;;76579:40;76607:2;76611:7;76579:27;:40::i;65475:942::-;-1:-1:-1;;;;;65555:16:0;;65547:61;;;;-1:-1:-1;;;65547:61:0;;20450:2:1;65547:61:0;;;20432:21:1;;;20469:18;;;20462:30;20528:34;20508:18;;;20501:62;20580:18;;65547:61:0;20248:356:1;65547:61:0;63647:4;63245:16;;;:7;:16;;;;;;-1:-1:-1;;;;;63245:16:0;63671:31;65619:58;;;;-1:-1:-1;;;65619:58:0;;20811:2:1;65619:58:0;;;20793:21:1;20850:2;20830:18;;;20823:30;20889;20869:18;;;20862:58;20937:18;;65619:58:0;20609:352:1;65619:58:0;65690:48;65719:1;65723:2;65727:7;65736:1;65690:20;:48::i;:::-;63647:4;63245:16;;;:7;:16;;;;;;-1:-1:-1;;;;;63245:16:0;63671:31;65828:58;;;;-1:-1:-1;;;65828:58:0;;20811:2:1;65828:58:0;;;20793:21:1;20850:2;20830:18;;;20823:30;20889;20869:18;;;20862:58;20937:18;;65828:58:0;20609:352:1;65828:58:0;-1:-1:-1;;;;;66235:13:0;;;;;;:9;:13;;;;;;;;:18;;66252:1;66235:18;;;66277:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;66277:21:0;;;;;66316:33;66285:7;;66235:13;;66316:33;;66235:13;;66316:33;81318:13:::1;81251:88:::0;:::o;70678:853::-;70832:4;-1:-1:-1;;;;;70853:13:0;;38416:19;:23;70849:675;;70889:71;;-1:-1:-1;;;70889:71:0;;-1:-1:-1;;;;;70889:36:0;;;;;:71;;34054:10;;70940:4;;70946:7;;70955:4;;70889:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;70889:71:0;;;;;;;;-1:-1:-1;;70889:71:0;;;;;;;;;;;;:::i;:::-;;;70885:584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71130:6;:13;71147:1;71130:18;71126:328;;71173:60;;-1:-1:-1;;;71173:60:0;;;;;;;:::i;71126:328::-;71404:6;71398:13;71389:6;71385:2;71381:15;71374:38;70885:584;-1:-1:-1;;;;;;71011:51:0;-1:-1:-1;;;71011:51:0;;-1:-1:-1;71004:58:0;;70849:675;-1:-1:-1;71508:4:0;70678:853;;;;;;:::o;14718:149::-;14781:7;14812:1;14808;:5;:51;;14943:13;15037:15;;;15073:4;15066:15;;;15120:4;15104:21;;14808:51;;;-1:-1:-1;14943:13:0;15037:15;;;15073:4;15066:15;15120:4;15104:21;;;14718:149::o;72263:410::-;72453:1;72441:9;:13;72437:229;;;-1:-1:-1;;;;;72475:18:0;;;72471:87;;-1:-1:-1;;;;;72514:15:0;;;;;;:9;:15;;;;;:28;;72533:9;;72514:15;:28;;72533:9;;72514:28;:::i;:::-;;;;-1:-1:-1;;72471:87:0;-1:-1:-1;;;;;72576:16:0;;;72572:83;;-1:-1:-1;;;;;72613:13:0;;;;;;:9;:13;;;;;:26;;72630:9;;72613:13;:26;;72630:9;;72613:26;:::i;:::-;;;;-1:-1:-1;;72263:410:0;;;;:::o;78152:988::-;78418:22;78468:1;78443:22;78460:4;78443:16;:22::i;:::-;:26;;;;:::i;:::-;78480:18;78501:26;;;:17;:26;;;;;;78418:51;;-1:-1:-1;78634:28:0;;;78630:328;;-1:-1:-1;;;;;78701:18:0;;78679:19;78701:18;;;:12;:18;;;;;;;;:34;;;;;;;;;78752:30;;;;;;:44;;;78869:30;;:17;:30;;;;;:43;;;78630:328;-1:-1:-1;79054:26:0;;;;:17;:26;;;;;;;;79047:33;;;-1:-1:-1;;;;;79098:18:0;;;;;:12;:18;;;;;:34;;;;;;;79091:41;78152:988::o;79435:1079::-;79713:10;:17;79688:22;;79713:21;;79733:1;;79713:21;:::i;:::-;79745:18;79766:24;;;:15;:24;;;;;;80139:10;:26;;79688:46;;-1:-1:-1;79766:24:0;;79688:46;;80139:26;;;;;;:::i;:::-;;;;;;;;;80117:48;;80203:11;80178:10;80189;80178:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;80283:28;;;:15;:28;;;;;;;:41;;;80455:24;;;;;80448:31;80490:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;79506:1008;;;79435:1079;:::o;76939:221::-;77024:14;77041:20;77058:2;77041:16;:20::i;:::-;-1:-1:-1;;;;;77072:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;77117:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;76939:221:0:o;14:131:1:-;-1:-1:-1;;;;;;88:32:1;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;592:250::-;677:1;687:113;701:6;698:1;695:13;687:113;;;777:11;;;771:18;758:11;;;751:39;723:2;716:10;687:113;;;-1:-1:-1;;834:1:1;816:16;;809:27;592:250::o;847:271::-;889:3;927:5;921:12;954:6;949:3;942:19;970:76;1039:6;1032:4;1027:3;1023:14;1016:4;1009:5;1005:16;970:76;:::i;:::-;1100:2;1079:15;-1:-1:-1;;1075:29:1;1066:39;;;;1107:4;1062:50;;847:271;-1:-1:-1;;847:271:1:o;1123:220::-;1272:2;1261:9;1254:21;1235:4;1292:45;1333:2;1322:9;1318:18;1310:6;1292:45;:::i;1348:180::-;1407:6;1460:2;1448:9;1439:7;1435:23;1431:32;1428:52;;;1476:1;1473;1466:12;1428:52;-1:-1:-1;1499:23:1;;1348:180;-1:-1:-1;1348:180:1:o;1741:173::-;1809:20;;-1:-1:-1;;;;;1858:31:1;;1848:42;;1838:70;;1904:1;1901;1894:12;1838:70;1741:173;;;:::o;1919:254::-;1987:6;1995;2048:2;2036:9;2027:7;2023:23;2019:32;2016:52;;;2064:1;2061;2054:12;2016:52;2087:29;2106:9;2087:29;:::i;:::-;2077:39;2163:2;2148:18;;;;2135:32;;-1:-1:-1;;;1919:254:1:o;2360:328::-;2437:6;2445;2453;2506:2;2494:9;2485:7;2481:23;2477:32;2474:52;;;2522:1;2519;2512:12;2474:52;2545:29;2564:9;2545:29;:::i;:::-;2535:39;;2593:38;2627:2;2616:9;2612:18;2593:38;:::i;:::-;2583:48;;2678:2;2667:9;2663:18;2650:32;2640:42;;2360:328;;;;;:::o;2693:118::-;2779:5;2772:13;2765:21;2758:5;2755:32;2745:60;;2801:1;2798;2791:12;2816:241;2872:6;2925:2;2913:9;2904:7;2900:23;2896:32;2893:52;;;2941:1;2938;2931:12;2893:52;2980:9;2967:23;2999:28;3021:5;2999:28;:::i;3483:127::-;3544:10;3539:3;3535:20;3532:1;3525:31;3575:4;3572:1;3565:15;3599:4;3596:1;3589:15;3615:632;3680:5;3710:18;3751:2;3743:6;3740:14;3737:40;;;3757:18;;:::i;:::-;3832:2;3826:9;3800:2;3886:15;;-1:-1:-1;;3882:24:1;;;3908:2;3878:33;3874:42;3862:55;;;3932:18;;;3952:22;;;3929:46;3926:72;;;3978:18;;:::i;:::-;4018:10;4014:2;4007:22;4047:6;4038:15;;4077:6;4069;4062:22;4117:3;4108:6;4103:3;4099:16;4096:25;4093:45;;;4134:1;4131;4124:12;4093:45;4184:6;4179:3;4172:4;4164:6;4160:17;4147:44;4239:1;4232:4;4223:6;4215;4211:19;4207:30;4200:41;;;;3615:632;;;;;:::o;4252:451::-;4321:6;4374:2;4362:9;4353:7;4349:23;4345:32;4342:52;;;4390:1;4387;4380:12;4342:52;4430:9;4417:23;4463:18;4455:6;4452:30;4449:50;;;4495:1;4492;4485:12;4449:50;4518:22;;4571:4;4563:13;;4559:27;-1:-1:-1;4549:55:1;;4600:1;4597;4590:12;4549:55;4623:74;4689:7;4684:2;4671:16;4666:2;4662;4658:11;4623:74;:::i;4708:254::-;4776:6;4784;4837:2;4825:9;4816:7;4812:23;4808:32;4805:52;;;4853:1;4850;4843:12;4805:52;4889:9;4876:23;4866:33;;4918:38;4952:2;4941:9;4937:18;4918:38;:::i;:::-;4908:48;;4708:254;;;;;:::o;4967:186::-;5026:6;5079:2;5067:9;5058:7;5054:23;5050:32;5047:52;;;5095:1;5092;5085:12;5047:52;5118:29;5137:9;5118:29;:::i;5343:315::-;5408:6;5416;5469:2;5457:9;5448:7;5444:23;5440:32;5437:52;;;5485:1;5482;5475:12;5437:52;5508:29;5527:9;5508:29;:::i;:::-;5498:39;;5587:2;5576:9;5572:18;5559:32;5600:28;5622:5;5600:28;:::i;:::-;5647:5;5637:15;;;5343:315;;;;;:::o;5663:667::-;5758:6;5766;5774;5782;5835:3;5823:9;5814:7;5810:23;5806:33;5803:53;;;5852:1;5849;5842:12;5803:53;5875:29;5894:9;5875:29;:::i;:::-;5865:39;;5923:38;5957:2;5946:9;5942:18;5923:38;:::i;:::-;5913:48;;6008:2;5997:9;5993:18;5980:32;5970:42;;6063:2;6052:9;6048:18;6035:32;6090:18;6082:6;6079:30;6076:50;;;6122:1;6119;6112:12;6076:50;6145:22;;6198:4;6190:13;;6186:27;-1:-1:-1;6176:55:1;;6227:1;6224;6217:12;6176:55;6250:74;6316:7;6311:2;6298:16;6293:2;6289;6285:11;6250:74;:::i;:::-;6240:84;;;5663:667;;;;;;;:::o;6335:615::-;6421:6;6429;6482:2;6470:9;6461:7;6457:23;6453:32;6450:52;;;6498:1;6495;6488:12;6450:52;6538:9;6525:23;6567:18;6608:2;6600:6;6597:14;6594:34;;;6624:1;6621;6614:12;6594:34;6662:6;6651:9;6647:22;6637:32;;6707:7;6700:4;6696:2;6692:13;6688:27;6678:55;;6729:1;6726;6719:12;6678:55;6769:2;6756:16;6795:2;6787:6;6784:14;6781:34;;;6811:1;6808;6801:12;6781:34;6864:7;6859:2;6849:6;6846:1;6842:14;6838:2;6834:23;6830:32;6827:45;6824:65;;;6885:1;6882;6875:12;6824:65;6916:2;6908:11;;;;;6938:6;;-1:-1:-1;6335:615:1;;-1:-1:-1;;;;6335:615:1:o;6955:260::-;7023:6;7031;7084:2;7072:9;7063:7;7059:23;7055:32;7052:52;;;7100:1;7097;7090:12;7052:52;7123:29;7142:9;7123:29;:::i;:::-;7113:39;;7171:38;7205:2;7194:9;7190:18;7171:38;:::i;7220:380::-;7299:1;7295:12;;;;7342;;;7363:61;;7417:4;7409:6;7405:17;7395:27;;7363:61;7470:2;7462:6;7459:14;7439:18;7436:38;7433:161;;7516:10;7511:3;7507:20;7504:1;7497:31;7551:4;7548:1;7541:15;7579:4;7576:1;7569:15;7433:161;;7220:380;;;:::o;8746:245::-;8813:6;8866:2;8854:9;8845:7;8841:23;8837:32;8834:52;;;8882:1;8879;8872:12;8834:52;8914:9;8908:16;8933:28;8955:5;8933:28;:::i;9821:127::-;9882:10;9877:3;9873:20;9870:1;9863:31;9913:4;9910:1;9903:15;9937:4;9934:1;9927:15;10079:545;10181:2;10176:3;10173:11;10170:448;;;10217:1;10242:5;10238:2;10231:17;10287:4;10283:2;10273:19;10357:2;10345:10;10341:19;10338:1;10334:27;10328:4;10324:38;10393:4;10381:10;10378:20;10375:47;;;-1:-1:-1;10416:4:1;10375:47;10471:2;10466:3;10462:12;10459:1;10455:20;10449:4;10445:31;10435:41;;10526:82;10544:2;10537:5;10534:13;10526:82;;;10589:17;;;10570:1;10559:13;10526:82;;;10530:3;;;10079:545;;;:::o;10800:1352::-;10926:3;10920:10;10953:18;10945:6;10942:30;10939:56;;;10975:18;;:::i;:::-;11004:97;11094:6;11054:38;11086:4;11080:11;11054:38;:::i;:::-;11048:4;11004:97;:::i;:::-;11156:4;;11220:2;11209:14;;11237:1;11232:663;;;;11939:1;11956:6;11953:89;;;-1:-1:-1;12008:19:1;;;12002:26;11953:89;-1:-1:-1;;10757:1:1;10753:11;;;10749:24;10745:29;10735:40;10781:1;10777:11;;;10732:57;12055:81;;11202:944;;11232:663;10026:1;10019:14;;;10063:4;10050:18;;-1:-1:-1;;11268:20:1;;;11386:236;11400:7;11397:1;11394:14;11386:236;;;11489:19;;;11483:26;11468:42;;11581:27;;;;11549:1;11537:14;;;;11416:19;;11386:236;;;11390:3;11650:6;11641:7;11638:19;11635:201;;;11711:19;;;11705:26;-1:-1:-1;;11794:1:1;11790:14;;;11806:3;11786:24;11782:37;11778:42;11763:58;11748:74;;11635:201;-1:-1:-1;;;;;11882:1:1;11866:14;;;11862:22;11849:36;;-1:-1:-1;10800:1352:1:o;12157:127::-;12218:10;12213:3;12209:20;12206:1;12199:31;12249:4;12246:1;12239:15;12273:4;12270:1;12263:15;12289:125;12354:9;;;12375:10;;;12372:36;;;12388:18;;:::i;13121:135::-;13160:3;13181:17;;;13178:43;;13201:18;;:::i;:::-;-1:-1:-1;13248:1:1;13237:13;;13121:135::o;16067:496::-;16246:3;16284:6;16278:13;16300:66;16359:6;16354:3;16347:4;16339:6;16335:17;16300:66;:::i;:::-;16429:13;;16388:16;;;;16451:70;16429:13;16388:16;16498:4;16486:17;;16451:70;:::i;:::-;16537:20;;16067:496;-1:-1:-1;;;;16067:496:1:o;16975:409::-;17177:2;17159:21;;;17216:2;17196:18;;;17189:30;17255:34;17250:2;17235:18;;17228:62;-1:-1:-1;;;17321:2:1;17306:18;;17299:43;17374:3;17359:19;;16975:409::o;18596:401::-;18798:2;18780:21;;;18837:2;18817:18;;;18810:30;18876:34;18871:2;18856:18;;18849:62;-1:-1:-1;;;18942:2:1;18927:18;;18920:35;18987:3;18972:19;;18596:401::o;19407:414::-;19609:2;19591:21;;;19648:2;19628:18;;;19621:30;19687:34;19682:2;19667:18;;19660:62;-1:-1:-1;;;19753:2:1;19738:18;;19731:48;19811:3;19796:19;;19407:414::o;20966:489::-;-1:-1:-1;;;;;21235:15:1;;;21217:34;;21287:15;;21282:2;21267:18;;21260:43;21334:2;21319:18;;21312:34;;;21382:3;21377:2;21362:18;;21355:31;;;21160:4;;21403:46;;21429:19;;21421:6;21403:46;:::i;:::-;21395:54;20966:489;-1:-1:-1;;;;;;20966:489:1:o;21460:249::-;21529:6;21582:2;21570:9;21561:7;21557:23;21553:32;21550:52;;;21598:1;21595;21588:12;21550:52;21630:9;21624:16;21649:30;21673:5;21649:30;:::i;21714:128::-;21781:9;;;21802:11;;;21799:37;;;21816:18;;:::i;21847:127::-;21908:10;21903:3;21899:20;21896:1;21889:31;21939:4;21936:1;21929:15;21963:4;21960:1;21953:15

Swarm Source

ipfs://971fa95e0dc1bf1934eb43edbed0fc692201d08d83d60f9ff2fad82672432fcf
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.