ETH Price: $3,086.65 (-2.07%)

Token

Age of Z (AOZ)
 

Overview

Max Total Supply

1,605 AOZ

Holders

463

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
44 AOZ
0xfc6d61941f1e42883a98b641ec411c8ab2a4c93e
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

The Age-of-Z citizens are 1993 hand-drawn unique erc721 NFT

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
AOZ

Compiler Version
v0.7.0+commit.9e61f92b

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-12-07
*/

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

// File: @openzeppelin/contracts/utils/Context.sol
/*
 * @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 GSN 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 payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

// File: @openzeppelin/contracts/introspection/IERC165.sol

pragma solidity >=0.6.0 <0.8.0;

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

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

pragma solidity >=0.6.2 <0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

pragma solidity >=0.6.2 <0.8.0;

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

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

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

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

pragma solidity >=0.6.2 <0.8.0;

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

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

pragma solidity >=0.6.0 <0.8.0;

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

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

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
abstract contract ERC165 is IERC165 {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    constructor() {
        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     *
     * Time complexity O(1), guaranteed to always use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal virtual {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

// File: @openzeppelin/contracts/math/SafeMath.sol

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

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

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) private 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

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

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

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

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

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

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

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

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

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

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

            return true;
        } else {
            return false;
        }
    }

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

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

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

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

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

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

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

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

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

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

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

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

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

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

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

    // UintSet

    struct UintSet {
        Set _inner;
    }

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

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

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

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

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

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

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Library for managing an enumerable variant of Solidity's
 * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
 * type.
 *
 * Maps have the following properties:
 *
 * - Entries are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Entries are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableMap for EnumerableMap.UintToAddressMap;
 *
 *     // Declare a set state variable
 *     EnumerableMap.UintToAddressMap private myMap;
 * }
 * ```
 *
 * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are
 * supported.
 */
library EnumerableMap {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Map type with
    // bytes32 keys and values.
    // The Map implementation uses private functions, and user-facing
    // implementations (such as Uint256ToAddressMap) are just wrappers around
    // the underlying Map.
    // This means that we can only create new EnumerableMaps for types that fit
    // in bytes32.

    struct MapEntry {
        bytes32 _key;
        bytes32 _value;
    }

    struct Map {
        // Storage of map keys and values
        MapEntry[] _entries;
        // Position of the entry defined by a key in the `entries` array, plus 1
        // because index 0 means a key is not in the map.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function _set(
        Map storage map,
        bytes32 key,
        bytes32 value
    ) private returns (bool) {
        // We read and store the key's index to prevent multiple reads from the same storage slot
        uint256 keyIndex = map._indexes[key];

        if (keyIndex == 0) {
            // Equivalent to !contains(map, key)
            map._entries.push(MapEntry({ _key: key, _value: value }));
            // The entry is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            map._indexes[key] = map._entries.length;
            return true;
        } else {
            map._entries[keyIndex - 1]._value = value;
            return false;
        }
    }

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

        if (keyIndex != 0) {
            // Equivalent to contains(map, key)
            // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one
            // in the array, and then remove the last entry (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = keyIndex - 1;
            uint256 lastIndex = map._entries.length - 1;

            // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            MapEntry storage lastEntry = map._entries[lastIndex];

            // Move the last entry to the index where the entry to delete is
            map._entries[toDeleteIndex] = lastEntry;
            // Update the index for the moved entry
            map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved entry was stored
            map._entries.pop();

            // Delete the index for the deleted slot
            delete map._indexes[key];

            return true;
        } else {
            return false;
        }
    }

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

    /**
     * @dev Returns the number of key-value pairs in the map. O(1).
     */
    function _length(Map storage map) private view returns (uint256) {
        return map._entries.length;
    }

    /**
     * @dev Returns the key-value pair stored at position `index` in the map. O(1).
     *
     * Note that there are no guarantees on the ordering of entries inside the
     * array, and it may change when more entries are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
        require(map._entries.length > index, "EnumerableMap: index out of bounds");

        MapEntry storage entry = map._entries[index];
        return (entry._key, entry._value);
    }

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     */
    function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
        uint256 keyIndex = map._indexes[key];
        if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)
        return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function _get(Map storage map, bytes32 key) private view returns (bytes32) {
        uint256 keyIndex = map._indexes[key];
        require(keyIndex != 0, "EnumerableMap: nonexistent key"); // Equivalent to contains(map, key)
        return map._entries[keyIndex - 1]._value; // All indexes are 1-based
    }

    /**
     * @dev Same as {_get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {_tryGet}.
     */
    function _get(
        Map storage map,
        bytes32 key,
        string memory errorMessage
    ) private view returns (bytes32) {
        uint256 keyIndex = map._indexes[key];
        require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)
        return map._entries[keyIndex - 1]._value; // All indexes are 1-based
    }

    // UintToAddressMap

    struct UintToAddressMap {
        Map _inner;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(
        UintToAddressMap storage map,
        uint256 key,
        address value
    ) internal returns (bool) {
        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
    }

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

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

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

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

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     *
     * _Available since v3.4._
     */
    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
        (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
        return (success, address(uint160(uint256(value))));
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
        return address(uint160(uint256(_get(map._inner, bytes32(key)))));
    }

    /**
     * @dev Same as {get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryGet}.
     */
    function get(
        UintToAddressMap storage map,
        uint256 key,
        string memory errorMessage
    ) internal view returns (address) {
        return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
    }
}

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

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    /**
     * @dev Converts a `uint256` to its ASCII `string` 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);
        uint256 index = digits - 1;
        temp = value;
        while (temp != 0) {
            buffer[index--] = bytes1(uint8(48 + (temp % 10)));
            temp /= 10;
        }
        return string(buffer);
    }
}

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

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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

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

pragma solidity >=0.6.0 <0.8.0;

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://eips.ethereum.org/EIPS/eip-721
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
    using SafeMath for uint256;
    using Address for address;
    using EnumerableSet for EnumerableSet.UintSet;
    using EnumerableMap for EnumerableMap.UintToAddressMap;
    using Strings for uint256;

    // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
    bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;

    // Mapping from holder address to their (enumerable) set of owned tokens
    mapping(address => EnumerableSet.UintSet) private _holderTokens;

    // Enumerable mapping from token ids to their owners
    EnumerableMap.UintToAddressMap private _tokenOwners;

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

    // Base URI
    string private _baseURI;

    /*
     *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
     *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
     *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
     *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
     *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
     *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
     *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
     *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
     *
     *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
     *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
     */
    bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;

    /*
     *     bytes4(keccak256('name()')) == 0x06fdde03
     *     bytes4(keccak256('symbol()')) == 0x95d89b41
     *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
     *
     *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
     */
    bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;

    /*
     *     bytes4(keccak256('totalSupply()')) == 0x18160ddd
     *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
     *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
     *
     *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
     */
    bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;

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

        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);
        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _holderTokens[owner].length();
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
    }

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

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

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

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

        // If there is no base URI, return the token URI.
        if (bytes(base).length == 0 || bytes(_tokenURI).length > 0) {
            return _tokenURI;
        }

        // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
        return string(abi.encodePacked(base, tokenId.toString()));
    }

    /**
     * @dev Returns the base URI set via {_setBaseURI}. This will be
     * automatically added as a prefix in {tokenURI} to each token's URI, or
     * to the token ID if no specific URI is set for that token ID.
     */
    function baseURI() public view virtual returns (string memory) {
        return _baseURI;
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        return _holderTokens[owner].at(index);
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
        return _tokenOwners.length();
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        (uint256 tokenId, ) = _tokenOwners.at(index);
        return tokenId;
    }

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

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

        _approve(to, tokenId);
    }

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

        return _tokenApprovals[tokenId];
    }

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

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

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

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

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

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

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

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

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

        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

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

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

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

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

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

        _holderTokens[owner].remove(tokenId);

        _tokenOwners.remove(tokenId);

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

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

        _beforeTokenTransfer(from, to, tokenId);

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

        _holderTokens[from].remove(tokenId);
        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        emit Transfer(from, to, tokenId);
    }

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

    /**
     * @dev Internal function to set the base URI for all token IDs. It is
     * automatically added as a prefix to the value returned in {tokenURI},
     * or to the token ID if {tokenURI} is empty.
     */
    function _setBaseURI(string memory baseURI_) internal virtual {
        _baseURI = baseURI_;
    }

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

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

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

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

