ETH Price: $3,275.28 (+0.91%)
Gas: 2 Gwei

Token

GoulieNFT (GOLE)
 

Overview

Max Total Supply

0 GOLE

Holders

509

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Filtered by Token Holder
weslay.eth
Balance
5 GOLE
0xafBa3199e32cA024A34c7bAc82ee432E78f6Bf62
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:
GhoulieNFT

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-10-03
*/

// File: utils.sol



// File: @openzeppelin/contracts/utils/cryptography/draft-EIP712.sol

pragma solidity ^0.8.0;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
    /* solhint-disable var-name-mixedcase */
    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
    uint256 private immutable _CACHED_CHAIN_ID;

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;

    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        bytes32 typeHash = keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
        _CACHED_CHAIN_ID = block.chainid;
        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(
            typeHash,
            hashedName,
            hashedVersion
        );
        _TYPE_HASH = typeHash;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (block.chainid == _CACHED_CHAIN_ID) {
            return _CACHED_DOMAIN_SEPARATOR;
        } else {
            return
                _buildDomainSeparator(
                    _TYPE_HASH,
                    _HASHED_NAME,
                    _HASHED_VERSION
                );
        }
    }

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    typeHash,
                    nameHash,
                    versionHash,
                    block.chainid,
                    address(this)
                )
            );
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash)
        internal
        view
        virtual
        returns (bytes32)
    {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }
}

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

pragma solidity ^0.8.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature)
        internal
        pure
        returns (address, RecoverError)
    {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature)
        internal
        pure
        returns (address)
    {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s;
        uint8 v;
        assembly {
            s := and(
                vs,
                0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
            )
            v := add(shr(255, vs), 27)
        }
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (
            uint256(s) >
            0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0
        ) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash)
        internal
        pure
        returns (bytes32)
    {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return
            keccak256(
                abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)
            );
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash)
        internal
        pure
        returns (bytes32)
    {
        return
            keccak256(
                abi.encodePacked("\x19\x01", domainSeparator, structHash)
            );
    }
}

// File: @openzeppelin/contracts/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/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`, 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 be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

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

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

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

    /**
     * @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 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);

    /**
     * @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;
}

// File: @openzeppelin/contracts/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/utils/introspection/ERC165.sol

pragma solidity ^0.8.0;

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

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

pragma solidity ^0.8.0;

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

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

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

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

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: balance query for the zero address"
        );
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        address owner = _owners[tokenId];
        require(
            owner != address(0),
            "ERC721: owner query for nonexistent token"
        );
        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)
    {
        require(
            _exists(tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );

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

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

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public 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 owner nor approved for all"
        );

        _approve(to, tokenId);
    }

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

        return _tokenApprovals[tokenId];
    }

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

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    /**
     * @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 of token that is not own"
        );
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

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

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

        emit Transfer(from, to, tokenId);
    }

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

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

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

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

pragma solidity ^0.8.0;

/**
 * @dev ERC721 token with storage based token URI management.
 */
abstract contract ERC721URIStorage is ERC721 {
    using Strings for uint256;

    // Optional mapping for token URIs
    mapping(uint256 => string) private _tokenURIs;

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        require(
            _exists(tokenId),
            "ERC721URIStorage: URI query for nonexistent token"
        );

        string memory _tokenURI = _tokenURIs[tokenId];
        string memory base = _baseURI();

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }

        return super.tokenURI(tokenId);
    }

    /**
     * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _setTokenURI(uint256 tokenId, string memory _tokenURI)
        internal
        virtual
    {
        require(
            _exists(tokenId),
            "ERC721URIStorage: URI set of nonexistent token"
        );
        _tokenURIs[tokenId] = _tokenURI;
    }

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

        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }
    }
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: @openzeppelin/contracts/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 `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(
        bytes32 indexed role,
        bytes32 indexed previousAdminRole,
        bytes32 indexed newAdminRole
    );

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account)
        external
        view
        returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

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

pragma solidity ^0.8.0;

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

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

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account)
        public
        view
        override
        returns (bool)
    {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account)
        public
        virtual
        override
        onlyRole(getRoleAdmin(role))
    {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account)
        public
        virtual
        override
        onlyRole(getRoleAdmin(role))
    {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account)
        public
        virtual
        override
    {
        require(
            account == _msgSender(),
            "AccessControl: can only renounce roles for self"
        );

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    function _grantRole(bytes32 role, address account) private {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    function _revokeRole(bytes32 role, address account) private {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

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 Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        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: GhoulieNFT.sol

// File: GhoulieNFT.sol

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2; // required to accept structs as function parameters


contract GhoulieNFT is ERC721URIStorage, EIP712, AccessControl, Ownable {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    string private constant SIGNING_DOMAIN = "LazyNFT-Voucher";
    string private constant SIGNATURE_VERSION = "1";

    // Map for storing URIs of NFTs
    mapping(uint256 => string) private _tokenURIs;
    
    // Maximum number of Ghoulies that can be minted ever
    uint256 public MAX_RANGE = 10001;
    
    // Maximum number of Ghoulies that can be redeemed by public
    uint256 public MAX_PUBLIC_RANGE = 9902; // 9900 + 2 special ghoulies
    
    // Presale start and end indicator
    bool private _presale = true; // true for 24 hours
    
    // Base URI of Ghoulie NFTs
    string private _CbaseURI;
    
    // All presale redeemed Ghoulies will have a single CID
    string private _presaleCID;
    
    // Maximum number of Ghoulies that can be sold in presale
    uint256 public presaleLimit = 2000;
    
    // Maximum number of Ghoulies that can be redeemed by a single address in presale
    uint256 public presaleRedemptionLimit = 5;
    
    // Maximum number of Ghoulies that can be redeemed by a single address ever
    uint256 public redemptionLimit = 25;
    
    string private _coffinURI;

    bool private _extPresale = true; //true for 24 hours + 2 hours
    
    // Presale counter
    uint256 private _presaleRange;

    // State variable for storing the latest minted toke id
    uint256 public currentTokenID;

    // withdrawal address were all the funds will be debited
    address payable withdrawalAddress =
        payable(0x55463096D572D6D89554603B8366561ADa382159);

    mapping(address => uint256) pendingWithdrawals;

    constructor(address payable minter)
        ERC721("GoulieNFT", "GOLE")
        EIP712(SIGNING_DOMAIN, SIGNATURE_VERSION)
    {
        _setupRole(MINTER_ROLE, minter);
        _CbaseURI = "https://ipfs.io/ipfs/";
        _coffinURI = "bafkreifzyndzi52omxpdfxegd23csnxswqtwixf4y4hw5rcemo7fskkrwu";
        _presaleRange = 0;
        currentTokenID = 0;

        // mint 3 special ghoulies
        ownerMint(
            7479,
            "bafkreigp4vba4wffnyvcjfe5ts5novumnih55s476fzknevqsm6r4uutoi"
        );
        ownerMint(
            9811,
            "bafkreiadmljofpfannzkksik3i6v35pu63tc2kkphg3gjjz7fk4y52v5au"
        );
        ownerMint(
            10001,
            "bafkreihqy5b2kf4uphndsckmcpefzy426pvmao6yuborzuuiswrcfig3ey"
        );
    }

    /// @notice Represents an un-minted NFT, which has not yet been recorded into the blockchain. A signed voucher can be redeemed for a real NFT using the redeem function.
    struct NFTVoucher {
        // @notice The id of the token to be redeemed. Must be unique - if another token with this ID already exists, the redeem function will revert.
        bool presale;
        // @notice The minimum price (in wei) that the NFT creator is willing to accept for the initial sale of this NFT.
        uint256 minPrice;
        // @notice The metadata URI to associate with this token.
        string cid;
        // @notice the EIP-712 signature of all other fields in the NFTVoucher struct. For a voucher to be valid, it must be signed by an account with the MINTER_ROLE.
        bytes signature;
    }

    function baseURI() public view returns (string memory) {
        return _CbaseURI;
    }

    function presaleStatus() public view returns (bool) {
        return _presale;
    }

    function presaleCID() public view returns (string memory) {
        return _presaleCID;
    }

    function presaleRange() public view returns (uint256) {
        return _presaleRange;
    }

    function extPresaleStatus() public view returns (bool) {
        return _extPresale;
    }

    function switchPresale() public onlyOwner {
        require(presaleStatus(), "Presale has already ended");
        _presale = false;
    }

    function switchExtPresale() public onlyOwner {
        require(!presaleStatus(), "Presale has not ended yet");
        require(
            bytes(presaleCID()).length > 0,
            "Presale CID has not been set yet"
        );
        require(extPresaleStatus(), "Extended presale has already ended");
        _extPresale = false;
    }

    function setMaxPublicRange(uint256 _maxRange) public onlyOwner {
        require(
            _maxRange <= MAX_RANGE,
            "Max_PUBLIC_RANGE cannot exceed MAX_RANGE"
        );
        MAX_PUBLIC_RANGE = _maxRange;
    }

    function setMaxRange(uint256 _maxRange) public onlyOwner {
        MAX_RANGE = _maxRange;
    }

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

    function setPresaleCID(string memory newPresaleCID) public onlyOwner {
        require(
            !presaleStatus(),
            "Cannot set the presale CID during the presale"
        );
        _presaleCID = newPresaleCID;
    }

    function setPresaleLimit(uint256 _presaleLimit) public onlyOwner {
        require(presaleStatus(), "Presale has already ended");
        presaleLimit = _presaleLimit;
    }

    function setPresaleRedemptionLimit(uint256 _limit) public onlyOwner {
        require(presaleStatus(), "Presale has ended");
        presaleRedemptionLimit = _limit;
    }

    function setRedemptionLimit(uint256 _limit) public onlyOwner {
        require(
            _limit <= MAX_PUBLIC_RANGE,
            "Redemption limit cannot be more than MAX_PUBLIC_RANGE"
        );
        redemptionLimit = _limit;
    }

    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        require(_exists(tokenId), "Query for non existent token");
        if (presaleStatus()) {
            return string(abi.encodePacked(baseURI(), _coffinURI));
        } else if (extPresaleStatus() && tokenId <= presaleRange()) {
            return string(abi.encodePacked(baseURI(), _coffinURI));
        } else if (tokenId <= presaleRange()) {
            string memory uri = string(
                abi.encodePacked(
                    baseURI(),
                    presaleCID(),
                    "/",
                    Strings.toString(tokenId),
                    ".json"
                )
            );
            return uri;
        } else {
            return string(abi.encodePacked(baseURI(), _tokenURIs[tokenId]));
        }
    }
    
    // Special function for setting the URI of special ghoulies
    // @notice This is critical function, should be used carefully
    function ownerSetURI(uint256 tokenId, string memory uri) public onlyOwner {
        require(
            tokenId > presaleRange(),
            "Uri cannot be set for Presale tokens"
        );
        require(tokenId <= MAX_RANGE, "Token id out of MAX_RANGE");
        require(_exists(tokenId), "Cannot set the uri for non-existent token");
        _tokenURIs[tokenId] = uri;
    }

    // special function for minting special ghoulies
    // CRITICAL: Only Owner can call this to prevent any hazard
    function ownerMint(uint256 tokenId, string memory cid) public onlyOwner {
        require(
            tokenId <= MAX_RANGE,
            "Max range for minting the NFTs has been reached"
        );
        require(
            tokenId > MAX_PUBLIC_RANGE || tokenId == 7479 || tokenId == 9811,
            "Owner minting is only allowed above MAX_PUBLIC_RANGE"
        );
        _mint(withdrawalAddress, tokenId);
        _tokenURIs[tokenId] = cid;
    }

    // special function for minting special ghoulies
    // CRITICAL: Only Owner can call this to prevent any hazard
    function ownerBatchMint(uint256[] memory ids, string[] memory cids)
        public
        onlyOwner
    {
        require(
            ids.length == cids.length,
            "ids length does not match cids length"
        );
        for (uint256 i = 0; i < ids.length; i++) {
            ownerMint(ids[i], cids[i]);
        }
    }

    /// @notice allows the user to redeem NFTs in batch
    /// payments and funds are handled here
    /// Wrapper for _redeem
    function redeem(
        uint256 tokenCount,
        address redeemer,
        NFTVoucher[] calldata vouchers
    ) public payable {
        require(redeemer != address(0), "Null address not allowed");
        require(
            tokenCount == vouchers.length,
            "token count and Vouchers length do not match"
        );

        uint256 balance = balanceOf(_msgSender());
        if (presaleStatus()) {
            require(
                balance + tokenCount <= presaleRedemptionLimit,
                string(
                    abi.encodePacked(
                        "Redeemer can only redeem ",
                        Strings.toString(presaleRedemptionLimit - balance),
                        " more tokens in presale"
                    )
                )
            );
        } else {
            require(
                balance + tokenCount <= redemptionLimit,
                string(
                    abi.encodePacked(
                        "Redeemer can only redeem ",
                        Strings.toString(redemptionLimit - balance),
                        " more tokens"
                    )
                )
            );
        }

        uint256 totalAmount = 0;
        for (uint256 i = 0; i < tokenCount; i++) {
            _redeem(redeemer, vouchers[i]);
            totalAmount = totalAmount + vouchers[i].minPrice;
        }

        // check if the total vlaue sent is enough to cover the min prices of all the tokens
        require(
            msg.value >= totalAmount,
            "Insufficient funds for the transaction"
        );
        pendingWithdrawals[withdrawalAddress] += msg.value;
    }

    /// @notice Transfers all pending withdrawal balance to the caller. Reverts if the caller is not an authorized minter.
    function withdraw() public {
        require(_msgSender() == withdrawalAddress, "Unauthorized withdrawal");

        // IMPORTANT: casting msg.sender to a payable address is only safe if ALL members of the minter role are payable addresses.
        address payable receiver = withdrawalAddress;

        uint256 amount = pendingWithdrawals[receiver];
        // zero account before transfer to prevent re-entrancy attack
        pendingWithdrawals[receiver] = 0;
        receiver.transfer(amount);
    }

    /// @notice Retuns the amount of Ether available to the caller to withdraw.
    function availableToWithdraw() public view returns (uint256) {
        return pendingWithdrawals[msg.sender];
    }
    
    
    // Sets the URIs for all the Ghoulies
    function _setURI(uint256 tokenId, string memory cid) internal virtual {
        require(
            _exists(tokenId),
            "Setting URI for non-existent token not allowed"
        );
        require(
            bytes(_tokenURIs[tokenId]).length == 0,
            "This token's URI already exists"
        );
        if (!presaleStatus() || tokenId > presaleRange()) {
            _tokenURIs[tokenId] = cid;
        }
    }
    
    /// @notice Redeems an NFTVoucher for an actual NFT, creating it in the process.
    /// @param redeemer The address of the account which will receive the NFT upon success.
    /// @param voucher A signed NFTVoucher that describes the NFT to be redeemed.
    function _redeem(address redeemer, NFTVoucher calldata voucher)
        internal
        virtual
    {
        // Check if the complete range is sold
        require(
            getNextTokenID() <= MAX_PUBLIC_RANGE,
            "Complete range sold out"
        );

        // make sure signature is valid and get the address of the signer
        address signer = _verify(voucher);

        // make sure that the signer is authorized to mint NFTs
        require(
            hasRole(MINTER_ROLE, signer),
            "Signature invalid or unauthorized"
        );

        // first assign the token to the signer, to establish provenance on-chain
        if (getNextTokenID() > presaleLimit) {
            require(
                !presaleStatus(),
                "Presale sold out, You cannot buy until the presale ends"
            );
        }

        // check if the presale is over and the function is recieving voucher.presale == true
        if (!presaleStatus()) {
            require(!voucher.presale, "Voucher is invalid: Presale has ended");
        }

        uint256 tokenId = getNextTokenID();

        _incrementTokenTypeId();
        if (presaleStatus()) {
            _incrementPresaleRange();
        }
        _mint(signer, tokenId);
        _setURI(tokenId, voucher.cid);

        // transfer the token to the redeemer
        _transfer(signer, redeemer, tokenId);
    }

    /// @notice Returns a hash of the given NFTVoucher, prepared using EIP712 typed data hashing rules.
    /// @param voucher An NFTVoucher to hash.
    function _hash(NFTVoucher calldata voucher)
        internal
        view
        returns (bytes32)
    {
        return
            _hashTypedDataV4(
                keccak256(
                    abi.encode(
                        keccak256(
                            "NFTVoucher(bool presale,uint256 minPrice,string cid)"
                        ),
                        voucher.presale,
                        voucher.minPrice,
                        keccak256(bytes(voucher.cid))
                    )
                )
            );
    }

    /// @notice Returns the chain id of the current blockchain.
    /// @dev This is used to workaround an issue with ganache returning different values from the on-chain chainid() function and
    ///  the eth_chainId RPC method. See https://github.com/protocol/nft-website/issues/121 for context.
    function getChainID() external view returns (uint256) {
        uint256 id;
        assembly {
            id := chainid()
        }
        return id;
    }

    /// @notice Verifies the signature for a given NFTVoucher, returning the address of the signer.
    /// @dev Will revert if the signature is invalid. Does not verify that the signer is authorized to mint NFTs.
    /// @param voucher An NFTVoucher describing an unminted NFT.
    function _verify(NFTVoucher calldata voucher)
        internal
        view
        returns (address)
    {
        bytes32 digest = _hash(voucher);
        return ECDSA.recover(digest, voucher.signature);
    }

    function getNextTokenID() public view returns (uint256) {
        if (_exists(currentTokenID + 1)) {
            return currentTokenID + 2;
        }
        return currentTokenID + 1;
    }

    /**
     * @dev increments the value of _currentTokenID
     */
    function _incrementTokenTypeId() private {
        require(
            currentTokenID <= MAX_PUBLIC_RANGE,
            "Max range has been reached"
        );
        if (_exists(currentTokenID + 1)) {
            currentTokenID += 2;
        } else {
            currentTokenID++;
        }
    }

    function _incrementPresaleRange() private {
        require(presaleRange() <= presaleLimit, "Presale sold out");
        if (_exists(currentTokenID + 1)) {
            _presaleRange += 2;
        } else {
            _presaleRange++;
        }
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(AccessControl, ERC721)
        returns (bool)
    {
        return
            ERC721.supportsInterface(interfaceId) ||
            AccessControl.supportsInterface(interfaceId);
    }

    function contractURI() public pure returns (string memory) {
        return
            "https://gateway.pinata.cloud/ipfs/QmXNv9ApVynHdT72XQnBmD87MU2HWyEvyJyqcvWjd9Z9Jo";
    }

    // Function to receive Ether. msg.data must be empty
    receive() external payable {}

    // Fallback function is called when msg.data is not empty
    fallback() external payable {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address payable","name":"minter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","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"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PUBLIC_RANGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_RANGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":[],"name":"availableToWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"currentTokenID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extPresaleStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"getChainID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextTokenID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","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":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"string[]","name":"cids","type":"string[]"}],"name":"ownerBatchMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"cid","type":"string"}],"name":"ownerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"uri","type":"string"}],"name":"ownerSetURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"presaleCID","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleRange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleRedemptionLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenCount","type":"uint256"},{"internalType":"address","name":"redeemer","type":"address"},{"components":[{"internalType":"bool","name":"presale","type":"bool"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"string","name":"cid","type":"string"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct GhoulieNFT.NFTVoucher[]","name":"vouchers","type":"tuple[]"}],"name":"redeem","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"redemptionLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxRange","type":"uint256"}],"name":"setMaxPublicRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxRange","type":"uint256"}],"name":"setMaxRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newPresaleCID","type":"string"}],"name":"setPresaleCID","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_presaleLimit","type":"uint256"}],"name":"setPresaleLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setPresaleRedemptionLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setRedemptionLimit","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":"switchExtPresale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"switchPresale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

