CRO Price: $0.08 (-0.31%)

Token

MadMeerkatEquipment (MME)

Overview

Max Total Supply

40,943 MME

Holders

2,371

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-
Balance
1 MME
0x18f3bd138b6a272180a5c173ffe25288de9fc366
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
MadMeerkatEquipment

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at cronoscan.com on 2022-07-31
*/

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



pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and 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 contracts/MadMeerkatEquipment.sol

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



pragma solidity ^0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with 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 payable(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





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


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



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






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





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






/**
 * @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 () internal {
        // 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





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





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





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





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





/**
 * @dev String operations.
 */
library Strings {
    /**
     * @dev Converts a `uint256` to its ASCII `string` representation.
     */
    function toString(uint256 _i) 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 (_i == 0) {
            return "0";
        }
        uint j = _i;
        uint len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint k = len;
        while (_i != 0) {
            k = k-1;
            uint8 temp = (48 + uint8(_i - _i / 10 * 10));
            bytes1 b1 = bytes1(temp);
            bstr[k] = b1;
            _i /= 10;
        }
        return string(bstr);
    }
}

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
















/**
 * @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_) public {
        _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) {
            return _tokenURI;
        }
        // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
        if (bytes(_tokenURI).length > 0) {
            return string(abi.encodePacked(base, _tokenURI));
        }
        // 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





/**
 * @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 () internal {
        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;
    }
}

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);
}


contract MadMeerkatEquipment is ERC721, Ownable, ReentrancyGuard {
    using SafeMath for uint256;

    IERC20 public MAD = IERC20(0x212331e1435A8df230715dB4C02B2a3A0abF8c61);

    uint public equipmentPrice = 3 ether;
    bool public saleIsActive = false; // determines whether sales is active
    mapping(address => bool) private operators;

    event AssetMinted(address account, uint256 tokenId);

    constructor() ERC721("MadMeerkatEquipment", "MME") {}

    /* ========== External public sales functions ========== */

    // @dev mints equipment for the general public
    function mintEquipment(uint numberOfTokens) external nonReentrant {
        require(saleIsActive); // Sale must be active
        require(numberOfTokens <= 20); // Max mint of 20

        require(MAD.transferFrom(msg.sender, address(this), equipmentPrice.mul(numberOfTokens)));

        for (uint i = 0; i < numberOfTokens; i++) {
            uint nextId = totalSupply() + 1;
            emit AssetMinted(msg.sender, nextId);

            _mint(msg.sender, nextId);
        }
    }

    /* ========== External owner functions ========== */

    // @dev mints equipment as giveaways
    function giveAway(address to, uint numberOfTokens) external nonReentrant onlyOperator {
        for (uint i = 0; i < numberOfTokens; i++) {
            emit AssetMinted(to, totalSupply() + 1);

            _mint(to, totalSupply() + 1);
        }
    }
    
    // @dev sets base URI
    function setBaseURI(string memory baseURI) external onlyOwner {
        _setBaseURI(baseURI);
    }

    // @dev withdraw funds
    function withdraw() external onlyOwner {
        uint balance = address(this).balance;
        payable(msg.sender).transfer(balance);
    }

    // @dev withdraw funds
    function withdrawERC20(address token) external onlyOwner {
        uint balance = IERC20(token).balanceOf(address(this));
        IERC20(token).transfer(msg.sender, balance);
    }

    // @dev flips the state for sales
    function flipSaleState() external onlyOwner {
        saleIsActive = !saleIsActive;
    }

    // @dev withdraw funds
    function setMAD(IERC20 _address) external onlyOwner {
        MAD = _address;
    }
    
    // @dev withdraw funds
    function setEquipmentPrice(uint256 _price) external onlyOwner {
        equipmentPrice = _price;
    }

    /* ========== External owner functions ========== */

    modifier onlyOperator () {
        require(operators[msg.sender], "only operators");
        _;
    }
}

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":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"AssetMinted","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":"MAD","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"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":[],"name":"equipmentPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"address","name":"to","type":"address"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"giveAway","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"mintEquipment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"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":"uint256","name":"_price","type":"uint256"}],"name":"setEquipmentPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_address","type":"address"}],"name":"setMAD","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":"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"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600c80546001600160a01b03191673212331e1435a8df230715db4c02b2a3a0abf8c611790556729a2241af62c0000600d55600e805460ff191690553480156200004d57600080fd5b50604080518082018252601381527f4d61644d6565726b617445717569706d656e7400000000000000000000000000602080830191909152825180840190935260038352624d4d4560e81b9083015290620000af6301ffc9a760e01b62000179565b8151620000c4906006906020850190620001d8565b508051620000da906007906020840190620001d8565b50620000ed6380ac58cd60e01b62000179565b620000ff635b5e139f60e01b62000179565b6200011163780e9d6360e01b62000179565b506000905062000120620001d4565b600a80546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600b55620002f2565b6001600160e01b03198082161415620001af5760405162461bcd60e51b8152600401620001a6906200027e565b60405180910390fd5b6001600160e01b0319166000908152602081905260409020805460ff19166001179055565b3390565b828054620001e690620002b5565b90600052602060002090601f0160209004810192826200020a576000855562000255565b82601f106200022557805160ff191683800117855562000255565b8280016001018555821562000255579182015b828111156200025557825182559160200191906001019062000238565b506200026392915062000267565b5090565b5b8082111562000263576000815560010162000268565b6020808252601c908201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604082015260600190565b600281046001821680620002ca57607f821691505b60208210811415620002ec57634e487b7160e01b600052602260045260246000fd5b50919050565b61264e80620003026000396000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c80636c0360eb1161010f578063c87b56dd116100a2578063ef73b67a11610071578063ef73b67a146103b1578063f2fde38b146103c4578063f4f3b200146103d7578063f5ec7e7c146103ea576101e5565b8063c87b56dd14610370578063ca80014414610383578063e985e9c514610396578063eb8d2444146103a9576101e5565b806395d89b41116100de57806395d89b411461032f578063a22cb46514610337578063b88d4fde1461034a578063c7f91ceb1461035d576101e5565b80636c0360eb1461030457806370a082311461030c578063715018a61461031f5780638da5cb5b14610327576101e5565b80632a65f5051161018757806342842e0e1161015657806342842e0e146102b85780634f6ccce7146102cb57806355f804b3146102de5780636352211e146102f1576101e5565b80632a65f5051461028d5780632f745c591461029557806334918dfd146102a85780633ccfd60b146102b0576101e5565b8063095ea7b3116101c3578063095ea7b31461024857806318160ddd1461025d57806323b872dd1461027257806324292dd814610285576101e5565b806301ffc9a7146101ea57806306fdde0314610213578063081812fc14610228575b600080fd5b6101fd6101f8366004611cf1565b6103fd565b60405161020a9190611ea4565b60405180910390f35b61021b610420565b60405161020a9190611eaf565b61023b610236366004611d6f565b6104b2565b60405161020a9190611e16565b61025b610256366004611caa565b6104fe565b005b610265610596565b60405161020a919061243a565b61025b610280366004611bc0565b6105a7565b61023b6105df565b6102656105ee565b6102656102a3366004611caa565b6105f4565b61025b61061f565b61025b610672565b61025b6102c6366004611bc0565b6106e4565b6102656102d9366004611d6f565b6106ff565b61025b6102ec366004611d29565b610715565b61023b6102ff366004611d6f565b610760565b61021b610788565b61026561031a366004611b6c565b610797565b61025b6107e0565b61023b610869565b61021b610878565b61025b610345366004611c7d565b610887565b61025b610358366004611c00565b610955565b61025b61036b366004611d6f565b610994565b61021b61037e366004611d6f565b610af9565b61025b610391366004611caa565b610c3c565b6101fd6103a4366004611b88565b610d21565b6101fd610d4f565b61025b6103bf366004611b6c565b610d58565b61025b6103d2366004611b6c565b610db9565b61025b6103e5366004611b6c565b610e7a565b61025b6103f8366004611d6f565b610fbb565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60606006805461042f90612502565b80601f016020809104026020016040519081016040528092919081815260200182805461045b90612502565b80156104a85780601f1061047d576101008083540402835291602001916104a8565b820191906000526020600020905b81548152906001019060200180831161048b57829003601f168201915b5050505050905090565b60006104bd82610fff565b6104e25760405162461bcd60e51b81526004016104d990612221565b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061050982610760565b9050806001600160a01b0316836001600160a01b0316141561053d5760405162461bcd60e51b81526004016104d99061233a565b806001600160a01b031661054f61100c565b6001600160a01b0316148061056b575061056b816103a461100c565b6105875760405162461bcd60e51b81526004016104d9906120c2565b6105918383611010565b505050565b60006105a2600261107e565b905090565b6105b86105b261100c565b82611089565b6105d45760405162461bcd60e51b81526004016104d99061237b565b61059183838361110e565b600c546001600160a01b031681565b600d5481565b6001600160a01b0382166000908152600160205260408120610616908361121c565b90505b92915050565b61062761100c565b6001600160a01b0316610638610869565b6001600160a01b03161461065e5760405162461bcd60e51b81526004016104d99061226d565b600e805460ff19811660ff90911615179055565b61067a61100c565b6001600160a01b031661068b610869565b6001600160a01b0316146106b15760405162461bcd60e51b81526004016104d99061226d565b6040514790339082156108fc029083906000818181858888f193505050501580156106e0573d6000803e3d6000fd5b5050565b61059183838360405180602001604052806000815250610955565b60008061070d600284611228565b509392505050565b61071d61100c565b6001600160a01b031661072e610869565b6001600160a01b0316146107545760405162461bcd60e51b81526004016104d99061226d565b61075d81611244565b50565b6000610619826040518060600160405280602981526020016125f06029913960029190611257565b60606009805461042f90612502565b60006001600160a01b0382166107bf5760405162461bcd60e51b81526004016104d99061211f565b6001600160a01b03821660009081526001602052604090206106199061107e565b6107e861100c565b6001600160a01b03166107f9610869565b6001600160a01b03161461081f5760405162461bcd60e51b81526004016104d99061226d565b600a546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600a80546001600160a01b0319169055565b600a546001600160a01b031690565b60606007805461042f90612502565b61088f61100c565b6001600160a01b0316826001600160a01b031614156108c05760405162461bcd60e51b81526004016104d99061203f565b80600560006108cd61100c565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff19169215159290921790915561091161100c565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516109499190611ea4565b60405180910390a35050565b61096661096061100c565b83611089565b6109825760405162461bcd60e51b81526004016104d99061237b565b61098e8484848461126e565b50505050565b6002600b5414156109b75760405162461bcd60e51b81526004016104d990612403565b6002600b55600e5460ff166109cb57600080fd5b60148111156109d957600080fd5b600c54600d546001600160a01b03909116906323b872dd90339030906109ff90866112a1565b6040518463ffffffff1660e01b8152600401610a1d93929190611e67565b602060405180830381600087803b158015610a3757600080fd5b505af1158015610a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6f9190611cd5565b610a7857600080fd5b60005b81811015610af0576000610a8d610596565b610a98906001612443565b90507f8d1457c1d60a6987eabbac898a50d8d7c81ba604c563663d2807027a4b0790543382604051610acb929190611e8b565b60405180910390a1610add33826112e6565b5080610ae88161253d565b915050610a7b565b50506001600b55565b6060610b0482610fff565b610b205760405162461bcd60e51b81526004016104d9906122eb565b60008281526008602052604081208054610b3990612502565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6590612502565b8015610bb25780601f10610b8757610100808354040283529160200191610bb2565b820191906000526020600020905b815481529060010190602001808311610b9557829003601f168201915b505050505090506000610bc3610788565b9050805160001415610bd75750905061041b565b815115610c09578082604051602001610bf1929190611de7565b6040516020818303038152906040529250505061041b565b80610c13856113aa565b604051602001610c24929190611de7565b60405160208183030381529060405292505050919050565b6002600b541415610c5f5760405162461bcd60e51b81526004016104d990612403565b6002600b55336000908152600f602052604090205460ff16610c935760405162461bcd60e51b81526004016104d990611f04565b60005b81811015610d17577f8d1457c1d60a6987eabbac898a50d8d7c81ba604c563663d2807027a4b07905483610cc8610596565b610cd3906001612443565b604051610ce1929190611e8b565b60405180910390a1610d0583610cf5610596565b610d00906001612443565b6112e6565b80610d0f8161253d565b915050610c96565b50506001600b5550565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b600e5460ff1681565b610d6061100c565b6001600160a01b0316610d71610869565b6001600160a01b031614610d975760405162461bcd60e51b81526004016104d99061226d565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b610dc161100c565b6001600160a01b0316610dd2610869565b6001600160a01b031614610df85760405162461bcd60e51b81526004016104d99061226d565b6001600160a01b038116610e1e5760405162461bcd60e51b81526004016104d990611f7e565b600a546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600a80546001600160a01b0319166001600160a01b0392909216919091179055565b610e8261100c565b6001600160a01b0316610e93610869565b6001600160a01b031614610eb95760405162461bcd60e51b81526004016104d99061226d565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610ee8903090600401611e16565b60206040518083038186803b158015610f0057600080fd5b505afa158015610f14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f389190611d87565b60405163a9059cbb60e01b81529091506001600160a01b0383169063a9059cbb90610f699033908590600401611e8b565b602060405180830381600087803b158015610f8357600080fd5b505af1158015610f97573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105919190611cd5565b610fc361100c565b6001600160a01b0316610fd4610869565b6001600160a01b031614610ffa5760405162461bcd60e51b81526004016104d99061226d565b600d55565b60006106196002836114f0565b3390565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061104582610760565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000610619826114fc565b600061109482610fff565b6110b05760405162461bcd60e51b81526004016104d990612076565b60006110bb83610760565b9050806001600160a01b0316846001600160a01b031614806110f65750836001600160a01b03166110eb846104b2565b6001600160a01b0316145b8061110657506111068185610d21565b949350505050565b826001600160a01b031661112182610760565b6001600160a01b0316146111475760405162461bcd60e51b81526004016104d9906122a2565b6001600160a01b03821661116d5760405162461bcd60e51b81526004016104d990611ffb565b611178838383610591565b611183600082611010565b6001600160a01b03831660009081526001602052604090206111a59082611500565b506001600160a01b03821660009081526001602052604090206111c8908261150c565b506111d560028284611518565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000610616838361152e565b60008080806112378686611587565b9097909650945050505050565b80516106e0906009906020840190611a63565b60006112648484846115f7565b90505b9392505050565b61127984848461110e565b6112858484848461166e565b61098e5760405162461bcd60e51b81526004016104d990611f2c565b6000826112b057506000610619565b60006112bc83856124a0565b9050826112c98583612480565b146106165760405162461bcd60e51b81526004016104d9906121e0565b6001600160a01b03821661130c5760405162461bcd60e51b81526004016104d9906121ab565b61131581610fff565b156113325760405162461bcd60e51b81526004016104d990611fc4565b61133e60008383610591565b6001600160a01b0382166000908152600160205260409020611360908261150c565b5061136d60028284611518565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6060816113cf57506040805180820190915260018152600360fc1b602082015261041b565b8160005b81156113f957806113e38161253d565b91506113f29050600a83612480565b91506113d3565b60008167ffffffffffffffff81111561142257634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561144c576020820181803683370190505b509050815b85156114e7576114626001826124bf565b90506000611471600a88612480565b61147c90600a6124a0565b61148690886124bf565b61149190603061245b565b905060008160f81b9050808484815181106114bc57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506114de600a89612480565b97505050611451565b50949350505050565b6000610616838361174d565b5490565b60006106168383611765565b60006106168383611882565b600061126484846001600160a01b0385166118cc565b815460009082106115515760405162461bcd60e51b81526004016104d990611ec2565b82600001828154811061157457634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b8154600090819083106115ac5760405162461bcd60e51b81526004016104d990612169565b60008460000184815481106115d157634e487b7160e01b600052603260045260246000fd5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816116275760405162461bcd60e51b81526004016104d99190611eaf565b50846116346001836124bf565b8154811061165257634e487b7160e01b600052603260045260246000fd5b9060005260206000209060020201600101549150509392505050565b6000611682846001600160a01b031661197b565b61168e57506001611106565b6000611716630a85bd0160e11b6116a361100c565b8887876040516024016116b99493929190611e2a565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050506040518060600160405280603281526020016125be603291396001600160a01b0388169190611981565b905060008180602001905181019061172e9190611d0d565b6001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b600081815260018301602052604081205480156118785760006117896001836124bf565b855490915060009061179d906001906124bf565b905060008660000182815481106117c457634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050808760000184815481106117f557634e487b7160e01b600052603260045260246000fd5b60009182526020909120015561180c836001612443565b6000828152600189016020526040902055865487908061183c57634e487b7160e01b600052603160045260246000fd5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610619565b6000915050610619565b600061188e838361174d565b6118c457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610619565b506000610619565b600082815260018401602052604081205480611931575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611267565b828561193e6001846124bf565b8154811061195c57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060020201600101819055506000915050611267565b3b151590565b60606112648484600085856119958561197b565b6119b15760405162461bcd60e51b81526004016104d9906123cc565b600080866001600160a01b031685876040516119cd9190611dcb565b60006040518083038185875af1925050503d8060008114611a0a576040519150601f19603f3d011682016040523d82523d6000602084013e611a0f565b606091505b5091509150611a1f828286611a2a565b979650505050505050565b60608315611a39575081611267565b825115611a495782518084602001fd5b8160405162461bcd60e51b81526004016104d99190611eaf565b828054611a6f90612502565b90600052602060002090601f016020900481019282611a915760008555611ad7565b82601f10611aaa57805160ff1916838001178555611ad7565b82800160010185558215611ad7579182015b82811115611ad7578251825591602001919060010190611abc565b50611ae3929150611ae7565b5090565b5b80821115611ae35760008155600101611ae8565b600067ffffffffffffffff80841115611b1757611b1761256e565b604051601f8501601f191681016020018281118282101715611b3b57611b3b61256e565b604052848152915081838501861015611b5357600080fd5b8484602083013760006020868301015250509392505050565b600060208284031215611b7d578081fd5b813561061681612584565b60008060408385031215611b9a578081fd5b8235611ba581612584565b91506020830135611bb581612584565b809150509250929050565b600080600060608486031215611bd4578081fd5b8335611bdf81612584565b92506020840135611bef81612584565b929592945050506040919091013590565b60008060008060808587031215611c15578081fd5b8435611c2081612584565b93506020850135611c3081612584565b925060408501359150606085013567ffffffffffffffff811115611c52578182fd5b8501601f81018713611c62578182fd5b611c7187823560208401611afc565b91505092959194509250565b60008060408385031215611c8f578182fd5b8235611c9a81612584565b91506020830135611bb581612599565b60008060408385031215611cbc578182fd5b8235611cc781612584565b946020939093013593505050565b600060208284031215611ce6578081fd5b815161061681612599565b600060208284031215611d02578081fd5b8135610616816125a7565b600060208284031215611d1e578081fd5b8151610616816125a7565b600060208284031215611d3a578081fd5b813567ffffffffffffffff811115611d50578182fd5b8201601f81018413611d60578182fd5b61110684823560208401611afc565b600060208284031215611d80578081fd5b5035919050565b600060208284031215611d98578081fd5b5051919050565b60008151808452611db78160208601602086016124d6565b601f01601f19169290920160200192915050565b60008251611ddd8184602087016124d6565b9190910192915050565b60008351611df98184602088016124d6565b835190830190611e0d8183602088016124d6565b01949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611e5d90830184611d9f565b9695505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602082526106166020830184611d9f565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b6020808252600e908201526d6f6e6c79206f70657261746f727360901b604082015260600190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604082015260600190565b60208082526024908201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526019908201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604082015260600190565b6020808252602c908201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b60208082526038908201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760408201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606082015260800190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604082015269726f206164647265737360b01b606082015260800190565b60208082526022908201527f456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960408201526839903737ba1037bbb760b91b606082015260800190565b6020808252602f908201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60408201526e3732bc34b9ba32b73a103a37b5b2b760891b606082015260800190565b60208082526021908201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656040820152603960f91b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b90815260200190565b6000821982111561245657612456612558565b500190565b600060ff821660ff84168060ff0382111561247857612478612558565b019392505050565b60008261249b57634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156124ba576124ba612558565b500290565b6000828210156124d1576124d1612558565b500390565b60005b838110156124f15781810151838201526020016124d9565b8381111561098e5750506000910152565b60028104600182168061251657607f821691505b6020821081141561253757634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561255157612551612558565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461075d57600080fd5b801515811461075d57600080fd5b6001600160e01b03198116811461075d57600080fdfe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656ea2646970667358221220c4544ed97b534a320897510b3aa009bf2a4de1d4b1f9c881285788d8d305b0a564736f6c63430008000033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101e55760003560e01c80636c0360eb1161010f578063c87b56dd116100a2578063ef73b67a11610071578063ef73b67a146103b1578063f2fde38b146103c4578063f4f3b200146103d7578063f5ec7e7c146103ea576101e5565b8063c87b56dd14610370578063ca80014414610383578063e985e9c514610396578063eb8d2444146103a9576101e5565b806395d89b41116100de57806395d89b411461032f578063a22cb46514610337578063b88d4fde1461034a578063c7f91ceb1461035d576101e5565b80636c0360eb1461030457806370a082311461030c578063715018a61461031f5780638da5cb5b14610327576101e5565b80632a65f5051161018757806342842e0e1161015657806342842e0e146102b85780634f6ccce7146102cb57806355f804b3146102de5780636352211e146102f1576101e5565b80632a65f5051461028d5780632f745c591461029557806334918dfd146102a85780633ccfd60b146102b0576101e5565b8063095ea7b3116101c3578063095ea7b31461024857806318160ddd1461025d57806323b872dd1461027257806324292dd814610285576101e5565b806301ffc9a7146101ea57806306fdde0314610213578063081812fc14610228575b600080fd5b6101fd6101f8366004611cf1565b6103fd565b60405161020a9190611ea4565b60405180910390f35b61021b610420565b60405161020a9190611eaf565b61023b610236366004611d6f565b6104b2565b60405161020a9190611e16565b61025b610256366004611caa565b6104fe565b005b610265610596565b60405161020a919061243a565b61025b610280366004611bc0565b6105a7565b61023b6105df565b6102656105ee565b6102656102a3366004611caa565b6105f4565b61025b61061f565b61025b610672565b61025b6102c6366004611bc0565b6106e4565b6102656102d9366004611d6f565b6106ff565b61025b6102ec366004611d29565b610715565b61023b6102ff366004611d6f565b610760565b61021b610788565b61026561031a366004611b6c565b610797565b61025b6107e0565b61023b610869565b61021b610878565b61025b610345366004611c7d565b610887565b61025b610358366004611c00565b610955565b61025b61036b366004611d6f565b610994565b61021b61037e366004611d6f565b610af9565b61025b610391366004611caa565b610c3c565b6101fd6103a4366004611b88565b610d21565b6101fd610d4f565b61025b6103bf366004611b6c565b610d58565b61025b6103d2366004611b6c565b610db9565b61025b6103e5366004611b6c565b610e7a565b61025b6103f8366004611d6f565b610fbb565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60606006805461042f90612502565b80601f016020809104026020016040519081016040528092919081815260200182805461045b90612502565b80156104a85780601f1061047d576101008083540402835291602001916104a8565b820191906000526020600020905b81548152906001019060200180831161048b57829003601f168201915b5050505050905090565b60006104bd82610fff565b6104e25760405162461bcd60e51b81526004016104d990612221565b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b600061050982610760565b9050806001600160a01b0316836001600160a01b0316141561053d5760405162461bcd60e51b81526004016104d99061233a565b806001600160a01b031661054f61100c565b6001600160a01b0316148061056b575061056b816103a461100c565b6105875760405162461bcd60e51b81526004016104d9906120c2565b6105918383611010565b505050565b60006105a2600261107e565b905090565b6105b86105b261100c565b82611089565b6105d45760405162461bcd60e51b81526004016104d99061237b565b61059183838361110e565b600c546001600160a01b031681565b600d5481565b6001600160a01b0382166000908152600160205260408120610616908361121c565b90505b92915050565b61062761100c565b6001600160a01b0316610638610869565b6001600160a01b03161461065e5760405162461bcd60e51b81526004016104d99061226d565b600e805460ff19811660ff90911615179055565b61067a61100c565b6001600160a01b031661068b610869565b6001600160a01b0316146106b15760405162461bcd60e51b81526004016104d99061226d565b6040514790339082156108fc029083906000818181858888f193505050501580156106e0573d6000803e3d6000fd5b5050565b61059183838360405180602001604052806000815250610955565b60008061070d600284611228565b509392505050565b61071d61100c565b6001600160a01b031661072e610869565b6001600160a01b0316146107545760405162461bcd60e51b81526004016104d99061226d565b61075d81611244565b50565b6000610619826040518060600160405280602981526020016125f06029913960029190611257565b60606009805461042f90612502565b60006001600160a01b0382166107bf5760405162461bcd60e51b81526004016104d99061211f565b6001600160a01b03821660009081526001602052604090206106199061107e565b6107e861100c565b6001600160a01b03166107f9610869565b6001600160a01b03161461081f5760405162461bcd60e51b81526004016104d99061226d565b600a546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600a80546001600160a01b0319169055565b600a546001600160a01b031690565b60606007805461042f90612502565b61088f61100c565b6001600160a01b0316826001600160a01b031614156108c05760405162461bcd60e51b81526004016104d99061203f565b80600560006108cd61100c565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff19169215159290921790915561091161100c565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516109499190611ea4565b60405180910390a35050565b61096661096061100c565b83611089565b6109825760405162461bcd60e51b81526004016104d99061237b565b61098e8484848461126e565b50505050565b6002600b5414156109b75760405162461bcd60e51b81526004016104d990612403565b6002600b55600e5460ff166109cb57600080fd5b60148111156109d957600080fd5b600c54600d546001600160a01b03909116906323b872dd90339030906109ff90866112a1565b6040518463ffffffff1660e01b8152600401610a1d93929190611e67565b602060405180830381600087803b158015610a3757600080fd5b505af1158015610a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6f9190611cd5565b610a7857600080fd5b60005b81811015610af0576000610a8d610596565b610a98906001612443565b90507f8d1457c1d60a6987eabbac898a50d8d7c81ba604c563663d2807027a4b0790543382604051610acb929190611e8b565b60405180910390a1610add33826112e6565b5080610ae88161253d565b915050610a7b565b50506001600b55565b6060610b0482610fff565b610b205760405162461bcd60e51b81526004016104d9906122eb565b60008281526008602052604081208054610b3990612502565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6590612502565b8015610bb25780601f10610b8757610100808354040283529160200191610bb2565b820191906000526020600020905b815481529060010190602001808311610b9557829003601f168201915b505050505090506000610bc3610788565b9050805160001415610bd75750905061041b565b815115610c09578082604051602001610bf1929190611de7565b6040516020818303038152906040529250505061041b565b80610c13856113aa565b604051602001610c24929190611de7565b60405160208183030381529060405292505050919050565b6002600b541415610c5f5760405162461bcd60e51b81526004016104d990612403565b6002600b55336000908152600f602052604090205460ff16610c935760405162461bcd60e51b81526004016104d990611f04565b60005b81811015610d17577f8d1457c1d60a6987eabbac898a50d8d7c81ba604c563663d2807027a4b07905483610cc8610596565b610cd3906001612443565b604051610ce1929190611e8b565b60405180910390a1610d0583610cf5610596565b610d00906001612443565b6112e6565b80610d0f8161253d565b915050610c96565b50506001600b5550565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b600e5460ff1681565b610d6061100c565b6001600160a01b0316610d71610869565b6001600160a01b031614610d975760405162461bcd60e51b81526004016104d99061226d565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b610dc161100c565b6001600160a01b0316610dd2610869565b6001600160a01b031614610df85760405162461bcd60e51b81526004016104d99061226d565b6001600160a01b038116610e1e5760405162461bcd60e51b81526004016104d990611f7e565b600a546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600a80546001600160a01b0319166001600160a01b0392909216919091179055565b610e8261100c565b6001600160a01b0316610e93610869565b6001600160a01b031614610eb95760405162461bcd60e51b81526004016104d99061226d565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610ee8903090600401611e16565b60206040518083038186803b158015610f0057600080fd5b505afa158015610f14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f389190611d87565b60405163a9059cbb60e01b81529091506001600160a01b0383169063a9059cbb90610f699033908590600401611e8b565b602060405180830381600087803b158015610f8357600080fd5b505af1158015610f97573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105919190611cd5565b610fc361100c565b6001600160a01b0316610fd4610869565b6001600160a01b031614610ffa5760405162461bcd60e51b81526004016104d99061226d565b600d55565b60006106196002836114f0565b3390565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061104582610760565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000610619826114fc565b600061109482610fff565b6110b05760405162461bcd60e51b81526004016104d990612076565b60006110bb83610760565b9050806001600160a01b0316846001600160a01b031614806110f65750836001600160a01b03166110eb846104b2565b6001600160a01b0316145b8061110657506111068185610d21565b949350505050565b826001600160a01b031661112182610760565b6001600160a01b0316146111475760405162461bcd60e51b81526004016104d9906122a2565b6001600160a01b03821661116d5760405162461bcd60e51b81526004016104d990611ffb565b611178838383610591565b611183600082611010565b6001600160a01b03831660009081526001602052604090206111a59082611500565b506001600160a01b03821660009081526001602052604090206111c8908261150c565b506111d560028284611518565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000610616838361152e565b60008080806112378686611587565b9097909650945050505050565b80516106e0906009906020840190611a63565b60006112648484846115f7565b90505b9392505050565b61127984848461110e565b6112858484848461166e565b61098e5760405162461bcd60e51b81526004016104d990611f2c565b6000826112b057506000610619565b60006112bc83856124a0565b9050826112c98583612480565b146106165760405162461bcd60e51b81526004016104d9906121e0565b6001600160a01b03821661130c5760405162461bcd60e51b81526004016104d9906121ab565b61131581610fff565b156113325760405162461bcd60e51b81526004016104d990611fc4565b61133e60008383610591565b6001600160a01b0382166000908152600160205260409020611360908261150c565b5061136d60028284611518565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6060816113cf57506040805180820190915260018152600360fc1b602082015261041b565b8160005b81156113f957806113e38161253d565b91506113f29050600a83612480565b91506113d3565b60008167ffffffffffffffff81111561142257634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561144c576020820181803683370190505b509050815b85156114e7576114626001826124bf565b90506000611471600a88612480565b61147c90600a6124a0565b61148690886124bf565b61149190603061245b565b905060008160f81b9050808484815181106114bc57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506114de600a89612480565b97505050611451565b50949350505050565b6000610616838361174d565b5490565b60006106168383611765565b60006106168383611882565b600061126484846001600160a01b0385166118cc565b815460009082106115515760405162461bcd60e51b81526004016104d990611ec2565b82600001828154811061157457634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b8154600090819083106115ac5760405162461bcd60e51b81526004016104d990612169565b60008460000184815481106115d157634e487b7160e01b600052603260045260246000fd5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816116275760405162461bcd60e51b81526004016104d99190611eaf565b50846116346001836124bf565b8154811061165257634e487b7160e01b600052603260045260246000fd5b9060005260206000209060020201600101549150509392505050565b6000611682846001600160a01b031661197b565b61168e57506001611106565b6000611716630a85bd0160e11b6116a361100c565b8887876040516024016116b99493929190611e2a565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050506040518060600160405280603281526020016125be603291396001600160a01b0388169190611981565b905060008180602001905181019061172e9190611d0d565b6001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b600081815260018301602052604081205480156118785760006117896001836124bf565b855490915060009061179d906001906124bf565b905060008660000182815481106117c457634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050808760000184815481106117f557634e487b7160e01b600052603260045260246000fd5b60009182526020909120015561180c836001612443565b6000828152600189016020526040902055865487908061183c57634e487b7160e01b600052603160045260246000fd5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610619565b6000915050610619565b600061188e838361174d565b6118c457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610619565b506000610619565b600082815260018401602052604081205480611931575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611267565b828561193e6001846124bf565b8154811061195c57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060020201600101819055506000915050611267565b3b151590565b60606112648484600085856119958561197b565b6119b15760405162461bcd60e51b81526004016104d9906123cc565b600080866001600160a01b031685876040516119cd9190611dcb565b60006040518083038185875af1925050503d8060008114611a0a576040519150601f19603f3d011682016040523d82523d6000602084013e611a0f565b606091505b5091509150611a1f828286611a2a565b979650505050505050565b60608315611a39575081611267565b825115611a495782518084602001fd5b8160405162461bcd60e51b81526004016104d99190611eaf565b828054611a6f90612502565b90600052602060002090601f016020900481019282611a915760008555611ad7565b82601f10611aaa57805160ff1916838001178555611ad7565b82800160010185558215611ad7579182015b82811115611ad7578251825591602001919060010190611abc565b50611ae3929150611ae7565b5090565b5b80821115611ae35760008155600101611ae8565b600067ffffffffffffffff80841115611b1757611b1761256e565b604051601f8501601f191681016020018281118282101715611b3b57611b3b61256e565b604052848152915081838501861015611b5357600080fd5b8484602083013760006020868301015250509392505050565b600060208284031215611b7d578081fd5b813561061681612584565b60008060408385031215611b9a578081fd5b8235611ba581612584565b91506020830135611bb581612584565b809150509250929050565b600080600060608486031215611bd4578081fd5b8335611bdf81612584565b92506020840135611bef81612584565b929592945050506040919091013590565b60008060008060808587031215611c15578081fd5b8435611c2081612584565b93506020850135611c3081612584565b925060408501359150606085013567ffffffffffffffff811115611c52578182fd5b8501601f81018713611c62578182fd5b611c7187823560208401611afc565b91505092959194509250565b60008060408385031215611c8f578182fd5b8235611c9a81612584565b91506020830135611bb581612599565b60008060408385031215611cbc578182fd5b8235611cc781612584565b946020939093013593505050565b600060208284031215611ce6578081fd5b815161061681612599565b600060208284031215611d02578081fd5b8135610616816125a7565b600060208284031215611d1e578081fd5b8151610616816125a7565b600060208284031215611d3a578081fd5b813567ffffffffffffffff811115611d50578182fd5b8201601f81018413611d60578182fd5b61110684823560208401611afc565b600060208284031215611d80578081fd5b5035919050565b600060208284031215611d98578081fd5b5051919050565b60008151808452611db78160208601602086016124d6565b601f01601f19169290920160200192915050565b60008251611ddd8184602087016124d6565b9190910192915050565b60008351611df98184602088016124d6565b835190830190611e0d8183602088016124d6565b01949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611e5d90830184611d9f565b9695505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602082526106166020830184611d9f565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b6020808252600e908201526d6f6e6c79206f70657261746f727360901b604082015260600190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604082015260600190565b60208082526024908201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526019908201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604082015260600190565b6020808252602c908201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b60208082526038908201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760408201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606082015260800190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604082015269726f206164647265737360b01b606082015260800190565b60208082526022908201527f456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960408201526839903737ba1037bbb760b91b606082015260800190565b6020808252602f908201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60408201526e3732bc34b9ba32b73a103a37b5b2b760891b606082015260800190565b60208082526021908201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656040820152603960f91b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b90815260200190565b6000821982111561245657612456612558565b500190565b600060ff821660ff84168060ff0382111561247857612478612558565b019392505050565b60008261249b57634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156124ba576124ba612558565b500290565b6000828210156124d1576124d1612558565b500390565b60005b838110156124f15781810151838201526020016124d9565b8381111561098e5750506000910152565b60028104600182168061251657607f821691505b6020821081141561253757634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561255157612551612558565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461075d57600080fd5b801515811461075d57600080fd5b6001600160e01b03198116811461075d57600080fdfe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656ea2646970667358221220c4544ed97b534a320897510b3aa009bf2a4de1d4b1f9c881285788d8d305b0a564736f6c63430008000033