pragma solidity >=0.6.0 <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() {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = 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");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

// File: contracts/AOZ.sol

//
//                     ,----..             ,----,
//    ,---,           /   /   \          .'   .`|
//   '  .' \         /   .     :      .'   .'   ;
//  /  ;    '.      .   /   ;.  \   ,---, '    .'
// :  :       \    .   ;   /  ` ;   |   :     ./
// :  |   /\   \   ;   |  ; \ ; |   ;   | .'  /
// |  :  ' ;.   :  |   :  | ; | '   `---' /  ;
// |  |  ;/  \   \ .   |  ' ' ' :     /  ;  /
// '  :  | \  \ ,' '   ;  \; /  |    ;  /  /--,
// |  |  '  '--'    \   \  ',  /    /  /  / .`|
// |  :  :           ;   :    /   ./__;       :
// |  | ,'            \   \ .'    |   :     .'
// `--''               `---`      ;   |  .'
//                                `---'

pragma experimental ABIEncoderV2;
pragma solidity ^0.7.0;

/**
 * @title AOZ contract
 * @dev Extends ERC721 Non-Fungible Token Standard basic implementation
 */
contract AOZ is ERC721, ReentrancyGuard, Ownable {
    using SafeMath for uint256;
    using Address for address;

    uint256 public constant aozPrice = 0.05 ether;
    uint256 public constant derivedPrice = 0.01 ether;

    uint256 public constant maxAOZPurchase = 2;
    uint256 public constant maxAOZDerive = 5;

    uint256 public constant MAX_SALE_AOZS = 1500;

    uint256 private constant MAX_SSR_TOKEN_ID = 9;
    uint256 private constant MAX_SR_TOKEN_ID = 49;
    uint256 private constant MAX_R_TOKEN_ID = 499;
    uint256 private constant MAX_N_TOKEN_ID = 1992;

    uint256 private constant MAX_SSR_DERIVE_NUM_PER_SUPER = 16;
    uint256 private constant MAX_SR_DERIVE_NUM_PER_SUPER = 8;
    uint256 private constant MAX_R_DERIVE_NUM_PER_SUPER = 4;
    uint256 private constant MAX_N_DERIVE_NUM_PER_SUPER = 2;

    uint256 private PAYABLE_DERIVED_START_TOKEN_ID = 7259;
    // 5000 payable derived token id from 7259 to 12258
    uint256 private _payableDerivedIdCounter;
    uint256 private constant MAX_PAYABLE_DERIVE_TOKEN_ID = 12258;

    // Grades of NFT
    enum Grade{None, SSR, SR, R, N}

    // Mapping from Grade to get the max derived number of the NFT
    mapping(Grade => uint256) private _mapMaxDerivedNum;

    // Mapping from Grade to get the current derived id counter
    mapping(Grade => uint256) private _mapDerivedIdCounter;

    // Mapping from super class token id to the number of sub class NFT that it has derived
    mapping(uint256 => uint256) public derivedRecord;

    // Mapping from sub class token id to its super's
    mapping(uint256 => uint256) private _derivedSubToSuper;

    bool public saleIsActive = false;
    bool public deriveIsActive = false;

    string private _contractURI;

    // Array of the token ids for blind box sale
    uint256[] public tokenIdsOnSale;

    constructor() ERC721("Age of Z", "AOZ") {
        // initialize _mapMaxDerivedNum
        _mapMaxDerivedNum[Grade.SSR] = MAX_SSR_DERIVE_NUM_PER_SUPER;
        _mapMaxDerivedNum[Grade.SR] = MAX_SR_DERIVE_NUM_PER_SUPER;
        _mapMaxDerivedNum[Grade.R] = MAX_R_DERIVE_NUM_PER_SUPER;
        _mapMaxDerivedNum[Grade.N] = MAX_N_DERIVE_NUM_PER_SUPER;

        // initialize _mapDerivedIdCounter
        _mapDerivedIdCounter[Grade.SSR] = 1993;
        _mapDerivedIdCounter[Grade.SR] = 2153;
        _mapDerivedIdCounter[Grade.R] = 2473;
        _mapDerivedIdCounter[Grade.N] = 4273;

        // initialize _payableDerivedIdCounter
        _payableDerivedIdCounter = PAYABLE_DERIVED_START_TOKEN_ID;
    }

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

    // Set Contract-level URI
    function setContractURI(string memory contractURI_) external onlyOwner {
        _contractURI = contractURI_;
    }

    // View Contract-level URI
    function contractURI() public view returns (string memory) {
        return _contractURI;
    }

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

    // Pause sale if active, make active if paused
    function flipSaleState() public onlyOwner {
        saleIsActive = !saleIsActive;
    }

    // Pause derive if active, make active if paused
    function flipDeriveState() public onlyOwner {
        deriveIsActive = !deriveIsActive;
    }

    // Mint AOZ
    function mintAOZ(uint256 numberOfTokens) public payable nonReentrant {
        address buyer = msg.sender;
        require(saleIsActive, "Sale must be active to mint AOZ");
        require(!buyer.isContract(), "Sale only to EOA");
        require(buyer.balance >= 0.5 ether, "Wallet balance must be greater than 0.5 ether");
        require(numberOfTokens <= maxAOZPurchase, "Can only mint 2 tokens at a time");
        require(numberOfTokens <= tokenIdsOnSale.length, "Purchase would exceed max supply of aoz");
        require(aozPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");

        for (uint256 i = 0; i < numberOfTokens; i++) {
            _safeMint(buyer, _getTokenIdToBeMinted(MAX_SALE_AOZS.sub(tokenIdsOnSale.length)));
        }
    }

    // Set token ids on sales
    function setTokenIdsOnSales(uint256 startId, uint256 endId) public onlyOwner {
        uint256 num = endId.sub(startId).add(1);
        // sanity check
        require(!saleIsActive && totalSupply() == 0, "Set ids must come before mintage");
        require(tokenIdsOnSale.length.add(num) <= MAX_SALE_AOZS, "Ids num exceeds the limit");

        while (startId <= endId) {
            tokenIdsOnSale.push(startId);
            startId++;
        }
    }

    // Get the current length of tokenIdsOnSale
    function getTokenIdsOnSaleLength() public view returns (uint256){
        return tokenIdsOnSale.length;
    }

    // get the super token id from a certain derived sub token id
    function getSuperTokenIdFromDerivedSub(uint256 derivedSubTokenId) public view returns (uint256){
        require(
            derivedSubTokenId > MAX_N_TOKEN_ID && derivedSubTokenId < PAYABLE_DERIVED_START_TOKEN_ID,
            "No information about super NFT"
        );
        require(_exists(derivedSubTokenId), "Has not been derived");
        return _derivedSubToSuper[derivedSubTokenId];
    }

    // Batch mint tokens to specific receivers by the owner
    function batchMintToAddresses(
        uint256[] calldata tokenIds,
        address[] calldata receivers
    )
    public
    onlyOwner
    {
        // sanity check
        uint256 tokenIdsLen = tokenIds.length;
        require(tokenIdsLen == receivers.length, "Unmatched lens of arrays");

        for (uint256 i = 0; i < tokenIdsLen; i++) {
            require(tokenIds[i] <= MAX_N_TOKEN_ID, "Not qualified to mint");
            _safeMint(receivers[i], tokenIds[i]);
        }
    }

    // Batch derive from super class freely
    /*      GRADE   ->   DERIVED TOKEN ID
     *       SSR    ->      1993 - 2152
     *       SR     ->      2153 - 2472
     *        R     ->      2473 - 4272
     *        N     ->      4273 - 7258
     */
    function batchDeriveFromSuperClass(
        uint256[] calldata superClassTokenIds,
        uint256[] calldata amountsToDerive
    )
    public
    nonReentrant
    {
        // sanity check
        uint256 tokenIdsLen = superClassTokenIds.length;
        require(tokenIdsLen == amountsToDerive.length, "Unmatched lens of arrays");
        require(deriveIsActive, "Not active to derive AOZ");

        for (uint256 i = 0; i < tokenIdsLen; i++) {
            uint256 superClassTokenId = superClassTokenIds[i];
            uint256 derivedAmount = amountsToDerive[i];

            address creator = msg.sender;
            require(superClassTokenId <= MAX_N_TOKEN_ID, "Not qualified to derive");
            require(!creator.isContract(), "Derivation only to EOA");
            require(ownerOf(superClassTokenId) == creator, "Wrong ownership");
            require(derivedAmount > 0, "Derive amount not correct");
            uint256 newDerivedRecord = derivedRecord[superClassTokenId].add(derivedAmount);
            Grade grade = _getGradeFromTokenId(superClassTokenId);
            require(
                newDerivedRecord <= _mapMaxDerivedNum[grade],
                "Exceed derived limitation"
            );

            // derive
            derivedRecord[superClassTokenId] = newDerivedRecord;
            uint256 idCounter = _mapDerivedIdCounter[grade];
            for (uint256 j = 0; j < derivedAmount; j++) {
                // update mapping to store super's token id
                _derivedSubToSuper[idCounter] = superClassTokenId;
                _safeMint(creator, idCounter);
                idCounter++;
            }
            _mapDerivedIdCounter[grade] = idCounter;
        }
    }

    // Pay to derive token with 0.01eth per NFT
    function payToDerive(uint256 amountToDerive) public payable nonReentrant {
        address creator = msg.sender;
        require(!creator.isContract(), "Derivation only to EOA");
        require(deriveIsActive, "Not active to derive AOZ");
        require(amountToDerive <= maxAOZDerive, "Can only derive 5 tokens at a time");
        uint256 newPayableDerivedIdCounter = _payableDerivedIdCounter.add(amountToDerive);
        require(
            newPayableDerivedIdCounter <= MAX_PAYABLE_DERIVE_TOKEN_ID,
            "Derive would exceed max supply of aoz"
        );
        require(derivedPrice.mul(amountToDerive) <= msg.value, "Ether value sent is not correct");

        for (uint256 i = _payableDerivedIdCounter; i < newPayableDerivedIdCounter; i++) {
            _safeMint(creator, i);
        }
        _payableDerivedIdCounter = newPayableDerivedIdCounter;
    }

    // Set token uri by the owner of contract
    function setTokenURI(uint256 tokenId, string memory tokenURI) public onlyOwner {
        _setTokenURI(tokenId, tokenURI);
    }

    // Batch Set token uri by the owner of contract
    function batchSetTokenURI(uint256[] calldata tokenIds, string[] calldata tokenURIs) public onlyOwner {
        require(tokenIds.length == tokenURIs.length, "Unmatched lens of arrays");
        for (uint256 i = 0; i < tokenIds.length; i++) {
            _setTokenURI(tokenIds[i], tokenURIs[i]);
        }
    }

    function _getGradeFromTokenId(uint256 tokenId) private pure returns (Grade){
        if (tokenId <= MAX_SSR_TOKEN_ID) {
            return Grade.SSR;
        } else if (tokenId <= MAX_SR_TOKEN_ID) {
            return Grade.SR;
        } else if (tokenId <= MAX_R_TOKEN_ID) {
            return Grade.R;
        } else if (tokenId <= MAX_N_TOKEN_ID) {
            return Grade.N;
        } else {
            return Grade.None;
        }
    }

    /**
   * @dev Returns a random available token id to be minted
   *
   * Code used as reference:
   * https://github.com/1001-digital/erc721-extensions/blob/main/contracts/RandomlyAssigned.sol
   */
    function _getTokenIdToBeMinted(uint256 _totalMintedTokens)
    private
    returns (uint256 tokenId)
    {
        uint256 tokenIdsOnSaleLen = tokenIdsOnSale.length;
        // get random number in range of the length of tokenIdsOnSale as the index
        uint256 randomIndex = _getRandomNumber(tokenIdsOnSaleLen, _totalMintedTokens);

        tokenId = tokenIdsOnSale[randomIndex];

        // reshape the array with popping the picked id out
        tokenIdsOnSale[randomIndex] = tokenIdsOnSale[tokenIdsOnSaleLen - 1];
        tokenIdsOnSale.pop();
    }

    // Generates a pseudo-random number.
    function _getRandomNumber(uint256 _upper, uint256 _totalMintedTokens)
    private
    view
    returns (uint256)
    {
        uint256 random = uint256(
                keccak256(
                    abi.encodePacked(
                        _totalMintedTokens,
                        blockhash(block.number - 1),
                        block.coinbase,
                        block.difficulty,
                        msg.sender
                    )
                )
            );

        return random % _upper;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MAX_SALE_AOZS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"aozPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"superClassTokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"amountsToDerive","type":"uint256[]"}],"name":"batchDeriveFromSuperClass","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"address[]","name":"receivers","type":"address[]"}],"name":"batchMintToAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string[]","name":"tokenURIs","type":"string[]"}],"name":"batchSetTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deriveIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"derivedPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"derivedRecord","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flipDeriveState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flipSaleState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"derivedSubTokenId","type":"uint256"}],"name":"getSuperTokenIdFromDerivedSub","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenIdsOnSaleLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"maxAOZDerive","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxAOZPurchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"mintAOZ","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountToDerive","type":"uint256"}],"name":"payToDerive","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":[],"name":"saleIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"contractURI_","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startId","type":"uint256"},{"internalType":"uint256","name":"endId","type":"uint256"}],"name":"setTokenIdsOnSales","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"tokenURI","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdsOnSale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052611c5b600c556012805461ffff191690553480156200002257600080fd5b50604080518082018252600881526720b3b29037b3102d60c11b6020808301919091528251808401909352600383526220a7ad60e91b90830152906200006f6301ffc9a760e01b6200026c565b815162000084906006906020850190620002cb565b5080516200009a906007906020840190620002cb565b50620000ad6380ac58cd60e01b6200026c565b620000bf635b5e139f60e01b6200026c565b620000d163780e9d6360e01b6200026c565b50506001600a556000620000e4620002c7565b600b80546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35060107fa7c5ba7114a813b50159add3a36832908dc83db71d0b9a24c2ad0f83be9582075560087f9adb202b1492743bc00c81d33cdc6423fa8c79109027eb6a845391e8fc1f04815560047fe0283e559c29e31ee7f56467acc9dd307779c843a883aeeb3bf5c6128c90814481905560027fa1d6913cd9e08c872be3e7525cca82e4fc0fc298a783f19022be725b19be685a55600f6020526107c97f169f97de0d9a84d840042b17d3c6b9638b3d6fd9024c9eb0c7a306a17b49f88f556108697fa74ba3945261e09fde15ba3db55005b205e61eeb4ad811ac0faa2b315bffeead556109a97f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc8296828556000526110b17f367ccd2d0ac16bf7110a5dffe0801fdc9452a95a1adb7e1a12fe97dd3e9a4edd55600c54600d556200039e565b6001600160e01b03198082161415620002a25760405162461bcd60e51b8152600401620002999062000367565b60405180910390fd5b6001600160e01b0319166000908152602081905260409020805460ff19166001179055565b3390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200030e57805160ff19168380011785556200033e565b828001600101855582156200033e579182015b828111156200033e57825182559160200191906001019062000321565b506200034c92915062000350565b5090565b5b808211156200034c576000815560010162000351565b6020808252601c908201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604082015260600190565b6135a480620003ae6000396000f3fe6080604052600436106102675760003560e01c806353658a9411610144578063938e3d7b116100b6578063b88d4fde1161007a578063b88d4fde146106a1578063c87b56dd146106c1578063e8a3d485146106e1578063e985e9c5146106f6578063eb8d244414610716578063f2fde38b1461072b57610267565b8063938e3d7b1461061757806395d89b4114610637578063a22cb4651461064c578063af61710f1461066c578063b7f1116e1461068c57610267565b80636c0360eb116101085780636c0360eb146105855780636cf77e731461059a57806370a08231146105ba578063715018a6146105da5780638da5cb5b146105ef57806391d32edd1461060457610267565b806353658a94146104f0578063554add8f1461051057806355f804b3146105255780636352211e146105455780636706467b1461056557610267565b80632d69c331116101dd5780633ccfd60b116101a15780633ccfd60b1461044657806342842e0e1461045b5780634f6ccce71461047b5780634f7ae9751461049b5780634fa1258a146104bb578063531f7f70146104db57610267565b80632d69c331146103d45780632f745c59146103e957806334918dfd1461040957806334c62fce1461041e578063397f4b211461043357610267565b8063162094c41161022f578063162094c41461034057806318160ddd146103605780631b8c32a4146103755780631e3589c71461038a57806323b872dd1461039f57806326ce9ca4146103bf57610267565b806301ffc9a71461026c57806306fdde03146102a2578063081812fc146102c4578063095ea7b3146102f15780630b523ca714610313575b600080fd5b34801561027857600080fd5b5061028c610287366004612805565b61074b565b60405161029991906129f2565b60405180910390f35b3480156102ae57600080fd5b506102b761076e565b60405161029991906129fd565b3480156102d057600080fd5b506102e46102df366004612870565b610804565b60405161029991906129a1565b3480156102fd57600080fd5b5061031161030c366004612772565b610850565b005b34801561031f57600080fd5b5061033361032e366004612870565b6108e8565b604051610299919061346e565b34801561034c57600080fd5b5061031161035b366004612888565b6108fa565b34801561036c57600080fd5b50610333610947565b34801561038157600080fd5b5061028c610958565b34801561039657600080fd5b50610333610966565b3480156103ab57600080fd5b506103116103ba36600461268f565b61096b565b3480156103cb57600080fd5b506103336109a3565b3480156103e057600080fd5b506103116109a9565b3480156103f557600080fd5b50610333610404366004612772565b610a05565b34801561041557600080fd5b50610311610a30565b34801561042a57600080fd5b50610333610a83565b610311610441366004612870565b610a8e565b34801561045257600080fd5b50610311610bef565b34801561046757600080fd5b5061031161047636600461268f565b610c5d565b34801561048757600080fd5b50610333610496366004612870565b610c78565b3480156104a757600080fd5b506103336104b6366004612870565b610c8e565b3480156104c757600080fd5b506103116104d636600461279c565b610cac565b3480156104e757600080fd5b50610333610d96565b3480156104fc57600080fd5b5061031161050b3660046128cd565b610da1565b34801561051c57600080fd5b50610333610ea4565b34801561053157600080fd5b5061031161054036600461283d565b610ea9565b34801561055157600080fd5b506102e4610560366004612870565b610ef4565b34801561057157600080fd5b5061031161058036600461279c565b610f1c565b34801561059157600080fd5b506102b7611002565b3480156105a657600080fd5b506103336105b5366004612870565b611063565b3480156105c657600080fd5b506103336105d5366004612640565b6110cb565b3480156105e657600080fd5b50610311611114565b3480156105fb57600080fd5b506102e461119d565b610311610612366004612870565b6111ac565b34801561062357600080fd5b5061031161063236600461283d565b6112d2565b34801561064357600080fd5b506102b7611324565b34801561065857600080fd5b50610311610667366004612737565b611385565b34801561067857600080fd5b5061031161068736600461279c565b611453565b34801561069857600080fd5b506103336116d6565b3480156106ad57600080fd5b506103116106bc3660046126cf565b6116dc565b3480156106cd57600080fd5b506102b76106dc366004612870565b61171b565b3480156106ed57600080fd5b506102b761183b565b34801561070257600080fd5b5061028c61071136600461265b565b61189c565b34801561072257600080fd5b5061028c6118ca565b34801561073757600080fd5b50610311610746366004612640565b6118d3565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107fa5780601f106107cf576101008083540402835291602001916107fa565b820191906000526020600020905b8154815290600101906020018083116107dd57829003601f168201915b5050505050905090565b600061080f82611994565b6108345760405162461bcd60e51b815260040161082b9061312d565b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061085b82610ef4565b9050806001600160a01b0316836001600160a01b0316141561088f5760405162461bcd60e51b815260040161082b906132c9565b806001600160a01b03166108a16119a1565b6001600160a01b031614806108bd57506108bd816107116119a1565b6108d95760405162461bcd60e51b815260040161082b90612e9b565b6108e383836119a5565b505050565b60106020526000908152604090205481565b6109026119a1565b6001600160a01b031661091361119d565b6001600160a01b0316146109395760405162461bcd60e51b815260040161082b906131c5565b6109438282611a13565b5050565b60006109536002611a57565b905090565b601254610100900460ff1681565b600581565b61097c6109766119a1565b82611a62565b6109985760405162461bcd60e51b815260040161082b9061330a565b6108e3838383611ae7565b60145490565b6109b16119a1565b6001600160a01b03166109c261119d565b6001600160a01b0316146109e85760405162461bcd60e51b815260040161082b906131c5565b6012805461ff001981166101009182900460ff1615909102179055565b6001600160a01b0382166000908152600160205260408120610a279083611bf5565b90505b92915050565b610a386119a1565b6001600160a01b0316610a4961119d565b6001600160a01b031614610a6f5760405162461bcd60e51b815260040161082b906131c5565b6012805460ff19811660ff90911615179055565b66b1a2bc2ec5000081565b6002600a541415610ab15760405162461bcd60e51b815260040161082b906133c9565b6002600a55601254339060ff16610ada5760405162461bcd60e51b815260040161082b90613292565b610aec816001600160a01b0316611c01565b15610b095760405162461bcd60e51b815260040161082b90612fdd565b6706f05b59d3b20000816001600160a01b0316311015610b3b5760405162461bcd60e51b815260040161082b90612e4e565b6002821115610b5c5760405162461bcd60e51b815260040161082b90612f71565b601454821115610b7e5760405162461bcd60e51b815260040161082b90612d0b565b34610b9066b1a2bc2ec5000084611c07565b1115610bae5760405162461bcd60e51b815260040161082b90612d94565b60005b82811015610be557601454610bdd908390610bd890610bd3906105dc90611c41565b611c69565b611cf2565b600101610bb1565b50506001600a5550565b610bf76119a1565b6001600160a01b0316610c0861119d565b6001600160a01b031614610c2e5760405162461bcd60e51b815260040161082b906131c5565b6040514790339082156108fc029083906000818181858888f19350505050158015610943573d6000803e3d6000fd5b6108e3838383604051806020016040528060008152506116dc565b600080610c86600284611d0c565b509392505050565b60148181548110610c9b57fe5b600091825260209091200154905081565b610cb46119a1565b6001600160a01b0316610cc561119d565b6001600160a01b031614610ceb5760405162461bcd60e51b815260040161082b906131c5565b82818114610d0b5760405162461bcd60e51b815260040161082b906130b5565b60005b81811015610d8e576107c8868683818110610d2557fe5b905060200201351115610d4a5760405162461bcd60e51b815260040161082b90612f42565b610d86848483818110610d5957fe5b9050602002016020810190610d6e9190612640565b878784818110610d7a57fe5b90506020020135611cf2565b600101610d0e565b505050505050565b662386f26fc1000081565b610da96119a1565b6001600160a01b0316610dba61119d565b6001600160a01b031614610de05760405162461bcd60e51b815260040161082b906131c5565b6000610df76001610df18486611c41565b90611d2a565b60125490915060ff16158015610e125750610e10610947565b155b610e2e5760405162461bcd60e51b815260040161082b90612ab9565b6014546105dc90610e3f9083611d2a565b1115610e5d5760405162461bcd60e51b815260040161082b90613392565b5b8183116108e35760148054600181810183556000929092527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec0184905590920191610e5e565b600281565b610eb16119a1565b6001600160a01b0316610ec261119d565b6001600160a01b031614610ee85760405162461bcd60e51b815260040161082b906131c5565b610ef181611d4f565b50565b6000610a2a826040518060600160405280602981526020016135466029913960029190611d62565b610f246119a1565b6001600160a01b0316610f3561119d565b6001600160a01b031614610f5b5760405162461bcd60e51b815260040161082b906131c5565b828114610f7a5760405162461bcd60e51b815260040161082b906130b5565b60005b83811015610ffb57610ff3858583818110610f9457fe5b90506020020135848484818110610fa757fe5b9050602002810190610fb99190613477565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a1392505050565b600101610f7d565b5050505050565b60098054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107fa5780601f106107cf576101008083540402835291602001916107fa565b60006107c8821180156110775750600c5482105b6110935760405162461bcd60e51b815260040161082b90613400565b61109c82611994565b6110b85760405162461bcd60e51b815260040161082b90612b86565b5060009081526011602052604090205490565b60006001600160a01b0382166110f35760405162461bcd60e51b815260040161082b90612ef8565b6001600160a01b0382166000908152600160205260409020610a2a90611a57565b61111c6119a1565b6001600160a01b031661112d61119d565b6001600160a01b0316146111535760405162461bcd60e51b815260040161082b906131c5565b600b546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600b80546001600160a01b0319169055565b600b546001600160a01b031690565b6002600a5414156111cf5760405162461bcd60e51b815260040161082b906133c9565b6002600a55336111de81611c01565b156111fb5760405162461bcd60e51b815260040161082b90612a89565b601254610100900460ff166112225760405162461bcd60e51b815260040161082b90612fa6565b60058211156112435760405162461bcd60e51b815260040161082b90612d52565b600d546000906112539084611d2a565b9050612fe28111156112775760405162461bcd60e51b815260040161082b90612c4b565b34611289662386f26fc1000085611c07565b11156112a75760405162461bcd60e51b815260040161082b90612d94565b600d545b818110156112c5576112bd8382611cf2565b6001016112ab565b50600d5550506001600a55565b6112da6119a1565b6001600160a01b03166112eb61119d565b6001600160a01b0316146113115760405162461bcd60e51b815260040161082b906131c5565b80516109439060139060208401906124d6565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107fa5780601f106107cf576101008083540402835291602001916107fa565b61138d6119a1565b6001600160a01b0316826001600160a01b031614156113be5760405162461bcd60e51b815260040161082b90612cd4565b80600560006113cb6119a1565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff19169215159290921790915561140f6119a1565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161144791906129f2565b60405180910390a35050565b6002600a5414156114765760405162461bcd60e51b815260040161082b906133c9565b6002600a558281811461149b5760405162461bcd60e51b815260040161082b906130b5565b601254610100900460ff166114c25760405162461bcd60e51b815260040161082b90612fa6565b60005b818110156116c95760008686838181106114db57fe5b90506020020135905060008585848181106114f257fe5b90506020020135905060003390506107c88311156115225760405162461bcd60e51b815260040161082b9061307e565b611534816001600160a01b0316611c01565b156115515760405162461bcd60e51b815260040161082b90612a89565b806001600160a01b031661156484610ef4565b6001600160a01b03161461158a5760405162461bcd60e51b815260040161082b90612c22565b600082116115aa5760405162461bcd60e51b815260040161082b90613437565b6000838152601060205260408120546115c39084611d2a565b905060006115d085611d79565b9050600e60008260048111156115e257fe5b60048111156115ed57fe5b81526020019081526020016000205482111561161b5760405162461bcd60e51b815260040161082b90612a52565b6000858152601060205260408120839055600f8183600481111561163b57fe5b600481111561164657fe5b815260200190815260200160002054905060005b8581101561168957600082815260116020526040902087905561167d8583611cf2565b6001918201910161165a565b5080600f600084600481111561169b57fe5b60048111156116a657fe5b81526020810191909152604001600020555050600190940193506114c592505050565b50506001600a5550505050565b6105dc81565b6116ed6116e76119a1565b83611a62565b6117095760405162461bcd60e51b815260040161082b9061330a565b61171584848484611dc5565b50505050565b606061172682611994565b6117425760405162461bcd60e51b815260040161082b90613243565b60008281526008602090815260409182902080548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452606093928301828280156117d75780601f106117ac576101008083540402835291602001916117d7565b820191906000526020600020905b8154815290600101906020018083116117ba57829003601f168201915b5050505050905060606117e8611002565b90508051600014806117fb575060008251115b1561180857509050610769565b8061181285611df8565b604051602001611823929190612936565b60405160208183030381529060405292505050919050565b60138054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107fa5780601f106107cf576101008083540402835291602001916107fa565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60125460ff1681565b6118db6119a1565b6001600160a01b03166118ec61119d565b6001600160a01b0316146119125760405162461bcd60e51b815260040161082b906131c5565b6001600160a01b0381166119385760405162461bcd60e51b815260040161082b90612b40565b600b546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000610a2a600283611ed3565b3390565b600081815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906119da82610ef4565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b611a1c82611994565b611a385760405162461bcd60e51b815260040161082b90613179565b600082815260086020908152604090912082516108e3928401906124d6565b6000610a2a82611edf565b6000611a6d82611994565b611a895760405162461bcd60e51b815260040161082b90612e02565b6000611a9483610ef4565b9050806001600160a01b0316846001600160a01b03161480611acf5750836001600160a01b0316611ac484610804565b6001600160a01b0316145b80611adf5750611adf818561189c565b949350505050565b826001600160a01b0316611afa82610ef4565b6001600160a01b031614611b205760405162461bcd60e51b815260040161082b906131fa565b6001600160a01b038216611b465760405162461bcd60e51b815260040161082b90612c90565b611b518383836108e3565b611b5c6000826119a5565b6001600160a01b0383166000908152600160205260409020611b7e9082611ee3565b506001600160a01b0382166000908152600160205260409020611ba19082611eef565b50611bae60028284611efb565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000610a278383611f11565b3b151590565b600082611c1657506000610a2a565b82820282848281611c2357fe5b0414610a275760405162461bcd60e51b815260040161082b906130ec565b600082821115611c635760405162461bcd60e51b815260040161082b90612dcb565b50900390565b60145460009081611c7a8285611f56565b905060148181548110611c8957fe5b9060005260206000200154925060146001830381548110611ca657fe5b906000526020600020015460148281548110611cbe57fe5b6000918252602090912001556014805480611cd557fe5b600190038181906000526020600020016000905590555050919050565b610943828260405180602001604052806000815250611fa3565b6000808080611d1b8686611fd6565b909450925050505b9250929050565b600082820183811015610a275760405162461bcd60e51b815260040161082b90612beb565b80516109439060099060208401906124d6565b6000611d6f848484612032565b90505b9392505050565b600060098211611d8b57506001610769565b60318211611d9b57506002610769565b6101f38211611dac57506003610769565b6107c88211611dbd57506004610769565b506000610769565b611dd0848484611ae7565b611ddc84848484612091565b6117155760405162461bcd60e51b815260040161082b90612aee565b606081611e1d57506040805180820190915260018152600360fc1b6020820152610769565b8160005b8115611e3557600101600a82049150611e21565b60608167ffffffffffffffff81118015611e4e57600080fd5b506040519080825280601f01601f191660200182016040528015611e79576020820181803683370190505b50859350905060001982015b8315611eca57600a840660300160f81b82828060019003935081518110611ea857fe5b60200101906001600160f81b031916908160001a905350600a84049350611e85565b50949350505050565b6000610a278383612170565b5490565b6000610a278383612188565b6000610a27838361224e565b6000611d6f84846001600160a01b038516612298565b81546000908210611f345760405162461bcd60e51b815260040161082b90612a10565b826000018281548110611f4357fe5b9060005260206000200154905092915050565b600080826001430340414433604051602001611f76959493929190612965565b6040516020818303038152906040528051906020012060001c9050838181611f9a57fe5b06949350505050565b611fad838361232f565b611fba6000848484612091565b6108e35760405162461bcd60e51b815260040161082b90612aee565b815460009081908310611ffb5760405162461bcd60e51b815260040161082b90613007565b600084600001848154811061200c57fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816120625760405162461bcd60e51b815260040161082b91906129fd565b5084600001600182038154811061207557fe5b9060005260206000209060020201600101549150509392505050565b60006120a5846001600160a01b0316611c01565b6120b157506001611adf565b6060612139630a85bd0160e11b6120c66119a1565b8887876040516024016120dc94939291906129b5565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806060016040528060328152602001613514603291396001600160a01b03881691906123f3565b90506000818060200190518101906121519190612821565b6001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b6000818152600183016020526040812054801561224457835460001980830191908101906000908790839081106121bb57fe5b90600052602060002001549050808760000184815481106121d857fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061220857fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610a2a565b6000915050610a2a565b600061225a8383612170565b61229057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610a2a565b506000610a2a565b6000828152600184016020526040812054806122fd575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611d72565b8285600001600183038154811061231057fe5b9060005260206000209060020201600101819055506000915050611d72565b6001600160a01b0382166123555760405162461bcd60e51b815260040161082b90613049565b61235e81611994565b1561237b5760405162461bcd60e51b815260040161082b90612bb4565b612387600083836108e3565b6001600160a01b03821660009081526001602052604090206123a99082611eef565b506123b660028284611efb565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6060611d6f84846000858561240785611c01565b6124235760405162461bcd60e51b815260040161082b9061335b565b60006060866001600160a01b03168587604051612440919061291a565b60006040518083038185875af1925050503d806000811461247d576040519150601f19603f3d011682016040523d82523d6000602084013e612482565b606091505b509150915061249282828661249d565b979650505050505050565b606083156124ac575081611d72565b8251156124bc5782518084602001fd5b8160405162461bcd60e51b815260040161082b91906129fd565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061251757805160ff1916838001178555612544565b82800160010185558215612544579182015b82811115612544578251825591602001919060010190612529565b50612550929150612554565b5090565b5b808211156125505760008155600101612555565b80356001600160a01b0381168114610a2a57600080fd5b60008083601f840112612591578182fd5b50813567ffffffffffffffff8111156125a8578182fd5b6020830191508360208083028501011115611d2357600080fd5b600082601f8301126125d2578081fd5b813567ffffffffffffffff808211156125e9578283fd5b604051601f8301601f191681016020018281118282101715612609578485fd5b60405282815292508284830160200186101561262457600080fd5b8260208601602083013760006020848301015250505092915050565b600060208284031215612651578081fd5b610a278383612569565b6000806040838503121561266d578081fd5b6126778484612569565b91506126868460208501612569565b90509250929050565b6000806000606084860312156126a3578081fd5b83356126ae816134e8565b925060208401356126be816134e8565b929592945050506040919091013590565b600080600080608085870312156126e4578081fd5b6126ee8686612569565b93506126fd8660208701612569565b925060408501359150606085013567ffffffffffffffff81111561271f578182fd5b61272b878288016125c2565b91505092959194509250565b60008060408385031215612749578182fd5b6127538484612569565b915060208301358015158114612767578182fd5b809150509250929050565b60008060408385031215612784578182fd5b61278e8484612569565b946020939093013593505050565b600080600080604085870312156127b1578384fd5b843567ffffffffffffffff808211156127c8578586fd5b6127d488838901612580565b909650945060208701359150808211156127ec578384fd5b506127f987828801612580565b95989497509550505050565b600060208284031215612816578081fd5b8135610a27816134fd565b600060208284031215612832578081fd5b8151610a27816134fd565b60006020828403121561284e578081fd5b813567ffffffffffffffff811115612864578182fd5b611adf848285016125c2565b600060208284031215612881578081fd5b5035919050565b6000806040838503121561289a578182fd5b82359150602083013567ffffffffffffffff8111156128b7578182fd5b6128c3858286016125c2565b9150509250929050565b600080604083850312156128df578182fd5b50508035926020909101359150565b600081518084526129068160208601602086016134bc565b601f01601f19169290920160200192915050565b6000825161292c8184602087016134bc565b9190910192915050565b600083516129488184602088016134bc565b83519083019061295c8183602088016134bc565b01949350505050565b94855260208501939093526bffffffffffffffffffffffff19606092831b81166040860152605485019190915291901b16607482015260880190565b6001600160a01b0391909116815260200190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906129e8908301846128ee565b9695505050505050565b901515815260200190565b600060208252610a2760208301846128ee565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b60208082526019908201527f4578636565642064657269766564206c696d69746174696f6e00000000000000604082015260600190565b60208082526016908201527544657269766174696f6e206f6e6c7920746f20454f4160501b604082015260600190565b6020808252818101527f53657420696473206d75737420636f6d65206265666f7265206d696e74616765604082015260600190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526014908201527312185cc81b9bdd081899595b8819195c9a5d995960621b604082015260600190565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600f908201526e057726f6e67206f776e65727368697608c1b604082015260600190565b60208082526025908201527f44657269766520776f756c6420657863656564206d617820737570706c79206f604082015264331030b7bd60d91b606082015260800190565b60208082526024908201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526019908201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604082015260600190565b60208082526027908201527f507572636861736520776f756c6420657863656564206d617820737570706c796040820152661037b31030b7bd60c91b606082015260800190565b60208082526022908201527f43616e206f6e6c7920646572697665203520746f6b656e7320617420612074696040820152616d6560f01b606082015260800190565b6020808252601f908201527f45746865722076616c75652073656e74206973206e6f7420636f727265637400604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252602c908201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252602d908201527f57616c6c65742062616c616e6365206d7573742062652067726561746572207460408201526c3430b71018171a9032ba3432b960991b606082015260800190565b60208082526038908201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760408201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606082015260800190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604082015269726f206164647265737360b01b606082015260800190565b602080825260159082015274139bdd081c5d585b1a599a5959081d1bc81b5a5b9d605a1b604082015260600190565b6020808252818101527f43616e206f6e6c79206d696e74203220746f6b656e7320617420612074696d65604082015260600190565b60208082526018908201527f4e6f742061637469766520746f2064657269766520414f5a0000000000000000604082015260600190565b60208082526010908201526f53616c65206f6e6c7920746f20454f4160801b604082015260600190565b60208082526022908201527f456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b60208082526017908201527f4e6f74207175616c696669656420746f20646572697665000000000000000000604082015260600190565b60208082526018908201527f556e6d617463686564206c656e73206f66206172726179730000000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252602c908201527f4552433732314d657461646174613a2055524920736574206f66206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960408201526839903737ba1037bbb760b91b606082015260800190565b6020808252602f908201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60408201526e3732bc34b9ba32b73a103a37b5b2b760891b606082015260800190565b6020808252601f908201527f53616c65206d7573742062652061637469766520746f206d696e7420414f5a00604082015260600190565b60208082526021908201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656040820152603960f91b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526019908201527f496473206e756d206578636565647320746865206c696d697400000000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601e908201527f4e6f20696e666f726d6174696f6e2061626f7574207375706572204e46540000604082015260600190565b60208082526019908201527f44657269766520616d6f756e74206e6f7420636f727265637400000000000000604082015260600190565b90815260200190565b6000808335601e1984360301811261348d578283fd5b83018035915067ffffffffffffffff8211156134a7578283fd5b602001915036819003821315611d2357600080fd5b60005b838110156134d75781810151838201526020016134bf565b838111156117155750506000910152565b6001600160a01b0381168114610ef157600080fd5b6001600160e01b031981168114610ef157600080fdfe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656ea2646970667358221220ebf374ffad17971d9ffebdc5a6c05ec516d5caab34b9193b9fea9bc224e9219364736f6c63430007000033