610120604052612711600a556126ae600b55600c805460ff1990811660019081179092556107d0600f5560056010556019601155601380549091169091179055601680546001600160a01b0319167355463096d572d6d89554603b8366561ada3821591790553480156200007257600080fd5b50604051620046c9380380620046c9833981016040819052620000959162000797565b6040518060400160405280600f81526020016e2630bd3ca7232a16ab37bab1b432b960891b815250604051806040016040528060018152602001603160f81b8152506040518060400160405280600981526020016811dbdd5b1a5953919560ba1b81525060405180604001604052806004815260200163474f4c4560e01b81525081600090805190602001906200012e929190620006f1565b50805162000144906001906020840190620006f1565b5050825160209384012082519284019290922060c083815260e08290524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818a018190528183019890985260608101959095526080808601939093523085830152805180860390920182529390920190925280519401939093209092526101005250620001db3362000306565b620002077f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68262000358565b6040805180820190915260158082527f68747470733a2f2f697066732e696f2f697066732f000000000000000000000060209092019182526200024d91600d91620006f1565b506040518060600160405280603b815260200162004618603b913980516200027e91601291602090910190620006f1565b50600060148190556015556040805160608101909152603b808252620002b191611d3791620045dd602083013962000368565b620002d86126536040518060600160405280603b81526020016200468e603b913962000368565b620002ff6127116040518060600160405280603b815260200162004653603b913962000368565b506200082d565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b62000364828262000505565b5050565b6008546001600160a01b03163314620003c85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b600a54821115620004345760405162461bcd60e51b815260206004820152602f60248201527f4d61782072616e676520666f72206d696e74696e6720746865204e465473206860448201526e185cc81899595b881c995858da1959608a1b6064820152608401620003bf565b600b5482118062000446575081611d37145b8062000453575081612653145b620004c75760405162461bcd60e51b815260206004820152603460248201527f4f776e6572206d696e74696e67206973206f6e6c7920616c6c6f77656420616260448201527f6f7665204d41585f5055424c49435f52414e47450000000000000000000000006064820152608401620003bf565b601654620004df906001600160a01b031683620005a9565b600082815260096020908152604090912082516200050092840190620006f1565b505050565b60008281526007602090815260408083206001600160a01b038516845290915290205460ff16620003645760008281526007602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620005653390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6001600160a01b038216620006015760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401620003bf565b6000818152600260205260409020546001600160a01b031615620006685760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401620003bf565b6001600160a01b038216600090815260036020526040812080546001929062000693908490620007c9565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054620006ff90620007f0565b90600052602060002090601f0160209004810192826200072357600085556200076e565b82601f106200073e57805160ff19168380011785556200076e565b828001600101855582156200076e579182015b828111156200076e57825182559160200191906001019062000751565b506200077c92915062000780565b5090565b5b808211156200077c576000815560010162000781565b600060208284031215620007aa57600080fd5b81516001600160a01b0381168114620007c257600080fd5b9392505050565b60008219821115620007eb57634e487b7160e01b600052601160045260246000fd5b500190565b600181811c908216806200080557607f821691505b602082108114156200082757634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051613d6b620008726000396000612fbc0152600061300b01526000612fe601526000612f6a01526000612f930152613d6b6000f3fe6080604052600436106102df5760003560e01c806370a082311161017e578063c29ad3ff116100d3578063e322ad2b1161008f578063f09fbfed1161006c578063f09fbfed14610899578063f2fde38b146108af578063f371742d146108cf578063ffb29023146108ef57005b8063e322ad2b14610819578063e8a3d4851461083b578063e985e9c51461085057005b8063c29ad3ff1461075b578063c87b56dd14610770578063ca999c2114610790578063d5391393146107a5578063d547741f146107d9578063e18b1736146107f957005b806395d89b411161013a578063a22cb46511610117578063a22cb465146106ed578063acfb23551461070d578063b88d4fde14610725578063bb62115e1461074557005b806395d89b41146106ad5780639f30b426146106c2578063a217fddf146106d857005b806370a08231146105fa578063715018a61461061a5780637fd255f11461062f57806385da735a1461064f5780638da5cb5b1461066f57806391d148541461068d57005b80632f2ff15d1161023457806354f4c098116101f05780635a941ea2116101cd5780635a941ea2146105995780636352211e146105af578063635d72e0146105cf5780636c0360eb146105e557005b806354f4c0981461055157806355f804b314610566578063564b81ef1461058657005b80632f2ff15d146104b157806336568abe146104d15780633ccfd60b146104f157806342842e0e146105065780634a19811914610526578063525b3fe31461053b57005b806320d35b491161029b57806325e1ff721161027857806325e1ff72146104395780632605c9301461045957806328673698146104715780632c49f86a1461049157005b806320d35b49146103c957806323b872dd146103e9578063248a9ca31461040957005b806301ffc9a7146102e857806306fdde031461031d578063081812fc1461033f578063095ea7b314610377578063113507a6146103975780631566a483146103aa57005b366102e657005b005b3480156102f457600080fd5b506103086103033660046135b5565b61090f565b60405190151581526020015b60405180910390f35b34801561032957600080fd5b5061033261092f565b60405161031491906139ab565b34801561034b57600080fd5b5061035f61035a366004613579565b6109c1565b6040516001600160a01b039091168152602001610314565b34801561038357600080fd5b506102e6610392366004613474565b610a4e565b6102e66103a5366004613624565b610b64565b3480156103b657600080fd5b506014545b604051908152602001610314565b3480156103d557600080fd5b506102e66103e4366004613579565b610e19565b3480156103f557600080fd5b506102e6610404366004613392565b610e8e565b34801561041557600080fd5b506103bb610424366004613579565b60009081526007602052604090206001015490565b34801561044557600080fd5b506102e66104543660046136ae565b610ebf565b34801561046557600080fd5b5060135460ff16610308565b34801561047d57600080fd5b506102e661048c3660046135ef565b61101e565b34801561049d57600080fd5b506102e66104ac3660046136ae565b6110c8565b3480156104bd57600080fd5b506102e66104cc366004613592565b6111f8565b3480156104dd57600080fd5b506102e66104ec366004613592565b61121e565b3480156104fd57600080fd5b506102e6611298565b34801561051257600080fd5b506102e6610521366004613392565b611349565b34801561053257600080fd5b506103bb611364565b34801561054757600080fd5b506103bb600f5481565b34801561055d57600080fd5b506102e66113a3565b34801561057257600080fd5b506102e66105813660046135ef565b6114e1565b34801561059257600080fd5b50466103bb565b3480156105a557600080fd5b506103bb60115481565b3480156105bb57600080fd5b5061035f6105ca366004613579565b61151e565b3480156105db57600080fd5b506103bb600b5481565b3480156105f157600080fd5b50610332611595565b34801561060657600080fd5b506103bb610615366004613344565b6115a4565b34801561062657600080fd5b506102e661162b565b34801561063b57600080fd5b506102e661064a366004613579565b611661565b34801561065b57600080fd5b506102e661066a366004613579565b6116de565b34801561067b57600080fd5b506008546001600160a01b031661035f565b34801561069957600080fd5b506103086106a8366004613592565b61170d565b3480156106b957600080fd5b50610332611738565b3480156106ce57600080fd5b506103bb60105481565b3480156106e457600080fd5b506103bb600081565b3480156106f957600080fd5b506102e661070836600461344a565b611747565b34801561071957600080fd5b50600c5460ff16610308565b34801561073157600080fd5b506102e66107403660046133ce565b61180c565b34801561075157600080fd5b506103bb60155481565b34801561076757600080fd5b506102e6611844565b34801561077c57600080fd5b5061033261078b366004613579565b6118c8565b34801561079c57600080fd5b506103326119f6565b3480156107b157600080fd5b506103bb7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b3480156107e557600080fd5b506102e66107f4366004613592565b611a05565b34801561080557600080fd5b506102e661081436600461349e565b611a2b565b34801561082557600080fd5b50336000908152601760205260409020546103bb565b34801561084757600080fd5b50610332611b0e565b34801561085c57600080fd5b5061030861086b36600461335f565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b3480156108a557600080fd5b506103bb600a5481565b3480156108bb57600080fd5b506102e66108ca366004613344565b611b2e565b3480156108db57600080fd5b506102e66108ea366004613579565b611bc9565b3480156108fb57600080fd5b506102e661090a366004613579565b611c5b565b600061091a82611cfa565b80610929575061092982611d4a565b92915050565b60606000805461093e90613bf7565b80601f016020809104026020016040519081016040528092919081815260200182805461096a90613bf7565b80156109b75780601f1061098c576101008083540402835291602001916109b7565b820191906000526020600020905b81548152906001019060200180831161099a57829003601f168201915b5050505050905090565b60006109cc82611d6f565b610a325760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000610a598261151e565b9050806001600160a01b0316836001600160a01b03161415610ac75760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610a29565b336001600160a01b0382161480610ae35750610ae3813361086b565b610b555760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610a29565b610b5f8383611d8c565b505050565b6001600160a01b038316610bba5760405162461bcd60e51b815260206004820152601860248201527f4e756c6c2061646472657373206e6f7420616c6c6f77656400000000000000006044820152606401610a29565b838114610c1e5760405162461bcd60e51b815260206004820152602c60248201527f746f6b656e20636f756e7420616e6420566f756368657273206c656e6774682060448201526b0c8de40dcdee840dac2e8c6d60a31b6064820152608401610a29565b6000610c29336115a4565b9050610c37600c5460ff1690565b15610ca457601054610c498683613b52565b1115610c6182601054610c5c9190613b9d565b611dfa565b604051602001610c71919061383a565b60405160208183030381529060405290610c9e5760405162461bcd60e51b8152600401610a2991906139ab565b50610d03565b601154610cb18683613b52565b1115610cc482601154610c5c9190613b9d565b604051602001610cd491906138a2565b60405160208183030381529060405290610d015760405162461bcd60e51b8152600401610a2991906139ab565b505b6000805b86811015610d8257610d3c86868684818110610d2557610d25613ca3565b9050602002810190610d379190613add565b611f00565b848482818110610d4e57610d4e613ca3565b9050602002810190610d609190613add565b610d6e906020013583613b52565b915080610d7a81613c32565b915050610d07565b5080341015610de25760405162461bcd60e51b815260206004820152602660248201527f496e73756666696369656e742066756e647320666f7220746865207472616e7360448201526530b1ba34b7b760d11b6064820152608401610a29565b6016546001600160a01b031660009081526017602052604081208054349290610e0c908490613b52565b9091555050505050505050565b6008546001600160a01b03163314610e435760405162461bcd60e51b8152600401610a2990613a10565b600c5460ff16610e895760405162461bcd60e51b8152602060048201526011602482015270141c995cd85b19481a185cc8195b991959607a1b6044820152606401610a29565b601055565b610e983382612169565b610eb45760405162461bcd60e51b8152600401610a2990613a45565b610b5f83838361224f565b6008546001600160a01b03163314610ee95760405162461bcd60e51b8152600401610a2990613a10565b6014548211610f465760405162461bcd60e51b8152602060048201526024808201527f5572692063616e6e6f742062652073657420666f722050726573616c6520746f6044820152636b656e7360e01b6064820152608401610a29565b600a54821115610f985760405162461bcd60e51b815260206004820152601960248201527f546f6b656e206964206f7574206f66204d41585f52414e4745000000000000006044820152606401610a29565b610fa182611d6f565b610fff5760405162461bcd60e51b815260206004820152602960248201527f43616e6e6f7420736574207468652075726920666f72206e6f6e2d657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610a29565b60008281526009602090815260409091208251610b5f92840190613175565b6008546001600160a01b031633146110485760405162461bcd60e51b8152600401610a2990613a10565b600c5460ff16156110b15760405162461bcd60e51b815260206004820152602d60248201527f43616e6e6f7420736574207468652070726573616c652043494420647572696e60448201526c67207468652070726573616c6560981b6064820152608401610a29565b80516110c490600e906020840190613175565b5050565b6008546001600160a01b031633146110f25760405162461bcd60e51b8152600401610a2990613a10565b600a5482111561115c5760405162461bcd60e51b815260206004820152602f60248201527f4d61782072616e676520666f72206d696e74696e6720746865204e465473206860448201526e185cc81899595b881c995858da1959608a1b6064820152608401610a29565b600b5482118061116d575081611d37145b80611179575081612653145b6111e25760405162461bcd60e51b815260206004820152603460248201527f4f776e6572206d696e74696e67206973206f6e6c7920616c6c6f7765642061626044820152736f7665204d41585f5055424c49435f52414e474560601b6064820152608401610a29565b601654610fff906001600160a01b0316836123ef565b6000828152600760205260409020600101546112148133612522565b610b5f8383612586565b6001600160a01b038116331461128e5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610a29565b6110c4828261260c565b6016546001600160a01b0316336001600160a01b0316146112fb5760405162461bcd60e51b815260206004820152601760248201527f556e617574686f72697a6564207769746864726177616c0000000000000000006044820152606401610a29565b6016546001600160a01b031660008181526017602052604080822080549083905590519091839183156108fc0291849190818181858888f19350505050158015610b5f573d6000803e3d6000fd5b610b5f8383836040518060200160405280600081525061180c565b600061137d60155460016113789190613b52565b611d6f565b1561139557601554611390906002613b52565b905090565b601554611390906001613b52565b6008546001600160a01b031633146113cd5760405162461bcd60e51b8152600401610a2990613a10565b600c5460ff16156114205760405162461bcd60e51b815260206004820152601960248201527f50726573616c6520686173206e6f7420656e64656420796574000000000000006044820152606401610a29565b600061142a6119f6565b51116114785760405162461bcd60e51b815260206004820181905260248201527f50726573616c652043494420686173206e6f74206265656e20736574207965746044820152606401610a29565b60135460ff166114d55760405162461bcd60e51b815260206004820152602260248201527f457874656e6465642070726573616c652068617320616c726561647920656e64604482015261195960f21b6064820152608401610a29565b6013805460ff19169055565b6008546001600160a01b0316331461150b5760405162461bcd60e51b8152600401610a2990613a10565b80516110c490600d906020840190613175565b6000818152600260205260408120546001600160a01b0316806109295760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610a29565b6060600d805461093e90613bf7565b60006001600160a01b03821661160f5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610a29565b506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b031633146116555760405162461bcd60e51b8152600401610a2990613a10565b61165f6000612673565b565b6008546001600160a01b0316331461168b5760405162461bcd60e51b8152600401610a2990613a10565b600c5460ff166116d95760405162461bcd60e51b8152602060048201526019602482015278141c995cd85b19481a185cc8185b1c9958591e48195b991959603a1b6044820152606401610a29565b600f55565b6008546001600160a01b031633146117085760405162461bcd60e51b8152600401610a2990613a10565b600a55565b60009182526007602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60606001805461093e90613bf7565b6001600160a01b0382163314156117a05760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a29565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6118163383612169565b6118325760405162461bcd60e51b8152600401610a2990613a45565b61183e848484846126c5565b50505050565b6008546001600160a01b0316331461186e5760405162461bcd60e51b8152600401610a2990613a10565b600c5460ff166118bc5760405162461bcd60e51b8152602060048201526019602482015278141c995cd85b19481a185cc8185b1c9958591e48195b991959603a1b6044820152606401610a29565b600c805460ff19169055565b60606118d382611d6f565b61191f5760405162461bcd60e51b815260206004820152601c60248201527f517565727920666f72206e6f6e206578697374656e7420746f6b656e000000006044820152606401610a29565b600c5460ff161561195b57611932611595565b6012604051602001611945929190613789565b6040516020818303038152906040529050919050565b60135460ff16801561196f57506014548211155b1561197c57611932611595565b60145482116119c957600061198f611595565b6119976119f6565b6119a085611dfa565b6040516020016119b293929190613727565b60408051601f198184030181529190529392505050565b6119d1611595565b600083815260096020908152604091829020915161194593929101613789565b919050565b6060600e805461093e90613bf7565b600082815260076020526040902060010154611a218133612522565b610b5f838361260c565b6008546001600160a01b03163314611a555760405162461bcd60e51b8152600401610a2990613a10565b8051825114611ab45760405162461bcd60e51b815260206004820152602560248201527f696473206c656e67746820646f6573206e6f74206d617463682063696473206c6044820152640cadccee8d60db1b6064820152608401610a29565b60005b8251811015610b5f57611afc838281518110611ad557611ad5613ca3565b6020026020010151838381518110611aef57611aef613ca3565b60200260200101516110c8565b80611b0681613c32565b915050611ab7565b6060604051806080016040528060508152602001613ce660509139905090565b6008546001600160a01b03163314611b585760405162461bcd60e51b8152600401610a2990613a10565b6001600160a01b038116611bbd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a29565b611bc681612673565b50565b6008546001600160a01b03163314611bf35760405162461bcd60e51b8152600401610a2990613a10565b600a54811115611c565760405162461bcd60e51b815260206004820152602860248201527f4d61785f5055424c49435f52414e47452063616e6e6f7420657863656564204d60448201526741585f52414e474560c01b6064820152608401610a29565b600b55565b6008546001600160a01b03163314611c855760405162461bcd60e51b8152600401610a2990613a10565b600b54811115611cf55760405162461bcd60e51b815260206004820152603560248201527f526564656d7074696f6e206c696d69742063616e6e6f74206265206d6f7265206044820152747468616e204d41585f5055424c49435f52414e474560581b6064820152608401610a29565b601155565b60006001600160e01b031982166380ac58cd60e01b1480611d2b57506001600160e01b03198216635b5e139f60e01b145b8061092957506301ffc9a760e01b6001600160e01b0319831614610929565b60006001600160e01b03198216637965db0b60e01b1480610929575061092982611cfa565b6000908152600260205260409020546001600160a01b0316151590565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611dc18261151e565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b606081611e1e5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611e485780611e3281613c32565b9150611e419050600a83613b6a565b9150611e22565b60008167ffffffffffffffff811115611e6357611e63613cb9565b6040519080825280601f01601f191660200182016040528015611e8d576020820181803683370190505b5090505b8415611ef857611ea2600183613b9d565b9150611eaf600a86613c4d565b611eba906030613b52565b60f81b818381518110611ecf57611ecf613ca3565b60200101906001600160f81b031916908160001a905350611ef1600a86613b6a565b9450611e91565b949350505050565b600b54611f0b611364565b1115611f595760405162461bcd60e51b815260206004820152601760248201527f436f6d706c6574652072616e676520736f6c64206f75740000000000000000006044820152606401610a29565b6000611f64826126f8565b9050611f907f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68261170d565b611fe65760405162461bcd60e51b815260206004820152602160248201527f5369676e617475726520696e76616c6964206f7220756e617574686f72697a656044820152601960fa1b6064820152608401610a29565b600f54611ff1611364565b111561207057600c5460ff16156120705760405162461bcd60e51b815260206004820152603760248201527f50726573616c6520736f6c64206f75742c20596f752063616e6e6f742062757960448201527f20756e74696c207468652070726573616c6520656e64730000000000000000006064820152608401610a29565b600c5460ff166120e257612087602083018361355e565b156120e25760405162461bcd60e51b815260206004820152602560248201527f566f756368657220697320696e76616c69643a2050726573616c652068617320604482015264195b99195960da1b6064820152608401610a29565b60006120ec611364565b90506120f6612758565b600c5460ff1615612109576121096127f8565b61211382826123ef565b61215e816121246040860186613a96565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061287992505050565b61183e82858361224f565b600061217482611d6f565b6121d55760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a29565b60006121e08361151e565b9050806001600160a01b0316846001600160a01b0316148061221b5750836001600160a01b0316612210846109c1565b6001600160a01b0316145b80611ef857506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff16611ef8565b826001600160a01b03166122628261151e565b6001600160a01b0316146122ca5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610a29565b6001600160a01b03821661232c5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610a29565b612337600082611d8c565b6001600160a01b0383166000908152600360205260408120805460019290612360908490613b9d565b90915550506001600160a01b038216600090815260036020526040812080546001929061238e908490613b52565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6001600160a01b0382166124455760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a29565b61244e81611d6f565b1561249b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a29565b6001600160a01b03821660009081526003602052604081208054600192906124c4908490613b52565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b61252c828261170d565b6110c457612544816001600160a01b03166014612984565b61254f836020612984565b6040516020016125609291906138f9565b60408051601f198184030181529082905262461bcd60e51b8252610a29916004016139ab565b612590828261170d565b6110c45760008281526007602090815260408083206001600160a01b03851684529091529020805460ff191660011790556125c83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b612616828261170d565b156110c45760008281526007602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6126d084848461224f565b6126dc84848484612b20565b61183e5760405162461bcd60e51b8152600401610a29906139be565b60008061270483612c2d565b9050612751816127176060860186613a96565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612cc992505050565b9392505050565b600b5460155411156127ac5760405162461bcd60e51b815260206004820152601a60248201527f4d61782072616e676520686173206265656e20726561636865640000000000006044820152606401610a29565b6127be60155460016113789190613b52565b156127e1576002601560008282546127d69190613b52565b9091555061165f9050565b601580549060006127f183613c32565b9190505550565b600f54601454111561283f5760405162461bcd60e51b815260206004820152601060248201526f141c995cd85b19481cdbdb19081bdd5d60821b6044820152606401610a29565b61285160155460016113789190613b52565b15612869576002601460008282546127d69190613b52565b601480549060006127f183613c32565b61288282611d6f565b6128e55760405162461bcd60e51b815260206004820152602e60248201527f53657474696e672055524920666f72206e6f6e2d6578697374656e7420746f6b60448201526d195b881b9bdd08185b1b1bddd95960921b6064820152608401610a29565b600082815260096020526040902080546128fe90613bf7565b15905061294d5760405162461bcd60e51b815260206004820152601f60248201527f5468697320746f6b656e27732055524920616c726561647920657869737473006044820152606401610a29565b600c5460ff161580612960575060145482115b156110c45760008281526009602090815260409091208251610b5f92840190613175565b60606000612993836002613b7e565b61299e906002613b52565b67ffffffffffffffff8111156129b6576129b6613cb9565b6040519080825280601f01601f1916602001820160405280156129e0576020820181803683370190505b509050600360fc1b816000815181106129fb576129fb613ca3565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110612a2a57612a2a613ca3565b60200101906001600160f81b031916908160001a9053506000612a4e846002613b7e565b612a59906001613b52565b90505b6001811115612ad1576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612a8d57612a8d613ca3565b1a60f81b828281518110612aa357612aa3613ca3565b60200101906001600160f81b031916908160001a90535060049490941c93612aca81613be0565b9050612a5c565b5083156127515760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a29565b60006001600160a01b0384163b15612c2257604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612b6490339089908890889060040161396e565b602060405180830381600087803b158015612b7e57600080fd5b505af1925050508015612bae575060408051601f3d908101601f19168201909252612bab918101906135d2565b60015b612c08573d808015612bdc576040519150601f19603f3d011682016040523d82523d6000602084013e612be1565b606091505b508051612c005760405162461bcd60e51b8152600401610a29906139be565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611ef8565b506001949350505050565b60006109297f9f67b1c61b2089e39f7d98615073c7968c47137301ed9686045ee416419fe8a1612c60602085018561355e565b6020850135612c726040870187613a96565b604051612c80929190613717565b604051908190038120612cae9493929160200193845291151560208401526040830152606082015260800190565b60405160208183030381529060405280519060200120612ced565b6000806000612cd88585612d3b565b91509150612ce581612dab565b509392505050565b6000610929612cfa612f66565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b600080825160411415612d725760208301516040840151606085015160001a612d6687828585613059565b94509450505050612da4565b825160401415612d9c5760208301516040840151612d91868383613146565b935093505050612da4565b506000905060025b9250929050565b6000816004811115612dbf57612dbf613c8d565b1415612dc85750565b6001816004811115612ddc57612ddc613c8d565b1415612e2a5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610a29565b6002816004811115612e3e57612e3e613c8d565b1415612e8c5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610a29565b6003816004811115612ea057612ea0613c8d565b1415612ef95760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610a29565b6004816004811115612f0d57612f0d613c8d565b1415611bc65760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610a29565b60007f0000000000000000000000000000000000000000000000000000000000000000461415612fb557507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613090575060009050600361313d565b8460ff16601b141580156130a857508460ff16601c14155b156130b9575060009050600461313d565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561310d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166131365760006001925092505061313d565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b0161316787828885613059565b935093505050935093915050565b82805461318190613bf7565b90600052602060002090601f0160209004810192826131a357600085556131e9565b82601f106131bc57805160ff19168380011785556131e9565b828001600101855582156131e9579182015b828111156131e95782518255916020019190600101906131ce565b506131f59291506131f9565b5090565b5b808211156131f557600081556001016131fa565b600067ffffffffffffffff83111561322857613228613cb9565b61323b601f8401601f1916602001613afd565b905082815283838301111561324f57600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b03811681146119f157600080fd5b600082601f83011261328e57600080fd5b813560206132a361329e83613b2e565b613afd565b80838252828201915082860187848660051b89010111156132c357600080fd5b6000805b8681101561330657823567ffffffffffffffff8111156132e5578283fd5b6132f38b88838d0101613324565b86525093850193918501916001016132c7565b509198975050505050505050565b803580151581146119f157600080fd5b600082601f83011261333557600080fd5b6127518383356020850161320e565b60006020828403121561335657600080fd5b61275182613266565b6000806040838503121561337257600080fd5b61337b83613266565b915061338960208401613266565b90509250929050565b6000806000606084860312156133a757600080fd5b6133b084613266565b92506133be60208501613266565b9150604084013590509250925092565b600080600080608085870312156133e457600080fd5b6133ed85613266565b93506133fb60208601613266565b925060408501359150606085013567ffffffffffffffff81111561341e57600080fd5b8501601f8101871361342f57600080fd5b61343e8782356020840161320e565b91505092959194509250565b6000806040838503121561345d57600080fd5b61346683613266565b915061338960208401613314565b6000806040838503121561348757600080fd5b61349083613266565b946020939093013593505050565b600080604083850312156134b157600080fd5b823567ffffffffffffffff808211156134c957600080fd5b818501915085601f8301126134dd57600080fd5b813560206134ed61329e83613b2e565b8083825282820191508286018a848660051b890101111561350d57600080fd5b600096505b84871015613530578035835260019690960195918301918301613512565b509650508601359250508082111561354757600080fd5b506135548582860161327d565b9150509250929050565b60006020828403121561357057600080fd5b61275182613314565b60006020828403121561358b57600080fd5b5035919050565b600080604083850312156135a557600080fd5b8235915061338960208401613266565b6000602082840312156135c757600080fd5b813561275181613ccf565b6000602082840312156135e457600080fd5b815161275181613ccf565b60006020828403121561360157600080fd5b813567ffffffffffffffff81111561361857600080fd5b611ef884828501613324565b6000806000806060858703121561363a57600080fd5b8435935061364a60208601613266565b9250604085013567ffffffffffffffff8082111561366757600080fd5b818701915087601f83011261367b57600080fd5b81358181111561368a57600080fd5b8860208260051b850101111561369f57600080fd5b95989497505060200194505050565b600080604083850312156136c157600080fd5b82359150602083013567ffffffffffffffff8111156136df57600080fd5b61355485828601613324565b60008151808452613703816020860160208601613bb4565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b60008451613739818460208901613bb4565b84519083019061374d818360208901613bb4565b602f60f81b9101908152835161376a816001840160208801613bb4565b64173539b7b760d91b6001929091019182015260060195945050505050565b60008351602061379c8285838901613bb4565b845491840191600090600181811c90808316806137ba57607f831692505b8583108114156137d857634e487b7160e01b85526022600452602485fd5b8080156137ec57600181146137fd5761382a565b60ff1985168852838801955061382a565b60008b81526020902060005b858110156138225781548a820152908401908801613809565b505083880195505b50939a9950505050505050505050565b7802932b232b2b6b2b91031b0b71037b7363c903932b232b2b69603d1b81526000825161386e816019850160208701613bb4565b7f206d6f726520746f6b656e7320696e2070726573616c650000000000000000006019939091019283015250603001919050565b7802932b232b2b6b2b91031b0b71037b7363c903932b232b2b69603d1b8152600082516138d6816019850160208701613bb4565b6b206d6f726520746f6b656e7360a01b6019939091019283015250602501919050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613931816017850160208801613bb4565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613962816028840160208801613bb4565b01602801949350505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906139a1908301846136eb565b9695505050505050565b60208152600061275160208301846136eb565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6000808335601e19843603018112613aad57600080fd5b83018035915067ffffffffffffffff821115613ac857600080fd5b602001915036819003821315612da457600080fd5b60008235607e19833603018112613af357600080fd5b9190910192915050565b604051601f8201601f1916810167ffffffffffffffff81118282101715613b2657613b26613cb9565b604052919050565b600067ffffffffffffffff821115613b4857613b48613cb9565b5060051b60200190565b60008219821115613b6557613b65613c61565b500190565b600082613b7957613b79613c77565b500490565b6000816000190483118215151615613b9857613b98613c61565b500290565b600082821015613baf57613baf613c61565b500390565b60005b83811015613bcf578181015183820152602001613bb7565b8381111561183e5750506000910152565b600081613bef57613bef613c61565b506000190190565b600181811c90821680613c0b57607f821691505b60208210811415613c2c57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415613c4657613c46613c61565b5060010190565b600082613c5c57613c5c613c77565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b031981168114611bc657600080fdfe68747470733a2f2f676174657761792e70696e6174612e636c6f75642f697066732f516d584e7639417056796e486454373258516e426d4438374d55324857794576794a79716376576a64395a394a6fa264697066735822122051577486d4206fa29ad4687374b8ab5f398e33f2ae64dcc3ee0d44967c26d5b464736f6c634300080700336261666b726569677034766261347766666e7976636a6665357473356e6f76756d6e6968353573343736667a6b6e657671736d3672347575746f696261666b726569667a796e647a6935326f6d7870646678656764323363736e7873777174776978663479346877357263656d6f3766736b6b7277756261666b7265696871793562326b66347570686e6473636b6d637065667a7934323670766d616f367975626f727a757569737772636669673365796261666b72656961646d6c6a6f667066616e6e7a6b6b73696b336936763335707536337463326b6b70686733676a6a7a37666b34793532763561750000000000000000000000003600ac1f03480774f25f937c1e3fb2f9e043d214

