ETH Price: $3,050.12 (+2.34%)
Gas: 2 Gwei

Token

MonkeEnlightenmentNFT (MNFT)
 

Overview

Max Total Supply

3,332 MNFT

Holders

189

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
19 MNFT
0xe9cbbcbeb5852db1e3bca5a35d116eab473b983a
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
MonkeEnlightenmentNFT

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-09-22
*/

// Sources flattened with hardhat v2.10.0 https://hardhat.org

// File @openzeppelin/contracts/utils/introspection/[email protected]

// 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/token/ERC721/[email protected]

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

pragma solidity ^0.8.0;

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

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

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

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

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

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}


// File @openzeppelin/contracts/token/ERC721/extensions/[email protected]

// 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/[email protected]

// ERC721A Contracts v3.3.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;


/**
 * @dev Interface of an ERC721A compliant contract.
 */
interface IERC721A is IERC721, IERC721Metadata {
    /**
     * The caller must own the token or be an approved operator.
     */
    error ApprovalCallerNotOwnerNorApproved();

    /**
     * The token does not exist.
     */
    error ApprovalQueryForNonexistentToken();

    /**
     * The caller cannot approve to their own address.
     */
    error ApproveToCaller();

    /**
     * The caller cannot approve to the current owner.
     */
    error ApprovalToCurrentOwner();

    /**
     * Cannot query the balance for the zero address.
     */
    error BalanceQueryForZeroAddress();

    /**
     * Cannot mint to the zero address.
     */
    error MintToZeroAddress();

    /**
     * The quantity of tokens minted must be more than zero.
     */
    error MintZeroQuantity();

    /**
     * The token does not exist.
     */
    error OwnerQueryForNonexistentToken();

    /**
     * The caller must own the token or be an approved operator.
     */
    error TransferCallerNotOwnerNorApproved();

    /**
     * The token must be owned by `from`.
     */
    error TransferFromIncorrectOwner();

    /**
     * Cannot safely transfer to a contract that does not implement the ERC721Receiver interface.
     */
    error TransferToNonERC721ReceiverImplementer();

    /**
     * Cannot transfer to the zero address.
     */
    error TransferToZeroAddress();

    /**
     * The token does not exist.
     */
    error URIQueryForNonexistentToken();

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

    /**
     * @dev Returns the total amount of tokens stored by the contract.
     * 
     * Burned tokens are calculated here, use `_totalMinted()` if you want to count just minted tokens.
     */
    function totalSupply() external view returns (uint256);
}


// File @openzeppelin/contracts/token/ERC721/[email protected]

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

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}


// File @openzeppelin/contracts/utils/[email protected]

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

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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


// File @openzeppelin/contracts/utils/[email protected]

// 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/utils/[email protected]

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

pragma solidity ^0.8.0;

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

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

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

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

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

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


// File @openzeppelin/contracts/utils/introspection/[email protected]

// 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 erc721a/contracts/[email protected]

// ERC721A Contracts v3.3.0
// Creator: Chiru Labs

pragma solidity ^0.8.4;






/**
 * @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, IERC721A {
    using Address for address;
    using Strings for uint256;

    // 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 override 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) if (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) if(!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()) if(!_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;
    }

    /**
     * @dev Equivalent to `_safeMint(to, quantity, '')`.
     */
    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 {
        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 (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 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) 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;

            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 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 @openzeppelin/contracts/utils/[email protected]

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

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}


// File @openzeppelin/contracts/access/[email protected]

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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


// File @openzeppelin/contracts/token/ERC20/[email protected]

// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]

// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}


// File @openzeppelin/contracts/token/ERC20/utils/[email protected]

// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;



/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}


// File contracts/MonkeNFT.sol
/// @author zscarabsz
/// @title Monke NFT (genesis)
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.11;  
contract MonkeEnlightenmentNFT is ERC721A , Ownable{  
    constructor() ERC721A("MonkeEnlightenmentNFT", "MNFT") {}  

    using Counters for Counters.Counter;
    using Strings for uint256;

    address payable private _PaymentAddress = payable(0x78bD4Fa99C9492A5Efc75a821a4034d88403004d);
	address private _monkeContract = address (0);

    Counters.Counter private _publicMNFT;
    uint256 private _MNFT_MAX = 3333;
    uint256 private _activeDateTime = 1663987096; 
    string private _tokenBaseURI = "";
    string private _revealURI = "https://ipfs.io/ipfs/QmbdvrpNNGRHBjafJ4YxZK2BznxEgkYpeH3SYEjC4m3Uoq";
    
    uint256 private PRESALE_PRICE = 0.00 ether;   
    uint256 private PUBLIC_PRICE = 0.00 ether;	 
    uint256 private REVEAL_DELAY = 96 hours;
    uint256 private PRESALE_HOURS = 0 hours;
    uint256 private PRESALE_MINT_LIMIT = 20;
	uint256 private PUBLIC_MINT_LIMIT = 20;
	uint256 private MONKE_TOKENS_NEEDED = 30000;

    mapping(address => bool) private _mappingWhiteList;
    mapping(address => uint256) private _mappingPresaleMintCount;
	mapping(address => uint256) private _mappingPublicMintCount;
	
	function setMonkeToken(address token) public onlyOwner {
        _monkeContract = token;
    }
	
	function setMaxMintAmount(uint256 maxAmount) external onlyOwner {
        _MNFT_MAX = maxAmount;
    }

    function setPaymentAddress(address paymentAddress) external onlyOwner {
        _PaymentAddress = payable(paymentAddress);
    }

    function setActiveDateTime(uint256 activeDateTime, uint256 presaleHours, uint256 revealDelay) external onlyOwner {
        _activeDateTime = activeDateTime;
        REVEAL_DELAY = revealDelay;
        PRESALE_HOURS = presaleHours;
    }

    function setWhiteList(address[] memory whiteListAddress, bool bEnable) external onlyOwner {
        for (uint256 i = 0; i < whiteListAddress.length; i++) {
            _mappingWhiteList[whiteListAddress[i]] = bEnable;
        }
    }

    function isWhiteListed(address addr) public view returns (bool) {
        return _mappingWhiteList[addr];
    }

    function setMintPrice(uint256 presaleMintPrice, uint256 publicMintPrice) external onlyOwner {
        PRESALE_PRICE = presaleMintPrice; 
        PUBLIC_PRICE = publicMintPrice; 
    }

    function setMintMaxLimit(uint256 presaleMintLimit, uint256 publicsaleMintLimit) external onlyOwner {
        PRESALE_MINT_LIMIT = presaleMintLimit;
		PUBLIC_MINT_LIMIT = publicsaleMintLimit;
    }
	
	function getPresaleMintMaxLimit() public view returns (uint256) {
		return PRESALE_MINT_LIMIT;
	}
	
	function getPublicsaleMintMaxLimit() public view returns (uint256) {
		return PUBLIC_MINT_LIMIT;
	}
	
	function getMintMax() public view returns (uint256) {
		return _MNFT_MAX;
	}
	
    function setMonkeTokensNeeded(uint256 tokensAmount) external onlyOwner {
        MONKE_TOKENS_NEEDED = tokensAmount;
    }
	
	function setURIs(string memory revealURI, string memory baseURI) external onlyOwner {
        _revealURI = revealURI;
		_tokenBaseURI = baseURI;
    }
	
    function tokenURI(uint256 tokenId) public view override(ERC721A) returns (string memory) {
        require(_exists(tokenId), "Token does not exist");

        if (_activeDateTime + REVEAL_DELAY < block.timestamp) {
            return string(abi.encodePacked(_tokenBaseURI, tokenId.toString()));
        }
        return _revealURI;
    }

    function withdraw() external onlyOwner {
        uint256 balance = address(this).balance;
        payable(msg.sender).transfer(balance);
    }

    function price() public view returns (uint256) {
		return (block.timestamp < _activeDateTime)? PRESALE_PRICE : PUBLIC_PRICE;
    }
	
	function isPresaleMintActive() public view returns (bool) {
		if (isPublicMintActive() == true) {
			return false;
		}
		return (block.timestamp > _activeDateTime - PRESALE_HOURS)? true : false;
	}
	
	function isPublicMintActive() public view returns (bool) {
		return (block.timestamp > _activeDateTime)? true : false;
	}

    function adminMint(uint256 adminMintAmt) external onlyOwner {
		require(_publicMNFT.current() + adminMintAmt < _MNFT_MAX, "Purchase would exceed _MNFT_MAX");
		
		for (uint256 i = 0; i < adminMintAmt; i++) {
			_publicMNFT.increment();
		}
        _safeMint(msg.sender, adminMintAmt);
    }
	
	function hasMonkeToken(address user) public view returns(bool) {
		IERC20 instance = IERC20(_monkeContract);
		bool result = false;
		uint bal = instance.balanceOf(user);

		if(bal >= MONKE_TOKENS_NEEDED){
			result = true;
		}

		return result;
	}

    function purchase(uint256 numberOfTokens) external payable {
        require(msg.sender != owner(), "You are owner!");
        require(_publicMNFT.current() + numberOfTokens < _MNFT_MAX, "Purchase would exceed _MNFT_MAX");
		require(hasMonkeToken(msg.sender) == true, "need to own more Monke tokens");

        if (block.timestamp < _activeDateTime) {
            require(_mappingWhiteList[msg.sender] == true, "Not registered to WhiteList");   
            require(block.timestamp > _activeDateTime - PRESALE_HOURS , "Mint is not activated for presale");
            require(_mappingPresaleMintCount[msg.sender] + numberOfTokens <= PRESALE_MINT_LIMIT, "Overflow for PRESALE_MINT_LIMIT");
            _mappingPresaleMintCount[msg.sender] = _mappingPresaleMintCount[msg.sender] + numberOfTokens;
        }
		else {
			require(block.timestamp > _activeDateTime, "Mint is not activated for public sale");
			require(numberOfTokens <= 10, "Amount to high for single transaction");
			require(_mappingPublicMintCount[msg.sender] + numberOfTokens <= PUBLIC_MINT_LIMIT, "Overflow for PUBLIC_MINT_LIMIT");
			_mappingPublicMintCount[msg.sender] = _mappingPublicMintCount[msg.sender] + numberOfTokens;
		}

        for(uint256 i=0; i<numberOfTokens; i++){
            _publicMNFT.increment();
        }
		
        _safeMint(msg.sender, numberOfTokens);
    }   
}

interface iMonkeToken {
	function ownerOf(uint256 tokenId) external returns (address);
	function balanceOf(address tokenOwner) external returns (uint balance);
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"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":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","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":[{"internalType":"uint256","name":"adminMintAmt","type":"uint256"}],"name":"adminMint","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":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintMax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPresaleMintMaxLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPublicsaleMintMaxLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"hasMonkeToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPresaleMintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPublicMintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isWhiteListed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"purchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"activeDateTime","type":"uint256"},{"internalType":"uint256","name":"presaleHours","type":"uint256"},{"internalType":"uint256","name":"revealDelay","type":"uint256"}],"name":"setActiveDateTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxAmount","type":"uint256"}],"name":"setMaxMintAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"presaleMintLimit","type":"uint256"},{"internalType":"uint256","name":"publicsaleMintLimit","type":"uint256"}],"name":"setMintMaxLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"presaleMintPrice","type":"uint256"},{"internalType":"uint256","name":"publicMintPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"setMonkeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokensAmount","type":"uint256"}],"name":"setMonkeTokensNeeded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"paymentAddress","type":"address"}],"name":"setPaymentAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"revealURI","type":"string"},{"internalType":"string","name":"baseURI","type":"string"}],"name":"setURIs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"whiteListAddress","type":"address[]"},{"internalType":"bool","name":"bEnable","type":"bool"}],"name":"setWhiteList","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":[],"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"}]

