ETH Price: $3,353.26 (-0.10%)
 

Overview

Max Total Supply

329 ROOM

Holders

92

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
6 ROOM
0xe42392a291589DB62B504D2518Ca8833499466fA
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:
ROOM22

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 2023-03-07
*/

// SPDX-License-Identifier: MIT

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

// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

            return true;
        } else {
            return false;
        }
    }

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

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

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

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

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

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

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

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

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

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

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

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

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

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

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

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

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

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

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

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

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

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

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

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

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

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

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

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

        return result;
    }
}

// File: contracts/IOperatorFilterRegistry.sol

pragma solidity ^0.8.13;

interface IOperatorFilterRegistry {
    function isOperatorAllowed(address registrant, address operator)
        external
        returns (bool);

    function register(address registrant) external;

    function registerAndSubscribe(address registrant, address subscription)
        external;

    function registerAndCopyEntries(
        address registrant,
        address registrantToCopy
    ) 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;

contract OperatorFilterer {
    error OperatorNotAllowed(address operator);

    IOperatorFilterRegistry constant operatorFilterRegistry =
        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(operatorFilterRegistry).code.length > 0) {
            if (subscribe) {
                operatorFilterRegistry.registerAndSubscribe(
                    address(this),
                    subscriptionOrRegistrantToCopy
                );
            } else {
                if (subscriptionOrRegistrantToCopy != address(0)) {
                    operatorFilterRegistry.registerAndCopyEntries(
                        address(this),
                        subscriptionOrRegistrantToCopy
                    );
                } else {
                    operatorFilterRegistry.register(address(this));
                }
            }
        }
    }

    modifier onlyAllowedOperator() virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(operatorFilterRegistry).code.length > 0) {
            if (
                !operatorFilterRegistry.isOperatorAllowed(
                    address(this),
                    msg.sender
                )
            ) {
                revert OperatorNotAllowed(msg.sender);
            }
        }
        _;
    }
}
// File: contracts/DefaultOperatorFilterer.sol

pragma solidity ^0.8.13;

contract DefaultOperatorFilterer is OperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION =
        address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

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

// 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/interfaces/IERC2981.sol

// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

// File: @openzeppelin/contracts/token/common/ERC2981.sol

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

pragma solidity ^0.8.0;

/**
 * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
 *
 * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
 * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
 *
 * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
 * fee is specified in basis points by default.
 *
 * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
 * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 *
 * _Available since v4.5._
 */
abstract contract ERC2981 is IERC2981, ERC165 {
    struct RoyaltyInfo {
        address receiver;
        uint96 royaltyFraction;
    }

    RoyaltyInfo private _defaultRoyaltyInfo;
    mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;

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

    /**
     * @inheritdoc IERC2981
     */
    function royaltyInfo(uint256 _tokenId, uint256 _salePrice)
        public
        view
        virtual
        override
        returns (address, uint256)
    {
        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];

        if (royalty.receiver == address(0)) {
            royalty = _defaultRoyaltyInfo;
        }

        uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) /
            _feeDenominator();

        return (royalty.receiver, royaltyAmount);
    }

    /**
     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
     * override.
     */
    function _feeDenominator() internal pure virtual returns (uint96) {
        return 10000;
    }

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setDefaultRoyalty(address receiver, uint96 feeNumerator)
        internal
        virtual
    {
        require(
            feeNumerator <= _feeDenominator(),
            "ERC2981: royalty fee will exceed salePrice"
        );
        require(receiver != address(0), "ERC2981: invalid receiver");

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Removes default royalty information.
     */
    function _deleteDefaultRoyalty() internal virtual {
        delete _defaultRoyaltyInfo;
    }

    /**
     * @dev Sets the royalty information for a specific token id, overriding the global default.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setTokenRoyalty(
        uint256 tokenId,
        address receiver,
        uint96 feeNumerator
    ) internal virtual {
        require(
            feeNumerator <= _feeDenominator(),
            "ERC2981: royalty fee will exceed salePrice"
        );
        require(receiver != address(0), "ERC2981: Invalid parameters");

        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Resets royalty information for the token id back to the global default.
     */
    function _resetTokenRoyalty(uint256 tokenId) internal virtual {
        delete _tokenRoyaltyInfo[tokenId];
    }
}

// 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/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/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/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/token/ERC721/extensions/IERC721Metadata.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

pragma solidity ^0.8.0;

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

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

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

// OpenZeppelin Contracts (last updated v4.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: @openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