Deployed Bytecode Sourcemap

69430:2572:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12750:150;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;53875:100;;;:::i;:::-;;;;;;;:::i;56661:221::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;56191:404::-;;;;;;:::i;:::-;;:::i;:::-;;55669:211;;;:::i;:::-;;;;;;;:::i;57551:305::-;;;;;;:::i;:::-;;:::i;69537:70::-;;;:::i;69616:36::-;;;:::i;55431:162::-;;;;;;:::i;:::-;;:::i;71471:91::-;;;:::i;71063:142::-;;;:::i;57927:151::-;;;;;;:::i;:::-;;:::i;55957:172::-;;;;;;:::i;:::-;;:::i;70926:101::-;;;;;;:::i;:::-;;:::i;53631:177::-;;;;;;:::i;:::-;;:::i;55250:97::-;;;:::i;53348:221::-;;;;;;:::i;:::-;;:::i;68555:148::-;;;:::i;67904:87::-;;;:::i;54044:104::-;;;:::i;56954:295::-;;;;;;:::i;:::-;;:::i;58149:285::-;;;;;;:::i;:::-;;:::i;70027:493::-;;;;;;:::i;:::-;;:::i;54219:792::-;;;;;;:::i;:::-;;:::i;70630:257::-;;;;;;:::i;:::-;;:::i;57320:164::-;;;;;;:::i;:::-;;:::i;69659:32::-;;;:::i;71598:85::-;;;;;;:::i;:::-;;:::i;68858:244::-;;;;;;:::i;:::-;;:::i;71241:183::-;;;;;;:::i;:::-;;:::i;71723:104::-;;;;;;:::i;:::-;;:::i;12750:150::-;-1:-1:-1;;;;;;12859:33:0;;12835:4;12859:33;;;;;;;;;;;;;12750:150;;;;:::o;53875:100::-;53929:13;53962:5;53955:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53875:100;:::o;56661:221::-;56737:7;56765:16;56773:7;56765;:16::i;:::-;56757:73;;;;-1:-1:-1;;;56757:73:0;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;56850:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;56850:24:0;;56661:221::o;56191:404::-;56272:13;56288:23;56303:7;56288:14;:23::i;:::-;56272:39;;56336:5;-1:-1:-1;;;;;56330:11:0;:2;-1:-1:-1;;;;;56330:11:0;;;56322:57;;;;-1:-1:-1;;;56322:57:0;;;;;;;:::i;:::-;56416:5;-1:-1:-1;;;;;56400:21:0;:12;:10;:12::i;:::-;-1:-1:-1;;;;;56400:21:0;;:69;;;;56425:44;56449:5;56456:12;:10;:12::i;56425:44::-;56392:161;;;;-1:-1:-1;;;56392:161:0;;;;;;;:::i;:::-;56566:21;56575:2;56579:7;56566:8;:21::i;:::-;56191:404;;;:::o;55669:211::-;55730:7;55851:21;:12;:19;:21::i;:::-;55844:28;;55669:211;:::o;57551:305::-;57712:41;57731:12;:10;:12::i;:::-;57745:7;57712:18;:41::i;:::-;57704:103;;;;-1:-1:-1;;;57704:103:0;;;;;;;:::i;:::-;57820:28;57830:4;57836:2;57840:7;57820:9;:28::i;69537:70::-;;;-1:-1:-1;;;;;69537:70:0;;:::o;69616:36::-;;;;:::o;55431:162::-;-1:-1:-1;;;;;55555:20:0;;55528:7;55555:20;;;:13;:20;;;;;:30;;55579:5;55555:23;:30::i;:::-;55548:37;;55431:162;;;;;:::o;71471:91::-;68135:12;:10;:12::i;:::-;-1:-1:-1;;;;;68124:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;68124:23:0;;68116:68;;;;-1:-1:-1;;;68116:68:0;;;;;;;:::i;:::-;71542:12:::1;::::0;;-1:-1:-1;;71526:28:0;::::1;71542:12;::::0;;::::1;71541:13;71526:28;::::0;;71471:91::o;71063:142::-;68135:12;:10;:12::i;:::-;-1:-1:-1;;;;;68124:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;68124:23:0;;68116:68;;;;-1:-1:-1;;;68116:68:0;;;;;;;:::i;:::-;71160:37:::1;::::0;71128:21:::1;::::0;71168:10:::1;::::0;71160:37;::::1;;;::::0;71128:21;;71113:12:::1;71160:37:::0;71113:12;71160:37;71128:21;71168:10;71160:37;::::1;;;;;;;;;;;;;::::0;::::1;;;;;;68195:1;71063:142::o:0;57927:151::-;58031:39;58048:4;58054:2;58058:7;58031:39;;;;;;;;;;;;:16;:39::i;55957:172::-;56032:7;;56074:22;:12;56090:5;56074:15;:22::i;:::-;-1:-1:-1;56052:44:0;55957:172;-1:-1:-1;;;55957:172:0:o;70926:101::-;68135:12;:10;:12::i;:::-;-1:-1:-1;;;;;68124:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;68124:23:0;;68116:68;;;;-1:-1:-1;;;68116:68:0;;;;;;;:::i;:::-;70999:20:::1;71011:7;70999:11;:20::i;:::-;70926:101:::0;:::o;53631:177::-;53703:7;53730:70;53747:7;53730:70;;;;;;;;;;;;;;;;;:12;;:70;:16;:70::i;55250:97::-;55298:13;55331:8;55324:15;;;;;:::i;53348:221::-;53420:7;-1:-1:-1;;;;;53448:19:0;;53440:74;;;;-1:-1:-1;;;53440:74:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;53532:20:0;;;;;;:13;:20;;;;;:29;;:27;:29::i;68555:148::-;68135:12;:10;:12::i;:::-;-1:-1:-1;;;;;68124:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;68124:23:0;;68116:68;;;;-1:-1:-1;;;68116:68:0;;;;;;;:::i;:::-;68646:6:::1;::::0;68625:40:::1;::::0;68662:1:::1;::::0;-1:-1:-1;;;;;68646:6:0::1;::::0;68625:40:::1;::::0;68662:1;;68625:40:::1;68676:6;:19:::0;;-1:-1:-1;;;;;;68676:19:0::1;::::0;;68555:148::o;67904:87::-;67977:6;;-1:-1:-1;;;;;67977:6:0;67904:87;:::o;54044:104::-;54100:13;54133:7;54126:14;;;;;:::i;56954:295::-;57069:12;:10;:12::i;:::-;-1:-1:-1;;;;;57057:24:0;:8;-1:-1:-1;;;;;57057:24:0;;;57049:62;;;;-1:-1:-1;;;57049:62:0;;;;;;;:::i;:::-;57169:8;57124:18;:32;57143:12;:10;:12::i;:::-;-1:-1:-1;;;;;57124:32:0;;;;;;;;;;;;;;;;;-1:-1:-1;57124:32:0;;;:42;;;;;;;;;;;;:53;;-1:-1:-1;;57124:53:0;;;;;;;;;;;57208:12;:10;:12::i;:::-;-1:-1:-1;;;;;57193:48:0;;57232:8;57193:48;;;;;;:::i;:::-;;;;;;;;56954:295;;:::o;58149:285::-;58281:41;58300:12;:10;:12::i;:::-;58314:7;58281:18;:41::i;:::-;58273:103;;;;-1:-1:-1;;;58273:103:0;;;;;;;:::i;:::-;58387:39;58401:4;58407:2;58411:7;58420:5;58387:13;:39::i;:::-;58149:285;;;;:::o;70027:493::-;1753:1;2349:7;;:19;;2341:63;;;;-1:-1:-1;;;2341:63:0;;;;;;;:::i;:::-;1753:1;2482:7;:18;70112:12:::1;::::0;::::1;;70104:21;;;::::0;::::1;;70185:2;70167:14;:20;;70159:29;;;::::0;::::1;;70227:3;::::0;70271:14:::1;::::0;-1:-1:-1;;;;;70227:3:0;;::::1;::::0;:16:::1;::::0;70244:10:::1;::::0;70264:4:::1;::::0;70271:34:::1;::::0;70290:14;70271:18:::1;:34::i;:::-;70227:79;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;70219:88;;;::::0;::::1;;70325:6;70320:193;70341:14;70337:1;:18;70320:193;;;70377:11;70391:13;:11;:13::i;:::-;:17;::::0;70407:1:::1;70391:17;:::i;:::-;70377:31;;70428;70440:10;70452:6;70428:31;;;;;;;:::i;:::-;;;;;;;;70476:25;70482:10;70494:6;70476:5;:25::i;:::-;-1:-1:-1::0;70357:3:0;::::1;::::0;::::1;:::i;:::-;;;;70320:193;;;-1:-1:-1::0;;1709:1:0;2661:7;:22;70027:493::o;54219:792::-;54292:13;54326:16;54334:7;54326;:16::i;:::-;54318:76;;;;-1:-1:-1;;;54318:76:0;;;;;;;:::i;:::-;54407:23;54433:19;;;:10;:19;;;;;54407:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54463:18;54484:9;:7;:9::i;:::-;54463:30;;54575:4;54569:18;54591:1;54569:23;54565:72;;;-1:-1:-1;54616:9:0;-1:-1:-1;54609:16:0;;54565:72;54741:23;;:27;54737:108;;54816:4;54822:9;54799:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;54785:48;;;;;;54737:108;54977:4;54983:18;:7;:16;:18::i;:::-;54960:42;;;;;;;;;:::i;:::-;;;;;;;;;;;;;54946:57;;;;54219:792;;;:::o;70630:257::-;1753:1;2349:7;;:19;;2341:63;;;;-1:-1:-1;;;2341:63:0;;;;;;;:::i;:::-;1753:1;2482:7;:18;71949:10:::1;71939:21;::::0;;;:9:::1;:21;::::0;;;;;::::1;;71931:48;;;;-1:-1:-1::0;;;71931:48:0::1;;;;;;;:::i;:::-;70732:6:::2;70727:153;70748:14;70744:1;:18;70727:153;;;70789:34;70801:2;70805:13;:11;:13::i;:::-;:17;::::0;70821:1:::2;70805:17;:::i;:::-;70789:34;;;;;;;:::i;:::-;;;;;;;;70840:28;70846:2;70850:13;:11;:13::i;:::-;:17;::::0;70866:1:::2;70850:17;:::i;:::-;70840:5;:28::i;:::-;70764:3:::0;::::2;::::0;::::2;:::i;:::-;;;;70727:153;;;-1:-1:-1::0;;1709:1:0;2661:7;:22;-1:-1:-1;70630:257:0:o;57320:164::-;-1:-1:-1;;;;;57441:25:0;;;57417:4;57441:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;57320:164::o;69659:32::-;;;;;;:::o;71598:85::-;68135:12;:10;:12::i;:::-;-1:-1:-1;;;;;68124:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;68124:23:0;;68116:68;;;;-1:-1:-1;;;68116:68:0;;;;;;;:::i;:::-;71661:3:::1;:14:::0;;-1:-1:-1;;;;;;71661:14:0::1;-1:-1:-1::0;;;;;71661:14:0;;;::::1;::::0;;;::::1;::::0;;71598:85::o;68858:244::-;68135:12;:10;:12::i;:::-;-1:-1:-1;;;;;68124:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;68124:23:0;;68116:68;;;;-1:-1:-1;;;68116:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;68947:22:0;::::1;68939:73;;;;-1:-1:-1::0;;;68939:73:0::1;;;;;;;:::i;:::-;69049:6;::::0;69028:38:::1;::::0;-1:-1:-1;;;;;69028:38:0;;::::1;::::0;69049:6:::1;::::0;69028:38:::1;::::0;69049:6:::1;::::0;69028:38:::1;69077:6;:17:::0;;-1:-1:-1;;;;;;69077:17:0::1;-1:-1:-1::0;;;;;69077:17:0;;;::::1;::::0;;;::::1;::::0;;68858:244::o;71241:183::-;68135:12;:10;:12::i;:::-;-1:-1:-1;;;;;68124:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;68124:23:0;;68116:68;;;;-1:-1:-1;;;68116:68:0;;;;;;;:::i;:::-;71324:38:::1;::::0;-1:-1:-1;;;71324:38:0;;71309:12:::1;::::0;-1:-1:-1;;;;;71324:23:0;::::1;::::0;::::1;::::0;:38:::1;::::0;71356:4:::1;::::0;71324:38:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71373:43;::::0;-1:-1:-1;;;71373:43:0;;71309:53;;-1:-1:-1;;;;;;71373:22:0;::::1;::::0;::::1;::::0;:43:::1;::::0;71396:10:::1;::::0;71309:53;;71373:43:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;71723:104::-:0;68135:12;:10;:12::i;:::-;-1:-1:-1;;;;;68124:23:0;:7;:5;:7::i;:::-;-1:-1:-1;;;;;68124:23:0;;68116:68;;;;-1:-1:-1;;;68116:68:0;;;;;;;:::i;:::-;71796:14:::1;:23:::0;71723:104::o;59901:127::-;59966:4;59990:30;:12;60012:7;59990:21;:30::i;3373:115::-;3469:10;3373:115;:::o;65919:192::-;65994:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;65994:29:0;-1:-1:-1;;;;;65994:29:0;;;;;;;;:24;;66048:23;65994:24;66048:14;:23::i;:::-;-1:-1:-1;;;;;66039:46:0;;;;;;;;;;;65919:192;;:::o;46669:123::-;46738:7;46765:19;46773:3;46765:7;:19::i;60195:355::-;60288:4;60313:16;60321:7;60313;:16::i;:::-;60305:73;;;;-1:-1:-1;;;60305:73:0;;;;;;;:::i;:::-;60389:13;60405:23;60420:7;60405:14;:23::i;:::-;60389:39;;60458:5;-1:-1:-1;;;;;60447:16:0;:7;-1:-1:-1;;;;;60447:16:0;;:51;;;;60491:7;-1:-1:-1;;;;;60467:31:0;:20;60479:7;60467:11;:20::i;:::-;-1:-1:-1;;;;;60467:31:0;;60447:51;:94;;;;60502:39;60526:5;60533:7;60502:23;:39::i;:::-;60439:103;60195:355;-1:-1:-1;;;;60195:355:0:o;63331:599::-;63456:4;-1:-1:-1;;;;;63429:31:0;:23;63444:7;63429:14;:23::i;:::-;-1:-1:-1;;;;;63429:31:0;;63421:85;;;;-1:-1:-1;;;63421:85:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;63543:16:0;;63535:65;;;;-1:-1:-1;;;63535:65:0;;;;;;;:::i;:::-;63613:39;63634:4;63640:2;63644:7;63613:20;:39::i;:::-;63717:29;63734:1;63738:7;63717:8;:29::i;:::-;-1:-1:-1;;;;;63759:19:0;;;;;;:13;:19;;;;;:35;;63786:7;63759:26;:35::i;:::-;-1:-1:-1;;;;;;63805:17:0;;;;;;:13;:17;;;;;:30;;63827:7;63805:21;:30::i;:::-;-1:-1:-1;63848:29:0;:12;63865:7;63874:2;63848:16;:29::i;:::-;;63914:7;63910:2;-1:-1:-1;;;;;63895:27:0;63904:4;-1:-1:-1;;;;;63895:27:0;;;;;;;;;;;63331:599;;;:::o;38491:137::-;38562:7;38597:22;38601:3;38613:5;38597:3;:22::i;47131:236::-;47211:7;;;;47271:22;47275:3;47287:5;47271:3;:22::i;:::-;47240:53;;;;-1:-1:-1;47131:236:0;-1:-1:-1;;;;;47131:236:0:o;64531:100::-;64604:19;;;;:8;;:19;;;;;:::i;48417:213::-;48524:7;48575:44;48580:3;48600;48606:12;48575:4;:44::i;:::-;48567:53;-1:-1:-1;48417:213:0;;;;;;:::o;59316:272::-;59430:28;59440:4;59446:2;59450:7;59430:9;:28::i;:::-;59477:48;59500:4;59506:2;59510:7;59519:5;59477:22;:48::i;:::-;59469:111;;;;-1:-1:-1;;;59469:111:0;;;;;;;:::i;17160:220::-;17218:7;17242:6;17238:20;;-1:-1:-1;17257:1:0;17250:8;;17238:20;17269:9;17281:5;17285:1;17281;:5;:::i;:::-;17269:17;-1:-1:-1;17314:1:0;17305:5;17309:1;17269:17;17305:5;:::i;:::-;:10;17297:56;;;;-1:-1:-1;;;17297:56:0;;;;;;;:::i;61816:404::-;-1:-1:-1;;;;;61896:16:0;;61888:61;;;;-1:-1:-1;;;61888:61:0;;;;;;;:::i;:::-;61969:16;61977:7;61969;:16::i;:::-;61968:17;61960:58;;;;-1:-1:-1;;;61960:58:0;;;;;;;:::i;:::-;62031:45;62060:1;62064:2;62068:7;62031:20;:45::i;:::-;-1:-1:-1;;;;;62089:17:0;;;;;;:13;:17;;;;;:30;;62111:7;62089:21;:30::i;:::-;-1:-1:-1;62132:29:0;:12;62149:7;62158:2;62132:16;:29::i;:::-;-1:-1:-1;62179:33:0;;62204:7;;-1:-1:-1;;;;;62179:33:0;;;62196:1;;62179:33;;62196:1;;62179:33;61816:404;;:::o;48850:753::-;48903:13;49124:7;49120:50;;-1:-1:-1;49148:10:0;;;;;;;;;;;;-1:-1:-1;;;49148:10:0;;;;;;49120:50;49189:2;49180:6;49221:69;49228:6;;49221:69;;49251:5;;;;:::i;:::-;;-1:-1:-1;49271:7:0;;-1:-1:-1;49276:2:0;49271:7;;:::i;:::-;;;49221:69;;;49300:17;49330:3;49320:14;;;;;;-1:-1:-1;;;49320:14:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49320:14:0;-1:-1:-1;49300:34:0;-1:-1:-1;49354:3:0;49368:198;49375:7;;49368:198;;49403:3;49405:1;49403;:3;:::i;:::-;49399:7;-1:-1:-1;49421:10:0;49451:7;49456:2;49451;:7;:::i;:::-;:12;;49461:2;49451:12;:::i;:::-;49446:17;;:2;:17;:::i;:::-;49435:29;;:2;:29;:::i;:::-;49421:44;;49480:9;49499:4;49492:12;;49480:24;;49529:2;49519:4;49524:1;49519:7;;;;;;-1:-1:-1;;;49519:7:0;;;;;;;;;;;;:12;-1:-1:-1;;;;;49519:12:0;;;;;;;;-1:-1:-1;49546:8:0;49552:2;49546:8;;:::i;:::-;;;49368:198;;;;;-1:-1:-1;49590:4:0;48850:753;-1:-1:-1;;;;48850:753:0:o;46430:151::-;46514:4;46538:35;46548:3;46568;46538:9;:35::i;43248:110::-;43331:19;;43248:110::o;37578:137::-;37648:4;37672:35;37680:3;37700:5;37672:7;:35::i;37271:131::-;37338:4;37362:32;37367:3;37387:5;37362:4;:32::i;45853:185::-;45942:4;45966:64;45971:3;45991;-1:-1:-1;;;;;46005:23:0;;45966:4;:64::i;33529:204::-;33624:18;;33596:7;;33624:26;-1:-1:-1;33616:73:0;;;;-1:-1:-1;;;33616:73:0;;;;;;;:::i;:::-;33707:3;:11;;33719:5;33707:18;;;;;;-1:-1:-1;;;33707:18:0;;;;;;;;;;;;;;;;;33700:25;;33529:204;;;;:::o;43713:279::-;43817:19;;43780:7;;;;43817:27;-1:-1:-1;43809:74:0;;;;-1:-1:-1;;;43809:74:0;;;;;;;:::i;:::-;43896:22;43921:3;:12;;43934:5;43921:19;;;;;;-1:-1:-1;;;43921:19:0;;;;;;;;;;;;;;;;;;;43896:44;;43959:5;:10;;;43971:5;:12;;;43951:33;;;;;43713:279;;;;;:::o;45210:319::-;45304:7;45343:17;;;:12;;;:17;;;;;;45394:12;45379:13;45371:36;;;;-1:-1:-1;;;45371:36:0;;;;;;;;:::i;:::-;-1:-1:-1;45461:3:0;45474:12;45485:1;45474:8;:12;:::i;:::-;45461:26;;;;;;-1:-1:-1;;;45461:26:0;;;;;;;;;;;;;;;;;;;:33;;;45454:40;;;45210:319;;;;;:::o;65196:604::-;65317:4;65344:15;:2;-1:-1:-1;;;;;65344:13:0;;:15::i;:::-;65339:60;;-1:-1:-1;65383:4:0;65376:11;;65339:60;65409:23;65435:252;-1:-1:-1;;;65548:12:0;:10;:12::i;:::-;65575:4;65594:7;65616:5;65451:181;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;;;;;65451:181:0;;;;;;;-1:-1:-1;;;;;65451:181:0;;;;;;;;;;;65435:252;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;65435:15:0;;;:252;:15;:252::i;:::-;65409:278;;65698:13;65725:10;65714:32;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;65765:26:0;-1:-1:-1;;;65765:26:0;;-1:-1:-1;;;65196:604:0;;;;;;:::o;43028:125::-;43099:4;43123:17;;;:12;;;;;:17;;;;;;:22;;;43028:125::o;31231:1544::-;31297:4;31436:19;;;:12;;;:19;;;;;;31472:15;;31468:1300;;31834:21;31858:14;31871:1;31858:10;:14;:::i;:::-;31907:18;;31834:38;;-1:-1:-1;31887:17:0;;31907:22;;31928:1;;31907:22;:::i;:::-;31887:42;;32174:17;32194:3;:11;;32206:9;32194:22;;;;;;-1:-1:-1;;;32194:22:0;;;;;;;;;;;;;;;;;32174:42;;32340:9;32311:3;:11;;32323:13;32311:26;;;;;;-1:-1:-1;;;32311:26:0;;;;;;;;;;;;;;;;;;:38;32443:17;:13;32459:1;32443:17;:::i;:::-;32417:23;;;;:12;;;:23;;;;;:43;32569:17;;32417:3;;32569:17;;;-1:-1:-1;;;32569:17:0;;;;;;;;;;;;;;;;;;;;;;;;;;32664:3;:12;;:19;32677:5;32664:19;;;;;;;;;;;32657:26;;;32707:4;32700:11;;;;;;;;31468:1300;32751:5;32744:12;;;;;30641:414;30704:4;30726:21;30736:3;30741:5;30726:9;:21::i;:::-;30721:327;;-1:-1:-1;30764:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;30947:18;;30925:19;;;:12;;;:19;;;;;;:40;;;;30980:11;;30721:327;-1:-1:-1;31031:5:0;31024:12;;40528:692;40604:4;40739:17;;;:12;;;:17;;;;;;40773:13;40769:444;;-1:-1:-1;;40858:38:0;;;;;;;;;;;;;;;;;;40840:57;;;;;;;;:12;:57;;;;;;;;;;;;;;;;;;;;;;;;41055:19;;41035:17;;;:12;;;:17;;;;;;;:39;41089:11;;40769:444;41169:5;41133:3;41146:12;41157:1;41146:8;:12;:::i;:::-;41133:26;;;;;;-1:-1:-1;;;41133:26:0;;;;;;;;;;;;;;;;;;;:33;;:41;;;;41196:5;41189:12;;;;;21691:422;22058:20;22097:8;;;21691:422::o;24609:195::-;24712:12;24744:52;24766:6;24774:4;24780:1;24783:12;24712;25913:18;25924:6;25913:10;:18::i;:::-;25905:60;;;;-1:-1:-1;;;25905:60:0;;;;;;;:::i;:::-;26039:12;26053:23;26080:6;-1:-1:-1;;;;;26080:11:0;26100:5;26108:4;26080:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26038:75;;;;26131:52;26149:7;26158:10;26170:12;26131:17;:52::i;:::-;26124:59;25661:530;-1:-1:-1;;;;;;;25661:530:0:o;28201:742::-;28316:12;28345:7;28341:595;;;-1:-1:-1;28376:10:0;28369:17;;28341:595;28490:17;;:21;28486:439;;28753:10;28747:17;28814:15;28801:10;28797:2;28793:19;28786:44;28701:148;28896:12;28889:20;;-1:-1:-1;;;28889:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:607:1;;110:18;151:2;143:6;140:14;137:2;;;157:18;;:::i;:::-;206:2;200:9;279:2;256:17;;-1:-1:-1;;252:31:1;240:44;;286:4;236:55;306:18;;;326:22;;;303:46;300:2;;;352:18;;:::i;:::-;388:2;381:22;436;;;421:6;-1:-1:-1;421:6:1;473:16;;;470:25;-1:-1:-1;467:2:1;;;508:1;505;498:12;467:2;558:6;553:3;546:4;538:6;534:17;521:44;613:1;606:4;597:6;589;585:19;581:30;574:41;;;90:531;;;;;:::o;626:259::-;;738:2;726:9;717:7;713:23;709:32;706:2;;;759:6;751;744:22;706:2;803:9;790:23;822:33;849:5;822:33;:::i;890:402::-;;;1019:2;1007:9;998:7;994:23;990:32;987:2;;;1040:6;1032;1025:22;987:2;1084:9;1071:23;1103:33;1130:5;1103:33;:::i;:::-;1155:5;-1:-1:-1;1212:2:1;1197:18;;1184:32;1225:35;1184:32;1225:35;:::i;:::-;1279:7;1269:17;;;977:315;;;;;:::o;1297:470::-;;;;1443:2;1431:9;1422:7;1418:23;1414:32;1411:2;;;1464:6;1456;1449:22;1411:2;1508:9;1495:23;1527:33;1554:5;1527:33;:::i;:::-;1579:5;-1:-1:-1;1636:2:1;1621:18;;1608:32;1649:35;1608:32;1649:35;:::i;:::-;1401:366;;1703:7;;-1:-1:-1;;;1757:2:1;1742:18;;;;1729:32;;1401:366::o;1772:830::-;;;;;1944:3;1932:9;1923:7;1919:23;1915:33;1912:2;;;1966:6;1958;1951:22;1912:2;2010:9;1997:23;2029:33;2056:5;2029:33;:::i;:::-;2081:5;-1:-1:-1;2138:2:1;2123:18;;2110:32;2151:35;2110:32;2151:35;:::i;:::-;2205:7;-1:-1:-1;2259:2:1;2244:18;;2231:32;;-1:-1:-1;2314:2:1;2299:18;;2286:32;2341:18;2330:30;;2327:2;;;2378:6;2370;2363:22;2327:2;2406:22;;2459:4;2451:13;;2447:27;-1:-1:-1;2437:2:1;;2493:6;2485;2478:22;2437:2;2521:75;2588:7;2583:2;2570:16;2565:2;2561;2557:11;2521:75;:::i;:::-;2511:85;;;1902:700;;;;;;;:::o;2607:396::-;;;2733:2;2721:9;2712:7;2708:23;2704:32;2701:2;;;2754:6;2746;2739:22;2701:2;2798:9;2785:23;2817:33;2844:5;2817:33;:::i;:::-;2869:5;-1:-1:-1;2926:2:1;2911:18;;2898:32;2939;2898;2939;:::i;3008:327::-;;;3137:2;3125:9;3116:7;3112:23;3108:32;3105:2;;;3158:6;3150;3143:22;3105:2;3202:9;3189:23;3221:33;3248:5;3221:33;:::i;:::-;3273:5;3325:2;3310:18;;;;3297:32;;-1:-1:-1;;;3095:240:1:o;3340:257::-;;3460:2;3448:9;3439:7;3435:23;3431:32;3428:2;;;3481:6;3473;3466:22;3428:2;3518:9;3512:16;3537:30;3561:5;3537:30;:::i;3602:257::-;;3713:2;3701:9;3692:7;3688:23;3684:32;3681:2;;;3734:6;3726;3719:22;3681:2;3778:9;3765:23;3797:32;3823:5;3797:32;:::i;3864:261::-;;3986:2;3974:9;3965:7;3961:23;3957:32;3954:2;;;4007:6;3999;3992:22;3954:2;4044:9;4038:16;4063:32;4089:5;4063:32;:::i;4409:482::-;;4531:2;4519:9;4510:7;4506:23;4502:32;4499:2;;;4552:6;4544;4537:22;4499:2;4597:9;4584:23;4630:18;4622:6;4619:30;4616:2;;;4667:6;4659;4652:22;4616:2;4695:22;;4748:4;4740:13;;4736:27;-1:-1:-1;4726:2:1;;4782:6;4774;4767:22;4726:2;4810:75;4877:7;4872:2;4859:16;4854:2;4850;4846:11;4810:75;:::i;4896:190::-;;5008:2;4996:9;4987:7;4983:23;4979:32;4976:2;;;5029:6;5021;5014:22;4976:2;-1:-1:-1;5057:23:1;;4966:120;-1:-1:-1;4966:120:1:o;5091:194::-;;5214:2;5202:9;5193:7;5189:23;5185:32;5182:2;;;5235:6;5227;5220:22;5182:2;-1:-1:-1;5263:16:1;;5172:113;-1:-1:-1;5172:113:1:o;5290:259::-;;5371:5;5365:12;5398:6;5393:3;5386:19;5414:63;5470:6;5463:4;5458:3;5454:14;5447:4;5440:5;5436:16;5414:63;:::i;:::-;5531:2;5510:15;-1:-1:-1;;5506:29:1;5497:39;;;;5538:4;5493:50;;5341:208;-1:-1:-1;;5341:208:1:o;5554:274::-;;5721:6;5715:13;5737:53;5783:6;5778:3;5771:4;5763:6;5759:17;5737:53;:::i;:::-;5806:16;;;;;5691:137;-1:-1:-1;;5691:137:1:o;5833:470::-;;6050:6;6044:13;6066:53;6112:6;6107:3;6100:4;6092:6;6088:17;6066:53;:::i;:::-;6182:13;;6141:16;;;;6204:57;6182:13;6141:16;6238:4;6226:17;;6204:57;:::i;:::-;6277:20;;6020:283;-1:-1:-1;;;;6020:283:1:o;6308:203::-;-1:-1:-1;;;;;6472:32:1;;;;6454:51;;6442:2;6427:18;;6409:102::o;6516:506::-;-1:-1:-1;;;;;6801:15:1;;;6783:34;;6853:15;;6848:2;6833:18;;6826:43;6900:2;6885:18;;6878:34;;;6948:3;6943:2;6928:18;;6921:31;;;6516:506;;6969:47;;6996:19;;6988:6;6969:47;:::i;:::-;6961:55;6735:287;-1:-1:-1;;;;;;6735:287:1:o;7027:375::-;-1:-1:-1;;;;;7285:15:1;;;7267:34;;7337:15;;;;7332:2;7317:18;;7310:43;7384:2;7369:18;;7362:34;;;;7217:2;7202:18;;7184:218::o;7407:274::-;-1:-1:-1;;;;;7599:32:1;;;;7581:51;;7663:2;7648:18;;7641:34;7569:2;7554:18;;7536:145::o;7686:187::-;7851:14;;7844:22;7826:41;;7814:2;7799:18;;7781:92::o;8101:221::-;;8250:2;8239:9;8232:21;8270:46;8312:2;8301:9;8297:18;8289:6;8270:46;:::i;8327:398::-;8529:2;8511:21;;;8568:2;8548:18;;;8541:30;8607:34;8602:2;8587:18;;8580:62;-1:-1:-1;;;8673:2:1;8658:18;;8651:32;8715:3;8700:19;;8501:224::o;8730:338::-;8932:2;8914:21;;;8971:2;8951:18;;;8944:30;-1:-1:-1;;;9005:2:1;8990:18;;8983:44;9059:2;9044:18;;8904:164::o;9073:414::-;9275:2;9257:21;;;9314:2;9294:18;;;9287:30;9353:34;9348:2;9333:18;;9326:62;-1:-1:-1;;;9419:2:1;9404:18;;9397:48;9477:3;9462:19;;9247:240::o;9492:402::-;9694:2;9676:21;;;9733:2;9713:18;;;9706:30;9772:34;9767:2;9752:18;;9745:62;-1:-1:-1;;;9838:2:1;9823:18;;9816:36;9884:3;9869:19;;9666:228::o;9899:352::-;10101:2;10083:21;;;10140:2;10120:18;;;10113:30;10179;10174:2;10159:18;;10152:58;10242:2;10227:18;;10073:178::o;10256:400::-;10458:2;10440:21;;;10497:2;10477:18;;;10470:30;10536:34;10531:2;10516:18;;10509:62;-1:-1:-1;;;10602:2:1;10587:18;;10580:34;10646:3;10631:19;;10430:226::o;10661:349::-;10863:2;10845:21;;;10902:2;10882:18;;;10875:30;10941:27;10936:2;10921:18;;10914:55;11001:2;10986:18;;10835:175::o;11422:408::-;11624:2;11606:21;;;11663:2;11643:18;;;11636:30;11702:34;11697:2;11682:18;;11675:62;-1:-1:-1;;;11768:2:1;11753:18;;11746:42;11820:3;11805:19;;11596:234::o;11835:420::-;12037:2;12019:21;;;12076:2;12056:18;;;12049:30;12115:34;12110:2;12095:18;;12088:62;12186:26;12181:2;12166:18;;12159:54;12245:3;12230:19;;12009:246::o;12260:406::-;12462:2;12444:21;;;12501:2;12481:18;;;12474:30;12540:34;12535:2;12520:18;;12513:62;-1:-1:-1;;;12606:2:1;12591:18;;12584:40;12656:3;12641:19;;12434:232::o;12671:398::-;12873:2;12855:21;;;12912:2;12892:18;;;12885:30;12951:34;12946:2;12931:18;;12924:62;-1:-1:-1;;;13017:2:1;13002:18;;12995:32;13059:3;13044:19;;12845:224::o;13074:356::-;13276:2;13258:21;;;13295:18;;;13288:30;13354:34;13349:2;13334:18;;13327:62;13421:2;13406:18;;13248:182::o;13435:397::-;13637:2;13619:21;;;13676:2;13656:18;;;13649:30;13715:34;13710:2;13695:18;;13688:62;-1:-1:-1;;;13781:2:1;13766:18;;13759:31;13822:3;13807:19;;13609:223::o;13837:408::-;14039:2;14021:21;;;14078:2;14058:18;;;14051:30;14117:34;14112:2;14097:18;;14090:62;-1:-1:-1;;;14183:2:1;14168:18;;14161:42;14235:3;14220:19;;14011:234::o;14250:356::-;14452:2;14434:21;;;14471:18;;;14464:30;14530:34;14525:2;14510:18;;14503:62;14597:2;14582:18;;14424:182::o;14611:405::-;14813:2;14795:21;;;14852:2;14832:18;;;14825:30;14891:34;14886:2;14871:18;;14864:62;-1:-1:-1;;;14957:2:1;14942:18;;14935:39;15006:3;14991:19;;14785:231::o;15021:411::-;15223:2;15205:21;;;15262:2;15242:18;;;15235:30;15301:34;15296:2;15281:18;;15274:62;-1:-1:-1;;;15367:2:1;15352:18;;15345:45;15422:3;15407:19;;15195:237::o;15437:397::-;15639:2;15621:21;;;15678:2;15658:18;;;15651:30;15717:34;15712:2;15697:18;;15690:62;-1:-1:-1;;;15783:2:1;15768:18;;15761:31;15824:3;15809:19;;15611:223::o;15839:413::-;16041:2;16023:21;;;16080:2;16060:18;;;16053:30;16119:34;16114:2;16099:18;;16092:62;-1:-1:-1;;;16185:2:1;16170:18;;16163:47;16242:3;16227:19;;16013:239::o;16257:353::-;16459:2;16441:21;;;16498:2;16478:18;;;16471:30;16537:31;16532:2;16517:18;;16510:59;16601:2;16586:18;;16431:179::o;16615:355::-;16817:2;16799:21;;;16856:2;16836:18;;;16829:30;16895:33;16890:2;16875:18;;16868:61;16961:2;16946:18;;16789:181::o;16975:177::-;17121:25;;;17109:2;17094:18;;17076:76::o;17157:128::-;;17228:1;17224:6;17221:1;17218:13;17215:2;;;17234:18;;:::i;:::-;-1:-1:-1;17270:9:1;;17205:80::o;17290:204::-;;17364:4;17361:1;17357:12;17396:4;17393:1;17389:12;17431:3;17425:4;17421:14;17416:3;17413:23;17410:2;;;17439:18;;:::i;:::-;17475:13;;17336:158;-1:-1:-1;;;17336:158:1:o;17499:217::-;;17565:1;17555:2;;-1:-1:-1;;;17590:31:1;;17644:4;17641:1;17634:15;17672:4;17597:1;17662:15;17555:2;-1:-1:-1;17701:9:1;;17545:171::o;17721:168::-;;17827:1;17823;17819:6;17815:14;17812:1;17809:21;17804:1;17797:9;17790:17;17786:45;17783:2;;;17834:18;;:::i;:::-;-1:-1:-1;17874:9:1;;17773:116::o;17894:125::-;;17962:1;17959;17956:8;17953:2;;;17967:18;;:::i;:::-;-1:-1:-1;18004:9:1;;17943:76::o;18024:258::-;18096:1;18106:113;18120:6;18117:1;18114:13;18106:113;;;18196:11;;;18190:18;18177:11;;;18170:39;18142:2;18135:10;18106:113;;;18237:6;18234:1;18231:13;18228:2;;;-1:-1:-1;;18272:1:1;18254:16;;18247:27;18077:205::o;18287:380::-;18372:1;18362:12;;18419:1;18409:12;;;18430:2;;18484:4;18476:6;18472:17;18462:27;;18430:2;18537;18529:6;18526:14;18506:18;18503:38;18500:2;;;18583:10;18578:3;18574:20;18571:1;18564:31;18618:4;18615:1;18608:15;18646:4;18643:1;18636:15;18500:2;;18342:325;;;:::o;18672:135::-;;-1:-1:-1;;18732:17:1;;18729:2;;;18752:18;;:::i;:::-;-1:-1:-1;18799:1:1;18788:13;;18719:88::o;18812:127::-;18873:10;18868:3;18864:20;18861:1;18854:31;18904:4;18901:1;18894:15;18928:4;18925:1;18918:15;18944:127;19005:10;19000:3;18996:20;18993:1;18986:31;19036:4;19033:1;19026:15;19060:4;19057:1;19050:15;19076:133;-1:-1:-1;;;;;19153:31:1;;19143:42;;19133:2;;19199:1;19196;19189:12;19214:120;19302:5;19295:13;19288:21;19281:5;19278:32;19268:2;;19324:1;19321;19314:12;19339:133;-1:-1:-1;;;;;;19415:32:1;;19405:43;;19395:2;;19462:1;19459;19452:12

Swarm Source

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