60806040527378bd4fa99c9492a5efc75a821a4034d88403004d600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610d05600c5563632e6d98600d5560405180602001604052806000815250600e9080519060200190620000d0929190620002e5565b50604051806080016040528060438152602001620043bb60439139600f908051906020019062000102929190620002e5565b50600060105560006011556205460060125560006013556014805560146015556175306016553480156200013557600080fd5b506040518060400160405280601581526020017f4d6f6e6b65456e6c69676874656e6d656e744e465400000000000000000000008152506040518060400160405280600481526020017f4d4e4654000000000000000000000000000000000000000000000000000000008152508160029080519060200190620001ba929190620002e5565b508060039080519060200190620001d3929190620002e5565b50620001e46200021260201b60201c565b60008190555050506200020c620002006200021760201b60201c565b6200021f60201b60201c565b620003fa565b600090565b600033905090565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b828054620002f390620003c4565b90600052602060002090601f01602090048101928262000317576000855562000363565b82601f106200033257805160ff191683800117855562000363565b8280016001018555821562000363579182015b828111156200036257825182559160200191906001019062000345565b5b50905062000372919062000376565b5090565b5b808211156200039157600081600090555060010162000377565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620003dd57607f821691505b60208210811415620003f457620003f362000395565b5b50919050565b613fb1806200040a6000396000f3fe60806040526004361061021a5760003560e01c806370a0823111610123578063bfdd30cb116100ab578063e43f696e1161006f578063e43f696e146107bb578063e8254174146107e4578063e985e9c51461080d578063efef39a11461084a578063f2fde38b146108665761021a565b8063bfdd30cb146106d8578063c1f2612314610701578063c55581981461072a578063c87b56dd14610755578063d42f21f6146107925761021a565b806395d89b41116100f257806395d89b41146106075780639791e38914610632578063a035b1fe1461065b578063a22cb46514610686578063b88d4fde146106af5761021a565b806370a082311461055d578063715018a61461059a5780638da5cb5b146105b1578063928dd6e3146105dc5761021a565b806323b872dd116101a65780633d842c37116101755780633d842c371461046857806342842e0e146104915780635e1e1004146104ba5780636352211e146104e35780636f9170f6146105205761021a565b806323b872dd146103d25780632483ada0146103fb5780632d6b6224146104265780633ccfd60b146104515761021a565b8063088a4ed0116101ed578063088a4ed0146102ed578063095ea7b31461031657806311054aa61461033f57806318160ddd1461037c5780631e51e4a1146103a75761021a565b806301ffc9a71461021f5780630442bfa81461025c57806306fdde0314610285578063081812fc146102b0575b600080fd5b34801561022b57600080fd5b5061024660048036038101906102419190612d70565b61088f565b6040516102539190612db8565b60405180910390f35b34801561026857600080fd5b50610283600480360381019061027e9190612e09565b610971565b005b34801561029157600080fd5b5061029a61098b565b6040516102a79190612ee2565b60405180910390f35b3480156102bc57600080fd5b506102d760048036038101906102d29190612f04565b610a1d565b6040516102e49190612f72565b60405180910390f35b3480156102f957600080fd5b50610314600480360381019061030f9190612f04565b610a99565b005b34801561032257600080fd5b5061033d60048036038101906103389190612fb9565b610aab565b005b34801561034b57600080fd5b5061036660048036038101906103619190612ff9565b610bb0565b6040516103739190612db8565b60405180910390f35b34801561038857600080fd5b50610391610c70565b60405161039e9190613035565b60405180910390f35b3480156103b357600080fd5b506103bc610c87565b6040516103c99190613035565b60405180910390f35b3480156103de57600080fd5b506103f960048036038101906103f49190613050565b610c91565b005b34801561040757600080fd5b50610410610ca1565b60405161041d9190613035565b60405180910390f35b34801561043257600080fd5b5061043b610cab565b6040516104489190612db8565b60405180910390f35b34801561045d57600080fd5b50610466610cc5565b005b34801561047457600080fd5b5061048f600480360381019061048a9190612ff9565b610d1c565b005b34801561049d57600080fd5b506104b860048036038101906104b39190613050565b610d68565b005b3480156104c657600080fd5b506104e160048036038101906104dc9190612ff9565b610d88565b005b3480156104ef57600080fd5b5061050a60048036038101906105059190612f04565b610dd4565b6040516105179190612f72565b60405180910390f35b34801561052c57600080fd5b5061054760048036038101906105429190612ff9565b610dea565b6040516105549190612db8565b60405180910390f35b34801561056957600080fd5b50610584600480360381019061057f9190612ff9565b610e40565b6040516105919190613035565b60405180910390f35b3480156105a657600080fd5b506105af610f10565b005b3480156105bd57600080fd5b506105c6610f24565b6040516105d39190612f72565b60405180910390f35b3480156105e857600080fd5b506105f1610f4e565b6040516105fe9190613035565b60405180910390f35b34801561061357600080fd5b5061061c610f58565b6040516106299190612ee2565b60405180910390f35b34801561063e57600080fd5b50610659600480360381019061065491906130a3565b610fea565b005b34801561066757600080fd5b5061067061100c565b60405161067d9190613035565b60405180910390f35b34801561069257600080fd5b506106ad60048036038101906106a89190613122565b611028565b005b3480156106bb57600080fd5b506106d660048036038101906106d19190613297565b6111a0565b005b3480156106e457600080fd5b506106ff60048036038101906106fa9190612f04565b611218565b005b34801561070d57600080fd5b5061072860048036038101906107239190612f04565b61122a565b005b34801561073657600080fd5b5061073f6112c0565b60405161074c9190612db8565b60405180910390f35b34801561076157600080fd5b5061077c60048036038101906107779190612f04565b611305565b6040516107899190612ee2565b60405180910390f35b34801561079e57600080fd5b506107b960048036038101906107b49190612e09565b61142b565b005b3480156107c757600080fd5b506107e260048036038101906107dd91906133e2565b611445565b005b3480156107f057600080fd5b5061080b600480360381019061080691906134df565b6114e2565b005b34801561081957600080fd5b50610834600480360381019061082f9190613557565b61151c565b6040516108419190612db8565b60405180910390f35b610864600480360381019061085f9190612f04565b6115b0565b005b34801561087257600080fd5b5061088d60048036038101906108889190612ff9565b611ab9565b005b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061095a57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061096a575061096982611b3d565b5b9050919050565b610979611ba7565b81601081905550806011819055505050565b60606002805461099a906135c6565b80601f01602080910402602001604051908101604052809291908181526020018280546109c6906135c6565b8015610a135780601f106109e857610100808354040283529160200191610a13565b820191906000526020600020905b8154815290600101906020018083116109f657829003601f168201915b5050505050905090565b6000610a2882611c25565b610a5e576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610aa1611ba7565b80600c8190555050565b6000610ab682610dd4565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610b1e576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610b3d611c73565b73ffffffffffffffffffffffffffffffffffffffff1614610ba057610b6981610b64611c73565b61151c565b610b9f576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b610bab838383611c7b565b505050565b600080600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000808273ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401610c149190612f72565b602060405180830381865afa158015610c31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c55919061360d565b90506016548110610c6557600191505b819350505050919050565b6000610c7a611d2d565b6001546000540303905090565b6000600c54905090565b610c9c838383611d32565b505050565b6000601454905090565b6000600d544211610cbd576000610cc0565b60015b905090565b610ccd611ba7565b60004790503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610d18573d6000803e3d6000fd5b5050565b610d24611ba7565b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610d83838383604051806020016040528060008152506111a0565b505050565b610d90611ba7565b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000610ddf826121e8565b600001519050919050565b6000601760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ea8576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b610f18611ba7565b610f226000612473565b565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000601554905090565b606060038054610f67906135c6565b80601f0160208091040260200160405190810160405280929190818152602001828054610f93906135c6565b8015610fe05780601f10610fb557610100808354040283529160200191610fe0565b820191906000526020600020905b815481529060010190602001808311610fc357829003601f168201915b5050505050905090565b610ff2611ba7565b82600d819055508060128190555081601381905550505050565b6000600d54421061101f57601154611023565b6010545b905090565b611030611c73565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611095576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600760006110a2611c73565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661114f611c73565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516111949190612db8565b60405180910390a35050565b6111ab848484611d32565b6111ca8373ffffffffffffffffffffffffffffffffffffffff16612539565b15611212576111db8484848461255c565b611211576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b611220611ba7565b8060168190555050565b611232611ba7565b600c5481611240600b6126ad565b61124a9190613669565b1061128a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112819061370b565b60405180910390fd5b60005b818110156112b25761129f600b6126bb565b80806112aa9061372b565b91505061128d565b506112bd33826126d1565b50565b6000600115156112ce610cab565b151514156112df5760009050611302565b601354600d546112ef9190613774565b42116112fc5760006112ff565b60015b90505b90565b606061131082611c25565b61134f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611346906137f4565b60405180910390fd5b42601254600d546113609190613669565b101561139857600e611371836126ef565b6040516020016113829291906138e4565b6040516020818303038152906040529050611426565b600f80546113a5906135c6565b80601f01602080910402602001604051908101604052809291908181526020018280546113d1906135c6565b801561141e5780601f106113f35761010080835404028352916020019161141e565b820191906000526020600020905b81548152906001019060200180831161140157829003601f168201915b505050505090505b919050565b611433611ba7565b81601481905550806015819055505050565b61144d611ba7565b60005b82518110156114dd57816017600085848151811061147157611470613908565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080806114d59061372b565b915050611450565b505050565b6114ea611ba7565b81600f9080519060200190611500929190612c1e565b5080600e9080519060200190611517929190612c1e565b505050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6115b8610f24565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415611626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161d90613983565b60405180910390fd5b600c5481611634600b6126ad565b61163e9190613669565b1061167e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116759061370b565b60405180910390fd5b6001151561168b33610bb0565b1515146116cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116c4906139ef565b60405180910390fd5b600d544210156118dd5760011515601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151461176a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161176190613a5b565b60405180910390fd5b601354600d5461177a9190613774565b42116117bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b290613aed565b60405180910390fd5b60145481601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546118099190613669565b111561184a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161184190613b59565b60405180910390fd5b80601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546118959190613669565b601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611a83565b600d544211611921576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191890613beb565b60405180910390fd5b600a811115611965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195c90613c7d565b60405180910390fd5b60155481601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119b39190613669565b11156119f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119eb90613ce9565b60405180910390fd5b80601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611a3f9190613669565b601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b60005b81811015611aab57611a98600b6126bb565b8080611aa39061372b565b915050611a86565b50611ab633826126d1565b50565b611ac1611ba7565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611b31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b2890613d7b565b60405180910390fd5b611b3a81612473565b50565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b611baf611c73565b73ffffffffffffffffffffffffffffffffffffffff16611bcd610f24565b73ffffffffffffffffffffffffffffffffffffffff1614611c23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1a90613de7565b60405180910390fd5b565b600081611c30611d2d565b11158015611c3f575060005482105b8015611c6c575060046000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b600033905090565b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b600090565b6000611d3d826121e8565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614611da8576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16611dc9611c73565b73ffffffffffffffffffffffffffffffffffffffff161480611df85750611df785611df2611c73565b61151c565b5b80611e3d5750611e06611c73565b73ffffffffffffffffffffffffffffffffffffffff16611e2584610a1d565b73ffffffffffffffffffffffffffffffffffffffff16145b905080611e76576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415611edd576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611eea8585856001612850565b611ef660008487611c7b565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561217657600054821461217557878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46121e18585856001612856565b5050505050565b6121f0612ca4565b6000829050806121fe611d2d565b1161243c5760005481101561243b576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050806040015161243957600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461231d57809250505061246e565b5b60011561243857818060019003925050600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461243357809250505061246e565b61231e565b5b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612582611c73565b8786866040518563ffffffff1660e01b81526004016125a49493929190613e5c565b6020604051808303816000875af19250505080156125e057506040513d601f19601f820116820180604052508101906125dd9190613ebd565b60015b61265a573d8060008114612610576040519150601f19603f3d011682016040523d82523d6000602084013e612615565b606091505b50600081511415612652576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b600081600001549050919050565b6001816000016000828254019250508190555050565b6126eb82826040518060200160405280600081525061285c565b5050565b60606000821415612737576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061284b565b600082905060005b600082146127695780806127529061372b565b915050600a826127629190613f19565b915061273f565b60008167ffffffffffffffff8111156127855761278461316c565b5b6040519080825280601f01601f1916602001820160405280156127b75781602001600182028036833780820191505090505b5090505b60008514612844576001826127d09190613774565b9150600a856127df9190613f4a565b60306127eb9190613669565b60f81b81838151811061280157612800613908565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561283d9190613f19565b94506127bb565b8093505050505b919050565b50505050565b50505050565b600080549050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156128c9576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000831415612904576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129116000858386612850565b82600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555082600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550836004600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426004600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600081905060008482019050612ad28673ffffffffffffffffffffffffffffffffffffffff16612539565b15612b97575b818673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612b47600087848060010195508761255c565b612b7d576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808210612ad8578260005414612b9257600080fd5b612c02565b5b818060010192508673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4808210612b98575b816000819055505050612c186000858386612856565b50505050565b828054612c2a906135c6565b90600052602060002090601f016020900481019282612c4c5760008555612c93565b82601f10612c6557805160ff1916838001178555612c93565b82800160010185558215612c93579182015b82811115612c92578251825591602001919060010190612c77565b5b509050612ca09190612ce7565b5090565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b5b80821115612d00576000816000905550600101612ce8565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612d4d81612d18565b8114612d5857600080fd5b50565b600081359050612d6a81612d44565b92915050565b600060208284031215612d8657612d85612d0e565b5b6000612d9484828501612d5b565b91505092915050565b60008115159050919050565b612db281612d9d565b82525050565b6000602082019050612dcd6000830184612da9565b92915050565b6000819050919050565b612de681612dd3565b8114612df157600080fd5b50565b600081359050612e0381612ddd565b92915050565b60008060408385031215612e2057612e1f612d0e565b5b6000612e2e85828601612df4565b9250506020612e3f85828601612df4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612e83578082015181840152602081019050612e68565b83811115612e92576000848401525b50505050565b6000601f19601f8301169050919050565b6000612eb482612e49565b612ebe8185612e54565b9350612ece818560208601612e65565b612ed781612e98565b840191505092915050565b60006020820190508181036000830152612efc8184612ea9565b905092915050565b600060208284031215612f1a57612f19612d0e565b5b6000612f2884828501612df4565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612f5c82612f31565b9050919050565b612f6c81612f51565b82525050565b6000602082019050612f876000830184612f63565b92915050565b612f9681612f51565b8114612fa157600080fd5b50565b600081359050612fb381612f8d565b92915050565b60008060408385031215612fd057612fcf612d0e565b5b6000612fde85828601612fa4565b9250506020612fef85828601612df4565b9150509250929050565b60006020828403121561300f5761300e612d0e565b5b600061301d84828501612fa4565b91505092915050565b61302f81612dd3565b82525050565b600060208201905061304a6000830184613026565b92915050565b60008060006060848603121561306957613068612d0e565b5b600061307786828701612fa4565b935050602061308886828701612fa4565b925050604061309986828701612df4565b9150509250925092565b6000806000606084860312156130bc576130bb612d0e565b5b60006130ca86828701612df4565b93505060206130db86828701612df4565b92505060406130ec86828701612df4565b9150509250925092565b6130ff81612d9d565b811461310a57600080fd5b50565b60008135905061311c816130f6565b92915050565b6000806040838503121561313957613138612d0e565b5b600061314785828601612fa4565b92505060206131588582860161310d565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6131a482612e98565b810181811067ffffffffffffffff821117156131c3576131c261316c565b5b80604052505050565b60006131d6612d04565b90506131e2828261319b565b919050565b600067ffffffffffffffff8211156132025761320161316c565b5b61320b82612e98565b9050602081019050919050565b82818337600083830152505050565b600061323a613235846131e7565b6131cc565b90508281526020810184848401111561325657613255613167565b5b613261848285613218565b509392505050565b600082601f83011261327e5761327d613162565b5b813561328e848260208601613227565b91505092915050565b600080600080608085870312156132b1576132b0612d0e565b5b60006132bf87828801612fa4565b94505060206132d087828801612fa4565b93505060406132e187828801612df4565b925050606085013567ffffffffffffffff81111561330257613301612d13565b5b61330e87828801613269565b91505092959194509250565b600067ffffffffffffffff8211156133355761333461316c565b5b602082029050602081019050919050565b600080fd5b600061335e6133598461331a565b6131cc565b9050808382526020820190506020840283018581111561338157613380613346565b5b835b818110156133aa57806133968882612fa4565b845260208401935050602081019050613383565b5050509392505050565b600082601f8301126133c9576133c8613162565b5b81356133d984826020860161334b565b91505092915050565b600080604083850312156133f9576133f8612d0e565b5b600083013567ffffffffffffffff81111561341757613416612d13565b5b613423858286016133b4565b92505060206134348582860161310d565b9150509250929050565b600067ffffffffffffffff8211156134595761345861316c565b5b61346282612e98565b9050602081019050919050565b600061348261347d8461343e565b6131cc565b90508281526020810184848401111561349e5761349d613167565b5b6134a9848285613218565b509392505050565b600082601f8301126134c6576134c5613162565b5b81356134d684826020860161346f565b91505092915050565b600080604083850312156134f6576134f5612d0e565b5b600083013567ffffffffffffffff81111561351457613513612d13565b5b613520858286016134b1565b925050602083013567ffffffffffffffff81111561354157613540612d13565b5b61354d858286016134b1565b9150509250929050565b6000806040838503121561356e5761356d612d0e565b5b600061357c85828601612fa4565b925050602061358d85828601612fa4565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806135de57607f821691505b602082108114156135f2576135f1613597565b5b50919050565b60008151905061360781612ddd565b92915050565b60006020828403121561362357613622612d0e565b5b6000613631848285016135f8565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061367482612dd3565b915061367f83612dd3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156136b4576136b361363a565b5b828201905092915050565b7f507572636861736520776f756c6420657863656564205f4d4e46545f4d415800600082015250565b60006136f5601f83612e54565b9150613700826136bf565b602082019050919050565b60006020820190508181036000830152613724816136e8565b9050919050565b600061373682612dd3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156137695761376861363a565b5b600182019050919050565b600061377f82612dd3565b915061378a83612dd3565b92508282101561379d5761379c61363a565b5b828203905092915050565b7f546f6b656e20646f6573206e6f74206578697374000000000000000000000000600082015250565b60006137de601483612e54565b91506137e9826137a8565b602082019050919050565b6000602082019050818103600083015261380d816137d1565b9050919050565b600081905092915050565b60008190508160005260206000209050919050565b60008154613841816135c6565b61384b8186613814565b945060018216600081146138665760018114613877576138aa565b60ff198316865281860193506138aa565b6138808561381f565b60005b838110156138a257815481890152600182019150602081019050613883565b838801955050505b50505092915050565b60006138be82612e49565b6138c88185613814565b93506138d8818560208601612e65565b80840191505092915050565b60006138f08285613834565b91506138fc82846138b3565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f596f7520617265206f776e657221000000000000000000000000000000000000600082015250565b600061396d600e83612e54565b915061397882613937565b602082019050919050565b6000602082019050818103600083015261399c81613960565b9050919050565b7f6e65656420746f206f776e206d6f7265204d6f6e6b6520746f6b656e73000000600082015250565b60006139d9601d83612e54565b91506139e4826139a3565b602082019050919050565b60006020820190508181036000830152613a08816139cc565b9050919050565b7f4e6f74207265676973746572656420746f2057686974654c6973740000000000600082015250565b6000613a45601b83612e54565b9150613a5082613a0f565b602082019050919050565b60006020820190508181036000830152613a7481613a38565b9050919050565b7f4d696e74206973206e6f742061637469766174656420666f722070726573616c60008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000613ad7602183612e54565b9150613ae282613a7b565b604082019050919050565b60006020820190508181036000830152613b0681613aca565b9050919050565b7f4f766572666c6f7720666f722050524553414c455f4d494e545f4c494d495400600082015250565b6000613b43601f83612e54565b9150613b4e82613b0d565b602082019050919050565b60006020820190508181036000830152613b7281613b36565b9050919050565b7f4d696e74206973206e6f742061637469766174656420666f72207075626c696360008201527f2073616c65000000000000000000000000000000000000000000000000000000602082015250565b6000613bd5602583612e54565b9150613be082613b79565b604082019050919050565b60006020820190508181036000830152613c0481613bc8565b9050919050565b7f416d6f756e7420746f206869676820666f722073696e676c65207472616e736160008201527f6374696f6e000000000000000000000000000000000000000000000000000000602082015250565b6000613c67602583612e54565b9150613c7282613c0b565b604082019050919050565b60006020820190508181036000830152613c9681613c5a565b9050919050565b7f4f766572666c6f7720666f72205055424c49435f4d494e545f4c494d49540000600082015250565b6000613cd3601e83612e54565b9150613cde82613c9d565b602082019050919050565b60006020820190508181036000830152613d0281613cc6565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000613d65602683612e54565b9150613d7082613d09565b604082019050919050565b60006020820190508181036000830152613d9481613d58565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000613dd1602083612e54565b9150613ddc82613d9b565b602082019050919050565b60006020820190508181036000830152613e0081613dc4565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000613e2e82613e07565b613e388185613e12565b9350613e48818560208601612e65565b613e5181612e98565b840191505092915050565b6000608082019050613e716000830187612f63565b613e7e6020830186612f63565b613e8b6040830185613026565b8181036060830152613e9d8184613e23565b905095945050505050565b600081519050613eb781612d44565b92915050565b600060208284031215613ed357613ed2612d0e565b5b6000613ee184828501613ea8565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613f2482612dd3565b9150613f2f83612dd3565b925082613f3f57613f3e613eea565b5b828204905092915050565b6000613f5582612dd3565b9150613f6083612dd3565b925082613f7057613f6f613eea565b5b82820690509291505056fea264697066735822122091be3311bd889c5e13c681ebfcd1c4f27bc633ac80190c31762178ca5a1ae0c764736f6c634300080b003368747470733a2f2f697066732e696f2f697066732f516d62647672704e4e475248426a61664a3459785a4b32427a6e7845676b59706548335359456a43346d33556f71