abstract contract Ownable is Context {
    address private _owner;

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

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

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

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

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

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

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

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

// File: contracts/RocStar22.sol

// Dev: N.R.H
// Max is a nerd
// Roc will never notice this
// Didi knows nothing
pragma solidity ^0.8.15;

contract ROOM22 is
    Ownable,
    ERC721Enumerable,
    DefaultOperatorFilterer,
    ReentrancyGuard,
    ERC2981
{
    string private baseTokenURI;

    // Minting
    bool public paused;

    uint256 public allowlistStartTime = 1674329400;
    uint256 public publicStartTime = 1678377600;

    mapping(address => bool) private oglist;
    mapping(address => bool) private allowlist;

    mapping(uint256 => uint256) private tokensMatrix;

    uint256 public maxMint = 10;
    uint256 public price = .022 ether;
    uint256 public allowlistPrice = .018 ether;
    uint256 public oglistPrice = 0 ether;

    // Royalties
    uint256 public mintRoyalties = 0;
    uint256 public totalRoyalties = 0;
    mapping(uint256 => uint256) private claimedRoyalties;
    uint256 private currentRoyalties = 0;

    // Payout
    address public projectWallet;

    // Events
    event MintStatusChanged(bool paused);
    event AllowlistUpdated();
    event OglistUpdated();
    event Minted(
        address indexed sender,
        uint256 currentSupply,
        uint256 amount,
        uint256 time
    );
    event RoyaltiesClaimed(address indexed sender, uint256 amount);

    // Errors
    error MintNotOpen();
    error PausedMint();
    error InsufficientPayment();
    error YouallReadyClaimed();
    error CannotMintZero();
    error OverMint();
    error MintLimit();
    error FreeMintLimit();
    error AddingNoRewards();

    // Constants
    uint256 public constant MAX_SUPPLY = 2222;

    // Structs
    struct TokenInfo {
        uint256 id;
        uint256 royalties;
    }

    struct MintInfo {
        bool paused;
        uint256 supply;
        uint256 maxSupply;
        uint256 maxMint;
        uint256 publicTimestamp;
        uint256 alTimestamp;
    }

    constructor(string memory uri_, address projectWallet_)
        ERC721("ROOM22", "ROOM")
    {
        baseTokenURI = uri_;
        projectWallet = projectWallet_;

        setDefaultRoyalty(projectWallet_, 1000);
    }

    // Owner
    // - Setup
    function setProjectWallet(address projectWallet_) public onlyOwner {
        projectWallet = projectWallet_;
    }

    function setBaseTokenURI(string memory uri) public onlyOwner {
        baseTokenURI = uri;
    }

    function setDefaultRoyalty(address receiver, uint96 feeNumerator)
        public
        onlyOwner
    {
        _setDefaultRoyalty(receiver, feeNumerator);
    }

    function addAllowlist(address[] memory addresses_) external onlyOwner {
        for (uint256 i = 0; i < addresses_.length; ) {
            allowlist[addresses_[i]] = true;
            unchecked {
                ++i;
            }
        }

        emit AllowlistUpdated();
    }

    function addOglist(address[] memory addresses_) external onlyOwner {
        for (uint256 i = 0; i < addresses_.length; ) {
            oglist[addresses_[i]] = true;
            unchecked {
                ++i;
            }
        }

        emit OglistUpdated();
    }

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

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

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

    function setTimestamps(
        uint256 allowlistStartTime_,
        uint256 publicStartTime_
    ) external onlyOwner {
        allowlistStartTime = allowlistStartTime_;
        publicStartTime = publicStartTime_;
    }

    function setMintRoyalties(uint256 mintRoyalties_) external onlyOwner {
        mintRoyalties = mintRoyalties_;
    }

    function setMaxMint(uint256 maxMint_) external onlyOwner {
        maxMint = maxMint_;
    }

    function setPrice(uint256 price_) external onlyOwner {
        price = price_;
    }

    function setallowlistPrice(uint256 allowlistPrice_) external onlyOwner {
        allowlistPrice = allowlistPrice_;
    }

    // - Team minting
    function teamMintSpecific(uint256[] memory tokens, address to)
        external
        onlyOwner
        nonReentrant
    {
        uint256 currentSupply = totalSupply();

        if (currentSupply + tokens.length > MAX_SUPPLY) revert OverMint();

        for (uint256 i = 0; i < tokens.length; ) {
            uint256 tokenId = tokens[i];
            fixTokenId(tokenId);

            _safeMint(to, tokenId);

            unchecked {
                claimedRoyalties[tokenId] = currentRoyalties;
                ++i;
            }
        }

        emit Minted(
            _msgSender(),
            currentSupply,
            tokens.length,
            block.timestamp
        );
    }

    function teamMint(uint256 amount, address to) external onlyOwner {
        uint256 currentSupply = totalSupply();

        if (currentSupply + amount > MAX_SUPPLY) revert OverMint();

        for (uint256 i = 1; i <= amount; ) {
            uint256 tokenId = randomTokenId();

            _safeMint(to, tokenId);
            unchecked {
                claimedRoyalties[tokenId] = currentRoyalties;
                ++i;
            }
        }

        emit Minted(_msgSender(), currentSupply, amount, block.timestamp);
    }

    function _payout(uint256 _amount) private {
        (bool success, ) = payable(projectWallet).call{
            value: _amount,
            gas: 50000
        }("");
        require(success, "Cannot payout");
    }

    function freeMint(uint256 amount) external payable nonReentrant {
        if (paused) revert PausedMint();
        if (!isOglisted(_msgSender()) && block.timestamp < publicStartTime)
            revert MintNotOpen();
        if (block.timestamp < allowlistStartTime) revert MintNotOpen();
        if (amount > maxMint) revert MintLimit();
        if (amount == 0) revert CannotMintZero();

        uint256 totalPrice = freemintPrice(_msgSender()) * amount;
        uint256 currentSupply = totalSupply();

        if (currentSupply + amount > MAX_SUPPLY) revert OverMint();
        if (balanceOf(msg.sender) > 0) revert YouallReadyClaimed();
        if (msg.value != totalPrice) revert InsufficientPayment();

        uint256 royalties = 0;
        if (currentSupply > 0 && mintRoyalties > 0) {
            royalties = (msg.value * mintRoyalties) / 100;
            _addRewards(royalties);
        }

        for (uint256 i = 1; i <= amount; ) {
            uint256 tokenId = randomTokenId();
            _safeMint(_msgSender(), tokenId);
            unchecked {
                claimedRoyalties[tokenId] = currentRoyalties;
                ++i;
            }
        }

        uint256 payout = totalPrice - royalties;

        _payout(payout);

        emit Minted(_msgSender(), currentSupply, amount, block.timestamp);
    }

    function mint(uint256 amount) external payable nonReentrant {
        if (paused) revert PausedMint();
        if (!isAllowlisted(_msgSender()) && block.timestamp < publicStartTime)
            revert MintNotOpen();
        if (block.timestamp < allowlistStartTime) revert MintNotOpen();
        if (amount > maxMint) revert MintLimit();
        if (amount == 0) revert CannotMintZero();

        uint256 totalPrice = mintPrice(_msgSender()) * amount;
        uint256 currentSupply = totalSupply();

        if (currentSupply + amount > MAX_SUPPLY) revert OverMint();
        if (msg.value != totalPrice) revert InsufficientPayment();

        uint256 royalties = 0;
        if (currentSupply > 0 && mintRoyalties > 0) {
            royalties = (msg.value * mintRoyalties) / 100;
            _addRewards(royalties);
        }

        for (uint256 i = 1; i <= amount; ) {
            uint256 tokenId = randomTokenId();
            _safeMint(_msgSender(), tokenId);
            unchecked {
                claimedRoyalties[tokenId] = currentRoyalties;
                ++i;
            }
        }

        uint256 payout = totalPrice - royalties;

        _payout(payout);

        emit Minted(_msgSender(), currentSupply, amount, block.timestamp);
    }

    function fixTokenId(uint256 tokenId_) internal {
        uint256 random = tokenId_ - 1;
        uint256 maxIndex = MAX_SUPPLY - totalSupply();

        if (tokensMatrix[maxIndex - 1] == 0) {
            tokensMatrix[random] = maxIndex - 1;
        } else {
            tokensMatrix[random] = tokensMatrix[maxIndex - 1];
        }
    }

    function randomTokenId() internal returns (uint256) {
        uint256 maxIndex = MAX_SUPPLY - totalSupply();

        uint256 random = uint256(
            keccak256(
                abi.encodePacked(
                    msg.sender,
                    block.coinbase,
                    block.difficulty,
                    block.gaslimit,
                    block.timestamp
                )
            )
        ) % maxIndex;

        uint256 value = 0;
        if (tokensMatrix[random] == 0) {
            value = random;
        } else {
            value = tokensMatrix[random];
        }

        if (tokensMatrix[maxIndex - 1] == 0) {
            tokensMatrix[random] = maxIndex - 1;
        } else {
            tokensMatrix[random] = tokensMatrix[maxIndex - 1];
        }

        return value + 1;
    }

    function tokensOfWallet(address _address)
        external
        view
        returns (uint256[] memory)
    {
        uint256 ownerTokenCount = balanceOf(_address);
        uint256[] memory tokenIds = new uint256[](ownerTokenCount);
        for (uint256 i; i < ownerTokenCount; i++) {
            tokenIds[i] = tokenOfOwnerByIndex(_address, i);
        }
        return tokenIds;
    }

    // Internal
    function _baseURI() internal view virtual override returns (string memory) {
        return baseTokenURI;
    }

    function tokenURI(uint256 _tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        require(
            _exists(_tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );
        string memory _tokenURI = string(
            abi.encodePacked(baseTokenURI, Strings.toString(_tokenId), ".json")
        );

        return _tokenURI;
    }

    // Getters
    function getMintInfo() external view returns (MintInfo memory) {
        return
            MintInfo(
                paused,
                totalSupply(),
                MAX_SUPPLY,
                maxMint,
                publicStartTime,
                allowlistStartTime
            );
    }

    // function freeMintCount(address _address) public view returns (uint256) {
    //     return oglist[_address];
    // }

    function isOglisted(address _address) public view returns (bool) {
        return oglist[_address];
    }

    function freemintPrice(address _address) public view returns (uint256) {
        return isOglisted(_address) ? oglistPrice : price;
    }

    function isAllowlisted(address _address) public view returns (bool) {
        return allowlist[_address];
    }

    function mintPrice(address _address) public view returns (uint256) {
        return isAllowlisted(_address) ? allowlistPrice : price;
    }

    // Royalties
    function addRoyalties() external payable {
        _addRewards(msg.value);
    }

    function _addRewards(uint256 amount) private {
        if (amount == 0) revert AddingNoRewards();

        totalRoyalties = totalRoyalties + amount;
        currentRoyalties += amount / totalSupply();
    }

    // Getters
    function getRewardsToken(uint256 id) public view returns (uint256 rewards) {
        rewards += currentRoyalties - claimedRoyalties[id];
    }

    function getRoyalties(address sender) external view returns (uint256) {
        uint256 balance = 0;

        uint256 count = balanceOf(sender);
        for (uint256 i = 0; i < count; i++) {
            uint256 tokenId = tokenOfOwnerByIndex(sender, i);
            balance += getRewardsToken(tokenId);
        }
        return balance;
    }

    function getRoyaltiesDetails(address sender)
        external
        view
        returns (TokenInfo[] memory)
    {
        uint256 count = balanceOf(sender);
        TokenInfo[] memory tokens = new TokenInfo[](count);

        for (uint256 i = 0; i < count; i++) {
            uint256 tokenId = tokenOfOwnerByIndex(sender, i);
            uint256 royalties = getRewardsToken(tokenId);
            tokens[i].id = tokenId;
            tokens[i].royalties = royalties;
        }

        return tokens;
    }

    // Claim
    function claimAllRoyalties() external {
        uint256 rewards = 0;

        uint256 count = balanceOf(_msgSender());
        for (uint256 i = 0; i < count; ) {
            uint256 tokenId = tokenOfOwnerByIndex(_msgSender(), i);
            unchecked {
                rewards += getRewardsToken(tokenId);
                claimedRoyalties[tokenId] = currentRoyalties;
                ++i;
            }
        }

        payable(_msgSender()).transfer(rewards);
        emit RoyaltiesClaimed(_msgSender(), rewards);
    }

    function claimRoyalties(uint256[] memory tokensToClaim) external {
        uint256 rewards = 0;

        for (uint256 i = 0; i < tokensToClaim.length; ) {
            unchecked {
                uint256 tokenId = tokensToClaim[i];
                if (ownerOf(tokenId) == _msgSender()) {
                    rewards += (getRewardsToken(tokenId));
                    claimedRoyalties[tokenId] = currentRoyalties;
                }
                ++i;
            }
        }

        payable(_msgSender()).transfer(rewards);
        emit RoyaltiesClaimed(_msgSender(), rewards);
    }

    function withdrawAll() external onlyOwner {
        (bool success, ) = owner().call{value: address(this).balance}("");
        require(success, "Transfer failed.");
    }

    // Overrides
    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721Enumerable, ERC2981)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"uri_","type":"string"},{"internalType":"address","name":"projectWallet_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddingNoRewards","type":"error"},{"inputs":[],"name":"CannotMintZero","type":"error"},{"inputs":[],"name":"FreeMintLimit","type":"error"},{"inputs":[],"name":"InsufficientPayment","type":"error"},{"inputs":[],"name":"MintLimit","type":"error"},{"inputs":[],"name":"MintNotOpen","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"OverMint","type":"error"},{"inputs":[],"name":"PausedMint","type":"error"},{"inputs":[],"name":"YouallReadyClaimed","type":"error"},{"anonymous":false,"inputs":[],"name":"AllowlistUpdated","type":"event"},{"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":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"MintStatusChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"currentSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[],"name":"OglistUpdated","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":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RoyaltiesClaimed","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":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses_","type":"address[]"}],"name":"addAllowlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses_","type":"address[]"}],"name":"addOglist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addRoyalties","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"allowlistPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowlistStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[],"name":"claimAllRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokensToClaim","type":"uint256[]"}],"name":"claimRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"freeMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"freemintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintInfo","outputs":[{"components":[{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"maxSupply","type":"uint256"},{"internalType":"uint256","name":"maxMint","type":"uint256"},{"internalType":"uint256","name":"publicTimestamp","type":"uint256"},{"internalType":"uint256","name":"alTimestamp","type":"uint256"}],"internalType":"struct ROOM22.MintInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getRewardsToken","outputs":[{"internalType":"uint256","name":"rewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"getRoyalties","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"getRoyaltiesDetails","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"royalties","type":"uint256"}],"internalType":"struct ROOM22.TokenInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isAllowlisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[{"internalType":"address","name":"_address","type":"address"}],"name":"isOglisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"mintPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintRoyalties","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oglistPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"projectWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"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":"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":"setBaseTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxMint_","type":"uint256"}],"name":"setMaxMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mintRoyalties_","type":"uint256"}],"name":"setMintRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"price_","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"projectWallet_","type":"address"}],"name":"setProjectWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"allowlistStartTime_","type":"uint256"},{"internalType":"uint256","name":"publicStartTime_","type":"uint256"}],"name":"setTimestamps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"allowlistPrice_","type":"uint256"}],"name":"setallowlistPrice","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":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"teamMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokens","type":"uint256[]"},{"internalType":"address","name":"to","type":"address"}],"name":"teamMintSpecific","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"address","name":"_address","type":"address"}],"name":"tokensOfWallet","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRoyalties","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526363cc3d3860105563640a0280601155600a601555664e28e2290f0000601655663ff2e795f50000601755600060185560006019556000601a556000601c553480156200005057600080fd5b506040516200422438038062004224833981016040819052620000739162000490565b733cc6cdda760b79bafa08df41ecfa224f810dceb66001604051806040016040528060068152602001652927a7a6991960d11b81525060405180604001604052806004815260200163524f4f4d60e01b815250620000e0620000da6200028c60201b60201c565b62000290565b6001620000ee838262000607565b506002620000fd828262000607565b5050506daaeb6d7670e522a718067333cd4e3b15620002455780156200019357604051633e9f1edf60e11b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b600060405180830381600087803b1580156200017457600080fd5b505af115801562000189573d6000803e3d6000fd5b5050505062000245565b6001600160a01b03821615620001e45760405163a0af290360e01b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e9063a0af29039060440162000159565b604051632210724360e11b81523060048201526daaeb6d7670e522a718067333cd4e90634420e48690602401600060405180830381600087803b1580156200022b57600080fd5b505af115801562000240573d6000803e3d6000fd5b505050505b50506001600b55600e6200025a838262000607565b50601d80546001600160a01b0319166001600160a01b03831617905562000284816103e8620002e0565b5050620006d3565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b620002ea620002fa565b620002f682826200035c565b5050565b6000546001600160a01b031633146200035a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b565b6127106001600160601b0382161115620003cc5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b606482015260840162000351565b6001600160a01b038216620004245760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c696420726563656976657200000000000000604482015260640162000351565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600c55565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200048b57600080fd5b919050565b60008060408385031215620004a457600080fd5b82516001600160401b0380821115620004bc57600080fd5b818501915085601f830112620004d157600080fd5b815181811115620004e657620004e66200045d565b604051601f8201601f19908116603f011681019083821181831017156200051157620005116200045d565b816040528281526020935088848487010111156200052e57600080fd5b600091505b8282101562000552578482018401518183018501529083019062000533565b60008484830101528096505050506200056d81860162000473565b925050509250929050565b600181811c908216806200058d57607f821691505b602082108103620005ae57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200060257600081815260208120601f850160051c81016020861015620005dd5750805b601f850160051c820191505b81811015620005fe57828155600101620005e9565b5050505b505050565b81516001600160401b038111156200062357620006236200045d565b6200063b8162000634845462000578565b84620005b4565b602080601f8311600181146200067357600084156200065a5750858301515b600019600386901b1c1916600185901b178555620005fe565b600085815260208120601f198616915b82811015620006a45788860151825594840194600190910190840162000683565b5085821015620006c35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b613b4180620006e36000396000f3fe6080604052600436106103815760003560e01c806370a08231116101d1578063a0712d6811610102578063d0520c23116100a0578063e9d595751161006f578063e9d5957514610a9b578063ea09e56614610ab1578063f2fde38b14610ad1578063fa10197714610af157600080fd5b8063d0520c23146109d1578063d74edb5e14610a34578063db4f6d3114610a4a578063e985e9c514610a5257600080fd5b8063b88d4fde116100dc578063b88d4fde14610951578063beb08ab914610971578063bfa457bc14610991578063c87b56dd146109b157600080fd5b8063a0712d68146108fe578063a22cb46514610911578063aa0c4a6b1461093157600080fd5b806386fd96941161016f57806390967a521161014957806390967a521461089d57806391b7f5ed146108b357806395d89b41146108d3578063a035b1fe146108e857600080fd5b806386fd9694146108325780638a7804471461085f5780638da5cb5b1461087f57600080fd5b806375935d11116101ab57806375935d11146107c75780637c928fe9146107f4578063853828b61461080757806386d026081461081c57600080fd5b806370a082311461077c578063715018a61461079c5780637501f741146107b157600080fd5b80632a55205a116102b65780634f6ccce71161025457806359d7bc4d1161022357806359d7bc4d146107165780635c975abb1461072c5780635fd1bbc4146107465780636352211e1461075c57600080fd5b80634f6ccce71461068857806352e43e83146106a8578063547520fe146106e1578063547eafd01461070157600080fd5b806332cb6b0c1161029057806332cb6b0c146106125780633cd972ac1461062857806342842e0e1461064857806346b370941461066857600080fd5b80632a55205a146105935780632f745c59146105d257806330176e13146105f257600080fd5b806313ece816116103235780632098a1b5116102fd5780632098a1b5146105135780632142aa2c1461053357806323b872dd146105535780632617dd4d1461057357600080fd5b806313ece816146104b057806314556a56146104d057806318160ddd146104fe57600080fd5b806306fdde031161035f57806306fdde0314610416578063081812fc14610438578063095ea7b3146104705780630b5f4bfd1461049057600080fd5b806301ffc9a71461038657806304634d8d146103bb57806305a3b809146103dd575b600080fd5b34801561039257600080fd5b506103a66103a1366004613131565b610b11565b60405190151581526020015b60405180910390f35b3480156103c757600080fd5b506103db6103d6366004613171565b610b22565b005b3480156103e957600080fd5b506103a66103f83660046131b4565b6001600160a01b031660009081526013602052604090205460ff1690565b34801561042257600080fd5b5061042b610b38565b6040516103b2919061321f565b34801561044457600080fd5b50610458610453366004613232565b610bca565b6040516001600160a01b0390911681526020016103b2565b34801561047c57600080fd5b506103db61048b36600461324b565b610bf1565b34801561049c57600080fd5b506103db6104ab366004613232565b610d0b565b3480156104bc57600080fd5b506103db6104cb36600461334b565b610d18565b3480156104dc57600080fd5b506104f06104eb3660046131b4565b610dfc565b6040519081526020016103b2565b34801561050a57600080fd5b506009546104f0565b34801561051f57600080fd5b506103db61052e366004613380565b610e56565b34801561053f57600080fd5b506104f061054e3660046131b4565b610ee9565b34801561055f57600080fd5b506103db61056e366004613418565b610f19565b34801561057f57600080fd5b506103db61058e366004613380565b610fcd565b34801561059f57600080fd5b506105b36105ae366004613454565b611060565b604080516001600160a01b0390931683526020830191909152016103b2565b3480156105de57600080fd5b506104f06105ed36600461324b565b61110c565b3480156105fe57600080fd5b506103db61060d3660046134ce565b6111a2565b34801561061e57600080fd5b506104f06108ae81565b34801561063457600080fd5b506104f0610643366004613232565b6111b6565b34801561065457600080fd5b506103db610663366004613418565b6111dc565b34801561067457600080fd5b506103db610683366004613517565b611290565b34801561069457600080fd5b506104f06106a3366004613232565b611385565b3480156106b457600080fd5b506103a66106c33660046131b4565b6001600160a01b031660009081526012602052604090205460ff1690565b3480156106ed57600080fd5b506103db6106fc366004613232565b611418565b34801561070d57600080fd5b506103db611425565b34801561072257600080fd5b506104f060105481565b34801561073857600080fd5b50600f546103a69060ff1681565b34801561075257600080fd5b506104f060115481565b34801561076857600080fd5b50610458610777366004613232565b6114d8565b34801561078857600080fd5b506104f06107973660046131b4565b611538565b3480156107a857600080fd5b506103db6115be565b3480156107bd57600080fd5b506104f060155481565b3480156107d357600080fd5b506107e76107e23660046131b4565b6115d2565b6040516103b29190613565565b6103db610802366004613232565b611674565b34801561081357600080fd5b506103db6118bb565b34801561082857600080fd5b506104f0601a5481565b34801561083e57600080fd5b5061085261084d3660046131b4565b611959565b6040516103b291906135a9565b34801561086b57600080fd5b506103db61087a3660046131b4565b611a4c565b34801561088b57600080fd5b506000546001600160a01b0316610458565b3480156108a957600080fd5b506104f060175481565b3480156108bf57600080fd5b506103db6108ce366004613232565b611a76565b3480156108df57600080fd5b5061042b611a83565b3480156108f457600080fd5b506104f060165481565b6103db61090c366004613232565b611a92565b34801561091d57600080fd5b506103db61092c366004613606565b611c42565b34801561093d57600080fd5b506104f061094c3660046131b4565b611c4d565b34801561095d57600080fd5b506103db61096c366004613632565b611c7d565b34801561097d57600080fd5b50601d54610458906001600160a01b031681565b34801561099d57600080fd5b506103db6109ac3660046136ae565b611d38565b3480156109bd57600080fd5b5061042b6109cc366004613232565b611dfc565b3480156109dd57600080fd5b506109e6611eb0565b6040516103b29190600060c0820190508251151582526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b348015610a4057600080fd5b506104f060195481565b6103db611f35565b348015610a5e57600080fd5b506103a6610a6d3660046136d1565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b348015610aa757600080fd5b506104f060185481565b348015610abd57600080fd5b506103db610acc366004613232565b611f3e565b348015610add57600080fd5b506103db610aec3660046131b4565b611f4b565b348015610afd57600080fd5b506103db610b0c366004613454565b611fc1565b6000610b1c82611fd4565b92915050565b610b2a611ff9565b610b348282612053565b5050565b606060018054610b47906136fb565b80601f0160208091040260200160405190810160405280929190818152602001828054610b73906136fb565b8015610bc05780601f10610b9557610100808354040283529160200191610bc0565b820191906000526020600020905b815481529060010190602001808311610ba357829003601f168201915b5050505050905090565b6000610bd582612150565b506000908152600560205260409020546001600160a01b031690565b6000610bfc826114d8565b9050806001600160a01b0316836001600160a01b031603610c6e5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610c8a5750610c8a8133610a6d565b610cfc5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610c65565b610d0683836121af565b505050565b610d13611ff9565b601955565b6000805b8251811015610d93576000838281518110610d3957610d39613735565b60200260200101519050610d4a3390565b6001600160a01b0316610d5c826114d8565b6001600160a01b031603610d8a57610d73816111b6565b601c546000838152601b6020526040902055909201915b50600101610d1c565b50604051339082156108fc029083906000818181858888f19350505050158015610dc1573d6000803e3d6000fd5b5060405181815233907f8fbbda19f4a70036f6f585dc4160142a8fa2a20ffb9393d23274f78de4e39888906020015b60405180910390a25050565b60008080610e0984611538565b905060005b81811015610e4d576000610e22868361110c565b9050610e2d816111b6565b610e379085613761565b9350508080610e4590613774565b915050610e0e565b50909392505050565b610e5e611ff9565b60005b8151811015610ebc57600160126000848481518110610e8257610e82613735565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101610e61565b506040517f0874ad8a4e51ef28f79a4bb4ad9897d3569a2afe601fdf6b116f0966701bcc1290600090a150565b6001600160a01b03811660009081526013602052604081205460ff16610f1157601654610b1c565b505060175490565b6daaeb6d7670e522a718067333cd4e3b15610fc257604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c6171134906044016020604051808303816000875af1158015610f7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa3919061378d565b610fc257604051633b79c77360e21b8152336004820152602401610c65565b610d0683838361221d565b610fd5611ff9565b60005b815181101561103357600160136000848481518110610ff957610ff9613735565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101610fd8565b506040517fac4285832aea1fb9e403127173fc92934a4267438dac67c9e366c1640b56bd8690600090a150565b6000828152600d602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916110d5575060408051808201909152600c546001600160a01b0381168252600160a01b90046001600160601b031660208201525b6020810151600090612710906110f4906001600160601b0316876137aa565b6110fe91906137d7565b915196919550909350505050565b600061111783611538565b82106111795760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610c65565b506001600160a01b03919091166000908152600760209081526040808320938352929052205490565b6111aa611ff9565b600e610b348282613839565b6000818152601b6020526040812054601c546111d291906138f9565b610b1c9082613761565b6daaeb6d7670e522a718067333cd4e3b1561128557604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c6171134906044016020604051808303816000875af1158015611242573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611266919061378d565b61128557604051633b79c77360e21b8152336004820152602401610c65565b610d0683838361224e565b611298611ff9565b6112a0612269565b60006112ab60095490565b90506108ae8351826112bd9190613761565b11156112dc57604051633bd7ad7760e21b815260040160405180910390fd5b60005b83518110156113345760008482815181106112fc576112fc613735565b6020026020010151905061130f816122c2565b6113198482612362565b601c546000918252601b6020526040909120556001016112df565b508251604080518381526020810192909252429082015233907f5a3358a3d27a5373c0df2604662088d37894d56b7cfd27f315770440f4e0d9199060600160405180910390a250610b346001600b55565b600061139060095490565b82106113f35760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610c65565b6009828154811061140657611406613735565b90600052602060002001549050919050565b611420611ff9565b601555565b60008061143133611538565b905060005b8181101561147757600061144a338361110c565b9050611455816111b6565b601c546000928352601b60205260409092209190915590920191600101611436565b50604051339083156108fc029084906000818181858888f193505050501580156114a5573d6000803e3d6000fd5b5060405182815233907f8fbbda19f4a70036f6f585dc4160142a8fa2a20ffb9393d23274f78de4e3988890602001610df0565b6000818152600360205260408120546001600160a01b031680610b1c5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c65565b60006001600160a01b0382166115a25760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610c65565b506001600160a01b031660009081526004602052604090205490565b6115c6611ff9565b6115d0600061237c565b565b606060006115df83611538565b905060008167ffffffffffffffff8111156115fc576115fc613275565b604051908082528060200260200182016040528015611625578160200160208202803683370190505b50905060005b8281101561166c5761163d858261110c565b82828151811061164f5761164f613735565b60209081029190910101528061166481613774565b91505061162b565b509392505050565b61167c612269565b600f5460ff16156116a057604051634c97d28b60e01b815260040160405180910390fd5b6116a9336106c3565b1580156116b7575060115442105b156116d55760405163951b974f60e01b815260040160405180910390fd5b6010544210156116f85760405163951b974f60e01b815260040160405180910390fd5b60155481111561171b5760405163ec8e6a6360e01b815260040160405180910390fd5b8060000361173c57604051632a6ce29960e11b815260040160405180910390fd5b60008161174833611c4d565b61175291906137aa565b9050600061175f60095490565b90506108ae61176e8483613761565b111561178d57604051633bd7ad7760e21b815260040160405180910390fd5b600061179833611538565b11156117b75760405163038e1a9f60e41b815260040160405180910390fd5b8134146117d75760405163cd1c886760e01b815260040160405180910390fd5b600080821180156117ea57506000601954115b15611814576064601954346117ff91906137aa565b61180991906137d7565b9050611814816123cc565b60015b848111611850576000611828612424565b9050611835335b82612362565b601c546000918252601b602052604090912055600101611817565b50600061185d82856138f9565b90506118688161255b565b60408051848152602081018790524281830152905133917f5a3358a3d27a5373c0df2604662088d37894d56b7cfd27f315770440f4e0d919919081900360600190a2505050506118b86001600b55565b50565b6118c3611ff9565b600080546040516001600160a01b039091169047908381818185875af1925050503d8060008114611910576040519150601f19603f3d011682016040523d82523d6000602084013e611915565b606091505b50509050806118b85760405162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b6044820152606401610c65565b6060600061196683611538565b905060008167ffffffffffffffff81111561198357611983613275565b6040519080825280602002602001820160405280156119c857816020015b60408051808201909152600080825260208201528152602001906001900390816119a15790505b50905060005b8281101561166c5760006119e2868361110c565b905060006119ef826111b6565b905081848481518110611a0457611a04613735565b6020026020010151600001818152505080848481518110611a2757611a27613735565b6020026020010151602001818152505050508080611a4490613774565b9150506119ce565b611a54611ff9565b601d80546001600160a01b0319166001600160a01b0392909216919091179055565b611a7e611ff9565b601655565b606060028054610b47906136fb565b611a9a612269565b600f5460ff1615611abe57604051634c97d28b60e01b815260040160405180910390fd5b611ac7336103f8565b158015611ad5575060115442105b15611af35760405163951b974f60e01b815260040160405180910390fd5b601054421015611b165760405163951b974f60e01b815260040160405180910390fd5b601554811115611b395760405163ec8e6a6360e01b815260040160405180910390fd5b80600003611b5a57604051632a6ce29960e11b815260040160405180910390fd5b600081611b6633610ee9565b611b7091906137aa565b90506000611b7d60095490565b90506108ae611b8c8483613761565b1115611bab57604051633bd7ad7760e21b815260040160405180910390fd5b813414611bcb5760405163cd1c886760e01b815260040160405180910390fd5b60008082118015611bde57506000601954115b15611c0857606460195434611bf391906137aa565b611bfd91906137d7565b9050611c08816123cc565b60015b848111611850576000611c1c612424565b9050611c273361182f565b601c546000918252601b602052604090912055600101611c0b565b610b343383836125f3565b6001600160a01b03811660009081526012602052604081205460ff16611c7557601654610b1c565b505060185490565b6daaeb6d7670e522a718067333cd4e3b15611d2657604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c6171134906044016020604051808303816000875af1158015611ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d07919061378d565b611d2657604051633b79c77360e21b8152336004820152602401610c65565b611d32848484846126c1565b50505050565b611d40611ff9565b6000611d4b60095490565b90506108ae611d5a8483613761565b1115611d7957604051633bd7ad7760e21b815260040160405180910390fd5b60015b838111611db4576000611d8d612424565b9050611d998482612362565b601c546000918252601b602052604090912055600101611d7c565b5060408051828152602081018590524281830152905133917f5a3358a3d27a5373c0df2604662088d37894d56b7cfd27f315770440f4e0d919919081900360600190a2505050565b6000818152600360205260409020546060906001600160a01b0316611e7b5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610c65565b6000600e611e88846126f3565b604051602001611e9992919061390c565b60408051601f198184030181529190529392505050565b611eeb6040518060c0016040528060001515815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805160c08101909152600f5460ff161515815260208101611f0d60095490565b81526020016108ae815260200160155481526020016011548152602001601054815250905090565b6115d0346123cc565b611f46611ff9565b601755565b611f53611ff9565b6001600160a01b038116611fb85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c65565b6118b88161237c565b611fc9611ff9565b601091909155601155565b60006001600160e01b0319821663152a902d60e11b1480610b1c5750610b1c82612786565b6000546001600160a01b031633146115d05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c65565b6127106001600160601b03821611156120c15760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610c65565b6001600160a01b0382166121175760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610c65565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600c55565b6000818152600360205260409020546001600160a01b03166118b85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c65565b600081815260056020526040902080546001600160a01b0319166001600160a01b03841690811790915581906121e4826114d8565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b61222733826127ab565b6122435760405162461bcd60e51b8152600401610c65906139a3565b610d0683838361282a565b610d0683838360405180602001604052806000815250611c7d565b6002600b54036122bb5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c65565b6002600b55565b60006122cf6001836138f9565b905060006122dc60095490565b6122e8906108ae6138f9565b9050601460006122f96001846138f9565b81526020019081526020016000205460000361232e5761231a6001826138f9565b600083815260146020526040902055505050565b6014600061233d6001846138f9565b8152602080820192909252604090810160009081205485825260149093522055505050565b610b3482826040518060200160405280600081525061299b565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b806000036123ed5760405163e3a12f6760e01b815260040160405180910390fd5b80601a546123fb9190613761565b601a5560095461240b90826137d7565b601c600082825461241c9190613761565b909155505050565b60008061243060095490565b61243c906108ae6138f9565b6040516bffffffffffffffffffffffff1933606090811b8216602084015241901b166034820152446048820152456068820152426088820152909150600090829060a8016040516020818303038152906040528051906020012060001c6124a391906139f0565b6000818152601460205260408120549192509081036124c35750806124d4565b506000818152601460205260409020545b601460006124e36001866138f9565b815260200190815260200160002054600003612518576125046001846138f9565b600083815260146020526040902055612548565b601460006125276001866138f9565b81526020808201929092526040908101600090812054858252601490935220555b612553816001613761565b935050505090565b601d546040516000916001600160a01b03169061c35090849084818181858888f193505050503d80600081146125ad576040519150601f19603f3d011682016040523d82523d6000602084013e6125b2565b606091505b5050905080610b345760405162461bcd60e51b815260206004820152600d60248201526c10d85b9b9bdd081c185e5bdd5d609a1b6044820152606401610c65565b816001600160a01b0316836001600160a01b0316036126545760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c65565b6001600160a01b03838116600081815260066020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6126cb33836127ab565b6126e75760405162461bcd60e51b8152600401610c65906139a3565b611d32848484846129ce565b6060600061270083612a01565b600101905060008167ffffffffffffffff81111561272057612720613275565b6040519080825280601f01601f19166020018201604052801561274a576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461275457509392505050565b60006001600160e01b0319821663780e9d6360e01b1480610b1c5750610b1c82612ad9565b6000806127b7836114d8565b9050806001600160a01b0316846001600160a01b031614806127fe57506001600160a01b0380821660009081526006602090815260408083209388168352929052205460ff165b806128225750836001600160a01b031661281784610bca565b6001600160a01b0316145b949350505050565b826001600160a01b031661283d826114d8565b6001600160a01b0316146128635760405162461bcd60e51b8152600401610c6590613a04565b6001600160a01b0382166128c55760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610c65565b6128d28383836001612b29565b826001600160a01b03166128e5826114d8565b6001600160a01b03161461290b5760405162461bcd60e51b8152600401610c6590613a04565b600081815260056020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260048552838620805460001901905590871680865283862080546001019055868652600390945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6129a58383612c69565b6129b26000848484612e02565b610d065760405162461bcd60e51b8152600401610c6590613a49565b6129d984848461282a565b6129e584848484612e02565b611d325760405162461bcd60e51b8152600401610c6590613a49565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310612a405772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612a6c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612a8a57662386f26fc10000830492506010015b6305f5e1008310612aa2576305f5e100830492506008015b6127108310612ab657612710830492506004015b60648310612ac8576064830492506002015b600a8310610b1c5760010192915050565b60006001600160e01b031982166380ac58cd60e01b1480612b0a57506001600160e01b03198216635b5e139f60e01b145b80610b1c57506301ffc9a760e01b6001600160e01b0319831614610b1c565b612b3584848484612f03565b6001811115612ba45760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b6064820152608401610c65565b816001600160a01b038516612c0057612bfb81600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b612c23565b836001600160a01b0316856001600160a01b031614612c2357612c238582612f8b565b6001600160a01b038416612c3f57612c3a81613028565b612c62565b846001600160a01b0316846001600160a01b031614612c6257612c6284826130d7565b5050505050565b6001600160a01b038216612cbf5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c65565b6000818152600360205260409020546001600160a01b031615612d245760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c65565b612d32600083836001612b29565b6000818152600360205260409020546001600160a01b031615612d975760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c65565b6001600160a01b038216600081815260046020908152604080832080546001019055848352600390915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001600160a01b0384163b15612ef857604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612e46903390899088908890600401613a9b565b6020604051808303816000875af1925050508015612e81575060408051601f3d908101601f19168201909252612e7e91810190613ad8565b60015b612ede573d808015612eaf576040519150601f19603f3d011682016040523d82523d6000602084013e612eb4565b606091505b508051600003612ed65760405162461bcd60e51b8152600401610c6590613a49565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612822565b506001949350505050565b6001811115611d32576001600160a01b03841615612f49576001600160a01b03841660009081526004602052604081208054839290612f439084906138f9565b90915550505b6001600160a01b03831615611d32576001600160a01b03831660009081526004602052604081208054839290612f80908490613761565b909155505050505050565b60006001612f9884611538565b612fa291906138f9565b600083815260086020526040902054909150808214612ff5576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b60095460009061303a906001906138f9565b6000838152600a60205260408120546009805493945090928490811061306257613062613735565b90600052602060002001549050806009838154811061308357613083613735565b6000918252602080832090910192909255828152600a909152604080822084905585825281205560098054806130bb576130bb613af5565b6001900381819060005260206000200160009055905550505050565b60006130e283611538565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b6001600160e01b0319811681146118b857600080fd5b60006020828403121561314357600080fd5b813561314e8161311b565b9392505050565b80356001600160a01b038116811461316c57600080fd5b919050565b6000806040838503121561318457600080fd5b61318d83613155565b915060208301356001600160601b03811681146131a957600080fd5b809150509250929050565b6000602082840312156131c657600080fd5b61314e82613155565b60005b838110156131ea5781810151838201526020016131d2565b50506000910152565b6000815180845261320b8160208601602086016131cf565b601f01601f19169290920160200192915050565b60208152600061314e60208301846131f3565b60006020828403121561324457600080fd5b5035919050565b6000806040838503121561325e57600080fd5b61326783613155565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156132b4576132b4613275565b604052919050565b600067ffffffffffffffff8211156132d6576132d6613275565b5060051b60200190565b600082601f8301126132f157600080fd5b81356020613306613301836132bc565b61328b565b82815260059290921b8401810191818101908684111561332557600080fd5b8286015b848110156133405780358352918301918301613329565b509695505050505050565b60006020828403121561335d57600080fd5b813567ffffffffffffffff81111561337457600080fd5b612822848285016132e0565b6000602080838503121561339357600080fd5b823567ffffffffffffffff8111156133aa57600080fd5b8301601f810185136133bb57600080fd5b80356133c9613301826132bc565b81815260059190911b820183019083810190878311156133e857600080fd5b928401925b8284101561340d576133fe84613155565b825292840192908401906133ed565b979650505050505050565b60008060006060848603121561342d57600080fd5b61343684613155565b925061344460208501613155565b9150604084013590509250925092565b6000806040838503121561346757600080fd5b50508035926020909101359150565b600067ffffffffffffffff83111561349057613490613275565b6134a3601f8401601f191660200161328b565b90508281528383830111156134b757600080fd5b828260208301376000602084830101529392505050565b6000602082840312156134e057600080fd5b813567ffffffffffffffff8111156134f757600080fd5b8201601f8101841361350857600080fd5b61282284823560208401613476565b6000806040838503121561352a57600080fd5b823567ffffffffffffffff81111561354157600080fd5b61354d858286016132e0565b92505061355c60208401613155565b90509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561359d57835183529284019291840191600101613581565b50909695505050505050565b602080825282518282018190526000919060409081850190868401855b828110156135eb578151805185528601518685015292840192908501906001016135c6565b5091979650505050505050565b80151581146118b857600080fd5b6000806040838503121561361957600080fd5b61362283613155565b915060208301356131a9816135f8565b6000806000806080858703121561364857600080fd5b61365185613155565b935061365f60208601613155565b925060408501359150606085013567ffffffffffffffff81111561368257600080fd5b8501601f8101871361369357600080fd5b6136a287823560208401613476565b91505092959194509250565b600080604083850312156136c157600080fd5b8235915061355c60208401613155565b600080604083850312156136e457600080fd5b6136ed83613155565b915061355c60208401613155565b600181811c9082168061370f57607f821691505b60208210810361372f57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610b1c57610b1c61374b565b6000600182016137865761378661374b565b5060010190565b60006020828403121561379f57600080fd5b815161314e816135f8565b8082028115828204841417610b1c57610b1c61374b565b634e487b7160e01b600052601260045260246000fd5b6000826137e6576137e66137c1565b500490565b601f821115610d0657600081815260208120601f850160051c810160208610156138125750805b601f850160051c820191505b818110156138315782815560010161381e565b505050505050565b815167ffffffffffffffff81111561385357613853613275565b6138678161386184546136fb565b846137eb565b602080601f83116001811461389c57600084156138845750858301515b600019600386901b1c1916600185901b178555613831565b600085815260208120601f198616915b828110156138cb578886015182559484019460019091019084016138ac565b50858210156138e95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b81810381811115610b1c57610b1c61374b565b600080845461391a816136fb565b60018281168015613932576001811461394757613976565b60ff1984168752821515830287019450613976565b8860005260208060002060005b8581101561396d5781548a820152908401908201613954565b50505082870194505b50505050835161398a8183602088016131cf565b64173539b7b760d91b9101908152600501949350505050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6000826139ff576139ff6137c1565b500690565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613ace908301846131f3565b9695505050505050565b600060208284031215613aea57600080fd5b815161314e8161311b565b634e487b7160e01b600052603160045260246000fdfea26469706673582212206840ac3a4ede9365ff4180f3c8e8e83b90c00cf7dace48724788e6aa9b8eb3e264736f6c634300081100330000000000000000000000000000000000000000000000000000000000000040000000000000000000000000ebfd19a9dc91367ff4040b008fa03982541a9fd1000000000000000000000000000000000000000000000000000000000000004468747470733a2f2f697066732e696f2f697066732f516d66487238616d45597a686e536a5956466258715a314770726e36554c7a31374a5354316e374462484e6b58772f00000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106103815760003560e01c806370a08231116101d1578063a0712d6811610102578063d0520c23116100a0578063e9d595751161006f578063e9d5957514610a9b578063ea09e56614610ab1578063f2fde38b14610ad1578063fa10197714610af157600080fd5b8063d0520c23146109d1578063d74edb5e14610a34578063db4f6d3114610a4a578063e985e9c514610a5257600080fd5b8063b88d4fde116100dc578063b88d4fde14610951578063beb08ab914610971578063bfa457bc14610991578063c87b56dd146109b157600080fd5b8063a0712d68146108fe578063a22cb46514610911578063aa0c4a6b1461093157600080fd5b806386fd96941161016f57806390967a521161014957806390967a521461089d57806391b7f5ed146108b357806395d89b41146108d3578063a035b1fe146108e857600080fd5b806386fd9694146108325780638a7804471461085f5780638da5cb5b1461087f57600080fd5b806375935d11116101ab57806375935d11146107c75780637c928fe9146107f4578063853828b61461080757806386d026081461081c57600080fd5b806370a082311461077c578063715018a61461079c5780637501f741146107b157600080fd5b80632a55205a116102b65780634f6ccce71161025457806359d7bc4d1161022357806359d7bc4d146107165780635c975abb1461072c5780635fd1bbc4146107465780636352211e1461075c57600080fd5b80634f6ccce71461068857806352e43e83146106a8578063547520fe146106e1578063547eafd01461070157600080fd5b806332cb6b0c1161029057806332cb6b0c146106125780633cd972ac1461062857806342842e0e1461064857806346b370941461066857600080fd5b80632a55205a146105935780632f745c59146105d257806330176e13146105f257600080fd5b806313ece816116103235780632098a1b5116102fd5780632098a1b5146105135780632142aa2c1461053357806323b872dd146105535780632617dd4d1461057357600080fd5b806313ece816146104b057806314556a56146104d057806318160ddd146104fe57600080fd5b806306fdde031161035f57806306fdde0314610416578063081812fc14610438578063095ea7b3146104705780630b5f4bfd1461049057600080fd5b806301ffc9a71461038657806304634d8d146103bb57806305a3b809146103dd575b600080fd5b34801561039257600080fd5b506103a66103a1366004613131565b610b11565b60405190151581526020015b60405180910390f35b3480156103c757600080fd5b506103db6103d6366004613171565b610b22565b005b3480156103e957600080fd5b506103a66103f83660046131b4565b6001600160a01b031660009081526013602052604090205460ff1690565b34801561042257600080fd5b5061042b610b38565b6040516103b2919061321f565b34801561044457600080fd5b50610458610453366004613232565b610bca565b6040516001600160a01b0390911681526020016103b2565b34801561047c57600080fd5b506103db61048b36600461324b565b610bf1565b34801561049c57600080fd5b506103db6104ab366004613232565b610d0b565b3480156104bc57600080fd5b506103db6104cb36600461334b565b610d18565b3480156104dc57600080fd5b506104f06104eb3660046131b4565b610dfc565b6040519081526020016103b2565b34801561050a57600080fd5b506009546104f0565b34801561051f57600080fd5b506103db61052e366004613380565b610e56565b34801561053f57600080fd5b506104f061054e3660046131b4565b610ee9565b34801561055f57600080fd5b506103db61056e366004613418565b610f19565b34801561057f57600080fd5b506103db61058e366004613380565b610fcd565b34801561059f57600080fd5b506105b36105ae366004613454565b611060565b604080516001600160a01b0390931683526020830191909152016103b2565b3480156105de57600080fd5b506104f06105ed36600461324b565b61110c565b3480156105fe57600080fd5b506103db61060d3660046134ce565b6111a2565b34801561061e57600080fd5b506104f06108ae81565b34801561063457600080fd5b506104f0610643366004613232565b6111b6565b34801561065457600080fd5b506103db610663366004613418565b6111dc565b34801561067457600080fd5b506103db610683366004613517565b611290565b34801561069457600080fd5b506104f06106a3366004613232565b611385565b3480156106b457600080fd5b506103a66106c33660046131b4565b6001600160a01b031660009081526012602052604090205460ff1690565b3480156106ed57600080fd5b506103db6106fc366004613232565b611418565b34801561070d57600080fd5b506103db611425565b34801561072257600080fd5b506104f060105481565b34801561073857600080fd5b50600f546103a69060ff1681565b34801561075257600080fd5b506104f060115481565b34801561076857600080fd5b50610458610777366004613232565b6114d8565b34801561078857600080fd5b506104f06107973660046131b4565b611538565b3480156107a857600080fd5b506103db6115be565b3480156107bd57600080fd5b506104f060155481565b3480156107d357600080fd5b506107e76107e23660046131b4565b6115d2565b6040516103b29190613565565b6103db610802366004613232565b611674565b34801561081357600080fd5b506103db6118bb565b34801561082857600080fd5b506104f0601a5481565b34801561083e57600080fd5b5061085261084d3660046131b4565b611959565b6040516103b291906135a9565b34801561086b57600080fd5b506103db61087a3660046131b4565b611a4c565b34801561088b57600080fd5b506000546001600160a01b0316610458565b3480156108a957600080fd5b506104f060175481565b3480156108bf57600080fd5b506103db6108ce366004613232565b611a76565b3480156108df57600080fd5b5061042b611a83565b3480156108f457600080fd5b506104f060165481565b6103db61090c366004613232565b611a92565b34801561091d57600080fd5b506103db61092c366004613606565b611c42565b34801561093d57600080fd5b506104f061094c3660046131b4565b611c4d565b34801561095d57600080fd5b506103db61096c366004613632565b611c7d565b34801561097d57600080fd5b50601d54610458906001600160a01b031681565b34801561099d57600080fd5b506103db6109ac3660046136ae565b611d38565b3480156109bd57600080fd5b5061042b6109cc366004613232565b611dfc565b3480156109dd57600080fd5b506109e6611eb0565b6040516103b29190600060c0820190508251151582526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b348015610a4057600080fd5b506104f060195481565b6103db611f35565b348015610a5e57600080fd5b506103a6610a6d3660046136d1565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b348015610aa757600080fd5b506104f060185481565b348015610abd57600080fd5b506103db610acc366004613232565b611f3e565b348015610add57600080fd5b506103db610aec3660046131b4565b611f4b565b348015610afd57600080fd5b506103db610b0c366004613454565b611fc1565b6000610b1c82611fd4565b92915050565b610b2a611ff9565b610b348282612053565b5050565b606060018054610b47906136fb565b80601f0160208091040260200160405190810160405280929190818152602001828054610b73906136fb565b8015610bc05780601f10610b9557610100808354040283529160200191610bc0565b820191906000526020600020905b815481529060010190602001808311610ba357829003601f168201915b5050505050905090565b6000610bd582612150565b506000908152600560205260409020546001600160a01b031690565b6000610bfc826114d8565b9050806001600160a01b0316836001600160a01b031603610c6e5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610c8a5750610c8a8133610a6d565b610cfc5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610c65565b610d0683836121af565b505050565b610d13611ff9565b601955565b6000805b8251811015610d93576000838281518110610d3957610d39613735565b60200260200101519050610d4a3390565b6001600160a01b0316610d5c826114d8565b6001600160a01b031603610d8a57610d73816111b6565b601c546000838152601b6020526040902055909201915b50600101610d1c565b50604051339082156108fc029083906000818181858888f19350505050158015610dc1573d6000803e3d6000fd5b5060405181815233907f8fbbda19f4a70036f6f585dc4160142a8fa2a20ffb9393d23274f78de4e39888906020015b60405180910390a25050565b60008080610e0984611538565b905060005b81811015610e4d576000610e22868361110c565b9050610e2d816111b6565b610e379085613761565b9350508080610e4590613774565b915050610e0e565b50909392505050565b610e5e611ff9565b60005b8151811015610ebc57600160126000848481518110610e8257610e82613735565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101610e61565b506040517f0874ad8a4e51ef28f79a4bb4ad9897d3569a2afe601fdf6b116f0966701bcc1290600090a150565b6001600160a01b03811660009081526013602052604081205460ff16610f1157601654610b1c565b505060175490565b6daaeb6d7670e522a718067333cd4e3b15610fc257604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c6171134906044016020604051808303816000875af1158015610f7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa3919061378d565b610fc257604051633b79c77360e21b8152336004820152602401610c65565b610d0683838361221d565b610fd5611ff9565b60005b815181101561103357600160136000848481518110610ff957610ff9613735565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101610fd8565b506040517fac4285832aea1fb9e403127173fc92934a4267438dac67c9e366c1640b56bd8690600090a150565b6000828152600d602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b03169282019290925282916110d5575060408051808201909152600c546001600160a01b0381168252600160a01b90046001600160601b031660208201525b6020810151600090612710906110f4906001600160601b0316876137aa565b6110fe91906137d7565b915196919550909350505050565b600061111783611538565b82106111795760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610c65565b506001600160a01b03919091166000908152600760209081526040808320938352929052205490565b6111aa611ff9565b600e610b348282613839565b6000818152601b6020526040812054601c546111d291906138f9565b610b1c9082613761565b6daaeb6d7670e522a718067333cd4e3b1561128557604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c6171134906044016020604051808303816000875af1158015611242573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611266919061378d565b61128557604051633b79c77360e21b8152336004820152602401610c65565b610d0683838361224e565b611298611ff9565b6112a0612269565b60006112ab60095490565b90506108ae8351826112bd9190613761565b11156112dc57604051633bd7ad7760e21b815260040160405180910390fd5b60005b83518110156113345760008482815181106112fc576112fc613735565b6020026020010151905061130f816122c2565b6113198482612362565b601c546000918252601b6020526040909120556001016112df565b508251604080518381526020810192909252429082015233907f5a3358a3d27a5373c0df2604662088d37894d56b7cfd27f315770440f4e0d9199060600160405180910390a250610b346001600b55565b600061139060095490565b82106113f35760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610c65565b6009828154811061140657611406613735565b90600052602060002001549050919050565b611420611ff9565b601555565b60008061143133611538565b905060005b8181101561147757600061144a338361110c565b9050611455816111b6565b601c546000928352601b60205260409092209190915590920191600101611436565b50604051339083156108fc029084906000818181858888f193505050501580156114a5573d6000803e3d6000fd5b5060405182815233907f8fbbda19f4a70036f6f585dc4160142a8fa2a20ffb9393d23274f78de4e3988890602001610df0565b6000818152600360205260408120546001600160a01b031680610b1c5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c65565b60006001600160a01b0382166115a25760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610c65565b506001600160a01b031660009081526004602052604090205490565b6115c6611ff9565b6115d0600061237c565b565b606060006115df83611538565b905060008167ffffffffffffffff8111156115fc576115fc613275565b604051908082528060200260200182016040528015611625578160200160208202803683370190505b50905060005b8281101561166c5761163d858261110c565b82828151811061164f5761164f613735565b60209081029190910101528061166481613774565b91505061162b565b509392505050565b61167c612269565b600f5460ff16156116a057604051634c97d28b60e01b815260040160405180910390fd5b6116a9336106c3565b1580156116b7575060115442105b156116d55760405163951b974f60e01b815260040160405180910390fd5b6010544210156116f85760405163951b974f60e01b815260040160405180910390fd5b60155481111561171b5760405163ec8e6a6360e01b815260040160405180910390fd5b8060000361173c57604051632a6ce29960e11b815260040160405180910390fd5b60008161174833611c4d565b61175291906137aa565b9050600061175f60095490565b90506108ae61176e8483613761565b111561178d57604051633bd7ad7760e21b815260040160405180910390fd5b600061179833611538565b11156117b75760405163038e1a9f60e41b815260040160405180910390fd5b8134146117d75760405163cd1c886760e01b815260040160405180910390fd5b600080821180156117ea57506000601954115b15611814576064601954346117ff91906137aa565b61180991906137d7565b9050611814816123cc565b60015b848111611850576000611828612424565b9050611835335b82612362565b601c546000918252601b602052604090912055600101611817565b50600061185d82856138f9565b90506118688161255b565b60408051848152602081018790524281830152905133917f5a3358a3d27a5373c0df2604662088d37894d56b7cfd27f315770440f4e0d919919081900360600190a2505050506118b86001600b55565b50565b6118c3611ff9565b600080546040516001600160a01b039091169047908381818185875af1925050503d8060008114611910576040519150601f19603f3d011682016040523d82523d6000602084013e611915565b606091505b50509050806118b85760405162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b6044820152606401610c65565b6060600061196683611538565b905060008167ffffffffffffffff81111561198357611983613275565b6040519080825280602002602001820160405280156119c857816020015b60408051808201909152600080825260208201528152602001906001900390816119a15790505b50905060005b8281101561166c5760006119e2868361110c565b905060006119ef826111b6565b905081848481518110611a0457611a04613735565b6020026020010151600001818152505080848481518110611a2757611a27613735565b6020026020010151602001818152505050508080611a4490613774565b9150506119ce565b611a54611ff9565b601d80546001600160a01b0319166001600160a01b0392909216919091179055565b611a7e611ff9565b601655565b606060028054610b47906136fb565b611a9a612269565b600f5460ff1615611abe57604051634c97d28b60e01b815260040160405180910390fd5b611ac7336103f8565b158015611ad5575060115442105b15611af35760405163951b974f60e01b815260040160405180910390fd5b601054421015611b165760405163951b974f60e01b815260040160405180910390fd5b601554811115611b395760405163ec8e6a6360e01b815260040160405180910390fd5b80600003611b5a57604051632a6ce29960e11b815260040160405180910390fd5b600081611b6633610ee9565b611b7091906137aa565b90506000611b7d60095490565b90506108ae611b8c8483613761565b1115611bab57604051633bd7ad7760e21b815260040160405180910390fd5b813414611bcb5760405163cd1c886760e01b815260040160405180910390fd5b60008082118015611bde57506000601954115b15611c0857606460195434611bf391906137aa565b611bfd91906137d7565b9050611c08816123cc565b60015b848111611850576000611c1c612424565b9050611c273361182f565b601c546000918252601b602052604090912055600101611c0b565b610b343383836125f3565b6001600160a01b03811660009081526012602052604081205460ff16611c7557601654610b1c565b505060185490565b6daaeb6d7670e522a718067333cd4e3b15611d2657604051633185c44d60e21b81523060048201523360248201526daaeb6d7670e522a718067333cd4e9063c6171134906044016020604051808303816000875af1158015611ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d07919061378d565b611d2657604051633b79c77360e21b8152336004820152602401610c65565b611d32848484846126c1565b50505050565b611d40611ff9565b6000611d4b60095490565b90506108ae611d5a8483613761565b1115611d7957604051633bd7ad7760e21b815260040160405180910390fd5b60015b838111611db4576000611d8d612424565b9050611d998482612362565b601c546000918252601b602052604090912055600101611d7c565b5060408051828152602081018590524281830152905133917f5a3358a3d27a5373c0df2604662088d37894d56b7cfd27f315770440f4e0d919919081900360600190a2505050565b6000818152600360205260409020546060906001600160a01b0316611e7b5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610c65565b6000600e611e88846126f3565b604051602001611e9992919061390c565b60408051601f198184030181529190529392505050565b611eeb6040518060c0016040528060001515815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805160c08101909152600f5460ff161515815260208101611f0d60095490565b81526020016108ae815260200160155481526020016011548152602001601054815250905090565b6115d0346123cc565b611f46611ff9565b601755565b611f53611ff9565b6001600160a01b038116611fb85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c65565b6118b88161237c565b611fc9611ff9565b601091909155601155565b60006001600160e01b0319821663152a902d60e11b1480610b1c5750610b1c82612786565b6000546001600160a01b031633146115d05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c65565b6127106001600160601b03821611156120c15760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b6064820152608401610c65565b6001600160a01b0382166121175760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610c65565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600c55565b6000818152600360205260409020546001600160a01b03166118b85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610c65565b600081815260056020526040902080546001600160a01b0319166001600160a01b03841690811790915581906121e4826114d8565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b61222733826127ab565b6122435760405162461bcd60e51b8152600401610c65906139a3565b610d0683838361282a565b610d0683838360405180602001604052806000815250611c7d565b6002600b54036122bb5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c65565b6002600b55565b60006122cf6001836138f9565b905060006122dc60095490565b6122e8906108ae6138f9565b9050601460006122f96001846138f9565b81526020019081526020016000205460000361232e5761231a6001826138f9565b600083815260146020526040902055505050565b6014600061233d6001846138f9565b8152602080820192909252604090810160009081205485825260149093522055505050565b610b3482826040518060200160405280600081525061299b565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b806000036123ed5760405163e3a12f6760e01b815260040160405180910390fd5b80601a546123fb9190613761565b601a5560095461240b90826137d7565b601c600082825461241c9190613761565b909155505050565b60008061243060095490565b61243c906108ae6138f9565b6040516bffffffffffffffffffffffff1933606090811b8216602084015241901b166034820152446048820152456068820152426088820152909150600090829060a8016040516020818303038152906040528051906020012060001c6124a391906139f0565b6000818152601460205260408120549192509081036124c35750806124d4565b506000818152601460205260409020545b601460006124e36001866138f9565b815260200190815260200160002054600003612518576125046001846138f9565b600083815260146020526040902055612548565b601460006125276001866138f9565b81526020808201929092526040908101600090812054858252601490935220555b612553816001613761565b935050505090565b601d546040516000916001600160a01b03169061c35090849084818181858888f193505050503d80600081146125ad576040519150601f19603f3d011682016040523d82523d6000602084013e6125b2565b606091505b5050905080610b345760405162461bcd60e51b815260206004820152600d60248201526c10d85b9b9bdd081c185e5bdd5d609a1b6044820152606401610c65565b816001600160a01b0316836001600160a01b0316036126545760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c65565b6001600160a01b03838116600081815260066020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6126cb33836127ab565b6126e75760405162461bcd60e51b8152600401610c65906139a3565b611d32848484846129ce565b6060600061270083612a01565b600101905060008167ffffffffffffffff81111561272057612720613275565b6040519080825280601f01601f19166020018201604052801561274a576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461275457509392505050565b60006001600160e01b0319821663780e9d6360e01b1480610b1c5750610b1c82612ad9565b6000806127b7836114d8565b9050806001600160a01b0316846001600160a01b031614806127fe57506001600160a01b0380821660009081526006602090815260408083209388168352929052205460ff165b806128225750836001600160a01b031661281784610bca565b6001600160a01b0316145b949350505050565b826001600160a01b031661283d826114d8565b6001600160a01b0316146128635760405162461bcd60e51b8152600401610c6590613a04565b6001600160a01b0382166128c55760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610c65565b6128d28383836001612b29565b826001600160a01b03166128e5826114d8565b6001600160a01b03161461290b5760405162461bcd60e51b8152600401610c6590613a04565b600081815260056020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260048552838620805460001901905590871680865283862080546001019055868652600390945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6129a58383612c69565b6129b26000848484612e02565b610d065760405162461bcd60e51b8152600401610c6590613a49565b6129d984848461282a565b6129e584848484612e02565b611d325760405162461bcd60e51b8152600401610c6590613a49565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8310612a405772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612a6c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc100008310612a8a57662386f26fc10000830492506010015b6305f5e1008310612aa2576305f5e100830492506008015b6127108310612ab657612710830492506004015b60648310612ac8576064830492506002015b600a8310610b1c5760010192915050565b60006001600160e01b031982166380ac58cd60e01b1480612b0a57506001600160e01b03198216635b5e139f60e01b145b80610b1c57506301ffc9a760e01b6001600160e01b0319831614610b1c565b612b3584848484612f03565b6001811115612ba45760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b6064820152608401610c65565b816001600160a01b038516612c0057612bfb81600980546000838152600a60205260408120829055600182018355919091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0155565b612c23565b836001600160a01b0316856001600160a01b031614612c2357612c238582612f8b565b6001600160a01b038416612c3f57612c3a81613028565b612c62565b846001600160a01b0316846001600160a01b031614612c6257612c6284826130d7565b5050505050565b6001600160a01b038216612cbf5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c65565b6000818152600360205260409020546001600160a01b031615612d245760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c65565b612d32600083836001612b29565b6000818152600360205260409020546001600160a01b031615612d975760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c65565b6001600160a01b038216600081815260046020908152604080832080546001019055848352600390915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001600160a01b0384163b15612ef857604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612e46903390899088908890600401613a9b565b6020604051808303816000875af1925050508015612e81575060408051601f3d908101601f19168201909252612e7e91810190613ad8565b60015b612ede573d808015612eaf576040519150601f19603f3d011682016040523d82523d6000602084013e612eb4565b606091505b508051600003612ed65760405162461bcd60e51b8152600401610c6590613a49565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612822565b506001949350505050565b6001811115611d32576001600160a01b03841615612f49576001600160a01b03841660009081526004602052604081208054839290612f439084906138f9565b90915550505b6001600160a01b03831615611d32576001600160a01b03831660009081526004602052604081208054839290612f80908490613761565b909155505050505050565b60006001612f9884611538565b612fa291906138f9565b600083815260086020526040902054909150808214612ff5576001600160a01b03841660009081526007602090815260408083208584528252808320548484528184208190558352600890915290208190555b5060009182526008602090815260408084208490556001600160a01b039094168352600781528383209183525290812055565b60095460009061303a906001906138f9565b6000838152600a60205260408120546009805493945090928490811061306257613062613735565b90600052602060002001549050806009838154811061308357613083613735565b6000918252602080832090910192909255828152600a909152604080822084905585825281205560098054806130bb576130bb613af5565b6001900381819060005260206000200160009055905550505050565b60006130e283611538565b6001600160a01b039093166000908152600760209081526040808320868452825280832085905593825260089052919091209190915550565b6001600160e01b0319811681146118b857600080fd5b60006020828403121561314357600080fd5b813561314e8161311b565b9392505050565b80356001600160a01b038116811461316c57600080fd5b919050565b6000806040838503121561318457600080fd5b61318d83613155565b915060208301356001600160601b03811681146131a957600080fd5b809150509250929050565b6000602082840312156131c657600080fd5b61314e82613155565b60005b838110156131ea5781810151838201526020016131d2565b50506000910152565b6000815180845261320b8160208601602086016131cf565b601f01601f19169290920160200192915050565b60208152600061314e60208301846131f3565b60006020828403121561324457600080fd5b5035919050565b6000806040838503121561325e57600080fd5b61326783613155565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156132b4576132b4613275565b604052919050565b600067ffffffffffffffff8211156132d6576132d6613275565b5060051b60200190565b600082601f8301126132f157600080fd5b81356020613306613301836132bc565b61328b565b82815260059290921b8401810191818101908684111561332557600080fd5b8286015b848110156133405780358352918301918301613329565b509695505050505050565b60006020828403121561335d57600080fd5b813567ffffffffffffffff81111561337457600080fd5b612822848285016132e0565b6000602080838503121561339357600080fd5b823567ffffffffffffffff8111156133aa57600080fd5b8301601f810185136133bb57600080fd5b80356133c9613301826132bc565b81815260059190911b820183019083810190878311156133e857600080fd5b928401925b8284101561340d576133fe84613155565b825292840192908401906133ed565b979650505050505050565b60008060006060848603121561342d57600080fd5b61343684613155565b925061344460208501613155565b9150604084013590509250925092565b6000806040838503121561346757600080fd5b50508035926020909101359150565b600067ffffffffffffffff83111561349057613490613275565b6134a3601f8401601f191660200161328b565b90508281528383830111156134b757600080fd5b828260208301376000602084830101529392505050565b6000602082840312156134e057600080fd5b813567ffffffffffffffff8111156134f757600080fd5b8201601f8101841361350857600080fd5b61282284823560208401613476565b6000806040838503121561352a57600080fd5b823567ffffffffffffffff81111561354157600080fd5b61354d858286016132e0565b92505061355c60208401613155565b90509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561359d57835183529284019291840191600101613581565b50909695505050505050565b602080825282518282018190526000919060409081850190868401855b828110156135eb578151805185528601518685015292840192908501906001016135c6565b5091979650505050505050565b80151581146118b857600080fd5b6000806040838503121561361957600080fd5b61362283613155565b915060208301356131a9816135f8565b6000806000806080858703121561364857600080fd5b61365185613155565b935061365f60208601613155565b925060408501359150606085013567ffffffffffffffff81111561368257600080fd5b8501601f8101871361369357600080fd5b6136a287823560208401613476565b91505092959194509250565b600080604083850312156136c157600080fd5b8235915061355c60208401613155565b600080604083850312156136e457600080fd5b6136ed83613155565b915061355c60208401613155565b600181811c9082168061370f57607f821691505b60208210810361372f57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610b1c57610b1c61374b565b6000600182016137865761378661374b565b5060010190565b60006020828403121561379f57600080fd5b815161314e816135f8565b8082028115828204841417610b1c57610b1c61374b565b634e487b7160e01b600052601260045260246000fd5b6000826137e6576137e66137c1565b500490565b601f821115610d0657600081815260208120601f850160051c810160208610156138125750805b601f850160051c820191505b818110156138315782815560010161381e565b505050505050565b815167ffffffffffffffff81111561385357613853613275565b6138678161386184546136fb565b846137eb565b602080601f83116001811461389c57600084156138845750858301515b600019600386901b1c1916600185901b178555613831565b600085815260208120601f198616915b828110156138cb578886015182559484019460019091019084016138ac565b50858210156138e95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b81810381811115610b1c57610b1c61374b565b600080845461391a816136fb565b60018281168015613932576001811461394757613976565b60ff1984168752821515830287019450613976565b8860005260208060002060005b8581101561396d5781548a820152908401908201613954565b50505082870194505b50505050835161398a8183602088016131cf565b64173539b7b760d91b9101908152600501949350505050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6000826139ff576139ff6137c1565b500690565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613ace908301846131f3565b9695505050505050565b600060208284031215613aea57600080fd5b815161314e8161311b565b634e487b7160e01b600052603160045260246000fdfea26469706673582212206840ac3a4ede9365ff4180f3c8e8e83b90c00cf7dace48724788e6aa9b8eb3e264736f6c63430008110033

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