Deployed Bytecode

0x6080604052600436106102df5760003560e01c806370a082311161017e578063c29ad3ff116100d3578063e322ad2b1161008f578063f09fbfed1161006c578063f09fbfed14610899578063f2fde38b146108af578063f371742d146108cf578063ffb29023146108ef57005b8063e322ad2b14610819578063e8a3d4851461083b578063e985e9c51461085057005b8063c29ad3ff1461075b578063c87b56dd14610770578063ca999c2114610790578063d5391393146107a5578063d547741f146107d9578063e18b1736146107f957005b806395d89b411161013a578063a22cb46511610117578063a22cb465146106ed578063acfb23551461070d578063b88d4fde14610725578063bb62115e1461074557005b806395d89b41146106ad5780639f30b426146106c2578063a217fddf146106d857005b806370a08231146105fa578063715018a61461061a5780637fd255f11461062f57806385da735a1461064f5780638da5cb5b1461066f57806391d148541461068d57005b80632f2ff15d1161023457806354f4c098116101f05780635a941ea2116101cd5780635a941ea2146105995780636352211e146105af578063635d72e0146105cf5780636c0360eb146105e557005b806354f4c0981461055157806355f804b314610566578063564b81ef1461058657005b80632f2ff15d146104b157806336568abe146104d15780633ccfd60b146104f157806342842e0e146105065780634a19811914610526578063525b3fe31461053b57005b806320d35b491161029b57806325e1ff721161027857806325e1ff72146104395780632605c9301461045957806328673698146104715780632c49f86a1461049157005b806320d35b49146103c957806323b872dd146103e9578063248a9ca31461040957005b806301ffc9a7146102e857806306fdde031461031d578063081812fc1461033f578063095ea7b314610377578063113507a6146103975780631566a483146103aa57005b366102e657005b005b3480156102f457600080fd5b506103086103033660046135b5565b61090f565b60405190151581526020015b60405180910390f35b34801561032957600080fd5b5061033261092f565b60405161031491906139ab565b34801561034b57600080fd5b5061035f61035a366004613579565b6109c1565b6040516001600160a01b039091168152602001610314565b34801561038357600080fd5b506102e6610392366004613474565b610a4e565b6102e66103a5366004613624565b610b64565b3480156103b657600080fd5b506014545b604051908152602001610314565b3480156103d557600080fd5b506102e66103e4366004613579565b610e19565b3480156103f557600080fd5b506102e6610404366004613392565b610e8e565b34801561041557600080fd5b506103bb610424366004613579565b60009081526007602052604090206001015490565b34801561044557600080fd5b506102e66104543660046136ae565b610ebf565b34801561046557600080fd5b5060135460ff16610308565b34801561047d57600080fd5b506102e661048c3660046135ef565b61101e565b34801561049d57600080fd5b506102e66104ac3660046136ae565b6110c8565b3480156104bd57600080fd5b506102e66104cc366004613592565b6111f8565b3480156104dd57600080fd5b506102e66104ec366004613592565b61121e565b3480156104fd57600080fd5b506102e6611298565b34801561051257600080fd5b506102e6610521366004613392565b611349565b34801561053257600080fd5b506103bb611364565b34801561054757600080fd5b506103bb600f5481565b34801561055d57600080fd5b506102e66113a3565b34801561057257600080fd5b506102e66105813660046135ef565b6114e1565b34801561059257600080fd5b50466103bb565b3480156105a557600080fd5b506103bb60115481565b3480156105bb57600080fd5b5061035f6105ca366004613579565b61151e565b3480156105db57600080fd5b506103bb600b5481565b3480156105f157600080fd5b50610332611595565b34801561060657600080fd5b506103bb610615366004613344565b6115a4565b34801561062657600080fd5b506102e661162b565b34801561063b57600080fd5b506102e661064a366004613579565b611661565b34801561065b57600080fd5b506102e661066a366004613579565b6116de565b34801561067b57600080fd5b506008546001600160a01b031661035f565b34801561069957600080fd5b506103086106a8366004613592565b61170d565b3480156106b957600080fd5b50610332611738565b3480156106ce57600080fd5b506103bb60105481565b3480156106e457600080fd5b506103bb600081565b3480156106f957600080fd5b506102e661070836600461344a565b611747565b34801561071957600080fd5b50600c5460ff16610308565b34801561073157600080fd5b506102e66107403660046133ce565b61180c565b34801561075157600080fd5b506103bb60155481565b34801561076757600080fd5b506102e6611844565b34801561077c57600080fd5b5061033261078b366004613579565b6118c8565b34801561079c57600080fd5b506103326119f6565b3480156107b157600080fd5b506103bb7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b3480156107e557600080fd5b506102e66107f4366004613592565b611a05565b34801561080557600080fd5b506102e661081436600461349e565b611a2b565b34801561082557600080fd5b50336000908152601760205260409020546103bb565b34801561084757600080fd5b50610332611b0e565b34801561085c57600080fd5b5061030861086b36600461335f565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b3480156108a557600080fd5b506103bb600a5481565b3480156108bb57600080fd5b506102e66108ca366004613344565b611b2e565b3480156108db57600080fd5b506102e66108ea366004613579565b611bc9565b3480156108fb57600080fd5b506102e661090a366004613579565b611c5b565b600061091a82611cfa565b80610929575061092982611d4a565b92915050565b60606000805461093e90613bf7565b80601f016020809104026020016040519081016040528092919081815260200182805461096a90613bf7565b80156109b75780601f1061098c576101008083540402835291602001916109b7565b820191906000526020600020905b81548152906001019060200180831161099a57829003601f168201915b5050505050905090565b60006109cc82611d6f565b610a325760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000610a598261151e565b9050806001600160a01b0316836001600160a01b03161415610ac75760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610a29565b336001600160a01b0382161480610ae35750610ae3813361086b565b610b555760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610a29565b610b5f8383611d8c565b505050565b6001600160a01b038316610bba5760405162461bcd60e51b815260206004820152601860248201527f4e756c6c2061646472657373206e6f7420616c6c6f77656400000000000000006044820152606401610a29565b838114610c1e5760405162461bcd60e51b815260206004820152602c60248201527f746f6b656e20636f756e7420616e6420566f756368657273206c656e6774682060448201526b0c8de40dcdee840dac2e8c6d60a31b6064820152608401610a29565b6000610c29336115a4565b9050610c37600c5460ff1690565b15610ca457601054610c498683613b52565b1115610c6182601054610c5c9190613b9d565b611dfa565b604051602001610c71919061383a565b60405160208183030381529060405290610c9e5760405162461bcd60e51b8152600401610a2991906139ab565b50610d03565b601154610cb18683613b52565b1115610cc482601154610c5c9190613b9d565b604051602001610cd491906138a2565b60405160208183030381529060405290610d015760405162461bcd60e51b8152600401610a2991906139ab565b505b6000805b86811015610d8257610d3c86868684818110610d2557610d25613ca3565b9050602002810190610d379190613add565b611f00565b848482818110610d4e57610d4e613ca3565b9050602002810190610d609190613add565b610d6e906020013583613b52565b915080610d7a81613c32565b915050610d07565b5080341015610de25760405162461bcd60e51b815260206004820152602660248201527f496e73756666696369656e742066756e647320666f7220746865207472616e7360448201526530b1ba34b7b760d11b6064820152608401610a29565b6016546001600160a01b031660009081526017602052604081208054349290610e0c908490613b52565b9091555050505050505050565b6008546001600160a01b03163314610e435760405162461bcd60e51b8152600401610a2990613a10565b600c5460ff16610e895760405162461bcd60e51b8152602060048201526011602482015270141c995cd85b19481a185cc8195b991959607a1b6044820152606401610a29565b601055565b610e983382612169565b610eb45760405162461bcd60e51b8152600401610a2990613a45565b610b5f83838361224f565b6008546001600160a01b03163314610ee95760405162461bcd60e51b8152600401610a2990613a10565b6014548211610f465760405162461bcd60e51b8152602060048201526024808201527f5572692063616e6e6f742062652073657420666f722050726573616c6520746f6044820152636b656e7360e01b6064820152608401610a29565b600a54821115610f985760405162461bcd60e51b815260206004820152601960248201527f546f6b656e206964206f7574206f66204d41585f52414e4745000000000000006044820152606401610a29565b610fa182611d6f565b610fff5760405162461bcd60e51b815260206004820152602960248201527f43616e6e6f7420736574207468652075726920666f72206e6f6e2d657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610a29565b60008281526009602090815260409091208251610b5f92840190613175565b6008546001600160a01b031633146110485760405162461bcd60e51b8152600401610a2990613a10565b600c5460ff16156110b15760405162461bcd60e51b815260206004820152602d60248201527f43616e6e6f7420736574207468652070726573616c652043494420647572696e60448201526c67207468652070726573616c6560981b6064820152608401610a29565b80516110c490600e906020840190613175565b5050565b6008546001600160a01b031633146110f25760405162461bcd60e51b8152600401610a2990613a10565b600a5482111561115c5760405162461bcd60e51b815260206004820152602f60248201527f4d61782072616e676520666f72206d696e74696e6720746865204e465473206860448201526e185cc81899595b881c995858da1959608a1b6064820152608401610a29565b600b5482118061116d575081611d37145b80611179575081612653145b6111e25760405162461bcd60e51b815260206004820152603460248201527f4f776e6572206d696e74696e67206973206f6e6c7920616c6c6f7765642061626044820152736f7665204d41585f5055424c49435f52414e474560601b6064820152608401610a29565b601654610fff906001600160a01b0316836123ef565b6000828152600760205260409020600101546112148133612522565b610b5f8383612586565b6001600160a01b038116331461128e5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610a29565b6110c4828261260c565b6016546001600160a01b0316336001600160a01b0316146112fb5760405162461bcd60e51b815260206004820152601760248201527f556e617574686f72697a6564207769746864726177616c0000000000000000006044820152606401610a29565b6016546001600160a01b031660008181526017602052604080822080549083905590519091839183156108fc0291849190818181858888f19350505050158015610b5f573d6000803e3d6000fd5b610b5f8383836040518060200160405280600081525061180c565b600061137d60155460016113789190613b52565b611d6f565b1561139557601554611390906002613b52565b905090565b601554611390906001613b52565b6008546001600160a01b031633146113cd5760405162461bcd60e51b8152600401610a2990613a10565b600c5460ff16156114205760405162461bcd60e51b815260206004820152601960248201527f50726573616c6520686173206e6f7420656e64656420796574000000000000006044820152606401610a29565b600061142a6119f6565b51116114785760405162461bcd60e51b815260206004820181905260248201527f50726573616c652043494420686173206e6f74206265656e20736574207965746044820152606401610a29565b60135460ff166114d55760405162461bcd60e51b815260206004820152602260248201527f457874656e6465642070726573616c652068617320616c726561647920656e64604482015261195960f21b6064820152608401610a29565b6013805460ff19169055565b6008546001600160a01b0316331461150b5760405162461bcd60e51b8152600401610a2990613a10565b80516110c490600d906020840190613175565b6000818152600260205260408120546001600160a01b0316806109295760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610a29565b6060600d805461093e90613bf7565b60006001600160a01b03821661160f5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610a29565b506001600160a01b031660009081526003602052604090205490565b6008546001600160a01b031633146116555760405162461bcd60e51b8152600401610a2990613a10565b61165f6000612673565b565b6008546001600160a01b0316331461168b5760405162461bcd60e51b8152600401610a2990613a10565b600c5460ff166116d95760405162461bcd60e51b8152602060048201526019602482015278141c995cd85b19481a185cc8185b1c9958591e48195b991959603a1b6044820152606401610a29565b600f55565b6008546001600160a01b031633146117085760405162461bcd60e51b8152600401610a2990613a10565b600a55565b60009182526007602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60606001805461093e90613bf7565b6001600160a01b0382163314156117a05760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a29565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6118163383612169565b6118325760405162461bcd60e51b8152600401610a2990613a45565b61183e848484846126c5565b50505050565b6008546001600160a01b0316331461186e5760405162461bcd60e51b8152600401610a2990613a10565b600c5460ff166118bc5760405162461bcd60e51b8152602060048201526019602482015278141c995cd85b19481a185cc8185b1c9958591e48195b991959603a1b6044820152606401610a29565b600c805460ff19169055565b60606118d382611d6f565b61191f5760405162461bcd60e51b815260206004820152601c60248201527f517565727920666f72206e6f6e206578697374656e7420746f6b656e000000006044820152606401610a29565b600c5460ff161561195b57611932611595565b6012604051602001611945929190613789565b6040516020818303038152906040529050919050565b60135460ff16801561196f57506014548211155b1561197c57611932611595565b60145482116119c957600061198f611595565b6119976119f6565b6119a085611dfa565b6040516020016119b293929190613727565b60408051601f198184030181529190529392505050565b6119d1611595565b600083815260096020908152604091829020915161194593929101613789565b919050565b6060600e805461093e90613bf7565b600082815260076020526040902060010154611a218133612522565b610b5f838361260c565b6008546001600160a01b03163314611a555760405162461bcd60e51b8152600401610a2990613a10565b8051825114611ab45760405162461bcd60e51b815260206004820152602560248201527f696473206c656e67746820646f6573206e6f74206d617463682063696473206c6044820152640cadccee8d60db1b6064820152608401610a29565b60005b8251811015610b5f57611afc838281518110611ad557611ad5613ca3565b6020026020010151838381518110611aef57611aef613ca3565b60200260200101516110c8565b80611b0681613c32565b915050611ab7565b6060604051806080016040528060508152602001613ce660509139905090565b6008546001600160a01b03163314611b585760405162461bcd60e51b8152600401610a2990613a10565b6001600160a01b038116611bbd5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a29565b611bc681612673565b50565b6008546001600160a01b03163314611bf35760405162461bcd60e51b8152600401610a2990613a10565b600a54811115611c565760405162461bcd60e51b815260206004820152602860248201527f4d61785f5055424c49435f52414e47452063616e6e6f7420657863656564204d60448201526741585f52414e474560c01b6064820152608401610a29565b600b55565b6008546001600160a01b03163314611c855760405162461bcd60e51b8152600401610a2990613a10565b600b54811115611cf55760405162461bcd60e51b815260206004820152603560248201527f526564656d7074696f6e206c696d69742063616e6e6f74206265206d6f7265206044820152747468616e204d41585f5055424c49435f52414e474560581b6064820152608401610a29565b601155565b60006001600160e01b031982166380ac58cd60e01b1480611d2b57506001600160e01b03198216635b5e139f60e01b145b8061092957506301ffc9a760e01b6001600160e01b0319831614610929565b60006001600160e01b03198216637965db0b60e01b1480610929575061092982611cfa565b6000908152600260205260409020546001600160a01b0316151590565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611dc18261151e565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b606081611e1e5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611e485780611e3281613c32565b9150611e419050600a83613b6a565b9150611e22565b60008167ffffffffffffffff811115611e6357611e63613cb9565b6040519080825280601f01601f191660200182016040528015611e8d576020820181803683370190505b5090505b8415611ef857611ea2600183613b9d565b9150611eaf600a86613c4d565b611eba906030613b52565b60f81b818381518110611ecf57611ecf613ca3565b60200101906001600160f81b031916908160001a905350611ef1600a86613b6a565b9450611e91565b949350505050565b600b54611f0b611364565b1115611f595760405162461bcd60e51b815260206004820152601760248201527f436f6d706c6574652072616e676520736f6c64206f75740000000000000000006044820152606401610a29565b6000611f64826126f8565b9050611f907f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68261170d565b611fe65760405162461bcd60e51b815260206004820152602160248201527f5369676e617475726520696e76616c6964206f7220756e617574686f72697a656044820152601960fa1b6064820152608401610a29565b600f54611ff1611364565b111561207057600c5460ff16156120705760405162461bcd60e51b815260206004820152603760248201527f50726573616c6520736f6c64206f75742c20596f752063616e6e6f742062757960448201527f20756e74696c207468652070726573616c6520656e64730000000000000000006064820152608401610a29565b600c5460ff166120e257612087602083018361355e565b156120e25760405162461bcd60e51b815260206004820152602560248201527f566f756368657220697320696e76616c69643a2050726573616c652068617320604482015264195b99195960da1b6064820152608401610a29565b60006120ec611364565b90506120f6612758565b600c5460ff1615612109576121096127f8565b61211382826123ef565b61215e816121246040860186613a96565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061287992505050565b61183e82858361224f565b600061217482611d6f565b6121d55760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a29565b60006121e08361151e565b9050806001600160a01b0316846001600160a01b0316148061221b5750836001600160a01b0316612210846109c1565b6001600160a01b0316145b80611ef857506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff16611ef8565b826001600160a01b03166122628261151e565b6001600160a01b0316146122ca5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610a29565b6001600160a01b03821661232c5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610a29565b612337600082611d8c565b6001600160a01b0383166000908152600360205260408120805460019290612360908490613b9d565b90915550506001600160a01b038216600090815260036020526040812080546001929061238e908490613b52565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6001600160a01b0382166124455760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a29565b61244e81611d6f565b1561249b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a29565b6001600160a01b03821660009081526003602052604081208054600192906124c4908490613b52565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b61252c828261170d565b6110c457612544816001600160a01b03166014612984565b61254f836020612984565b6040516020016125609291906138f9565b60408051601f198184030181529082905262461bcd60e51b8252610a29916004016139ab565b612590828261170d565b6110c45760008281526007602090815260408083206001600160a01b03851684529091529020805460ff191660011790556125c83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b612616828261170d565b156110c45760008281526007602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6126d084848461224f565b6126dc84848484612b20565b61183e5760405162461bcd60e51b8152600401610a29906139be565b60008061270483612c2d565b9050612751816127176060860186613a96565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612cc992505050565b9392505050565b600b5460155411156127ac5760405162461bcd60e51b815260206004820152601a60248201527f4d61782072616e676520686173206265656e20726561636865640000000000006044820152606401610a29565b6127be60155460016113789190613b52565b156127e1576002601560008282546127d69190613b52565b9091555061165f9050565b601580549060006127f183613c32565b9190505550565b600f54601454111561283f5760405162461bcd60e51b815260206004820152601060248201526f141c995cd85b19481cdbdb19081bdd5d60821b6044820152606401610a29565b61285160155460016113789190613b52565b15612869576002601460008282546127d69190613b52565b601480549060006127f183613c32565b61288282611d6f565b6128e55760405162461bcd60e51b815260206004820152602e60248201527f53657474696e672055524920666f72206e6f6e2d6578697374656e7420746f6b60448201526d195b881b9bdd08185b1b1bddd95960921b6064820152608401610a29565b600082815260096020526040902080546128fe90613bf7565b15905061294d5760405162461bcd60e51b815260206004820152601f60248201527f5468697320746f6b656e27732055524920616c726561647920657869737473006044820152606401610a29565b600c5460ff161580612960575060145482115b156110c45760008281526009602090815260409091208251610b5f92840190613175565b60606000612993836002613b7e565b61299e906002613b52565b67ffffffffffffffff8111156129b6576129b6613cb9565b6040519080825280601f01601f1916602001820160405280156129e0576020820181803683370190505b509050600360fc1b816000815181106129fb576129fb613ca3565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110612a2a57612a2a613ca3565b60200101906001600160f81b031916908160001a9053506000612a4e846002613b7e565b612a59906001613b52565b90505b6001811115612ad1576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110612a8d57612a8d613ca3565b1a60f81b828281518110612aa357612aa3613ca3565b60200101906001600160f81b031916908160001a90535060049490941c93612aca81613be0565b9050612a5c565b5083156127515760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610a29565b60006001600160a01b0384163b15612c2257604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612b6490339089908890889060040161396e565b602060405180830381600087803b158015612b7e57600080fd5b505af1925050508015612bae575060408051601f3d908101601f19168201909252612bab918101906135d2565b60015b612c08573d808015612bdc576040519150601f19603f3d011682016040523d82523d6000602084013e612be1565b606091505b508051612c005760405162461bcd60e51b8152600401610a29906139be565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611ef8565b506001949350505050565b60006109297f9f67b1c61b2089e39f7d98615073c7968c47137301ed9686045ee416419fe8a1612c60602085018561355e565b6020850135612c726040870187613a96565b604051612c80929190613717565b604051908190038120612cae9493929160200193845291151560208401526040830152606082015260800190565b60405160208183030381529060405280519060200120612ced565b6000806000612cd88585612d3b565b91509150612ce581612dab565b509392505050565b6000610929612cfa612f66565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b600080825160411415612d725760208301516040840151606085015160001a612d6687828585613059565b94509450505050612da4565b825160401415612d9c5760208301516040840151612d91868383613146565b935093505050612da4565b506000905060025b9250929050565b6000816004811115612dbf57612dbf613c8d565b1415612dc85750565b6001816004811115612ddc57612ddc613c8d565b1415612e2a5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610a29565b6002816004811115612e3e57612e3e613c8d565b1415612e8c5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610a29565b6003816004811115612ea057612ea0613c8d565b1415612ef95760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610a29565b6004816004811115612f0d57612f0d613c8d565b1415611bc65760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610a29565b60007f0000000000000000000000000000000000000000000000000000000000000001461415612fb557507f8e7a33d0bb5dc6e92e079e808dd6c8b25597d5bdf9ad60dcd0acdcd257d6529390565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527ff052f95a33109dff431ea69dec1a0c175842c11488c5ee2a81e41c1a7b77d09b828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613090575060009050600361313d565b8460ff16601b141580156130a857508460ff16601c14155b156130b9575060009050600461313d565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561310d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166131365760006001925092505061313d565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b0161316787828885613059565b935093505050935093915050565b82805461318190613bf7565b90600052602060002090601f0160209004810192826131a357600085556131e9565b82601f106131bc57805160ff19168380011785556131e9565b828001600101855582156131e9579182015b828111156131e95782518255916020019190600101906131ce565b506131f59291506131f9565b5090565b5b808211156131f557600081556001016131fa565b600067ffffffffffffffff83111561322857613228613cb9565b61323b601f8401601f1916602001613afd565b905082815283838301111561324f57600080fd5b828260208301376000602084830101529392505050565b80356001600160a01b03811681146119f157600080fd5b600082601f83011261328e57600080fd5b813560206132a361329e83613b2e565b613afd565b80838252828201915082860187848660051b89010111156132c357600080fd5b6000805b8681101561330657823567ffffffffffffffff8111156132e5578283fd5b6132f38b88838d0101613324565b86525093850193918501916001016132c7565b509198975050505050505050565b803580151581146119f157600080fd5b600082601f83011261333557600080fd5b6127518383356020850161320e565b60006020828403121561335657600080fd5b61275182613266565b6000806040838503121561337257600080fd5b61337b83613266565b915061338960208401613266565b90509250929050565b6000806000606084860312156133a757600080fd5b6133b084613266565b92506133be60208501613266565b9150604084013590509250925092565b600080600080608085870312156133e457600080fd5b6133ed85613266565b93506133fb60208601613266565b925060408501359150606085013567ffffffffffffffff81111561341e57600080fd5b8501601f8101871361342f57600080fd5b61343e8782356020840161320e565b91505092959194509250565b6000806040838503121561345d57600080fd5b61346683613266565b915061338960208401613314565b6000806040838503121561348757600080fd5b61349083613266565b946020939093013593505050565b600080604083850312156134b157600080fd5b823567ffffffffffffffff808211156134c957600080fd5b818501915085601f8301126134dd57600080fd5b813560206134ed61329e83613b2e565b8083825282820191508286018a848660051b890101111561350d57600080fd5b600096505b84871015613530578035835260019690960195918301918301613512565b509650508601359250508082111561354757600080fd5b506135548582860161327d565b9150509250929050565b60006020828403121561357057600080fd5b61275182613314565b60006020828403121561358b57600080fd5b5035919050565b600080604083850312156135a557600080fd5b8235915061338960208401613266565b6000602082840312156135c757600080fd5b813561275181613ccf565b6000602082840312156135e457600080fd5b815161275181613ccf565b60006020828403121561360157600080fd5b813567ffffffffffffffff81111561361857600080fd5b611ef884828501613324565b6000806000806060858703121561363a57600080fd5b8435935061364a60208601613266565b9250604085013567ffffffffffffffff8082111561366757600080fd5b818701915087601f83011261367b57600080fd5b81358181111561368a57600080fd5b8860208260051b850101111561369f57600080fd5b95989497505060200194505050565b600080604083850312156136c157600080fd5b82359150602083013567ffffffffffffffff8111156136df57600080fd5b61355485828601613324565b60008151808452613703816020860160208601613bb4565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b60008451613739818460208901613bb4565b84519083019061374d818360208901613bb4565b602f60f81b9101908152835161376a816001840160208801613bb4565b64173539b7b760d91b6001929091019182015260060195945050505050565b60008351602061379c8285838901613bb4565b845491840191600090600181811c90808316806137ba57607f831692505b8583108114156137d857634e487b7160e01b85526022600452602485fd5b8080156137ec57600181146137fd5761382a565b60ff1985168852838801955061382a565b60008b81526020902060005b858110156138225781548a820152908401908801613809565b505083880195505b50939a9950505050505050505050565b7802932b232b2b6b2b91031b0b71037b7363c903932b232b2b69603d1b81526000825161386e816019850160208701613bb4565b7f206d6f726520746f6b656e7320696e2070726573616c650000000000000000006019939091019283015250603001919050565b7802932b232b2b6b2b91031b0b71037b7363c903932b232b2b69603d1b8152600082516138d6816019850160208701613bb4565b6b206d6f726520746f6b656e7360a01b6019939091019283015250602501919050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613931816017850160208801613bb4565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351613962816028840160208801613bb4565b01602801949350505050565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906139a1908301846136eb565b9695505050505050565b60208152600061275160208301846136eb565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6000808335601e19843603018112613aad57600080fd5b83018035915067ffffffffffffffff821115613ac857600080fd5b602001915036819003821315612da457600080fd5b60008235607e19833603018112613af357600080fd5b9190910192915050565b604051601f8201601f1916810167ffffffffffffffff81118282101715613b2657613b26613cb9565b604052919050565b600067ffffffffffffffff821115613b4857613b48613cb9565b5060051b60200190565b60008219821115613b6557613b65613c61565b500190565b600082613b7957613b79613c77565b500490565b6000816000190483118215151615613b9857613b98613c61565b500290565b600082821015613baf57613baf613c61565b500390565b60005b83811015613bcf578181015183820152602001613bb7565b8381111561183e5750506000910152565b600081613bef57613bef613c61565b506000190190565b600181811c90821680613c0b57607f821691505b60208210811415613c2c57634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415613c4657613c46613c61565b5060010190565b600082613c5c57613c5c613c77565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b031981168114611bc657600080fdfe68747470733a2f2f676174657761792e70696e6174612e636c6f75642f697066732f516d584e7639417056796e486454373258516e426d4438374d55324857794576794a79716376576a64395a394a6fa264697066735822122051577486d4206fa29ad4687374b8ab5f398e33f2ae64dcc3ee0d44967c26d5b464736f6c63430008070033

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