Deployed Bytecode

0x6080604052600436106102675760003560e01c806353658a9411610144578063938e3d7b116100b6578063b88d4fde1161007a578063b88d4fde146106a1578063c87b56dd146106c1578063e8a3d485146106e1578063e985e9c5146106f6578063eb8d244414610716578063f2fde38b1461072b57610267565b8063938e3d7b1461061757806395d89b4114610637578063a22cb4651461064c578063af61710f1461066c578063b7f1116e1461068c57610267565b80636c0360eb116101085780636c0360eb146105855780636cf77e731461059a57806370a08231146105ba578063715018a6146105da5780638da5cb5b146105ef57806391d32edd1461060457610267565b806353658a94146104f0578063554add8f1461051057806355f804b3146105255780636352211e146105455780636706467b1461056557610267565b80632d69c331116101dd5780633ccfd60b116101a15780633ccfd60b1461044657806342842e0e1461045b5780634f6ccce71461047b5780634f7ae9751461049b5780634fa1258a146104bb578063531f7f70146104db57610267565b80632d69c331146103d45780632f745c59146103e957806334918dfd1461040957806334c62fce1461041e578063397f4b211461043357610267565b8063162094c41161022f578063162094c41461034057806318160ddd146103605780631b8c32a4146103755780631e3589c71461038a57806323b872dd1461039f57806326ce9ca4146103bf57610267565b806301ffc9a71461026c57806306fdde03146102a2578063081812fc146102c4578063095ea7b3146102f15780630b523ca714610313575b600080fd5b34801561027857600080fd5b5061028c610287366004612805565b61074b565b60405161029991906129f2565b60405180910390f35b3480156102ae57600080fd5b506102b761076e565b60405161029991906129fd565b3480156102d057600080fd5b506102e46102df366004612870565b610804565b60405161029991906129a1565b3480156102fd57600080fd5b5061031161030c366004612772565b610850565b005b34801561031f57600080fd5b5061033361032e366004612870565b6108e8565b604051610299919061346e565b34801561034c57600080fd5b5061031161035b366004612888565b6108fa565b34801561036c57600080fd5b50610333610947565b34801561038157600080fd5b5061028c610958565b34801561039657600080fd5b50610333610966565b3480156103ab57600080fd5b506103116103ba36600461268f565b61096b565b3480156103cb57600080fd5b506103336109a3565b3480156103e057600080fd5b506103116109a9565b3480156103f557600080fd5b50610333610404366004612772565b610a05565b34801561041557600080fd5b50610311610a30565b34801561042a57600080fd5b50610333610a83565b610311610441366004612870565b610a8e565b34801561045257600080fd5b50610311610bef565b34801561046757600080fd5b5061031161047636600461268f565b610c5d565b34801561048757600080fd5b50610333610496366004612870565b610c78565b3480156104a757600080fd5b506103336104b6366004612870565b610c8e565b3480156104c757600080fd5b506103116104d636600461279c565b610cac565b3480156104e757600080fd5b50610333610d96565b3480156104fc57600080fd5b5061031161050b3660046128cd565b610da1565b34801561051c57600080fd5b50610333610ea4565b34801561053157600080fd5b5061031161054036600461283d565b610ea9565b34801561055157600080fd5b506102e4610560366004612870565b610ef4565b34801561057157600080fd5b5061031161058036600461279c565b610f1c565b34801561059157600080fd5b506102b7611002565b3480156105a657600080fd5b506103336105b5366004612870565b611063565b3480156105c657600080fd5b506103336105d5366004612640565b6110cb565b3480156105e657600080fd5b50610311611114565b3480156105fb57600080fd5b506102e461119d565b610311610612366004612870565b6111ac565b34801561062357600080fd5b5061031161063236600461283d565b6112d2565b34801561064357600080fd5b506102b7611324565b34801561065857600080fd5b50610311610667366004612737565b611385565b34801561067857600080fd5b5061031161068736600461279c565b611453565b34801561069857600080fd5b506103336116d6565b3480156106ad57600080fd5b506103116106bc3660046126cf565b6116dc565b3480156106cd57600080fd5b506102b76106dc366004612870565b61171b565b3480156106ed57600080fd5b506102b761183b565b34801561070257600080fd5b5061028c61071136600461265b565b61189c565b34801561072257600080fd5b5061028c6118ca565b34801561073757600080fd5b50610311610746366004612640565b6118d3565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107fa5780601f106107cf576101008083540402835291602001916107fa565b820191906000526020600020905b8154815290600101906020018083116107dd57829003601f168201915b5050505050905090565b600061080f82611994565b6108345760405162461bcd60e51b815260040161082b9061312d565b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061085b82610ef4565b9050806001600160a01b0316836001600160a01b0316141561088f5760405162461bcd60e51b815260040161082b906132c9565b806001600160a01b03166108a16119a1565b6001600160a01b031614806108bd57506108bd816107116119a1565b6108d95760405162461bcd60e51b815260040161082b90612e9b565b6108e383836119a5565b505050565b60106020526000908152604090205481565b6109026119a1565b6001600160a01b031661091361119d565b6001600160a01b0316146109395760405162461bcd60e51b815260040161082b906131c5565b6109438282611a13565b5050565b60006109536002611a57565b905090565b601254610100900460ff1681565b600581565b61097c6109766119a1565b82611a62565b6109985760405162461bcd60e51b815260040161082b9061330a565b6108e3838383611ae7565b60145490565b6109b16119a1565b6001600160a01b03166109c261119d565b6001600160a01b0316146109e85760405162461bcd60e51b815260040161082b906131c5565b6012805461ff001981166101009182900460ff1615909102179055565b6001600160a01b0382166000908152600160205260408120610a279083611bf5565b90505b92915050565b610a386119a1565b6001600160a01b0316610a4961119d565b6001600160a01b031614610a6f5760405162461bcd60e51b815260040161082b906131c5565b6012805460ff19811660ff90911615179055565b66b1a2bc2ec5000081565b6002600a541415610ab15760405162461bcd60e51b815260040161082b906133c9565b6002600a55601254339060ff16610ada5760405162461bcd60e51b815260040161082b90613292565b610aec816001600160a01b0316611c01565b15610b095760405162461bcd60e51b815260040161082b90612fdd565b6706f05b59d3b20000816001600160a01b0316311015610b3b5760405162461bcd60e51b815260040161082b90612e4e565b6002821115610b5c5760405162461bcd60e51b815260040161082b90612f71565b601454821115610b7e5760405162461bcd60e51b815260040161082b90612d0b565b34610b9066b1a2bc2ec5000084611c07565b1115610bae5760405162461bcd60e51b815260040161082b90612d94565b60005b82811015610be557601454610bdd908390610bd890610bd3906105dc90611c41565b611c69565b611cf2565b600101610bb1565b50506001600a5550565b610bf76119a1565b6001600160a01b0316610c0861119d565b6001600160a01b031614610c2e5760405162461bcd60e51b815260040161082b906131c5565b6040514790339082156108fc029083906000818181858888f19350505050158015610943573d6000803e3d6000fd5b6108e3838383604051806020016040528060008152506116dc565b600080610c86600284611d0c565b509392505050565b60148181548110610c9b57fe5b600091825260209091200154905081565b610cb46119a1565b6001600160a01b0316610cc561119d565b6001600160a01b031614610ceb5760405162461bcd60e51b815260040161082b906131c5565b82818114610d0b5760405162461bcd60e51b815260040161082b906130b5565b60005b81811015610d8e576107c8868683818110610d2557fe5b905060200201351115610d4a5760405162461bcd60e51b815260040161082b90612f42565b610d86848483818110610d5957fe5b9050602002016020810190610d6e9190612640565b878784818110610d7a57fe5b90506020020135611cf2565b600101610d0e565b505050505050565b662386f26fc1000081565b610da96119a1565b6001600160a01b0316610dba61119d565b6001600160a01b031614610de05760405162461bcd60e51b815260040161082b906131c5565b6000610df76001610df18486611c41565b90611d2a565b60125490915060ff16158015610e125750610e10610947565b155b610e2e5760405162461bcd60e51b815260040161082b90612ab9565b6014546105dc90610e3f9083611d2a565b1115610e5d5760405162461bcd60e51b815260040161082b90613392565b5b8183116108e35760148054600181810183556000929092527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec0184905590920191610e5e565b600281565b610eb16119a1565b6001600160a01b0316610ec261119d565b6001600160a01b031614610ee85760405162461bcd60e51b815260040161082b906131c5565b610ef181611d4f565b50565b6000610a2a826040518060600160405280602981526020016135466029913960029190611d62565b610f246119a1565b6001600160a01b0316610f3561119d565b6001600160a01b031614610f5b5760405162461bcd60e51b815260040161082b906131c5565b828114610f7a5760405162461bcd60e51b815260040161082b906130b5565b60005b83811015610ffb57610ff3858583818110610f9457fe5b90506020020135848484818110610fa757fe5b9050602002810190610fb99190613477565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a1392505050565b600101610f7d565b5050505050565b60098054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107fa5780601f106107cf576101008083540402835291602001916107fa565b60006107c8821180156110775750600c5482105b6110935760405162461bcd60e51b815260040161082b90613400565b61109c82611994565b6110b85760405162461bcd60e51b815260040161082b90612b86565b5060009081526011602052604090205490565b60006001600160a01b0382166110f35760405162461bcd60e51b815260040161082b90612ef8565b6001600160a01b0382166000908152600160205260409020610a2a90611a57565b61111c6119a1565b6001600160a01b031661112d61119d565b6001600160a01b0316146111535760405162461bcd60e51b815260040161082b906131c5565b600b546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600b80546001600160a01b0319169055565b600b546001600160a01b031690565b6002600a5414156111cf5760405162461bcd60e51b815260040161082b906133c9565b6002600a55336111de81611c01565b156111fb5760405162461bcd60e51b815260040161082b90612a89565b601254610100900460ff166112225760405162461bcd60e51b815260040161082b90612fa6565b60058211156112435760405162461bcd60e51b815260040161082b90612d52565b600d546000906112539084611d2a565b9050612fe28111156112775760405162461bcd60e51b815260040161082b90612c4b565b34611289662386f26fc1000085611c07565b11156112a75760405162461bcd60e51b815260040161082b90612d94565b600d545b818110156112c5576112bd8382611cf2565b6001016112ab565b50600d5550506001600a55565b6112da6119a1565b6001600160a01b03166112eb61119d565b6001600160a01b0316146113115760405162461bcd60e51b815260040161082b906131c5565b80516109439060139060208401906124d6565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107fa5780601f106107cf576101008083540402835291602001916107fa565b61138d6119a1565b6001600160a01b0316826001600160a01b031614156113be5760405162461bcd60e51b815260040161082b90612cd4565b80600560006113cb6119a1565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff19169215159290921790915561140f6119a1565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161144791906129f2565b60405180910390a35050565b6002600a5414156114765760405162461bcd60e51b815260040161082b906133c9565b6002600a558281811461149b5760405162461bcd60e51b815260040161082b906130b5565b601254610100900460ff166114c25760405162461bcd60e51b815260040161082b90612fa6565b60005b818110156116c95760008686838181106114db57fe5b90506020020135905060008585848181106114f257fe5b90506020020135905060003390506107c88311156115225760405162461bcd60e51b815260040161082b9061307e565b611534816001600160a01b0316611c01565b156115515760405162461bcd60e51b815260040161082b90612a89565b806001600160a01b031661156484610ef4565b6001600160a01b03161461158a5760405162461bcd60e51b815260040161082b90612c22565b600082116115aa5760405162461bcd60e51b815260040161082b90613437565b6000838152601060205260408120546115c39084611d2a565b905060006115d085611d79565b9050600e60008260048111156115e257fe5b60048111156115ed57fe5b81526020019081526020016000205482111561161b5760405162461bcd60e51b815260040161082b90612a52565b6000858152601060205260408120839055600f8183600481111561163b57fe5b600481111561164657fe5b815260200190815260200160002054905060005b8581101561168957600082815260116020526040902087905561167d8583611cf2565b6001918201910161165a565b5080600f600084600481111561169b57fe5b60048111156116a657fe5b81526020810191909152604001600020555050600190940193506114c592505050565b50506001600a5550505050565b6105dc81565b6116ed6116e76119a1565b83611a62565b6117095760405162461bcd60e51b815260040161082b9061330a565b61171584848484611dc5565b50505050565b606061172682611994565b6117425760405162461bcd60e51b815260040161082b90613243565b60008281526008602090815260409182902080548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452606093928301828280156117d75780601f106117ac576101008083540402835291602001916117d7565b820191906000526020600020905b8154815290600101906020018083116117ba57829003601f168201915b5050505050905060606117e8611002565b90508051600014806117fb575060008251115b1561180857509050610769565b8061181285611df8565b604051602001611823929190612936565b60405160208183030381529060405292505050919050565b60138054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156107fa5780601f106107cf576101008083540402835291602001916107fa565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60125460ff1681565b6118db6119a1565b6001600160a01b03166118ec61119d565b6001600160a01b0316146119125760405162461bcd60e51b815260040161082b906131c5565b6001600160a01b0381166119385760405162461bcd60e51b815260040161082b90612b40565b600b546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000610a2a600283611ed3565b3390565b600081815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906119da82610ef4565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b611a1c82611994565b611a385760405162461bcd60e51b815260040161082b90613179565b600082815260086020908152604090912082516108e3928401906124d6565b6000610a2a82611edf565b6000611a6d82611994565b611a895760405162461bcd60e51b815260040161082b90612e02565b6000611a9483610ef4565b9050806001600160a01b0316846001600160a01b03161480611acf5750836001600160a01b0316611ac484610804565b6001600160a01b0316145b80611adf5750611adf818561189c565b949350505050565b826001600160a01b0316611afa82610ef4565b6001600160a01b031614611b205760405162461bcd60e51b815260040161082b906131fa565b6001600160a01b038216611b465760405162461bcd60e51b815260040161082b90612c90565b611b518383836108e3565b611b5c6000826119a5565b6001600160a01b0383166000908152600160205260409020611b7e9082611ee3565b506001600160a01b0382166000908152600160205260409020611ba19082611eef565b50611bae60028284611efb565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000610a278383611f11565b3b151590565b600082611c1657506000610a2a565b82820282848281611c2357fe5b0414610a275760405162461bcd60e51b815260040161082b906130ec565b600082821115611c635760405162461bcd60e51b815260040161082b90612dcb565b50900390565b60145460009081611c7a8285611f56565b905060148181548110611c8957fe5b9060005260206000200154925060146001830381548110611ca657fe5b906000526020600020015460148281548110611cbe57fe5b6000918252602090912001556014805480611cd557fe5b600190038181906000526020600020016000905590555050919050565b610943828260405180602001604052806000815250611fa3565b6000808080611d1b8686611fd6565b909450925050505b9250929050565b600082820183811015610a275760405162461bcd60e51b815260040161082b90612beb565b80516109439060099060208401906124d6565b6000611d6f848484612032565b90505b9392505050565b600060098211611d8b57506001610769565b60318211611d9b57506002610769565b6101f38211611dac57506003610769565b6107c88211611dbd57506004610769565b506000610769565b611dd0848484611ae7565b611ddc84848484612091565b6117155760405162461bcd60e51b815260040161082b90612aee565b606081611e1d57506040805180820190915260018152600360fc1b6020820152610769565b8160005b8115611e3557600101600a82049150611e21565b60608167ffffffffffffffff81118015611e4e57600080fd5b506040519080825280601f01601f191660200182016040528015611e79576020820181803683370190505b50859350905060001982015b8315611eca57600a840660300160f81b82828060019003935081518110611ea857fe5b60200101906001600160f81b031916908160001a905350600a84049350611e85565b50949350505050565b6000610a278383612170565b5490565b6000610a278383612188565b6000610a27838361224e565b6000611d6f84846001600160a01b038516612298565b81546000908210611f345760405162461bcd60e51b815260040161082b90612a10565b826000018281548110611f4357fe5b9060005260206000200154905092915050565b600080826001430340414433604051602001611f76959493929190612965565b6040516020818303038152906040528051906020012060001c9050838181611f9a57fe5b06949350505050565b611fad838361232f565b611fba6000848484612091565b6108e35760405162461bcd60e51b815260040161082b90612aee565b815460009081908310611ffb5760405162461bcd60e51b815260040161082b90613007565b600084600001848154811061200c57fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816120625760405162461bcd60e51b815260040161082b91906129fd565b5084600001600182038154811061207557fe5b9060005260206000209060020201600101549150509392505050565b60006120a5846001600160a01b0316611c01565b6120b157506001611adf565b6060612139630a85bd0160e11b6120c66119a1565b8887876040516024016120dc94939291906129b5565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806060016040528060328152602001613514603291396001600160a01b03881691906123f3565b90506000818060200190518101906121519190612821565b6001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b6000818152600183016020526040812054801561224457835460001980830191908101906000908790839081106121bb57fe5b90600052602060002001549050808760000184815481106121d857fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061220857fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610a2a565b6000915050610a2a565b600061225a8383612170565b61229057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610a2a565b506000610a2a565b6000828152600184016020526040812054806122fd575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611d72565b8285600001600183038154811061231057fe5b9060005260206000209060020201600101819055506000915050611d72565b6001600160a01b0382166123555760405162461bcd60e51b815260040161082b90613049565b61235e81611994565b1561237b5760405162461bcd60e51b815260040161082b90612bb4565b612387600083836108e3565b6001600160a01b03821660009081526001602052604090206123a99082611eef565b506123b660028284611efb565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6060611d6f84846000858561240785611c01565b6124235760405162461bcd60e51b815260040161082b9061335b565b60006060866001600160a01b03168587604051612440919061291a565b60006040518083038185875af1925050503d806000811461247d576040519150601f19603f3d011682016040523d82523d6000602084013e612482565b606091505b509150915061249282828661249d565b979650505050505050565b606083156124ac575081611d72565b8251156124bc5782518084602001fd5b8160405162461bcd60e51b815260040161082b91906129fd565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061251757805160ff1916838001178555612544565b82800160010185558215612544579182015b82811115612544578251825591602001919060010190612529565b50612550929150612554565b5090565b5b808211156125505760008155600101612555565b80356001600160a01b0381168114610a2a57600080fd5b60008083601f840112612591578182fd5b50813567ffffffffffffffff8111156125a8578182fd5b6020830191508360208083028501011115611d2357600080fd5b600082601f8301126125d2578081fd5b813567ffffffffffffffff808211156125e9578283fd5b604051601f8301601f191681016020018281118282101715612609578485fd5b60405282815292508284830160200186101561262457600080fd5b8260208601602083013760006020848301015250505092915050565b600060208284031215612651578081fd5b610a278383612569565b6000806040838503121561266d578081fd5b6126778484612569565b91506126868460208501612569565b90509250929050565b6000806000606084860312156126a3578081fd5b83356126ae816134e8565b925060208401356126be816134e8565b929592945050506040919091013590565b600080600080608085870312156126e4578081fd5b6126ee8686612569565b93506126fd8660208701612569565b925060408501359150606085013567ffffffffffffffff81111561271f578182fd5b61272b878288016125c2565b91505092959194509250565b60008060408385031215612749578182fd5b6127538484612569565b915060208301358015158114612767578182fd5b809150509250929050565b60008060408385031215612784578182fd5b61278e8484612569565b946020939093013593505050565b600080600080604085870312156127b1578384fd5b843567ffffffffffffffff808211156127c8578586fd5b6127d488838901612580565b909650945060208701359150808211156127ec578384fd5b506127f987828801612580565b95989497509550505050565b600060208284031215612816578081fd5b8135610a27816134fd565b600060208284031215612832578081fd5b8151610a27816134fd565b60006020828403121561284e578081fd5b813567ffffffffffffffff811115612864578182fd5b611adf848285016125c2565b600060208284031215612881578081fd5b5035919050565b6000806040838503121561289a578182fd5b82359150602083013567ffffffffffffffff8111156128b7578182fd5b6128c3858286016125c2565b9150509250929050565b600080604083850312156128df578182fd5b50508035926020909101359150565b600081518084526129068160208601602086016134bc565b601f01601f19169290920160200192915050565b6000825161292c8184602087016134bc565b9190910192915050565b600083516129488184602088016134bc565b83519083019061295c8183602088016134bc565b01949350505050565b94855260208501939093526bffffffffffffffffffffffff19606092831b81166040860152605485019190915291901b16607482015260880190565b6001600160a01b0391909116815260200190565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906129e8908301846128ee565b9695505050505050565b901515815260200190565b600060208252610a2760208301846128ee565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b60208082526019908201527f4578636565642064657269766564206c696d69746174696f6e00000000000000604082015260600190565b60208082526016908201527544657269766174696f6e206f6e6c7920746f20454f4160501b604082015260600190565b6020808252818101527f53657420696473206d75737420636f6d65206265666f7265206d696e74616765604082015260600190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526014908201527312185cc81b9bdd081899595b8819195c9a5d995960621b604082015260600190565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600f908201526e057726f6e67206f776e65727368697608c1b604082015260600190565b60208082526025908201527f44657269766520776f756c6420657863656564206d617820737570706c79206f604082015264331030b7bd60d91b606082015260800190565b60208082526024908201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526019908201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604082015260600190565b60208082526027908201527f507572636861736520776f756c6420657863656564206d617820737570706c796040820152661037b31030b7bd60c91b606082015260800190565b60208082526022908201527f43616e206f6e6c7920646572697665203520746f6b656e7320617420612074696040820152616d6560f01b606082015260800190565b6020808252601f908201527f45746865722076616c75652073656e74206973206e6f7420636f727265637400604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252602c908201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252602d908201527f57616c6c65742062616c616e6365206d7573742062652067726561746572207460408201526c3430b71018171a9032ba3432b960991b606082015260800190565b60208082526038908201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760408201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606082015260800190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604082015269726f206164647265737360b01b606082015260800190565b602080825260159082015274139bdd081c5d585b1a599a5959081d1bc81b5a5b9d605a1b604082015260600190565b6020808252818101527f43616e206f6e6c79206d696e74203220746f6b656e7320617420612074696d65604082015260600190565b60208082526018908201527f4e6f742061637469766520746f2064657269766520414f5a0000000000000000604082015260600190565b60208082526010908201526f53616c65206f6e6c7920746f20454f4160801b604082015260600190565b60208082526022908201527f456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b60208082526017908201527f4e6f74207175616c696669656420746f20646572697665000000000000000000604082015260600190565b60208082526018908201527f556e6d617463686564206c656e73206f66206172726179730000000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252602c908201527f4552433732314d657461646174613a2055524920736574206f66206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960408201526839903737ba1037bbb760b91b606082015260800190565b6020808252602f908201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60408201526e3732bc34b9ba32b73a103a37b5b2b760891b606082015260800190565b6020808252601f908201527f53616c65206d7573742062652061637469766520746f206d696e7420414f5a00604082015260600190565b60208082526021908201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656040820152603960f91b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526019908201527f496473206e756d206578636565647320746865206c696d697400000000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601e908201527f4e6f20696e666f726d6174696f6e2061626f7574207375706572204e46540000604082015260600190565b60208082526019908201527f44657269766520616d6f756e74206e6f7420636f727265637400000000000000604082015260600190565b90815260200190565b6000808335601e1984360301811261348d578283fd5b83018035915067ffffffffffffffff8211156134a7578283fd5b602001915036819003821315611d2357600080fd5b60005b838110156134d75781810151838201526020016134bf565b838111156117155750506000910152565b6001600160a01b0381168114610ef157600080fd5b6001600160e01b031981168114610ef157600080fdfe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656ea2646970667358221220ebf374ffad17971d9ffebdc5a6c05ec516d5caab34b9193b9fea9bc224e9219364736f6c63430007000033