0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000ebfd19a9dc91367ff4040b008fa03982541a9fd1000000000000000000000000000000000000000000000000000000000000004468747470733a2f2f697066732e696f2f697066732f516d66487238616d45597a686e536a5956466258715a314770726e36554c7a31374a5354316e374462484e6b58772f00000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : uri_ (string): https://ipfs.io/ipfs/QmfHr8amEYzhnSjYVFbXqZ1Gprn6ULz17JST1n7DbHNkXw/
Arg [1] : projectWallet_ (address): 0xEbfD19a9dc91367fF4040B008fa03982541a9fD1

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 000000000000000000000000ebfd19a9dc91367ff4040b008fa03982541a9fd1
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000044
Arg [3] : 68747470733a2f2f697066732e696f2f697066732f516d66487238616d45597a
Arg [4] : 686e536a5956466258715a314770726e36554c7a31374a5354316e374462484e
Arg [5] : 6b58772f00000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

91901:14832:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106517:213;;;;;;;;;;-1:-1:-1;106517:213:0;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;106517:213:0;;;;;;;;94242:167;;;;;;;;;;-1:-1:-1;94242:167:0;;;;;:::i;:::-;;:::i;:::-;;103495:113;;;;;;;;;;-1:-1:-1;103495:113:0;;;;;:::i;:::-;-1:-1:-1;;;;;103581:19:0;103557:4;103581:19;;;:9;:19;;;;;;;;;103495:113;66197:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;67806:221::-;;;;;;;;;;-1:-1:-1;67806:221:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;2437:32:1;;;2419:51;;2407:2;2392:18;67806:221:0;2273:203:1;67324:416:0;;;;;;;;;;-1:-1:-1;67324:416:0;;;;;:::i;:::-;;:::i;95934:118::-;;;;;;;;;;-1:-1:-1;95934:118:0;;;;;:::i;:::-;;:::i;105710:600::-;;;;;;;;;;-1:-1:-1;105710:600:0;;;;;:::i;:::-;;:::i;104260:350::-;;;;;;;;;;-1:-1:-1;104260:350:0;;;;;:::i;:::-;;:::i;:::-;;;4506:25:1;;;4494:2;4479:18;104260:350:0;4360:177:1;83594:113:0;;;;;;;;;;-1:-1:-1;83682:10:0;:17;83594:113;;94714:280;;;;;;;;;;-1:-1:-1;94714:280:0;;;;;:::i;:::-;;:::i;103616:141::-;;;;;;;;;;-1:-1:-1;103616:141:0;;;;;:::i;:::-;;:::i;95002:208::-;;;;;;;;;;-1:-1:-1;95002:208:0;;;;;:::i;:::-;;:::i;94417:289::-;;;;;;;;;;-1:-1:-1;94417:289:0;;;;;:::i;:::-;;:::i;23190:505::-;;;;;;;;;;-1:-1:-1;23190:505:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;6222:32:1;;;6204:51;;6286:2;6271:18;;6264:34;;;;6177:18;23190:505:0;6030:274:1;83175:343:0;;;;;;;;;;-1:-1:-1;83175:343:0;;;;;:::i;:::-;;:::i;94136:98::-;;;;;;;;;;-1:-1:-1;94136:98:0;;;;;:::i;:::-;;:::i;93403:41::-;;;;;;;;;;;;93440:4;93403:41;;104108:144;;;;;;;;;;-1:-1:-1;104108:144:0;;;;;:::i;:::-;;:::i;95218:216::-;;;;;;;;;;-1:-1:-1;95218:216:0;;;;;:::i;:::-;;:::i;96409:716::-;;;;;;;;;;-1:-1:-1;96409:716:0;;;;;:::i;:::-;;:::i;83784:320::-;;;;;;;;;;-1:-1:-1;83784:320:0;;;;;:::i;:::-;;:::i;103233:107::-;;;;;;;;;;-1:-1:-1;103233:107:0;;;;;:::i;:::-;-1:-1:-1;;;;;103316:16:0;103292:4;103316:16;;;:6;:16;;;;;;;;;103233:107;96060:94;;;;;;;;;;-1:-1:-1;96060:94:0;;;;;:::i;:::-;;:::i;105164:538::-;;;;;;;;;;;;;:::i;92109:46::-;;;;;;;;;;;;;;;;92082:18;;;;;;;;;;-1:-1:-1;92082:18:0;;;;;;;;92162:43;;;;;;;;;;;;;;;;65857:273;;;;;;;;;;-1:-1:-1;65857:273:0;;;;;:::i;:::-;;:::i;65501:294::-;;;;;;;;;;-1:-1:-1;65501:294:0;;;;;:::i;:::-;;:::i;90896:103::-;;;;;;;;;;;;;:::i;92368:27::-;;;;;;;;;;;;;;;;101781:399;;;;;;;;;;-1:-1:-1;101781:399:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;97910:1361::-;;;;;;:::i;:::-;;:::i;106318:173::-;;;;;;;;;;;;;:::i;92593:33::-;;;;;;;;;;;;;;;;104618:524;;;;;;;;;;-1:-1:-1;104618:524:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;94012:116::-;;;;;;;;;;-1:-1:-1;94012:116:0;;;;;:::i;:::-;;:::i;90248:87::-;;;;;;;;;;-1:-1:-1;90294:7:0;90321:6;-1:-1:-1;;;;;90321:6:0;90248:87;;92442:42;;;;;;;;;;;;;;;;96162:86;;;;;;;;;;-1:-1:-1;96162:86:0;;;;;:::i;:::-;;:::i;66366:104::-;;;;;;;;;;;;;:::i;92402:33::-;;;;;;;;;;;;;;;;99279:1287;;;;;;:::i;:::-;;:::i;68099:187::-;;;;;;;;;;-1:-1:-1;68099:187:0;;;;;:::i;:::-;;:::i;103348:139::-;;;;;;;;;;-1:-1:-1;103348:139:0;;;;;:::i;:::-;;:::i;95442:250::-;;;;;;;;;;-1:-1:-1;95442:250:0;;;;;:::i;:::-;;:::i;92752:28::-;;;;;;;;;;-1:-1:-1;92752:28:0;;;;-1:-1:-1;;;;;92752:28:0;;;97133:541;;;;;;;;;;-1:-1:-1;97133:541:0;;;;;:::i;:::-;;:::i;102326:437::-;;;;;;;;;;-1:-1:-1;102326:437:0;;;;;:::i;:::-;;:::i;102787:308::-;;;;;;;;;;;;;:::i;:::-;;;;;;10556:4:1;10598:3;10587:9;10583:19;10575:27;;10649:6;10643:13;10636:21;10629:29;10618:9;10611:48;10715:4;10707:6;10703:17;10697:24;10690:4;10679:9;10675:20;10668:54;10778:4;10770:6;10766:17;10760:24;10753:4;10742:9;10738:20;10731:54;10841:4;10833:6;10829:17;10823:24;10816:4;10805:9;10801:20;10794:54;10904:4;10896:6;10892:17;10886:24;10879:4;10868:9;10864:20;10857:54;10967:4;10959:6;10955:17;10949:24;10942:4;10931:9;10927:20;10920:54;10412:568;;;;;92554:32:0;;;;;;;;;;;;;;;;103783:82;;;:::i;68357:214::-;;;;;;;;;;-1:-1:-1;68357:214:0;;;;;:::i;:::-;-1:-1:-1;;;;;68528:25:0;;;68499:4;68528:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;68357:214;92491:36;;;;;;;;;;;;;;;;96256:122;;;;;;;;;;-1:-1:-1;96256:122:0;;;;;:::i;:::-;;:::i;91154:238::-;;;;;;;;;;-1:-1:-1;91154:238:0;;;;;:::i;:::-;;:::i;95700:226::-;;;;;;;;;;-1:-1:-1;95700:226:0;;;;;:::i;:::-;;:::i;106517:213::-;106657:4;106686:36;106710:11;106686:23;:36::i;:::-;106679:43;106517:213;-1:-1:-1;;106517:213:0:o;94242:167::-;90134:13;:11;:13::i;:::-;94359:42:::1;94378:8;94388:12;94359:18;:42::i;:::-;94242:167:::0;;:::o;66197:100::-;66251:13;66284:5;66277:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66197:100;:::o;67806:221::-;67927:7;67952:23;67967:7;67952:14;:23::i;:::-;-1:-1:-1;67995:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;67995:24:0;;67806:221::o;67324:416::-;67405:13;67421:23;67436:7;67421:14;:23::i;:::-;67405:39;;67469:5;-1:-1:-1;;;;;67463:11:0;:2;-1:-1:-1;;;;;67463:11:0;;67455:57;;;;-1:-1:-1;;;67455:57:0;;11837:2:1;67455:57:0;;;11819:21:1;11876:2;11856:18;;;11849:30;11915:34;11895:18;;;11888:62;-1:-1:-1;;;11966:18:1;;;11959:31;12007:19;;67455:57:0;;;;;;;;;63557:10;-1:-1:-1;;;;;67547:21:0;;;;:62;;-1:-1:-1;67572:37:0;67589:5;63557:10;68357:214;:::i;67572:37::-;67525:173;;;;-1:-1:-1;;;67525:173:0;;12239:2:1;67525:173:0;;;12221:21:1;12278:2;12258:18;;;12251:30;12317:34;12297:18;;;12290:62;12388:31;12368:18;;;12361:59;12437:19;;67525:173:0;12037:425:1;67525:173:0;67711:21;67720:2;67724:7;67711:8;:21::i;:::-;67394:346;67324:416;;:::o;95934:118::-;90134:13;:11;:13::i;:::-;96014::::1;:30:::0;95934:118::o;105710:600::-;105786:15;105823:9;105818:378;105842:13;:20;105838:1;:24;105818:378;;;105910:15;105928:13;105942:1;105928:16;;;;;;;;:::i;:::-;;;;;;;105910:34;;105987:12;63557:10;;63477:98;105987:12;-1:-1:-1;;;;;105967:32:0;:16;105975:7;105967;:16::i;:::-;-1:-1:-1;;;;;105967:32:0;;105963:185;;106036:24;106052:7;106036:15;:24::i;:::-;106112:16;;106084:25;;;;:16;:25;;;;;:44;106024:37;;;;105963:185;-1:-1:-1;106166:3:0;;105818:378;;;-1:-1:-1;106208:39:0;;63557:10;;106208:39;;;;;106239:7;;106208:39;;;;106239:7;63557:10;106208:39;;;;;;;;;;;;;;;;;;;;-1:-1:-1;106263:39:0;;4506:25:1;;;63557:10:0;;106263:39;;4494:2:1;4479:18;106263:39:0;;;;;;;;105775:535;105710:600;:::o;104260:350::-;104321:7;;;104389:17;104399:6;104389:9;:17::i;:::-;104373:33;;104422:9;104417:161;104441:5;104437:1;:9;104417:161;;;104468:15;104486:30;104506:6;104514:1;104486:19;:30::i;:::-;104468:48;;104542:24;104558:7;104542:15;:24::i;:::-;104531:35;;;;:::i;:::-;;;104453:125;104448:3;;;;;:::i;:::-;;;;104417:161;;;-1:-1:-1;104595:7:0;;104260:350;-1:-1:-1;;;104260:350:0:o;94714:280::-;90134:13;:11;:13::i;:::-;94797:9:::1;94792:162;94816:10;:17;94812:1;:21;94792:162;;;94876:4;94852:6;:21;94859:10;94870:1;94859:13;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;;;94852:21:0::1;::::0;;;::::1;::::0;;;;;;-1:-1:-1;94852:21:0;:28;;-1:-1:-1;;94852:28:0::1;::::0;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;94924:3:0::1;94792:162;;;-1:-1:-1::0;94971:15:0::1;::::0;::::1;::::0;;;::::1;94714:280:::0;:::o;103616:141::-;-1:-1:-1;;;;;103581:19:0;;103674:7;103581:19;;;:9;:19;;;;;;;;103701:48;;103744:5;;103701:48;;;-1:-1:-1;;103727:14:0;;;103616:141::o;95002:208::-;16665:42;17927:43;:47;17923:318;;18014:128;;-1:-1:-1;;;18014:128:0;;18085:4;18014:128;;;13213:34:1;18113:10:0;13263:18:1;;;13256:43;16665:42:0;;18014:40;;13148:18:1;;18014:128:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17991:239;;18184:30;;-1:-1:-1;;;18184:30:0;;18203:10;18184:30;;;2419:51:1;2392:18;;18184:30:0;2273:203:1;17991:239:0;95165:37:::1;95184:4;95190:2;95194:7;95165:18;:37::i;94417:289::-:0;90134:13;:11;:13::i;:::-;94503:9:::1;94498:165;94522:10;:17;94518:1;:21;94498:165;;;94585:4;94558:9;:24;94568:10;94579:1;94568:13;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;;;-1:-1:-1;;;;;94558:24:0::1;::::0;;;::::1;::::0;;;;;;-1:-1:-1;94558:24:0;:31;;-1:-1:-1;;94558:31:0::1;::::0;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;94633:3:0::1;94498:165;;;-1:-1:-1::0;94680:18:0::1;::::0;::::1;::::0;;;::::1;94417:289:::0;:::o;23190:505::-;23332:7;23395:27;;;:17;:27;;;;;;;;23366:56;;;;;;;;;-1:-1:-1;;;;;23366:56:0;;;;;-1:-1:-1;;;23366:56:0;;;-1:-1:-1;;;;;23366:56:0;;;;;;;;23332:7;;23435:92;;-1:-1:-1;23486:29:0;;;;;;;;;23496:19;23486:29;-1:-1:-1;;;;;23486:29:0;;;;-1:-1:-1;;;23486:29:0;;-1:-1:-1;;;;;23486:29:0;;;;;23435:92;23577:23;;;;23539:21;;24061:5;;23564:36;;-1:-1:-1;;;;;23564:36:0;:10;:36;:::i;:::-;23563:71;;;;:::i;:::-;23655:16;;;;;-1:-1:-1;23190:505:0;;-1:-1:-1;;;;23190:505:0:o;83175:343::-;83317:7;83372:23;83389:5;83372:16;:23::i;:::-;83364:5;:31;83342:124;;;;-1:-1:-1;;;83342:124:0;;14192:2:1;83342:124:0;;;14174:21:1;14231:2;14211:18;;;14204:30;14270:34;14250:18;;;14243:62;-1:-1:-1;;;14321:18:1;;;14314:41;14372:19;;83342:124:0;13990:407:1;83342:124:0;-1:-1:-1;;;;;;83484:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;83175:343::o;94136:98::-;90134:13;:11;:13::i;:::-;94208:12:::1;:18;94223:3:::0;94208:12;:18:::1;:::i;104108:144::-:0;104166:15;104224:20;;;:16;:20;;;;;;104205:16;;:39;;104224:20;104205:39;:::i;:::-;104194:50;;;;:::i;95218:216::-;16665:42;17927:43;:47;17923:318;;18014:128;;-1:-1:-1;;;18014:128:0;;18085:4;18014:128;;;13213:34:1;18113:10:0;13263:18:1;;;13256:43;16665:42:0;;18014:40;;13148:18:1;;18014:128:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17991:239;;18184:30;;-1:-1:-1;;;18184:30:0;;18203:10;18184:30;;;2419:51:1;2392:18;;18184:30:0;2273:203:1;17991:239:0;95385:41:::1;95408:4;95414:2;95418:7;95385:22;:41::i;96409:716::-:0;90134:13;:11;:13::i;:::-;28190:21:::1;:19;:21::i;:::-;96547::::2;96571:13;83682:10:::0;:17;;83594:113;96571:13:::2;96547:37;;93440:4;96617:6;:13;96601;:29;;;;:::i;:::-;:42;96597:65;;;96652:10;;-1:-1:-1::0;;;96652:10:0::2;;;;;;;;;;;96597:65;96680:9;96675:295;96699:6;:13;96695:1;:17;96675:295;;;96731:15;96749:6;96756:1;96749:9;;;;;;;;:::i;:::-;;;;;;;96731:27;;96773:19;96784:7;96773:10;:19::i;:::-;96809:22;96819:2;96823:7;96809:9;:22::i;:::-;96905:16;::::0;96877:25:::2;::::0;;;:16:::2;:25;::::0;;;;;:44;96940:3:::2;;96675:295;;;-1:-1:-1::0;97063:13:0;;96987:130:::2;::::0;;16941:25:1;;;16997:2;16982:18;;16975:34;;;;97091:15:0::2;17025:18:1::0;;;17018:34;63557:10:0;;96987:130:::2;::::0;16929:2:1;16914:18;96987:130:0::2;;;;;;;96536:589;28234:20:::1;27628:1:::0;28754:7;:22;28571:213;83784:320;83904:7;83959:30;83682:10;:17;;83594:113;83959:30;83951:5;:38;83929:132;;;;-1:-1:-1;;;83929:132:0;;17265:2:1;83929:132:0;;;17247:21:1;17304:2;17284:18;;;17277:30;17343:34;17323:18;;;17316:62;-1:-1:-1;;;17394:18:1;;;17387:42;17446:19;;83929:132:0;17063:408:1;83929:132:0;84079:10;84090:5;84079:17;;;;;;;;:::i;:::-;;;;;;;;;84072:24;;83784:320;;;:::o;96060:94::-;90134:13;:11;:13::i;:::-;96128:7:::1;:18:::0;96060:94::o;105164:538::-;105213:15;;105261:23;63557:10;65501:294;:::i;105261:23::-;105245:39;;105300:9;105295:293;105319:5;105315:1;:9;105295:293;;;105343:15;105361:36;63557:10;105395:1;105361:19;:36::i;:::-;105343:54;;105452:24;105468:7;105452:15;:24::i;:::-;105523:16;;105495:25;;;;:16;:25;;;;;;:44;;;;105441:35;;;;105558:3;;105295:293;;;-1:-1:-1;105600:39:0;;63557:10;;105600:39;;;;;105631:7;;105600:39;;;;105631:7;63557:10;105600:39;;;;;;;;;;;;;;;;;;;;-1:-1:-1;105655:39:0;;4506:25:1;;;63557:10:0;;105655:39;;4494:2:1;4479:18;105655:39:0;4360:177:1;65857:273:0;65974:7;71134:16;;;:7;:16;;;;;;-1:-1:-1;;;;;71134:16:0;;66043:56;;;;-1:-1:-1;;;66043:56:0;;17678:2:1;66043:56:0;;;17660:21:1;17717:2;17697:18;;;17690:30;-1:-1:-1;;;17736:18:1;;;17729:54;17800:18;;66043:56:0;17476:348:1;65501:294:0;65618:7;-1:-1:-1;;;;;65665:19:0;;65643:110;;;;-1:-1:-1;;;65643:110:0;;18031:2:1;65643:110:0;;;18013:21:1;18070:2;18050:18;;;18043:30;18109:34;18089:18;;;18082:62;-1:-1:-1;;;18160:18:1;;;18153:39;18209:19;;65643:110:0;17829:405:1;65643:110:0;-1:-1:-1;;;;;;65771:16:0;;;;;:9;:16;;;;;;;65501:294::o;90896:103::-;90134:13;:11;:13::i;:::-;90961:30:::1;90988:1;90961:18;:30::i;:::-;90896:103::o:0;101781:399::-;101873:16;101907:23;101933:19;101943:8;101933:9;:19::i;:::-;101907:45;;101963:25;102005:15;101991:30;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;101991:30:0;;101963:58;;102037:9;102032:115;102052:15;102048:1;:19;102032:115;;;102103:32;102123:8;102133:1;102103:19;:32::i;:::-;102089:8;102098:1;102089:11;;;;;;;;:::i;:::-;;;;;;;;;;:46;102069:3;;;;:::i;:::-;;;;102032:115;;;-1:-1:-1;102164:8:0;101781:399;-1:-1:-1;;;101781:399:0:o;97910:1361::-;28190:21;:19;:21::i;:::-;97989:6:::1;::::0;::::1;;97985:31;;;98004:12;;-1:-1:-1::0;;;98004:12:0::1;;;;;;;;;;;97985:31;98032:24;63557:10:::0;98043:12:::1;63477:98:::0;98032:24:::1;98031:25;:62;;;;;98078:15;;98060;:33;98031:62;98027:101;;;98115:13;;-1:-1:-1::0;;;98115:13:0::1;;;;;;;;;;;98027:101;98161:18;;98143:15;:36;98139:62;;;98188:13;;-1:-1:-1::0;;;98188:13:0::1;;;;;;;;;;;98139:62;98225:7;;98216:6;:16;98212:40;;;98241:11;;-1:-1:-1::0;;;98241:11:0::1;;;;;;;;;;;98212:40;98267:6;98277:1;98267:11:::0;98263:40:::1;;98287:16;;-1:-1:-1::0;;;98287:16:0::1;;;;;;;;;;;98263:40;98316:18;98367:6:::0;98337:27:::1;63557:10:::0;103348:139;:::i;98337:27::-:1;:36;;;;:::i;:::-;98316:57;;98384:21;98408:13;83682:10:::0;:17;;83594:113;98408:13:::1;98384:37:::0;-1:-1:-1;93440:4:0::1;98438:22;98454:6:::0;98384:37;98438:22:::1;:::i;:::-;:35;98434:58;;;98482:10;;-1:-1:-1::0;;;98482:10:0::1;;;;;;;;;;;98434:58;98531:1;98507:21;98517:10;98507:9;:21::i;:::-;:25;98503:58;;;98541:20;;-1:-1:-1::0;;;98541:20:0::1;;;;;;;;;;;98503:58;98589:10;98576:9;:23;98572:57;;98608:21;;-1:-1:-1::0;;;98608:21:0::1;;;;;;;;;;;98572:57;98642:17;98694:1:::0;98678:13:::1;:17;:38;;;;;98715:1;98699:13;;:17;98678:38;98674:153;;;98775:3;98758:13;;98746:9;:25;;;;:::i;:::-;98745:33;;;;:::i;:::-;98733:45;;98793:22;98805:9;98793:11;:22::i;:::-;98856:1;98839:267;98864:6;98859:1;:11;98839:267;;98889:15;98907;:13;:15::i;:::-;98889:33:::0;-1:-1:-1;98937:32:0::1;63557:10:::0;98947:12:::1;98961:7;98937:9;:32::i;:::-;99041:16;::::0;99013:25:::1;::::0;;;:16:::1;:25;::::0;;;;;:44;99076:3:::1;;98839:267;;;-1:-1:-1::0;99118:14:0::1;99135:22;99148:9:::0;99135:10;:22:::1;:::i;:::-;99118:39;;99170:15;99178:6;99170:7;:15::i;:::-;99203:60;::::0;;16941:25:1;;;16997:2;16982:18;;16975:34;;;99247:15:0::1;17025:18:1::0;;;17018:34;99203:60:0;;63557:10;;99203:60:::1;::::0;;;;;16929:2:1;99203:60:0;;::::1;97974:1297;;;;28234:20:::0;27628:1;28754:7;:22;28571:213;28234:20;97910:1361;:::o;106318:173::-;90134:13;:11;:13::i;:::-;106372:12:::1;90321:6:::0;;106390:46:::1;::::0;-1:-1:-1;;;;;90321:6:0;;;;106410:21:::1;::::0;106372:12;106390:46;106372:12;106390:46;106410:21;90321:6;106390:46:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106371:65;;;106455:7;106447:36;;;::::0;-1:-1:-1;;;106447:36:0;;18651:2:1;106447:36:0::1;::::0;::::1;18633:21:1::0;18690:2;18670:18;;;18663:30;-1:-1:-1;;;18709:18:1;;;18702:46;18765:18;;106447:36:0::1;18449:340:1::0;104618:524:0;104713:18;104749:13;104765:17;104775:6;104765:9;:17::i;:::-;104749:33;;104793:25;104837:5;104821:22;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;104821:22:0;;;;;;;;;;;;;;;;104793:50;;104861:9;104856:253;104880:5;104876:1;:9;104856:253;;;104907:15;104925:30;104945:6;104953:1;104925:19;:30::i;:::-;104907:48;;104970:17;104990:24;105006:7;104990:15;:24::i;:::-;104970:44;;105044:7;105029:6;105036:1;105029:9;;;;;;;;:::i;:::-;;;;;;;:12;;:22;;;;;105088:9;105066:6;105073:1;105066:9;;;;;;;;:::i;:::-;;;;;;;:19;;:31;;;;;104892:217;;104887:3;;;;;:::i;:::-;;;;104856:253;;94012:116;90134:13;:11;:13::i;:::-;94090::::1;:30:::0;;-1:-1:-1;;;;;;94090:30:0::1;-1:-1:-1::0;;;;;94090:30:0;;;::::1;::::0;;;::::1;::::0;;94012:116::o;96162:86::-;90134:13;:11;:13::i;:::-;96226:5:::1;:14:::0;96162:86::o;66366:104::-;66422:13;66455:7;66448:14;;;;;:::i;99279:1287::-;28190:21;:19;:21::i;:::-;99354:6:::1;::::0;::::1;;99350:31;;;99369:12;;-1:-1:-1::0;;;99369:12:0::1;;;;;;;;;;;99350:31;99397:27;63557:10:::0;99411:12:::1;63477:98:::0;99397:27:::1;99396:28;:65;;;;;99446:15;;99428;:33;99396:65;99392:104;;;99483:13;;-1:-1:-1::0;;;99483:13:0::1;;;;;;;;;;;99392:104;99529:18;;99511:15;:36;99507:62;;;99556:13;;-1:-1:-1::0;;;99556:13:0::1;;;;;;;;;;;99507:62;99593:7;;99584:6;:16;99580:40;;;99609:11;;-1:-1:-1::0;;;99609:11:0::1;;;;;;;;;;;99580:40;99635:6;99645:1;99635:11:::0;99631:40:::1;;99655:16;;-1:-1:-1::0;;;99655:16:0::1;;;;;;;;;;;99631:40;99684:18;99731:6:::0;99705:23:::1;63557:10:::0;103616:141;:::i;99705:23::-:1;:32;;;;:::i;:::-;99684:53;;99748:21;99772:13;83682:10:::0;:17;;83594:113;99772:13:::1;99748:37:::0;-1:-1:-1;93440:4:0::1;99802:22;99818:6:::0;99748:37;99802:22:::1;:::i;:::-;:35;99798:58;;;99846:10;;-1:-1:-1::0;;;99846:10:0::1;;;;;;;;;;;99798:58;99884:10;99871:9;:23;99867:57;;99903:21;;-1:-1:-1::0;;;99903:21:0::1;;;;;;;;;;;99867:57;99937:17;99989:1:::0;99973:13:::1;:17;:38;;;;;100010:1;99994:13;;:17;99973:38;99969:153;;;100070:3;100053:13;;100041:9;:25;;;;:::i;:::-;100040:33;;;;:::i;:::-;100028:45;;100088:22;100100:9;100088:11;:22::i;:::-;100151:1;100134:267;100159:6;100154:1;:11;100134:267;;100184:15;100202;:13;:15::i;:::-;100184:33:::0;-1:-1:-1;100232:32:0::1;63557:10:::0;100242:12:::1;63477:98:::0;100232:32:::1;100336:16;::::0;100308:25:::1;::::0;;;:16:::1;:25;::::0;;;;;:44;100371:3:::1;;100134:267;;68099:187:::0;68226:52;63557:10;68259:8;68269;68226:18;:52::i;103348:139::-;-1:-1:-1;;;;;103316:16:0;;103410:7;103316:16;;;:6;:16;;;;;;;;103437:42;;103474:5;;103437:42;;;-1:-1:-1;;103460:11:0;;;103348:139::o;95442:250::-;16665:42;17927:43;:47;17923:318;;18014:128;;-1:-1:-1;;;18014:128:0;;18085:4;18014:128;;;13213:34:1;18113:10:0;13263:18:1;;;13256:43;16665:42:0;;18014:40;;13148:18:1;;18014:128:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17991:239;;18184:30;;-1:-1:-1;;;18184:30:0;;18203:10;18184:30;;;2419:51:1;2392:18;;18184:30:0;2273:203:1;17991:239:0;95637:47:::1;95660:4;95666:2;95670:7;95679:4;95637:22;:47::i;:::-;95442:250:::0;;;;:::o;97133:541::-;90134:13;:11;:13::i;:::-;97209:21:::1;97233:13;83682:10:::0;:17;;83594:113;97233:13:::1;97209:37:::0;-1:-1:-1;93440:4:0::1;97263:22;97279:6:::0;97209:37;97263:22:::1;:::i;:::-;:35;97259:58;;;97307:10;;-1:-1:-1::0;;;97307:10:0::1;;;;;;;;;;;97259:58;97347:1;97330:259;97355:6;97350:1;:11;97330:259;;97380:15;97398;:13;:15::i;:::-;97380:33;;97430:22;97440:2;97444:7;97430:9;:22::i;:::-;97524:16;::::0;97496:25:::1;::::0;;;:16:::1;:25;::::0;;;;;:44;97559:3:::1;;97330:259;;;-1:-1:-1::0;97606:60:0::1;::::0;;16941:25:1;;;16997:2;16982:18;;16975:34;;;97650:15:0::1;17025:18:1::0;;;17018:34;97606:60:0;;63557:10;;97606:60:::1;::::0;;;;;16929:2:1;97606:60:0;;::::1;97198:476;97133:541:::0;;:::o;102326:437::-;71536:4;71134:16;;;:7;:16;;;;;;102445:13;;-1:-1:-1;;;;;71134:16:0;102476:114;;;;-1:-1:-1;;;102476:114:0;;18996:2:1;102476:114:0;;;18978:21:1;19035:2;19015:18;;;19008:30;19074:34;19054:18;;;19047:62;-1:-1:-1;;;19125:18:1;;;19118:45;19180:19;;102476:114:0;18794:411:1;102476:114:0;102601:23;102665:12;102679:26;102696:8;102679:16;:26::i;:::-;102648:67;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;102648:67:0;;;;;;;;;;102326:437;-1:-1:-1;;;102326:437:0:o;102787:308::-;102833:15;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102833:15:0;102881:206;;;;;;;;;102908:6;;;;102881:206;;;;;;;102933:13;83682:10;:17;;83594:113;102933:13;102881:206;;;;93440:4;102881:206;;;;102994:7;;102881:206;;;;103020:15;;102881:206;;;;103054:18;;102881:206;;;102861:226;;102787:308;:::o;103783:82::-;103835:22;103847:9;103835:11;:22::i;96256:122::-;90134:13;:11;:13::i;:::-;96338:14:::1;:32:::0;96256:122::o;91154:238::-;90134:13;:11;:13::i;:::-;-1:-1:-1;;;;;91257:22:0;::::1;91235:110;;;::::0;-1:-1:-1;;;91235:110:0;;20604:2:1;91235:110:0::1;::::0;::::1;20586:21:1::0;20643:2;20623:18;;;20616:30;20682:34;20662:18;;;20655:62;-1:-1:-1;;;20733:18:1;;;20726:36;20779:19;;91235:110:0::1;20402:402:1::0;91235:110:0::1;91356:28;91375:8;91356:18;:28::i;95700:226::-:0;90134:13;:11;:13::i;:::-;95833:18:::1;:40:::0;;;;95884:15:::1;:34:::0;95700:226::o;22844:291::-;22991:4;-1:-1:-1;;;;;;23033:41:0;;-1:-1:-1;;;23033:41:0;;:94;;;23091:36;23115:11;23091:23;:36::i;90413:132::-;90294:7;90321:6;-1:-1:-1;;;;;90321:6:0;63557:10;90477:23;90469:68;;;;-1:-1:-1;;;90469:68:0;;21011:2:1;90469:68:0;;;20993:21:1;;;21030:18;;;21023:30;21089:34;21069:18;;;21062:62;21141:18;;90469:68:0;20809:356:1;24345:392:0;24061:5;-1:-1:-1;;;;;24485:33:0;;;;24463:125;;;;-1:-1:-1;;;24463:125:0;;21372:2:1;24463:125:0;;;21354:21:1;21411:2;21391:18;;;21384:30;21450:34;21430:18;;;21423:62;-1:-1:-1;;;21501:18:1;;;21494:40;21551:19;;24463:125:0;21170:406:1;24463:125:0;-1:-1:-1;;;;;24607:22:0;;24599:60;;;;-1:-1:-1;;;24599:60:0;;21783:2:1;24599:60:0;;;21765:21:1;21822:2;21802:18;;;21795:30;21861:27;21841:18;;;21834:55;21906:18;;24599:60:0;21581:349:1;24599:60:0;24694:35;;;;;;;;;-1:-1:-1;;;;;24694:35:0;;;;;;-1:-1:-1;;;;;24694:35:0;;;;;;;;;;-1:-1:-1;;;24672:57:0;;;;:19;:57;24345:392::o;78009:135::-;71536:4;71134:16;;;:7;:16;;;;;;-1:-1:-1;;;;;71134:16:0;78083:53;;;;-1:-1:-1;;;78083:53:0;;17678:2:1;78083:53:0;;;17660:21:1;17717:2;17697:18;;;17690:30;-1:-1:-1;;;17736:18:1;;;17729:54;17800:18;;78083:53:0;17476:348:1;77288:174:0;77363:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;77363:29:0;-1:-1:-1;;;;;77363:29:0;;;;;;;;:24;;77417:23;77363:24;77417:14;:23::i;:::-;-1:-1:-1;;;;;77408:46:0;;;;;;;;;;;77288:174;;:::o;68638:372::-;68847:41;63557:10;68880:7;68847:18;:41::i;:::-;68825:136;;;;-1:-1:-1;;;68825:136:0;;;;;;;:::i;:::-;68974:28;68984:4;68990:2;68994:7;68974:9;:28::i;69081:185::-;69219:39;69236:4;69242:2;69246:7;69219:39;;;;;;;;;;;;:16;:39::i;28270:293::-;27672:1;28404:7;;:19;28396:63;;;;-1:-1:-1;;;28396:63:0;;22551:2:1;28396:63:0;;;22533:21:1;22590:2;22570:18;;;22563:30;22629:33;22609:18;;;22602:61;22680:18;;28396:63:0;22349:355:1;28396:63:0;27672:1;28537:7;:18;28270:293::o;100574:344::-;100632:14;100649:12;100660:1;100649:8;:12;:::i;:::-;100632:29;;100672:16;100704:13;83682:10;:17;;83594:113;100704:13;100691:26;;93440:4;100691:26;:::i;:::-;100672:45;-1:-1:-1;100734:12:0;:26;100747:12;100758:1;100672:45;100747:12;:::i;:::-;100734:26;;;;;;;;;;;;100764:1;100734:31;100730:181;;100805:12;100816:1;100805:8;:12;:::i;:::-;100782:20;;;;:12;:20;;;;;:35;67394:346;67324:416;;:::o;100730:181::-;100873:12;:26;100886:12;100897:1;100886:8;:12;:::i;:::-;100873:26;;;;;;;;;;;;;;-1:-1:-1;100873:26:0;;;;100850:20;;;:12;:20;;;;:49;100621:297;;100574:344;:::o;72439:110::-;72515:26;72525:2;72529:7;72515:26;;;;;;;;;;;;:9;:26::i;91552:191::-;91626:16;91645:6;;-1:-1:-1;;;;;91662:17:0;;;-1:-1:-1;;;;;;91662:17:0;;;;;;91695:40;;91645:6;;;;;;;91695:40;;91626:16;91695:40;91615:128;91552:191;:::o;103873:211::-;103933:6;103943:1;103933:11;103929:41;;103953:17;;-1:-1:-1;;;103953:17:0;;;;;;;;;;;103929:41;104017:6;104000:14;;:23;;;;:::i;:::-;103983:14;:40;83682:10;:17;104054:22;;:6;:22;:::i;:::-;104034:16;;:42;;;;;;;:::i;:::-;;;;-1:-1:-1;;;103873:211:0:o;100926:847::-;100969:7;100989:16;101021:13;83682:10;:17;;83594:113;101021:13;101008:26;;93440:4;101008:26;:::i;:::-;101114:219;;-1:-1:-1;;101153:10:0;23036:2:1;23032:15;;;23028:24;;101114:219:0;;;23016:37:1;101186:14:0;23087:15:1;;23083:24;23069:12;;;23062:46;101223:16:0;23124:12:1;;;23117:28;101262:14:0;23161:12:1;;;23154:28;101299:15:0;23198:13:1;;;23191:29;100989:45:0;;-1:-1:-1;101047:14:0;;100989:45;;23236:13:1;;101114:219:0;;;;;;;;;;;;101086:262;;;;;;101064:295;;:306;;;;:::i;:::-;101383:13;101415:20;;;:12;:20;;;;;;101047:323;;-1:-1:-1;101383:13:0;101415:25;;101411:133;;-1:-1:-1;101465:6:0;101411:133;;;-1:-1:-1;101512:20:0;;;;:12;:20;;;;;;101411:133;101560:12;:26;101573:12;101584:1;101573:8;:12;:::i;:::-;101560:26;;;;;;;;;;;;101590:1;101560:31;101556:181;;101631:12;101642:1;101631:8;:12;:::i;:::-;101608:20;;;;:12;:20;;;;;:35;101556:181;;;101699:12;:26;101712:12;101723:1;101712:8;:12;:::i;:::-;101699:26;;;;;;;;;;;;;;-1:-1:-1;101699:26:0;;;;101676:20;;;:12;:20;;;;:49;101556:181;101756:9;:5;101764:1;101756:9;:::i;:::-;101749:16;;;;;100926:847;:::o;97682:220::-;97762:13;;97754:96;;97736:12;;-1:-1:-1;;;;;97762:13:0;;97830:5;;97803:7;;97736:12;97754:96;97736:12;97754:96;97803:7;97762:13;97830:5;97754:96;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97735:115;;;97869:7;97861:33;;;;-1:-1:-1;;;97861:33:0;;23579:2:1;97861:33:0;;;23561:21:1;23618:2;23598:18;;;23591:30;-1:-1:-1;;;23637:18:1;;;23630:43;23690:18;;97861:33:0;23377:337:1;77605:315:0;77760:8;-1:-1:-1;;;;;77751:17:0;:5;-1:-1:-1;;;;;77751:17:0;;77743:55;;;;-1:-1:-1;;;77743:55:0;;23921:2:1;77743:55:0;;;23903:21:1;23960:2;23940:18;;;23933:30;23999:27;23979:18;;;23972:55;24044:18;;77743:55:0;23719:349:1;77743:55:0;-1:-1:-1;;;;;77809:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;77809:46:0;;;;;;;;;;77871:41;;540::1;;;77871::0;;513:18:1;77871:41:0;;;;;;;77605:315;;;:::o;69337:359::-;69525:41;63557:10;69558:7;69525:18;:41::i;:::-;69503:136;;;;-1:-1:-1;;;69503:136:0;;;;;;;:::i;:::-;69650:38;69664:4;69670:2;69674:7;69683:4;69650:13;:38::i;48713:716::-;48769:13;48820:14;48837:17;48848:5;48837:10;:17::i;:::-;48857:1;48837:21;48820:38;;48873:20;48907:6;48896:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48896:18:0;-1:-1:-1;48873:41:0;-1:-1:-1;49038:28:0;;;49054:2;49038:28;49095:288;-1:-1:-1;;49127:5:0;-1:-1:-1;;;49264:2:0;49253:14;;49248:30;49127:5;49235:44;49325:2;49316:11;;;-1:-1:-1;49346:21:0;49095:288;49346:21;-1:-1:-1;49404:6:0;48713:716;-1:-1:-1;;;48713:716:0:o;82791:300::-;82938:4;-1:-1:-1;;;;;;82980:50:0;;-1:-1:-1;;;82980:50:0;;:103;;;83047:36;83071:11;83047:23;:36::i;71766:331::-;71895:4;71917:13;71933:23;71948:7;71933:14;:23::i;:::-;71917:39;;71986:5;-1:-1:-1;;;;;71975:16:0;:7;-1:-1:-1;;;;;71975:16:0;;:65;;;-1:-1:-1;;;;;;68528:25:0;;;68499:4;68528:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;72008:32;71975:113;;;;72081:7;-1:-1:-1;;;;;72057:31:0;:20;72069:7;72057:11;:20::i;:::-;-1:-1:-1;;;;;72057:31:0;;71975:113;71967:122;71766:331;-1:-1:-1;;;;71766:331:0:o;75832:1337::-;76005:4;-1:-1:-1;;;;;75978:31:0;:23;75993:7;75978:14;:23::i;:::-;-1:-1:-1;;;;;75978:31:0;;75956:118;;;;-1:-1:-1;;;75956:118:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;76093:16:0;;76085:65;;;;-1:-1:-1;;;76085:65:0;;24681:2:1;76085:65:0;;;24663:21:1;24720:2;24700:18;;;24693:30;24759:34;24739:18;;;24732:62;-1:-1:-1;;;24810:18:1;;;24803:34;24854:19;;76085:65:0;24479:400:1;76085:65:0;76163:42;76184:4;76190:2;76194:7;76203:1;76163:20;:42::i;:::-;76349:4;-1:-1:-1;;;;;76322:31:0;:23;76337:7;76322:14;:23::i;:::-;-1:-1:-1;;;;;76322:31:0;;76300:118;;;;-1:-1:-1;;;76300:118:0;;;;;;;:::i;:::-;76490:24;;;;:15;:24;;;;;;;;76483:31;;-1:-1:-1;;;;;;76483:31:0;;;;;;-1:-1:-1;;;;;76966:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;76966:20:0;;;77001:13;;;;;;;;;:18;;76483:31;77001:18;;;77041:16;;;:7;:16;;;;;;:21;;;;;;;;;;77080:27;;76506:7;;77080:27;;;67394:346;67324:416;;:::o;72776:319::-;72905:18;72911:2;72915:7;72905:5;:18::i;:::-;72956:53;72987:1;72991:2;72995:7;73004:4;72956:22;:53::i;:::-;72934:153;;;;-1:-1:-1;;;72934:153:0;;;;;;;:::i;70577:350::-;70733:28;70743:4;70749:2;70753:7;70733:9;:28::i;:::-;70794:47;70817:4;70823:2;70827:7;70836:4;70794:22;:47::i;:::-;70772:147;;;;-1:-1:-1;;;70772:147:0;;;;;;;:::i;45451:922::-;45504:7;;-1:-1:-1;;;45582:15:0;;45578:102;;-1:-1:-1;;;45618:15:0;;;-1:-1:-1;45662:2:0;45652:12;45578:102;45707:6;45698:5;:15;45694:102;;45743:6;45734:15;;;-1:-1:-1;45778:2:0;45768:12;45694:102;45823:6;45814:5;:15;45810:102;;45859:6;45850:15;;;-1:-1:-1;45894:2:0;45884:12;45810:102;45939:5;45930;:14;45926:99;;45974:5;45965:14;;;-1:-1:-1;46008:1:0;45998:11;45926:99;46052:5;46043;:14;46039:99;;46087:5;46078:14;;;-1:-1:-1;46121:1:0;46111:11;46039:99;46165:5;46156;:14;46152:99;;46200:5;46191:14;;;-1:-1:-1;46234:1:0;46224:11;46152:99;46278:5;46269;:14;46265:66;;46314:1;46304:11;46359:6;45451:922;-1:-1:-1;;45451:922:0:o;65082:355::-;65229:4;-1:-1:-1;;;;;;65271:40:0;;-1:-1:-1;;;65271:40:0;;:105;;-1:-1:-1;;;;;;;65328:48:0;;-1:-1:-1;;;65328:48:0;65271:105;:158;;;-1:-1:-1;;;;;;;;;;20515:40:0;;;65393:36;20356:207;84178:915;84355:61;84382:4;84388:2;84392:12;84406:9;84355:26;:61::i;:::-;84445:1;84433:9;:13;84429:222;;;84576:63;;-1:-1:-1;;;84576:63:0;;25505:2:1;84576:63:0;;;25487:21:1;25544:2;25524:18;;;25517:30;25583:34;25563:18;;;25556:62;-1:-1:-1;;;25634:18:1;;;25627:51;25695:19;;84576:63:0;25303:417:1;84429:222:0;84681:12;-1:-1:-1;;;;;84710:18:0;;84706:187;;84745:40;84777:7;85920:10;:17;;85893:24;;;;:15;:24;;;;;:44;;;85948:24;;;;;;;;;;;;85816:164;84745:40;84706:187;;;84815:2;-1:-1:-1;;;;;84807:10:0;:4;-1:-1:-1;;;;;84807:10:0;;84803:90;;84834:47;84867:4;84873:7;84834:32;:47::i;:::-;-1:-1:-1;;;;;84907:16:0;;84903:183;;84940:45;84977:7;84940:36;:45::i;:::-;84903:183;;;85013:4;-1:-1:-1;;;;;85007:10:0;:2;-1:-1:-1;;;;;85007:10:0;;85003:83;;85034:40;85062:2;85066:7;85034:27;:40::i;:::-;84344:749;84178:915;;;;:::o;73431:942::-;-1:-1:-1;;;;;73511:16:0;;73503:61;;;;-1:-1:-1;;;73503:61:0;;25927:2:1;73503:61:0;;;25909:21:1;;;25946:18;;;25939:30;26005:34;25985:18;;;25978:62;26057:18;;73503:61:0;25725:356:1;73503:61:0;71536:4;71134:16;;;:7;:16;;;;;;-1:-1:-1;;;;;71134:16:0;71560:31;73575:58;;;;-1:-1:-1;;;73575:58:0;;26288:2:1;73575:58:0;;;26270:21:1;26327:2;26307:18;;;26300:30;26366;26346:18;;;26339:58;26414:18;;73575:58:0;26086:352:1;73575:58:0;73646:48;73675:1;73679:2;73683:7;73692:1;73646:20;:48::i;:::-;71536:4;71134:16;;;:7;:16;;;;;;-1:-1:-1;;;;;71134:16:0;71560:31;73784:58;;;;-1:-1:-1;;;73784:58:0;;26288:2:1;73784:58:0;;;26270:21:1;26327:2;26307:18;;;26300:30;26366;26346:18;;;26339:58;26414:18;;73784:58:0;26086:352:1;73784:58:0;-1:-1:-1;;;;;74191:13:0;;;;;;:9;:13;;;;;;;;:18;;74208:1;74191:18;;;74233:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;74233:21:0;;;;;74272:33;74241:7;;74191:13;;74272:33;;74191:13;;74272:33;94242:167;;:::o;78708:1034::-;78862:4;-1:-1:-1;;;;;78883:13:0;;52165:19;:23;78879:856;;78936:174;;-1:-1:-1;;;78936:174:0;;-1:-1:-1;;;;;78936:36:0;;;;;:174;;63557:10;;79030:4;;79057:7;;79087:4;;78936:174;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78936:174:0;;;;;;;;-1:-1:-1;;78936:174:0;;;;;;;;;;;;:::i;:::-;;;78915:765;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79293:6;:13;79310:1;79293:18;79289:376;;79336:108;;-1:-1:-1;;;79336:108:0;;;;;;;:::i;79289:376::-;79615:6;79609:13;79600:6;79596:2;79592:15;79585:38;78915:765;-1:-1:-1;;;;;;79174:51:0;-1:-1:-1;;;79174:51:0;;-1:-1:-1;79167:58:0;;78879:856;-1:-1:-1;79719:4:0;78708:1034;;;;;;:::o;80474:410::-;80664:1;80652:9;:13;80648:229;;;-1:-1:-1;;;;;80686:18:0;;;80682:87;;-1:-1:-1;;;;;80725:15:0;;;;;;:9;:15;;;;;:28;;80744:9;;80725:15;:28;;80744:9;;80725:28;:::i;:::-;;;;-1:-1:-1;;80682:87:0;-1:-1:-1;;;;;80787:16:0;;;80783:83;;-1:-1:-1;;;;;80824:13:0;;;;;;:9;:13;;;;;:26;;80841:9;;80824:13;:26;;80841:9;;80824:26;:::i;:::-;;;;-1:-1:-1;;80474:410:0;;;;:::o;86607:1002::-;86887:22;86937:1;86912:22;86929:4;86912:16;:22::i;:::-;:26;;;;:::i;:::-;86949:18;86970:26;;;:17;:26;;;;;;86887:51;;-1:-1:-1;87103:28:0;;;87099:328;;-1:-1:-1;;;;;87170:18:0;;87148:19;87170:18;;;:12;:18;;;;;;;;:34;;;;;;;;;87221:30;;;;;;:44;;;87338:30;;:17;:30;;;;;:43;;;87099:328;-1:-1:-1;87523:26:0;;;;:17;:26;;;;;;;;87516:33;;;-1:-1:-1;;;;;87567:18:0;;;;;:12;:18;;;;;:34;;;;;;;87560:41;86607:1002::o;87904:1079::-;88182:10;:17;88157:22;;88182:21;;88202:1;;88182:21;:::i;:::-;88214:18;88235:24;;;:15;:24;;;;;;88608:10;:26;;88157:46;;-1:-1:-1;88235:24:0;;88157:46;;88608:26;;;;;;:::i;:::-;;;;;;;;;88586:48;;88672:11;88647:10;88658;88647:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;88752:28;;;:15;:28;;;;;;;:41;;;88924:24;;;;;88917:31;88959:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;87975:1008;;;87904:1079;:::o;85394:221::-;85479:14;85496:20;85513:2;85496:16;:20::i;:::-;-1:-1:-1;;;;;85527:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;85572:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;85394: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;:::-;384:5;150:245;-1:-1:-1;;;150:245:1:o;592:173::-;660:20;;-1:-1:-1;;;;;709:31:1;;699:42;;689:70;;755:1;752;745:12;689:70;592:173;;;:::o;770:366::-;837:6;845;898:2;886:9;877:7;873:23;869:32;866:52;;;914:1;911;904:12;866:52;937:29;956:9;937:29;:::i;:::-;927:39;;1016:2;1005:9;1001:18;988:32;-1:-1:-1;;;;;1053:5:1;1049:38;1042:5;1039:49;1029:77;;1102:1;1099;1092:12;1029:77;1125:5;1115:15;;;770:366;;;;;:::o;1141:186::-;1200:6;1253:2;1241:9;1232:7;1228:23;1224:32;1221:52;;;1269:1;1266;1259:12;1221:52;1292:29;1311:9;1292:29;:::i;1332:250::-;1417:1;1427:113;1441:6;1438:1;1435:13;1427:113;;;1517:11;;;1511:18;1498:11;;;1491:39;1463:2;1456:10;1427:113;;;-1:-1:-1;;1574:1:1;1556:16;;1549:27;1332:250::o;1587:271::-;1629:3;1667:5;1661:12;1694:6;1689:3;1682:19;1710:76;1779:6;1772:4;1767:3;1763:14;1756:4;1749:5;1745:16;1710:76;:::i;:::-;1840:2;1819:15;-1:-1:-1;;1815:29:1;1806:39;;;;1847:4;1802:50;;1587:271;-1:-1:-1;;1587:271:1:o;1863:220::-;2012:2;2001:9;1994:21;1975:4;2032:45;2073:2;2062:9;2058:18;2050:6;2032:45;:::i;2088:180::-;2147:6;2200:2;2188:9;2179:7;2175:23;2171:32;2168:52;;;2216:1;2213;2206:12;2168:52;-1:-1:-1;2239:23:1;;2088:180;-1:-1:-1;2088:180:1:o;2481:254::-;2549:6;2557;2610:2;2598:9;2589:7;2585:23;2581:32;2578:52;;;2626:1;2623;2616:12;2578:52;2649:29;2668:9;2649:29;:::i;:::-;2639:39;2725:2;2710:18;;;;2697:32;;-1:-1:-1;;;2481:254:1:o;2740:127::-;2801:10;2796:3;2792:20;2789:1;2782:31;2832:4;2829:1;2822:15;2856:4;2853:1;2846:15;2872:275;2943:2;2937:9;3008:2;2989:13;;-1:-1:-1;;2985:27:1;2973:40;;3043:18;3028:34;;3064:22;;;3025:62;3022:88;;;3090:18;;:::i;:::-;3126:2;3119:22;2872:275;;-1:-1:-1;2872:275:1:o;3152:183::-;3212:4;3245:18;3237:6;3234:30;3231:56;;;3267:18;;:::i;:::-;-1:-1:-1;3312:1:1;3308:14;3324:4;3304:25;;3152:183::o;3340:662::-;3394:5;3447:3;3440:4;3432:6;3428:17;3424:27;3414:55;;3465:1;3462;3455:12;3414:55;3501:6;3488:20;3527:4;3551:60;3567:43;3607:2;3567:43;:::i;:::-;3551:60;:::i;:::-;3645:15;;;3731:1;3727:10;;;;3715:23;;3711:32;;;3676:12;;;;3755:15;;;3752:35;;;3783:1;3780;3773:12;3752:35;3819:2;3811:6;3807:15;3831:142;3847:6;3842:3;3839:15;3831:142;;;3913:17;;3901:30;;3951:12;;;;3864;;3831:142;;;-1:-1:-1;3991:5:1;3340:662;-1:-1:-1;;;;;;3340:662:1:o;4007:348::-;4091:6;4144:2;4132:9;4123:7;4119:23;4115:32;4112:52;;;4160:1;4157;4150:12;4112:52;4200:9;4187:23;4233:18;4225:6;4222:30;4219:50;;;4265:1;4262;4255:12;4219:50;4288:61;4341:7;4332:6;4321:9;4317:22;4288:61;:::i;4542:897::-;4626:6;4657:2;4700;4688:9;4679:7;4675:23;4671:32;4668:52;;;4716:1;4713;4706:12;4668:52;4756:9;4743:23;4789:18;4781:6;4778:30;4775:50;;;4821:1;4818;4811:12;4775:50;4844:22;;4897:4;4889:13;;4885:27;-1:-1:-1;4875:55:1;;4926:1;4923;4916:12;4875:55;4962:2;4949:16;4985:60;5001:43;5041:2;5001:43;:::i;4985:60::-;5079:15;;;5161:1;5157:10;;;;5149:19;;5145:28;;;5110:12;;;;5185:19;;;5182:39;;;5217:1;5214;5207:12;5182:39;5241:11;;;;5261:148;5277:6;5272:3;5269:15;5261:148;;;5343:23;5362:3;5343:23;:::i;:::-;5331:36;;5294:12;;;;5387;;;;5261:148;;;5428:5;4542:897;-1:-1:-1;;;;;;;4542:897:1:o;5444:328::-;5521:6;5529;5537;5590:2;5578:9;5569:7;5565:23;5561:32;5558:52;;;5606:1;5603;5596:12;5558:52;5629:29;5648:9;5629:29;:::i;:::-;5619:39;;5677:38;5711:2;5700:9;5696:18;5677:38;:::i;:::-;5667:48;;5762:2;5751:9;5747:18;5734:32;5724:42;;5444:328;;;;;:::o;5777:248::-;5845:6;5853;5906:2;5894:9;5885:7;5881:23;5877:32;5874:52;;;5922:1;5919;5912:12;5874:52;-1:-1:-1;;5945:23:1;;;6015:2;6000:18;;;5987:32;;-1:-1:-1;5777:248:1:o;6309:407::-;6374:5;6408:18;6400:6;6397:30;6394:56;;;6430:18;;:::i;:::-;6468:57;6513:2;6492:15;;-1:-1:-1;;6488:29:1;6519:4;6484:40;6468:57;:::i;:::-;6459:66;;6548:6;6541:5;6534:21;6588:3;6579:6;6574:3;6570:16;6567:25;6564:45;;;6605:1;6602;6595:12;6564:45;6654:6;6649:3;6642:4;6635:5;6631:16;6618:43;6708:1;6701:4;6692:6;6685:5;6681:18;6677:29;6670:40;6309:407;;;;;:::o;6721:451::-;6790:6;6843:2;6831:9;6822:7;6818:23;6814:32;6811:52;;;6859:1;6856;6849:12;6811:52;6899:9;6886:23;6932:18;6924:6;6921:30;6918:50;;;6964:1;6961;6954:12;6918:50;6987:22;;7040:4;7032:13;;7028:27;-1:-1:-1;7018:55:1;;7069:1;7066;7059:12;7018:55;7092:74;7158:7;7153:2;7140:16;7135:2;7131;7127:11;7092:74;:::i;7177:422::-;7270:6;7278;7331:2;7319:9;7310:7;7306:23;7302:32;7299:52;;;7347:1;7344;7337:12;7299:52;7387:9;7374:23;7420:18;7412:6;7409:30;7406:50;;;7452:1;7449;7442:12;7406:50;7475:61;7528:7;7519:6;7508:9;7504:22;7475:61;:::i;:::-;7465:71;;;7555:38;7589:2;7578:9;7574:18;7555:38;:::i;:::-;7545:48;;7177:422;;;;;:::o;7604:632::-;7775:2;7827:21;;;7897:13;;7800:18;;;7919:22;;;7746:4;;7775:2;7998:15;;;;7972:2;7957:18;;;7746:4;8041:169;8055:6;8052:1;8049:13;8041:169;;;8116:13;;8104:26;;8185:15;;;;8150:12;;;;8077:1;8070:9;8041:169;;;-1:-1:-1;8227:3:1;;7604:632;-1:-1:-1;;;;;;7604:632:1:o;8241:792::-;8466:2;8518:21;;;8588:13;;8491:18;;;8610:22;;;8437:4;;8466:2;8651;;8669:18;;;;8710:15;;;8437:4;8753:254;8767:6;8764:1;8761:13;8753:254;;;8826:13;;8864:9;;8852:22;;8914:11;;8908:18;8894:12;;;8887:40;8947:12;;;;8982:15;;;;8789:1;8782:9;8753:254;;;-1:-1:-1;9024:3:1;;8241:792;-1:-1:-1;;;;;;;8241:792:1:o;9038:118::-;9124:5;9117:13;9110:21;9103:5;9100:32;9090:60;;9146:1;9143;9136:12;9161:315;9226:6;9234;9287:2;9275:9;9266:7;9262:23;9258:32;9255:52;;;9303:1;9300;9293:12;9255:52;9326:29;9345:9;9326:29;:::i;:::-;9316:39;;9405:2;9394:9;9390:18;9377:32;9418:28;9440:5;9418:28;:::i;9481:667::-;9576:6;9584;9592;9600;9653:3;9641:9;9632:7;9628:23;9624:33;9621:53;;;9670:1;9667;9660:12;9621:53;9693:29;9712:9;9693:29;:::i;:::-;9683:39;;9741:38;9775:2;9764:9;9760:18;9741:38;:::i;:::-;9731:48;;9826:2;9815:9;9811:18;9798:32;9788:42;;9881:2;9870:9;9866:18;9853:32;9908:18;9900:6;9897:30;9894:50;;;9940:1;9937;9930:12;9894:50;9963:22;;10016:4;10008:13;;10004:27;-1:-1:-1;9994:55:1;;10045:1;10042;10035:12;9994:55;10068:74;10134:7;10129:2;10116:16;10111:2;10107;10103:11;10068:74;:::i;:::-;10058:84;;;9481:667;;;;;;;:::o;10153:254::-;10221:6;10229;10282:2;10270:9;10261:7;10257:23;10253:32;10250:52;;;10298:1;10295;10288:12;10250:52;10334:9;10321:23;10311:33;;10363:38;10397:2;10386:9;10382:18;10363:38;:::i;10985:260::-;11053:6;11061;11114:2;11102:9;11093:7;11089:23;11085:32;11082:52;;;11130:1;11127;11120:12;11082:52;11153:29;11172:9;11153:29;:::i;:::-;11143:39;;11201:38;11235:2;11224:9;11220:18;11201:38;:::i;11250:380::-;11329:1;11325:12;;;;11372;;;11393:61;;11447:4;11439:6;11435:17;11425:27;;11393:61;11500:2;11492:6;11489:14;11469:18;11466:38;11463:161;;11546:10;11541:3;11537:20;11534:1;11527:31;11581:4;11578:1;11571:15;11609:4;11606:1;11599:15;11463:161;;11250:380;;;:::o;12467:127::-;12528:10;12523:3;12519:20;12516:1;12509:31;12559:4;12556:1;12549:15;12583:4;12580:1;12573:15;12599:127;12660:10;12655:3;12651:20;12648:1;12641:31;12691:4;12688:1;12681:15;12715:4;12712:1;12705:15;12731:125;12796:9;;;12817:10;;;12814:36;;;12830:18;;:::i;12861:135::-;12900:3;12921:17;;;12918:43;;12941:18;;:::i;:::-;-1:-1:-1;12988:1:1;12977:13;;12861:135::o;13310:245::-;13377:6;13430:2;13418:9;13409:7;13405:23;13401:32;13398:52;;;13446:1;13443;13436:12;13398:52;13478:9;13472:16;13497:28;13519:5;13497:28;:::i;13560:168::-;13633:9;;;13664;;13681:15;;;13675:22;;13661:37;13651:71;;13702:18;;:::i;13733:127::-;13794:10;13789:3;13785:20;13782:1;13775:31;13825:4;13822:1;13815:15;13849:4;13846:1;13839:15;13865:120;13905:1;13931;13921:35;;13936:18;;:::i;:::-;-1:-1:-1;13970:9:1;;13865:120::o;14528:545::-;14630:2;14625:3;14622:11;14619:448;;;14666:1;14691:5;14687:2;14680:17;14736:4;14732:2;14722:19;14806:2;14794:10;14790:19;14787:1;14783:27;14777:4;14773:38;14842:4;14830:10;14827:20;14824:47;;;-1:-1:-1;14865:4:1;14824:47;14920:2;14915:3;14911:12;14908:1;14904:20;14898:4;14894:31;14884:41;;14975:82;14993:2;14986:5;14983:13;14975:82;;;15038:17;;;15019:1;15008:13;14975:82;;;14979:3;;;14528:545;;;:::o;15249:1352::-;15375:3;15369:10;15402:18;15394:6;15391:30;15388:56;;;15424:18;;:::i;:::-;15453:97;15543:6;15503:38;15535:4;15529:11;15503:38;:::i;:::-;15497:4;15453:97;:::i;:::-;15605:4;;15669:2;15658:14;;15686:1;15681:663;;;;16388:1;16405:6;16402:89;;;-1:-1:-1;16457:19:1;;;16451:26;16402:89;-1:-1:-1;;15206:1:1;15202:11;;;15198:24;15194:29;15184:40;15230:1;15226:11;;;15181:57;16504:81;;15651:944;;15681:663;14475:1;14468:14;;;14512:4;14499:18;;-1:-1:-1;;15717:20:1;;;15835:236;15849:7;15846:1;15843:14;15835:236;;;15938:19;;;15932:26;15917:42;;16030:27;;;;15998:1;15986:14;;;;15865:19;;15835:236;;;15839:3;16099:6;16090:7;16087:19;16084:201;;;16160:19;;;16154:26;-1:-1:-1;;16243:1:1;16239:14;;;16255:3;16235:24;16231:37;16227:42;16212:58;16197:74;;16084:201;-1:-1:-1;;;;;16331:1:1;16315:14;;;16311:22;16298:36;;-1:-1:-1;15249:1352:1:o;16606:128::-;16673:9;;;16694:11;;;16691:37;;;16708:18;;:::i;19210:1187::-;19487:3;19516:1;19549:6;19543:13;19579:36;19605:9;19579:36;:::i;:::-;19634:1;19651:18;;;19678:133;;;;19825:1;19820:356;;;;19644:532;;19678:133;-1:-1:-1;;19711:24:1;;19699:37;;19784:14;;19777:22;19765:35;;19756:45;;;-1:-1:-1;19678:133:1;;19820:356;19851:6;19848:1;19841:17;19881:4;19926:2;19923:1;19913:16;19951:1;19965:165;19979:6;19976:1;19973:13;19965:165;;;20057:14;;20044:11;;;20037:35;20100:16;;;;19994:10;;19965:165;;;19969:3;;;20159:6;20154:3;20150:16;20143:23;;19644:532;;;;;20207:6;20201:13;20223:68;20282:8;20277:3;20270:4;20262:6;20258:17;20223:68;:::i;:::-;-1:-1:-1;;;20313:18:1;;20340:22;;;20389:1;20378:13;;19210:1187;-1:-1:-1;;;;19210:1187:1:o;21935:409::-;22137:2;22119:21;;;22176:2;22156:18;;;22149:30;22215:34;22210:2;22195:18;;22188:62;-1:-1:-1;;;22281:2:1;22266:18;;22259:43;22334:3;22319:19;;21935:409::o;23260:112::-;23292:1;23318;23308:35;;23323:18;;:::i;:::-;-1:-1:-1;23357:9:1;;23260:112::o;24073:401::-;24275:2;24257:21;;;24314:2;24294:18;;;24287:30;24353:34;24348:2;24333:18;;24326:62;-1:-1:-1;;;24419:2:1;24404:18;;24397:35;24464:3;24449:19;;24073:401::o;24884:414::-;25086:2;25068:21;;;25125:2;25105:18;;;25098:30;25164:34;25159:2;25144:18;;25137:62;-1:-1:-1;;;25230:2:1;25215:18;;25208:48;25288:3;25273:19;;24884:414::o;26443:489::-;-1:-1:-1;;;;;26712:15:1;;;26694:34;;26764:15;;26759:2;26744:18;;26737:43;26811:2;26796:18;;26789:34;;;26859:3;26854:2;26839:18;;26832:31;;;26637:4;;26880:46;;26906:19;;26898:6;26880:46;:::i;:::-;26872:54;26443:489;-1:-1:-1;;;;;;26443:489:1:o;26937:249::-;27006:6;27059:2;27047:9;27038:7;27034:23;27030:32;27027:52;;;27075:1;27072;27065:12;27027:52;27107:9;27101:16;27126:30;27150:5;27126:30;:::i;27191:127::-;27252:10;27247:3;27243:20;27240:1;27233:31;27283:4;27280:1;27273:15;27307:4;27304:1;27297:15

Swarm Source

ipfs://6840ac3a4ede9365ff4180f3c8e8e83b90c00cf7dace48724788e6aa9b8eb3e2
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.