ETH Price: $3,366.75 (-3.43%)
Gas: 6.38 Gwei

Token

Ethernal Gates (Ethernal Gates)
 

Overview

Max Total Supply

1,450 Ethernal Gates

Holders

784

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
maalouf.eth
Balance
1 Ethernal Gates
0xcb253a2d733428653bdf7f3fca2aff8b2e133608
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

The Ethernal Gates is a collection of NFTs designed and created by Kristel Bechara and which grants access to the Arts DAO community.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
EthernalGates

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-04-19
*/

// SPDX-License-Identifier: MIT

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

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

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Trees proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

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

    function _efficientHash(bytes32 a, bytes32 b)
        private
        pure
        returns (bytes32 value)
    {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

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

// OpenZeppelin Contracts v4.4.1 (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.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

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

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

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

pragma solidity ^0.8.0;

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

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

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

// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

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

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

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

    /**
     * @dev 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: @openzeppelin/contracts/utils/Address.sol

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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// OpenZeppelin Contracts v4.4.1 (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/introspection/IERC165.sol

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

pragma solidity ^0.8.0;

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

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

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

pragma solidity ^0.8.0;

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

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

// OpenZeppelin Contracts v4.4.1 (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/token/ERC721/extensions/IERC721Metadata.sol

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

pragma solidity ^0.8.0;

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

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

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

// File: erc721a/contracts/ERC721A.sol

// Creator: Chiru Labs

pragma solidity ^0.8.4;

error ApprovalCallerNotOwnerNorApproved();
error ApprovalQueryForNonexistentToken();
error ApproveToCaller();
error ApprovalToCurrentOwner();
error BalanceQueryForZeroAddress();
error MintToZeroAddress();
error MintZeroQuantity();
error OwnerQueryForNonexistentToken();
error TransferCallerNotOwnerNorApproved();
error TransferFromIncorrectOwner();
error TransferToNonERC721ReceiverImplementer();
error TransferToZeroAddress();
error URIQueryForNonexistentToken();

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

    // Compiler will pack this into a single 256bit word.
    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Keeps track of the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
    }

    // Compiler will pack this into a single 256bit word.
    struct AddressData {
        // Realistically, 2**64-1 is more than enough.
        uint64 balance;
        // Keeps track of mint count with minimal overhead for tokenomics.
        uint64 numberMinted;
        // Keeps track of burn count with minimal overhead for tokenomics.
        uint64 numberBurned;
        // For miscellaneous variable(s) pertaining to the address
        // (e.g. number of whitelist mint slots used).
        // If there are multiple variables, please pack them into a uint64.
        uint64 aux;
    }

    // The tokenId of the next token to be minted.
    uint256 internal _currentIndex;

    // The number of tokens burned.
    uint256 internal _burnCounter;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

    /**
     * To change the starting tokenId, please override this function.
     */
    function _startTokenId() internal view virtual returns (uint256) {
        return 0;
    }

    /**
     * @dev Burned tokens are calculated here, use _totalMinted() if you want to count just minted tokens.
     */
    function totalSupply() public view returns (uint256) {
        // Counter underflow is impossible as _burnCounter cannot be incremented
        // more than _currentIndex - _startTokenId() times
        unchecked {
            return _currentIndex - _burnCounter - _startTokenId();
        }
    }

    /**
     * Returns the total amount of tokens minted in the contract.
     */
    function _totalMinted() internal view returns (uint256) {
        // Counter underflow is impossible as _currentIndex does not decrement,
        // and it is initialized to _startTokenId()
        unchecked {
            return _currentIndex - _startTokenId();
        }
    }

    /**
     * @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 override returns (uint256) {
        if (owner == address(0)) revert BalanceQueryForZeroAddress();
        return uint256(_addressData[owner].balance);
    }

    /**
     * Returns the number of tokens minted by `owner`.
     */
    function _numberMinted(address owner) internal view returns (uint256) {
        return uint256(_addressData[owner].numberMinted);
    }

    /**
     * Returns the number of tokens burned by or on behalf of `owner`.
     */
    function _numberBurned(address owner) internal view returns (uint256) {
        return uint256(_addressData[owner].numberBurned);
    }

    /**
     * Returns the auxillary data for `owner`. (e.g. number of whitelist mint slots used).
     */
    function _getAux(address owner) internal view returns (uint64) {
        return _addressData[owner].aux;
    }

    /**
     * Sets the auxillary data for `owner`. (e.g. number of whitelist mint slots used).
     * If there are multiple variables, please pack them into a uint64.
     */
    function _setAux(address owner, uint64 aux) internal {
        _addressData[owner].aux = aux;
    }

    /**
     * Gas spent here starts off proportional to the maximum mint batch size.
     * It gradually moves to O(1) as tokens get transferred around in the collection over time.
     */
    function _ownershipOf(uint256 tokenId)
        internal
        view
        returns (TokenOwnership memory)
    {
        uint256 curr = tokenId;

        unchecked {
            if (_startTokenId() <= curr && curr < _currentIndex) {
                TokenOwnership memory ownership = _ownerships[curr];
                if (!ownership.burned) {
                    if (ownership.addr != address(0)) {
                        return ownership;
                    }
                    // Invariant:
                    // There will always be an ownership that has an address and is not burned
                    // before an ownership that does not have an address and is not burned.
                    // Hence, curr will not underflow.
                    while (true) {
                        curr--;
                        ownership = _ownerships[curr];
                        if (ownership.addr != address(0)) {
                            return ownership;
                        }
                    }
                }
            }
        }
        revert OwnerQueryForNonexistentToken();
    }

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

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

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

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

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

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

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public override {
        address owner = ERC721A.ownerOf(tokenId);
        if (to == owner) revert ApprovalToCurrentOwner();

        if (_msgSender() != owner && !isApprovedForAll(owner, _msgSender())) {
            revert ApprovalCallerNotOwnerNorApproved();
        }

        _approve(to, tokenId, owner);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId)
        public
        view
        override
        returns (address)
    {
        if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken();

        return _tokenApprovals[tokenId];
    }

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

        _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 {
        _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 {
        _transfer(from, to, tokenId);
        if (
            to.isContract() &&
            !_checkContractOnERC721Received(from, to, tokenId, _data)
        ) {
            revert TransferToNonERC721ReceiverImplementer();
        }
    }

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

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

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

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

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

        // Overflows are incredibly unrealistic.
        // balance or numberMinted overflow if current value of either + quantity > 1.8e19 (2**64) - 1
        // updatedIndex overflows if _currentIndex + quantity > 1.2e77 (2**256) - 1
        unchecked {
            _addressData[to].balance += uint64(quantity);
            _addressData[to].numberMinted += uint64(quantity);

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

            uint256 updatedIndex = startTokenId;
            uint256 end = updatedIndex + quantity;

            if (safe && to.isContract()) {
                do {
                    emit Transfer(address(0), to, updatedIndex);
                    if (
                        !_checkContractOnERC721Received(
                            address(0),
                            to,
                            updatedIndex++,
                            _data
                        )
                    ) {
                        revert TransferToNonERC721ReceiverImplementer();
                    }
                } while (updatedIndex != end);
                // Reentrancy protection
                if (_currentIndex != startTokenId) revert();
            } else {
                do {
                    emit Transfer(address(0), to, updatedIndex++);
                } while (updatedIndex != end);
            }
            _currentIndex = updatedIndex;
        }
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) private {
        TokenOwnership memory prevOwnership = _ownershipOf(tokenId);

        if (prevOwnership.addr != from) revert TransferFromIncorrectOwner();

        bool isApprovedOrOwner = (_msgSender() == from ||
            isApprovedForAll(from, _msgSender()) ||
            getApproved(tokenId) == _msgSender());

        if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        if (to == address(0)) revert TransferToZeroAddress();

        _beforeTokenTransfers(from, to, tokenId, 1);

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

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

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

            // If the ownership slot of tokenId+1 is not explicitly set, that means the transfer initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            TokenOwnership storage nextSlot = _ownerships[nextTokenId];
            if (nextSlot.addr == address(0)) {
                // This will suffice for checking _exists(nextTokenId),
                // as a burned slot cannot contain the zero address.
                if (nextTokenId != _currentIndex) {
                    nextSlot.addr = from;
                    nextSlot.startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

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

    /**
     * @dev This is equivalent to _burn(tokenId, false)
     */
    function _burn(uint256 tokenId) internal virtual {
        _burn(tokenId, false);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId, bool approvalCheck) internal virtual {
        TokenOwnership memory prevOwnership = _ownershipOf(tokenId);

        address from = prevOwnership.addr;

        if (approvalCheck) {
            bool isApprovedOrOwner = (_msgSender() == from ||
                isApprovedForAll(from, _msgSender()) ||
                getApproved(tokenId) == _msgSender());

            if (!isApprovedOrOwner) revert TransferCallerNotOwnerNorApproved();
        }

        _beforeTokenTransfers(from, address(0), tokenId, 1);

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

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

            // Keep track of who burned the token, and the timestamp of burning.
            TokenOwnership storage currSlot = _ownerships[tokenId];
            currSlot.addr = from;
            currSlot.startTimestamp = uint64(block.timestamp);
            currSlot.burned = true;

            // If the ownership slot of tokenId+1 is not explicitly set, that means the burn initiator owns it.
            // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
            uint256 nextTokenId = tokenId + 1;
            TokenOwnership storage nextSlot = _ownerships[nextTokenId];
            if (nextSlot.addr == address(0)) {
                // This will suffice for checking _exists(nextTokenId),
                // as a burned slot cannot contain the zero address.
                if (nextTokenId != _currentIndex) {
                    nextSlot.addr = from;
                    nextSlot.startTimestamp = prevOwnership.startTimestamp;
                }
            }
        }

        emit Transfer(from, address(0), tokenId);
        _afterTokenTransfers(from, address(0), tokenId, 1);

        // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times.
        unchecked {
            _burnCounter++;
        }
    }

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

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target 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 _checkContractOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        try
            IERC721Receiver(to).onERC721Received(
                _msgSender(),
                from,
                tokenId,
                _data
            )
        returns (bytes4 retval) {
            return retval == IERC721Receiver(to).onERC721Received.selector;
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                revert TransferToNonERC721ReceiverImplementer();
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }

    /**
     * @dev Hook that is called before a set of serially-ordered token ids are about to be transferred. This includes minting.
     * And also called before burning one token.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, `tokenId` will be burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}

    /**
     * @dev Hook that is called after a set of serially-ordered token ids have been transferred. This includes
     * minting.
     * And also called after one token has been burned.
     *
     * startTokenId - the first token id to be transferred
     * quantity - the amount to be transferred
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
     * transferred to `to`.
     * - When `from` is zero, `tokenId` has been minted for `to`.
     * - When `to` is zero, `tokenId` has been burned by `from`.
     * - `from` and `to` are never both zero.
     */
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}
}

// File: erc721a/contracts/extensions/ERC721AQueryable.sol

// Creator: Chiru Labs

pragma solidity ^0.8.4;

error InvalidQueryRange();

/**
 * @title ERC721A Queryable
 * @dev ERC721A subclass with convenience query functions.
 */
abstract contract ERC721AQueryable is ERC721A {
    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *   - `addr` = `address(0)`
     *   - `startTimestamp` = `0`
     *   - `burned` = `false`
     *
     * If the `tokenId` is burned:
     *   - `addr` = `<Address of owner before token was burned>`
     *   - `startTimestamp` = `<Timestamp when token was burned>`
     *   - `burned = `true`
     *
     * Otherwise:
     *   - `addr` = `<Address of owner>`
     *   - `startTimestamp` = `<Timestamp of start of ownership>`
     *   - `burned = `false`
     */
    function explicitOwnershipOf(uint256 tokenId)
        public
        view
        returns (TokenOwnership memory)
    {
        TokenOwnership memory ownership;
        if (tokenId < _startTokenId() || tokenId >= _currentIndex) {
            return ownership;
        }
        ownership = _ownerships[tokenId];
        if (ownership.burned) {
            return ownership;
        }
        return _ownershipOf(tokenId);
    }

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] memory tokenIds)
        external
        view
        returns (TokenOwnership[] memory)
    {
        unchecked {
            uint256 tokenIdsLength = tokenIds.length;
            TokenOwnership[] memory ownerships = new TokenOwnership[](
                tokenIdsLength
            );
            for (uint256 i; i != tokenIdsLength; ++i) {
                ownerships[i] = explicitOwnershipOf(tokenIds[i]);
            }
            return ownerships;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start` < `stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view returns (uint256[] memory) {
        unchecked {
            if (start >= stop) revert InvalidQueryRange();
            uint256 tokenIdsIdx;
            uint256 stopLimit = _currentIndex;
            // Set `start = max(start, _startTokenId())`.
            if (start < _startTokenId()) {
                start = _startTokenId();
            }
            // Set `stop = min(stop, _currentIndex)`.
            if (stop > stopLimit) {
                stop = stopLimit;
            }
            uint256 tokenIdsMaxLength = balanceOf(owner);
            // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`,
            // to cater for cases where `balanceOf(owner)` is too big.
            if (start < stop) {
                uint256 rangeLength = stop - start;
                if (rangeLength < tokenIdsMaxLength) {
                    tokenIdsMaxLength = rangeLength;
                }
            } else {
                tokenIdsMaxLength = 0;
            }
            uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength);
            if (tokenIdsMaxLength == 0) {
                return tokenIds;
            }
            // We need to call `explicitOwnershipOf(start)`,
            // because the slot at `start` may not be initialized.
            TokenOwnership memory ownership = explicitOwnershipOf(start);
            address currOwnershipAddr;
            // If the starting slot exists (i.e. not burned), initialize `currOwnershipAddr`.
            // `ownership.address` will not be zero, as `start` is clamped to the valid token ID range.
            if (!ownership.burned) {
                currOwnershipAddr = ownership.addr;
            }
            for (
                uint256 i = start;
                i != stop && tokenIdsIdx != tokenIdsMaxLength;
                ++i
            ) {
                ownership = _ownerships[i];
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            // Downsize the array to fit.
            assembly {
                mstore(tokenIds, tokenIdsIdx)
            }
            return tokenIds;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(totalSupply) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K pfp collections should be fine).
     */
    function tokensOfOwner(address owner)
        external
        view
        returns (uint256[] memory)
    {
        unchecked {
            uint256 tokenIdsIdx;
            address currOwnershipAddr;
            uint256 tokenIdsLength = balanceOf(owner);
            uint256[] memory tokenIds = new uint256[](tokenIdsLength);
            TokenOwnership memory ownership;
            for (
                uint256 i = _startTokenId();
                tokenIdsIdx != tokenIdsLength;
                ++i
            ) {
                ownership = _ownerships[i];
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            return tokenIds;
        }
    }
}

// File: contracts/EthernalGates.sol

pragma solidity 0.8.4;

error ExceedsMaximumSupply();
error SupplyExceedingMaxSupply();
error TransferFailed();
error CallerIsContract();
error PresaleNotStarted();
error AddressNotEligibleForPresaleMint();
error CountExceedsAllowedMintCount();
error IncorrectEtherSent();
error PublicSaleNotStarted();
error TransactionExceedsMaxNFTsAllowedInPresale();

/// @author Hammad Ghazi
contract EthernalGates is ERC721AQueryable, Ownable {
    using MerkleProof for bytes32[];

    enum SALE_STATUS {
        OFF,
        INVESTOR,
        VIP,
        WL,
        PUBLIC
    }

    SALE_STATUS public saleStatus;

    string private baseTokenURI;

    // Max Supply of Ethernal Gates
    uint256 public constant MAX_SUPPLY = 6000;

    // Holds max number of NFTs that can be minted at the moment
    uint256 public currentSupply = 2000;

    uint256 public presalePrice = 0.49 ether;
    uint256 public publicPrice = 0.59 ether;

    bytes32 public merkleRoot;

    // To store NFTs a particular address has minted in each whitelist phase
    struct MintCounts {
        uint16 investorMintCount;
        uint16 vipMintCount;
        uint16 wlMintCount;
    }

    mapping(address => MintCounts) public mintCounts;

    constructor(string memory baseURI)
        ERC721A("Ethernal Gates", "Ethernal Gates")
    {
        baseTokenURI = baseURI;
    }

    modifier soldOut(uint256 _count) {
        if (_totalMinted() + _count > currentSupply)
            revert ExceedsMaximumSupply();
        _;
    }

    // Admin only functions

    // To update sale status
    function setSaleStatus(SALE_STATUS _status) external onlyOwner {
        saleStatus = _status;
    }

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

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

    function changePresalePrice(uint256 _presalePrice) external onlyOwner {
        presalePrice = _presalePrice;
    }

    function changePublicPrice(uint256 _publicPrice) external onlyOwner {
        publicPrice = _publicPrice;
    }

    // To increase the supply, can't exceed 6000
    function increaseSupply(uint256 _increaseBy) external onlyOwner {
        if (currentSupply + _increaseBy > MAX_SUPPLY)
            revert SupplyExceedingMaxSupply();
        unchecked {
            currentSupply += _increaseBy;
        }
    }

    function withdraw() external onlyOwner {
        (bool success, ) = msg.sender.call{value: address(this).balance}("");
        if (!success) revert TransferFailed();
    }

    // Set some Ethernal Gates aside
    function reserveEthernalGates(uint256 _count)
        external
        onlyOwner
        soldOut(_count)
    {
        mint(msg.sender, _count);
    }

    function airdrop(address[] memory _addresses, uint256 _count)
        external
        onlyOwner
        soldOut(_count * _addresses.length)
    {
        uint256 stop = _addresses.length;
        for (uint256 i; i != stop; ) {
            _mint(_addresses[i], _count, "", false);
            unchecked {
                i++;
            }
        }
    }

    // Getter functions

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

    function _startTokenId() internal pure virtual override returns (uint256) {
        return 1;
    }

    //Mint functions

    /**
     * @dev '_allowedCount' represents number of NFTs caller is allowed to mint in presale, and,
     * '_count' indiciates number of NFTs caller wants to mint in the transaction
     */
    function presaleMint(
        bytes32[] calldata _proof,
        uint256 _allowedCount,
        uint16 _count
    ) external payable soldOut(_count) {
        SALE_STATUS saleState = saleStatus;
        MintCounts memory mintCount = mintCounts[msg.sender];
        if (saleState == SALE_STATUS.OFF || saleState == SALE_STATUS.PUBLIC)
            revert PresaleNotStarted();
        if (
            !MerkleProof.verify(
                _proof,
                merkleRoot,
                keccak256(abi.encodePacked(msg.sender, _allowedCount))
            )
        ) revert AddressNotEligibleForPresaleMint();
        if (_count > _allowedCount) revert CountExceedsAllowedMintCount();
        if (msg.value < presalePrice * _count) revert IncorrectEtherSent();
        if (saleState == SALE_STATUS.INVESTOR) {
            if (_allowedCount < mintCount.investorMintCount + _count)
                revert TransactionExceedsMaxNFTsAllowedInPresale();
            mintCount.investorMintCount += _count;
        } else if (saleState == SALE_STATUS.VIP) {
            if (_allowedCount < mintCount.vipMintCount + _count)
                revert TransactionExceedsMaxNFTsAllowedInPresale();
            mintCount.vipMintCount += _count;
        } else {
            if (_allowedCount < mintCount.wlMintCount + _count)
                revert TransactionExceedsMaxNFTsAllowedInPresale();
            mintCount.wlMintCount += _count;
        }
        mintCounts[msg.sender] = mintCount;
        mint(msg.sender, _count);
    }

    // Public mint

    function publicMint(uint256 _count) external payable soldOut(_count) {
        if (saleStatus != SALE_STATUS.PUBLIC) revert PublicSaleNotStarted();
        if (msg.value < publicPrice * _count) revert IncorrectEtherSent();
        mint(msg.sender, _count);
    }

    function mint(address _addr, uint256 quantity) private {
        if (tx.origin != msg.sender) revert CallerIsContract();
        _mint(_addr, quantity, "", false);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressNotEligibleForPresaleMint","type":"error"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApprovalToCurrentOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"CallerIsContract","type":"error"},{"inputs":[],"name":"CountExceedsAllowedMintCount","type":"error"},{"inputs":[],"name":"ExceedsMaximumSupply","type":"error"},{"inputs":[],"name":"IncorrectEtherSent","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"PresaleNotStarted","type":"error"},{"inputs":[],"name":"PublicSaleNotStarted","type":"error"},{"inputs":[],"name":"SupplyExceedingMaxSupply","type":"error"},{"inputs":[],"name":"TransactionExceedsMaxNFTsAllowedInPresale","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_presalePrice","type":"uint256"}],"name":"changePresalePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_publicPrice","type":"uint256"}],"name":"changePublicPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"}],"internalType":"struct ERC721A.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"}],"internalType":"struct ERC721A.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_increaseBy","type":"uint256"}],"name":"increaseSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintCounts","outputs":[{"internalType":"uint16","name":"investorMintCount","type":"uint16"},{"internalType":"uint16","name":"vipMintCount","type":"uint16"},{"internalType":"uint16","name":"wlMintCount","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"uint256","name":"_allowedCount","type":"uint256"},{"internalType":"uint16","name":"_count","type":"uint16"}],"name":"presaleMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"presalePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"publicPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_count","type":"uint256"}],"name":"reserveEthernalGates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saleStatus","outputs":[{"internalType":"enum EthernalGates.SALE_STATUS","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum EthernalGates.SALE_STATUS","name":"_status","type":"uint8"}],"name":"setSaleStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526107d0600a556706ccd46763f10000600b5567083019dfc17b0000600c553480156200002f57600080fd5b5060405162002d7b38038062002d7b8339810160408190526200005291620001d9565b604080518082018252600e8082526d45746865726e616c20476174657360901b6020808401828152855180870190965292855284015281519192916200009b9160029162000133565b508051620000b190600390602084019062000133565b5050600160005550620000c433620000e1565b8051620000d990600990602084019062000133565b505062000302565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8280546200014190620002af565b90600052602060002090601f016020900481019282620001655760008555620001b0565b82601f106200018057805160ff1916838001178555620001b0565b82800160010185558215620001b0579182015b82811115620001b057825182559160200191906001019062000193565b50620001be929150620001c2565b5090565b5b80821115620001be5760008155600101620001c3565b60006020808385031215620001ec578182fd5b82516001600160401b038082111562000203578384fd5b818501915085601f83011262000217578384fd5b8151818111156200022c576200022c620002ec565b604051601f8201601f19908116603f01168101908382118183101715620002575762000257620002ec565b8160405282815288868487010111156200026f578687fd5b8693505b8284101562000292578484018601518185018701529285019262000273565b82841115620002a357868684830101525b98975050505050505050565b600181811c90821680620002c457607f821691505b60208210811415620002e657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b612a6980620003126000396000f3fe60806040526004361061022f5760003560e01c806370a082311161012e578063a22cb465116100ab578063c23dc68f1161006f578063c23dc68f146106a7578063c87b56dd146106d4578063e985e9c5146106f4578063f2fde38b14610714578063f9020e331461073457600080fd5b8063a22cb46514610611578063a945bf8014610631578063b88d4fde14610647578063b921e16314610667578063c204642c1461068757600080fd5b80638606d938116100f25780638606d9381461057e5780638da5cb5b1461059e57806395d89b41146105bc57806399a2557a146105d15780639d7e8d5f146105f157600080fd5b806370a08231146104e6578063715018a614610506578063771282f61461051b5780637cb64759146105315780638462151c1461055157600080fd5b80632eb4a7ab116101bc5780634aa8a13b116101805780634aa8a13b146103ed578063532778791461040d57806355f804b3146104795780635bbb2177146104995780636352211e146104c657600080fd5b80632eb4a7ab1461036c57806332cb6b0c146103825780633ccfd60b1461039857806342842e0e146103ad5780634891ad88146103cd57600080fd5b8063095ea7b311610203578063095ea7b3146102e757806318160ddd146103095780631e6a77f61461032657806323b872dd146103395780632db115441461035957600080fd5b80620e7fa81461023457806301ffc9a71461025d57806306fdde031461028d578063081812fc146102af575b600080fd5b34801561024057600080fd5b5061024a600b5481565b6040519081526020015b60405180910390f35b34801561026957600080fd5b5061027d6102783660046125d1565b610762565b6040519015158152602001610254565b34801561029957600080fd5b506102a26107b4565b60405161025491906127f6565b3480156102bb57600080fd5b506102cf6102ca3660046125b9565b610846565b6040516001600160a01b039091168152602001610254565b3480156102f357600080fd5b5061030761030236600461239a565b61088a565b005b34801561031557600080fd5b50600154600054036000190161024a565b610307610334366004612499565b610918565b34801561034557600080fd5b5061030761035436600461226e565b610ca5565b6103076103673660046125b9565b610cb0565b34801561037857600080fd5b5061024a600d5481565b34801561038e57600080fd5b5061024a61177081565b3480156103a457600080fd5b50610307610d73565b3480156103b957600080fd5b506103076103c836600461226e565b610e12565b3480156103d957600080fd5b506103076103e8366004612609565b610e2d565b3480156103f957600080fd5b506103076104083660046125b9565b610e92565b34801561041957600080fd5b50610454610428366004612222565b600e6020526000908152604090205461ffff808216916201000081048216916401000000009091041683565b6040805161ffff94851681529284166020840152921691810191909152606001610254565b34801561048557600080fd5b50610307610494366004612628565b610ef7565b3480156104a557600080fd5b506104b96104b4366004612527565b610f2d565b604051610254919061272c565b3480156104d257600080fd5b506102cf6104e13660046125b9565b61101d565b3480156104f257600080fd5b5061024a610501366004612222565b61102f565b34801561051257600080fd5b5061030761107d565b34801561052757600080fd5b5061024a600a5481565b34801561053d57600080fd5b5061030761054c3660046125b9565b6110b3565b34801561055d57600080fd5b5061057161056c366004612222565b6110e2565b6040516102549190612796565b34801561058a57600080fd5b506103076105993660046125b9565b61124b565b3480156105aa57600080fd5b506008546001600160a01b03166102cf565b3480156105c857600080fd5b506102a261127a565b3480156105dd57600080fd5b506105716105ec3660046123c3565b611289565b3480156105fd57600080fd5b5061030761060c3660046125b9565b61146b565b34801561061d57600080fd5b5061030761062c366004612360565b61149a565b34801561063d57600080fd5b5061024a600c5481565b34801561065357600080fd5b506103076106623660046122a9565b611530565b34801561067357600080fd5b506103076106823660046125b9565b611581565b34801561069357600080fd5b506103076106a23660046123f5565b6115e6565b3480156106b357600080fd5b506106c76106c23660046125b9565b6116b4565b604051610254919061283e565b3480156106e057600080fd5b506102a26106ef3660046125b9565b61176e565b34801561070057600080fd5b5061027d61070f36600461223c565b6117f2565b34801561072057600080fd5b5061030761072f366004612222565b611820565b34801561074057600080fd5b5060085461075590600160a01b900460ff1681565b60405161025491906127ce565b60006001600160e01b031982166380ac58cd60e01b148061079357506001600160e01b03198216635b5e139f60e01b145b806107ae57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600280546107c390612971565b80601f01602080910402602001604051908101604052809291908181526020018280546107ef90612971565b801561083c5780601f106108115761010080835404028352916020019161083c565b820191906000526020600020905b81548152906001019060200180831161081f57829003601f168201915b5050505050905090565b6000610851826118b8565b61086e576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b60006108958261101d565b9050806001600160a01b0316836001600160a01b031614156108ca5760405163250fdee360e21b815260040160405180910390fd5b336001600160a01b038216148015906108ea57506108e881336117f2565b155b15610908576040516367d9dca160e11b815260040160405180910390fd5b6109138383836118f1565b505050565b8061ffff16600a548161092e6000546000190190565b61093891906128e3565b111561095757604051638f0c6ebf60e01b815260040160405180910390fd5b600854336000908152600e602090815260408083208151606081018352905461ffff8082168352620100008204811694830194909452640100000000900490921690820152600160a01b90920460ff1691908260048111156109c957634e487b7160e01b600052602160045260246000fd5b14806109f4575060048260048111156109f257634e487b7160e01b600052602160045260246000fd5b145b15610a1257604051631385865760e21b815260040160405180910390fd5b610a8e87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600d546040516bffffffffffffffffffffffff193360601b166020820152603481018b905290925060540190506040516020818303038152906040528051906020012061194d565b610aab57604051633f8d373d60e21b815260040160405180910390fd5b848461ffff161115610ad057604051632998588d60e21b815260040160405180910390fd5b8361ffff16600b54610ae2919061290f565b341015610b0257604051635fa2c2b960e11b815260040160405180910390fd5b6001826004811115610b2457634e487b7160e01b600052602160045260246000fd5b1415610b79578051610b379085906128c6565b61ffff16851015610b5b5760405163584db25960e11b815260040160405180910390fd5b8381600001818151610b6d91906128c6565b61ffff16905250610c35565b6002826004811115610b9b57634e487b7160e01b600052602160045260246000fd5b1415610be757838160200151610bb191906128c6565b61ffff16851015610bd55760405163584db25960e11b815260040160405180910390fd5b8381602001818151610b6d91906128c6565b838160400151610bf791906128c6565b61ffff16851015610c1b5760405163584db25960e11b815260040160405180910390fd5b8381604001818151610c2d91906128c6565b61ffff169052505b336000818152600e602090815260409182902084518154928601519386015161ffff9081166401000000000265ffff0000000019958216620100000263ffffffff1990951692821692909217939093179390931692909217909155610c9c91908616611963565b50505050505050565b61091383838361199f565b80600a5481610cc26000546000190190565b610ccc91906128e3565b1115610ceb57604051638f0c6ebf60e01b815260040160405180910390fd5b6004600854600160a01b900460ff166004811115610d1957634e487b7160e01b600052602160045260246000fd5b14610d375760405163ac4d09c760e01b815260040160405180910390fd5b81600c54610d45919061290f565b341015610d6557604051635fa2c2b960e11b815260040160405180910390fd5b610d6f3383611963565b5050565b6008546001600160a01b03163314610da65760405162461bcd60e51b8152600401610d9d90612809565b60405180910390fd5b604051600090339047908381818185875af1925050503d8060008114610de8576040519150601f19603f3d011682016040523d82523d6000602084013e610ded565b606091505b5050905080610e0f576040516312171d8360e31b815260040160405180910390fd5b50565b61091383838360405180602001604052806000815250611530565b6008546001600160a01b03163314610e575760405162461bcd60e51b8152600401610d9d90612809565b6008805482919060ff60a01b1916600160a01b836004811115610e8a57634e487b7160e01b600052602160045260246000fd5b021790555050565b6008546001600160a01b03163314610ebc5760405162461bcd60e51b8152600401610d9d90612809565b80600a5481610ece6000546000190190565b610ed891906128e3565b1115610d6557604051638f0c6ebf60e01b815260040160405180910390fd5b6008546001600160a01b03163314610f215760405162461bcd60e51b8152600401610d9d90612809565b6109136009838361216d565b80516060906000816001600160401b03811115610f5a57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610fa557816020015b6040805160608101825260008082526020808301829052928201528252600019909201910181610f785790505b50905060005b82811461101557610fe2858281518110610fd557634e487b7160e01b600052603260045260246000fd5b60200260200101516116b4565b82828151811061100257634e487b7160e01b600052603260045260246000fd5b6020908102919091010152600101610fab565b509392505050565b600061102882611b8a565b5192915050565b60006001600160a01b038216611058576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b03166000908152600560205260409020546001600160401b031690565b6008546001600160a01b031633146110a75760405162461bcd60e51b8152600401610d9d90612809565b6110b16000611cb1565b565b6008546001600160a01b031633146110dd5760405162461bcd60e51b8152600401610d9d90612809565b600d55565b606060008060006110f28561102f565b90506000816001600160401b0381111561111c57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611145578160200160208202803683370190505b50905061116b604080516060810182526000808252602082018190529181019190915290565b60015b83861461123f57600081815260046020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff161580159282019290925292506111d457611237565b81516001600160a01b0316156111e957815194505b876001600160a01b0316856001600160a01b03161415611237578083878060010198508151811061122a57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b60010161116e565b50909695505050505050565b6008546001600160a01b031633146112755760405162461bcd60e51b8152600401610d9d90612809565b600b55565b6060600380546107c390612971565b60608183106112ab57604051631960ccad60e11b815260040160405180910390fd5b6000805460018510156112bd57600194505b808411156112c9578093505b60006112d48761102f565b9050848610156112f357858503818110156112ed578091505b506112f7565b5060005b6000816001600160401b0381111561131f57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611348578160200160208202803683370190505b5090508161135b57935061146492505050565b6000611366886116b4565b905060008160400151611377575080515b885b8881141580156113895750848714155b1561145857600081815260046020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff161580159282019290925293506113ed57611450565b82516001600160a01b03161561140257825191505b8a6001600160a01b0316826001600160a01b03161415611450578084888060010199508151811061144357634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b600101611379565b50505092835250909150505b9392505050565b6008546001600160a01b031633146114955760405162461bcd60e51b8152600401610d9d90612809565b600c55565b6001600160a01b0382163314156114c45760405163b06307db60e01b815260040160405180910390fd5b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61153b84848461199f565b6001600160a01b0383163b1515801561155d575061155b84848484611d03565b155b1561157b576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b6008546001600160a01b031633146115ab5760405162461bcd60e51b8152600401610d9d90612809565b61177081600a546115bc91906128e3565b11156115db5760405163a3d4a1b360e01b815260040160405180910390fd5b600a80549091019055565b6008546001600160a01b031633146116105760405162461bcd60e51b8152600401610d9d90612809565b815161161c908261290f565b600a548161162d6000546000190190565b61163791906128e3565b111561165657604051638f0c6ebf60e01b815260040160405180910390fd5b825160005b8181146116ad576116a585828151811061168557634e487b7160e01b600052603260045260246000fd5b602002602001015185604051806020016040528060008152506000611dfb565b60010161165b565b5050505050565b604080516060808201835260008083526020808401829052838501829052845192830185528183528201819052928101929092529060018310806116fa57506000548310155b156117055792915050565b50600082815260046020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff1615801592820192909252906117655792915050565b61146483611b8a565b6060611779826118b8565b61179657604051630a14c4b560e41b815260040160405180910390fd5b60006117a0611fcb565b90508051600014156117c15760405180602001604052806000815250611464565b806117cb84611fda565b6040516020016117dc9291906126c0565b6040516020818303038152906040529392505050565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b6008546001600160a01b0316331461184a5760405162461bcd60e51b8152600401610d9d90612809565b6001600160a01b0381166118af5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d9d565b610e0f81611cb1565b6000816001111580156118cc575060005482105b80156107ae575050600090815260046020526040902054600160e01b900460ff161590565b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60008261195a85846120f3565b14949350505050565b32331461198357604051637df1f81760e01b815260040160405180910390fd5b610d6f8282604051806020016040528060008152506000611dfb565b60006119aa82611b8a565b9050836001600160a01b031681600001516001600160a01b0316146119e15760405162a1148160e81b815260040160405180910390fd5b6000336001600160a01b03861614806119ff57506119ff85336117f2565b80611a1a575033611a0f84610846565b6001600160a01b0316145b905080611a3a57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b038416611a6157604051633a954ecd60e21b815260040160405180910390fd5b611a6d600084876118f1565b6001600160a01b038581166000908152600560209081526040808320805467ffffffffffffffff198082166001600160401b0392831660001901831617909255898616808652838620805493841693831660019081018416949094179055898652600490945282852080546001600160e01b031916909417600160a01b42909216919091021783558701808452922080549193909116611b41576000548214611b4157805460208601516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b038a16171781555b50505082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46116ad565b60408051606081018252600080825260208201819052918101919091528180600111158015611bba575060005481105b15611c9857600081815260046020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff16151591810182905290611c965780516001600160a01b031615611c2d579392505050565b5060001901600081815260046020908152604091829020825160608101845290546001600160a01b038116808352600160a01b82046001600160401b031693830193909352600160e01b900460ff1615159281019290925215611c91579392505050565b611c2d565b505b604051636f96cda160e11b815260040160405180910390fd5b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290611d389033908990889088906004016126ef565b602060405180830381600087803b158015611d5257600080fd5b505af1925050508015611d82575060408051601f3d908101601f19168201909252611d7f918101906125ed565b60015b611ddd573d808015611db0576040519150601f19603f3d011682016040523d82523d6000602084013e611db5565b606091505b508051611dd5576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b6000546001600160a01b038516611e2457604051622e076360e81b815260040160405180910390fd5b83611e425760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b038516600081815260056020908152604080832080546fffffffffffffffffffffffffffffffff1981166001600160401b038083168c0181169182176801000000000000000067ffffffffffffffff1990941690921783900481168c01811690920217909155858452600490925290912080546001600160e01b031916909217600160a01b429092169190910217905580808501838015611ef357506001600160a01b0387163b15155b15611f7c575b60405182906001600160a01b038916906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4611f446000888480600101955088611d03565b611f61576040516368d2bf6b60e11b815260040160405180910390fd5b80821415611ef9578260005414611f7757600080fd5b611fc2565b5b6040516001830192906001600160a01b038916906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a480821415611f7d575b506000556116ad565b6060600980546107c390612971565b606081611ffe5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156120285780612012816129ac565b91506120219050600a836128fb565b9150612002565b6000816001600160401b0381111561205057634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561207a576020820181803683370190505b5090505b8415611df35761208f60018361292e565b915061209c600a866129c7565b6120a79060306128e3565b60f81b8183815181106120ca57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506120ec600a866128fb565b945061207e565b600081815b845181101561101557600085828151811061212357634e487b7160e01b600052603260045260246000fd5b60200260200101519050808311612149576000838152602082905260409020925061215a565b600081815260208490526040902092505b5080612165816129ac565b9150506120f8565b82805461217990612971565b90600052602060002090601f01602090048101928261219b57600085556121e1565b82601f106121b45782800160ff198235161785556121e1565b828001600101855582156121e1579182015b828111156121e15782358255916020019190600101906121c6565b506121ed9291506121f1565b5090565b5b808211156121ed57600081556001016121f2565b80356001600160a01b038116811461221d57600080fd5b919050565b600060208284031215612233578081fd5b61146482612206565b6000806040838503121561224e578081fd5b61225783612206565b915061226560208401612206565b90509250929050565b600080600060608486031215612282578081fd5b61228b84612206565b925061229960208501612206565b9150604084013590509250925092565b600080600080608085870312156122be578081fd5b6122c785612206565b935060206122d6818701612206565b93506040860135925060608601356001600160401b03808211156122f8578384fd5b818801915088601f83011261230b578384fd5b81358181111561231d5761231d612a07565b61232f601f8201601f19168501612873565b91508082528984828501011115612344578485fd5b8084840185840137810190920192909252939692955090935050565b60008060408385031215612372578182fd5b61237b83612206565b91506020830135801515811461238f578182fd5b809150509250929050565b600080604083850312156123ac578182fd5b6123b583612206565b946020939093013593505050565b6000806000606084860312156123d7578283fd5b6123e084612206565b95602085013595506040909401359392505050565b60008060408385031215612407578182fd5b82356001600160401b0381111561241c578283fd5b8301601f8101851361242c578283fd5b8035602061244161243c836128a3565b612873565b80838252828201915082850189848660051b8801011115612460578788fd5b8795505b848610156124895761247581612206565b835260019590950194918301918301612464565b5098969091013596505050505050565b600080600080606085870312156124ae578182fd5b84356001600160401b03808211156124c4578384fd5b818701915087601f8301126124d7578384fd5b8135818111156124e5578485fd5b8860208260051b85010111156124f9578485fd5b602092830196509450508501359150604085013561ffff8116811461251c578182fd5b939692955090935050565b60006020808385031215612539578182fd5b82356001600160401b0381111561254e578283fd5b8301601f8101851361255e578283fd5b803561256c61243c826128a3565b80828252848201915084840188868560051b870101111561258b578687fd5b8694505b838510156125ad57803583526001949094019391850191850161258f565b50979650505050505050565b6000602082840312156125ca578081fd5b5035919050565b6000602082840312156125e2578081fd5b813561146481612a1d565b6000602082840312156125fe578081fd5b815161146481612a1d565b60006020828403121561261a578081fd5b813560058110611464578182fd5b6000806020838503121561263a578182fd5b82356001600160401b0380821115612650578384fd5b818501915085601f830112612663578384fd5b813581811115612671578485fd5b866020828501011115612682578485fd5b60209290920196919550909350505050565b600081518084526126ac816020860160208601612945565b601f01601f19169290920160200192915050565b600083516126d2818460208801612945565b8351908301906126e6818360208801612945565b01949350505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061272290830184612694565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561123f5761278383855180516001600160a01b031682526020808201516001600160401b0316908301526040908101511515910152565b9284019260609290920191600101612748565b6020808252825182820181905260009190848201906040850190845b8181101561123f578351835292840192918401916001016127b2565b60208101600583106127f057634e487b7160e01b600052602160045260246000fd5b91905290565b6020815260006114646020830184612694565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b81516001600160a01b031681526020808301516001600160401b031690820152604080830151151590820152606081016107ae565b604051601f8201601f191681016001600160401b038111828210171561289b5761289b612a07565b604052919050565b60006001600160401b038211156128bc576128bc612a07565b5060051b60200190565b600061ffff8083168185168083038211156126e6576126e66129db565b600082198211156128f6576128f66129db565b500190565b60008261290a5761290a6129f1565b500490565b6000816000190483118215151615612929576129296129db565b500290565b600082821015612940576129406129db565b500390565b60005b83811015612960578181015183820152602001612948565b8381111561157b5750506000910152565b600181811c9082168061298557607f821691505b602082108114156129a657634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156129c0576129c06129db565b5060010190565b6000826129d6576129d66129f1565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b031981168114610e0f57600080fdfea26469706673582212206031a4213767e9f2d94f57f1da1f277b7b762d92a7d93e4d0f5de9dc72ec97b864736f6c6343000804003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361061022f5760003560e01c806370a082311161012e578063a22cb465116100ab578063c23dc68f1161006f578063c23dc68f146106a7578063c87b56dd146106d4578063e985e9c5146106f4578063f2fde38b14610714578063f9020e331461073457600080fd5b8063a22cb46514610611578063a945bf8014610631578063b88d4fde14610647578063b921e16314610667578063c204642c1461068757600080fd5b80638606d938116100f25780638606d9381461057e5780638da5cb5b1461059e57806395d89b41146105bc57806399a2557a146105d15780639d7e8d5f146105f157600080fd5b806370a08231146104e6578063715018a614610506578063771282f61461051b5780637cb64759146105315780638462151c1461055157600080fd5b80632eb4a7ab116101bc5780634aa8a13b116101805780634aa8a13b146103ed578063532778791461040d57806355f804b3146104795780635bbb2177146104995780636352211e146104c657600080fd5b80632eb4a7ab1461036c57806332cb6b0c146103825780633ccfd60b1461039857806342842e0e146103ad5780634891ad88146103cd57600080fd5b8063095ea7b311610203578063095ea7b3146102e757806318160ddd146103095780631e6a77f61461032657806323b872dd146103395780632db115441461035957600080fd5b80620e7fa81461023457806301ffc9a71461025d57806306fdde031461028d578063081812fc146102af575b600080fd5b34801561024057600080fd5b5061024a600b5481565b6040519081526020015b60405180910390f35b34801561026957600080fd5b5061027d6102783660046125d1565b610762565b6040519015158152602001610254565b34801561029957600080fd5b506102a26107b4565b60405161025491906127f6565b3480156102bb57600080fd5b506102cf6102ca3660046125b9565b610846565b6040516001600160a01b039091168152602001610254565b3480156102f357600080fd5b5061030761030236600461239a565b61088a565b005b34801561031557600080fd5b50600154600054036000190161024a565b610307610334366004612499565b610918565b34801561034557600080fd5b5061030761035436600461226e565b610ca5565b6103076103673660046125b9565b610cb0565b34801561037857600080fd5b5061024a600d5481565b34801561038e57600080fd5b5061024a61177081565b3480156103a457600080fd5b50610307610d73565b3480156103b957600080fd5b506103076103c836600461226e565b610e12565b3480156103d957600080fd5b506103076103e8366004612609565b610e2d565b3480156103f957600080fd5b506103076104083660046125b9565b610e92565b34801561041957600080fd5b50610454610428366004612222565b600e6020526000908152604090205461ffff808216916201000081048216916401000000009091041683565b6040805161ffff94851681529284166020840152921691810191909152606001610254565b34801561048557600080fd5b50610307610494366004612628565b610ef7565b3480156104a557600080fd5b506104b96104b4366004612527565b610f2d565b604051610254919061272c565b3480156104d257600080fd5b506102cf6104e13660046125b9565b61101d565b3480156104f257600080fd5b5061024a610501366004612222565b61102f565b34801561051257600080fd5b5061030761107d565b34801561052757600080fd5b5061024a600a5481565b34801561053d57600080fd5b5061030761054c3660046125b9565b6110b3565b34801561055d57600080fd5b5061057161056c366004612222565b6110e2565b6040516102549190612796565b34801561058a57600080fd5b506103076105993660046125b9565b61124b565b3480156105aa57600080fd5b506008546001600160a01b03166102cf565b3480156105c857600080fd5b506102a261127a565b3480156105dd57600080fd5b506105716105ec3660046123c3565b611289565b3480156105fd57600080fd5b5061030761060c3660046125b9565b61146b565b34801561061d57600080fd5b5061030761062c366004612360565b61149a565b34801561063d57600080fd5b5061024a600c5481565b34801561065357600080fd5b506103076106623660046122a9565b611530565b34801561067357600080fd5b506103076106823660046125b9565b611581565b34801561069357600080fd5b506103076106a23660046123f5565b6115e6565b3480156106b357600080fd5b506106c76106c23660046125b9565b6116b4565b604051610254919061283e565b3480156106e057600080fd5b506102a26106ef3660046125b9565b61176e565b34801561070057600080fd5b5061027d61070f36600461223c565b6117f2565b34801561072057600080fd5b5061030761072f366004612222565b611820565b34801561074057600080fd5b5060085461075590600160a01b900460ff1681565b60405161025491906127ce565b60006001600160e01b031982166380ac58cd60e01b148061079357506001600160e01b03198216635b5e139f60e01b145b806107ae57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600280546107c390612971565b80601f01602080910402602001604051908101604052809291908181526020018280546107ef90612971565b801561083c5780601f106108115761010080835404028352916020019161083c565b820191906000526020600020905b81548152906001019060200180831161081f57829003601f168201915b5050505050905090565b6000610851826118b8565b61086e576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b60006108958261101d565b9050806001600160a01b0316836001600160a01b031614156108ca5760405163250fdee360e21b815260040160405180910390fd5b336001600160a01b038216148015906108ea57506108e881336117f2565b155b15610908576040516367d9dca160e11b815260040160405180910390fd5b6109138383836118f1565b505050565b8061ffff16600a548161092e6000546000190190565b61093891906128e3565b111561095757604051638f0c6ebf60e01b815260040160405180910390fd5b600854336000908152600e602090815260408083208151606081018352905461ffff8082168352620100008204811694830194909452640100000000900490921690820152600160a01b90920460ff1691908260048111156109c957634e487b7160e01b600052602160045260246000fd5b14806109f4575060048260048111156109f257634e487b7160e01b600052602160045260246000fd5b145b15610a1257604051631385865760e21b815260040160405180910390fd5b610a8e87878080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600d546040516bffffffffffffffffffffffff193360601b166020820152603481018b905290925060540190506040516020818303038152906040528051906020012061194d565b610aab57604051633f8d373d60e21b815260040160405180910390fd5b848461ffff161115610ad057604051632998588d60e21b815260040160405180910390fd5b8361ffff16600b54610ae2919061290f565b341015610b0257604051635fa2c2b960e11b815260040160405180910390fd5b6001826004811115610b2457634e487b7160e01b600052602160045260246000fd5b1415610b79578051610b379085906128c6565b61ffff16851015610b5b5760405163584db25960e11b815260040160405180910390fd5b8381600001818151610b6d91906128c6565b61ffff16905250610c35565b6002826004811115610b9b57634e487b7160e01b600052602160045260246000fd5b1415610be757838160200151610bb191906128c6565b61ffff16851015610bd55760405163584db25960e11b815260040160405180910390fd5b8381602001818151610b6d91906128c6565b838160400151610bf791906128c6565b61ffff16851015610c1b5760405163584db25960e11b815260040160405180910390fd5b8381604001818151610c2d91906128c6565b61ffff169052505b336000818152600e602090815260409182902084518154928601519386015161ffff9081166401000000000265ffff0000000019958216620100000263ffffffff1990951692821692909217939093179390931692909217909155610c9c91908616611963565b50505050505050565b61091383838361199f565b80600a5481610cc26000546000190190565b610ccc91906128e3565b1115610ceb57604051638f0c6ebf60e01b815260040160405180910390fd5b6004600854600160a01b900460ff166004811115610d1957634e487b7160e01b600052602160045260246000fd5b14610d375760405163ac4d09c760e01b815260040160405180910390fd5b81600c54610d45919061290f565b341015610d6557604051635fa2c2b960e11b815260040160405180910390fd5b610d6f3383611963565b5050565b6008546001600160a01b03163314610da65760405162461bcd60e51b8152600401610d9d90612809565b60405180910390fd5b604051600090339047908381818185875af1925050503d8060008114610de8576040519150601f19603f3d011682016040523d82523d6000602084013e610ded565b606091505b5050905080610e0f576040516312171d8360e31b815260040160405180910390fd5b50565b61091383838360405180602001604052806000815250611530565b6008546001600160a01b03163314610e575760405162461bcd60e51b8152600401610d9d90612809565b6008805482919060ff60a01b1916600160a01b836004811115610e8a57634e487b7160e01b600052602160045260246000fd5b021790555050565b6008546001600160a01b03163314610ebc5760405162461bcd60e51b8152600401610d9d90612809565b80600a5481610ece6000546000190190565b610ed891906128e3565b1115610d6557604051638f0c6ebf60e01b815260040160405180910390fd5b6008546001600160a01b03163314610f215760405162461bcd60e51b8152600401610d9d90612809565b6109136009838361216d565b80516060906000816001600160401b03811115610f5a57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610fa557816020015b6040805160608101825260008082526020808301829052928201528252600019909201910181610f785790505b50905060005b82811461101557610fe2858281518110610fd557634e487b7160e01b600052603260045260246000fd5b60200260200101516116b4565b82828151811061100257634e487b7160e01b600052603260045260246000fd5b6020908102919091010152600101610fab565b509392505050565b600061102882611b8a565b5192915050565b60006001600160a01b038216611058576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b03166000908152600560205260409020546001600160401b031690565b6008546001600160a01b031633146110a75760405162461bcd60e51b8152600401610d9d90612809565b6110b16000611cb1565b565b6008546001600160a01b031633146110dd5760405162461bcd60e51b8152600401610d9d90612809565b600d55565b606060008060006110f28561102f565b90506000816001600160401b0381111561111c57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611145578160200160208202803683370190505b50905061116b604080516060810182526000808252602082018190529181019190915290565b60015b83861461123f57600081815260046020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff161580159282019290925292506111d457611237565b81516001600160a01b0316156111e957815194505b876001600160a01b0316856001600160a01b03161415611237578083878060010198508151811061122a57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b60010161116e565b50909695505050505050565b6008546001600160a01b031633146112755760405162461bcd60e51b8152600401610d9d90612809565b600b55565b6060600380546107c390612971565b60608183106112ab57604051631960ccad60e11b815260040160405180910390fd5b6000805460018510156112bd57600194505b808411156112c9578093505b60006112d48761102f565b9050848610156112f357858503818110156112ed578091505b506112f7565b5060005b6000816001600160401b0381111561131f57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611348578160200160208202803683370190505b5090508161135b57935061146492505050565b6000611366886116b4565b905060008160400151611377575080515b885b8881141580156113895750848714155b1561145857600081815260046020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff161580159282019290925293506113ed57611450565b82516001600160a01b03161561140257825191505b8a6001600160a01b0316826001600160a01b03161415611450578084888060010199508151811061144357634e487b7160e01b600052603260045260246000fd5b6020026020010181815250505b600101611379565b50505092835250909150505b9392505050565b6008546001600160a01b031633146114955760405162461bcd60e51b8152600401610d9d90612809565b600c55565b6001600160a01b0382163314156114c45760405163b06307db60e01b815260040160405180910390fd5b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61153b84848461199f565b6001600160a01b0383163b1515801561155d575061155b84848484611d03565b155b1561157b576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b6008546001600160a01b031633146115ab5760405162461bcd60e51b8152600401610d9d90612809565b61177081600a546115bc91906128e3565b11156115db5760405163a3d4a1b360e01b815260040160405180910390fd5b600a80549091019055565b6008546001600160a01b031633146116105760405162461bcd60e51b8152600401610d9d90612809565b815161161c908261290f565b600a548161162d6000546000190190565b61163791906128e3565b111561165657604051638f0c6ebf60e01b815260040160405180910390fd5b825160005b8181146116ad576116a585828151811061168557634e487b7160e01b600052603260045260246000fd5b602002602001015185604051806020016040528060008152506000611dfb565b60010161165b565b5050505050565b604080516060808201835260008083526020808401829052838501829052845192830185528183528201819052928101929092529060018310806116fa57506000548310155b156117055792915050565b50600082815260046020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff1615801592820192909252906117655792915050565b61146483611b8a565b6060611779826118b8565b61179657604051630a14c4b560e41b815260040160405180910390fd5b60006117a0611fcb565b90508051600014156117c15760405180602001604052806000815250611464565b806117cb84611fda565b6040516020016117dc9291906126c0565b6040516020818303038152906040529392505050565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b6008546001600160a01b0316331461184a5760405162461bcd60e51b8152600401610d9d90612809565b6001600160a01b0381166118af5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d9d565b610e0f81611cb1565b6000816001111580156118cc575060005482105b80156107ae575050600090815260046020526040902054600160e01b900460ff161590565b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60008261195a85846120f3565b14949350505050565b32331461198357604051637df1f81760e01b815260040160405180910390fd5b610d6f8282604051806020016040528060008152506000611dfb565b60006119aa82611b8a565b9050836001600160a01b031681600001516001600160a01b0316146119e15760405162a1148160e81b815260040160405180910390fd5b6000336001600160a01b03861614806119ff57506119ff85336117f2565b80611a1a575033611a0f84610846565b6001600160a01b0316145b905080611a3a57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b038416611a6157604051633a954ecd60e21b815260040160405180910390fd5b611a6d600084876118f1565b6001600160a01b038581166000908152600560209081526040808320805467ffffffffffffffff198082166001600160401b0392831660001901831617909255898616808652838620805493841693831660019081018416949094179055898652600490945282852080546001600160e01b031916909417600160a01b42909216919091021783558701808452922080549193909116611b41576000548214611b4157805460208601516001600160401b0316600160a01b026001600160e01b03199091166001600160a01b038a16171781555b50505082846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46116ad565b60408051606081018252600080825260208201819052918101919091528180600111158015611bba575060005481105b15611c9857600081815260046020908152604091829020825160608101845290546001600160a01b0381168252600160a01b81046001600160401b031692820192909252600160e01b90910460ff16151591810182905290611c965780516001600160a01b031615611c2d579392505050565b5060001901600081815260046020908152604091829020825160608101845290546001600160a01b038116808352600160a01b82046001600160401b031693830193909352600160e01b900460ff1615159281019290925215611c91579392505050565b611c2d565b505b604051636f96cda160e11b815260040160405180910390fd5b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290611d389033908990889088906004016126ef565b602060405180830381600087803b158015611d5257600080fd5b505af1925050508015611d82575060408051601f3d908101601f19168201909252611d7f918101906125ed565b60015b611ddd573d808015611db0576040519150601f19603f3d011682016040523d82523d6000602084013e611db5565b606091505b508051611dd5576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b6000546001600160a01b038516611e2457604051622e076360e81b815260040160405180910390fd5b83611e425760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b038516600081815260056020908152604080832080546fffffffffffffffffffffffffffffffff1981166001600160401b038083168c0181169182176801000000000000000067ffffffffffffffff1990941690921783900481168c01811690920217909155858452600490925290912080546001600160e01b031916909217600160a01b429092169190910217905580808501838015611ef357506001600160a01b0387163b15155b15611f7c575b60405182906001600160a01b038916906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4611f446000888480600101955088611d03565b611f61576040516368d2bf6b60e11b815260040160405180910390fd5b80821415611ef9578260005414611f7757600080fd5b611fc2565b5b6040516001830192906001600160a01b038916906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a480821415611f7d575b506000556116ad565b6060600980546107c390612971565b606081611ffe5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156120285780612012816129ac565b91506120219050600a836128fb565b9150612002565b6000816001600160401b0381111561205057634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561207a576020820181803683370190505b5090505b8415611df35761208f60018361292e565b915061209c600a866129c7565b6120a79060306128e3565b60f81b8183815181106120ca57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506120ec600a866128fb565b945061207e565b600081815b845181101561101557600085828151811061212357634e487b7160e01b600052603260045260246000fd5b60200260200101519050808311612149576000838152602082905260409020925061215a565b600081815260208490526040902092505b5080612165816129ac565b9150506120f8565b82805461217990612971565b90600052602060002090601f01602090048101928261219b57600085556121e1565b82601f106121b45782800160ff198235161785556121e1565b828001600101855582156121e1579182015b828111156121e15782358255916020019190600101906121c6565b506121ed9291506121f1565b5090565b5b808211156121ed57600081556001016121f2565b80356001600160a01b038116811461221d57600080fd5b919050565b600060208284031215612233578081fd5b61146482612206565b6000806040838503121561224e578081fd5b61225783612206565b915061226560208401612206565b90509250929050565b600080600060608486031215612282578081fd5b61228b84612206565b925061229960208501612206565b9150604084013590509250925092565b600080600080608085870312156122be578081fd5b6122c785612206565b935060206122d6818701612206565b93506040860135925060608601356001600160401b03808211156122f8578384fd5b818801915088601f83011261230b578384fd5b81358181111561231d5761231d612a07565b61232f601f8201601f19168501612873565b91508082528984828501011115612344578485fd5b8084840185840137810190920192909252939692955090935050565b60008060408385031215612372578182fd5b61237b83612206565b91506020830135801515811461238f578182fd5b809150509250929050565b600080604083850312156123ac578182fd5b6123b583612206565b946020939093013593505050565b6000806000606084860312156123d7578283fd5b6123e084612206565b95602085013595506040909401359392505050565b60008060408385031215612407578182fd5b82356001600160401b0381111561241c578283fd5b8301601f8101851361242c578283fd5b8035602061244161243c836128a3565b612873565b80838252828201915082850189848660051b8801011115612460578788fd5b8795505b848610156124895761247581612206565b835260019590950194918301918301612464565b5098969091013596505050505050565b600080600080606085870312156124ae578182fd5b84356001600160401b03808211156124c4578384fd5b818701915087601f8301126124d7578384fd5b8135818111156124e5578485fd5b8860208260051b85010111156124f9578485fd5b602092830196509450508501359150604085013561ffff8116811461251c578182fd5b939692955090935050565b60006020808385031215612539578182fd5b82356001600160401b0381111561254e578283fd5b8301601f8101851361255e578283fd5b803561256c61243c826128a3565b80828252848201915084840188868560051b870101111561258b578687fd5b8694505b838510156125ad57803583526001949094019391850191850161258f565b50979650505050505050565b6000602082840312156125ca578081fd5b5035919050565b6000602082840312156125e2578081fd5b813561146481612a1d565b6000602082840312156125fe578081fd5b815161146481612a1d565b60006020828403121561261a578081fd5b813560058110611464578182fd5b6000806020838503121561263a578182fd5b82356001600160401b0380821115612650578384fd5b818501915085601f830112612663578384fd5b813581811115612671578485fd5b866020828501011115612682578485fd5b60209290920196919550909350505050565b600081518084526126ac816020860160208601612945565b601f01601f19169290920160200192915050565b600083516126d2818460208801612945565b8351908301906126e6818360208801612945565b01949350505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061272290830184612694565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561123f5761278383855180516001600160a01b031682526020808201516001600160401b0316908301526040908101511515910152565b9284019260609290920191600101612748565b6020808252825182820181905260009190848201906040850190845b8181101561123f578351835292840192918401916001016127b2565b60208101600583106127f057634e487b7160e01b600052602160045260246000fd5b91905290565b6020815260006114646020830184612694565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b81516001600160a01b031681526020808301516001600160401b031690820152604080830151151590820152606081016107ae565b604051601f8201601f191681016001600160401b038111828210171561289b5761289b612a07565b604052919050565b60006001600160401b038211156128bc576128bc612a07565b5060051b60200190565b600061ffff8083168185168083038211156126e6576126e66129db565b600082198211156128f6576128f66129db565b500190565b60008261290a5761290a6129f1565b500490565b6000816000190483118215151615612929576129296129db565b500290565b600082821015612940576129406129db565b500390565b60005b83811015612960578181015183820152602001612948565b8381111561157b5750506000910152565b600181811c9082168061298557607f821691505b602082108114156129a657634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156129c0576129c06129db565b5060010190565b6000826129d6576129d66129f1565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b031981168114610e0f57600080fdfea26469706673582212206031a4213767e9f2d94f57f1da1f277b7b762d92a7d93e4d0f5de9dc72ec97b864736f6c63430008040033

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

00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : baseURI (string):

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

55468:5391:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55947:40;;;;;;;;;;;;;;;;;;;11709:25:1;;;11697:2;11682:18;55947:40:0;;;;;;;;30183:355;;;;;;;;;;-1:-1:-1;30183:355:0;;;;;:::i;:::-;;:::i;:::-;;;11536:14:1;;11529:22;11511:41;;11499:2;11484:18;30183:355:0;11466:92:1;33378:100:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;34978:245::-;;;;;;;;;;-1:-1:-1;34978:245:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;9464:32:1;;;9446:51;;9434:2;9419:18;34978:245:0;9401:102:1;34541:371:0;;;;;;;;;;-1:-1:-1;34541:371:0;;;;;:::i;:::-;;:::i;:::-;;29432:303;;;;;;;;;;-1:-1:-1;58591:1:0;29686:12;29476:7;29670:13;:28;-1:-1:-1;;29670:46:0;29432:303;;58831:1549;;;;;;:::i;:::-;;:::i;35966:170::-;;;;;;;;;;-1:-1:-1;35966:170:0;;;;;:::i;:::-;;:::i;60410:266::-;;;;;;:::i;:::-;;:::i;56042:25::-;;;;;;;;;;;;;;;;55787:41;;;;;;;;;;;;55824:4;55787:41;;57592:174;;;;;;;;;;;;;:::i;36207:185::-;;;;;;;;;;-1:-1:-1;36207:185:0;;;;;:::i;:::-;;:::i;56701:102::-;;;;;;;;;;-1:-1:-1;56701:102:0;;;;;:::i;:::-;;:::i;57812:156::-;;;;;;;;;;-1:-1:-1;57812:156:0;;;;;:::i;:::-;;:::i;56282:48::-;;;;;;;;;;-1:-1:-1;56282:48:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13562:6:1;13595:15;;;13577:34;;13647:15;;;13642:2;13627:18;;13620:43;13699:15;;13679:18;;;13672:43;;;;13540:2;13525:18;56282:48:0;13507:214:1;56925:105:0;;;;;;;;;;-1:-1:-1;56925:105:0;;;;;:::i;:::-;;:::i;50121:523::-;;;;;;;;;;-1:-1:-1;50121:523:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;33186:125::-;;;;;;;;;;-1:-1:-1;33186:125:0;;;;;:::i;:::-;;:::i;30602:206::-;;;;;;;;;;-1:-1:-1;30602:206:0;;;;;:::i;:::-;;:::i;7265:103::-;;;;;;;;;;;;;:::i;55903:35::-;;;;;;;;;;;;;;;;56811:106;;;;;;;;;;-1:-1:-1;56811:106:0;;;;;:::i;:::-;;:::i;54047:980::-;;;;;;;;;;-1:-1:-1;54047:980:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;57038:117::-;;;;;;;;;;-1:-1:-1;57038:117:0;;;;;:::i;:::-;;:::i;6614:87::-;;;;;;;;;;-1:-1:-1;6687:6:0;;-1:-1:-1;;;;;6687:6:0;6614:87;;33547:104;;;;;;;;;;;;;:::i;51034:2564::-;;;;;;;;;;-1:-1:-1;51034:2564:0;;;;;:::i;:::-;;:::i;57163:113::-;;;;;;;;;;-1:-1:-1;57163:113:0;;;;;:::i;:::-;;:::i;35295:319::-;;;;;;;;;;-1:-1:-1;35295:319:0;;;;;:::i;:::-;;:::i;55994:39::-;;;;;;;;;;;;;;;;36463:406;;;;;;;;;;-1:-1:-1;36463:406:0;;;;;:::i;:::-;;:::i;57334:250::-;;;;;;;;;;-1:-1:-1;57334:250:0;;;;;:::i;:::-;;:::i;57976:367::-;;;;;;;;;;-1:-1:-1;57976:367:0;;;;;:::i;:::-;;:::i;49521:441::-;;;;;;;;;;-1:-1:-1;49521:441:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;33722:415::-;;;;;;;;;;-1:-1:-1;33722:415:0;;;;;:::i;:::-;;:::i;35685:214::-;;;;;;;;;;-1:-1:-1;35685:214:0;;;;;:::i;:::-;;:::i;7523:238::-;;;;;;;;;;-1:-1:-1;7523:238:0;;;;;:::i;:::-;;:::i;55676:29::-;;;;;;;;;;-1:-1:-1;55676:29:0;;;;-1:-1:-1;;;55676:29:0;;;;;;;;;;;;;:::i;30183:355::-;30330:4;-1:-1:-1;;;;;;30372:40:0;;-1:-1:-1;;;30372:40:0;;:105;;-1:-1:-1;;;;;;;30429:48:0;;-1:-1:-1;;;30429:48:0;30372:105;:158;;;-1:-1:-1;;;;;;;;;;20051:40:0;;;30494:36;30352:178;30183:355;-1:-1:-1;;30183:355:0:o;33378:100::-;33432:13;33465:5;33458:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33378:100;:::o;34978:245::-;35082:7;35112:16;35120:7;35112;:16::i;:::-;35107:64;;35137:34;;-1:-1:-1;;;35137:34:0;;;;;;;;;;;35107:64;-1:-1:-1;35191:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;35191:24:0;;34978:245::o;34541:371::-;34614:13;34630:24;34646:7;34630:15;:24::i;:::-;34614:40;;34675:5;-1:-1:-1;;;;;34669:11:0;:2;-1:-1:-1;;;;;34669:11:0;;34665:48;;;34689:24;;-1:-1:-1;;;34689:24:0;;;;;;;;;;;34665:48;5397:10;-1:-1:-1;;;;;34730:21:0;;;;;;:63;;-1:-1:-1;34756:37:0;34773:5;5397:10;35685:214;:::i;34756:37::-;34755:38;34730:63;34726:138;;;34817:35;;-1:-1:-1;;;34817:35:0;;;;;;;;;;;34726:138;34876:28;34885:2;34889:7;34898:5;34876:8;:28::i;:::-;34541:371;;;:::o;58831:1549::-;58976:6;56481:151;;56555:13;;56546:6;56529:14;29875:7;30061:13;-1:-1:-1;;30061:31:0;;29828:283;56529:14;:23;;;;:::i;:::-;:39;56525:87;;;56590:22;;-1:-1:-1;;;56590:22:0;;;;;;;;;;;56525:87;59019:10:::1;::::0;59081::::1;58995:21;59070:22:::0;;;:10:::1;:22;::::0;;;;;;;59040:52;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;;::::1;::::0;;;;-1:-1:-1;;;59019:10:0;;::::1;;;::::0;59040:52;59107:9:::1;:28;;;;;;-1:-1:-1::0;;;59107:28:0::1;;;;;;;;;;:63;;;-1:-1:-1::0;59152:18:0::1;59139:9;:31;;;;;;-1:-1:-1::0;;;59139:31:0::1;;;;;;;;;;59107:63;59103:108;;;59192:19;;-1:-1:-1::0;;;59192:19:0::1;;;;;;;;;;;59103:108;59241:160;59278:6;;59241:160;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;;59303:10:0::1;::::0;59342:43:::1;::::0;-1:-1:-1;;59359:10:0::1;8493:2:1::0;8489:15;8485:53;59342:43:0::1;::::0;::::1;8473:66:1::0;8555:12;;;8548:28;;;59303:10:0;;-1:-1:-1;8592:12:1;;;-1:-1:-1;59342:43:0::1;;;;;;;;;;;;59332:54;;;;;;59241:18;:160::i;:::-;59222:232;;59420:34;;-1:-1:-1::0;;;59420:34:0::1;;;;;;;;;;;59222:232;59478:13;59469:6;:22;;;59465:65;;;59500:30;;-1:-1:-1::0;;;59500:30:0::1;;;;;;;;;;;59465:65;59572:6;59557:21;;:12;;:21;;;;:::i;:::-;59545:9;:33;59541:66;;;59587:20;;-1:-1:-1::0;;;59587:20:0::1;;;;;;;;;;;59541:66;59635:20;59622:9;:33;;;;;;-1:-1:-1::0;;;59622:33:0::1;;;;;;;;;;59618:675;;;59692:27:::0;;:36:::1;::::0;59722:6;;59692:36:::1;:::i;:::-;59676:52;;:13;:52;59672:125;;;59754:43;;-1:-1:-1::0;;;59754:43:0::1;;;;;;;;;;;59672:125;59843:6;59812:9;:27;;:37;;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;59618:675:0::1;;;59884:15;59871:9;:28;;;;;;-1:-1:-1::0;;;59871:28:0::1;;;;;;;;;;59867:426;;;59961:6;59936:9;:22;;;:31;;;;:::i;:::-;59920:47;;:13;:47;59916:120;;;59993:43;;-1:-1:-1::0;;;59993:43:0::1;;;;;;;;;;;59916:120;60077:6;60051:9;:22;;:32;;;;;;;:::i;59867:426::-;60160:6;60136:9;:21;;;:30;;;;:::i;:::-;60120:46;;:13;:46;60116:119;;;60192:43;;-1:-1:-1::0;;;60192:43:0::1;;;;;;;;;;;60116:119;60275:6;60250:9;:21;;:31;;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;59867:426:0::1;60314:10;60303:22;::::0;;;:10:::1;:22;::::0;;;;;;;;:34;;;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;-1:-1:-1::0;;60303:34:0;;::::1;::::0;::::1;-1:-1:-1::0;;60303:34:0;;;;;::::1;::::0;;;;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;60348:24:::1;::::0;60314:10;60348:24;::::1;:4;:24::i;:::-;56623:1;;58831:1549:::0;;;;;:::o;35966:170::-;36100:28;36110:4;36116:2;36120:7;36100:9;:28::i;60410:266::-;60471:6;56555:13;;56546:6;56529:14;29875:7;30061:13;-1:-1:-1;;30061:31:0;;29828:283;56529:14;:23;;;;:::i;:::-;:39;56525:87;;;56590:22;;-1:-1:-1;;;56590:22:0;;;;;;;;;;;56525:87;60508:18:::1;60494:10;::::0;-1:-1:-1;;;60494:10:0;::::1;;;:32;::::0;::::1;;;;-1:-1:-1::0;;;60494:32:0::1;;;;;;;;;;60490:67;;60535:22;;-1:-1:-1::0;;;60535:22:0::1;;;;;;;;;;;60490:67;60598:6;60584:11;;:20;;;;:::i;:::-;60572:9;:32;60568:65;;;60613:20;;-1:-1:-1::0;;;60613:20:0::1;;;;;;;;;;;60568:65;60644:24;60649:10;60661:6;60644:4;:24::i;:::-;60410:266:::0;;:::o;57592:174::-;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;;;;;;;;;57661:49:::1;::::0;57643:12:::1;::::0;57661:10:::1;::::0;57684:21:::1;::::0;57643:12;57661:49;57643:12;57661:49;57684:21;57661:10;:49:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57642:68;;;57726:7;57721:37;;57742:16;;-1:-1:-1::0;;;57742:16:0::1;;;;;;;;;;;57721:37;6905:1;57592:174::o:0;36207:185::-;36345:39;36362:4;36368:2;36372:7;36345:39;;;;;;;;;;;;:16;:39::i;56701:102::-;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;56775:10:::1;:20:::0;;56788:7;;56775:10;-1:-1:-1;;;;56775:20:0::1;-1:-1:-1::0;;;56788:7:0;56775:20:::1;::::0;::::1;;;;-1:-1:-1::0;;;56775:20:0::1;;;;;;;;;;;;;;56701:102:::0;:::o;57812:156::-;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;57912:6:::1;56555:13;;56546:6;56529:14;29875:7:::0;30061:13;-1:-1:-1;;30061:31:0;;29828:283;56529:14:::1;:23;;;;:::i;:::-;:39;56525:87;;;56590:22;;-1:-1:-1::0;;;56590:22:0::1;;;;;;;;;;;56925:105:::0;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;57000:22:::1;:12;57015:7:::0;;57000:22:::1;:::i;50121:523::-:0;50319:15;;50228:23;;50294:22;50319:15;-1:-1:-1;;;;;50386:68:0;;;;;-1:-1:-1;;;50386:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;50386:68:0;;-1:-1:-1;;50386:68:0;;;;;;;;;;;;50349:105;;50474:9;50469:125;50490:14;50485:1;:19;50469:125;;50546:32;50566:8;50575:1;50566:11;;;;;;-1:-1:-1;;;50566:11:0;;;;;;;;;;;;;;;50546:19;:32::i;:::-;50530:10;50541:1;50530:13;;;;;;-1:-1:-1;;;50530:13:0;;;;;;;;;;;;;;;;;;:48;50506:3;;50469:125;;;-1:-1:-1;50615:10:0;50121:523;-1:-1:-1;;;50121:523:0:o;33186:125::-;33250:7;33277:21;33290:7;33277:12;:21::i;:::-;:26;;33186:125;-1:-1:-1;;33186:125:0:o;30602:206::-;30666:7;-1:-1:-1;;;;;30690:19:0;;30686:60;;30718:28;;-1:-1:-1;;;30718:28:0;;;;;;;;;;;30686:60;-1:-1:-1;;;;;;30772:19:0;;;;;:12;:19;;;;;:27;-1:-1:-1;;;;;30772:27:0;;30602:206::o;7265:103::-;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;7330:30:::1;7357:1;7330:18;:30::i;:::-;7265:103::o:0;56811:106::-;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;56885:10:::1;:24:::0;56811:106::o;54047:980::-;54135:16;54194:19;54228:25;54268:22;54293:16;54303:5;54293:9;:16::i;:::-;54268:41;;54324:25;54366:14;-1:-1:-1;;;;;54352:29:0;;;;;-1:-1:-1;;;54352:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;54352:29:0;;54324:57;;54396:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;54396:31:0;58591:1;54442:537;54526:14;54511:11;:29;54442:537;;54609:14;;;;:11;:14;;;;;;;;;54597:26;;;;;;;;;-1:-1:-1;;;;;54597:26:0;;;;-1:-1:-1;;;54597:26:0;;-1:-1:-1;;;;;54597:26:0;;;;;;;;-1:-1:-1;;;54597:26:0;;;;;;;;;;;;;;;;-1:-1:-1;54642:73:0;;54687:8;;54642:73;54737:14;;-1:-1:-1;;;;;54737:28:0;;54733:111;;54810:14;;;-1:-1:-1;54733:111:0;54887:5;-1:-1:-1;;;;;54866:26:0;:17;-1:-1:-1;;;;;54866:26:0;;54862:102;;;54943:1;54917:8;54926:13;;;;;;54917:23;;;;;;-1:-1:-1;;;54917:23:0;;;;;;;;;;;;;;:27;;;;;54862:102;54559:3;;54442:537;;;-1:-1:-1;55000:8:0;;54047:980;-1:-1:-1;;;;;;54047:980:0:o;57038:117::-;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;57119:12:::1;:28:::0;57038:117::o;33547:104::-;33603:13;33636:7;33629:14;;;;;:::i;51034:2564::-;51160:16;51227:4;51218:5;:13;51214:45;;51240:19;;-1:-1:-1;;;51240:19:0;;;;;;;;;;;51214:45;51274:19;51328:13;;58591:1;51419:5;:23;51415:87;;;58591:1;51463:23;;51415:87;51582:9;51575:4;:16;51571:73;;;51619:9;51612:16;;51571:73;51658:25;51686:16;51696:5;51686:9;:16::i;:::-;51658:44;;51880:4;51872:5;:12;51868:278;;;51927:12;;;51962:31;;;51958:111;;;52038:11;52018:31;;51958:111;51868:278;;;;-1:-1:-1;52129:1:0;51868:278;52160:25;52202:17;-1:-1:-1;;;;;52188:32:0;;;;;-1:-1:-1;;;52188:32:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52188:32:0;-1:-1:-1;52160:60:0;-1:-1:-1;52239:22:0;52235:78;;52289:8;-1:-1:-1;52282:15:0;;-1:-1:-1;;;52282:15:0;52235:78;52457:31;52491:26;52511:5;52491:19;:26::i;:::-;52457:60;;52532:25;52777:9;:16;;;52772:92;;-1:-1:-1;52834:14:0;;52772:92;52913:5;52878:543;52942:4;52937:1;:9;;:45;;;;;52965:17;52950:11;:32;;52937:45;52878:543;;;53051:14;;;;:11;:14;;;;;;;;;53039:26;;;;;;;;;-1:-1:-1;;;;;53039:26:0;;;;-1:-1:-1;;;53039:26:0;;-1:-1:-1;;;;;53039:26:0;;;;;;;;-1:-1:-1;;;53039:26:0;;;;;;;;;;;;;;;;-1:-1:-1;53084:73:0;;53129:8;;53084:73;53179:14;;-1:-1:-1;;;;;53179:28:0;;53175:111;;53252:14;;;-1:-1:-1;53175:111:0;53329:5;-1:-1:-1;;;;;53308:26:0;:17;-1:-1:-1;;;;;53308:26:0;;53304:102;;;53385:1;53359:8;53368:13;;;;;;53359:23;;;;;;-1:-1:-1;;;53359:23:0;;;;;;;;;;;;;;:27;;;;;53304:102;53001:3;;52878:543;;;-1:-1:-1;;;53506:29:0;;;-1:-1:-1;53513:8:0;;-1:-1:-1;;51034:2564:0;;;;;;:::o;57163:113::-;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;57242:11:::1;:26:::0;57163:113::o;35295:319::-;-1:-1:-1;;;;;35426:24:0;;5397:10;35426:24;35422:54;;;35459:17;;-1:-1:-1;;;35459:17:0;;;;;;;;;;;35422:54;5397:10;35489:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;35489:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;35489:53:0;;;;;;;;;;35558:48;;11511:41:1;;;35489:42:0;;5397:10;35558:48;;11484:18:1;35558:48:0;;;;;;;35295:319;;:::o;36463:406::-;36630:28;36640:4;36646:2;36650:7;36630:9;:28::i;:::-;-1:-1:-1;;;;;36687:13:0;;9645:19;:23;;36687:89;;;;;36720:56;36751:4;36757:2;36761:7;36770:5;36720:30;:56::i;:::-;36719:57;36687:89;36669:193;;;36810:40;;-1:-1:-1;;;36810:40:0;;;;;;;;;;;36669:193;36463:406;;;;:::o;57334:250::-;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;55824:4:::1;57429:11;57413:13;;:27;;;;:::i;:::-;:40;57409:92;;;57475:26;;-1:-1:-1::0;;;57475:26:0::1;;;;;;;;;;;57409:92;57537:13;:28:::0;;;;::::1;::::0;;57334:250::o;57976:367::-;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;58101:17;;58092:26:::1;::::0;:6;:26:::1;:::i;:::-;56555:13;;56546:6;56529:14;29875:7:::0;30061:13;-1:-1:-1;;30061:31:0;;29828:283;56529:14:::1;:23;;;;:::i;:::-;:39;56525:87;;;56590:22;;-1:-1:-1::0;;;56590:22:0::1;;;;;;;;;;;56525:87;58151:17:::0;;58136:12:::2;58179:157;58200:4;58195:1;:9;58179:157;;58223:39;58229:10;58240:1;58229:13;;;;;;-1:-1:-1::0;;;58229:13:0::2;;;;;;;;;;;;;;;58244:6;58223:39;;;;;;;;;;;::::0;58256:5:::2;58223;:39::i;:::-;58306:3;;58179:157;;;;56623:1;6905::::1;57976:367:::0;;:::o;49521:441::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58591:1:0;49700:25;;;:53;;;49740:13;;49729:7;:24;;49700:53;49696:102;;;49777:9;49521:441;-1:-1:-1;;49521:441:0:o;49696:102::-;-1:-1:-1;49820:20:0;;;;:11;:20;;;;;;;;;49808:32;;;;;;;;;-1:-1:-1;;;;;49808:32:0;;;;-1:-1:-1;;;49808:32:0;;-1:-1:-1;;;;;49808:32:0;;;;;;;;-1:-1:-1;;;49808:32:0;;;;;;;;;;;;;;;;49851:65;;49895:9;49521:441;-1:-1:-1;;49521:441:0:o;49851:65::-;49933:21;49946:7;49933:12;:21::i;33722:415::-;33840:13;33876:16;33884:7;33876;:16::i;:::-;33871:59;;33901:29;;-1:-1:-1;;;33901:29:0;;;;;;;;;;;33871:59;33943:21;33967:10;:8;:10::i;:::-;33943:34;;34014:7;34008:21;34033:1;34008:26;;:121;;;;;;;;;;;;;;;;;34078:7;34087:18;:7;:16;:18::i;:::-;34061:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;33988:141;33722:415;-1:-1:-1;;;33722:415:0:o;35685:214::-;-1:-1:-1;;;;;35856:25:0;;;35827:4;35856:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;35685:214::o;7523:238::-;6687:6;;-1:-1:-1;;;;;6687:6:0;5397:10;6834:23;6826:68;;;;-1:-1:-1;;;6826:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;7626:22:0;::::1;7604:110;;;::::0;-1:-1:-1;;;7604:110:0;;12520:2:1;7604:110:0::1;::::0;::::1;12502:21:1::0;12559:2;12539:18;;;12532:30;12598:34;12578:18;;;12571:62;-1:-1:-1;;;12649:18:1;;;12642:36;12695:19;;7604:110:0::1;12492:228:1::0;7604:110:0::1;7725:28;7744:8;7725:18;:28::i;37124:213::-:0;37181:4;37237:7;58591:1;37218:26;;:66;;;;;37271:13;;37261:7;:23;37218:66;:111;;;;-1:-1:-1;;37302:20:0;;;;:11;:20;;;;;:27;-1:-1:-1;;;37302:27:0;;;;37301:28;;37124:213::o;45511:196::-;45626:24;;;;:15;:24;;;;;;:29;;-1:-1:-1;;;;;;45626:29:0;-1:-1:-1;;;;;45626:29:0;;;;;;;;;45671:28;;45626:24;;45671:28;;;;;;;45511:196;;;:::o;956:190::-;1081:4;1134;1105:25;1118:5;1125:4;1105:12;:25::i;:::-;:33;;956:190;-1:-1:-1;;;;956:190:0:o;60684:172::-;60754:9;60767:10;60754:23;60750:54;;60786:18;;-1:-1:-1;;;60786:18:0;;;;;;;;;;;60750:54;60815:33;60821:5;60828:8;60815:33;;;;;;;;;;;;60842:5;60815;:33::i;40454:2130::-;40569:35;40607:21;40620:7;40607:12;:21::i;:::-;40569:59;;40667:4;-1:-1:-1;;;;;40645:26:0;:13;:18;;;-1:-1:-1;;;;;40645:26:0;;40641:67;;40680:28;;-1:-1:-1;;;40680:28:0;;;;;;;;;;;40641:67;40721:22;5397:10;-1:-1:-1;;;;;40747:20:0;;;;:73;;-1:-1:-1;40784:36:0;40801:4;5397:10;35685:214;:::i;40784:36::-;40747:126;;;-1:-1:-1;5397:10:0;40837:20;40849:7;40837:11;:20::i;:::-;-1:-1:-1;;;;;40837:36:0;;40747:126;40721:153;;40892:17;40887:66;;40918:35;;-1:-1:-1;;;40918:35:0;;;;;;;;;;;40887:66;-1:-1:-1;;;;;40968:16:0;;40964:52;;40993:23;;-1:-1:-1;;;40993:23:0;;;;;;;;;;;40964:52;41137:35;41154:1;41158:7;41167:4;41137:8;:35::i;:::-;-1:-1:-1;;;;;41468:18:0;;;;;;;:12;:18;;;;;;;;:31;;-1:-1:-1;;41468:31:0;;;-1:-1:-1;;;;;41468:31:0;;;-1:-1:-1;;41468:31:0;;;;;;;41514:16;;;;;;;;;:29;;;;;;;;-1:-1:-1;41514:29:0;;;;;;;;;;;41594:20;;;:11;:20;;;;;;41629:18;;-1:-1:-1;;;;;;41662:49:0;;;;-1:-1:-1;;;41695:15:0;41662:49;;;;;;;;;;41985:11;;42045:24;;;;;42088:13;;41594:20;;42045:24;;42088:13;42084:384;;42298:13;;42283:11;:28;42279:174;;42336:20;;42405:28;;;;-1:-1:-1;;;;;42379:54:0;-1:-1:-1;;;42379:54:0;-1:-1:-1;;;;;;42379:54:0;;;-1:-1:-1;;;;;42336:20:0;;42379:54;;;;42279:174;40454:2130;;;42515:7;42511:2;-1:-1:-1;;;;;42496:27:0;42505:4;-1:-1:-1;;;;;42496:27:0;;;;;;;;;;;42534:42;36463:406;31983:1141;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;32126:7:0;;58591:1;32175:23;;:47;;;;;32209:13;;32202:4;:20;32175:47;32171:886;;;32243:31;32277:17;;;:11;:17;;;;;;;;;32243:51;;;;;;;;;-1:-1:-1;;;;;32243:51:0;;;;-1:-1:-1;;;32243:51:0;;-1:-1:-1;;;;;32243:51:0;;;;;;;;-1:-1:-1;;;32243:51:0;;;;;;;;;;;;;;32313:729;;32363:14;;-1:-1:-1;;;;;32363:28:0;;32359:101;;32427:9;31983:1141;-1:-1:-1;;;31983:1141:0:o;32359:101::-;-1:-1:-1;;;32802:6:0;32847:17;;;;:11;:17;;;;;;;;;32835:29;;;;;;;;;-1:-1:-1;;;;;32835:29:0;;;;;-1:-1:-1;;;32835:29:0;;-1:-1:-1;;;;;32835:29:0;;;;;;;;-1:-1:-1;;;32835:29:0;;;;;;;;;;;;;32895:28;32891:109;;32963:9;31983:1141;-1:-1:-1;;;31983:1141:0:o;32891:109::-;32762:261;;;32171:886;;33085:31;;-1:-1:-1;;;33085:31:0;;;;;;;;;;;7921:191;8014:6;;;-1:-1:-1;;;;;8031:17:0;;;-1:-1:-1;;;;;;8031:17:0;;;;;;;8064:40;;8014:6;;;8031:17;8014:6;;8064:40;;7995:16;;8064:40;7921:191;;:::o;46199:772::-;46396:155;;-1:-1:-1;;;46396:155:0;;46362:4;;-1:-1:-1;;;;;46396:36:0;;;;;:155;;5397:10;;46482:4;;46505:7;;46531:5;;46396:155;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46396:155:0;;;;;;;;-1:-1:-1;;46396:155:0;;;;;;;;;;;;:::i;:::-;;;46379:585;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46722:13:0;;46718:235;;46768:40;;-1:-1:-1;;;46768:40:0;;;;;;;;;;;46718:235;46911:6;46905:13;46896:6;46892:2;46888:15;46881:38;46379:585;-1:-1:-1;;;;;;46607:55:0;-1:-1:-1;;;46607:55:0;;-1:-1:-1;46379:585:0;46199:772;;;;;;:::o;38234:1966::-;38373:20;38396:13;-1:-1:-1;;;;;38424:16:0;;38420:48;;38449:19;;-1:-1:-1;;;38449:19:0;;;;;;;;;;;38420:48;38483:13;38479:44;;38505:18;;-1:-1:-1;;;38505:18:0;;;;;;;;;;;38479:44;-1:-1:-1;;;;;38874:16:0;;;;;;:12;:16;;;;;;;;:44;;-1:-1:-1;;38933:49:0;;-1:-1:-1;;;;;38874:44:0;;;;;;;38933:49;;;;-1:-1:-1;;38874:44:0;;;;;;38933:49;;;;;;;;;;;;;;;;38999:25;;;:11;:25;;;;;;:35;;-1:-1:-1;;;;;;39049:66:0;;;;-1:-1:-1;;;39099:15:0;39049:66;;;;;;;;;;38999:25;39196:23;;;39240:4;:23;;;;-1:-1:-1;;;;;;39248:13:0;;9645:19;:23;;39248:15;39236:832;;;39284:505;39315:38;;39340:12;;-1:-1:-1;;;;;39315:38:0;;;39332:1;;39315:38;;39332:1;;39315:38;39407:212;39476:1;39509:2;39542:14;;;;;;39587:5;39407:30;:212::i;:::-;39376:365;;39677:40;;-1:-1:-1;;;39677:40:0;;;;;;;;;;;39376:365;39784:3;39768:12;:19;;39284:505;;39870:12;39853:13;;:29;39849:43;;39884:8;;;39849:43;39236:832;;;39933:120;39964:40;;39989:14;;;;;-1:-1:-1;;;;;39964:40:0;;;39981:1;;39964:40;;39981:1;;39964:40;40048:3;40032:12;:19;;39933:120;;39236:832;-1:-1:-1;40082:13:0;:28;40132:60;36463:406;58378:113;58438:13;58471:12;58464:19;;;;;:::i;2849:723::-;2905:13;3126:10;3122:53;;-1:-1:-1;;3153:10:0;;;;;;;;;;;;-1:-1:-1;;;3153:10:0;;;;;2849:723::o;3122:53::-;3200:5;3185:12;3241:78;3248:9;;3241:78;;3274:8;;;;:::i;:::-;;-1:-1:-1;3297:10:0;;-1:-1:-1;3305:2:0;3297:10;;:::i;:::-;;;3241:78;;;3329:19;3361:6;-1:-1:-1;;;;;3351:17:0;;;;;-1:-1:-1;;;3351:17:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3351:17:0;;3329:39;;3379:154;3386:10;;3379:154;;3413:11;3423:1;3413:11;;:::i;:::-;;-1:-1:-1;3482:10:0;3490:2;3482:5;:10;:::i;:::-;3469:24;;:2;:24;:::i;:::-;3456:39;;3439:6;3446;3439:14;;;;;;-1:-1:-1;;;3439:14:0;;;;;;;;;;;;:56;-1:-1:-1;;;;;3439:56:0;;;;;;;;-1:-1:-1;3510:11:0;3519:2;3510:11;;:::i;:::-;;;3379:154;;1508:707;1618:7;1666:4;1618:7;1681:497;1705:5;:12;1701:1;:16;1681:497;;;1739:20;1762:5;1768:1;1762:8;;;;;;-1:-1:-1;;;1762:8:0;;;;;;;;;;;;;;;1739:31;;1805:12;1789;:28;1785:382;;2318:13;2373:15;;;2409:4;2402:15;;;2456:4;2440:21;;1917:57;;1785:382;;;2318:13;2373:15;;;2409:4;2402:15;;;2456:4;2440:21;;2094:57;;1785:382;-1:-1:-1;1719:3:0;;;;:::i;:::-;;;;1681:497;;-1:-1:-1;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:173:1;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:2;;177:1;174;167:12;111:2;63:124;;;:::o;192:196::-;251:6;304:2;292:9;283:7;279:23;275:32;272:2;;;325:6;317;310:22;272:2;353:29;372:9;353:29;:::i;393:270::-;461:6;469;522:2;510:9;501:7;497:23;493:32;490:2;;;543:6;535;528:22;490:2;571:29;590:9;571:29;:::i;:::-;561:39;;619:38;653:2;642:9;638:18;619:38;:::i;:::-;609:48;;480:183;;;;;:::o;668:338::-;745:6;753;761;814:2;802:9;793:7;789:23;785:32;782:2;;;835:6;827;820:22;782:2;863:29;882:9;863:29;:::i;:::-;853:39;;911:38;945:2;934:9;930:18;911:38;:::i;:::-;901:48;;996:2;985:9;981:18;968:32;958:42;;772:234;;;;;:::o;1011:1025::-;1106:6;1114;1122;1130;1183:3;1171:9;1162:7;1158:23;1154:33;1151:2;;;1205:6;1197;1190:22;1151:2;1233:29;1252:9;1233:29;:::i;:::-;1223:39;;1281:2;1302:38;1336:2;1325:9;1321:18;1302:38;:::i;:::-;1292:48;;1387:2;1376:9;1372:18;1359:32;1349:42;;1442:2;1431:9;1427:18;1414:32;-1:-1:-1;;;;;1506:2:1;1498:6;1495:14;1492:2;;;1527:6;1519;1512:22;1492:2;1570:6;1559:9;1555:22;1545:32;;1615:7;1608:4;1604:2;1600:13;1596:27;1586:2;;1642:6;1634;1627:22;1586:2;1683;1670:16;1705:2;1701;1698:10;1695:2;;;1711:18;;:::i;:::-;1753:53;1796:2;1777:13;;-1:-1:-1;;1773:27:1;1769:36;;1753:53;:::i;:::-;1740:66;;1829:2;1822:5;1815:17;1869:7;1864:2;1859;1855;1851:11;1847:20;1844:33;1841:2;;;1895:6;1887;1880:22;1841:2;1955;1950;1946;1942:11;1937:2;1930:5;1926:14;1913:45;1978:14;;1974:23;;;1967:39;;;;1141:895;;;;-1:-1:-1;1141:895:1;;-1:-1:-1;;1141:895:1:o;2041:367::-;2106:6;2114;2167:2;2155:9;2146:7;2142:23;2138:32;2135:2;;;2188:6;2180;2173:22;2135:2;2216:29;2235:9;2216:29;:::i;:::-;2206:39;;2295:2;2284:9;2280:18;2267:32;2342:5;2335:13;2328:21;2321:5;2318:32;2308:2;;2369:6;2361;2354:22;2308:2;2397:5;2387:15;;;2125:283;;;;;:::o;2413:264::-;2481:6;2489;2542:2;2530:9;2521:7;2517:23;2513:32;2510:2;;;2563:6;2555;2548:22;2510:2;2591:29;2610:9;2591:29;:::i;:::-;2581:39;2667:2;2652:18;;;;2639:32;;-1:-1:-1;;;2500:177:1:o;2682:332::-;2759:6;2767;2775;2828:2;2816:9;2807:7;2803:23;2799:32;2796:2;;;2849:6;2841;2834:22;2796:2;2877:29;2896:9;2877:29;:::i;:::-;2867:39;2953:2;2938:18;;2925:32;;-1:-1:-1;3004:2:1;2989:18;;;2976:32;;2786:228;-1:-1:-1;;;2786:228:1:o;3019:1023::-;3112:6;3120;3173:2;3161:9;3152:7;3148:23;3144:32;3141:2;;;3194:6;3186;3179:22;3141:2;3239:9;3226:23;-1:-1:-1;;;;;3264:6:1;3261:30;3258:2;;;3309:6;3301;3294:22;3258:2;3337:22;;3390:4;3382:13;;3378:27;-1:-1:-1;3368:2:1;;3424:6;3416;3409:22;3368:2;3465;3452:16;3487:4;3511:60;3527:43;3567:2;3527:43;:::i;:::-;3511:60;:::i;:::-;3593:3;3617:2;3612:3;3605:15;3645:2;3640:3;3636:12;3629:19;;3676:2;3672;3668:11;3724:7;3719:2;3713;3710:1;3706:10;3702:2;3698:19;3694:28;3691:41;3688:2;;;3750:6;3742;3735:22;3688:2;3777:6;3768:15;;3792:169;3806:2;3803:1;3800:9;3792:169;;;3863:23;3882:3;3863:23;:::i;:::-;3851:36;;3824:1;3817:9;;;;;3907:12;;;;3939;;3792:169;;;-1:-1:-1;3980:5:1;4017:18;;;;4004:32;;-1:-1:-1;;;;;;3131:911:1:o;4047:909::-;4150:6;4158;4166;4174;4227:2;4215:9;4206:7;4202:23;4198:32;4195:2;;;4248:6;4240;4233:22;4195:2;4293:9;4280:23;-1:-1:-1;;;;;4363:2:1;4355:6;4352:14;4349:2;;;4384:6;4376;4369:22;4349:2;4427:6;4416:9;4412:22;4402:32;;4472:7;4465:4;4461:2;4457:13;4453:27;4443:2;;4499:6;4491;4484:22;4443:2;4544;4531:16;4570:2;4562:6;4559:14;4556:2;;;4591:6;4583;4576:22;4556:2;4651:7;4644:4;4634:6;4631:1;4627:14;4623:2;4619:23;4615:34;4612:47;4609:2;;;4677:6;4669;4662:22;4609:2;4713:4;4705:13;;;;-1:-1:-1;4737:6:1;-1:-1:-1;;4775:20:1;;4762:34;;-1:-1:-1;4846:2:1;4831:18;;4818:32;4890:6;4879:18;;4869:29;;4859:2;;4917:6;4909;4902:22;4859:2;4185:771;;;;-1:-1:-1;4185:771:1;;-1:-1:-1;;4185:771:1:o;4961:947::-;5045:6;5076:2;5119;5107:9;5098:7;5094:23;5090:32;5087:2;;;5140:6;5132;5125:22;5087:2;5185:9;5172:23;-1:-1:-1;;;;;5210:6:1;5207:30;5204:2;;;5255:6;5247;5240:22;5204:2;5283:22;;5336:4;5328:13;;5324:27;-1:-1:-1;5314:2:1;;5370:6;5362;5355:22;5314:2;5411;5398:16;5434:60;5450:43;5490:2;5450:43;:::i;5434:60::-;5516:3;5540:2;5535:3;5528:15;5568:2;5563:3;5559:12;5552:19;;5599:2;5595;5591:11;5647:7;5642:2;5636;5633:1;5629:10;5625:2;5621:19;5617:28;5614:41;5611:2;;;5673:6;5665;5658:22;5611:2;5700:6;5691:15;;5715:163;5729:2;5726:1;5723:9;5715:163;;;5786:17;;5774:30;;5747:1;5740:9;;;;;5824:12;;;;5856;;5715:163;;;-1:-1:-1;5897:5:1;5056:852;-1:-1:-1;;;;;;;5056:852:1:o;5913:190::-;5972:6;6025:2;6013:9;6004:7;6000:23;5996:32;5993:2;;;6046:6;6038;6031:22;5993:2;-1:-1:-1;6074:23:1;;5983:120;-1:-1:-1;5983:120:1:o;6108:255::-;6166:6;6219:2;6207:9;6198:7;6194:23;6190:32;6187:2;;;6240:6;6232;6225:22;6187:2;6284:9;6271:23;6303:30;6327:5;6303:30;:::i;6368:259::-;6437:6;6490:2;6478:9;6469:7;6465:23;6461:32;6458:2;;;6511:6;6503;6496:22;6458:2;6548:9;6542:16;6567:30;6591:5;6567:30;:::i;6632:292::-;6707:6;6760:2;6748:9;6739:7;6735:23;6731:32;6728:2;;;6781:6;6773;6766:22;6728:2;6825:9;6812:23;6864:1;6857:5;6854:12;6844:2;;6885:6;6877;6870:22;6929:642;7000:6;7008;7061:2;7049:9;7040:7;7036:23;7032:32;7029:2;;;7082:6;7074;7067:22;7029:2;7127:9;7114:23;-1:-1:-1;;;;;7197:2:1;7189:6;7186:14;7183:2;;;7218:6;7210;7203:22;7183:2;7261:6;7250:9;7246:22;7236:32;;7306:7;7299:4;7295:2;7291:13;7287:27;7277:2;;7333:6;7325;7318:22;7277:2;7378;7365:16;7404:2;7396:6;7393:14;7390:2;;;7425:6;7417;7410:22;7390:2;7475:7;7470:2;7461:6;7457:2;7453:15;7449:24;7446:37;7443:2;;;7501:6;7493;7486:22;7443:2;7537;7529:11;;;;;7559:6;;-1:-1:-1;7019:552:1;;-1:-1:-1;;;;7019:552:1:o;7771:257::-;7812:3;7850:5;7844:12;7877:6;7872:3;7865:19;7893:63;7949:6;7942:4;7937:3;7933:14;7926:4;7919:5;7915:16;7893:63;:::i;:::-;8010:2;7989:15;-1:-1:-1;;7985:29:1;7976:39;;;;8017:4;7972:50;;7820:208;-1:-1:-1;;7820:208:1:o;8615:470::-;8794:3;8832:6;8826:13;8848:53;8894:6;8889:3;8882:4;8874:6;8870:17;8848:53;:::i;:::-;8964:13;;8923:16;;;;8986:57;8964:13;8923:16;9020:4;9008:17;;8986:57;:::i;:::-;9059:20;;8802:283;-1:-1:-1;;;;8802:283:1:o;9508:488::-;-1:-1:-1;;;;;9777:15:1;;;9759:34;;9829:15;;9824:2;9809:18;;9802:43;9876:2;9861:18;;9854:34;;;9924:3;9919:2;9904:18;;9897:31;;;9702:4;;9945:45;;9970:19;;9962:6;9945:45;:::i;:::-;9937:53;9711:285;-1:-1:-1;;;;;;9711:285:1:o;10001:725::-;10234:2;10286:21;;;10356:13;;10259:18;;;10378:22;;;10205:4;;10234:2;10457:15;;;;10431:2;10416:18;;;10205:4;10503:197;10517:6;10514:1;10511:13;10503:197;;;10566:52;10614:3;10605:6;10599:13;8117:12;;-1:-1:-1;;;;;8113:38:1;8101:51;;8205:4;8194:16;;;8188:23;-1:-1:-1;;;;;8184:48:1;8168:14;;;8161:72;8296:4;8285:16;;;8279:23;8272:31;8265:39;8249:14;;8242:63;8091:220;10566:52;10675:15;;;;10647:4;10638:14;;;;;10539:1;10532:9;10503:197;;10731:635;10902:2;10954:21;;;11024:13;;10927:18;;;11046:22;;;10873:4;;10902:2;11125:15;;;;11099:2;11084:18;;;10873:4;11171:169;11185:6;11182:1;11179:13;11171:169;;;11246:13;;11234:26;;11315:15;;;;11280:12;;;;11207:1;11200:9;11171:169;;11745:344;11893:2;11878:18;;11926:1;11915:13;;11905:2;;11971:10;11966:3;11962:20;11959:1;11952:31;12006:4;12003:1;11996:15;12034:4;12031:1;12024:15;11905:2;12058:25;;;11860:229;:::o;12094:219::-;12243:2;12232:9;12225:21;12206:4;12263:44;12303:2;12292:9;12288:18;12280:6;12263:44;:::i;12725:356::-;12927:2;12909:21;;;12946:18;;;12939:30;13005:34;13000:2;12985:18;;12978:62;13072:2;13057:18;;12899:182::o;13086:265::-;8117:12;;-1:-1:-1;;;;;8113:38:1;8101:51;;8205:4;8194:16;;;8188:23;-1:-1:-1;;;;;8184:48:1;8168:14;;;8161:72;8296:4;8285:16;;;8279:23;8272:31;8265:39;8249:14;;;8242:63;13282:2;13267:18;;13294:51;8091:220;13908:275;13979:2;13973:9;14044:2;14025:13;;-1:-1:-1;;14021:27:1;14009:40;;-1:-1:-1;;;;;14064:34:1;;14100:22;;;14061:62;14058:2;;;14126:18;;:::i;:::-;14162:2;14155:22;13953:230;;-1:-1:-1;13953:230:1:o;14188:183::-;14248:4;-1:-1:-1;;;;;14273:6:1;14270:30;14267:2;;;14303:18;;:::i;:::-;-1:-1:-1;14348:1:1;14344:14;14360:4;14340:25;;14257:114::o;14376:224::-;14415:3;14443:6;14476:2;14473:1;14469:10;14506:2;14503:1;14499:10;14537:3;14533:2;14529:12;14524:3;14521:21;14518:2;;;14545:18;;:::i;14605:128::-;14645:3;14676:1;14672:6;14669:1;14666:13;14663:2;;;14682:18;;:::i;:::-;-1:-1:-1;14718:9:1;;14653:80::o;14738:120::-;14778:1;14804;14794:2;;14809:18;;:::i;:::-;-1:-1:-1;14843:9:1;;14784:74::o;14863:168::-;14903:7;14969:1;14965;14961:6;14957:14;14954:1;14951:21;14946:1;14939:9;14932:17;14928:45;14925:2;;;14976:18;;:::i;:::-;-1:-1:-1;15016:9:1;;14915:116::o;15036:125::-;15076:4;15104:1;15101;15098:8;15095:2;;;15109:18;;:::i;:::-;-1:-1:-1;15146:9:1;;15085:76::o;15166:258::-;15238:1;15248:113;15262:6;15259:1;15256:13;15248:113;;;15338:11;;;15332:18;15319:11;;;15312:39;15284:2;15277:10;15248:113;;;15379:6;15376:1;15373:13;15370:2;;;-1:-1:-1;;15414:1:1;15396:16;;15389:27;15219:205::o;15429:380::-;15508:1;15504:12;;;;15551;;;15572:2;;15626:4;15618:6;15614:17;15604:27;;15572:2;15679;15671:6;15668:14;15648:18;15645:38;15642:2;;;15725:10;15720:3;15716:20;15713:1;15706:31;15760:4;15757:1;15750:15;15788:4;15785:1;15778:15;15642:2;;15484:325;;;:::o;15814:135::-;15853:3;-1:-1:-1;;15874:17:1;;15871:2;;;15894:18;;:::i;:::-;-1:-1:-1;15941:1:1;15930:13;;15861:88::o;15954:112::-;15986:1;16012;16002:2;;16017:18;;:::i;:::-;-1:-1:-1;16051:9:1;;15992:74::o;16071:127::-;16132:10;16127:3;16123:20;16120:1;16113:31;16163:4;16160:1;16153:15;16187:4;16184:1;16177:15;16203:127;16264:10;16259:3;16255:20;16252:1;16245:31;16295:4;16292:1;16285:15;16319:4;16316:1;16309:15;16335:127;16396:10;16391:3;16387:20;16384:1;16377:31;16427:4;16424:1;16417:15;16451:4;16448:1;16441:15;16467:131;-1:-1:-1;;;;;;16541:32:1;;16531:43;;16521:2;;16588:1;16585;16578:12

Swarm Source

ipfs://6031a4213767e9f2d94f57f1da1f277b7b762d92a7d93e4d0f5de9dc72ec97b8
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.