Deployed Bytecode Sourcemap

71060:11331:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10329:150;;;;;;;;;;-1:-1:-1;10329:150:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;54800:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;57429:221::-;;;;;;;;;;-1:-1:-1;57429:221:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;56945:418::-;;;;;;;;;;-1:-1:-1;56945:418:0;;;;;:::i;:::-;;:::i;:::-;;72552:48;;;;;;;;;;-1:-1:-1;72552:48:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;80041:129::-;;;;;;;;;;-1:-1:-1;80041:129:0;;;;;:::i;:::-;;:::i;56423:211::-;;;;;;;;;;;;;:::i;72766:34::-;;;;;;;;;;;;;:::i;71342:40::-;;;;;;;;;;;;;:::i;58319:339::-;;;;;;;;;;-1:-1:-1;58319:339:0;;;;;:::i;:::-;;:::i;75867:111::-;;;;;;;;;;;;;:::i;74402:95::-;;;;;;;;;;;;;:::i;56185:162::-;;;;;;;;;;-1:-1:-1;56185:162:0;;;;;:::i;:::-;;:::i;74251:89::-;;;;;;;;;;;;;:::i;71183:45::-;;;;;;;;;;;;;:::i;74522:786::-;;;;;;:::i;:::-;;:::i;73657:134::-;;;;;;;;;;;;;:::i;58729:185::-;;;;;;;;;;-1:-1:-1;58729:185:0;;;;;:::i;:::-;;:::i;56711:172::-;;;;;;;;;;-1:-1:-1;56711:172:0;;;;;:::i;:::-;;:::i;72895:31::-;;;;;;;;;;-1:-1:-1;72895:31:0;;;;;:::i;:::-;;:::i;76529:501::-;;;;;;;;;;-1:-1:-1;76529:501:0;;;;;:::i;:::-;;:::i;71235:49::-;;;;;;;;;;;;;:::i;75347:463::-;;;;;;;;;;-1:-1:-1;75347:463:0;;;;;:::i;:::-;;:::i;71293:42::-;;;;;;;;;;;;;:::i;74092:99::-;;;;;;;;;;-1:-1:-1;74092:99:0;;;;;:::i;:::-;;:::i;54556:177::-;;;;;;;;;;-1:-1:-1;54556:177:0;;;;;:::i;:::-;;:::i;80231:314::-;;;;;;;;;;-1:-1:-1;80231:314:0;;;;;:::i;:::-;;:::i;56004:97::-;;;;;;;;;;;;;:::i;76053:407::-;;;;;;;;;;-1:-1:-1;76053:407:0;;;;;:::i;:::-;;:::i;54273:221::-;;;;;;;;;;-1:-1:-1;54273:221:0;;;;;:::i;:::-;;:::i;69622:148::-;;;;;;;;;;;;;:::i;68971:87::-;;;;;;;;;;;;;:::i;79098:888::-;;;;;;:::i;:::-;;:::i;73830:117::-;;;;;;;;;;-1:-1:-1;73830:117:0;;;;;:::i;:::-;;:::i;54969:104::-;;;;;;;;;;;;;:::i;57722:295::-;;;;;;;;;;-1:-1:-1;57722:295:0;;;;;:::i;:::-;;:::i;77299:1742::-;;;;;;;;;;-1:-1:-1;77299:1742:0;;;;;:::i;:::-;;:::i;71391:44::-;;;;;;;;;;;;;:::i;58985:328::-;;;;;;;;;;-1:-1:-1;58985:328:0;;;;;:::i;:::-;;:::i;55144:617::-;;;;;;;;;;-1:-1:-1;55144:617:0;;;;;:::i;:::-;;:::i;73987:97::-;;;;;;;;;;;;;:::i;58088:164::-;;;;;;;;;;-1:-1:-1;58088:164:0;;;;;:::i;:::-;;:::i;72727:32::-;;;;;;;;;;;;;:::i;69925:244::-;;;;;;;;;;-1:-1:-1;69925:244:0;;;;;:::i;:::-;;:::i;10329:150::-;-1:-1:-1;;;;;;10438:33:0;;10414:4;10438:33;;;;;;;;;;;;;10329:150;;;;:::o;54800:100::-;54887:5;54880:12;;;;;;;;-1:-1:-1;;54880:12:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54854:13;;54880:12;;54887:5;;54880:12;;54887:5;54880:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54800:100;:::o;57429:221::-;57505:7;57533:16;57541:7;57533;:16::i;:::-;57525:73;;;;-1:-1:-1;;;57525:73:0;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;57618:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;57618:24:0;;57429:221::o;56945:418::-;57026:13;57042:23;57057:7;57042:14;:23::i;:::-;57026:39;;57090:5;-1:-1:-1;;;;;57084:11:0;:2;-1:-1:-1;;;;;57084:11:0;;;57076:57;;;;-1:-1:-1;;;57076:57:0;;;;;;;:::i;:::-;57184:5;-1:-1:-1;;;;;57168:21:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;57168:21:0;;:69;;;;57193:44;57217:5;57224:12;:10;:12::i;57193:44::-;57146:175;;;;-1:-1:-1;;;57146:175:0;;;;;;;:::i;:::-;57334:21;57343:2;57347:7;57334:8;:21::i;:::-;56945:418;;;:::o;72552:48::-;;;;;;;;;;;;;:::o;80041:129::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;80131:31:::1;80144:7;80153:8;80131:12;:31::i;:::-;80041:129:::0;;:::o;56423:211::-;56484:7;56605:21;:12;:19;:21::i;:::-;56598:28;;56423:211;:::o;72766:34::-;;;;;;;;;:::o;71342:40::-;71381:1;71342:40;:::o;58319:339::-;58514:41;58533:12;:10;:12::i;:::-;58547:7;58514:18;:41::i;:::-;58506:103;;;;-1:-1:-1;;;58506:103:0;;;;;;;:::i;:::-;58622:28;58632:4;58638:2;58642:7;58622:9;:28::i;75867:111::-;75949:14;:21;75867:111;:::o;74402:95::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;74475:14:::1;::::0;;-1:-1:-1;;74457:32:0;::::1;74475:14;::::0;;;::::1;;;74474:15;74457:32:::0;;::::1;;::::0;;74402:95::o;56185:162::-;-1:-1:-1;;;;;56309:20:0;;56282:7;56309:20;;;:13;:20;;;;;:30;;56333:5;56309:23;:30::i;:::-;56302:37;;56185:162;;;;;:::o;74251:89::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;74320:12:::1;::::0;;-1:-1:-1;;74304:28:0;::::1;74320:12;::::0;;::::1;74319:13;74304:28;::::0;;74251:89::o;71183:45::-;71218:10;71183:45;:::o;74522:786::-;49598:1;50194:7;;:19;;50186:63;;;;-1:-1:-1;;;50186:63:0;;;;;;;:::i;:::-;49598:1;50327:7;:18;74647:12:::1;::::0;74618:10:::1;::::0;74647:12:::1;;74639:56;;;;-1:-1:-1::0;;;74639:56:0::1;;;;;;;:::i;:::-;74715:18;:5;-1:-1:-1::0;;;;;74715:16:0::1;;:18::i;:::-;74714:19;74706:48;;;;-1:-1:-1::0;;;74706:48:0::1;;;;;;;:::i;:::-;74790:9;74773:5;-1:-1:-1::0;;;;;74773:13:0::1;;:26;;74765:84;;;;-1:-1:-1::0;;;74765:84:0::1;;;;;;;:::i;:::-;71334:1;74868:14;:32;;74860:77;;;;-1:-1:-1::0;;;74860:77:0::1;;;;;;;:::i;:::-;74974:14;:21:::0;74956:39;::::1;;74948:91;;;;-1:-1:-1::0;;;74948:91:0::1;;;;;;;:::i;:::-;75090:9;75058:28;71218:10;75071:14:::0;75058:12:::1;:28::i;:::-;:41;;75050:85;;;;-1:-1:-1::0;;;75050:85:0::1;;;;;;;:::i;:::-;75153:9;75148:153;75172:14;75168:1;:18;75148:153;;;75265:14;:21:::0;75208:81:::1;::::0;75218:5;;75225:63:::1;::::0;75247:40:::1;::::0;71431:4:::1;::::0;75247:17:::1;:40::i;:::-;75225:21;:63::i;:::-;75208:9;:81::i;:::-;75188:3;;75148:153;;;-1:-1:-1::0;;49554:1:0;50506:7;:22;-1:-1:-1;74522:786:0:o;73657:134::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;73755:28:::1;::::0;73723:21:::1;::::0;73755:10:::1;::::0;:28;::::1;;;::::0;73723:21;;73705:15:::1;73755:28:::0;73705:15;73755:28;73723:21;73755:10;:28;::::1;;;;;;;;;;;;;::::0;::::1;;;;58729:185:::0;58867:39;58884:4;58890:2;58894:7;58867:39;;;;;;;;;;;;:16;:39::i;56711:172::-;56786:7;;56828:22;:12;56844:5;56828:15;:22::i;:::-;-1:-1:-1;56806:44:0;56711:172;-1:-1:-1;;;56711:172:0:o;72895:31::-;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72895:31:0;:::o;76529:501::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;76733:8;76767:31;;::::1;76759:68;;;;-1:-1:-1::0;;;76759:68:0::1;;;;;;;:::i;:::-;76845:9;76840:183;76864:11;76860:1;:15;76840:183;;;71642:4;76905:8;;76914:1;76905:11;;;;;;;;;;;;;:29;;76897:63;;;;-1:-1:-1::0;;;76897:63:0::1;;;;;;;:::i;:::-;76975:36;76985:9;;76995:1;76985:12;;;;;;;;;;;;;;;;;;;;:::i;:::-;76999:8;;77008:1;76999:11;;;;;;;;;;;;;76975:9;:36::i;:::-;76877:3;;76840:183;;;;69262:1;76529:501:::0;;;;:::o;71235:49::-;71274:10;71235:49;:::o;75347:463::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;75435:11:::1;75449:25;75472:1;75449:18;:5:::0;75459:7;75449:9:::1;:18::i;:::-;:22:::0;::::1;:25::i;:::-;75519:12;::::0;75435:39;;-1:-1:-1;75519:12:0::1;;75518:13;:35:::0;::::1;;;;75535:13;:11;:13::i;:::-;:18:::0;75518:35:::1;75510:80;;;;-1:-1:-1::0;;;75510:80:0::1;;;;;;;:::i;:::-;75609:14;:21:::0;71431:4:::1;::::0;75609:30:::1;::::0;75635:3;75609:25:::1;:30::i;:::-;:47;;75601:85;;;;-1:-1:-1::0;;;75601:85:0::1;;;;;;;:::i;:::-;75699:104;75717:5;75706:7;:16;75699:104;;75739:14;:28:::0;;::::1;::::0;;::::1;::::0;;-1:-1:-1;75739:28:0;;;;;::::1;::::0;;;75782:9;;::::1;::::0;75699:104:::1;;71293:42:::0;71334:1;71293:42;:::o;74092:99::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;74163:20:::1;74175:7;74163:11;:20::i;:::-;74092:99:::0;:::o;54556:177::-;54628:7;54655:70;54672:7;54655:70;;;;;;;;;;;;;;;;;:12;;:70;:16;:70::i;80231:314::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;80351:35;;::::1;80343:72;;;;-1:-1:-1::0;;;80343:72:0::1;;;;;;;:::i;:::-;80431:9;80426:112;80446:19:::0;;::::1;80426:112;;;80487:39;80500:8;;80509:1;80500:11;;;;;;;;;;;;;80513:9;;80523:1;80513:12;;;;;;;;;;;;;;;;;;:::i;:::-;80487:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;80487:12:0::1;::::0;-1:-1:-1;;;80487:39:0:i:1;:::-;80467:3;;80426:112;;;;80231:314:::0;;;;:::o;56004:97::-;56085:8;56078:15;;;;;;;;-1:-1:-1;;56078:15:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56052:13;;56078:15;;56085:8;;56078:15;;56085:8;56078:15;;;;;;;;;;;;;;;;;;;;;;;;76053:407;76140:7;71642:4;76181:17;:34;:88;;;;;76239:30;;76219:17;:50;76181:88;76159:168;;;;-1:-1:-1;;;76159:168:0;;;;;;;:::i;:::-;76346:26;76354:17;76346:7;:26::i;:::-;76338:59;;;;-1:-1:-1;;;76338:59:0;;;;;;;:::i;:::-;-1:-1:-1;76415:37:0;;;;:18;:37;;;;;;;76053:407::o;54273:221::-;54345:7;-1:-1:-1;;;;;54373:19:0;;54365:74;;;;-1:-1:-1;;;54365:74:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;54457:20:0;;;;;;:13;:20;;;;;:29;;:27;:29::i;69622:148::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;69713:6:::1;::::0;69692:40:::1;::::0;69729:1:::1;::::0;-1:-1:-1;;;;;69713:6:0::1;::::0;69692:40:::1;::::0;69729:1;;69692:40:::1;69743:6;:19:::0;;-1:-1:-1;;;;;;69743:19:0::1;::::0;;69622:148::o;68971:87::-;69044:6;;-1:-1:-1;;;;;69044:6:0;68971:87;:::o;79098:888::-;49598:1;50194:7;;:19;;50186:63;;;;-1:-1:-1;;;50186:63:0;;;;;;;:::i;:::-;49598:1;50327:7;:18;79200:10:::1;79230:20;79200:10:::0;79230:18:::1;:20::i;:::-;79229:21;79221:56;;;;-1:-1:-1::0;;;79221:56:0::1;;;;;;;:::i;:::-;79296:14;::::0;::::1;::::0;::::1;;;79288:51;;;;-1:-1:-1::0;;;79288:51:0::1;;;;;;;:::i;:::-;71381:1;79358:14;:30;;79350:77;;;;-1:-1:-1::0;;;79350:77:0::1;;;;;;;:::i;:::-;79475:24;::::0;79438:34:::1;::::0;79475:44:::1;::::0;79504:14;79475:28:::1;:44::i;:::-;79438:81;;72128:5;79552:26;:57;;79530:144;;;;-1:-1:-1::0;;;79530:144:0::1;;;;;;;:::i;:::-;79729:9;79693:32;71274:10;79710:14:::0;79693:16:::1;:32::i;:::-;:45;;79685:89;;;;-1:-1:-1::0;;;79685:89:0::1;;;;;;;:::i;:::-;79804:24;::::0;79787:128:::1;79834:26;79830:1;:30;79787:128;;;79882:21;79892:7;79901:1;79882:9;:21::i;:::-;79862:3;;79787:128;;;-1:-1:-1::0;79925:24:0::1;:53:::0;-1:-1:-1;;49554:1:0;50506:7;:22;79098:888::o;73830:117::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;73912:27;;::::1;::::0;:12:::1;::::0;:27:::1;::::0;::::1;::::0;::::1;:::i;54969:104::-:0;55058:7;55051:14;;;;;;;;-1:-1:-1;;55051:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55025:13;;55051:14;;55058:7;;55051:14;;55058:7;55051:14;;;;;;;;;;;;;;;;;;;;;;;;57722:295;57837:12;:10;:12::i;:::-;-1:-1:-1;;;;;57825:24:0;:8;-1:-1:-1;;;;;57825:24:0;;;57817:62;;;;-1:-1:-1;;;57817:62:0;;;;;;;:::i;:::-;57937:8;57892:18;:32;57911:12;:10;:12::i;:::-;-1:-1:-1;;;;;57892:32:0;;;;;;;;;;;;;;;;;-1:-1:-1;57892:32:0;;;:42;;;;;;;;;;;;:53;;-1:-1:-1;;57892:53:0;;;;;;;;;;;57976:12;:10;:12::i;:::-;-1:-1:-1;;;;;57961:48:0;;58000:8;57961:48;;;;;;:::i;:::-;;;;;;;;57722:295;;:::o;77299:1742::-;49598:1;50194:7;;:19;;50186:63;;;;-1:-1:-1;;;50186:63:0;;;;;;;:::i;:::-;49598:1;50327:7;:18;77527;77571:37;;::::1;77563:74;;;;-1:-1:-1::0;;;77563:74:0::1;;;;;;;:::i;:::-;77656:14;::::0;::::1;::::0;::::1;;;77648:51;;;;-1:-1:-1::0;;;77648:51:0::1;;;;;;;:::i;:::-;77717:9;77712:1322;77736:11;77732:1;:15;77712:1322;;;77769:25;77797:18;;77816:1;77797:21;;;;;;;;;;;;;77769:49;;77833:21;77857:15;;77873:1;77857:18;;;;;;;;;;;;;77833:42;;77892:15;77910:10;77892:28;;71642:4;77943:17;:35;;77935:71;;;;-1:-1:-1::0;;;77935:71:0::1;;;;;;;:::i;:::-;78030:20;:7;-1:-1:-1::0;;;;;78030:18:0::1;;:20::i;:::-;78029:21;78021:56;;;;-1:-1:-1::0;;;78021:56:0::1;;;;;;;:::i;:::-;78130:7;-1:-1:-1::0;;;;;78100:37:0::1;:26;78108:17;78100:7;:26::i;:::-;-1:-1:-1::0;;;;;78100:37:0::1;;78092:65;;;;-1:-1:-1::0;;;78092:65:0::1;;;;;;;:::i;:::-;78196:1;78180:13;:17;78172:55;;;;-1:-1:-1::0;;;78172:55:0::1;;;;;;;:::i;:::-;78242:24;78269:32:::0;;;:13:::1;:32;::::0;;;;;:51:::1;::::0;78306:13;78269:36:::1;:51::i;:::-;78242:78;;78335:11;78349:39;78370:17;78349:20;:39::i;:::-;78335:53;;78449:17;:24;78467:5;78449:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;78429:16;:44;;78403:131;;;;-1:-1:-1::0;;;78403:131:0::1;;;;;;;:::i;:::-;78574:32;::::0;;;:13:::1;:32;::::0;;;;:51;;;78660:20:::1;78574:32:::0;78681:5;78660:27:::1;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;78640:47;;78707:9;78702:267;78726:13;78722:1;:17;78702:267;;;78826:29;::::0;;;:18:::1;:29;::::0;;;;:49;;;78894:29:::1;78904:7:::0;78845:9;78894::::1;:29::i;:::-;78942:11;::::0;;::::1;::::0;78741:3:::1;78702:267;;;;79013:9;78983:20;:27;79004:5;78983:27;;;;;;;;;;;;;;;;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;78983:27:0;:39;-1:-1:-1;;77749:3:0::1;::::0;;::::1;::::0;-1:-1:-1;77712:1322:0::1;::::0;-1:-1:-1;;;77712:1322:0::1;;-1:-1:-1::0;;49554:1:0;50506:7;:22;-1:-1:-1;;;;77299:1742:0:o;71391:44::-;71431:4;71391:44;:::o;58985:328::-;59160:41;59179:12;:10;:12::i;:::-;59193:7;59160:18;:41::i;:::-;59152:103;;;;-1:-1:-1;;;59152:103:0;;;;;;;:::i;:::-;59266:39;59280:4;59286:2;59290:7;59299:5;59266:13;:39::i;:::-;58985:328;;;;:::o;55144:617::-;55217:13;55251:16;55259:7;55251;:16::i;:::-;55243:76;;;;-1:-1:-1;;;55243:76:0;;;;;;;:::i;:::-;55358:19;;;;:10;:19;;;;;;;;;55332:45;;;;;;-1:-1:-1;;55332:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:23;;:45;;;55358:19;55332:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55388:18;55409:9;:7;:9::i;:::-;55388:30;;55500:4;55494:18;55516:1;55494:23;:54;;;;55547:1;55527:9;55521:23;:27;55494:54;55490:103;;;-1:-1:-1;55572:9:0;-1:-1:-1;55565:16:0;;55490:103;55727:4;55733:18;:7;:16;:18::i;:::-;55710:42;;;;;;;;;:::i;:::-;;;;;;;;;;;;;55696:57;;;;55144:617;;;:::o;73987:97::-;74064:12;74057:19;;;;;;;;-1:-1:-1;;74057:19:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74031:13;;74057:19;;74064:12;;74057:19;;74064:12;74057:19;;;;;;;;;;;;;;;;;;;;;;;;58088:164;-1:-1:-1;;;;;58209:25:0;;;58185:4;58209:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;58088:164::o;72727:32::-;;;;;;:::o;69925:244::-;69202:12;:10;:12::i;:::-;-1:-1:-1;;;;;69191:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;69191:23:0;;69183:68;;;;-1:-1:-1;;;69183:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;70014:22:0;::::1;70006:73;;;;-1:-1:-1::0;;;70006:73:0::1;;;;;;;:::i;:::-;70116:6;::::0;70095:38:::1;::::0;-1:-1:-1;;;;;70095:38:0;;::::1;::::0;70116:6:::1;::::0;70095:38:::1;::::0;70116:6:::1;::::0;70095:38:::1;70144:6;:17:::0;;-1:-1:-1;;;;;;70144:17:0::1;-1:-1:-1::0;;;;;70144:17:0;;;::::1;::::0;;;::::1;::::0;;69925:244::o;60823:127::-;60888:4;60912:30;:12;60934:7;60912:21;:30::i;665:106::-;753:10;665:106;:::o;66936:192::-;67011:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;67011:29:0;-1:-1:-1;;;;;67011:29:0;;;;;;;;:24;;67065:23;67011:24;67065:14;:23::i;:::-;-1:-1:-1;;;;;67056:46:0;;;;;;;;;;;66936:192;;:::o;65113:215::-;65213:16;65221:7;65213;:16::i;:::-;65205:73;;;;-1:-1:-1;;;65205:73:0;;;;;;;:::i;:::-;65289:19;;;;:10;:19;;;;;;;;:31;;;;;;;;:::i;44879:123::-;44948:7;44975:19;44983:3;44975:7;:19::i;61117:355::-;61210:4;61235:16;61243:7;61235;:16::i;:::-;61227:73;;;;-1:-1:-1;;;61227:73:0;;;;;;;:::i;:::-;61311:13;61327:23;61342:7;61327:14;:23::i;:::-;61311:39;;61380:5;-1:-1:-1;;;;;61369:16:0;:7;-1:-1:-1;;;;;61369:16:0;;:51;;;;61413:7;-1:-1:-1;;;;;61389:31:0;:20;61401:7;61389:11;:20::i;:::-;-1:-1:-1;;;;;61389:31:0;;61369:51;:94;;;;61424:39;61448:5;61455:7;61424:23;:39::i;:::-;61361:103;61117:355;-1:-1:-1;;;;61117:355:0:o;64324:633::-;64483:4;-1:-1:-1;;;;;64456:31:0;:23;64471:7;64456:14;:23::i;:::-;-1:-1:-1;;;;;64456:31:0;;64448:85;;;;-1:-1:-1;;;64448:85:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;64570:16:0;;64562:65;;;;-1:-1:-1;;;64562:65:0;;;;;;;:::i;:::-;64640:39;64661:4;64667:2;64671:7;64640:20;:39::i;:::-;64744:29;64761:1;64765:7;64744:8;:29::i;:::-;-1:-1:-1;;;;;64786:19:0;;;;;;:13;:19;;;;;:35;;64813:7;64786:26;:35::i;:::-;-1:-1:-1;;;;;;64832:17:0;;;;;;:13;:17;;;;;:30;;64854:7;64832:21;:30::i;:::-;-1:-1:-1;64875:29:0;:12;64892:7;64901:2;64875:16;:29::i;:::-;;64941:7;64937:2;-1:-1:-1;;;;;64922:27:0;64931:4;-1:-1:-1;;;;;64922:27:0;;;;;;;;;;;64324:633;;;:::o;36539:137::-;36610:7;36645:22;36649:3;36661:5;36645:3;:22::i;19426:444::-;19806:20;19854:8;;;19426:444::o;14766:220::-;14824:7;14848:6;14844:20;;-1:-1:-1;14863:1:0;14856:8;;14844:20;14887:5;;;14891:1;14887;:5;:1;14911:5;;;;;:10;14903:56;;;;-1:-1:-1;;;14903:56:0;;;;;;;:::i;14349:158::-;14407:7;14440:1;14435;:6;;14427:49;;;;-1:-1:-1;;;14427:49:0;;;;;;;:::i;:::-;-1:-1:-1;14494:5:0;;;14349:158::o;81225:570::-;81372:14;:21;81311:15;;;81510:55;81372:21;81546:18;81510:16;:55::i;:::-;81488:77;;81588:14;81603:11;81588:27;;;;;;;;;;;;;;;;81578:37;;81719:14;81754:1;81734:17;:21;81719:37;;;;;;;;;;;;;;;;81689:14;81704:11;81689:27;;;;;;;;;;;;;;;;;:67;81767:14;:20;;;;;;;;;;;;;;;;;;;;;;;;81225:570;;;;;:::o;61815:110::-;61891:26;61901:2;61905:7;61891:26;;;;;;;;;;;;:9;:26::i;45350:236::-;45430:7;;;;45490:22;45494:3;45506:5;45490:3;:22::i;:::-;45459:53;;-1:-1:-1;45459:53:0;-1:-1:-1;;;45350:236:0;;;;;;:::o;13887:179::-;13945:7;13977:5;;;14001:6;;;;13993:46;;;;-1:-1:-1;;;13993:46:0;;;;;;;:::i;65558:100::-;65631:19;;;;:8;;:19;;;;;:::i;46636:247::-;46777:7;46828:44;46833:3;46853;46859:12;46828:4;:44::i;:::-;46820:53;-1:-1:-1;46636:247:0;;;;;;:::o;80553:455::-;80622:5;71488:1;80643:7;:27;80639:362;;-1:-1:-1;80694:9:0;80687:16;;80639:362;71539:2;80725:7;:26;80721:280;;-1:-1:-1;80775:8:0;80768:15;;80721:280;71590:3;80805:7;:25;80801:200;;-1:-1:-1;80854:7:0;80847:14;;80801:200;71642:4;80883:7;:25;80879:122;;-1:-1:-1;80932:7:0;80925:14;;80879:122;-1:-1:-1;80979:10:0;80972:17;;60195:315;60352:28;60362:4;60368:2;60372:7;60352:9;:28::i;:::-;60399:48;60422:4;60428:2;60432:7;60441:5;60399:22;:48::i;:::-;60391:111;;;;-1:-1:-1;;;60391:111:0;;;;;;;:::i;47130:748::-;47186:13;47407:10;47403:53;;-1:-1:-1;47434:10:0;;;;;;;;;;;;-1:-1:-1;;;47434:10:0;;;;;;47403:53;47481:5;47466:12;47522:78;47529:9;;47522:78;;47555:8;;47586:2;47578:10;;;;47522:78;;;47610:19;47642:6;47632:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;47632:17:0;-1:-1:-1;47704:5:0;;-1:-1:-1;47610:39:0;-1:-1:-1;;;47676:10:0;;47720:119;47727:9;;47720:119;;47797:2;47790:4;:9;47784:2;:16;47771:31;;47753:6;47760:7;;;;;;;47753:15;;;;;;;;;;;:49;-1:-1:-1;;;;;47753:49:0;;;;;;;;-1:-1:-1;47825:2:0;47817:10;;;;47720:119;;;-1:-1:-1;47863:6:0;47130:748;-1:-1:-1;;;;47130:748:0:o;44640:151::-;44724:4;44748:35;44758:3;44778;44748:9;:35::i;41380:110::-;41463:19;;41380:110::o;35616:137::-;35686:4;35710:35;35718:3;35738:5;35710:7;:35::i;35309:131::-;35376:4;35400:32;35405:3;35425:5;35400:4;:32::i;44029:219::-;44152:4;44176:64;44181:3;44201;-1:-1:-1;;;;;44215:23:0;;44176:4;:64::i;31549:204::-;31644:18;;31616:7;;31644:26;-1:-1:-1;31636:73:0;;;;-1:-1:-1;;;31636:73:0;;;;;;;:::i;:::-;31727:3;:11;;31739:5;31727:18;;;;;;;;;;;;;;;;31720:25;;31549:204;;;;:::o;81845:543::-;81952:7;81977:14;82095:18;82165:1;82150:12;:16;82140:27;82194:14;82235:16;82278:10;82052:259;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;82020:310;;;;;;81994:351;;81977:368;;82374:6;82365;:15;;;;;;;81845:543;-1:-1:-1;;;;81845:543:0:o;62152:321::-;62282:18;62288:2;62292:7;62282:5;:18::i;:::-;62333:54;62364:1;62368:2;62372:7;62381:5;62333:22;:54::i;:::-;62311:154;;;;-1:-1:-1;;;62311:154:0;;;;;;;:::i;41855:279::-;41959:19;;41922:7;;;;41959:27;-1:-1:-1;41951:74:0;;;;-1:-1:-1;;;41951:74:0;;;;;;;:::i;:::-;42038:22;42063:3;:12;;42076:5;42063:19;;;;;;;;;;;;;;;;;;42038:44;;42101:5;:10;;;42113:5;:12;;;42093:33;;;;;41855:279;;;;;:::o;43352:353::-;43480:7;43519:17;;;:12;;;:17;;;;;;43570:12;43555:13;43547:36;;;;-1:-1:-1;;;43547:36:0;;;;;;;;:::i;:::-;;43637:3;:12;;43661:1;43650:8;:12;43637:26;;;;;;;;;;;;;;;;;;:33;;;43630:40;;;43352:353;;;;;:::o;66223:594::-;66378:4;66400:15;:2;-1:-1:-1;;;;;66400:13:0;;:15::i;:::-;66395:60;;-1:-1:-1;66439:4:0;66432:11;;66395:60;66465:23;66491:213;-1:-1:-1;;;66591:12:0;:10;:12::i;:::-;66605:4;66611:7;66620:5;66521:105;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;66521:105:0;;;;;;;-1:-1:-1;;;;;66521:105:0;;;;;;;;;;;66491:213;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66491:15:0;;;:213;:15;:213::i;:::-;66465:239;;66715:13;66742:10;66731:32;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;66782:26:0;-1:-1:-1;;;66782:26:0;;-1:-1:-1;;;66223:594:0;;;;;;:::o;41160:125::-;41231:4;41255:17;;;:12;;;;;:17;;;;;;:22;;;41160:125::o;29228:1557::-;29294:4;29433:19;;;:12;;;:19;;;;;;29469:15;;29465:1313;;29917:18;;-1:-1:-1;;29868:14:0;;;;29917:22;;;;29844:21;;29917:3;;:22;;30204;;;;;;;;;;;;;;30184:42;;30350:9;30321:3;:11;;30333:13;30321:26;;;;;;;;;;;;;;;;;;;:38;;;;30427:23;;;30469:1;30427:12;;;:23;;;;;;30453:17;;;30427:43;;30579:17;;30427:3;;30579:17;;;;;;;;;;;;;;;;;;;;;;30674:3;:12;;:19;30687:5;30674:19;;;;;;;;;;;30667:26;;;30717:4;30710:11;;;;;;;;29465:1313;30761:5;30754:12;;;;;28638:414;28701:4;28723:21;28733:3;28738:5;28723:9;:21::i;:::-;28718:327;;-1:-1:-1;28761:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;28944:18;;28922:19;;;:12;;;:19;;;;;;:40;;;;28977:11;;28718:327;-1:-1:-1;29028:5:0;29021:12;;38600:739;38710:4;38845:17;;;:12;;;:17;;;;;;38879:13;38875:457;;-1:-1:-1;;38977:38:0;;;;;;;;;;;;;;;;;;38959:57;;;;;;;;:12;:57;;;;;;;;;;;;;;;;;;;;;;;;39174:19;;39154:17;;;:12;;;:17;;;;;;;:39;39208:11;;38875:457;39288:5;39252:3;:12;;39276:1;39265:8;:12;39252:26;;;;;;;;;;;;;;;;;;:33;;:41;;;;39315:5;39308:12;;;;;62809:404;-1:-1:-1;;;;;62889:16:0;;62881:61;;;;-1:-1:-1;;;62881:61:0;;;;;;;:::i;:::-;62962:16;62970:7;62962;:16::i;:::-;62961:17;62953:58;;;;-1:-1:-1;;;62953:58:0;;;;;;;:::i;:::-;63024:45;63053:1;63057:2;63061:7;63024:20;:45::i;:::-;-1:-1:-1;;;;;63082:17:0;;;;;;:13;:17;;;;;:30;;63104:7;63082:21;:30::i;:::-;-1:-1:-1;63125:29:0;:12;63142:7;63151:2;63125:16;:29::i;:::-;-1:-1:-1;63172:33:0;;63197:7;;-1:-1:-1;;;;;63172:33:0;;;63189:1;;63172:33;;63189:1;;63172:33;62809:404;;:::o;22368:229::-;22505:12;22537:52;22559:6;22567:4;22573:1;22576:12;22505;23783:18;23794:6;23783:10;:18::i;:::-;23775:60;;;;-1:-1:-1;;;23775:60:0;;;;;;;:::i;:::-;23909:12;23923:23;23950:6;-1:-1:-1;;;;;23950:11:0;23970:5;23978:4;23950:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23908:75;;;;24001:52;24019:7;24028:10;24040:12;24001:17;:52::i;:::-;23994:59;23488:573;-1:-1:-1;;;;;;;23488:573:0:o;26139:777::-;26289:12;26318:7;26314:595;;;-1:-1:-1;26349:10:0;26342:17;;26314:595;26463:17;;:21;26459:439;;26726:10;26720:17;26787:15;26774:10;26770:2;26766:19;26759:44;26674:148;26869:12;26862:20;;-1:-1:-1;;;26862:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;5:130;72:20;;-1:-1;;;;;52398:54;;53608:35;;53598:2;;53657:1;;53647:12;160:352;;;290:3;283:4;275:6;271:17;267:27;257:2;;-1:-1;;298:12;257:2;-1:-1;328:20;;368:18;357:30;;354:2;;;-1:-1;;390:12;354:2;434:4;426:6;422:17;410:29;;485:3;434:4;;469:6;465:17;426:6;451:32;;448:41;445:2;;;502:1;;492:12;1693:440;;1794:3;1787:4;1779:6;1775:17;1771:27;1761:2;;-1:-1;;1802:12;1761:2;1849:6;1836:20;50389:18;;50381:6;50378:30;50375:2;;;-1:-1;;50411:12;50375:2;50045;50039:9;50484;50465:17;;-1:-1;;50461:33;50071:17;;50552:4;50071:17;50131:34;;;50167:22;;;50128:62;50125:2;;;-1:-1;;50193:12;50125:2;50045;50212:22;1941:21;;;1862:73;-1:-1;1862:73;2041:16;;;50552:4;2041:16;2038:25;-1:-1;2035:2;;;2076:1;;2066:12;2035:2;52625:6;50552:4;1983:6;1979:17;50552:4;2017:5;2013:16;52602:30;52681:1;50552:4;52672:6;2017:5;52663:16;;52656:27;;;;1754:379;;;;:::o;2729:241::-;;2833:2;2821:9;2812:7;2808:23;2804:32;2801:2;;;-1:-1;;2839:12;2801:2;2901:53;2946:7;2922:22;2901:53;:::i;2977:366::-;;;3098:2;3086:9;3077:7;3073:23;3069:32;3066:2;;;-1:-1;;3104:12;3066:2;3166:53;3211:7;3187:22;3166:53;:::i;:::-;3156:63;;3274:53;3319:7;3256:2;3299:9;3295:22;3274:53;:::i;:::-;3264:63;;3060:283;;;;;:::o;3350:491::-;;;;3488:2;3476:9;3467:7;3463:23;3459:32;3456:2;;;-1:-1;;3494:12;3456:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;3546:63;-1:-1;3646:2;3685:22;;72:20;97:33;72:20;97:33;:::i;:::-;3450:391;;3654:63;;-1:-1;;;3754:2;3793:22;;;;2659:20;;3450:391::o;3848:721::-;;;;;4012:3;4000:9;3991:7;3987:23;3983:33;3980:2;;;-1:-1;;4019:12;3980:2;4081:53;4126:7;4102:22;4081:53;:::i;:::-;4071:63;;4189:53;4234:7;4171:2;4214:9;4210:22;4189:53;:::i;:::-;4179:63;;4279:2;4322:9;4318:22;2659:20;4287:63;;4415:2;4404:9;4400:18;4387:32;4439:18;4431:6;4428:30;4425:2;;;-1:-1;;4461:12;4425:2;4491:62;4545:7;4536:6;4525:9;4521:22;4491:62;:::i;:::-;4481:72;;;3974:595;;;;;;;:::o;4576:360::-;;;4694:2;4682:9;4673:7;4669:23;4665:32;4662:2;;;-1:-1;;4700:12;4662:2;4762:53;4807:7;4783:22;4762:53;:::i;:::-;4752:63;;4852:2;4892:9;4888:22;1351:20;53754:5;52080:13;52073:21;53732:5;53729:32;53719:2;;-1:-1;;53765:12;53719:2;4860:60;;;;4656:280;;;;;:::o;4943:366::-;;;5064:2;5052:9;5043:7;5039:23;5035:32;5032:2;;;-1:-1;;5070:12;5032:2;5132:53;5177:7;5153:22;5132:53;:::i;:::-;5122:63;5222:2;5261:22;;;;2659:20;;-1:-1;;;5026:283::o;5316:678::-;;;;;5507:2;5495:9;5486:7;5482:23;5478:32;5475:2;;;-1:-1;;5513:12;5475:2;5571:17;5558:31;5609:18;;5601:6;5598:30;5595:2;;;-1:-1;;5631:12;5595:2;5669:80;5741:7;5732:6;5721:9;5717:22;5669:80;:::i;:::-;5651:98;;-1:-1;5651:98;-1:-1;5814:2;5799:18;;5786:32;;-1:-1;5827:30;;;5824:2;;;-1:-1;;5860:12;5824:2;;5898:80;5970:7;5961:6;5950:9;5946:22;5898:80;:::i;:::-;5469:525;;;;-1:-1;5880:98;-1:-1;;;;5469:525::o;7395:239::-;;7498:2;7486:9;7477:7;7473:23;7469:32;7466:2;;;-1:-1;;7504:12;7466:2;1497:6;1484:20;1509:32;1535:5;1509:32;:::i;7641:261::-;;7755:2;7743:9;7734:7;7730:23;7726:32;7723:2;;;-1:-1;;7761:12;7723:2;1636:6;1630:13;1648:32;1674:5;1648:32;:::i;7909:347::-;;8023:2;8011:9;8002:7;7998:23;7994:32;7991:2;;;-1:-1;;8029:12;7991:2;8087:17;8074:31;8125:18;8117:6;8114:30;8111:2;;;-1:-1;;8147:12;8111:2;8177:63;8232:7;8223:6;8212:9;8208:22;8177:63;:::i;8263:241::-;;8367:2;8355:9;8346:7;8342:23;8338:32;8335:2;;;-1:-1;;8373:12;8335:2;-1:-1;2659:20;;8329:175;-1:-1;8329:175::o;8511:472::-;;;8642:2;8630:9;8621:7;8617:23;8613:32;8610:2;;;-1:-1;;8648:12;8610:2;2672:6;2659:20;8700:63;;8828:2;8817:9;8813:18;8800:32;8852:18;8844:6;8841:30;8838:2;;;-1:-1;;8874:12;8838:2;8904:63;8959:7;8950:6;8939:9;8935:22;8904:63;:::i;:::-;8894:73;;;8604:379;;;;;:::o;8990:366::-;;;9111:2;9099:9;9090:7;9086:23;9082:32;9079:2;;;-1:-1;;9117:12;9079:2;-1:-1;;2659:20;;;9269:2;9308:22;;;2659:20;;-1:-1;9073:283::o;10088:343::-;;10230:5;50990:12;51275:6;51270:3;51263:19;10323:52;10368:6;51312:4;51307:3;51303:14;51312:4;10349:5;10345:16;10323:52;:::i;:::-;50484:9;53410:14;-1:-1;;53406:28;10387:39;;;;51312:4;10387:39;;10178:253;-1:-1;;10178:253::o;27585:271::-;;10598:5;50990:12;10709:52;10754:6;10749:3;10742:4;10735:5;10731:16;10709:52;:::i;:::-;10773:16;;;;;27719:137;-1:-1;;27719:137::o;27863:436::-;;10598:5;50990:12;10709:52;10754:6;10749:3;10742:4;10735:5;10731:16;10709:52;:::i;:::-;50990:12;;10773:16;;;;10709:52;50990:12;10773:16;10742:4;10731:16;;10709:52;:::i;:::-;10773:16;;28047:252;-1:-1;;;;28047:252::o;28306:873::-;10018:58;;;28675:2;28666:12;;10018:58;;;;-1:-1;;53521:2;53517:14;;;;;28777:12;;;9612:74;28904:12;;;10018:58;;;;53517:14;;;;29015:12;;;9612:74;29142:12;;;28566:613::o;29186:222::-;-1:-1;;;;;52398:54;;;;9450:45;;29313:2;29298:18;;29284:124::o;29415:672::-;-1:-1;;;;;52398:54;;;9450:45;;52398:54;;29841:2;29826:18;;9450:45;29924:2;29909:18;;10018:58;;;29660:3;29961:2;29946:18;;29939:48;;;29415:672;;30001:76;;29645:19;;30063:6;30001:76;:::i;:::-;29993:84;29631:456;-1:-1;;;;;;29631:456::o;30094:210::-;52080:13;;52073:21;9883:34;;30215:2;30200:18;;30186:118::o;30311:310::-;;30458:2;30479:17;30472:47;30533:78;30458:2;30447:9;30443:18;30597:6;30533:78;:::i;30628:416::-;30828:2;30842:47;;;11747:2;30813:18;;;51263:19;11783:34;51303:14;;;11763:55;-1:-1;;;11838:12;;;11831:26;11876:12;;;30799:245::o;31051:416::-;31251:2;31265:47;;;12127:2;31236:18;;;51263:19;12163:27;51303:14;;;12143:48;12210:12;;;31222:245::o;31474:416::-;31674:2;31688:47;;;12461:2;31659:18;;;51263:19;-1:-1;;;51303:14;;;12477:45;12541:12;;;31645:245::o;31897:416::-;32097:2;32111:47;;;32082:18;;;51263:19;12828:34;51303:14;;;12808:55;12882:12;;;32068:245::o;32320:416::-;32520:2;32534:47;;;13133:2;32505:18;;;51263:19;13169:34;51303:14;;;13149:55;-1:-1;;;13224:12;;;13217:42;13278:12;;;32491:245::o;32743:416::-;32943:2;32957:47;;;13529:2;32928:18;;;51263:19;13565:34;51303:14;;;13545:55;-1:-1;;;13620:12;;;13613:30;13662:12;;;32914:245::o;33166:416::-;33366:2;33380:47;;;13913:2;33351:18;;;51263:19;-1:-1;;;51303:14;;;13929:43;13991:12;;;33337:245::o;33589:416::-;33789:2;33803:47;;;14242:2;33774:18;;;51263:19;14278:30;51303:14;;;14258:51;14328:12;;;33760:245::o;34012:416::-;34212:2;34226:47;;;14579:2;34197:18;;;51263:19;14615:29;51303:14;;;14595:50;14664:12;;;34183:245::o;34435:416::-;34635:2;34649:47;;;14915:2;34620:18;;;51263:19;-1:-1;;;51303:14;;;14931:38;14988:12;;;34606:245::o;34858:416::-;35058:2;35072:47;;;15239:2;35043:18;;;51263:19;15275:34;51303:14;;;15255:55;-1:-1;;;15330:12;;;15323:29;15371:12;;;35029:245::o;35281:416::-;35481:2;35495:47;;;15622:2;35466:18;;;51263:19;15658:34;51303:14;;;15638:55;-1:-1;;;15713:12;;;15706:28;15753:12;;;35452:245::o;35704:416::-;35904:2;35918:47;;;16004:2;35889:18;;;51263:19;16040:27;51303:14;;;16020:48;16087:12;;;35875:245::o;36127:416::-;36327:2;36341:47;;;16338:2;36312:18;;;51263:19;16374:34;51303:14;;;16354:55;-1:-1;;;16429:12;;;16422:31;16472:12;;;36298:245::o;36550:416::-;36750:2;36764:47;;;16723:2;36735:18;;;51263:19;16759:34;51303:14;;;16739:55;-1:-1;;;16814:12;;;16807:26;16852:12;;;36721:245::o;36973:416::-;37173:2;37187:47;;;17103:2;37158:18;;;51263:19;17139:33;51303:14;;;17119:54;17192:12;;;37144:245::o;37396:416::-;37596:2;37610:47;;;17443:2;37581:18;;;51263:19;17479:32;51303:14;;;17459:53;17531:12;;;37567:245::o;38242:416::-;38442:2;38456:47;;;18166:2;38427:18;;;51263:19;18202:34;51303:14;;;18182:55;-1:-1;;;18257:12;;;18250:36;18305:12;;;38413:245::o;38665:416::-;38865:2;38879:47;;;18556:2;38850:18;;;51263:19;18592:34;51303:14;;;18572:55;-1:-1;;;18647:12;;;18640:37;18696:12;;;38836:245::o;39088:416::-;39288:2;39302:47;;;18947:2;39273:18;;;51263:19;18983:34;51303:14;;;18963:55;19052:26;19038:12;;;19031:48;19098:12;;;39259:245::o;39511:416::-;39711:2;39725:47;;;19349:2;39696:18;;;51263:19;19385:34;51303:14;;;19365:55;-1:-1;;;19440:12;;;19433:34;19486:12;;;39682:245::o;39934:416::-;40134:2;40148:47;;;19737:2;40119:18;;;51263:19;-1:-1;;;51303:14;;;19753:44;19816:12;;;40105:245::o;40357:416::-;40557:2;40571:47;;;40542:18;;;51263:19;20103:34;51303:14;;;20083:55;20157:12;;;40528:245::o;40780:416::-;40980:2;40994:47;;;20408:2;40965:18;;;51263:19;20444:26;51303:14;;;20424:47;20490:12;;;40951:245::o;41203:416::-;41403:2;41417:47;;;20741:2;41388:18;;;51263:19;-1:-1;;;51303:14;;;20757:39;20815:12;;;41374:245::o;41626:416::-;41826:2;41840:47;;;21066:2;41811:18;;;51263:19;21102:34;51303:14;;;21082:55;-1:-1;;;21157:12;;;21150:26;21195:12;;;41797:245::o;42049:416::-;42249:2;42263:47;;;42234:18;;;51263:19;21482:34;51303:14;;;21462:55;21536:12;;;42220:245::o;42472:416::-;42672:2;42686:47;;;21787:2;42657:18;;;51263:19;21823:25;51303:14;;;21803:46;21868:12;;;42643:245::o;42895:416::-;43095:2;43109:47;;;22119:2;43080:18;;;51263:19;22155:26;51303:14;;;22135:47;22201:12;;;43066:245::o;43318:416::-;43518:2;43532:47;;;22452:2;43503:18;;;51263:19;22488:34;51303:14;;;22468:55;-1:-1;;;22543:12;;;22536:25;22580:12;;;43489:245::o;43741:416::-;43941:2;43955:47;;;22831:2;43926:18;;;51263:19;22867:34;51303:14;;;22847:55;-1:-1;;;22922:12;;;22915:36;22970:12;;;43912:245::o;44164:416::-;44364:2;44378:47;;;23221:2;44349:18;;;51263:19;23257:34;51303:14;;;23237:55;-1:-1;;;23312:12;;;23305:36;23360:12;;;44335:245::o;44587:416::-;44787:2;44801:47;;;44772:18;;;51263:19;23647:34;51303:14;;;23627:55;23701:12;;;44758:245::o;45010:416::-;45210:2;45224:47;;;23952:2;45195:18;;;51263:19;23988:34;51303:14;;;23968:55;-1:-1;;;24043:12;;;24036:33;24088:12;;;45181:245::o;45433:416::-;45633:2;45647:47;;;24339:2;45618:18;;;51263:19;24375:34;51303:14;;;24355:55;-1:-1;;;24430:12;;;24423:39;24481:12;;;45604:245::o;45856:416::-;46056:2;46070:47;;;24732:2;46041:18;;;51263:19;24768:33;51303:14;;;24748:54;24821:12;;;46027:245::o;46279:416::-;46479:2;46493:47;;;25072:2;46464:18;;;51263:19;25108:34;51303:14;;;25088:55;-1:-1;;;25163:12;;;25156:25;25200:12;;;46450:245::o;46702:416::-;46902:2;46916:47;;;25451:2;46887:18;;;51263:19;25487:34;51303:14;;;25467:55;-1:-1;;;25542:12;;;25535:41;25595:12;;;46873:245::o;47125:416::-;47325:2;47339:47;;;25846:2;47310:18;;;51263:19;25882:31;51303:14;;;25862:52;25933:12;;;47296:245::o;47548:416::-;47748:2;47762:47;;;26184:2;47733:18;;;51263:19;26220:27;51303:14;;;26200:48;26267:12;;;47719:245::o;47971:416::-;48171:2;48185:47;;;26518:2;48156:18;;;51263:19;26554:33;51303:14;;;26534:54;26607:12;;;48142:245::o;48394:416::-;48594:2;48608:47;;;26858:2;48579:18;;;51263:19;26894:32;51303:14;;;26874:53;26946:12;;;48565:245::o;48817:416::-;49017:2;49031:47;;;27197:2;49002:18;;;51263:19;27233:27;51303:14;;;27213:48;27280:12;;;48988:245::o;49240:222::-;10018:58;;;49367:2;49352:18;;49338:124::o;49469:507::-;;;49605:11;49592:25;49656:48;;49680:8;49664:14;49660:29;49656:48;49636:18;49632:73;49622:2;;-1:-1;;49709:12;49622:2;49736:33;;49790:18;;;-1:-1;49828:18;49817:30;;49814:2;;;-1:-1;;49850:12;49814:2;49695:4;49878:13;;-1:-1;49664:14;49910:38;;;49900:49;;49897:2;;;49962:1;;49952:12;52698:268;52763:1;52770:101;52784:6;52781:1;52778:13;52770:101;;;52851:11;;;52845:18;52832:11;;;52825:39;52806:2;52799:10;52770:101;;;52886:6;52883:1;52880:13;52877:2;;;-1:-1;;52763:1;52933:16;;52926:27;52747:219::o;53549:117::-;-1:-1;;;;;52398:54;;53608:35;;53598:2;;53657:1;;53647:12;53791:115;-1:-1;;;;;;52246:78;;53849:34;;53839:2;;53897:1;;53887:12

Swarm Source

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