Deployed Bytecode

0x60806040526004361061021a5760003560e01c806370a0823111610123578063bfdd30cb116100ab578063e43f696e1161006f578063e43f696e146107bb578063e8254174146107e4578063e985e9c51461080d578063efef39a11461084a578063f2fde38b146108665761021a565b8063bfdd30cb146106d8578063c1f2612314610701578063c55581981461072a578063c87b56dd14610755578063d42f21f6146107925761021a565b806395d89b41116100f257806395d89b41146106075780639791e38914610632578063a035b1fe1461065b578063a22cb46514610686578063b88d4fde146106af5761021a565b806370a082311461055d578063715018a61461059a5780638da5cb5b146105b1578063928dd6e3146105dc5761021a565b806323b872dd116101a65780633d842c37116101755780633d842c371461046857806342842e0e146104915780635e1e1004146104ba5780636352211e146104e35780636f9170f6146105205761021a565b806323b872dd146103d25780632483ada0146103fb5780632d6b6224146104265780633ccfd60b146104515761021a565b8063088a4ed0116101ed578063088a4ed0146102ed578063095ea7b31461031657806311054aa61461033f57806318160ddd1461037c5780631e51e4a1146103a75761021a565b806301ffc9a71461021f5780630442bfa81461025c57806306fdde0314610285578063081812fc146102b0575b600080fd5b34801561022b57600080fd5b5061024660048036038101906102419190612d70565b61088f565b6040516102539190612db8565b60405180910390f35b34801561026857600080fd5b50610283600480360381019061027e9190612e09565b610971565b005b34801561029157600080fd5b5061029a61098b565b6040516102a79190612ee2565b60405180910390f35b3480156102bc57600080fd5b506102d760048036038101906102d29190612f04565b610a1d565b6040516102e49190612f72565b60405180910390f35b3480156102f957600080fd5b50610314600480360381019061030f9190612f04565b610a99565b005b34801561032257600080fd5b5061033d60048036038101906103389190612fb9565b610aab565b005b34801561034b57600080fd5b5061036660048036038101906103619190612ff9565b610bb0565b6040516103739190612db8565b60405180910390f35b34801561038857600080fd5b50610391610c70565b60405161039e9190613035565b60405180910390f35b3480156103b357600080fd5b506103bc610c87565b6040516103c99190613035565b60405180910390f35b3480156103de57600080fd5b506103f960048036038101906103f49190613050565b610c91565b005b34801561040757600080fd5b50610410610ca1565b60405161041d9190613035565b60405180910390f35b34801561043257600080fd5b5061043b610cab565b6040516104489190612db8565b60405180910390f35b34801561045d57600080fd5b50610466610cc5565b005b34801561047457600080fd5b5061048f600480360381019061048a9190612ff9565b610d1c565b005b34801561049d57600080fd5b506104b860048036038101906104b39190613050565b610d68565b005b3480156104c657600080fd5b506104e160048036038101906104dc9190612ff9565b610d88565b005b3480156104ef57600080fd5b5061050a60048036038101906105059190612f04565b610dd4565b6040516105179190612f72565b60405180910390f35b34801561052c57600080fd5b5061054760048036038101906105429190612ff9565b610dea565b6040516105549190612db8565b60405180910390f35b34801561056957600080fd5b50610584600480360381019061057f9190612ff9565b610e40565b6040516105919190613035565b60405180910390f35b3480156105a657600080fd5b506105af610f10565b005b3480156105bd57600080fd5b506105c6610f24565b6040516105d39190612f72565b60405180910390f35b3480156105e857600080fd5b506105f1610f4e565b6040516105fe9190613035565b60405180910390f35b34801561061357600080fd5b5061061c610f58565b6040516106299190612ee2565b60405180910390f35b34801561063e57600080fd5b50610659600480360381019061065491906130a3565b610fea565b005b34801561066757600080fd5b5061067061100c565b60405161067d9190613035565b60405180910390f35b34801561069257600080fd5b506106ad60048036038101906106a89190613122565b611028565b005b3480156106bb57600080fd5b506106d660048036038101906106d19190613297565b6111a0565b005b3480156106e457600080fd5b506106ff60048036038101906106fa9190612f04565b611218565b005b34801561070d57600080fd5b5061072860048036038101906107239190612f04565b61122a565b005b34801561073657600080fd5b5061073f6112c0565b60405161074c9190612db8565b60405180910390f35b34801561076157600080fd5b5061077c60048036038101906107779190612f04565b611305565b6040516107899190612ee2565b60405180910390f35b34801561079e57600080fd5b506107b960048036038101906107b49190612e09565b61142b565b005b3480156107c757600080fd5b506107e260048036038101906107dd91906133e2565b611445565b005b3480156107f057600080fd5b5061080b600480360381019061080691906134df565b6114e2565b005b34801561081957600080fd5b50610834600480360381019061082f9190613557565b61151c565b6040516108419190612db8565b60405180910390f35b610864600480360381019061085f9190612f04565b6115b0565b005b34801561087257600080fd5b5061088d60048036038101906108889190612ff9565b611ab9565b005b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061095a57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b8061096a575061096982611b3d565b5b9050919050565b610979611ba7565b81601081905550806011819055505050565b60606002805461099a906135c6565b80601f01602080910402602001604051908101604052809291908181526020018280546109c6906135c6565b8015610a135780601f106109e857610100808354040283529160200191610a13565b820191906000526020600020905b8154815290600101906020018083116109f657829003601f168201915b5050505050905090565b6000610a2882611c25565b610a5e576040517fcf4700e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b610aa1611ba7565b80600c8190555050565b6000610ab682610dd4565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610b1e576040517f943f7b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610b3d611c73565b73ffffffffffffffffffffffffffffffffffffffff1614610ba057610b6981610b64611c73565b61151c565b610b9f576040517fcfb3b94200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b610bab838383611c7b565b505050565b600080600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000808273ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401610c149190612f72565b602060405180830381865afa158015610c31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c55919061360d565b90506016548110610c6557600191505b819350505050919050565b6000610c7a611d2d565b6001546000540303905090565b6000600c54905090565b610c9c838383611d32565b505050565b6000601454905090565b6000600d544211610cbd576000610cc0565b60015b905090565b610ccd611ba7565b60004790503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610d18573d6000803e3d6000fd5b5050565b610d24611ba7565b80600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610d83838383604051806020016040528060008152506111a0565b505050565b610d90611ba7565b80600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000610ddf826121e8565b600001519050919050565b6000601760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ea8576040517f8f4eb60400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b610f18611ba7565b610f226000612473565b565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000601554905090565b606060038054610f67906135c6565b80601f0160208091040260200160405190810160405280929190818152602001828054610f93906135c6565b8015610fe05780601f10610fb557610100808354040283529160200191610fe0565b820191906000526020600020905b815481529060010190602001808311610fc357829003601f168201915b5050505050905090565b610ff2611ba7565b82600d819055508060128190555081601381905550505050565b6000600d54421061101f57601154611023565b6010545b905090565b611030611c73565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611095576040517fb06307db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600760006110a2611c73565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff1661114f611c73565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516111949190612db8565b60405180910390a35050565b6111ab848484611d32565b6111ca8373ffffffffffffffffffffffffffffffffffffffff16612539565b15611212576111db8484848461255c565b611211576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b50505050565b611220611ba7565b8060168190555050565b611232611ba7565b600c5481611240600b6126ad565b61124a9190613669565b1061128a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112819061370b565b60405180910390fd5b60005b818110156112b25761129f600b6126bb565b80806112aa9061372b565b91505061128d565b506112bd33826126d1565b50565b6000600115156112ce610cab565b151514156112df5760009050611302565b601354600d546112ef9190613774565b42116112fc5760006112ff565b60015b90505b90565b606061131082611c25565b61134f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611346906137f4565b60405180910390fd5b42601254600d546113609190613669565b101561139857600e611371836126ef565b6040516020016113829291906138e4565b6040516020818303038152906040529050611426565b600f80546113a5906135c6565b80601f01602080910402602001604051908101604052809291908181526020018280546113d1906135c6565b801561141e5780601f106113f35761010080835404028352916020019161141e565b820191906000526020600020905b81548152906001019060200180831161140157829003601f168201915b505050505090505b919050565b611433611ba7565b81601481905550806015819055505050565b61144d611ba7565b60005b82518110156114dd57816017600085848151811061147157611470613908565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080806114d59061372b565b915050611450565b505050565b6114ea611ba7565b81600f9080519060200190611500929190612c1e565b5080600e9080519060200190611517929190612c1e565b505050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6115b8610f24565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415611626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161161d90613983565b60405180910390fd5b600c5481611634600b6126ad565b61163e9190613669565b1061167e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116759061370b565b60405180910390fd5b6001151561168b33610bb0565b1515146116cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116c4906139ef565b60405180910390fd5b600d544210156118dd5760011515601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151461176a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161176190613a5b565b60405180910390fd5b601354600d5461177a9190613774565b42116117bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b290613aed565b60405180910390fd5b60145481601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546118099190613669565b111561184a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161184190613b59565b60405180910390fd5b80601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546118959190613669565b601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611a83565b600d544211611921576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191890613beb565b60405180910390fd5b600a811115611965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195c90613c7d565b60405180910390fd5b60155481601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546119b39190613669565b11156119f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119eb90613ce9565b60405180910390fd5b80601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611a3f9190613669565b601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b60005b81811015611aab57611a98600b6126bb565b8080611aa39061372b565b915050611a86565b50611ab633826126d1565b50565b611ac1611ba7565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611b31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b2890613d7b565b60405180910390fd5b611b3a81612473565b50565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b611baf611c73565b73ffffffffffffffffffffffffffffffffffffffff16611bcd610f24565b73ffffffffffffffffffffffffffffffffffffffff1614611c23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c1a90613de7565b60405180910390fd5b565b600081611c30611d2d565b11158015611c3f575060005482105b8015611c6c575060046000838152602001908152602001600020600001601c9054906101000a900460ff16155b9050919050565b600033905090565b826006600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b600090565b6000611d3d826121e8565b90508373ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff1614611da8576040517fa114810000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008473ffffffffffffffffffffffffffffffffffffffff16611dc9611c73565b73ffffffffffffffffffffffffffffffffffffffff161480611df85750611df785611df2611c73565b61151c565b5b80611e3d5750611e06611c73565b73ffffffffffffffffffffffffffffffffffffffff16611e2584610a1d565b73ffffffffffffffffffffffffffffffffffffffff16145b905080611e76576040517f59c896be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415611edd576040517fea553b3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611eea8585856001612850565b611ef660008487611c7b565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160392506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000600460008581526020019081526020016000209050848160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550428160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060006001850190506000600460008381526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561217657600054821461217557878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084602001518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5b505050828473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46121e18585856001612856565b5050505050565b6121f0612ca4565b6000829050806121fe611d2d565b1161243c5760005481101561243b576000600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050806040015161243957600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461231d57809250505061246e565b5b60011561243857818060019003925050600460008381526020019081526020016000206040518060600160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160008201601c9054906101000a900460ff1615151515815250509050600073ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff161461243357809250505061246e565b61231e565b5b505b5b6040517fdf2d9b4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60008373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612582611c73565b8786866040518563ffffffff1660e01b81526004016125a49493929190613e5c565b6020604051808303816000875af19250505080156125e057506040513d601f19601f820116820180604052508101906125dd9190613ebd565b60015b61265a573d8060008114612610576040519150601f19603f3d011682016040523d82523d6000602084013e612615565b606091505b50600081511415612652576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050949350505050565b600081600001549050919050565b6001816000016000828254019250508190555050565b6126eb82826040518060200160405280600081525061285c565b5050565b60606000821415612737576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061284b565b600082905060005b600082146127695780806127529061372b565b915050600a826127629190613f19565b915061273f565b60008167ffffffffffffffff8111156127855761278461316c565b5b6040519080825280601f01601f1916602001820160405280156127b75781602001600182028036833780820191505090505b5090505b60008514612844576001826127d09190613774565b9150600a856127df9190613f4a565b60306127eb9190613669565b60f81b81838151811061280157612800613908565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561283d9190613f19565b94506127bb565b8093505050505b919050565b50505050565b50505050565b600080549050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156128c9576040517f2e07630000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000831415612904576040517fb562e8dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129116000858386612850565b82600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160008282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555082600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160088282829054906101000a900467ffffffffffffffff160192506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550836004600083815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550426004600083815260200190815260200160002060000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600081905060008482019050612ad28673ffffffffffffffffffffffffffffffffffffffff16612539565b15612b97575b818673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612b47600087848060010195508761255c565b612b7d576040517fd1a57ed600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808210612ad8578260005414612b9257600080fd5b612c02565b5b818060010192508673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4808210612b98575b816000819055505050612c186000858386612856565b50505050565b828054612c2a906135c6565b90600052602060002090601f016020900481019282612c4c5760008555612c93565b82601f10612c6557805160ff1916838001178555612c93565b82800160010185558215612c93579182015b82811115612c92578251825591602001919060010190612c77565b5b509050612ca09190612ce7565b5090565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600067ffffffffffffffff1681526020016000151581525090565b5b80821115612d00576000816000905550600101612ce8565b5090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612d4d81612d18565b8114612d5857600080fd5b50565b600081359050612d6a81612d44565b92915050565b600060208284031215612d8657612d85612d0e565b5b6000612d9484828501612d5b565b91505092915050565b60008115159050919050565b612db281612d9d565b82525050565b6000602082019050612dcd6000830184612da9565b92915050565b6000819050919050565b612de681612dd3565b8114612df157600080fd5b50565b600081359050612e0381612ddd565b92915050565b60008060408385031215612e2057612e1f612d0e565b5b6000612e2e85828601612df4565b9250506020612e3f85828601612df4565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612e83578082015181840152602081019050612e68565b83811115612e92576000848401525b50505050565b6000601f19601f8301169050919050565b6000612eb482612e49565b612ebe8185612e54565b9350612ece818560208601612e65565b612ed781612e98565b840191505092915050565b60006020820190508181036000830152612efc8184612ea9565b905092915050565b600060208284031215612f1a57612f19612d0e565b5b6000612f2884828501612df4565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612f5c82612f31565b9050919050565b612f6c81612f51565b82525050565b6000602082019050612f876000830184612f63565b92915050565b612f9681612f51565b8114612fa157600080fd5b50565b600081359050612fb381612f8d565b92915050565b60008060408385031215612fd057612fcf612d0e565b5b6000612fde85828601612fa4565b9250506020612fef85828601612df4565b9150509250929050565b60006020828403121561300f5761300e612d0e565b5b600061301d84828501612fa4565b91505092915050565b61302f81612dd3565b82525050565b600060208201905061304a6000830184613026565b92915050565b60008060006060848603121561306957613068612d0e565b5b600061307786828701612fa4565b935050602061308886828701612fa4565b925050604061309986828701612df4565b9150509250925092565b6000806000606084860312156130bc576130bb612d0e565b5b60006130ca86828701612df4565b93505060206130db86828701612df4565b92505060406130ec86828701612df4565b9150509250925092565b6130ff81612d9d565b811461310a57600080fd5b50565b60008135905061311c816130f6565b92915050565b6000806040838503121561313957613138612d0e565b5b600061314785828601612fa4565b92505060206131588582860161310d565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6131a482612e98565b810181811067ffffffffffffffff821117156131c3576131c261316c565b5b80604052505050565b60006131d6612d04565b90506131e2828261319b565b919050565b600067ffffffffffffffff8211156132025761320161316c565b5b61320b82612e98565b9050602081019050919050565b82818337600083830152505050565b600061323a613235846131e7565b6131cc565b90508281526020810184848401111561325657613255613167565b5b613261848285613218565b509392505050565b600082601f83011261327e5761327d613162565b5b813561328e848260208601613227565b91505092915050565b600080600080608085870312156132b1576132b0612d0e565b5b60006132bf87828801612fa4565b94505060206132d087828801612fa4565b93505060406132e187828801612df4565b925050606085013567ffffffffffffffff81111561330257613301612d13565b5b61330e87828801613269565b91505092959194509250565b600067ffffffffffffffff8211156133355761333461316c565b5b602082029050602081019050919050565b600080fd5b600061335e6133598461331a565b6131cc565b9050808382526020820190506020840283018581111561338157613380613346565b5b835b818110156133aa57806133968882612fa4565b845260208401935050602081019050613383565b5050509392505050565b600082601f8301126133c9576133c8613162565b5b81356133d984826020860161334b565b91505092915050565b600080604083850312156133f9576133f8612d0e565b5b600083013567ffffffffffffffff81111561341757613416612d13565b5b613423858286016133b4565b92505060206134348582860161310d565b9150509250929050565b600067ffffffffffffffff8211156134595761345861316c565b5b61346282612e98565b9050602081019050919050565b600061348261347d8461343e565b6131cc565b90508281526020810184848401111561349e5761349d613167565b5b6134a9848285613218565b509392505050565b600082601f8301126134c6576134c5613162565b5b81356134d684826020860161346f565b91505092915050565b600080604083850312156134f6576134f5612d0e565b5b600083013567ffffffffffffffff81111561351457613513612d13565b5b613520858286016134b1565b925050602083013567ffffffffffffffff81111561354157613540612d13565b5b61354d858286016134b1565b9150509250929050565b6000806040838503121561356e5761356d612d0e565b5b600061357c85828601612fa4565b925050602061358d85828601612fa4565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806135de57607f821691505b602082108114156135f2576135f1613597565b5b50919050565b60008151905061360781612ddd565b92915050565b60006020828403121561362357613622612d0e565b5b6000613631848285016135f8565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061367482612dd3565b915061367f83612dd3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156136b4576136b361363a565b5b828201905092915050565b7f507572636861736520776f756c6420657863656564205f4d4e46545f4d415800600082015250565b60006136f5601f83612e54565b9150613700826136bf565b602082019050919050565b60006020820190508181036000830152613724816136e8565b9050919050565b600061373682612dd3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156137695761376861363a565b5b600182019050919050565b600061377f82612dd3565b915061378a83612dd3565b92508282101561379d5761379c61363a565b5b828203905092915050565b7f546f6b656e20646f6573206e6f74206578697374000000000000000000000000600082015250565b60006137de601483612e54565b91506137e9826137a8565b602082019050919050565b6000602082019050818103600083015261380d816137d1565b9050919050565b600081905092915050565b60008190508160005260206000209050919050565b60008154613841816135c6565b61384b8186613814565b945060018216600081146138665760018114613877576138aa565b60ff198316865281860193506138aa565b6138808561381f565b60005b838110156138a257815481890152600182019150602081019050613883565b838801955050505b50505092915050565b60006138be82612e49565b6138c88185613814565b93506138d8818560208601612e65565b80840191505092915050565b60006138f08285613834565b91506138fc82846138b3565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f596f7520617265206f776e657221000000000000000000000000000000000000600082015250565b600061396d600e83612e54565b915061397882613937565b602082019050919050565b6000602082019050818103600083015261399c81613960565b9050919050565b7f6e65656420746f206f776e206d6f7265204d6f6e6b6520746f6b656e73000000600082015250565b60006139d9601d83612e54565b91506139e4826139a3565b602082019050919050565b60006020820190508181036000830152613a08816139cc565b9050919050565b7f4e6f74207265676973746572656420746f2057686974654c6973740000000000600082015250565b6000613a45601b83612e54565b9150613a5082613a0f565b602082019050919050565b60006020820190508181036000830152613a7481613a38565b9050919050565b7f4d696e74206973206e6f742061637469766174656420666f722070726573616c60008201527f6500000000000000000000000000000000000000000000000000000000000000602082015250565b6000613ad7602183612e54565b9150613ae282613a7b565b604082019050919050565b60006020820190508181036000830152613b0681613aca565b9050919050565b7f4f766572666c6f7720666f722050524553414c455f4d494e545f4c494d495400600082015250565b6000613b43601f83612e54565b9150613b4e82613b0d565b602082019050919050565b60006020820190508181036000830152613b7281613b36565b9050919050565b7f4d696e74206973206e6f742061637469766174656420666f72207075626c696360008201527f2073616c65000000000000000000000000000000000000000000000000000000602082015250565b6000613bd5602583612e54565b9150613be082613b79565b604082019050919050565b60006020820190508181036000830152613c0481613bc8565b9050919050565b7f416d6f756e7420746f206869676820666f722073696e676c65207472616e736160008201527f6374696f6e000000000000000000000000000000000000000000000000000000602082015250565b6000613c67602583612e54565b9150613c7282613c0b565b604082019050919050565b60006020820190508181036000830152613c9681613c5a565b9050919050565b7f4f766572666c6f7720666f72205055424c49435f4d494e545f4c494d49540000600082015250565b6000613cd3601e83612e54565b9150613cde82613c9d565b602082019050919050565b60006020820190508181036000830152613d0281613cc6565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000613d65602683612e54565b9150613d7082613d09565b604082019050919050565b60006020820190508181036000830152613d9481613d58565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000613dd1602083612e54565b9150613ddc82613d9b565b602082019050919050565b60006020820190508181036000830152613e0081613dc4565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000613e2e82613e07565b613e388185613e12565b9350613e48818560208601612e65565b613e5181612e98565b840191505092915050565b6000608082019050613e716000830187612f63565b613e7e6020830186612f63565b613e8b6040830185613026565b8181036060830152613e9d8184613e23565b905095945050505050565b600081519050613eb781612d44565b92915050565b600060208284031215613ed357613ed2612d0e565b5b6000613ee184828501613ea8565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613f2482612dd3565b9150613f2f83612dd3565b925082613f3f57613f3e613eea565b5b828204905092915050565b6000613f5582612dd3565b9150613f6083612dd3565b925082613f7057613f6f613eea565b5b82820690509291505056fea264697066735822122091be3311bd889c5e13c681ebfcd1c4f27bc633ac80190c31762178ca5a1ae0c764736f6c634300080b0033