0000000000000000000000003600ac1f03480774f25f937c1e3fb2f9e043d214

-----Decoded View---------------
Arg [0] : minter (address): 0x3600AC1F03480774f25F937c1E3Fb2f9e043d214

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000003600ac1f03480774f25f937c1e3fb2f9e043d214


Deployed Bytecode Sourcemap

63281:16358:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78951:301;;;;;;;;;;-1:-1:-1;78951:301:0;;;;;:::i;:::-;;:::i;:::-;;;13972:14:1;;13965:22;13947:41;;13935:2;13920:18;78951:301:0;;;;;;;;24974:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;26667:308::-;;;;;;;;;;-1:-1:-1;26667:308:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;13270:32:1;;;13252:51;;13240:2;13225:18;26667:308:0;13106:203:1;26190:411:0;;;;;;;;;;-1:-1:-1;26190:411:0;;;;;:::i;:::-;;:::i;71605:1706::-;;;;;;:::i;:::-;;:::i;66941:93::-;;;;;;;;;;-1:-1:-1;67013:13:0;;66941:93;;;14145:25:1;;;14133:2;14118:18;66941:93:0;13999:177:1;68519:174:0;;;;;;;;;;-1:-1:-1;68519:174:0;;;;;:::i;:::-;;:::i;27726:376::-;;;;;;;;;;-1:-1:-1;27726:376:0;;;;;:::i;:::-;;:::i;57254:123::-;;;;;;;;;;-1:-1:-1;57254:123:0;;;;;:::i;:::-;57320:7;57347:12;;;:6;:12;;;;;:22;;;;57254:123;70015:389;;;;;;;;;;-1:-1:-1;70015:389:0;;;;;:::i;:::-;;:::i;67042:92::-;;;;;;;;;;-1:-1:-1;67115:11:0;;;;67042:92;;68090:237;;;;;;;;;;-1:-1:-1;68090:237:0;;;;;:::i;:::-;;:::i;70531:465::-;;;;;;;;;;-1:-1:-1;70531:465:0;;;;;:::i;:::-;;:::i;57639:188::-;;;;;;;;;;-1:-1:-1;57639:188:0;;;;;:::i;:::-;;:::i;58769:287::-;;;;;;;;;;-1:-1:-1;58769:287:0;;;;;:::i;:::-;;:::i;73443:513::-;;;;;;;;;;;;;:::i;28173:185::-;;;;;;;;;;-1:-1:-1;28173:185:0;;;;;:::i;:::-;;:::i;78097:195::-;;;;;;;;;;;;;:::i;64230:34::-;;;;;;;;;;;;;;;;67291:347;;;;;;;;;;;;;:::i;67992:90::-;;;;;;;;;;-1:-1:-1;67992:90:0;;;;;:::i;:::-;;:::i;77418:163::-;;;;;;;;;;-1:-1:-1;77534:9:0;77418:163;;64499:35;;;;;;;;;;;;;;;;24581:326;;;;;;;;;;-1:-1:-1;24581:326:0;;;;;:::i;:::-;;:::i;63815:38::-;;;;;;;;;;;;;;;;66646:90;;;;;;;;;;;;;:::i;24224:295::-;;;;;;;;;;-1:-1:-1;24224:295:0;;;;;:::i;:::-;;:::i;62238:103::-;;;;;;;;;;;;;:::i;68335:176::-;;;;;;;;;;-1:-1:-1;68335:176:0;;;;;:::i;:::-;;:::i;67887:97::-;;;;;;;;;;-1:-1:-1;67887:97:0;;;;;:::i;:::-;;:::i;61587:87::-;;;;;;;;;;-1:-1:-1;61660:6:0;;-1:-1:-1;;;;;61660:6:0;61587:87;;56098:180;;;;;;;;;;-1:-1:-1;56098:180:0;;;;;:::i;:::-;;:::i;25143:104::-;;;;;;;;;;;;;:::i;64364:41::-;;;;;;;;;;;;;;;;55113:49;;;;;;;;;;-1:-1:-1;55113:49:0;55158:4;55113:49;;27047:327;;;;;;;;;;-1:-1:-1;27047:327:0;;;;;:::i;:::-;;:::i;66744:86::-;;;;;;;;;;-1:-1:-1;66814:8:0;;;;66744:86;;28429:365;;;;;;;;;;-1:-1:-1;28429:365:0;;;;;:::i;:::-;;:::i;64778:29::-;;;;;;;;;;;;;;;;67142:141;;;;;;;;;;;;;:::i;68953:917::-;;;;;;;;;;-1:-1:-1;68953:917:0;;;;;:::i;:::-;;:::i;66838:95::-;;;;;;;;;;;;;:::i;63360:62::-;;;;;;;;;;;;63398:24;63360:62;;58072:190;;;;;;;;;;-1:-1:-1;58072:190:0;;;;;:::i;:::-;;:::i;71123:343::-;;;;;;;;;;-1:-1:-1;71123:343:0;;;;;:::i;:::-;;:::i;74045:117::-;;;;;;;;;;-1:-1:-1;74143:10:0;74097:7;74124:30;;;:18;:30;;;;;;74045:117;;79260:180;;;;;;;;;;;;;:::i;27445:214::-;;;;;;;;;;-1:-1:-1;27445:214:0;;;;;:::i;:::-;-1:-1:-1;;;;;27616:25:0;;;27587:4;27616:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;27445:214;63704:32;;;;;;;;;;;;;;;;62496:238;;;;;;;;;;-1:-1:-1;62496:238:0;;;;;:::i;:::-;;:::i;67646:233::-;;;;;;;;;;-1:-1:-1;67646:233:0;;;;;:::i;:::-;;:::i;68701:244::-;;;;;;;;;;-1:-1:-1;68701:244:0;;;;;:::i;:::-;;:::i;78951:301::-;79104:4;79146:37;79171:11;79146:24;:37::i;:::-;:98;;;;79200:44;79232:11;79200:31;:44::i;:::-;79126:118;78951:301;-1:-1:-1;;78951:301:0:o;24974:100::-;25028:13;25061:5;25054:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24974:100;:::o;26667:308::-;26788:7;26835:16;26843:7;26835;:16::i;:::-;26813:110;;;;-1:-1:-1;;;26813:110:0;;27709:2:1;26813:110:0;;;27691:21:1;27748:2;27728:18;;;27721:30;27787:34;27767:18;;;27760:62;-1:-1:-1;;;27838:18:1;;;27831:42;27890:19;;26813:110:0;;;;;;;;;-1:-1:-1;26943:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;26943:24:0;;26667:308::o;26190:411::-;26271:13;26287:23;26302:7;26287:14;:23::i;:::-;26271:39;;26335:5;-1:-1:-1;;;;;26329:11:0;:2;-1:-1:-1;;;;;26329:11:0;;;26321:57;;;;-1:-1:-1;;;26321:57:0;;29611:2:1;26321:57:0;;;29593:21:1;29650:2;29630:18;;;29623:30;29689:34;29669:18;;;29662:62;-1:-1:-1;;;29740:18:1;;;29733:31;29781:19;;26321:57:0;29409:397:1;26321:57:0;20624:10;-1:-1:-1;;;;;26413:21:0;;;;:62;;-1:-1:-1;26438:37:0;26455:5;20624:10;27445:214;:::i;26438:37::-;26391:168;;;;-1:-1:-1;;;26391:168:0;;25699:2:1;26391:168:0;;;25681:21:1;25738:2;25718:18;;;25711:30;25777:34;25757:18;;;25750:62;25848:26;25828:18;;;25821:54;25892:19;;26391:168:0;25497:420:1;26391:168:0;26572:21;26581:2;26585:7;26572:8;:21::i;:::-;26260:341;26190:411;;:::o;71605:1706::-;-1:-1:-1;;;;;71759:22:0;;71751:59;;;;-1:-1:-1;;;71751:59:0;;31188:2:1;71751:59:0;;;31170:21:1;31227:2;31207:18;;;31200:30;31266:26;31246:18;;;31239:54;31310:18;;71751:59:0;30986:348:1;71751:59:0;71843:29;;;71821:123;;;;-1:-1:-1;;;71821:123:0;;20516:2:1;71821:123:0;;;20498:21:1;20555:2;20535:18;;;20528:30;20594:34;20574:18;;;20567:62;-1:-1:-1;;;20645:18:1;;;20638:42;20697:19;;71821:123:0;20314:408:1;71821:123:0;71957:15;71975:23;20624:10;24224:295;:::i;71975:23::-;71957:41;;72013:15;66814:8;;;;;66744:86;72013:15;72009:808;;;72095:22;;72071:20;72081:10;72071:7;:20;:::i;:::-;:46;;72262:50;72304:7;72279:22;;:32;;;;:::i;:::-;72262:16;:50::i;:::-;72165:222;;;;;;;;:::i;:::-;;;;;;;;;;;;;72045:376;;;;;-1:-1:-1;;;72045:376:0;;;;;;;;:::i;:::-;;72009:808;;;72504:15;;72480:20;72490:10;72480:7;:20;:::i;:::-;:39;;72664:43;72699:7;72681:15;;:25;;;;:::i;72664:43::-;72567:204;;;;;;;;:::i;:::-;;;;;;;;;;;;;72454:351;;;;;-1:-1:-1;;;72454:351:0;;;;;;;;:::i;:::-;;72009:808;72829:19;72868:9;72863:161;72887:10;72883:1;:14;72863:161;;;72919:30;72927:8;72937;;72946:1;72937:11;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;72919:7;:30::i;:::-;72992:8;;73001:1;72992:11;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;72978:34;;72992:20;;;72978:11;:34;:::i;:::-;72964:48;-1:-1:-1;72899:3:0;;;;:::i;:::-;;;;72863:161;;;;73165:11;73152:9;:24;;73130:112;;;;-1:-1:-1;;;73130:112:0;;33411:2:1;73130:112:0;;;33393:21:1;33450:2;33430:18;;;33423:30;33489:34;33469:18;;;33462:62;-1:-1:-1;;;33540:18:1;;;33533:36;33586:19;;73130:112:0;33209:402:1;73130:112:0;73272:17;;-1:-1:-1;;;;;73272:17:0;73253:37;;;;:18;:37;;;;;:50;;73294:9;;73253:37;:50;;73294:9;;73253:50;:::i;:::-;;;;-1:-1:-1;;;;;;;;71605:1706:0:o;68519:174::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;66814:8;;;;68598:45:::1;;;::::0;-1:-1:-1;;;68598:45:0;;16263:2:1;68598:45:0::1;::::0;::::1;16245:21:1::0;16302:2;16282:18;;;16275:30;-1:-1:-1;;;16321:18:1;;;16314:47;16378:18;;68598:45:0::1;16061:341:1::0;68598:45:0::1;68654:22;:31:::0;68519:174::o;27726:376::-;27935:41;20624:10;27968:7;27935:18;:41::i;:::-;27913:140;;;;-1:-1:-1;;;27913:140:0;;;;;;;:::i;:::-;28066:28;28076:4;28082:2;28086:7;28066:9;:28::i;70015:389::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;67013:13;;70122:7:::1;:24;70100:110;;;::::0;-1:-1:-1;;;70100:110:0;;31541:2:1;70100:110:0::1;::::0;::::1;31523:21:1::0;31580:2;31560:18;;;31553:30;31619:34;31599:18;;;31592:62;-1:-1:-1;;;31670:18:1;;;31663:34;31714:19;;70100:110:0::1;31339:400:1::0;70100:110:0::1;70240:9;;70229:7;:20;;70221:58;;;::::0;-1:-1:-1;;;70221:58:0;;31946:2:1;70221:58:0::1;::::0;::::1;31928:21:1::0;31985:2;31965:18;;;31958:30;32024:27;32004:18;;;31997:55;32069:18;;70221:58:0::1;31744:349:1::0;70221:58:0::1;70298:16;70306:7;70298;:16::i;:::-;70290:70;;;::::0;-1:-1:-1;;;70290:70:0;;22114:2:1;70290:70:0::1;::::0;::::1;22096:21:1::0;22153:2;22133:18;;;22126:30;22192:34;22172:18;;;22165:62;-1:-1:-1;;;22243:18:1;;;22236:39;22292:19;;70290:70:0::1;21912:405:1::0;70290:70:0::1;70371:19;::::0;;;:10:::1;:19;::::0;;;;;;;:25;;::::1;::::0;;::::1;::::0;::::1;:::i;68090:237::-:0;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;66814:8;;;;68192:16:::1;68170:111;;;::::0;-1:-1:-1;;;68170:111:0;;32997:2:1;68170:111:0::1;::::0;::::1;32979:21:1::0;33036:2;33016:18;;;33009:30;33075:34;33055:18;;;33048:62;-1:-1:-1;;;33126:18:1;;;33119:43;33179:19;;68170:111:0::1;32795:409:1::0;68170:111:0::1;68292:27:::0;;::::1;::::0;:11:::1;::::0;:27:::1;::::0;::::1;::::0;::::1;:::i;:::-;;68090:237:::0;:::o;70531:465::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;70647:9:::1;;70636:7;:20;;70614:117;;;::::0;-1:-1:-1;;;70614:117:0;;22524:2:1;70614:117:0::1;::::0;::::1;22506:21:1::0;22563:2;22543:18;;;22536:30;22602:34;22582:18;;;22575:62;-1:-1:-1;;;22653:18:1;;;22646:45;22708:19;;70614:117:0::1;22322:411:1::0;70614:117:0::1;70774:16;;70764:7;:26;:45;;;;70794:7;70805:4;70794:15;70764:45;:64;;;;70813:7;70824:4;70813:15;70764:64;70742:166;;;::::0;-1:-1:-1;;;70742:166:0;;17015:2:1;70742:166:0::1;::::0;::::1;16997:21:1::0;17054:2;17034:18;;;17027:30;17093:34;17073:18;;;17066:62;-1:-1:-1;;;17144:18:1;;;17137:50;17204:19;;70742:166:0::1;16813:416:1::0;70742:166:0::1;70925:17;::::0;70919:33:::1;::::0;-1:-1:-1;;;;;70925:17:0::1;70944:7:::0;70919:5:::1;:33::i;57639:188::-:0;57320:7;57347:12;;;:6;:12;;;;;:22;;;55604:30;55615:4;20624:10;55604;:30::i;:::-;57794:25:::1;57805:4;57811:7;57794:10;:25::i;58769:287::-:0;-1:-1:-1;;;;;58911:23:0;;20624:10;58911:23;58889:120;;;;-1:-1:-1;;;58889:120:0;;33818:2:1;58889:120:0;;;33800:21:1;33857:2;33837:18;;;33830:30;33896:34;33876:18;;;33869:62;-1:-1:-1;;;33947:18:1;;;33940:45;34002:19;;58889:120:0;33616:411:1;58889:120:0;59022:26;59034:4;59040:7;59022:11;:26::i;73443:513::-;73505:17;;-1:-1:-1;;;;;73505:17:0;20624:10;-1:-1:-1;;;;;73489:33:0;;73481:69;;;;-1:-1:-1;;;73481:69:0;;17797:2:1;73481:69:0;;;17779:21:1;17836:2;17816:18;;;17809:30;17875:25;17855:18;;;17848:53;17918:18;;73481:69:0;17595:347:1;73481:69:0;73723:17;;-1:-1:-1;;;;;73723:17:0;73696:24;73770:28;;;:18;:28;;;;;;;;73880:32;;;;73923:25;;73770:28;;73723:17;;73923:25;;;;;73770:28;;73923:25;;73696:24;73923:25;73770:28;73723:17;73923:25;;;;;;;;;;;;;;;;;;;28173:185;28311:39;28328:4;28334:2;28338:7;28311:39;;;;;;;;;;;;:16;:39::i;78097:195::-;78144:7;78168:27;78176:14;;78193:1;78176:18;;;;:::i;:::-;78168:7;:27::i;:::-;78164:85;;;78219:14;;:18;;78236:1;78219:18;:::i;:::-;78212:25;;78097:195;:::o;78164:85::-;78266:14;;:18;;78283:1;78266:18;:::i;67291:347::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;66814:8;;;;67355:16:::1;67347:54;;;::::0;-1:-1:-1;;;67347:54:0;;34234:2:1;67347:54:0::1;::::0;::::1;34216:21:1::0;34273:2;34253:18;;;34246:30;34312:27;34292:18;;;34285:55;34357:18;;67347:54:0::1;34032:349:1::0;67347:54:0::1;67463:1;67440:12;:10;:12::i;:::-;67434:26;:30;67412:112;;;::::0;-1:-1:-1;;;67412:112:0;;28479:2:1;67412:112:0::1;::::0;::::1;28461:21:1::0;;;28498:18;;;28491:30;28557:34;28537:18;;;28530:62;28609:18;;67412:112:0::1;28277:356:1::0;67412:112:0::1;67115:11:::0;;;;67535:65:::1;;;::::0;-1:-1:-1;;;67535:65:0;;18927:2:1;67535:65:0::1;::::0;::::1;18909:21:1::0;18966:2;18946:18;;;18939:30;19005:34;18985:18;;;18978:62;-1:-1:-1;;;19056:18:1;;;19049:32;19098:19;;67535:65:0::1;18725:398:1::0;67535:65:0::1;67611:11;:19:::0;;-1:-1:-1;;67611:19:0::1;::::0;;67291:347::o;67992:90::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;68059:15;;::::1;::::0;:9:::1;::::0;:15:::1;::::0;::::1;::::0;::::1;:::i;24581:326::-:0;24698:7;24739:16;;;:7;:16;;;;;;-1:-1:-1;;;;;24739:16:0;24788:19;24766:110;;;;-1:-1:-1;;;24766:110:0;;26535:2:1;24766:110:0;;;26517:21:1;26574:2;26554:18;;;26547:30;26613:34;26593:18;;;26586:62;-1:-1:-1;;;26664:18:1;;;26657:39;26713:19;;24766:110:0;26333:405:1;66646:90:0;66686:13;66719:9;66712:16;;;;;:::i;24224:295::-;24341:7;-1:-1:-1;;;;;24388:19:0;;24366:111;;;;-1:-1:-1;;;24366:111:0;;26124:2:1;24366:111:0;;;26106:21:1;26163:2;26143:18;;;26136:30;26202:34;26182:18;;;26175:62;-1:-1:-1;;;26253:18:1;;;26246:40;26303:19;;24366:111:0;25922:406:1;24366:111:0;-1:-1:-1;;;;;;24495:16:0;;;;;:9;:16;;;;;;;24224:295::o;62238:103::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;62303:30:::1;62330:1;62303:18;:30::i;:::-;62238:103::o:0;68335:176::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;66814:8;;;;68411:53:::1;;;::::0;-1:-1:-1;;;68411:53:0;;18573:2:1;68411:53:0::1;::::0;::::1;18555:21:1::0;18612:2;18592:18;;;18585:30;-1:-1:-1;;;18631:18:1;;;18624:55;18696:18;;68411:53:0::1;18371:349:1::0;68411:53:0::1;68475:12;:28:::0;68335:176::o;67887:97::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;67955:9:::1;:21:::0;67887:97::o;56098:180::-;56212:4;56241:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;56241:29:0;;;;;;;;;;;;;;;56098:180::o;25143:104::-;25199:13;25232:7;25225:14;;;;;:::i;27047:327::-;-1:-1:-1;;;;;27182:24:0;;20624:10;27182:24;;27174:62;;;;-1:-1:-1;;;27174:62:0;;23760:2:1;27174:62:0;;;23742:21:1;23799:2;23779:18;;;23772:30;23838:27;23818:18;;;23811:55;23883:18;;27174:62:0;23558:349:1;27174:62:0;20624:10;27249:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;27249:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;27249:53:0;;;;;;;;;;27318:48;;13947:41:1;;;27249:42:0;;20624:10;27318:48;;13920:18:1;27318:48:0;;;;;;;27047:327;;:::o;28429:365::-;28618:41;20624:10;28651:7;28618:18;:41::i;:::-;28596:140;;;;-1:-1:-1;;;28596:140:0;;;;;;;:::i;:::-;28747:39;28761:4;28767:2;28771:7;28780:5;28747:13;:39::i;:::-;28429:365;;;;:::o;67142:141::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;66814:8;;;;67195:53:::1;;;::::0;-1:-1:-1;;;67195:53:0;;18573:2:1;67195:53:0::1;::::0;::::1;18555:21:1::0;18612:2;18592:18;;;18585:30;-1:-1:-1;;;18631:18:1;;;18624:55;18696:18;;67195:53:0::1;18371:349:1::0;67195:53:0::1;67259:8;:16:::0;;-1:-1:-1;;67259:16:0::1;::::0;;67142:141::o;68953:917::-;69071:13;69110:16;69118:7;69110;:16::i;:::-;69102:57;;;;-1:-1:-1;;;69102:57:0;;28122:2:1;69102:57:0;;;28104:21:1;28161:2;28141:18;;;28134:30;28200;28180:18;;;28173:58;28248:18;;69102:57:0;27920:352:1;69102:57:0;66814:8;;;;69170:693;;;69237:9;:7;:9::i;:::-;69248:10;69220:39;;;;;;;;;:::i;:::-;;;;;;;;;;;;;69206:54;;68953:917;;;:::o;69170:693::-;67115:11;;;;69282:47;;;;-1:-1:-1;67013:13:0;;69304:7;:25;;69282:47;69278:585;;;69377:9;:7;:9::i;69278:585::-;67013:13;;69422:7;:25;69418:445;;69464:17;69548:9;:7;:9::i;:::-;69580:12;:10;:12::i;:::-;69641:25;69658:7;69641:16;:25::i;:::-;69509:206;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;69509:206:0;;;;;;;;;;68953:917;-1:-1:-1;;;68953:917:0:o;69418:445::-;69819:9;:7;:9::i;:::-;69830:19;;;;:10;:19;;;;;;;;;69802:48;;;;;69830:19;69802:48;;:::i;69418:445::-;68953:917;;;:::o;66838:95::-;66881:13;66914:11;66907:18;;;;;:::i;58072:190::-;57320:7;57347:12;;;:6;:12;;;;;:22;;;55604:30;55615:4;20624:10;55604;:30::i;:::-;58228:26:::1;58240:4;58246:7;58228:11;:26::i;71123:343::-:0;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;71278:4:::1;:11;71264:3;:10;:25;71242:112;;;::::0;-1:-1:-1;;;71242:112:0;;21286:2:1;71242:112:0::1;::::0;::::1;21268:21:1::0;21325:2;21305:18;;;21298:30;21364:34;21344:18;;;21337:62;-1:-1:-1;;;21415:18:1;;;21408:35;21460:19;;71242:112:0::1;21084:401:1::0;71242:112:0::1;71370:9;71365:94;71389:3;:10;71385:1;:14;71365:94;;;71421:26;71431:3;71435:1;71431:6;;;;;;;;:::i;:::-;;;;;;;71439:4;71444:1;71439:7;;;;;;;;:::i;:::-;;;;;;;71421:9;:26::i;:::-;71401:3:::0;::::1;::::0;::::1;:::i;:::-;;;;71365:94;;79260:180:::0;79304:13;79330:102;;;;;;;;;;;;;;;;;;;79260:180;:::o;62496:238::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;62599:22:0;::::1;62577:110;;;::::0;-1:-1:-1;;;62577:110:0;;20109:2:1;62577:110:0::1;::::0;::::1;20091:21:1::0;20148:2;20128:18;;;20121:30;20187:34;20167:18;;;20160:62;-1:-1:-1;;;20238:18:1;;;20231:36;20284:19;;62577:110:0::1;19907:402:1::0;62577:110:0::1;62698:28;62717:8;62698:18;:28::i;:::-;62496:238:::0;:::o;67646:233::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;67755:9:::1;;67742;:22;;67720:112;;;::::0;-1:-1:-1;;;67720:112:0;;25290:2:1;67720:112:0::1;::::0;::::1;25272:21:1::0;25329:2;25309:18;;;25302:30;25368:34;25348:18;;;25341:62;-1:-1:-1;;;25419:18:1;;;25412:38;25467:19;;67720:112:0::1;25088:404:1::0;67720:112:0::1;67843:16;:28:::0;67646:233::o;68701:244::-;61660:6;;-1:-1:-1;;;;;61660:6:0;20624:10;61807:23;61799:68;;;;-1:-1:-1;;;61799:68:0;;;;;;;:::i;:::-;68805:16:::1;;68795:6;:26;;68773:129;;;::::0;-1:-1:-1;;;68773:129:0;;21692:2:1;68773:129:0::1;::::0;::::1;21674:21:1::0;21731:2;21711:18;;;21704:30;21770:34;21750:18;;;21743:62;-1:-1:-1;;;21821:18:1;;;21814:51;21882:19;;68773:129:0::1;21490:417:1::0;68773:129:0::1;68913:15;:24:::0;68701:244::o;23805:355::-;23952:4;-1:-1:-1;;;;;;23994:40:0;;-1:-1:-1;;;23994:40:0;;:105;;-1:-1:-1;;;;;;;24051:48:0;;-1:-1:-1;;;24051:48:0;23994:105;:158;;;-1:-1:-1;;;;;;;;;;21709:40:0;;;24116:36;21550:207;55726:280;55856:4;-1:-1:-1;;;;;;55898:47:0;;-1:-1:-1;;;55898:47:0;;:100;;;55962:36;55986:11;55962:23;:36::i;30341:127::-;30406:4;30430:16;;;:7;:16;;;;;;-1:-1:-1;;;;;30430:16:0;:30;;;30341:127::o;34464:174::-;34539:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;34539:29:0;-1:-1:-1;;;;;34539:29:0;;;;;;;;:24;;34593:23;34539:24;34593:14;:23::i;:::-;-1:-1:-1;;;;;34584:46:0;;;;;;;;;;;34464:174;;:::o;48778:723::-;48834:13;49055:10;49051:53;;-1:-1:-1;;49082:10:0;;;;;;;;;;;;-1:-1:-1;;;49082:10:0;;;;;48778:723::o;49051:53::-;49129:5;49114:12;49170:78;49177:9;;49170:78;;49203:8;;;;:::i;:::-;;-1:-1:-1;49226:10:0;;-1:-1:-1;49234:2:0;49226:10;;:::i;:::-;;;49170:78;;;49258:19;49290:6;49280:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49280:17:0;;49258:39;;49308:154;49315:10;;49308:154;;49342:11;49352:1;49342:11;;:::i;:::-;;-1:-1:-1;49411:10:0;49419:2;49411:5;:10;:::i;:::-;49398:24;;:2;:24;:::i;:::-;49385:39;;49368:6;49375;49368:14;;;;;;;;:::i;:::-;;;;:56;-1:-1:-1;;;;;49368:56:0;;;;;;;;-1:-1:-1;49439:11:0;49448:2;49439:11;;:::i;:::-;;;49308:154;;;49486:6;48778:723;-1:-1:-1;;;;48778:723:0:o;74940:1438::-;75145:16;;75125;:14;:16::i;:::-;:36;;75103:109;;;;-1:-1:-1;;;75103:109:0;;32300:2:1;75103:109:0;;;32282:21:1;32339:2;32319:18;;;32312:30;32378:25;32358:18;;;32351:53;32421:18;;75103:109:0;32098:347:1;75103:109:0;75300:14;75317:16;75325:7;75317;:16::i;:::-;75300:33;;75433:28;63398:24;75454:6;75433:7;:28::i;:::-;75411:111;;;;-1:-1:-1;;;75411:111:0;;30013:2:1;75411:111:0;;;29995:21:1;30052:2;30032:18;;;30025:30;30091:34;30071:18;;;30064:62;-1:-1:-1;;;30142:18:1;;;30135:31;30183:19;;75411:111:0;29811:397:1;75411:111:0;75641:12;;75622:16;:14;:16::i;:::-;:31;75618:197;;;66814:8;;;;75696:16;75670:133;;;;-1:-1:-1;;;75670:133:0;;18149:2:1;75670:133:0;;;18131:21:1;18188:2;18168:18;;;18161:30;18227:34;18207:18;;;18200:62;18298:25;18278:18;;;18271:53;18341:19;;75670:133:0;17947:419:1;75670:133:0;66814:8;;;;75922:115;;75968:15;;;;:7;:15;:::i;:::-;75967:16;75959:66;;;;-1:-1:-1;;;75959:66:0;;16609:2:1;75959:66:0;;;16591:21:1;16648:2;16628:18;;;16621:30;16687:34;16667:18;;;16660:62;-1:-1:-1;;;16738:18:1;;;16731:35;16783:19;;75959:66:0;16407:401:1;75959:66:0;76049:15;76067:16;:14;:16::i;:::-;76049:34;;76096:23;:21;:23::i;:::-;66814:8;;;;76130:72;;;76166:24;:22;:24::i;:::-;76212:22;76218:6;76226:7;76212:5;:22::i;:::-;76245:29;76253:7;76262:11;;;;:7;:11;:::i;:::-;76245:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76245:7:0;;-1:-1:-1;;;76245:29:0:i;:::-;76334:36;76344:6;76352:8;76362:7;76334:9;:36::i;30635:452::-;30764:4;30808:16;30816:7;30808;:16::i;:::-;30786:110;;;;-1:-1:-1;;;30786:110:0;;24517:2:1;30786:110:0;;;24499:21:1;24556:2;24536:18;;;24529:30;24595:34;24575:18;;;24568:62;-1:-1:-1;;;24646:18:1;;;24639:42;24698:19;;30786:110:0;24315:408:1;30786:110:0;30907:13;30923:23;30938:7;30923:14;:23::i;:::-;30907:39;;30976:5;-1:-1:-1;;;;;30965:16:0;:7;-1:-1:-1;;;;;30965:16:0;;:64;;;;31022:7;-1:-1:-1;;;;;30998:31:0;:20;31010:7;30998:11;:20::i;:::-;-1:-1:-1;;;;;30998:31:0;;30965:64;:113;;;-1:-1:-1;;;;;;27616:25:0;;;27587:4;27616:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;31046:32;27445:214;33731:615;33904:4;-1:-1:-1;;;;;33877:31:0;:23;33892:7;33877:14;:23::i;:::-;-1:-1:-1;;;;;33877:31:0;;33855:122;;;;-1:-1:-1;;;33855:122:0;;29201:2:1;33855:122:0;;;29183:21:1;29240:2;29220:18;;;29213:30;29279:34;29259:18;;;29252:62;-1:-1:-1;;;29330:18:1;;;29323:39;29379:19;;33855:122:0;28999:405:1;33855:122:0;-1:-1:-1;;;;;33996:16:0;;33988:65;;;;-1:-1:-1;;;33988:65:0;;23355:2:1;33988:65:0;;;23337:21:1;23394:2;23374:18;;;23367:30;23433:34;23413:18;;;23406:62;-1:-1:-1;;;23484:18:1;;;23477:34;23528:19;;33988:65:0;23153:400:1;33988:65:0;34170:29;34187:1;34191:7;34170:8;:29::i;:::-;-1:-1:-1;;;;;34212:15:0;;;;;;:9;:15;;;;;:20;;34231:1;;34212:15;:20;;34231:1;;34212:20;:::i;:::-;;;;-1:-1:-1;;;;;;;34243:13:0;;;;;;:9;:13;;;;;:18;;34260:1;;34243:13;:18;;34260:1;;34243:18;:::i;:::-;;;;-1:-1:-1;;34272:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;34272:21:0;-1:-1:-1;;;;;34272:21:0;;;;;;;;;34311:27;;34272:16;;34311:27;;;;;;;33731:615;;;:::o;32423:382::-;-1:-1:-1;;;;;32503:16:0;;32495:61;;;;-1:-1:-1;;;32495:61:0;;27348:2:1;32495:61:0;;;27330:21:1;;;27367:18;;;27360:30;27426:34;27406:18;;;27399:62;27478:18;;32495:61:0;27146:356:1;32495:61:0;32576:16;32584:7;32576;:16::i;:::-;32575:17;32567:58;;;;-1:-1:-1;;;32567:58:0;;20929:2:1;32567:58:0;;;20911:21:1;20968:2;20948:18;;;20941:30;21007;20987:18;;;20980:58;21055:18;;32567:58:0;20727:352:1;32567:58:0;-1:-1:-1;;;;;32696:13:0;;;;;;:9;:13;;;;;:18;;32713:1;;32696:13;:18;;32713:1;;32696:18;:::i;:::-;;;;-1:-1:-1;;32725:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;32725:21:0;-1:-1:-1;;;;;32725:21:0;;;;;;;;32764:33;;32725:16;;;32764:33;;32725:16;;32764:33;32423:382;;:::o;56568:497::-;56649:22;56657:4;56663:7;56649;:22::i;:::-;56644:414;;56837:41;56865:7;-1:-1:-1;;;;;56837:41:0;56875:2;56837:19;:41::i;:::-;56951:38;56979:4;56986:2;56951:19;:38::i;:::-;56742:270;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;56742:270:0;;;;;;;;;;-1:-1:-1;;;56688:358:0;;;;;;;:::i;60142:229::-;60217:22;60225:4;60231:7;60217;:22::i;:::-;60212:152;;60256:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;60256:29:0;;;;;;;;;:36;;-1:-1:-1;;60256:36:0;60288:4;60256:36;;;60339:12;20624:10;;20544:98;60339:12;-1:-1:-1;;;;;60312:40:0;60330:7;-1:-1:-1;;;;;60312:40:0;60324:4;60312:40;;;;;;;;;;60142:229;;:::o;60379:230::-;60454:22;60462:4;60468:7;60454;:22::i;:::-;60450:152;;;60525:5;60493:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;60493:29:0;;;;;;;;;;:37;;-1:-1:-1;;60493:37:0;;;60550:40;20624:10;;60493:12;;60550:40;;60525:5;60550:40;60379:230;;:::o;62894:191::-;62987:6;;;-1:-1:-1;;;;;63004:17:0;;;-1:-1:-1;;;;;;63004:17:0;;;;;;;63037:40;;62987:6;;;63004:17;62987:6;;63037:40;;62968:16;;63037:40;62957:128;62894:191;:::o;29676:352::-;29833:28;29843:4;29849:2;29853:7;29833:9;:28::i;:::-;29894:48;29917:4;29923:2;29927:7;29936:5;29894:22;:48::i;:::-;29872:148;;;;-1:-1:-1;;;29872:148:0;;;;;;;:::i;77871:218::-;77967:7;77992:14;78009;78015:7;78009:5;:14::i;:::-;77992:31;-1:-1:-1;78041:40:0;77992:31;78063:17;;;;:7;:17;:::i;:::-;78041:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78041:13:0;;-1:-1:-1;;;78041:40:0:i;:::-;78034:47;77871:218;-1:-1:-1;;;77871:218:0:o;78371:308::-;78463:16;;78445:14;;:34;;78423:110;;;;-1:-1:-1;;;78423:110:0;;30833:2:1;78423:110:0;;;30815:21:1;30872:2;30852:18;;;30845:30;30911:28;30891:18;;;30884:56;30957:18;;78423:110:0;30631:350:1;78423:110:0;78548:27;78556:14;;78573:1;78556:18;;;;:::i;78548:27::-;78544:128;;;78610:1;78592:14;;:19;;;;;;;:::i;:::-;;;;-1:-1:-1;78544:128:0;;-1:-1:-1;78544:128:0;;78644:14;:16;;;:14;:16;;;:::i;:::-;;;;;;78371:308::o;78687:256::-;78766:12;;67013:13;;78748:30;;78740:59;;;;-1:-1:-1;;;78740:59:0;;32652:2:1;78740:59:0;;;32634:21:1;32691:2;32671:18;;;32664:30;-1:-1:-1;;;32710:18:1;;;32703:46;32766:18;;78740:59:0;32450:340:1;78740:59:0;78814:27;78822:14;;78839:1;78822:18;;;;:::i;78814:27::-;78810:126;;;78875:1;78858:13;;:18;;;;;;;:::i;78810:126::-;78909:13;:15;;;:13;:15;;;:::i;74223:443::-;74326:16;74334:7;74326;:16::i;:::-;74304:112;;;;-1:-1:-1;;;74304:112:0;;22940:2:1;74304:112:0;;;22922:21:1;22979:2;22959:18;;;22952:30;23018:34;22998:18;;;22991:62;-1:-1:-1;;;23069:18:1;;;23062:44;23123:19;;74304:112:0;22738:410:1;74304:112:0;74455:19;;;;:10;:19;;;;;74449:33;;;;;:::i;:::-;:38;;-1:-1:-1;74427:119:0;;;;-1:-1:-1;;;74427:119:0;;24930:2:1;74427:119:0;;;24912:21:1;24969:2;24949:18;;;24942:30;25008:33;24988:18;;;24981:61;25059:18;;74427:119:0;24728:355:1;74427:119:0;66814:8;;;;74561:16;:44;;;-1:-1:-1;67013:13:0;;74581:7;:24;74561:44;74557:102;;;74622:19;;;;:10;:19;;;;;;;;:25;;;;;;;;:::i;49629:483::-;49731:13;49762:19;49794:10;49798:6;49794:1;:10;:::i;:::-;:14;;49807:1;49794:14;:::i;:::-;49784:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49784:25:0;;49762:47;;-1:-1:-1;;;49820:6:0;49827:1;49820:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;49820:15:0;;;;;;;;;-1:-1:-1;;;49846:6:0;49853:1;49846:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;49846:15:0;;;;;;;;-1:-1:-1;49877:9:0;49889:10;49893:6;49889:1;:10;:::i;:::-;:14;;49902:1;49889:14;:::i;:::-;49877:26;;49872:135;49909:1;49905;:5;49872:135;;;-1:-1:-1;;;49957:5:0;49965:3;49957:11;49944:25;;;;;;;:::i;:::-;;;;49932:6;49939:1;49932:9;;;;;;;;:::i;:::-;;;;:37;-1:-1:-1;;;;;49932:37:0;;;;;;;;-1:-1:-1;49994:1:0;49984:11;;;;;49912:3;;;:::i;:::-;;;49872:135;;;-1:-1:-1;50025:10:0;;50017:55;;;;-1:-1:-1;;;50017:55:0;;17436:2:1;50017:55:0;;;17418:21:1;;;17455:18;;;17448:30;17514:34;17494:18;;;17487:62;17566:18;;50017:55:0;17234:356:1;35203:980:0;35358:4;-1:-1:-1;;;;;35379:13:0;;40038:20;40086:8;35375:801;;35432:175;;-1:-1:-1;;;35432:175:0;;-1:-1:-1;;;;;35432:36:0;;;;;:175;;20624:10;;35526:4;;35553:7;;35583:5;;35432:175;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;35432:175:0;;;;;;;;-1:-1:-1;;35432:175:0;;;;;;;;;;;;:::i;:::-;;;35411:710;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;35790:13:0;;35786:320;;35833:108;;-1:-1:-1;;;35833:108:0;;;;;;;:::i;35786:320::-;36056:6;36050:13;36041:6;36037:2;36033:15;36026:38;35411:710;-1:-1:-1;;;;;;35671:51:0;-1:-1:-1;;;35671:51:0;;-1:-1:-1;35664:58:0;;35375:801;-1:-1:-1;36160:4:0;35203:980;;;;;;:::o;76538:570::-;76632:7;76677:423;76781:121;76929:15;;;;:7;:15;:::i;:::-;76971:16;;;;77030:11;;;;76971:7;77030:11;:::i;:::-;77014:29;;;;;;;:::i;:::-;;;;;;;;;76744:322;;;;;;;14406:25:1;;;14474:14;;14467:22;14462:2;14447:18;;14440:50;14521:2;14506:18;;14499:34;14564:2;14549:18;;14542:34;14393:3;14378:19;;14181:401;76744:322:0;;;;;;;;;;;;;76712:373;;;;;;76677:16;:423::i;9184:263::-;9289:7;9315:17;9334:18;9356:27;9367:4;9373:9;9356:10;:27::i;:::-;9314:69;;;;9394:18;9406:5;9394:11;:18::i;:::-;-1:-1:-1;9430:9:0;9184:263;-1:-1:-1;;;9184:263:0:o;4606:208::-;4719:7;4751:55;4773:20;:18;:20::i;:::-;4795:10;14040:57;;-1:-1:-1;;;14040:57:0;;;10935:27:1;10978:11;;;10971:27;;;11014:12;;;11007:28;;;13967:7:0;;11051:12:1;;14040:57:0;;;;;;;;;;;;14012:100;;;;;;13992:120;;13847:273;;;;;7042:1340;7150:7;7159:12;7389:9;:16;7409:2;7389:22;7385:990;;;7685:4;7670:20;;7664:27;7735:4;7720:20;;7714:27;7793:4;7778:20;;7772:27;7428:9;7764:36;7836:25;7847:4;7764:36;7664:27;7714;7836:10;:25::i;:::-;7829:32;;;;;;;;;7385:990;7883:9;:16;7903:2;7883:22;7879:496;;;8158:4;8143:20;;8137:27;8209:4;8194:20;;8188:27;8251:23;8262:4;8137:27;8188;8251:10;:23::i;:::-;8244:30;;;;;;;;7879:496;-1:-1:-1;8323:1:0;;-1:-1:-1;8327:35:0;7879:496;7042:1340;;;;;:::o;5313:643::-;5391:20;5382:5;:29;;;;;;;;:::i;:::-;;5378:571;;;5313:643;:::o;5378:571::-;5489:29;5480:5;:38;;;;;;;;:::i;:::-;;5476:473;;;5535:34;;-1:-1:-1;;;5535:34:0;;15910:2:1;5535:34:0;;;15892:21:1;15949:2;15929:18;;;15922:30;15988:26;15968:18;;;15961:54;16032:18;;5535:34:0;15708:348:1;5476:473:0;5600:35;5591:5;:44;;;;;;;;:::i;:::-;;5587:362;;;5652:41;;-1:-1:-1;;;5652:41:0;;19330:2:1;5652:41:0;;;19312:21:1;19369:2;19349:18;;;19342:30;19408:33;19388:18;;;19381:61;19459:18;;5652:41:0;19128:355:1;5587:362:0;5724:30;5715:5;:39;;;;;;;;:::i;:::-;;5711:238;;;5771:44;;-1:-1:-1;;;5771:44:0;;24114:2:1;5771:44:0;;;24096:21:1;24153:2;24133:18;;;24126:30;24192:34;24172:18;;;24165:62;-1:-1:-1;;;24243:18:1;;;24236:32;24285:19;;5771:44:0;23912:398:1;5711:238:0;5846:30;5837:5;:39;;;;;;;;:::i;:::-;;5833:116;;;5893:44;;-1:-1:-1;;;5893:44:0;;26945:2:1;5893:44:0;;;26927:21:1;26984:2;26964:18;;;26957:30;27023:34;27003:18;;;26996:62;-1:-1:-1;;;27074:18:1;;;27067:32;27116:19;;5893:44:0;26743:398:1;3144:380:0;3197:7;3238:16;3221:13;:33;3217:300;;;-1:-1:-1;3278:24:0;;3144:380::o;3217:300::-;-1:-1:-1;3744:197:0;;;3403:10;3744:197;;;;14846:25:1;;;;3436:12:0;14887:18:1;;;14880:34;3471:15:0;14930:18:1;;;14923:34;3873:13:0;14973:18:1;;;14966:34;3917:4:0;15016:19:1;;;;15009:61;;;;3744:197:0;;;;;;;;;;14818:19:1;;;;3744:197:0;;;3716:240;;;;;;78097:195::o;10764:1669::-;10895:7;;11856:66;11830:92;;11812:200;;;-1:-1:-1;11965:1:0;;-1:-1:-1;11969:30:0;11949:51;;11812:200;12026:1;:7;;12031:2;12026:7;;:18;;;;;12037:1;:7;;12042:2;12037:7;;12026:18;12022:102;;;-1:-1:-1;12077:1:0;;-1:-1:-1;12081:30:0;12061:51;;12022:102;12238:24;;;12221:14;12238:24;;;;;;;;;15308:25:1;;;15381:4;15369:17;;15349:18;;;15342:45;;;;15403:18;;;15396:34;;;15446:18;;;15439:34;;;12238:24:0;;15280:19:1;;12238:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;12238:24:0;;-1:-1:-1;;12238:24:0;;;-1:-1:-1;;;;;;;12277:20:0;;12273:103;;12330:1;12334:29;12314:50;;;;;;;12273:103;12396:6;-1:-1:-1;12404:20:0;;-1:-1:-1;10764:1669:0;;;;;;;;:::o;9710:440::-;9824:7;;-1:-1:-1;;;;;9925:124:0;;10076:3;10072:12;;;10086:2;10068:21;10117:25;10128:4;10068:21;10137:1;9925:124;10117:10;:25::i;:::-;10110:32;;;;;;9710:440;;;;;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:406:1;78:5;112:18;104:6;101:30;98:56;;;134:18;;:::i;:::-;172:57;217:2;196:15;;-1:-1:-1;;192:29:1;223:4;188:40;172:57;:::i;:::-;163:66;;252:6;245:5;238:21;292:3;283:6;278:3;274:16;271:25;268:45;;;309:1;306;299:12;268:45;358:6;353:3;346:4;339:5;335:16;322:43;412:1;405:4;396:6;389:5;385:18;381:29;374:40;14:406;;;;;:::o;425:173::-;493:20;;-1:-1:-1;;;;;542:31:1;;532:42;;522:70;;588:1;585;578:12;603:855;656:5;709:3;702:4;694:6;690:17;686:27;676:55;;727:1;724;717:12;676:55;763:6;750:20;789:4;813:59;829:42;868:2;829:42;:::i;:::-;813:59;:::i;:::-;894:3;918:2;913:3;906:15;946:2;941:3;937:12;930:19;;981:2;973:6;969:15;1033:3;1028:2;1022;1019:1;1015:10;1007:6;1003:23;999:32;996:41;993:61;;;1050:1;1047;1040:12;993:61;1072:1;1093;1103:326;1119:2;1114:3;1111:11;1103:326;;;1200:3;1187:17;1236:18;1223:11;1220:35;1217:55;;;1268:1;1265;1258:12;1217:55;1297:57;1350:3;1345:2;1331:11;1323:6;1319:24;1315:33;1297:57;:::i;:::-;1285:70;;-1:-1:-1;1375:12:1;;;;1407;;;;1141:1;1132:11;1103:326;;;-1:-1:-1;1447:5:1;;603:855;-1:-1:-1;;;;;;;;603:855:1:o;1463:160::-;1528:20;;1584:13;;1577:21;1567:32;;1557:60;;1613:1;1610;1603:12;1628:221;1671:5;1724:3;1717:4;1709:6;1705:17;1701:27;1691:55;;1742:1;1739;1732:12;1691:55;1764:79;1839:3;1830:6;1817:20;1810:4;1802:6;1798:17;1764:79;:::i;1854:186::-;1913:6;1966:2;1954:9;1945:7;1941:23;1937:32;1934:52;;;1982:1;1979;1972:12;1934:52;2005:29;2024:9;2005:29;:::i;2045:260::-;2113:6;2121;2174:2;2162:9;2153:7;2149:23;2145:32;2142:52;;;2190:1;2187;2180:12;2142:52;2213:29;2232:9;2213:29;:::i;:::-;2203:39;;2261:38;2295:2;2284:9;2280:18;2261:38;:::i;:::-;2251:48;;2045:260;;;;;:::o;2310:328::-;2387:6;2395;2403;2456:2;2444:9;2435:7;2431:23;2427:32;2424:52;;;2472:1;2469;2462:12;2424:52;2495:29;2514:9;2495:29;:::i;:::-;2485:39;;2543:38;2577:2;2566:9;2562:18;2543:38;:::i;:::-;2533:48;;2628:2;2617:9;2613:18;2600:32;2590:42;;2310:328;;;;;:::o;2643:666::-;2738:6;2746;2754;2762;2815:3;2803:9;2794:7;2790:23;2786:33;2783:53;;;2832:1;2829;2822:12;2783:53;2855:29;2874:9;2855:29;:::i;:::-;2845:39;;2903:38;2937:2;2926:9;2922:18;2903:38;:::i;:::-;2893:48;;2988:2;2977:9;2973:18;2960:32;2950:42;;3043:2;3032:9;3028:18;3015:32;3070:18;3062:6;3059:30;3056:50;;;3102:1;3099;3092:12;3056:50;3125:22;;3178:4;3170:13;;3166:27;-1:-1:-1;3156:55:1;;3207:1;3204;3197:12;3156:55;3230:73;3295:7;3290:2;3277:16;3272:2;3268;3264:11;3230:73;:::i;:::-;3220:83;;;2643:666;;;;;;;:::o;3314:254::-;3379:6;3387;3440:2;3428:9;3419:7;3415:23;3411:32;3408:52;;;3456:1;3453;3446:12;3408:52;3479:29;3498:9;3479:29;:::i;:::-;3469:39;;3527:35;3558:2;3547:9;3543:18;3527:35;:::i;3573:254::-;3641:6;3649;3702:2;3690:9;3681:7;3677:23;3673:32;3670:52;;;3718:1;3715;3708:12;3670:52;3741:29;3760:9;3741:29;:::i;:::-;3731:39;3817:2;3802:18;;;;3789:32;;-1:-1:-1;;;3573:254:1:o;3832:1159::-;3960:6;3968;4021:2;4009:9;4000:7;3996:23;3992:32;3989:52;;;4037:1;4034;4027:12;3989:52;4077:9;4064:23;4106:18;4147:2;4139:6;4136:14;4133:34;;;4163:1;4160;4153:12;4133:34;4201:6;4190:9;4186:22;4176:32;;4246:7;4239:4;4235:2;4231:13;4227:27;4217:55;;4268:1;4265;4258:12;4217:55;4304:2;4291:16;4326:4;4350:59;4366:42;4405:2;4366:42;:::i;4350:59::-;4431:3;4455:2;4450:3;4443:15;4483:2;4478:3;4474:12;4467:19;;4514:2;4510;4506:11;4562:7;4557:2;4551;4548:1;4544:10;4540:2;4536:19;4532:28;4529:41;4526:61;;;4583:1;4580;4573:12;4526:61;4605:1;4596:10;;4615:163;4629:2;4626:1;4623:9;4615:163;;;4686:17;;4674:30;;4647:1;4640:9;;;;;4724:12;;;;4756;;4615:163;;;-1:-1:-1;4797:5:1;-1:-1:-1;;4840:18:1;;4827:32;;-1:-1:-1;;4871:16:1;;;4868:36;;;4900:1;4897;4890:12;4868:36;;4923:62;4977:7;4966:8;4955:9;4951:24;4923:62;:::i;:::-;4913:72;;;3832:1159;;;;;:::o;4996:180::-;5052:6;5105:2;5093:9;5084:7;5080:23;5076:32;5073:52;;;5121:1;5118;5111:12;5073:52;5144:26;5160:9;5144:26;:::i;5181:180::-;5240:6;5293:2;5281:9;5272:7;5268:23;5264:32;5261:52;;;5309:1;5306;5299:12;5261:52;-1:-1:-1;5332:23:1;;5181:180;-1:-1:-1;5181:180:1:o;5366:254::-;5434:6;5442;5495:2;5483:9;5474:7;5470:23;5466:32;5463:52;;;5511:1;5508;5501:12;5463:52;5547:9;5534:23;5524:33;;5576:38;5610:2;5599:9;5595:18;5576:38;:::i;5625:245::-;5683:6;5736:2;5724:9;5715:7;5711:23;5707:32;5704:52;;;5752:1;5749;5742:12;5704:52;5791:9;5778:23;5810:30;5834:5;5810:30;:::i;5875:249::-;5944:6;5997:2;5985:9;5976:7;5972:23;5968:32;5965:52;;;6013:1;6010;6003:12;5965:52;6045:9;6039:16;6064:30;6088:5;6064:30;:::i;6129:322::-;6198:6;6251:2;6239:9;6230:7;6226:23;6222:32;6219:52;;;6267:1;6264;6257:12;6219:52;6307:9;6294:23;6340:18;6332:6;6329:30;6326:50;;;6372:1;6369;6362:12;6326:50;6395;6437:7;6428:6;6417:9;6413:22;6395:50;:::i;6641:787::-;6775:6;6783;6791;6799;6852:2;6840:9;6831:7;6827:23;6823:32;6820:52;;;6868:1;6865;6858:12;6820:52;6904:9;6891:23;6881:33;;6933:38;6967:2;6956:9;6952:18;6933:38;:::i;:::-;6923:48;;7022:2;7011:9;7007:18;6994:32;7045:18;7086:2;7078:6;7075:14;7072:34;;;7102:1;7099;7092:12;7072:34;7140:6;7129:9;7125:22;7115:32;;7185:7;7178:4;7174:2;7170:13;7166:27;7156:55;;7207:1;7204;7197:12;7156:55;7247:2;7234:16;7273:2;7265:6;7262:14;7259:34;;;7289:1;7286;7279:12;7259:34;7342:7;7337:2;7327:6;7324:1;7320:14;7316:2;7312:23;7308:32;7305:45;7302:65;;;7363:1;7360;7353:12;7302:65;6641:787;;;;-1:-1:-1;;7394:2:1;7386:11;;-1:-1:-1;;;6641:787:1:o;7433:390::-;7511:6;7519;7572:2;7560:9;7551:7;7547:23;7543:32;7540:52;;;7588:1;7585;7578:12;7540:52;7624:9;7611:23;7601:33;;7685:2;7674:9;7670:18;7657:32;7712:18;7704:6;7701:30;7698:50;;;7744:1;7741;7734:12;7698:50;7767;7809:7;7800:6;7789:9;7785:22;7767:50;:::i;7828:257::-;7869:3;7907:5;7901:12;7934:6;7929:3;7922:19;7950:63;8006:6;7999:4;7994:3;7990:14;7983:4;7976:5;7972:16;7950:63;:::i;:::-;8067:2;8046:15;-1:-1:-1;;8042:29:1;8033:39;;;;8074:4;8029:50;;7828:257;-1:-1:-1;;7828:257:1:o;8090:271::-;8273:6;8265;8260:3;8247:33;8229:3;8299:16;;8324:13;;;8299:16;8090:271;-1:-1:-1;8090:271:1:o;8366:966::-;8795:3;8833:6;8827:13;8849:53;8895:6;8890:3;8883:4;8875:6;8871:17;8849:53;:::i;:::-;8965:13;;8924:16;;;;8987:57;8965:13;8924:16;9021:4;9009:17;;8987:57;:::i;:::-;-1:-1:-1;;;9066:20:1;;9095:18;;;9138:13;;9160:65;9138:13;9212:1;9201:13;;9194:4;9182:17;;9160:65;:::i;:::-;-1:-1:-1;;;9288:1:1;9244:20;;;;9280:10;;;9273:27;9324:1;9316:10;;8366:966;-1:-1:-1;;;;;8366:966:1:o;9337:1335::-;9513:3;9551:6;9545:13;9577:4;9590:51;9634:6;9629:3;9624:2;9616:6;9612:15;9590:51;:::i;:::-;9726:13;;9663:16;;;;9699:1;;9786;9808:18;;;;9861;;;;9888:93;;9966:4;9956:8;9952:19;9940:31;;9888:93;10029:2;10019:8;10016:16;9996:18;9993:40;9990:167;;;-1:-1:-1;;;10056:33:1;;10112:4;10109:1;10102:15;10142:4;10063:3;10130:17;9990:167;10173:18;10200:110;;;;10324:1;10319:328;;;;10166:481;;10200:110;-1:-1:-1;;10235:24:1;;10221:39;;10280:20;;;;-1:-1:-1;10200:110:1;;10319:328;36494:1;36487:14;;;36531:4;36518:18;;10414:1;10428:169;10442:8;10439:1;10436:15;10428:169;;;10524:14;;10509:13;;;10502:37;10567:16;;;;10459:10;;10428:169;;;10432:3;;10628:8;10621:5;10617:20;10610:27;;10166:481;-1:-1:-1;10663:3:1;;9337:1335;-1:-1:-1;;;;;;;;;;9337:1335:1:o;11074:621::-;-1:-1:-1;;;11432:3:1;11425:40;11407:3;11494:6;11488:13;11510:62;11565:6;11560:2;11555:3;11551:12;11544:4;11536:6;11532:17;11510:62;:::i;:::-;11636:25;11631:2;11591:16;;;;11623:11;;;11616:46;-1:-1:-1;11686:2:1;11678:11;;11074:621;-1:-1:-1;11074:621:1:o;11700:610::-;-1:-1:-1;;;12058:3:1;12051:40;12033:3;12120:6;12114:13;12136:62;12191:6;12186:2;12181:3;12177:12;12170:4;12162:6;12158:17;12136:62;:::i;:::-;-1:-1:-1;;;12257:2:1;12217:16;;;;12249:11;;;12242:35;-1:-1:-1;12301:2:1;12293:11;;11700:610;-1:-1:-1;11700:610:1:o;12315:786::-;12726:25;12721:3;12714:38;12696:3;12781:6;12775:13;12797:62;12852:6;12847:2;12842:3;12838:12;12831:4;12823:6;12819:17;12797:62;:::i;:::-;-1:-1:-1;;;12918:2:1;12878:16;;;12910:11;;;12903:40;12968:13;;12990:63;12968:13;13039:2;13031:11;;13024:4;13012:17;;12990:63;:::i;:::-;13073:17;13092:2;13069:26;;12315:786;-1:-1:-1;;;;12315:786:1:o;13314:488::-;-1:-1:-1;;;;;13583:15:1;;;13565:34;;13635:15;;13630:2;13615:18;;13608:43;13682:2;13667:18;;13660:34;;;13730:3;13725:2;13710:18;;13703:31;;;13508:4;;13751:45;;13776:19;;13768:6;13751:45;:::i;:::-;13743:53;13314:488;-1:-1:-1;;;;;;13314:488:1:o;15484:219::-;15633:2;15622:9;15615:21;15596:4;15653:44;15693:2;15682:9;15678:18;15670:6;15653:44;:::i;19488:414::-;19690:2;19672:21;;;19729:2;19709:18;;;19702:30;19768:34;19763:2;19748:18;;19741:62;-1:-1:-1;;;19834:2:1;19819:18;;19812:48;19892:3;19877:19;;19488:414::o;28638:356::-;28840:2;28822:21;;;28859:18;;;28852:30;28918:34;28913:2;28898:18;;28891:62;28985:2;28970:18;;28638:356::o;30213:413::-;30415:2;30397:21;;;30454:2;30434:18;;;30427:30;30493:34;30488:2;30473:18;;30466:62;-1:-1:-1;;;30559:2:1;30544:18;;30537:47;30616:3;30601:19;;30213:413::o;34568:521::-;34645:4;34651:6;34711:11;34698:25;34805:2;34801:7;34790:8;34774:14;34770:29;34766:43;34746:18;34742:68;34732:96;;34824:1;34821;34814:12;34732:96;34851:33;;34903:20;;;-1:-1:-1;34946:18:1;34935:30;;34932:50;;;34978:1;34975;34968:12;34932:50;35011:4;34999:17;;-1:-1:-1;35042:14:1;35038:27;;;35028:38;;35025:58;;;35079:1;35076;35069:12;35621:328;35717:4;35775:11;35762:25;35869:3;35865:8;35854;35838:14;35834:29;35830:44;35810:18;35806:69;35796:97;;35889:1;35886;35879:12;35796:97;35910:33;;;;;35621:328;-1:-1:-1;;35621:328:1:o;35954:275::-;36025:2;36019:9;36090:2;36071:13;;-1:-1:-1;;36067:27:1;36055:40;;36125:18;36110:34;;36146:22;;;36107:62;36104:88;;;36172:18;;:::i;:::-;36208:2;36201:22;35954:275;;-1:-1:-1;35954:275:1:o;36234:182::-;36293:4;36326:18;36318:6;36315:30;36312:56;;;36348:18;;:::i;:::-;-1:-1:-1;36393:1:1;36389:14;36405:4;36385:25;;36234:182::o;36547:128::-;36587:3;36618:1;36614:6;36611:1;36608:13;36605:39;;;36624:18;;:::i;:::-;-1:-1:-1;36660:9:1;;36547:128::o;36680:120::-;36720:1;36746;36736:35;;36751:18;;:::i;:::-;-1:-1:-1;36785:9:1;;36680:120::o;36805:168::-;36845:7;36911:1;36907;36903:6;36899:14;36896:1;36893:21;36888:1;36881:9;36874:17;36870:45;36867:71;;;36918:18;;:::i;:::-;-1:-1:-1;36958:9:1;;36805:168::o;36978:125::-;37018:4;37046:1;37043;37040:8;37037:34;;;37051:18;;:::i;:::-;-1:-1:-1;37088:9:1;;36978:125::o;37108:258::-;37180:1;37190:113;37204:6;37201:1;37198:13;37190:113;;;37280:11;;;37274:18;37261:11;;;37254:39;37226:2;37219:10;37190:113;;;37321:6;37318:1;37315:13;37312:48;;;-1:-1:-1;;37356:1:1;37338:16;;37331:27;37108:258::o;37371:136::-;37410:3;37438:5;37428:39;;37447:18;;:::i;:::-;-1:-1:-1;;;37483:18:1;;37371:136::o;37512:380::-;37591:1;37587:12;;;;37634;;;37655:61;;37709:4;37701:6;37697:17;37687:27;;37655:61;37762:2;37754:6;37751:14;37731:18;37728:38;37725:161;;;37808:10;37803:3;37799:20;37796:1;37789:31;37843:4;37840:1;37833:15;37871:4;37868:1;37861:15;37725:161;;37512:380;;;:::o;37897:135::-;37936:3;-1:-1:-1;;37957:17:1;;37954:43;;;37977:18;;:::i;:::-;-1:-1:-1;38024:1:1;38013:13;;37897:135::o;38037:112::-;38069:1;38095;38085:35;;38100:18;;:::i;:::-;-1:-1:-1;38134:9:1;;38037:112::o;38154:127::-;38215:10;38210:3;38206:20;38203:1;38196:31;38246:4;38243:1;38236:15;38270:4;38267:1;38260:15;38286:127;38347:10;38342:3;38338:20;38335:1;38328:31;38378:4;38375:1;38368:15;38402:4;38399:1;38392:15;38418:127;38479:10;38474:3;38470:20;38467:1;38460:31;38510:4;38507:1;38500:15;38534:4;38531:1;38524:15;38550:127;38611:10;38606:3;38602:20;38599:1;38592:31;38642:4;38639:1;38632:15;38666:4;38663:1;38656:15;38682:127;38743:10;38738:3;38734:20;38731:1;38724:31;38774:4;38771:1;38764:15;38798:4;38795:1;38788:15;38814:131;-1:-1:-1;;;;;;38888:32:1;;38878:43;;38868:71;;38935:1;38932;38925:12

Swarm Source

ipfs://51577486d4206fa29ad4687374b8ab5f398e33f2ae64dcc3ee0d44967c26d5b4
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.