Deployed Bytecode Sourcemap

59453:6040:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26548:305;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61574:186;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;29663:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;31167:204;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;60710:104;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;30729:372;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;63849:258;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;25788:312;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;62185:78;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32032:170;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;61973:99;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;63415:123;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;62916:145;;;;;;;;;;;;;:::i;:::-;;60608:96;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;32273:185;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;60822:130;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;29471:125;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61453:113;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;26917:206;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;48720:103;;;;;;;;;;;;;:::i;:::-;;48072:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;62078:101;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;29832:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;60960:240;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;63069:132;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;31443:287;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;32529:370;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62272:124;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;63546:297;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;63207:202;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;62564:344;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;61768:199;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;61208:237;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;62402:153;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;31801:164;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;64115:1372;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;48978:201;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;26548:305;26650:4;26702:25;26687:40;;;:11;:40;;;;:105;;;;26759:33;26744:48;;;:11;:48;;;;26687:105;:158;;;;26809:36;26833:11;26809:23;:36::i;:::-;26687:158;26667:178;;26548:305;;;:::o;61574:186::-;47958:13;:11;:13::i;:::-;61693:16:::1;61677:13;:32;;;;61736:15;61721:12;:30;;;;61574:186:::0;;:::o;29663:100::-;29717:13;29750:5;29743:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29663:100;:::o;31167:204::-;31235:7;31260:16;31268:7;31260;:16::i;:::-;31255:64;;31285:34;;;;;;;;;;;;;;31255:64;31339:15;:24;31355:7;31339:24;;;;;;;;;;;;;;;;;;;;;31332:31;;31167:204;;;:::o;60710:104::-;47958:13;:11;:13::i;:::-;60797:9:::1;60785;:21;;;;60710:104:::0;:::o;30729:372::-;30802:13;30818:24;30834:7;30818:15;:24::i;:::-;30802:40;;30863:5;30857:11;;:2;:11;;;30853:48;;;30877:24;;;;;;;;;;;;;;30853:48;30934:5;30918:21;;:12;:10;:12::i;:::-;:21;;;30914:139;;30945:37;30962:5;30969:12;:10;:12::i;:::-;30945:16;:37::i;:::-;30941:112;;31006:35;;;;;;;;;;;;;;30941:112;30914:139;31065:28;31074:2;31078:7;31087:5;31065:8;:28::i;:::-;30791:310;30729:372;;:::o;63849:258::-;63906:4;63917:15;63942:14;;;;;;;;;;;63917:40;;63962:11;63986:8;63997;:18;;;64016:4;63997:24;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63986:35;;64038:19;;64031:3;:26;64028:55;;64073:4;64064:13;;64028:55;64096:6;64089:13;;;;;63849:258;;;:::o;25788:312::-;25841:7;26066:15;:13;:15::i;:::-;26051:12;;26035:13;;:28;:46;26028:53;;25788:312;:::o;62185:78::-;62228:7;62249:9;;62242:16;;62185:78;:::o;32032:170::-;32166:28;32176:4;32182:2;32186:7;32166:9;:28::i;:::-;32032:170;;;:::o;61973:99::-;62028:7;62049:18;;62042:25;;61973:99;:::o;63415:123::-;63466:4;63503:15;;63485;:33;63484:49;;63528:5;63484:49;;;63521:4;63484:49;63477:56;;63415:123;:::o;62916:145::-;47958:13;:11;:13::i;:::-;62966:15:::1;62984:21;62966:39;;63024:10;63016:28;;:37;63045:7;63016:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;62955:106;62916:145::o:0;60608:96::-;47958:13;:11;:13::i;:::-;60691:5:::1;60674:14;;:22;;;;;;;;;;;;;;;;;;60608:96:::0;:::o;32273:185::-;32411:39;32428:4;32434:2;32438:7;32411:39;;;;;;;;;;;;:16;:39::i;:::-;32273:185;;;:::o;60822:130::-;47958:13;:11;:13::i;:::-;60929:14:::1;60903:15;;:41;;;;;;;;;;;;;;;;;;60822:130:::0;:::o;29471:125::-;29535:7;29562:21;29575:7;29562:12;:21::i;:::-;:26;;;29555:33;;29471:125;;;:::o;61453:113::-;61511:4;61535:17;:23;61553:4;61535:23;;;;;;;;;;;;;;;;;;;;;;;;;61528:30;;61453:113;;;:::o;26917:206::-;26981:7;27022:1;27005:19;;:5;:19;;;27001:60;;;27033:28;;;;;;;;;;;;;;27001:60;27087:12;:19;27100:5;27087:19;;;;;;;;;;;;;;;:27;;;;;;;;;;;;27079:36;;27072:43;;26917:206;;;:::o;48720:103::-;47958:13;:11;:13::i;:::-;48785:30:::1;48812:1;48785:18;:30::i;:::-;48720:103::o:0;48072:87::-;48118:7;48145:6;;;;;;;;;;;48138:13;;48072:87;:::o;62078:101::-;62136:7;62157:17;;62150:24;;62078:101;:::o;29832:104::-;29888:13;29921:7;29914:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29832:104;:::o;60960:240::-;47958:13;:11;:13::i;:::-;61102:14:::1;61084:15;:32;;;;61142:11;61127:12;:26;;;;61180:12;61164:13;:28;;;;60960:240:::0;;;:::o;63069:132::-;63107:7;63147:15;;63129;:33;63128:65;;63181:12;;63128:65;;;63165:13;;63128:65;63121:72;;63069:132;:::o;31443:287::-;31554:12;:10;:12::i;:::-;31542:24;;:8;:24;;;31538:54;;;31575:17;;;;;;;;;;;;;;31538:54;31650:8;31605:18;:32;31624:12;:10;:12::i;:::-;31605:32;;;;;;;;;;;;;;;:42;31638:8;31605:42;;;;;;;;;;;;;;;;:53;;;;;;;;;;;;;;;;;;31703:8;31674:48;;31689:12;:10;:12::i;:::-;31674:48;;;31713:8;31674:48;;;;;;:::i;:::-;;;;;;;;31443:287;;:::o;32529:370::-;32696:28;32706:4;32712:2;32716:7;32696:9;:28::i;:::-;32739:15;:2;:13;;;:15::i;:::-;32735:157;;;32760:56;32791:4;32797:2;32801:7;32810:5;32760:30;:56::i;:::-;32756:136;;32840:40;;;;;;;;;;;;;;32756:136;32735:157;32529:370;;;;:::o;62272:124::-;47958:13;:11;:13::i;:::-;62376:12:::1;62354:19;:34;;;;62272:124:::0;:::o;63546:297::-;47958:13;:11;:13::i;:::-;63658:9:::1;;63643:12;63619:21;:11;:19;:21::i;:::-;:36;;;;:::i;:::-;:48;63611:92;;;;;;;;;;;;:::i;:::-;;;;;;;;;63717:9;63712:78;63736:12;63732:1;:16;63712:78;;;63761:23;:11;:21;:23::i;:::-;63750:3;;;;;:::i;:::-;;;;63712:78;;;;63800:35;63810:10;63822:12;63800:9;:35::i;:::-;63546:297:::0;:::o;63207:202::-;63259:4;63298;63274:28;;:20;:18;:20::i;:::-;:28;;;63270:58;;;63317:5;63310:12;;;;63270:58;63376:13;;63358:15;;:31;;;;:::i;:::-;63340:15;:49;63339:65;;63399:5;63339:65;;;63392:4;63339:65;63332:72;;63207:202;;:::o;62564:344::-;62638:13;62672:16;62680:7;62672;:16::i;:::-;62664:49;;;;;;;;;;;;:::i;:::-;;;;;;;;;62763:15;62748:12;;62730:15;;:30;;;;:::i;:::-;:48;62726:147;;;62826:13;62841:18;:7;:16;:18::i;:::-;62809:51;;;;;;;;;:::i;:::-;;;;;;;;;;;;;62795:66;;;;62726:147;62890:10;62883:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62564:344;;;;:::o;61768:199::-;47958:13;:11;:13::i;:::-;61899:16:::1;61878:18;:37;;;;61940:19;61920:17;:39;;;;61768:199:::0;;:::o;61208:237::-;47958:13;:11;:13::i;:::-;61314:9:::1;61309:129;61333:16;:23;61329:1;:27;61309:129;;;61419:7;61378:17;:38;61396:16;61413:1;61396:19;;;;;;;;:::i;:::-;;;;;;;;61378:38;;;;;;;;;;;;;;;;:48;;;;;;;;;;;;;;;;;;61358:3;;;;;:::i;:::-;;;;61309:129;;;;61208:237:::0;;:::o;62402:153::-;47958:13;:11;:13::i;:::-;62510:9:::1;62497:10;:22;;;;;;;;;;;;:::i;:::-;;62540:7;62524:13;:23;;;;;;;;;;;;:::i;:::-;;62402:153:::0;;:::o;31801:164::-;31898:4;31922:18;:25;31941:5;31922:25;;;;;;;;;;;;;;;:35;31948:8;31922:35;;;;;;;;;;;;;;;;;;;;;;;;;31915:42;;31801:164;;;;:::o;64115:1372::-;64207:7;:5;:7::i;:::-;64193:21;;:10;:21;;;;64185:48;;;;;;;;;;;;:::i;:::-;;;;;;;;;64293:9;;64276:14;64252:21;:11;:19;:21::i;:::-;:38;;;;:::i;:::-;:50;64244:94;;;;;;;;;;;;:::i;:::-;;;;;;;;;64380:4;64351:33;;:25;64365:10;64351:13;:25::i;:::-;:33;;;64343:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;64453:15;;64435;:33;64431:896;;;64526:4;64493:37;;:17;:29;64511:10;64493:29;;;;;;;;;;;;;;;;;;;;;;;;;:37;;;64485:77;;;;;;;;;;;;:::i;:::-;;;;;;;;;64624:13;;64606:15;;:31;;;;:::i;:::-;64588:15;:49;64580:96;;;;;;;;;;;;:::i;:::-;;;;;;;;;64756:18;;64738:14;64699:24;:36;64724:10;64699:36;;;;;;;;;;;;;;;;:53;;;;:::i;:::-;:75;;64691:119;;;;;;;;;;;;:::i;:::-;;;;;;;;;64903:14;64864:24;:36;64889:10;64864:36;;;;;;;;;;;;;;;;:53;;;;:::i;:::-;64825:24;:36;64850:10;64825:36;;;;;;;;;;;;;;;:92;;;;64431:896;;;64970:15;;64952;:33;64944:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;65059:2;65041:14;:20;;65033:70;;;;;;;;;;;;:::i;:::-;;;;;;;;;65173:17;;65155:14;65117:23;:35;65141:10;65117:35;;;;;;;;;;;;;;;;:52;;;;:::i;:::-;:73;;65109:116;;;;;;;;;;;;:::i;:::-;;;;;;;;;65307:14;65269:23;:35;65293:10;65269:35;;;;;;;;;;;;;;;;:52;;;;:::i;:::-;65231:23;:35;65255:10;65231:35;;;;;;;;;;;;;;;:90;;;;64431:896;65343:9;65339:89;65358:14;65356:1;:16;65339:89;;;65393:23;:11;:21;:23::i;:::-;65374:3;;;;;:::i;:::-;;;;65339:89;;;;65442:37;65452:10;65464:14;65442:9;:37::i;:::-;64115:1372;:::o;48978:201::-;47958:13;:11;:13::i;:::-;49087:1:::1;49067:22;;:8;:22;;;;49059:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;49143:28;49162:8;49143:18;:28::i;:::-;48978:201:::0;:::o;23531:157::-;23616:4;23655:25;23640:40;;;:11;:40;;;;23633:47;;23531:157;;;:::o;48237:132::-;48312:12;:10;:12::i;:::-;48301:23;;:7;:5;:7::i;:::-;:23;;;48293:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;48237:132::o;33154:174::-;33211:4;33254:7;33235:15;:13;:15::i;:::-;:26;;:53;;;;;33275:13;;33265:7;:23;33235:53;:85;;;;;33293:11;:20;33305:7;33293:20;;;;;;;;;;;:27;;;;;;;;;;;;33292:28;33235:85;33228:92;;33154:174;;;:::o;19945:98::-;19998:7;20025:10;20018:17;;19945:98;:::o;42376:196::-;42518:2;42491:15;:24;42507:7;42491:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;42556:7;42552:2;42536:28;;42545:5;42536:28;;;;;;;;;;;;42376:196;;;:::o;25562:92::-;25618:7;25562:92;:::o;37324:2130::-;37439:35;37477:21;37490:7;37477:12;:21::i;:::-;37439:59;;37537:4;37515:26;;:13;:18;;;:26;;;37511:67;;37550:28;;;;;;;;;;;;;;37511:67;37591:22;37633:4;37617:20;;:12;:10;:12::i;:::-;:20;;;:73;;;;37654:36;37671:4;37677:12;:10;:12::i;:::-;37654:16;:36::i;:::-;37617:73;:126;;;;37731:12;:10;:12::i;:::-;37707:36;;:20;37719:7;37707:11;:20::i;:::-;:36;;;37617:126;37591:153;;37762:17;37757:66;;37788:35;;;;;;;;;;;;;;37757:66;37852:1;37838:16;;:2;:16;;;37834:52;;;37863:23;;;;;;;;;;;;;;37834:52;37899:43;37921:4;37927:2;37931:7;37940:1;37899:21;:43::i;:::-;38007:35;38024:1;38028:7;38037:4;38007:8;:35::i;:::-;38368:1;38338:12;:18;38351:4;38338:18;;;;;;;;;;;;;;;:26;;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38412:1;38384:12;:16;38397:2;38384:16;;;;;;;;;;;;;;;:24;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38430:31;38464:11;:20;38476:7;38464:20;;;;;;;;;;;38430:54;;38515:2;38499:8;:13;;;:18;;;;;;;;;;;;;;;;;;38565:15;38532:8;:23;;;:49;;;;;;;;;;;;;;;;;;38833:19;38865:1;38855:7;:11;38833:33;;38881:31;38915:11;:24;38927:11;38915:24;;;;;;;;;;;38881:58;;38983:1;38958:27;;:8;:13;;;;;;;;;;;;:27;;;38954:384;;;39168:13;;39153:11;:28;39149:174;;39222:4;39206:8;:13;;;:20;;;;;;;;;;;;;;;;;;39275:13;:28;;;39249:8;:23;;;:54;;;;;;;;;;;;;;;;;;39149:174;38954:384;38313:1036;;;39385:7;39381:2;39366:27;;39375:4;39366:27;;;;;;;;;;;;39404:42;39425:4;39431:2;39435:7;39444:1;39404:20;:42::i;:::-;37428:2026;;37324:2130;;;:::o;28298:1111::-;28360:21;;:::i;:::-;28394:12;28409:7;28394:22;;28477:4;28458:15;:13;:15::i;:::-;:23;28454:888;;28494:13;;28487:4;:20;28483:859;;;28528:31;28562:11;:17;28574:4;28562:17;;;;;;;;;;;28528:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28603:9;:16;;;28598:729;;28674:1;28648:28;;:9;:14;;;:28;;;28644:101;;28712:9;28705:16;;;;;;28644:101;29047:261;29054:4;29047:261;;;29087:6;;;;;;;;29132:11;:17;29144:4;29132:17;;;;;;;;;;;29120:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29206:1;29180:28;;:9;:14;;;:28;;;29176:109;;29248:9;29241:16;;;;;;29176:109;29047:261;;;28598:729;28509:833;28483:859;28454:888;29370:31;;;;;;;;;;;;;;28298:1111;;;;:::o;49339:191::-;49413:16;49432:6;;;;;;;;;;;49413:25;;49458:8;49449:6;;:17;;;;;;;;;;;;;;;;;;49513:8;49482:40;;49503:8;49482:40;;;;;;;;;;;;49402:128;49339:191;:::o;11940:326::-;12000:4;12257:1;12235:7;:19;;;:23;12228:30;;11940:326;;;:::o;43064:667::-;43227:4;43264:2;43248:36;;;43285:12;:10;:12::i;:::-;43299:4;43305:7;43314:5;43248:72;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;43244:480;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43499:1;43482:6;:13;:18;43478:235;;;43528:40;;;;;;;;;;;;;;43478:235;43671:6;43665:13;43656:6;43652:2;43648:15;43641:38;43244:480;43377:45;;;43367:55;;;:6;:55;;;;43360:62;;;43064:667;;;;;;:::o;46240:114::-;46305:7;46332;:14;;;46325:21;;46240:114;;;:::o;46362:127::-;46469:1;46451:7;:14;;;:19;;;;;;;;;;;46362:127;:::o;33412:104::-;33481:27;33491:2;33495:8;33481:27;;;;;;;;;;;;:9;:27::i;:::-;33412:104;;:::o;20595:723::-;20651:13;20881:1;20872:5;:10;20868:53;;;20899:10;;;;;;;;;;;;;;;;;;;;;20868:53;20931:12;20946:5;20931:20;;20962:14;20987:78;21002:1;20994:4;:9;20987:78;;21020:8;;;;;:::i;:::-;;;;21051:2;21043:10;;;;;:::i;:::-;;;20987:78;;;21075:19;21107:6;21097:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21075:39;;21125:154;21141:1;21132:5;:10;21125:154;;21169:1;21159:11;;;;;:::i;:::-;;;21236:2;21228:5;:10;;;;:::i;:::-;21215:2;:24;;;;:::i;:::-;21202:39;;21185:6;21192;21185:14;;;;;;;;:::i;:::-;;;;;:56;;;;;;;;;;;21265:2;21256:11;;;;;:::i;:::-;;;21125:154;;;21303:6;21289:21;;;;;20595:723;;;;:::o;44379:159::-;;;;;:::o;45197:158::-;;;;;:::o;33889:1749::-;34012:20;34035:13;;34012:36;;34077:1;34063:16;;:2;:16;;;34059:48;;;34088:19;;;;;;;;;;;;;;34059:48;34134:1;34122:8;:13;34118:44;;;34144:18;;;;;;;;;;;;;;34118:44;34175:61;34205:1;34209:2;34213:12;34227:8;34175:21;:61::i;:::-;34548:8;34513:12;:16;34526:2;34513:16;;;;;;;;;;;;;;;:24;;;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34612:8;34572:12;:16;34585:2;34572:16;;;;;;;;;;;;;;;:29;;;:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34671:2;34638:11;:25;34650:12;34638:25;;;;;;;;;;;:30;;;:35;;;;;;;;;;;;;;;;;;34738:15;34688:11;:25;34700:12;34688:25;;;;;;;;;;;:40;;;:66;;;;;;;;;;;;;;;;;;34771:20;34794:12;34771:35;;34821:11;34850:8;34835:12;:23;34821:37;;34879:15;:2;:13;;;:15::i;:::-;34875:631;;;34915:313;34971:12;34967:2;34946:38;;34963:1;34946:38;;;;;;;;;;;;35012:69;35051:1;35055:2;35059:14;;;;;;35075:5;35012:30;:69::i;:::-;35007:174;;35117:40;;;;;;;;;;;;;;35007:174;35223:3;35208:12;:18;34915:313;;35309:12;35292:13;;:29;35288:43;;35323:8;;;35288:43;34875:631;;;35372:119;35428:14;;;;;;35424:2;35403:40;;35420:1;35403:40;;;;;;;;;;;;35486:3;35471:12;:18;35372:119;;34875:631;35536:12;35520:13;:28;;;;34488:1072;;35570:60;35599:1;35603:2;35607:12;35621:8;35570:20;:60::i;:::-;34001:1637;33889:1749;;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:77::-;1555:7;1584:5;1573:16;;1518:77;;;:::o;1601:122::-;1674:24;1692:5;1674:24;:::i;:::-;1667:5;1664:35;1654:63;;1713:1;1710;1703:12;1654:63;1601:122;:::o;1729:139::-;1775:5;1813:6;1800:20;1791:29;;1829:33;1856:5;1829:33;:::i;:::-;1729:139;;;;:::o;1874:474::-;1942:6;1950;1999:2;1987:9;1978:7;1974:23;1970:32;1967:119;;;2005:79;;:::i;:::-;1967:119;2125:1;2150:53;2195:7;2186:6;2175:9;2171:22;2150:53;:::i;:::-;2140:63;;2096:117;2252:2;2278:53;2323:7;2314:6;2303:9;2299:22;2278:53;:::i;:::-;2268:63;;2223:118;1874:474;;;;;:::o;2354:99::-;2406:6;2440:5;2434:12;2424:22;;2354:99;;;:::o;2459:169::-;2543:11;2577:6;2572:3;2565:19;2617:4;2612:3;2608:14;2593:29;;2459:169;;;;:::o;2634:307::-;2702:1;2712:113;2726:6;2723:1;2720:13;2712:113;;;2811:1;2806:3;2802:11;2796:18;2792:1;2787:3;2783:11;2776:39;2748:2;2745:1;2741:10;2736:15;;2712:113;;;2843:6;2840:1;2837:13;2834:101;;;2923:1;2914:6;2909:3;2905:16;2898:27;2834:101;2683:258;2634:307;;;:::o;2947:102::-;2988:6;3039:2;3035:7;3030:2;3023:5;3019:14;3015:28;3005:38;;2947:102;;;:::o;3055:364::-;3143:3;3171:39;3204:5;3171:39;:::i;:::-;3226:71;3290:6;3285:3;3226:71;:::i;:::-;3219:78;;3306:52;3351:6;3346:3;3339:4;3332:5;3328:16;3306:52;:::i;:::-;3383:29;3405:6;3383:29;:::i;:::-;3378:3;3374:39;3367:46;;3147:272;3055:364;;;;:::o;3425:313::-;3538:4;3576:2;3565:9;3561:18;3553:26;;3625:9;3619:4;3615:20;3611:1;3600:9;3596:17;3589:47;3653:78;3726:4;3717:6;3653:78;:::i;:::-;3645:86;;3425:313;;;;:::o;3744:329::-;3803:6;3852:2;3840:9;3831:7;3827:23;3823:32;3820:119;;;3858:79;;:::i;:::-;3820:119;3978:1;4003:53;4048:7;4039:6;4028:9;4024:22;4003:53;:::i;:::-;3993:63;;3949:117;3744:329;;;;:::o;4079:126::-;4116:7;4156:42;4149:5;4145:54;4134:65;;4079:126;;;:::o;4211:96::-;4248:7;4277:24;4295:5;4277:24;:::i;:::-;4266:35;;4211:96;;;:::o;4313:118::-;4400:24;4418:5;4400:24;:::i;:::-;4395:3;4388:37;4313:118;;:::o;4437:222::-;4530:4;4568:2;4557:9;4553:18;4545:26;;4581:71;4649:1;4638:9;4634:17;4625:6;4581:71;:::i;:::-;4437:222;;;;:::o;4665:122::-;4738:24;4756:5;4738:24;:::i;:::-;4731:5;4728:35;4718:63;;4777:1;4774;4767:12;4718:63;4665:122;:::o;4793:139::-;4839:5;4877:6;4864:20;4855:29;;4893:33;4920:5;4893:33;:::i;:::-;4793:139;;;;:::o;4938:474::-;5006:6;5014;5063:2;5051:9;5042:7;5038:23;5034:32;5031:119;;;5069:79;;:::i;:::-;5031:119;5189:1;5214:53;5259:7;5250:6;5239:9;5235:22;5214:53;:::i;:::-;5204:63;;5160:117;5316:2;5342:53;5387:7;5378:6;5367:9;5363:22;5342:53;:::i;:::-;5332:63;;5287:118;4938:474;;;;;:::o;5418:329::-;5477:6;5526:2;5514:9;5505:7;5501:23;5497:32;5494:119;;;5532:79;;:::i;:::-;5494:119;5652:1;5677:53;5722:7;5713:6;5702:9;5698:22;5677:53;:::i;:::-;5667:63;;5623:117;5418:329;;;;:::o;5753:118::-;5840:24;5858:5;5840:24;:::i;:::-;5835:3;5828:37;5753:118;;:::o;5877:222::-;5970:4;6008:2;5997:9;5993:18;5985:26;;6021:71;6089:1;6078:9;6074:17;6065:6;6021:71;:::i;:::-;5877:222;;;;:::o;6105:619::-;6182:6;6190;6198;6247:2;6235:9;6226:7;6222:23;6218:32;6215:119;;;6253:79;;:::i;:::-;6215:119;6373:1;6398:53;6443:7;6434:6;6423:9;6419:22;6398:53;:::i;:::-;6388:63;;6344:117;6500:2;6526:53;6571:7;6562:6;6551:9;6547:22;6526:53;:::i;:::-;6516:63;;6471:118;6628:2;6654:53;6699:7;6690:6;6679:9;6675:22;6654:53;:::i;:::-;6644:63;;6599:118;6105:619;;;;;:::o;6730:::-;6807:6;6815;6823;6872:2;6860:9;6851:7;6847:23;6843:32;6840:119;;;6878:79;;:::i;:::-;6840:119;6998:1;7023:53;7068:7;7059:6;7048:9;7044:22;7023:53;:::i;:::-;7013:63;;6969:117;7125:2;7151:53;7196:7;7187:6;7176:9;7172:22;7151:53;:::i;:::-;7141:63;;7096:118;7253:2;7279:53;7324:7;7315:6;7304:9;7300:22;7279:53;:::i;:::-;7269:63;;7224:118;6730:619;;;;;:::o;7355:116::-;7425:21;7440:5;7425:21;:::i;:::-;7418:5;7415:32;7405:60;;7461:1;7458;7451:12;7405:60;7355:116;:::o;7477:133::-;7520:5;7558:6;7545:20;7536:29;;7574:30;7598:5;7574:30;:::i;:::-;7477:133;;;;:::o;7616:468::-;7681:6;7689;7738:2;7726:9;7717:7;7713:23;7709:32;7706:119;;;7744:79;;:::i;:::-;7706:119;7864:1;7889:53;7934:7;7925:6;7914:9;7910:22;7889:53;:::i;:::-;7879:63;;7835:117;7991:2;8017:50;8059:7;8050:6;8039:9;8035:22;8017:50;:::i;:::-;8007:60;;7962:115;7616:468;;;;;:::o;8090:117::-;8199:1;8196;8189:12;8213:117;8322:1;8319;8312:12;8336:180;8384:77;8381:1;8374:88;8481:4;8478:1;8471:15;8505:4;8502:1;8495:15;8522:281;8605:27;8627:4;8605:27;:::i;:::-;8597:6;8593:40;8735:6;8723:10;8720:22;8699:18;8687:10;8684:34;8681:62;8678:88;;;8746:18;;:::i;:::-;8678:88;8786:10;8782:2;8775:22;8565:238;8522:281;;:::o;8809:129::-;8843:6;8870:20;;:::i;:::-;8860:30;;8899:33;8927:4;8919:6;8899:33;:::i;:::-;8809:129;;;:::o;8944:307::-;9005:4;9095:18;9087:6;9084:30;9081:56;;;9117:18;;:::i;:::-;9081:56;9155:29;9177:6;9155:29;:::i;:::-;9147:37;;9239:4;9233;9229:15;9221:23;;8944:307;;;:::o;9257:154::-;9341:6;9336:3;9331;9318:30;9403:1;9394:6;9389:3;9385:16;9378:27;9257:154;;;:::o;9417:410::-;9494:5;9519:65;9535:48;9576:6;9535:48;:::i;:::-;9519:65;:::i;:::-;9510:74;;9607:6;9600:5;9593:21;9645:4;9638:5;9634:16;9683:3;9674:6;9669:3;9665:16;9662:25;9659:112;;;9690:79;;:::i;:::-;9659:112;9780:41;9814:6;9809:3;9804;9780:41;:::i;:::-;9500:327;9417:410;;;;;:::o;9846:338::-;9901:5;9950:3;9943:4;9935:6;9931:17;9927:27;9917:122;;9958:79;;:::i;:::-;9917:122;10075:6;10062:20;10100:78;10174:3;10166:6;10159:4;10151:6;10147:17;10100:78;:::i;:::-;10091:87;;9907:277;9846:338;;;;:::o;10190:943::-;10285:6;10293;10301;10309;10358:3;10346:9;10337:7;10333:23;10329:33;10326:120;;;10365:79;;:::i;:::-;10326:120;10485:1;10510:53;10555:7;10546:6;10535:9;10531:22;10510:53;:::i;:::-;10500:63;;10456:117;10612:2;10638:53;10683:7;10674:6;10663:9;10659:22;10638:53;:::i;:::-;10628:63;;10583:118;10740:2;10766:53;10811:7;10802:6;10791:9;10787:22;10766:53;:::i;:::-;10756:63;;10711:118;10896:2;10885:9;10881:18;10868:32;10927:18;10919:6;10916:30;10913:117;;;10949:79;;:::i;:::-;10913:117;11054:62;11108:7;11099:6;11088:9;11084:22;11054:62;:::i;:::-;11044:72;;10839:287;10190:943;;;;;;;:::o;11139:311::-;11216:4;11306:18;11298:6;11295:30;11292:56;;;11328:18;;:::i;:::-;11292:56;11378:4;11370:6;11366:17;11358:25;;11438:4;11432;11428:15;11420:23;;11139:311;;;:::o;11456:117::-;11565:1;11562;11555:12;11596:710;11692:5;11717:81;11733:64;11790:6;11733:64;:::i;:::-;11717:81;:::i;:::-;11708:90;;11818:5;11847:6;11840:5;11833:21;11881:4;11874:5;11870:16;11863:23;;11934:4;11926:6;11922:17;11914:6;11910:30;11963:3;11955:6;11952:15;11949:122;;;11982:79;;:::i;:::-;11949:122;12097:6;12080:220;12114:6;12109:3;12106:15;12080:220;;;12189:3;12218:37;12251:3;12239:10;12218:37;:::i;:::-;12213:3;12206:50;12285:4;12280:3;12276:14;12269:21;;12156:144;12140:4;12135:3;12131:14;12124:21;;12080:220;;;12084:21;11698:608;;11596:710;;;;;:::o;12329:370::-;12400:5;12449:3;12442:4;12434:6;12430:17;12426:27;12416:122;;12457:79;;:::i;:::-;12416:122;12574:6;12561:20;12599:94;12689:3;12681:6;12674:4;12666:6;12662:17;12599:94;:::i;:::-;12590:103;;12406:293;12329:370;;;;:::o;12705:678::-;12795:6;12803;12852:2;12840:9;12831:7;12827:23;12823:32;12820:119;;;12858:79;;:::i;:::-;12820:119;13006:1;12995:9;12991:17;12978:31;13036:18;13028:6;13025:30;13022:117;;;13058:79;;:::i;:::-;13022:117;13163:78;13233:7;13224:6;13213:9;13209:22;13163:78;:::i;:::-;13153:88;;12949:302;13290:2;13316:50;13358:7;13349:6;13338:9;13334:22;13316:50;:::i;:::-;13306:60;;13261:115;12705:678;;;;;:::o;13389:308::-;13451:4;13541:18;13533:6;13530:30;13527:56;;;13563:18;;:::i;:::-;13527:56;13601:29;13623:6;13601:29;:::i;:::-;13593:37;;13685:4;13679;13675:15;13667:23;;13389:308;;;:::o;13703:412::-;13781:5;13806:66;13822:49;13864:6;13822:49;:::i;:::-;13806:66;:::i;:::-;13797:75;;13895:6;13888:5;13881:21;13933:4;13926:5;13922:16;13971:3;13962:6;13957:3;13953:16;13950:25;13947:112;;;13978:79;;:::i;:::-;13947:112;14068:41;14102:6;14097:3;14092;14068:41;:::i;:::-;13787:328;13703:412;;;;;:::o;14135:340::-;14191:5;14240:3;14233:4;14225:6;14221:17;14217:27;14207:122;;14248:79;;:::i;:::-;14207:122;14365:6;14352:20;14390:79;14465:3;14457:6;14450:4;14442:6;14438:17;14390:79;:::i;:::-;14381:88;;14197:278;14135:340;;;;:::o;14481:834::-;14569:6;14577;14626:2;14614:9;14605:7;14601:23;14597:32;14594:119;;;14632:79;;:::i;:::-;14594:119;14780:1;14769:9;14765:17;14752:31;14810:18;14802:6;14799:30;14796:117;;;14832:79;;:::i;:::-;14796:117;14937:63;14992:7;14983:6;14972:9;14968:22;14937:63;:::i;:::-;14927:73;;14723:287;15077:2;15066:9;15062:18;15049:32;15108:18;15100:6;15097:30;15094:117;;;15130:79;;:::i;:::-;15094:117;15235:63;15290:7;15281:6;15270:9;15266:22;15235:63;:::i;:::-;15225:73;;15020:288;14481:834;;;;;:::o;15321:474::-;15389:6;15397;15446:2;15434:9;15425:7;15421:23;15417:32;15414:119;;;15452:79;;:::i;:::-;15414:119;15572:1;15597:53;15642:7;15633:6;15622:9;15618:22;15597:53;:::i;:::-;15587:63;;15543:117;15699:2;15725:53;15770:7;15761:6;15750:9;15746:22;15725:53;:::i;:::-;15715:63;;15670:118;15321:474;;;;;:::o;15801:180::-;15849:77;15846:1;15839:88;15946:4;15943:1;15936:15;15970:4;15967:1;15960:15;15987:320;16031:6;16068:1;16062:4;16058:12;16048:22;;16115:1;16109:4;16105:12;16136:18;16126:81;;16192:4;16184:6;16180:17;16170:27;;16126:81;16254:2;16246:6;16243:14;16223:18;16220:38;16217:84;;;16273:18;;:::i;:::-;16217:84;16038:269;15987:320;;;:::o;16313:143::-;16370:5;16401:6;16395:13;16386:22;;16417:33;16444:5;16417:33;:::i;:::-;16313:143;;;;:::o;16462:351::-;16532:6;16581:2;16569:9;16560:7;16556:23;16552:32;16549:119;;;16587:79;;:::i;:::-;16549:119;16707:1;16732:64;16788:7;16779:6;16768:9;16764:22;16732:64;:::i;:::-;16722:74;;16678:128;16462:351;;;;:::o;16819:180::-;16867:77;16864:1;16857:88;16964:4;16961:1;16954:15;16988:4;16985:1;16978:15;17005:305;17045:3;17064:20;17082:1;17064:20;:::i;:::-;17059:25;;17098:20;17116:1;17098:20;:::i;:::-;17093:25;;17252:1;17184:66;17180:74;17177:1;17174:81;17171:107;;;17258:18;;:::i;:::-;17171:107;17302:1;17299;17295:9;17288:16;;17005:305;;;;:::o;17316:181::-;17456:33;17452:1;17444:6;17440:14;17433:57;17316:181;:::o;17503:366::-;17645:3;17666:67;17730:2;17725:3;17666:67;:::i;:::-;17659:74;;17742:93;17831:3;17742:93;:::i;:::-;17860:2;17855:3;17851:12;17844:19;;17503:366;;;:::o;17875:419::-;18041:4;18079:2;18068:9;18064:18;18056:26;;18128:9;18122:4;18118:20;18114:1;18103:9;18099:17;18092:47;18156:131;18282:4;18156:131;:::i;:::-;18148:139;;17875:419;;;:::o;18300:233::-;18339:3;18362:24;18380:5;18362:24;:::i;:::-;18353:33;;18408:66;18401:5;18398:77;18395:103;;;18478:18;;:::i;:::-;18395:103;18525:1;18518:5;18514:13;18507:20;;18300:233;;;:::o;18539:191::-;18579:4;18599:20;18617:1;18599:20;:::i;:::-;18594:25;;18633:20;18651:1;18633:20;:::i;:::-;18628:25;;18672:1;18669;18666:8;18663:34;;;18677:18;;:::i;:::-;18663:34;18722:1;18719;18715:9;18707:17;;18539:191;;;;:::o;18736:170::-;18876:22;18872:1;18864:6;18860:14;18853:46;18736:170;:::o;18912:366::-;19054:3;19075:67;19139:2;19134:3;19075:67;:::i;:::-;19068:74;;19151:93;19240:3;19151:93;:::i;:::-;19269:2;19264:3;19260:12;19253:19;;18912:366;;;:::o;19284:419::-;19450:4;19488:2;19477:9;19473:18;19465:26;;19537:9;19531:4;19527:20;19523:1;19512:9;19508:17;19501:47;19565:131;19691:4;19565:131;:::i;:::-;19557:139;;19284:419;;;:::o;19709:148::-;19811:11;19848:3;19833:18;;19709:148;;;;:::o;19863:141::-;19912:4;19935:3;19927:11;;19958:3;19955:1;19948:14;19992:4;19989:1;19979:18;19971:26;;19863:141;;;:::o;20034:845::-;20137:3;20174:5;20168:12;20203:36;20229:9;20203:36;:::i;:::-;20255:89;20337:6;20332:3;20255:89;:::i;:::-;20248:96;;20375:1;20364:9;20360:17;20391:1;20386:137;;;;20537:1;20532:341;;;;20353:520;;20386:137;20470:4;20466:9;20455;20451:25;20446:3;20439:38;20506:6;20501:3;20497:16;20490:23;;20386:137;;20532:341;20599:38;20631:5;20599:38;:::i;:::-;20659:1;20673:154;20687:6;20684:1;20681:13;20673:154;;;20761:7;20755:14;20751:1;20746:3;20742:11;20735:35;20811:1;20802:7;20798:15;20787:26;;20709:4;20706:1;20702:12;20697:17;;20673:154;;;20856:6;20851:3;20847:16;20840:23;;20539:334;;20353:520;;20141:738;;20034:845;;;;:::o;20885:377::-;20991:3;21019:39;21052:5;21019:39;:::i;:::-;21074:89;21156:6;21151:3;21074:89;:::i;:::-;21067:96;;21172:52;21217:6;21212:3;21205:4;21198:5;21194:16;21172:52;:::i;:::-;21249:6;21244:3;21240:16;21233:23;;20995:267;20885:377;;;;:::o;21268:429::-;21445:3;21467:92;21555:3;21546:6;21467:92;:::i;:::-;21460:99;;21576:95;21667:3;21658:6;21576:95;:::i;:::-;21569:102;;21688:3;21681:10;;21268:429;;;;;:::o;21703:180::-;21751:77;21748:1;21741:88;21848:4;21845:1;21838:15;21872:4;21869:1;21862:15;21889:164;22029:16;22025:1;22017:6;22013:14;22006:40;21889:164;:::o;22059:366::-;22201:3;22222:67;22286:2;22281:3;22222:67;:::i;:::-;22215:74;;22298:93;22387:3;22298:93;:::i;:::-;22416:2;22411:3;22407:12;22400:19;;22059:366;;;:::o;22431:419::-;22597:4;22635:2;22624:9;22620:18;22612:26;;22684:9;22678:4;22674:20;22670:1;22659:9;22655:17;22648:47;22712:131;22838:4;22712:131;:::i;:::-;22704:139;;22431:419;;;:::o;22856:179::-;22996:31;22992:1;22984:6;22980:14;22973:55;22856:179;:::o;23041:366::-;23183:3;23204:67;23268:2;23263:3;23204:67;:::i;:::-;23197:74;;23280:93;23369:3;23280:93;:::i;:::-;23398:2;23393:3;23389:12;23382:19;;23041:366;;;:::o;23413:419::-;23579:4;23617:2;23606:9;23602:18;23594:26;;23666:9;23660:4;23656:20;23652:1;23641:9;23637:17;23630:47;23694:131;23820:4;23694:131;:::i;:::-;23686:139;;23413:419;;;:::o;23838:177::-;23978:29;23974:1;23966:6;23962:14;23955:53;23838:177;:::o;24021:366::-;24163:3;24184:67;24248:2;24243:3;24184:67;:::i;:::-;24177:74;;24260:93;24349:3;24260:93;:::i;:::-;24378:2;24373:3;24369:12;24362:19;;24021:366;;;:::o;24393:419::-;24559:4;24597:2;24586:9;24582:18;24574:26;;24646:9;24640:4;24636:20;24632:1;24621:9;24617:17;24610:47;24674:131;24800:4;24674:131;:::i;:::-;24666:139;;24393:419;;;:::o;24818:220::-;24958:34;24954:1;24946:6;24942:14;24935:58;25027:3;25022:2;25014:6;25010:15;25003:28;24818:220;:::o;25044:366::-;25186:3;25207:67;25271:2;25266:3;25207:67;:::i;:::-;25200:74;;25283:93;25372:3;25283:93;:::i;:::-;25401:2;25396:3;25392:12;25385:19;;25044:366;;;:::o;25416:419::-;25582:4;25620:2;25609:9;25605:18;25597:26;;25669:9;25663:4;25659:20;25655:1;25644:9;25640:17;25633:47;25697:131;25823:4;25697:131;:::i;:::-;25689:139;;25416:419;;;:::o;25841:181::-;25981:33;25977:1;25969:6;25965:14;25958:57;25841:181;:::o;26028:366::-;26170:3;26191:67;26255:2;26250:3;26191:67;:::i;:::-;26184:74;;26267:93;26356:3;26267:93;:::i;:::-;26385:2;26380:3;26376:12;26369:19;;26028:366;;;:::o;26400:419::-;26566:4;26604:2;26593:9;26589:18;26581:26;;26653:9;26647:4;26643:20;26639:1;26628:9;26624:17;26617:47;26681:131;26807:4;26681:131;:::i;:::-;26673:139;;26400:419;;;:::o;26825:224::-;26965:34;26961:1;26953:6;26949:14;26942:58;27034:7;27029:2;27021:6;27017:15;27010:32;26825:224;:::o;27055:366::-;27197:3;27218:67;27282:2;27277:3;27218:67;:::i;:::-;27211:74;;27294:93;27383:3;27294:93;:::i;:::-;27412:2;27407:3;27403:12;27396:19;;27055:366;;;:::o;27427:419::-;27593:4;27631:2;27620:9;27616:18;27608:26;;27680:9;27674:4;27670:20;27666:1;27655:9;27651:17;27644:47;27708:131;27834:4;27708:131;:::i;:::-;27700:139;;27427:419;;;:::o;27852:224::-;27992:34;27988:1;27980:6;27976:14;27969:58;28061:7;28056:2;28048:6;28044:15;28037:32;27852:224;:::o;28082:366::-;28224:3;28245:67;28309:2;28304:3;28245:67;:::i;:::-;28238:74;;28321:93;28410:3;28321:93;:::i;:::-;28439:2;28434:3;28430:12;28423:19;;28082:366;;;:::o;28454:419::-;28620:4;28658:2;28647:9;28643:18;28635:26;;28707:9;28701:4;28697:20;28693:1;28682:9;28678:17;28671:47;28735:131;28861:4;28735:131;:::i;:::-;28727:139;;28454:419;;;:::o;28879:180::-;29019:32;29015:1;29007:6;29003:14;28996:56;28879:180;:::o;29065:366::-;29207:3;29228:67;29292:2;29287:3;29228:67;:::i;:::-;29221:74;;29304:93;29393:3;29304:93;:::i;:::-;29422:2;29417:3;29413:12;29406:19;;29065:366;;;:::o;29437:419::-;29603:4;29641:2;29630:9;29626:18;29618:26;;29690:9;29684:4;29680:20;29676:1;29665:9;29661:17;29654:47;29718:131;29844:4;29718:131;:::i;:::-;29710:139;;29437:419;;;:::o;29862:225::-;30002:34;29998:1;29990:6;29986:14;29979:58;30071:8;30066:2;30058:6;30054:15;30047:33;29862:225;:::o;30093:366::-;30235:3;30256:67;30320:2;30315:3;30256:67;:::i;:::-;30249:74;;30332:93;30421:3;30332:93;:::i;:::-;30450:2;30445:3;30441:12;30434:19;;30093:366;;;:::o;30465:419::-;30631:4;30669:2;30658:9;30654:18;30646:26;;30718:9;30712:4;30708:20;30704:1;30693:9;30689:17;30682:47;30746:131;30872:4;30746:131;:::i;:::-;30738:139;;30465:419;;;:::o;30890:182::-;31030:34;31026:1;31018:6;31014:14;31007:58;30890:182;:::o;31078:366::-;31220:3;31241:67;31305:2;31300:3;31241:67;:::i;:::-;31234:74;;31317:93;31406:3;31317:93;:::i;:::-;31435:2;31430:3;31426:12;31419:19;;31078:366;;;:::o;31450:419::-;31616:4;31654:2;31643:9;31639:18;31631:26;;31703:9;31697:4;31693:20;31689:1;31678:9;31674:17;31667:47;31731:131;31857:4;31731:131;:::i;:::-;31723:139;;31450:419;;;:::o;31875:98::-;31926:6;31960:5;31954:12;31944:22;;31875:98;;;:::o;31979:168::-;32062:11;32096:6;32091:3;32084:19;32136:4;32131:3;32127:14;32112:29;;31979:168;;;;:::o;32153:360::-;32239:3;32267:38;32299:5;32267:38;:::i;:::-;32321:70;32384:6;32379:3;32321:70;:::i;:::-;32314:77;;32400:52;32445:6;32440:3;32433:4;32426:5;32422:16;32400:52;:::i;:::-;32477:29;32499:6;32477:29;:::i;:::-;32472:3;32468:39;32461:46;;32243:270;32153:360;;;;:::o;32519:640::-;32714:4;32752:3;32741:9;32737:19;32729:27;;32766:71;32834:1;32823:9;32819:17;32810:6;32766:71;:::i;:::-;32847:72;32915:2;32904:9;32900:18;32891:6;32847:72;:::i;:::-;32929;32997:2;32986:9;32982:18;32973:6;32929:72;:::i;:::-;33048:9;33042:4;33038:20;33033:2;33022:9;33018:18;33011:48;33076:76;33147:4;33138:6;33076:76;:::i;:::-;33068:84;;32519:640;;;;;;;:::o;33165:141::-;33221:5;33252:6;33246:13;33237:22;;33268:32;33294:5;33268:32;:::i;:::-;33165:141;;;;:::o;33312:349::-;33381:6;33430:2;33418:9;33409:7;33405:23;33401:32;33398:119;;;33436:79;;:::i;:::-;33398:119;33556:1;33581:63;33636:7;33627:6;33616:9;33612:22;33581:63;:::i;:::-;33571:73;;33527:127;33312:349;;;;:::o;33667:180::-;33715:77;33712:1;33705:88;33812:4;33809:1;33802:15;33836:4;33833:1;33826:15;33853:185;33893:1;33910:20;33928:1;33910:20;:::i;:::-;33905:25;;33944:20;33962:1;33944:20;:::i;:::-;33939:25;;33983:1;33973:35;;33988:18;;:::i;:::-;33973:35;34030:1;34027;34023:9;34018:14;;33853:185;;;;:::o;34044:176::-;34076:1;34093:20;34111:1;34093:20;:::i;:::-;34088:25;;34127:20;34145:1;34127:20;:::i;:::-;34122:25;;34166:1;34156:35;;34171:18;;:::i;:::-;34156:35;34212:1;34209;34205:9;34200:14;;34044:176;;;;:::o

Swarm Source

ipfs://91be3311bd889c5e13c681ebfcd1c4f27bc633ac80190c31762178ca5a1ae0c7
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.