ETH Price: $3,398.13 (+1.50%)

Token

LOOTaDOG Pass Card (LADT)
 

Overview

Max Total Supply

3,302 LADT

Holders

3,302

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
wirelessfi.eth
Balance
1 LADT
0x1390136b4d5a431d1c6499644cf18037df2f5148
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
LOOTaDOG

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 18 : LOOTaDOG.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;
import "./ERC3525.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";

contract LOOTaDOG is ERC3525, Ownable, Pausable {
    bool private _allow_transfer;
    bool private _allow_transfer_value;

    address private _signer;
    mapping(uint256 => bool) private _order_ids;
    string private _baseTokenURI;
    uint256 private _token_count_limit;
    /* Represents an un-minted NFT, which has not yet been recorded into the blockchain. A signed voucher can be redeemed for a real NFT using the redeem function. */
    struct Voucher {
        uint256 id;
        /* The tokenId  */
        uint256 tokenId;
        /* The amount  */
        uint256 amount;
        /*expiration Time*/
        uint256 expirationTime;
        /*owner*/
        address owner;
    }

    constructor() ERC3525("LOOTaDOG Pass Card", "LADT", 2) {
        _allow_transfer = false;
        _allow_transfer_value = false;
        _signer = msg.sender;
        _token_count_limit = 1000;
    }

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

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

    function queryId(uint256 id) public view returns (bool) {
        return _order_ids[id];
    }

    function blockId(uint256 id) public {
        _order_ids[id] = true;
    }

    function pause() public onlyOwner {
        _pause();
    }

    function unpause() public onlyOwner {
        _unpause();
    }

    function mintToken(
        uint256 id,
        uint256 amount,
        uint256 expirationTime,
        address owner,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public payable whenNotPaused {
        require(block.timestamp < expirationTime, "Expired voucher");
        require(totalSupply() < _token_count_limit, "Sold out");
        require(balanceOf(msg.sender) == 0, "Already minted");
        require(_order_ids[id] == false, "Duplicate id");
        require(owner == msg.sender, "Invalid owner");
        _verifySign(Voucher(id, 0, amount, expirationTime, owner), v, r, s);
        _mint(msg.sender, 1, amount);
        _order_ids[id] = true;
    }

    function mintValue(
        uint256 id,
        uint256 tokenId,
        uint256 amount,
        uint256 expirationTime,
        address owner,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public payable whenNotPaused {
        require(block.timestamp < expirationTime, "Expired voucher");
        require(_order_ids[id] == false, "Duplicate id");
        require(owner == msg.sender, "Invalid owner");
        require(amount > 0, "Invalid amount");
        _verifySign(Voucher(id, tokenId, amount, expirationTime, owner), v, r, s);
        _mintValue(tokenId, amount);
        _order_ids[id] = true;
    }

    function transferFrom(
        uint256 fromTokenId_,
        address to_,
        uint256 value_
    ) public payable virtual override whenNotPaused returns (uint256) {
        require(_allow_transfer_value, "Value does not allow transfer");
        return super.transferFrom(fromTokenId_, to_, value_);
    }

    function transferFrom(
        uint256 fromTokenId_,
        uint256 toTokenId_,
        uint256 value_
    ) public payable virtual override whenNotPaused {
        super.transferFrom(fromTokenId_, toTokenId_, value_);
    }

    function transferFrom(
        address from_,
        address to_,
        uint256 tokenId_
    ) public payable virtual override whenNotPaused {
        require(_allow_transfer, "Token does not allow transfer");
        super.transferFrom(from_, to_, tokenId_);
    }

    function safeTransferFrom(
        address from_,
        address to_,
        uint256 tokenId_,
        bytes memory data_
    ) public payable virtual override whenNotPaused {
        require(_allow_transfer, "Token does not allow transfer");
        super.safeTransferFrom(from_, to_, tokenId_, data_);
    }

    function safeTransferFrom(
        address from_,
        address to_,
        uint256 tokenId_
    ) public payable virtual override whenNotPaused {
        require(_allow_transfer, "Token does not allow transfer");
        super.safeTransferFrom(from_, to_, tokenId_);
    }

    function setTokenCountLimit(uint256 count) public onlyOwner {
        _token_count_limit = count;
    }

    function getTokenCountLimit() public view returns (uint256) {
        return _token_count_limit;
    }

    function setSigner(address addr) public onlyOwner {
        _signer = addr;
    }

    function getSigner() public view returns (address) {
        return _signer;
    }

    bytes32 private constant salt = 0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558;
    //string private constant EIP712_DOMAIN ="EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)";
    bytes32 private constant EIP712_DOMAIN_TYPEHASH =
        0xd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472; //keccak256(bytes(EIP712_DOMAIN));

    //string private constant VOUCHER_TYPE =
    //"Voucher(uint256 id,uint256 tokenId,uint256 amount,uint256 expirationTime,address owner)";
    bytes32 private constant VOUCHER_TYPEHASH = 0x4bd317336ea30fdfa31168cda381dacdf9ed1dd92eda94108d28629b6cf9b8c7; //keccak256(bytes(VOUCHER_TYPEHASH));

    function _verifySign(
        Voucher memory voucher,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal view {
        address signer = ecrecover(_hashVoucher(voucher), v, r, s);
        require(_signer == signer, "Invalid signer");
    }

    /// @notice Returns a hash of the given NFTVoucher, prepared using EIP712 typed data hashing rules.
    /// @param voucher An NFTVoucher describing an unminted NFT.
    function _hashVoucher(Voucher memory voucher) internal view returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", _hashDomainSeparator(), _encodeVoucher(voucher)));
    }

    function _encodeVoucher(Voucher memory voucher) internal pure returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    VOUCHER_TYPEHASH,
                    voucher.id,
                    voucher.tokenId,
                    voucher.amount,
                    voucher.expirationTime,
                    voucher.owner
                )
            );
    }

    function _hashDomainSeparator() internal view returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    EIP712_DOMAIN_TYPEHASH,
                    keccak256(bytes("LOOTaDOG Dapp")),
                    keccak256(bytes("1")),
                    _getChainID(),
                    address(this),
                    salt
                )
            );
    }

    /*Since v0.5.12, Solidity provides a CHAINID OPCODE in assembly */
    function _getChainID() internal view returns (uint256) {
        return block.chainid;
    }
}

File 2 of 18 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.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() {
        _transferOwnership(_msgSender());
    }

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

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

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

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

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

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

File 3 of 18 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 4 of 18 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

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

        return account.code.length > 0;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

File 5 of 18 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

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

File 6 of 18 : Counters.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

File 7 of 18 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

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

File 8 of 18 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

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

File 9 of 18 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

File 10 of 18 : ERC3525.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "./IERC721.sol";
import "./IERC3525.sol";
import "./IERC721Receiver.sol";
import "./IERC3525Receiver.sol";
import "./extensions/IERC721Enumerable.sol";
import "./extensions/IERC721Metadata.sol";
import "./extensions/IERC3525Metadata.sol";
import "./periphery/interface/IERC3525MetadataDescriptor.sol";

contract ERC3525 is Context, IERC3525Metadata, IERC721Enumerable {
    using Strings for address;
    using Strings for uint256;
    using Address for address;
    using Counters for Counters.Counter;

    event SetMetadataDescriptor(address indexed metadataDescriptor);

    struct TokenData {
        uint256 id;
        uint256 slot;
        uint256 balance;
        address owner;
        address approved;
        address[] valueApprovals;
    }

    struct AddressData {
        uint256[] ownedTokens;
        mapping(uint256 => uint256) ownedTokensIndex;
        mapping(address => bool) approvals;
    }

    string private _name;
    string private _symbol;
    uint8 private _decimals;
    Counters.Counter private _tokenIdGenerator;

    // id => (approval => allowance)
    // @dev _approvedValues cannot be defined within TokenData, cause struct containing mappings cannot be constructed.
    mapping(uint256 => mapping(address => uint256)) private _approvedValues;

    TokenData[] private _allTokens;

    // key: id
    mapping(uint256 => uint256) private _allTokensIndex;

    mapping(address => AddressData) private _addressData;

    IERC3525MetadataDescriptor public metadataDescriptor;

    constructor(string memory name_, string memory symbol_, uint8 decimals_) {
         _name = name_;
        _symbol = symbol_;
        _decimals = decimals_;
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return
            interfaceId == type(IERC165).interfaceId ||
            interfaceId == type(IERC3525).interfaceId ||
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC3525Metadata).interfaceId ||
            interfaceId == type(IERC721Enumerable).interfaceId || 
            interfaceId == type(IERC721Metadata).interfaceId;
    }

    /**
     * @dev Returns the token collection name.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals the token uses for value.
     */
    function valueDecimals() public view virtual override returns (uint8) {
        return _decimals;
    }

    function balanceOf(uint256 tokenId_) public view virtual override returns (uint256) {
        _requireMinted(tokenId_);
        return _allTokens[_allTokensIndex[tokenId_]].balance;
    }

    function ownerOf(uint256 tokenId_) public view virtual override returns (address owner_) {
        _requireMinted(tokenId_);
        owner_ = _allTokens[_allTokensIndex[tokenId_]].owner;
        require(owner_ != address(0), "ERC3525: invalid token ID");
    }

    function slotOf(uint256 tokenId_) public view virtual override returns (uint256) {
        _requireMinted(tokenId_);
        return _allTokens[_allTokensIndex[tokenId_]].slot;
    }

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

    function contractURI() public view virtual override returns (string memory) {
        string memory baseURI = _baseURI();
        return 
            address(metadataDescriptor) != address(0) ? 
                metadataDescriptor.constructContractURI() :
                bytes(baseURI).length > 0 ? 
                    string(abi.encodePacked(baseURI, "contract/", Strings.toHexString(address(this)))) : 
                    "";
    }

    function slotURI(uint256 slot_) public view virtual override returns (string memory) {
        string memory baseURI = _baseURI();
        return 
            address(metadataDescriptor) != address(0) ? 
                metadataDescriptor.constructSlotURI(slot_) : 
                bytes(baseURI).length > 0 ? 
                    string(abi.encodePacked(baseURI, "slot/", slot_.toString())) : 
                    "";
    }

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId_) public view virtual override returns (string memory) {
        _requireMinted(tokenId_);
        string memory baseURI = _baseURI();
        return 
            address(metadataDescriptor) != address(0) ? 
                metadataDescriptor.constructTokenURI(tokenId_) : 
                bytes(baseURI).length > 0 ? 
                    string(abi.encodePacked(baseURI, tokenId_.toString())) : 
                    "";
    }

    function approve(uint256 tokenId_, address to_, uint256 value_) public payable virtual override {
        address owner = ERC3525.ownerOf(tokenId_);
        require(to_ != owner, "ERC3525: approval to current owner");

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

        _approveValue(tokenId_, to_, value_);
    }

    function allowance(uint256 tokenId_, address operator_) public view virtual override returns (uint256) {
        _requireMinted(tokenId_);
        return _approvedValues[tokenId_][operator_];
    }

    function transferFrom(
        uint256 fromTokenId_,
        address to_,
        uint256 value_
    ) public payable virtual override returns (uint256) {
        _spendAllowance(_msgSender(), fromTokenId_, value_);

        uint256 newTokenId = _createDerivedTokenId(fromTokenId_);
        _mint(to_, newTokenId, ERC3525.slotOf(fromTokenId_), 0);
        _transferValue(fromTokenId_, newTokenId, value_);

        return newTokenId;
    }

    function transferFrom(
        uint256 fromTokenId_,
        uint256 toTokenId_,
        uint256 value_
    ) public payable virtual override {
        _spendAllowance(_msgSender(), fromTokenId_, value_);
        _transferValue(fromTokenId_, toTokenId_, value_);
    }

    function balanceOf(address owner_) public view virtual override returns (uint256 balance) {
        require(owner_ != address(0), "ERC3525: balance query for the zero address");
        return _addressData[owner_].ownedTokens.length;
    }

    function transferFrom(
        address from_,
        address to_,
        uint256 tokenId_
    ) public payable virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId_), "ERC3525: transfer caller is not owner nor approved");
        _transferTokenId(from_, to_, tokenId_);
    }

    function safeTransferFrom(
        address from_,
        address to_,
        uint256 tokenId_,
        bytes memory data_
    ) public payable virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId_), "ERC3525: transfer caller is not owner nor approved");
        _safeTransferTokenId(from_, to_, tokenId_, data_);
    }

    function safeTransferFrom(
        address from_,
        address to_,
        uint256 tokenId_
    ) public payable virtual override {
        safeTransferFrom(from_, to_, tokenId_, "");
    }

    function approve(address to_, uint256 tokenId_) public payable virtual override {
        address owner = ERC3525.ownerOf(tokenId_);
        require(to_ != owner, "ERC3525: approval to current owner");

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

        _approve(to_, tokenId_);
    }

    function getApproved(uint256 tokenId_) public view virtual override returns (address) {
        _requireMinted(tokenId_);
        return _allTokens[_allTokensIndex[tokenId_]].approved;
    }

    function setApprovalForAll(address operator_, bool approved_) public virtual override {
        _setApprovalForAll(_msgSender(), operator_, approved_);
    }

    function isApprovedForAll(address owner_, address operator_) public view virtual override returns (bool) {
        return _addressData[owner_].approvals[operator_];
    }

    function totalSupply() public view virtual override returns (uint256) {
        return _allTokens.length;
    }

    function tokenByIndex(uint256 index_) public view virtual override returns (uint256) {
        require(index_ < ERC3525.totalSupply(), "ERC3525: global index out of bounds");
        return _allTokens[index_].id;
    }

    function tokenOfOwnerByIndex(address owner_, uint256 index_) public view virtual override returns (uint256) {
        require(index_ < ERC3525.balanceOf(owner_), "ERC3525: owner index out of bounds");
        return _addressData[owner_].ownedTokens[index_];
    }

    function _setApprovalForAll(
        address owner_,
        address operator_,
        bool approved_
    ) internal virtual {
        require(owner_ != operator_, "ERC3525: approve to caller");

        _addressData[owner_].approvals[operator_] = approved_;

        emit ApprovalForAll(owner_, operator_, approved_);
    }

    function _isApprovedOrOwner(address operator_, uint256 tokenId_) internal view virtual returns (bool) {
        _requireMinted(tokenId_);
        address owner = ERC3525.ownerOf(tokenId_);
        return (
            operator_ == owner ||
            ERC3525.isApprovedForAll(owner, operator_) ||
            ERC3525.getApproved(tokenId_) == operator_
        );
    }

    function _spendAllowance(address operator_, uint256 tokenId_, uint256 value_) internal virtual {
        uint256 currentAllowance = ERC3525.allowance(tokenId_, operator_);
        if (!_isApprovedOrOwner(operator_, tokenId_) && currentAllowance != type(uint256).max) {
            require(currentAllowance >= value_, "ERC3525: insufficient allowance");
            _approveValue(tokenId_, operator_, currentAllowance - value_);
        }
    }

    function _exists(uint256 tokenId_) internal view virtual returns (bool) {
        return _allTokens.length != 0 && _allTokens[_allTokensIndex[tokenId_]].id == tokenId_;
    }

    function _requireMinted(uint256 tokenId_) internal view virtual {
        require(_exists(tokenId_), "ERC3525: invalid token ID");
    }

    function _mint(address to_, uint256 slot_, uint256 value_) internal virtual returns (uint256) {
        uint256 tokenId = _createOriginalTokenId();
        _mint(to_, tokenId, slot_, value_);  
        return tokenId;
    }

    function _mint(address to_, uint256 tokenId_, uint256 slot_, uint256 value_) internal virtual {
        require(to_ != address(0), "ERC3525: mint to the zero address");
        require(tokenId_ != 0, "ERC3525: cannot mint zero tokenId");
        require(!_exists(tokenId_), "ERC3525: token already minted");

        _beforeValueTransfer(address(0), to_, 0, tokenId_, slot_, value_);
        __mintToken(to_, tokenId_, slot_);
        __mintValue(tokenId_, value_);
        _afterValueTransfer(address(0), to_, 0, tokenId_, slot_, value_);
    }

    function _mintValue(uint256 tokenId_, uint256 value_) internal virtual {
        _requireMinted(tokenId_);

        address owner = ERC3525.ownerOf(tokenId_);
        uint256 slot = ERC3525.slotOf(tokenId_);
        _beforeValueTransfer(address(0), owner, 0, tokenId_, slot, value_);
        __mintValue(tokenId_, value_);
        _afterValueTransfer(address(0), owner, 0, tokenId_, slot, value_);
    }

    function __mintValue(uint256 tokenId_, uint256 value_) private {
        _allTokens[_allTokensIndex[tokenId_]].balance += value_;
        emit TransferValue(0, tokenId_, value_);
    }

    function __mintToken(address to_, uint256 tokenId_, uint256 slot_) private {
        TokenData memory tokenData = TokenData({
            id: tokenId_,
            slot: slot_,
            balance: 0,
            owner: to_,
            approved: address(0),
            valueApprovals: new address[](0)
        });

        _addTokenToAllTokensEnumeration(tokenData);
        _addTokenToOwnerEnumeration(to_, tokenId_);

        emit Transfer(address(0), to_, tokenId_);
        emit SlotChanged(tokenId_, 0, slot_);
    }

    function _burn(uint256 tokenId_) internal virtual {
        _requireMinted(tokenId_);

        TokenData storage tokenData = _allTokens[_allTokensIndex[tokenId_]];
        address owner = tokenData.owner;
        uint256 slot = tokenData.slot;
        uint256 value = tokenData.balance;

        _beforeValueTransfer(owner, address(0), tokenId_, 0, slot, value);

        _clearApprovedValues(tokenId_);
        _removeTokenFromOwnerEnumeration(owner, tokenId_);
        _removeTokenFromAllTokensEnumeration(tokenId_);

        emit TransferValue(tokenId_, 0, value);
        emit SlotChanged(tokenId_, slot, 0);
        emit Transfer(owner, address(0), tokenId_);

        _afterValueTransfer(owner, address(0), tokenId_, 0, slot, value);
    }

    function _burnValue(uint256 tokenId_, uint256 burnValue_) internal virtual {
        _requireMinted(tokenId_);

        TokenData storage tokenData = _allTokens[_allTokensIndex[tokenId_]];
        address owner = tokenData.owner;
        uint256 slot = tokenData.slot;
        uint256 value = tokenData.balance;

        require(value >= burnValue_, "ERC3525: burn value exceeds balance");

        _beforeValueTransfer(owner, address(0), tokenId_, 0, slot, burnValue_);
        
        tokenData.balance -= burnValue_;
        emit TransferValue(tokenId_, 0, burnValue_);
        
        _afterValueTransfer(owner, address(0), tokenId_, 0, slot, burnValue_);
    }

    function _addTokenToOwnerEnumeration(address to_, uint256 tokenId_) private {
        _allTokens[_allTokensIndex[tokenId_]].owner = to_;

        _addressData[to_].ownedTokensIndex[tokenId_] = _addressData[to_].ownedTokens.length;
        _addressData[to_].ownedTokens.push(tokenId_);
    }

    function _removeTokenFromOwnerEnumeration(address from_, uint256 tokenId_) private {
        _allTokens[_allTokensIndex[tokenId_]].owner = address(0);

        AddressData storage ownerData = _addressData[from_];
        uint256 lastTokenIndex = ownerData.ownedTokens.length - 1;
        uint256 lastTokenId = ownerData.ownedTokens[lastTokenIndex];
        uint256 tokenIndex = ownerData.ownedTokensIndex[tokenId_];

        ownerData.ownedTokens[tokenIndex] = lastTokenId;
        ownerData.ownedTokensIndex[lastTokenId] = tokenIndex;

        delete ownerData.ownedTokensIndex[tokenId_];
        ownerData.ownedTokens.pop();
    }

    function _addTokenToAllTokensEnumeration(TokenData memory tokenData_) private {
        _allTokensIndex[tokenData_.id] = _allTokens.length;
        _allTokens.push(tokenData_);
    }

    function _removeTokenFromAllTokensEnumeration(uint256 tokenId_) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId_];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        TokenData memory lastTokenData = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenData; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenData.id] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId_];
        _allTokens.pop();
    }

    function _approve(address to_, uint256 tokenId_) internal virtual {
        _allTokens[_allTokensIndex[tokenId_]].approved = to_;
        emit Approval(ERC3525.ownerOf(tokenId_), to_, tokenId_);
    }

    function _approveValue(
        uint256 tokenId_,
        address to_,
        uint256 value_
    ) internal virtual {
        require(to_ != address(0), "ERC3525: approve value to the zero address");
        if (!_existApproveValue(to_, tokenId_)) {
            _allTokens[_allTokensIndex[tokenId_]].valueApprovals.push(to_);
        }
        _approvedValues[tokenId_][to_] = value_;

        emit ApprovalValue(tokenId_, to_, value_);
    }

    function _clearApprovedValues(uint256 tokenId_) internal virtual {
        TokenData storage tokenData = _allTokens[_allTokensIndex[tokenId_]];
        uint256 length = tokenData.valueApprovals.length;
        for (uint256 i = 0; i < length; i++) {
            address approval = tokenData.valueApprovals[i];
            delete _approvedValues[tokenId_][approval];
        }
    }

    function _existApproveValue(address to_, uint256 tokenId_) internal view virtual returns (bool) {
        uint256 length = _allTokens[_allTokensIndex[tokenId_]].valueApprovals.length;
        for (uint256 i = 0; i < length; i++) {
            if (_allTokens[_allTokensIndex[tokenId_]].valueApprovals[i] == to_) {
                return true;
            }
        }
        return false;
    }

    function _transferValue(
        uint256 fromTokenId_,
        uint256 toTokenId_,
        uint256 value_
    ) internal virtual {
        require(_exists(fromTokenId_), "ERC3525: transfer from invalid token ID");
        require(_exists(toTokenId_), "ERC3525: transfer to invalid token ID");

        TokenData storage fromTokenData = _allTokens[_allTokensIndex[fromTokenId_]];
        TokenData storage toTokenData = _allTokens[_allTokensIndex[toTokenId_]];

        require(fromTokenData.balance >= value_, "ERC3525: insufficient balance for transfer");
        require(fromTokenData.slot == toTokenData.slot, "ERC3525: transfer to token with different slot");

        _beforeValueTransfer(
            fromTokenData.owner,
            toTokenData.owner,
            fromTokenId_,
            toTokenId_,
            fromTokenData.slot,
            value_
        );

        fromTokenData.balance -= value_;
        toTokenData.balance += value_;

        emit TransferValue(fromTokenId_, toTokenId_, value_);

        _afterValueTransfer(
            fromTokenData.owner,
            toTokenData.owner,
            fromTokenId_,
            toTokenId_,
            fromTokenData.slot,
            value_
        );

        require(
            _checkOnERC3525Received(fromTokenId_, toTokenId_, value_, ""),
            "ERC3525: transfer to non ERC3525Receiver"
        );
    }

    function _transferTokenId(
        address from_,
        address to_,
        uint256 tokenId_
    ) internal virtual {
        require(ERC3525.ownerOf(tokenId_) == from_, "ERC3525: transfer from invalid owner");
        require(to_ != address(0), "ERC3525: transfer to the zero address");

        uint256 slot = ERC3525.slotOf(tokenId_);
        uint256 value = ERC3525.balanceOf(tokenId_);

        _beforeValueTransfer(from_, to_, tokenId_, tokenId_, slot, value);

        _approve(address(0), tokenId_);
        _clearApprovedValues(tokenId_);

        _removeTokenFromOwnerEnumeration(from_, tokenId_);
        _addTokenToOwnerEnumeration(to_, tokenId_);

        emit Transfer(from_, to_, tokenId_);

        _afterValueTransfer(from_, to_, tokenId_, tokenId_, slot, value);
    }

    function _safeTransferTokenId(
        address from_,
        address to_,
        uint256 tokenId_,
        bytes memory data_
    ) internal virtual {
        _transferTokenId(from_, to_, tokenId_);
        require(
            _checkOnERC721Received(from_, to_, tokenId_, data_),
            "ERC3525: transfer to non ERC721Receiver"
        );
    }

    function _checkOnERC3525Received( 
        uint256 fromTokenId_, 
        uint256 toTokenId_, 
        uint256 value_, 
        bytes memory data_
    ) private returns (bool) {
        address to = ERC3525.ownerOf(toTokenId_);
        if (to.isContract() && IERC165(to).supportsInterface(type(IERC3525Receiver).interfaceId)) {
            try
                IERC3525Receiver(to).onERC3525Received(_msgSender(), fromTokenId_, toTokenId_, value_, data_) returns (bytes4 retval) {
                return retval == IERC3525Receiver.onERC3525Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert( "ERC3525: transfer to non ERC3525Receiver");
                } else {
                    // solhint-disable-next-line
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @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() && IERC165(to_).supportsInterface(type(IERC721Receiver).interfaceId)) {
            try 
                IERC721Receiver(to_).onERC721Received(_msgSender(), from_, tokenId_, data_) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver");
                } else {
                    // solhint-disable-next-line
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /* solhint-disable */
    function _beforeValueTransfer(
        address from_,
        address to_,
        uint256 fromTokenId_,
        uint256 toTokenId_,
        uint256 slot_,
        uint256 value_
    ) internal virtual {}

    function _afterValueTransfer(
        address from_,
        address to_,
        uint256 fromTokenId_,
        uint256 toTokenId_,
        uint256 slot_,
        uint256 value_
    ) internal virtual {}
    /* solhint-enable */

    function _setMetadataDescriptor(address metadataDescriptor_) internal virtual {
        metadataDescriptor = IERC3525MetadataDescriptor(metadataDescriptor_);
        emit SetMetadataDescriptor(metadataDescriptor_);
    }

    function _createOriginalTokenId() internal virtual returns (uint256) {
         _tokenIdGenerator.increment();
        return _tokenIdGenerator.current();
    }

    function _createDerivedTokenId(uint256 fromTokenId_) internal virtual returns (uint256) {
        fromTokenId_;
        return _createOriginalTokenId();
    }
}

File 11 of 18 : IERC3525Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC3525.sol";
import "./IERC721Metadata.sol";

/**
 * @title ERC-3525 Semi-Fungible Token Standard, optional extension for metadata
 * @dev Interfaces for any contract that wants to support query of the Uniform Resource Identifier
 *  (URI) for the ERC3525 contract as well as a specified slot.
 *  Because of the higher reliability of data stored in smart contracts compared to data stored in
 *  centralized systems, it is recommended that metadata, including `contractURI`, `slotURI` and
 *  `tokenURI`, be directly returned in JSON format, instead of being returned with a url pointing
 *  to any resource stored in a centralized system.
 *  See https://eips.ethereum.org/EIPS/eip-3525
 * Note: the ERC-165 identifier for this interface is 0xe1600902.
 */
interface IERC3525Metadata is IERC3525, IERC721Metadata {
    /**
     * @notice Returns the Uniform Resource Identifier (URI) for the current ERC3525 contract.
     * @dev This function SHOULD return the URI for this contract in JSON format, starting with
     *  header `data:application/json;`.
     *  See https://eips.ethereum.org/EIPS/eip-3525 for the JSON schema for contract URI.
     * @return The JSON formatted URI of the current ERC3525 contract
     */
    function contractURI() external view returns (string memory);

    /**
     * @notice Returns the Uniform Resource Identifier (URI) for the specified slot.
     * @dev This function SHOULD return the URI for `_slot` in JSON format, starting with header
     *  `data:application/json;`.
     *  See https://eips.ethereum.org/EIPS/eip-3525 for the JSON schema for slot URI.
     * @return The JSON formatted URI of `_slot`
     */
    function slotURI(uint256 _slot) external view returns (string memory);
}

File 12 of 18 : IERC721Enumerable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 *  Note: the ERC-165 identifier for this interface is 0x780e9d63.
 */
interface IERC721Enumerable is IERC721 {
    /** 
     * @notice Count NFTs tracked by this contract
     * @return A count of valid NFTs tracked by this contract, where each one of
     *  them has an assigned and queryable owner not equal to the zero address
     */
    function totalSupply() external view returns (uint256);

    /** 
     * @notice Enumerate valid NFTs
     * @dev Throws if `_index` >= `totalSupply()`.
     * @param _index A counter less than `totalSupply()`
     * @return The token identifier for the `_index`th NFT,
     *  (sort order not specified)
     */
    function tokenByIndex(uint256 _index) external view returns (uint256);

    /** 
     * @notice Enumerate NFTs assigned to an owner
     * @dev Throws if `_index` >= `balanceOf(_owner)` or if
     *  `_owner` is the zero address, representing invalid NFTs.
     * @param _owner An address where we are interested in NFTs owned by them
     * @param _index A counter less than `balanceOf(_owner)`
     * @return The token identifier for the `_index`th NFT assigned to `_owner`,
     *  (sort order not specified)
     */
    function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
}

File 13 of 18 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 *  Note: the ERC-165 identifier for this interface is 0x5b5e139f.
 */
interface IERC721Metadata is IERC721 {
    /**
     * @notice A descriptive name for a collection of NFTs in this contract
     */
    function name() external view returns (string memory);

    /**
     * @notice An abbreviated name for NFTs in this contract
     */
    function symbol() external view returns (string memory);

    /**
     * @notice A distinct Uniform Resource Identifier (URI) for a given asset.
     * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
     *  3986. The URI may point to a JSON file that conforms to the "ERC721
     *  Metadata JSON Schema".
     */
    function tokenURI(uint256 _tokenId) external view returns (string memory);
}

File 14 of 18 : IERC3525.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "./IERC721.sol";

/**
 * @title ERC-3525 Semi-Fungible Token Standard
 * @dev See https://eips.ethereum.org/EIPS/eip-3525
 * Note: the ERC-165 identifier for this interface is 0xc97ae3d5.
 */
interface IERC3525 is IERC165, IERC721 {
    /**
     * @dev MUST emit when value of a token is transferred to another token with the same slot,
     *  including zero value transfers (_value == 0) as well as transfers when tokens are created
     *  (`_fromTokenId` == 0) or destroyed (`_toTokenId` == 0).
     * @param _fromTokenId The token id to transfer value from
     * @param _toTokenId The token id to transfer value to
     * @param _value The transferred value
     */
    event TransferValue(uint256 indexed _fromTokenId, uint256 indexed _toTokenId, uint256 _value);

    /**
     * @dev MUST emits when the approval value of a token is set or changed.
     * @param _tokenId The token to approve
     * @param _operator The operator to approve for
     * @param _value The maximum value that `_operator` is allowed to manage
     */
    event ApprovalValue(uint256 indexed _tokenId, address indexed _operator, uint256 _value);

    /**
     * @dev MUST emit when the slot of a token is set or changed.
     * @param _tokenId The token of which slot is set or changed
     * @param _oldSlot The previous slot of the token
     * @param _newSlot The updated slot of the token
     */ 
    event SlotChanged(uint256 indexed _tokenId, uint256 indexed _oldSlot, uint256 indexed _newSlot);

    /**
     * @notice Get the number of decimals the token uses for value - e.g. 6, means the user
     *  representation of the value of a token can be calculated by dividing it by 1,000,000.
     *  Considering the compatibility with third-party wallets, this function is defined as
     *  `valueDecimals()` instead of `decimals()` to avoid conflict with ERC20 tokens.
     * @return The number of decimals for value
     */
    function valueDecimals() external view returns (uint8);

    /**
     * @notice Get the value of a token.
     * @param _tokenId The token for which to query the balance
     * @return The value of `_tokenId`
     */
    function balanceOf(uint256 _tokenId) external view returns (uint256);

    /**
     * @notice Get the slot of a token.
     * @param _tokenId The identifier for a token
     * @return The slot of the token
     */
    function slotOf(uint256 _tokenId) external view returns (uint256);

    /**
     * @notice Allow an operator to manage the value of a token, up to the `_value` amount.
     * @dev MUST revert unless caller is the current owner, an authorized operator, or the approved
     *  address for `_tokenId`.
     *  MUST emit ApprovalValue event.
     * @param _tokenId The token to approve
     * @param _operator The operator to be approved
     * @param _value The maximum value of `_toTokenId` that `_operator` is allowed to manage
     */
    function approve(
        uint256 _tokenId,
        address _operator,
        uint256 _value
    ) external payable;

    /**
     * @notice Get the maximum value of a token that an operator is allowed to manage.
     * @param _tokenId The token for which to query the allowance
     * @param _operator The address of an operator
     * @return The current approval value of `_tokenId` that `_operator` is allowed to manage
     */
    function allowance(uint256 _tokenId, address _operator) external view returns (uint256);

    /**
     * @notice Transfer value from a specified token to another specified token with the same slot.
     * @dev Caller MUST be the current owner, an authorized operator or an operator who has been
     *  approved the whole `_fromTokenId` or part of it.
     *  MUST revert if `_fromTokenId` or `_toTokenId` is zero token id or does not exist.
     *  MUST revert if slots of `_fromTokenId` and `_toTokenId` do not match.
     *  MUST revert if `_value` exceeds the balance of `_fromTokenId` or its allowance to the
     *  operator.
     *  MUST emit `TransferValue` event.
     * @param _fromTokenId The token to transfer value from
     * @param _toTokenId The token to transfer value to
     * @param _value The transferred value
     */
    function transferFrom(
        uint256 _fromTokenId,
        uint256 _toTokenId,
        uint256 _value
    ) external payable;

    /**
     * @notice Transfer value from a specified token to an address. The caller should confirm that
     *  `_to` is capable of receiving ERC3525 tokens.
     * @dev This function MUST create a new ERC3525 token with the same slot for `_to` to receive
     *  the transferred value.
     *  MUST revert if `_fromTokenId` is zero token id or does not exist.
     *  MUST revert if `_to` is zero address.
     *  MUST revert if `_value` exceeds the balance of `_fromTokenId` or its allowance to the
     *  operator.
     *  MUST emit `Transfer` and `TransferValue` events.
     * @param _fromTokenId The token to transfer value from
     * @param _to The address to transfer value to
     * @param _value The transferred value
     * @return ID of the new token created for `_to` which receives the transferred value
     */
    function transferFrom(
        uint256 _fromTokenId,
        address _to,
        uint256 _value
    ) external payable returns (uint256);
}

File 15 of 18 : IERC3525Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title EIP-3525 token receiver interface
 * @dev Interface for a smart contract that wants to be informed by EIP-3525 contracts when 
 *  receiving values from ANY addresses or EIP-3525 tokens.
 * Note: the EIP-165 identifier for this interface is 0x009ce20b.
 */
interface IERC3525Receiver {
    /**
     * @notice Handle the receipt of an EIP-3525 token value.
     * @dev An EIP-3525 smart contract MUST check whether this function is implemented by the 
     *  recipient contract, if the recipient contract implements this function, the EIP-3525 
     *  contract MUST call this function after a value transfer (i.e. `transferFrom(uint256,
     *  uint256,uint256,bytes)`).
     *  MUST return 0x009ce20b (i.e. `bytes4(keccak256('onERC3525Received(address,uint256,uint256,
     *  uint256,bytes)'))`) if the transfer is accepted.
     *  MUST revert or return any value other than 0x009ce20b if the transfer is rejected.
     * @param _operator The address which triggered the transfer
     * @param _fromTokenId The token id to transfer value from
     * @param _toTokenId The token id to transfer value to
     * @param _value The transferred value
     * @param _data Additional data with no specified format
     * @return `bytes4(keccak256('onERC3525Received(address,uint256,uint256,uint256,bytes)'))` 
     *  unless the transfer is rejected.
     */
    function onERC3525Received(address _operator, uint256 _fromTokenId, uint256 _toTokenId, uint256 _value, bytes calldata _data) external returns (bytes4);

}

File 16 of 18 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/** 
 * @title ERC-721 Non-Fungible Token Standard
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 *  Note: the ERC-165 identifier for this interface is 0x80ac58cd.
 */
interface IERC721 is IERC165 {
    /** 
     * @dev This emits when ownership of any NFT changes by any mechanism.
     *  This event emits when NFTs are created (`from` == 0) and destroyed
     *  (`to` == 0). Exception: during contract creation, any number of NFTs
     *  may be created and assigned without emitting Transfer. At the time of
     *  any transfer, the approved address for that NFT (if any) is reset to none.
     */
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

    /**
     * @dev This emits when the approved address for an NFT is changed or
     *  reaffirmed. The zero address indicates there is no approved address.
     *  When a Transfer event emits, this also indicates that the approved
     *  address for that NFT (if any) is reset to none.
     */
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

    /**
     * @dev This emits when an operator is enabled or disabled for an owner.
     *  The operator can manage all NFTs of the owner.
     */
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

    /**
     * @notice Count all NFTs assigned to an owner
     * @dev NFTs assigned to the zero address are considered invalid, and this
     *  function throws for queries about the zero address.
     * @param _owner An address for whom to query the balance
     * @return The number of NFTs owned by `_owner`, possibly zero
     */
    function balanceOf(address _owner) external view returns (uint256);

    /**
     * @notice Find the owner of an NFT
     * @dev NFTs assigned to zero address are considered invalid, and queries
     *  about them do throw.
     * @param _tokenId The identifier for an NFT
     * @return The address of the owner of the NFT
     */
    function ownerOf(uint256 _tokenId) external view returns (address);

    /**
     * @notice Transfers the ownership of an NFT from one address to another address
     * @dev Throws unless `msg.sender` is the current owner, an authorized
     *  operator, or the approved address for this NFT. Throws if `_from` is
     *  not the current owner. Throws if `_to` is the zero address. Throws if
     *  `_tokenId` is not a valid NFT. When transfer is complete, this function
     *  checks if `_to` is a smart contract (code size > 0). If so, it calls
     *  `onERC721Received` on `_to` and throws if the return value is not
     *  `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
     * @param _from The current owner of the NFT
     * @param _to The new owner
     * @param _tokenId The NFT to transfer
     * @param data Additional data with no specified format, sent in call to `_to`
     */
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable;

    /**
     * @notice Transfers the ownership of an NFT from one address to another address
     * @dev This works identically to the other function with an extra data parameter,
     *  except this function just sets data to "".
     * @param _from The current owner of the NFT
     * @param _to The new owner
     * @param _tokenId The NFT to transfer
     */
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;

    /**
     * @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
     *  TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
     *  THEY MAY BE PERMANENTLY LOST
     * @dev Throws unless `msg.sender` is the current owner, an authorized
     *  operator, or the approved address for this NFT. Throws if `_from` is
     *  not the current owner. Throws if `_to` is the zero address. Throws if
     *  `_tokenId` is not a valid NFT.
     * @param _from The current owner of the NFT
     * @param _to The new owner
     * @param _tokenId The NFT to transfer
     */
    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;

    /**
     * @notice Change or reaffirm the approved address for an NFT
     * @dev The zero address indicates there is no approved address.
     *  Throws unless `msg.sender` is the current NFT owner, or an authorized
     *  operator of the current owner.
     * @param _approved The new approved NFT controller
     * @param _tokenId The NFT to approve
     */
    function approve(address _approved, uint256 _tokenId) external payable;

    /**
     * @notice Enable or disable approval for a third party ("operator") to manage
     *  all of `msg.sender`'s assets
     * @dev Emits the ApprovalForAll event. The contract MUST allow
     *  multiple operators per owner.
     * @param _operator Address to add to the set of authorized operators
     * @param _approved True if the operator is approved, false to revoke approval
     */
    function setApprovalForAll(address _operator, bool _approved) external;

    /**
     * @notice Get the approved address for a single NFT
     * @dev Throws if `_tokenId` is not a valid NFT.
     * @param _tokenId The NFT to find the approved address for
     * @return The approved address for this NFT, or the zero address if there is none
     */
    function getApproved(uint256 _tokenId) external view returns (address);

    /**
     * @notice Query if an address is an authorized operator for another address
     * @param _owner The address that owns the NFTs
     * @param _operator The address that acts on behalf of the owner
     * @return True if `_operator` is an approved operator for `_owner`, false otherwise
     */
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}

File 17 of 18 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers from ERC721 asset contracts.
 *  Note: the ERC-165 identifier for this interface is 0x150b7a02.
 */
interface IERC721Receiver {
    /** 
     * @notice Handle the receipt of an NFT
     * @dev The ERC721 smart contract calls this function on the recipient
     *  after a `transfer`. This function MAY throw to revert and reject the
     *  transfer. Return of other than the magic value MUST result in the
     *  transaction being reverted.
     *  Note: the contract address is always the message sender.
     * @param _operator The address which called `safeTransferFrom` function
     * @param _from The address which previously owned the token
     * @param _tokenId The NFT identifier which is being transferred
     * @param _data Additional data with no specified format
     * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
     *  unless throwing
     */
    function onERC721Received(
        address _operator, 
        address _from, 
        uint256 _tokenId, 
        bytes calldata _data
    ) external returns(bytes4);
}

File 18 of 18 : IERC3525MetadataDescriptor.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IERC3525MetadataDescriptor {

    function constructContractURI() external view returns (string memory);

    function constructSlotURI(uint256 slot) external view returns (string memory);
    
    function constructTokenURI(uint256 tokenId) external view returns (string memory);

}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_operator","type":"address"},{"indexed":false,"internalType":"bool","name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_operator","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"ApprovalValue","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"metadataDescriptor","type":"address"}],"name":"SetMetadataDescriptor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_oldSlot","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_newSlot","type":"uint256"}],"name":"SlotChanged","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_toTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"TransferValue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"operator_","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"blockId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenCountLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"operator_","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataDescriptor","outputs":[{"internalType":"contract IERC3525MetadataDescriptor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"mintToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"mintValue","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"queryId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"payable","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":"payable","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":"address","name":"addr","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"setTokenCountLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"slotOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"slot_","type":"uint256"}],"name":"slotURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","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":"uint256","name":"fromTokenId_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","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":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fromTokenId_","type":"uint256"},{"internalType":"uint256","name":"toTokenId_","type":"uint256"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"valueDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b50604051806040016040528060128152602001711313d3d5185113d1c814185cdcc810d85c9960721b815250604051806040016040528060048152602001631310511560e21b815250600282600090816200006d9190620001ca565b5060016200007c8382620001ca565b506002805460ff191660ff9290921691909117905550620000a69050620000a03390565b620000d3565b6009805462ffffff60a01b19169055600a80546001600160a01b031916331790556103e8600d5562000296565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200015057607f821691505b6020821081036200017157634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001c557600081815260208120601f850160051c81016020861015620001a05750805b601f850160051c820191505b81811015620001c157828155600101620001ac565b5050505b505050565b81516001600160401b03811115620001e657620001e662000125565b620001fe81620001f784546200013b565b8462000177565b602080601f8311600181146200023657600084156200021d5750858301515b600019600386901b1c1916600185901b178555620001c1565b600085815260208120601f198616915b82811015620002675788860151825594840194600190910190840162000246565b5085821015620002865787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b613ad380620002a66000396000f3fe6080604052600436106102465760003560e01c80636352211e1161013957806395d89b41116100b6578063e345e0bc1161007a578063e345e0bc14610630578063e8a3d48514610650578063e985e9c514610665578063f2fde38b146106b2578063f7b6feab146106d2578063f7dba4d51461070257600080fd5b806395d89b41146105a85780639cc7f708146105bd578063a22cb465146105dd578063b88d4fde146105fd578063c87b56dd1461061057600080fd5b80637ac3c02f116100fd5780637ac3c02f14610524578063840f7113146105425780638456cb59146105625780638cb0a511146105775780638da5cb5b1461058a57600080fd5b80636352211e1461049a5780636c19e783146104ba57806370a08231146104da578063715018a6146104fa5780637789a00c1461050f57600080fd5b8063263f3e7e116101c757806342842e0e1161018b57806342842e0e146104155780634f6ccce71461042857806352c18f861461044857806355f804b31461045b5780635c975abb1461047b57600080fd5b8063263f3e7e1461038b5780632f745c59146103ab578063310ed7f0146103cb5780633e7e8669146103de5780633f4ba83a1461040057600080fd5b80630f485c021161020e5780630f485c021461030f578063168162d21461033057806318160ddd146103435780631d3e8c401461035857806323b872dd1461037857600080fd5b806301ffc9a71461024b57806306fdde0314610280578063081812fc146102a2578063095ea7b3146102da57806309c3dd87146102ef575b600080fd5b34801561025757600080fd5b5061026b61026636600461307e565b610738565b60405190151581526020015b60405180910390f35b34801561028c57600080fd5b506102956107db565b60405161027791906130f3565b3480156102ae57600080fd5b506102c26102bd366004613106565b61086d565b6040516001600160a01b039091168152602001610277565b6102ed6102e8366004613136565b6108bf565b005b3480156102fb57600080fd5b5061029561030a366004613106565b61094d565b61032261031d366004613160565b610a32565b604051908152602001610277565b6102ed61033e3660046131a6565b610aa8565b34801561034f57600080fd5b50600554610322565b34801561036457600080fd5b506102ed610373366004613106565b610c76565b6102ed610386366004613209565b610c83565b34801561039757600080fd5b506103226103a6366004613106565b610cbf565b3480156103b757600080fd5b506103226103c6366004613136565b610d07565b6102ed6103d9366004613235565b610da8565b3480156103ea57600080fd5b5060025460405160ff9091168152602001610277565b34801561040c57600080fd5b506102ed610dbb565b6102ed610423366004613209565b610dcd565b34801561043457600080fd5b50610322610443366004613106565b610e09565b6102ed610456366004613261565b610e9a565b34801561046757600080fd5b506102ed6104763660046132ce565b610fff565b34801561048757600080fd5b50600954600160a01b900460ff1661026b565b3480156104a657600080fd5b506102c26104b5366004613106565b611014565b3480156104c657600080fd5b506102ed6104d5366004613340565b6110b0565b3480156104e657600080fd5b506103226104f5366004613340565b6110da565b34801561050657600080fd5b506102ed611162565b34801561051b57600080fd5b50600d54610322565b34801561053057600080fd5b50600a546001600160a01b03166102c2565b34801561054e57600080fd5b506008546102c2906001600160a01b031681565b34801561056e57600080fd5b506102ed611174565b6102ed610585366004613160565b611184565b34801561059657600080fd5b506009546001600160a01b03166102c2565b3480156105b457600080fd5b5061029561120b565b3480156105c957600080fd5b506103226105d8366004613106565b61121a565b3480156105e957600080fd5b506102ed6105f8366004613369565b611262565b6102ed61060b36600461340f565b611271565b34801561061c57600080fd5b5061029561062b366004613106565b6112ae565b34801561063c57600080fd5b5061032261064b3660046134ba565b611340565b34801561065c57600080fd5b50610295611374565b34801561067157600080fd5b5061026b6106803660046134e6565b6001600160a01b0391821660009081526007602090815260408083209390941682526002909201909152205460ff1690565b3480156106be57600080fd5b506102ed6106cd366004613340565b611461565b3480156106de57600080fd5b5061026b6106ed366004613106565b6000908152600b602052604090205460ff1690565b34801561070e57600080fd5b506102ed61071d366004613106565b6000908152600b60205260409020805460ff19166001179055565b60006001600160e01b031982166301ffc9a760e01b148061076957506001600160e01b03198216630354d60560e61b145b8061078457506001600160e01b031982166380ac58cd60e01b145b8061079f57506001600160e01b031982166370b0048160e11b145b806107ba57506001600160e01b0319821663780e9d6360e01b145b806107d557506001600160e01b03198216635b5e139f60e01b145b92915050565b6060600080546107ea90613510565b80601f016020809104026020016040519081016040528092919081815260200182805461081690613510565b80156108635780601f1061083857610100808354040283529160200191610863565b820191906000526020600020905b81548152906001019060200180831161084657829003601f168201915b5050505050905090565b6000610878826114da565b60008281526006602052604090205460058054909190811061089c5761089c61354a565b60009182526020909120600460069092020101546001600160a01b031692915050565b60006108ca82611014565b9050806001600160a01b0316836001600160a01b0316036109065760405162461bcd60e51b81526004016108fd90613560565b60405180910390fd5b336001600160a01b038216148061092257506109228133610680565b61093e5760405162461bcd60e51b81526004016108fd906135a2565b610948838361152b565b505050565b606060006109596115c2565b6008549091506001600160a01b03166109b957600081511161098a5760405180602001604052806000815250610a2b565b80610994846115d1565b6040516020016109a59291906135ff565b604051602081830303815290604052610a2b565b600854604051633601bfc560e11b8152600481018590526001600160a01b0390911690636c037f8a906024015b600060405180830381865afa158015610a03573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a2b919081019061363f565b9392505050565b6000610a3c6116d2565b600954600160b01b900460ff16610a955760405162461bcd60e51b815260206004820152601d60248201527f56616c756520646f6573206e6f7420616c6c6f77207472616e7366657200000060448201526064016108fd565b610aa084848461171f565b949350505050565b610ab06116d2565b844210610af15760405162461bcd60e51b815260206004820152600f60248201526e22bc3834b932b2103b37bab1b432b960891b60448201526064016108fd565b600d5460055410610b2f5760405162461bcd60e51b815260206004820152600860248201526714dbdb19081bdd5d60c21b60448201526064016108fd565b610b38336110da565b15610b765760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e481b5a5b9d195960921b60448201526064016108fd565b6000878152600b602052604090205460ff1615610bc45760405162461bcd60e51b815260206004820152600c60248201526b111d5c1b1a58d85d19481a5960a21b60448201526064016108fd565b6001600160a01b0384163314610c0c5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21037bbb732b960991b60448201526064016108fd565b610c486040518060a0016040528089815260200160008152602001888152602001878152602001866001600160a01b0316815250848484611759565b610c5433600188611818565b50505060009485525050600b602052505060409020805460ff19166001179055565b610c7e611831565b600d55565b610c8b6116d2565b600954600160a81b900460ff16610cb45760405162461bcd60e51b81526004016108fd906136b6565b61094883838361188b565b6000610cca826114da565b600082815260066020526040902054600580549091908110610cee57610cee61354a565b9060005260206000209060060201600101549050919050565b6000610d12836110da565b8210610d6b5760405162461bcd60e51b815260206004820152602260248201527f455243333532353a206f776e657220696e646578206f7574206f6620626f756e604482015261647360f01b60648201526084016108fd565b6001600160a01b0383166000908152600760205260409020805483908110610d9557610d9561354a565b9060005260206000200154905092915050565b610db06116d2565b6109488383836118bc565b610dc3611831565b610dcb6118d2565b565b610dd56116d2565b600954600160a81b900460ff16610dfe5760405162461bcd60e51b81526004016108fd906136b6565b610948838383611927565b6000610e1460055490565b8210610e6e5760405162461bcd60e51b815260206004820152602360248201527f455243333532353a20676c6f62616c20696e646578206f7574206f6620626f756044820152626e647360e81b60648201526084016108fd565b60058281548110610e8157610e8161354a565b9060005260206000209060060201600001549050919050565b610ea26116d2565b844210610ee35760405162461bcd60e51b815260206004820152600f60248201526e22bc3834b932b2103b37bab1b432b960891b60448201526064016108fd565b6000888152600b602052604090205460ff1615610f315760405162461bcd60e51b815260206004820152600c60248201526b111d5c1b1a58d85d19481a5960a21b60448201526064016108fd565b6001600160a01b0384163314610f795760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21037bbb732b960991b60448201526064016108fd565b60008611610fba5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b60448201526064016108fd565b610ff56040518060a001604052808a8152602001898152602001888152602001878152602001866001600160a01b0316815250848484611759565b610c548787611942565b611007611831565b600c610948828483613733565b600061101f826114da565b6000828152600660205260409020546005805490919081106110435761104361354a565b60009182526020909120600360069092020101546001600160a01b03169050806110ab5760405162461bcd60e51b8152602060048201526019602482015278115490cccd4c8d4e881a5b9d985b1a59081d1bdad95b881251603a1b60448201526064016108fd565b919050565b6110b8611831565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b0382166111465760405162461bcd60e51b815260206004820152602b60248201527f455243333532353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084016108fd565b506001600160a01b031660009081526007602052604090205490565b61116a611831565b610dcb6000611974565b61117c611831565b610dcb6119c6565b600061118f84611014565b9050806001600160a01b0316836001600160a01b0316036111c25760405162461bcd60e51b81526004016108fd90613560565b336001600160a01b03821614806111de57506111de8133610680565b6111fa5760405162461bcd60e51b81526004016108fd906135a2565b611205848484611a09565b50505050565b6060600180546107ea90613510565b6000611225826114da565b6000828152600660205260409020546005805490919081106112495761124961354a565b9060005260206000209060060201600201549050919050565b61126d338383611b41565b5050565b6112796116d2565b600954600160a81b900460ff166112a25760405162461bcd60e51b81526004016108fd906136b6565b61120584848484611c0b565b60606112b9826114da565b60006112c36115c2565b6008549091506001600160a01b031661130f5760008151116112f45760405180602001604052806000815250610a2b565b806112fe846115d1565b6040516020016109a59291906137f3565b6008546040516344a5a61760e11b8152600481018590526001600160a01b039091169063894b4c2e906024016109e6565b600061134b836114da565b5060009182526004602090815260408084206001600160a01b0393909316845291905290205490565b606060006113806115c2565b6008549091506001600160a01b03166113e05760008151116113b1576040518060200160405280600081525061145b565b806113bb30611c3d565b6040516020016113cc929190613822565b60405160208183030381529060405261145b565b600860009054906101000a90046001600160a01b03166001600160a01b031663725fa09c6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261145b919081019061363f565b91505090565b611469611831565b6001600160a01b0381166114ce5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108fd565b6114d781611974565b50565b6114e381611c53565b6114d75760405162461bcd60e51b8152602060048201526019602482015278115490cccd4c8d4e881a5b9d985b1a59081d1bdad95b881251603a1b60448201526064016108fd565b60008181526006602052604090205460058054849290811061154f5761154f61354a565b6000918252602090912060069091020160040180546001600160a01b0319166001600160a01b039283161790558190831661158982611014565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6060600c80546107ea90613510565b6060816000036115f85750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611622578061160c8161387c565b915061161b9050600a836138ab565b91506115fc565b60008167ffffffffffffffff81111561163d5761163d6133a0565b6040519080825280601f01601f191660200182016040528015611667576020820181803683370190505b5090505b8415610aa05761167c6001836138bf565b9150611689600a866138d6565b6116949060306138ea565b60f81b8183815181106116a9576116a961354a565b60200101906001600160f81b031916908160001a9053506116cb600a866138ab565b945061166b565b600954600160a01b900460ff1615610dcb5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016108fd565b600061172c338584611c9f565b600061173785611d2f565b905061174e848261174788610cbf565b6000611d39565b610aa0858285611e5e565b6000600161176686612109565b6040805160008152602081018083529290925260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156117b4573d6000803e3d6000fd5b5050604051601f190151600a549092506001600160a01b0380841691161490506118115760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b60448201526064016108fd565b5050505050565b60008061182361224d565b9050610aa085828686611d39565b6009546001600160a01b03163314610dcb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108fd565b6118953382612264565b6118b15760405162461bcd60e51b81526004016108fd90613902565b6109488383836122cc565b6118c7338483611c9f565b610948838383611e5e565b6118da61242d565b6009805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b61094883838360405180602001604052806000815250611271565b61194b826114da565b600061195683611014565b9050600061196384610cbf565b905061196f8484612485565b611205565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6119ce6116d2565b6009805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861190a3390565b6001600160a01b038216611a725760405162461bcd60e51b815260206004820152602a60248201527f455243333532353a20617070726f76652076616c756520746f20746865207a65604482015269726f206164647265737360b01b60648201526084016108fd565b611a7c828461250a565b611ae257600083815260066020526040902054600580549091908110611aa457611aa461354a565b60009182526020808320600692909202909101600501805460018101825590835291200180546001600160a01b0319166001600160a01b0384161790555b60008381526004602090815260408083206001600160a01b038616808552908352928190208490555183815285917f621b050de0ad08b51d19b48b3e6df75348c4de6bdd93e81b252ca62e28265b1b91015b60405180910390a3505050565b816001600160a01b0316836001600160a01b031603611ba25760405162461bcd60e51b815260206004820152601a60248201527f455243333532353a20617070726f766520746f2063616c6c657200000000000060448201526064016108fd565b6001600160a01b0383811660008181526007602090815260408083209487168084526002909501825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101611b34565b611c153383612264565b611c315760405162461bcd60e51b81526004016108fd90613902565b611205848484846125dd565b60606107d56001600160a01b0383166014612650565b600554600090158015906107d55750600082815260066020526040902054600580548492908110611c8657611c8661354a565b9060005260206000209060060201600001541492915050565b6000611cab8385611340565b9050611cb78484612264565b158015611cc657506000198114155b156112055781811015611d1b5760405162461bcd60e51b815260206004820152601f60248201527f455243333532353a20696e73756666696369656e7420616c6c6f77616e63650060448201526064016108fd565b6112058385611d2a85856138bf565b611a09565b60006107d561224d565b6001600160a01b038416611d995760405162461bcd60e51b815260206004820152602160248201527f455243333532353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b60648201526084016108fd565b82600003611df35760405162461bcd60e51b815260206004820152602160248201527f455243333532353a2063616e6e6f74206d696e74207a65726f20746f6b656e496044820152601960fa1b60648201526084016108fd565b611dfc83611c53565b15611e495760405162461bcd60e51b815260206004820152601d60248201527f455243333532353a20746f6b656e20616c7265616479206d696e74656400000060448201526064016108fd565b611e548484846127ec565b61196f8382612485565b611e6783611c53565b611ec35760405162461bcd60e51b815260206004820152602760248201527f455243333532353a207472616e736665722066726f6d20696e76616c696420746044820152661bdad95b88125160ca1b60648201526084016108fd565b611ecc82611c53565b611f265760405162461bcd60e51b815260206004820152602560248201527f455243333532353a207472616e7366657220746f20696e76616c696420746f6b604482015264195b88125160da1b60648201526084016108fd565b600083815260066020526040812054600580549091908110611f4a57611f4a61354a565b9060005260206000209060060201905060006005600660008681526020019081526020016000205481548110611f8257611f8261354a565b906000526020600020906006020190508282600201541015611ff95760405162461bcd60e51b815260206004820152602a60248201527f455243333532353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b60648201526084016108fd565b80600101548260010154146120675760405162461bcd60e51b815260206004820152602e60248201527f455243333532353a207472616e7366657220746f20746f6b656e20776974682060448201526d191a5999995c995b9d081cdb1bdd60921b60648201526084016108fd565b8282600201600082825461207b91906138bf565b925050819055508281600201600082825461209691906138ea565b9091555050604051838152849086907f0b2aac84f3ec956911fd78eae5311062972ff949f38412e8da39069d9f068cc69060200160405180910390a36120ed858585604051806020016040528060008152506128b2565b6118115760405162461bcd60e51b81526004016108fd90613954565b6000612208604080518082018252600d81526c04c4f4f5461444f47204461707609c1b6020918201528151808301835260018152603160f81b9082015281517fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472818301527f7adf56923e686bb1b093759a744659a5bc83da4e64912930cd2c64f30774ef92818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201527ff2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a55860c0808301919091528351808303909101815260e0909101909252815191012090565b61221183612a36565b60405161190160f01b6020820152602281019290925260428201526062015b604051602081830303815290604052805190602001209050919050565b600061225d600380546001019055565b5060035490565b600061226f826114da565b600061227a83611014565b9050806001600160a01b0316846001600160a01b031614806122a157506122a18185610680565b80610aa05750836001600160a01b03166122ba8461086d565b6001600160a01b031614949350505050565b826001600160a01b03166122df82611014565b6001600160a01b0316146123415760405162461bcd60e51b8152602060048201526024808201527f455243333532353a207472616e736665722066726f6d20696e76616c6964206f6044820152633bb732b960e11b60648201526084016108fd565b6001600160a01b0382166123a55760405162461bcd60e51b815260206004820152602560248201527f455243333532353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b60648201526084016108fd565b60006123b082610cbf565b905060006123bd8361121a565b90506123ca60008461152b565b6123d383612ab1565b6123dd8584612b4d565b6123e78484612c6e565b82846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611811565b600954600160a01b900460ff16610dcb5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016108fd565b505050505050565b6000828152600660205260409020546005805483929081106124a9576124a961354a565b906000526020600020906006020160020160008282546124c991906138ea565b909155505060405181815282906000907f0b2aac84f3ec956911fd78eae5311062972ff949f38412e8da39069d9f068cc69060200160405180910390a35050565b60008181526006602052604081205460058054839290811061252e5761252e61354a565b6000918252602082206005600690920201015491505b818110156125d257600084815260066020526040902054600580546001600160a01b038816929081106125795761257961354a565b9060005260206000209060060201600501828154811061259b5761259b61354a565b6000918252602090912001546001600160a01b0316036125c0576001925050506107d5565b806125ca8161387c565b915050612544565b506000949350505050565b6125e88484846122cc565b6125f484848484612cf7565b6112055760405162461bcd60e51b815260206004820152602760248201527f455243333532353a207472616e7366657220746f206e6f6e204552433732315260448201526632b1b2b4bb32b960c91b60648201526084016108fd565b6060600061265f83600261399c565b61266a9060026138ea565b67ffffffffffffffff811115612682576126826133a0565b6040519080825280601f01601f1916602001820160405280156126ac576020820181803683370190505b509050600360fc1b816000815181106126c7576126c761354a565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106126f6576126f661354a565b60200101906001600160f81b031916908160001a905350600061271a84600261399c565b6127259060016138ea565b90505b600181111561279d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106127595761275961354a565b1a60f81b82828151811061276f5761276f61354a565b60200101906001600160f81b031916908160001a90535060049490941c93612796816139bb565b9050612728565b508315610a2b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108fd565b6040805160c081018252838152602080820184905260008284018190526001600160a01b038716606084015260808301819052835181815291820190935260a0820152905061283a81612ea4565b6128448484612c6e565b60405183906001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4816000847fe4f48c240d3b994948aa54f3e2f5fca59263dfe1d52b6e4cf39a5d249b5ccb6560405160405180910390a450505050565b6000806128be85611014565b90506001600160a01b0381163b1515801561294257506040516301ffc9a760e01b8152629ce20b60e01b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa15801561291e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061294291906139d2565b15612a2c57604051629ce20b60e01b81526001600160a01b03821690629ce20b906129799033908a908a908a908a906004016139ef565b6020604051808303816000875af19250505080156129b4575060408051601f3d908101601f191682019092526129b191810190613a2d565b60015b612a11573d8080156129e2576040519150601f19603f3d011682016040523d82523d6000602084013e6129e7565b606091505b508051600003612a095760405162461bcd60e51b81526004016108fd90613954565b805181602001fd5b6001600160e01b031916629ce20b60e01b149150610aa09050565b6001915050610aa0565b8051602080830151604080850151606086015160808701519251600096612230967f4bd317336ea30fdfa31168cda381dacdf9ed1dd92eda94108d28629b6cf9b8c7969195919493920195865260208601949094526040850192909252606084015260808301526001600160a01b031660a082015260c00190565b600081815260066020526040812054600580549091908110612ad557612ad561354a565b600091825260208220600560069092020190810154909250905b81811015611205576000836005018281548110612b0e57612b0e61354a565b60009182526020808320909101548783526004825260408084206001600160a01b03909216845291528120555080612b458161387c565b915050612aef565b600081815260066020526040812054600580549091908110612b7157612b7161354a565b6000918252602080832060069290920290910160030180546001600160a01b0319166001600160a01b0394851617905591841681526007909152604081208054909190612bc0906001906138bf565b90506000826000018281548110612bd957612bd961354a565b90600052602060002001549050600083600101600086815260200190815260200160002054905081846000018281548110612c1657612c1661354a565b60009182526020808320909101929092558381526001860190915260408082208390558682528120558354849080612c5057612c50613a4a565b60019003818190600052602060002001600090559055505050505050565b600081815260066020526040902054600580548492908110612c9257612c9261354a565b6000918252602080832060069290920290910160030180546001600160a01b0319166001600160a01b03948516179055939091168152600780845260408083208054858552600182810188529285208190559286529082018155825292902090910155565b60006001600160a01b0384163b15158015612d7c57506040516301ffc9a760e01b8152630a85bd0160e11b60048201526001600160a01b038516906301ffc9a790602401602060405180830381865afa158015612d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d7c91906139d2565b15612e9c57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612db3903390899088908890600401613a60565b6020604051808303816000875af1925050508015612dee575060408051601f3d908101601f19168201909252612deb91810190613a2d565b60015b612e82573d808015612e1c576040519150601f19603f3d011682016040523d82523d6000602084013e612e21565b606091505b508051600003612a095760405162461bcd60e51b815260206004820152602660248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201526531b2b4bb32b960d11b60648201526084016108fd565b6001600160e01b031916630a85bd0160e11b149050610aa0565b506001610aa0565b600580548251600090815260066020818152604080842085905560018501865594909252845192027f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db08101928355818501517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db1820155928401517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db284015560608401517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db3840180546001600160a01b039283166001600160a01b03199182161790915560808601517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db48601805491909316911617905560a084015180518594611205937f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db5909101920190828054828255906000526020600020908101928215613043579160200282015b8281111561304357825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061300e565b5061304f929150613053565b5090565b5b8082111561304f5760008155600101613054565b6001600160e01b0319811681146114d757600080fd5b60006020828403121561309057600080fd5b8135610a2b81613068565b60005b838110156130b657818101518382015260200161309e565b838111156112055750506000910152565b600081518084526130df81602086016020860161309b565b601f01601f19169290920160200192915050565b602081526000610a2b60208301846130c7565b60006020828403121561311857600080fd5b5035919050565b80356001600160a01b03811681146110ab57600080fd5b6000806040838503121561314957600080fd5b6131528361311f565b946020939093013593505050565b60008060006060848603121561317557600080fd5b833592506131856020850161311f565b9150604084013590509250925092565b803560ff811681146110ab57600080fd5b600080600080600080600060e0888a0312156131c157600080fd5b8735965060208801359550604088013594506131df6060890161311f565b93506131ed60808901613195565b925060a0880135915060c0880135905092959891949750929550565b60008060006060848603121561321e57600080fd5b6132278461311f565b92506131856020850161311f565b60008060006060848603121561324a57600080fd5b505081359360208301359350604090920135919050565b600080600080600080600080610100898b03121561327e57600080fd5b883597506020890135965060408901359550606089013594506132a360808a0161311f565b93506132b160a08a01613195565b925060c0890135915060e089013590509295985092959890939650565b600080602083850312156132e157600080fd5b823567ffffffffffffffff808211156132f957600080fd5b818501915085601f83011261330d57600080fd5b81358181111561331c57600080fd5b86602082850101111561332e57600080fd5b60209290920196919550909350505050565b60006020828403121561335257600080fd5b610a2b8261311f565b80151581146114d757600080fd5b6000806040838503121561337c57600080fd5b6133858361311f565b915060208301356133958161335b565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156133df576133df6133a0565b604052919050565b600067ffffffffffffffff821115613401576134016133a0565b50601f01601f191660200190565b6000806000806080858703121561342557600080fd5b61342e8561311f565b935061343c6020860161311f565b925060408501359150606085013567ffffffffffffffff81111561345f57600080fd5b8501601f8101871361347057600080fd5b803561348361347e826133e7565b6133b6565b81815288602083850101111561349857600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080604083850312156134cd57600080fd5b823591506134dd6020840161311f565b90509250929050565b600080604083850312156134f957600080fd5b6135028361311f565b91506134dd6020840161311f565b600181811c9082168061352457607f821691505b60208210810361354457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60208082526022908201527f455243333532353a20617070726f76616c20746f2063757272656e74206f776e60408201526132b960f11b606082015260800190565b60208082526039908201527f455243333532353a20617070726f76652063616c6c6572206973206e6f74206f60408201527f776e6572206e6f7220617070726f76656420666f7220616c6c00000000000000606082015260800190565b6000835161361181846020880161309b565b64736c6f742f60d81b908301908152835161363381600584016020880161309b565b01600501949350505050565b60006020828403121561365157600080fd5b815167ffffffffffffffff81111561366857600080fd5b8201601f8101841361367957600080fd5b805161368761347e826133e7565b81815285602083850101111561369c57600080fd5b6136ad82602083016020860161309b565b95945050505050565b6020808252601d908201527f546f6b656e20646f6573206e6f7420616c6c6f77207472616e73666572000000604082015260600190565b601f82111561094857600081815260208120601f850160051c810160208610156137145750805b601f850160051c820191505b8181101561247d57828155600101613720565b67ffffffffffffffff83111561374b5761374b6133a0565b61375f836137598354613510565b836136ed565b6000601f841160018114613793576000851561377b5750838201355b600019600387901b1c1916600186901b178355611811565b600083815260209020601f19861690835b828110156137c457868501358255602094850194600190920191016137a4565b50868210156137e15760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000835161380581846020880161309b565b83519083019061381981836020880161309b565b01949350505050565b6000835161383481846020880161309b565b68636f6e74726163742f60b81b908301908152835161385a81600984016020880161309b565b01600901949350505050565b634e487b7160e01b600052601160045260246000fd5b60006001820161388e5761388e613866565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826138ba576138ba613895565b500490565b6000828210156138d1576138d1613866565b500390565b6000826138e5576138e5613895565b500690565b600082198211156138fd576138fd613866565b500190565b60208082526032908201527f455243333532353a207472616e736665722063616c6c6572206973206e6f74206040820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b606082015260800190565b60208082526028908201527f455243333532353a207472616e7366657220746f206e6f6e20455243333532356040820152672932b1b2b4bb32b960c11b606082015260800190565b60008160001904831182151516156139b6576139b6613866565b500290565b6000816139ca576139ca613866565b506000190190565b6000602082840312156139e457600080fd5b8151610a2b8161335b565b60018060a01b038616815284602082015283604082015282606082015260a060808201526000613a2260a08301846130c7565b979650505050505050565b600060208284031215613a3f57600080fd5b8151610a2b81613068565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613a93908301846130c7565b969550505050505056fea2646970667358221220e2ad52a24bcfe504f6e72a3537011dff23006983c70992647239373d09abd19664736f6c634300080f0033

Deployed Bytecode

0x6080604052600436106102465760003560e01c80636352211e1161013957806395d89b41116100b6578063e345e0bc1161007a578063e345e0bc14610630578063e8a3d48514610650578063e985e9c514610665578063f2fde38b146106b2578063f7b6feab146106d2578063f7dba4d51461070257600080fd5b806395d89b41146105a85780639cc7f708146105bd578063a22cb465146105dd578063b88d4fde146105fd578063c87b56dd1461061057600080fd5b80637ac3c02f116100fd5780637ac3c02f14610524578063840f7113146105425780638456cb59146105625780638cb0a511146105775780638da5cb5b1461058a57600080fd5b80636352211e1461049a5780636c19e783146104ba57806370a08231146104da578063715018a6146104fa5780637789a00c1461050f57600080fd5b8063263f3e7e116101c757806342842e0e1161018b57806342842e0e146104155780634f6ccce71461042857806352c18f861461044857806355f804b31461045b5780635c975abb1461047b57600080fd5b8063263f3e7e1461038b5780632f745c59146103ab578063310ed7f0146103cb5780633e7e8669146103de5780633f4ba83a1461040057600080fd5b80630f485c021161020e5780630f485c021461030f578063168162d21461033057806318160ddd146103435780631d3e8c401461035857806323b872dd1461037857600080fd5b806301ffc9a71461024b57806306fdde0314610280578063081812fc146102a2578063095ea7b3146102da57806309c3dd87146102ef575b600080fd5b34801561025757600080fd5b5061026b61026636600461307e565b610738565b60405190151581526020015b60405180910390f35b34801561028c57600080fd5b506102956107db565b60405161027791906130f3565b3480156102ae57600080fd5b506102c26102bd366004613106565b61086d565b6040516001600160a01b039091168152602001610277565b6102ed6102e8366004613136565b6108bf565b005b3480156102fb57600080fd5b5061029561030a366004613106565b61094d565b61032261031d366004613160565b610a32565b604051908152602001610277565b6102ed61033e3660046131a6565b610aa8565b34801561034f57600080fd5b50600554610322565b34801561036457600080fd5b506102ed610373366004613106565b610c76565b6102ed610386366004613209565b610c83565b34801561039757600080fd5b506103226103a6366004613106565b610cbf565b3480156103b757600080fd5b506103226103c6366004613136565b610d07565b6102ed6103d9366004613235565b610da8565b3480156103ea57600080fd5b5060025460405160ff9091168152602001610277565b34801561040c57600080fd5b506102ed610dbb565b6102ed610423366004613209565b610dcd565b34801561043457600080fd5b50610322610443366004613106565b610e09565b6102ed610456366004613261565b610e9a565b34801561046757600080fd5b506102ed6104763660046132ce565b610fff565b34801561048757600080fd5b50600954600160a01b900460ff1661026b565b3480156104a657600080fd5b506102c26104b5366004613106565b611014565b3480156104c657600080fd5b506102ed6104d5366004613340565b6110b0565b3480156104e657600080fd5b506103226104f5366004613340565b6110da565b34801561050657600080fd5b506102ed611162565b34801561051b57600080fd5b50600d54610322565b34801561053057600080fd5b50600a546001600160a01b03166102c2565b34801561054e57600080fd5b506008546102c2906001600160a01b031681565b34801561056e57600080fd5b506102ed611174565b6102ed610585366004613160565b611184565b34801561059657600080fd5b506009546001600160a01b03166102c2565b3480156105b457600080fd5b5061029561120b565b3480156105c957600080fd5b506103226105d8366004613106565b61121a565b3480156105e957600080fd5b506102ed6105f8366004613369565b611262565b6102ed61060b36600461340f565b611271565b34801561061c57600080fd5b5061029561062b366004613106565b6112ae565b34801561063c57600080fd5b5061032261064b3660046134ba565b611340565b34801561065c57600080fd5b50610295611374565b34801561067157600080fd5b5061026b6106803660046134e6565b6001600160a01b0391821660009081526007602090815260408083209390941682526002909201909152205460ff1690565b3480156106be57600080fd5b506102ed6106cd366004613340565b611461565b3480156106de57600080fd5b5061026b6106ed366004613106565b6000908152600b602052604090205460ff1690565b34801561070e57600080fd5b506102ed61071d366004613106565b6000908152600b60205260409020805460ff19166001179055565b60006001600160e01b031982166301ffc9a760e01b148061076957506001600160e01b03198216630354d60560e61b145b8061078457506001600160e01b031982166380ac58cd60e01b145b8061079f57506001600160e01b031982166370b0048160e11b145b806107ba57506001600160e01b0319821663780e9d6360e01b145b806107d557506001600160e01b03198216635b5e139f60e01b145b92915050565b6060600080546107ea90613510565b80601f016020809104026020016040519081016040528092919081815260200182805461081690613510565b80156108635780601f1061083857610100808354040283529160200191610863565b820191906000526020600020905b81548152906001019060200180831161084657829003601f168201915b5050505050905090565b6000610878826114da565b60008281526006602052604090205460058054909190811061089c5761089c61354a565b60009182526020909120600460069092020101546001600160a01b031692915050565b60006108ca82611014565b9050806001600160a01b0316836001600160a01b0316036109065760405162461bcd60e51b81526004016108fd90613560565b60405180910390fd5b336001600160a01b038216148061092257506109228133610680565b61093e5760405162461bcd60e51b81526004016108fd906135a2565b610948838361152b565b505050565b606060006109596115c2565b6008549091506001600160a01b03166109b957600081511161098a5760405180602001604052806000815250610a2b565b80610994846115d1565b6040516020016109a59291906135ff565b604051602081830303815290604052610a2b565b600854604051633601bfc560e11b8152600481018590526001600160a01b0390911690636c037f8a906024015b600060405180830381865afa158015610a03573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a2b919081019061363f565b9392505050565b6000610a3c6116d2565b600954600160b01b900460ff16610a955760405162461bcd60e51b815260206004820152601d60248201527f56616c756520646f6573206e6f7420616c6c6f77207472616e7366657200000060448201526064016108fd565b610aa084848461171f565b949350505050565b610ab06116d2565b844210610af15760405162461bcd60e51b815260206004820152600f60248201526e22bc3834b932b2103b37bab1b432b960891b60448201526064016108fd565b600d5460055410610b2f5760405162461bcd60e51b815260206004820152600860248201526714dbdb19081bdd5d60c21b60448201526064016108fd565b610b38336110da565b15610b765760405162461bcd60e51b815260206004820152600e60248201526d105b1c9958591e481b5a5b9d195960921b60448201526064016108fd565b6000878152600b602052604090205460ff1615610bc45760405162461bcd60e51b815260206004820152600c60248201526b111d5c1b1a58d85d19481a5960a21b60448201526064016108fd565b6001600160a01b0384163314610c0c5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21037bbb732b960991b60448201526064016108fd565b610c486040518060a0016040528089815260200160008152602001888152602001878152602001866001600160a01b0316815250848484611759565b610c5433600188611818565b50505060009485525050600b602052505060409020805460ff19166001179055565b610c7e611831565b600d55565b610c8b6116d2565b600954600160a81b900460ff16610cb45760405162461bcd60e51b81526004016108fd906136b6565b61094883838361188b565b6000610cca826114da565b600082815260066020526040902054600580549091908110610cee57610cee61354a565b9060005260206000209060060201600101549050919050565b6000610d12836110da565b8210610d6b5760405162461bcd60e51b815260206004820152602260248201527f455243333532353a206f776e657220696e646578206f7574206f6620626f756e604482015261647360f01b60648201526084016108fd565b6001600160a01b0383166000908152600760205260409020805483908110610d9557610d9561354a565b9060005260206000200154905092915050565b610db06116d2565b6109488383836118bc565b610dc3611831565b610dcb6118d2565b565b610dd56116d2565b600954600160a81b900460ff16610dfe5760405162461bcd60e51b81526004016108fd906136b6565b610948838383611927565b6000610e1460055490565b8210610e6e5760405162461bcd60e51b815260206004820152602360248201527f455243333532353a20676c6f62616c20696e646578206f7574206f6620626f756044820152626e647360e81b60648201526084016108fd565b60058281548110610e8157610e8161354a565b9060005260206000209060060201600001549050919050565b610ea26116d2565b844210610ee35760405162461bcd60e51b815260206004820152600f60248201526e22bc3834b932b2103b37bab1b432b960891b60448201526064016108fd565b6000888152600b602052604090205460ff1615610f315760405162461bcd60e51b815260206004820152600c60248201526b111d5c1b1a58d85d19481a5960a21b60448201526064016108fd565b6001600160a01b0384163314610f795760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21037bbb732b960991b60448201526064016108fd565b60008611610fba5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b60448201526064016108fd565b610ff56040518060a001604052808a8152602001898152602001888152602001878152602001866001600160a01b0316815250848484611759565b610c548787611942565b611007611831565b600c610948828483613733565b600061101f826114da565b6000828152600660205260409020546005805490919081106110435761104361354a565b60009182526020909120600360069092020101546001600160a01b03169050806110ab5760405162461bcd60e51b8152602060048201526019602482015278115490cccd4c8d4e881a5b9d985b1a59081d1bdad95b881251603a1b60448201526064016108fd565b919050565b6110b8611831565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b0382166111465760405162461bcd60e51b815260206004820152602b60248201527f455243333532353a2062616c616e636520717565727920666f7220746865207a60448201526a65726f206164647265737360a81b60648201526084016108fd565b506001600160a01b031660009081526007602052604090205490565b61116a611831565b610dcb6000611974565b61117c611831565b610dcb6119c6565b600061118f84611014565b9050806001600160a01b0316836001600160a01b0316036111c25760405162461bcd60e51b81526004016108fd90613560565b336001600160a01b03821614806111de57506111de8133610680565b6111fa5760405162461bcd60e51b81526004016108fd906135a2565b611205848484611a09565b50505050565b6060600180546107ea90613510565b6000611225826114da565b6000828152600660205260409020546005805490919081106112495761124961354a565b9060005260206000209060060201600201549050919050565b61126d338383611b41565b5050565b6112796116d2565b600954600160a81b900460ff166112a25760405162461bcd60e51b81526004016108fd906136b6565b61120584848484611c0b565b60606112b9826114da565b60006112c36115c2565b6008549091506001600160a01b031661130f5760008151116112f45760405180602001604052806000815250610a2b565b806112fe846115d1565b6040516020016109a59291906137f3565b6008546040516344a5a61760e11b8152600481018590526001600160a01b039091169063894b4c2e906024016109e6565b600061134b836114da565b5060009182526004602090815260408084206001600160a01b0393909316845291905290205490565b606060006113806115c2565b6008549091506001600160a01b03166113e05760008151116113b1576040518060200160405280600081525061145b565b806113bb30611c3d565b6040516020016113cc929190613822565b60405160208183030381529060405261145b565b600860009054906101000a90046001600160a01b03166001600160a01b031663725fa09c6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611433573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261145b919081019061363f565b91505090565b611469611831565b6001600160a01b0381166114ce5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108fd565b6114d781611974565b50565b6114e381611c53565b6114d75760405162461bcd60e51b8152602060048201526019602482015278115490cccd4c8d4e881a5b9d985b1a59081d1bdad95b881251603a1b60448201526064016108fd565b60008181526006602052604090205460058054849290811061154f5761154f61354a565b6000918252602090912060069091020160040180546001600160a01b0319166001600160a01b039283161790558190831661158982611014565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6060600c80546107ea90613510565b6060816000036115f85750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611622578061160c8161387c565b915061161b9050600a836138ab565b91506115fc565b60008167ffffffffffffffff81111561163d5761163d6133a0565b6040519080825280601f01601f191660200182016040528015611667576020820181803683370190505b5090505b8415610aa05761167c6001836138bf565b9150611689600a866138d6565b6116949060306138ea565b60f81b8183815181106116a9576116a961354a565b60200101906001600160f81b031916908160001a9053506116cb600a866138ab565b945061166b565b600954600160a01b900460ff1615610dcb5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016108fd565b600061172c338584611c9f565b600061173785611d2f565b905061174e848261174788610cbf565b6000611d39565b610aa0858285611e5e565b6000600161176686612109565b6040805160008152602081018083529290925260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156117b4573d6000803e3d6000fd5b5050604051601f190151600a549092506001600160a01b0380841691161490506118115760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b60448201526064016108fd565b5050505050565b60008061182361224d565b9050610aa085828686611d39565b6009546001600160a01b03163314610dcb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108fd565b6118953382612264565b6118b15760405162461bcd60e51b81526004016108fd90613902565b6109488383836122cc565b6118c7338483611c9f565b610948838383611e5e565b6118da61242d565b6009805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b61094883838360405180602001604052806000815250611271565b61194b826114da565b600061195683611014565b9050600061196384610cbf565b905061196f8484612485565b611205565b600980546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6119ce6116d2565b6009805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861190a3390565b6001600160a01b038216611a725760405162461bcd60e51b815260206004820152602a60248201527f455243333532353a20617070726f76652076616c756520746f20746865207a65604482015269726f206164647265737360b01b60648201526084016108fd565b611a7c828461250a565b611ae257600083815260066020526040902054600580549091908110611aa457611aa461354a565b60009182526020808320600692909202909101600501805460018101825590835291200180546001600160a01b0319166001600160a01b0384161790555b60008381526004602090815260408083206001600160a01b038616808552908352928190208490555183815285917f621b050de0ad08b51d19b48b3e6df75348c4de6bdd93e81b252ca62e28265b1b91015b60405180910390a3505050565b816001600160a01b0316836001600160a01b031603611ba25760405162461bcd60e51b815260206004820152601a60248201527f455243333532353a20617070726f766520746f2063616c6c657200000000000060448201526064016108fd565b6001600160a01b0383811660008181526007602090815260408083209487168084526002909501825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101611b34565b611c153383612264565b611c315760405162461bcd60e51b81526004016108fd90613902565b611205848484846125dd565b60606107d56001600160a01b0383166014612650565b600554600090158015906107d55750600082815260066020526040902054600580548492908110611c8657611c8661354a565b9060005260206000209060060201600001541492915050565b6000611cab8385611340565b9050611cb78484612264565b158015611cc657506000198114155b156112055781811015611d1b5760405162461bcd60e51b815260206004820152601f60248201527f455243333532353a20696e73756666696369656e7420616c6c6f77616e63650060448201526064016108fd565b6112058385611d2a85856138bf565b611a09565b60006107d561224d565b6001600160a01b038416611d995760405162461bcd60e51b815260206004820152602160248201527f455243333532353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b60648201526084016108fd565b82600003611df35760405162461bcd60e51b815260206004820152602160248201527f455243333532353a2063616e6e6f74206d696e74207a65726f20746f6b656e496044820152601960fa1b60648201526084016108fd565b611dfc83611c53565b15611e495760405162461bcd60e51b815260206004820152601d60248201527f455243333532353a20746f6b656e20616c7265616479206d696e74656400000060448201526064016108fd565b611e548484846127ec565b61196f8382612485565b611e6783611c53565b611ec35760405162461bcd60e51b815260206004820152602760248201527f455243333532353a207472616e736665722066726f6d20696e76616c696420746044820152661bdad95b88125160ca1b60648201526084016108fd565b611ecc82611c53565b611f265760405162461bcd60e51b815260206004820152602560248201527f455243333532353a207472616e7366657220746f20696e76616c696420746f6b604482015264195b88125160da1b60648201526084016108fd565b600083815260066020526040812054600580549091908110611f4a57611f4a61354a565b9060005260206000209060060201905060006005600660008681526020019081526020016000205481548110611f8257611f8261354a565b906000526020600020906006020190508282600201541015611ff95760405162461bcd60e51b815260206004820152602a60248201527f455243333532353a20696e73756666696369656e742062616c616e636520666f60448201526939103a3930b739b332b960b11b60648201526084016108fd565b80600101548260010154146120675760405162461bcd60e51b815260206004820152602e60248201527f455243333532353a207472616e7366657220746f20746f6b656e20776974682060448201526d191a5999995c995b9d081cdb1bdd60921b60648201526084016108fd565b8282600201600082825461207b91906138bf565b925050819055508281600201600082825461209691906138ea565b9091555050604051838152849086907f0b2aac84f3ec956911fd78eae5311062972ff949f38412e8da39069d9f068cc69060200160405180910390a36120ed858585604051806020016040528060008152506128b2565b6118115760405162461bcd60e51b81526004016108fd90613954565b6000612208604080518082018252600d81526c04c4f4f5461444f47204461707609c1b6020918201528151808301835260018152603160f81b9082015281517fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472818301527f7adf56923e686bb1b093759a744659a5bc83da4e64912930cd2c64f30774ef92818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201527ff2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a55860c0808301919091528351808303909101815260e0909101909252815191012090565b61221183612a36565b60405161190160f01b6020820152602281019290925260428201526062015b604051602081830303815290604052805190602001209050919050565b600061225d600380546001019055565b5060035490565b600061226f826114da565b600061227a83611014565b9050806001600160a01b0316846001600160a01b031614806122a157506122a18185610680565b80610aa05750836001600160a01b03166122ba8461086d565b6001600160a01b031614949350505050565b826001600160a01b03166122df82611014565b6001600160a01b0316146123415760405162461bcd60e51b8152602060048201526024808201527f455243333532353a207472616e736665722066726f6d20696e76616c6964206f6044820152633bb732b960e11b60648201526084016108fd565b6001600160a01b0382166123a55760405162461bcd60e51b815260206004820152602560248201527f455243333532353a207472616e7366657220746f20746865207a65726f206164604482015264647265737360d81b60648201526084016108fd565b60006123b082610cbf565b905060006123bd8361121a565b90506123ca60008461152b565b6123d383612ab1565b6123dd8584612b4d565b6123e78484612c6e565b82846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4611811565b600954600160a01b900460ff16610dcb5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016108fd565b505050505050565b6000828152600660205260409020546005805483929081106124a9576124a961354a565b906000526020600020906006020160020160008282546124c991906138ea565b909155505060405181815282906000907f0b2aac84f3ec956911fd78eae5311062972ff949f38412e8da39069d9f068cc69060200160405180910390a35050565b60008181526006602052604081205460058054839290811061252e5761252e61354a565b6000918252602082206005600690920201015491505b818110156125d257600084815260066020526040902054600580546001600160a01b038816929081106125795761257961354a565b9060005260206000209060060201600501828154811061259b5761259b61354a565b6000918252602090912001546001600160a01b0316036125c0576001925050506107d5565b806125ca8161387c565b915050612544565b506000949350505050565b6125e88484846122cc565b6125f484848484612cf7565b6112055760405162461bcd60e51b815260206004820152602760248201527f455243333532353a207472616e7366657220746f206e6f6e204552433732315260448201526632b1b2b4bb32b960c91b60648201526084016108fd565b6060600061265f83600261399c565b61266a9060026138ea565b67ffffffffffffffff811115612682576126826133a0565b6040519080825280601f01601f1916602001820160405280156126ac576020820181803683370190505b509050600360fc1b816000815181106126c7576126c761354a565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106126f6576126f661354a565b60200101906001600160f81b031916908160001a905350600061271a84600261399c565b6127259060016138ea565b90505b600181111561279d576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106127595761275961354a565b1a60f81b82828151811061276f5761276f61354a565b60200101906001600160f81b031916908160001a90535060049490941c93612796816139bb565b9050612728565b508315610a2b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016108fd565b6040805160c081018252838152602080820184905260008284018190526001600160a01b038716606084015260808301819052835181815291820190935260a0820152905061283a81612ea4565b6128448484612c6e565b60405183906001600160a01b038616906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4816000847fe4f48c240d3b994948aa54f3e2f5fca59263dfe1d52b6e4cf39a5d249b5ccb6560405160405180910390a450505050565b6000806128be85611014565b90506001600160a01b0381163b1515801561294257506040516301ffc9a760e01b8152629ce20b60e01b60048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa15801561291e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061294291906139d2565b15612a2c57604051629ce20b60e01b81526001600160a01b03821690629ce20b906129799033908a908a908a908a906004016139ef565b6020604051808303816000875af19250505080156129b4575060408051601f3d908101601f191682019092526129b191810190613a2d565b60015b612a11573d8080156129e2576040519150601f19603f3d011682016040523d82523d6000602084013e6129e7565b606091505b508051600003612a095760405162461bcd60e51b81526004016108fd90613954565b805181602001fd5b6001600160e01b031916629ce20b60e01b149150610aa09050565b6001915050610aa0565b8051602080830151604080850151606086015160808701519251600096612230967f4bd317336ea30fdfa31168cda381dacdf9ed1dd92eda94108d28629b6cf9b8c7969195919493920195865260208601949094526040850192909252606084015260808301526001600160a01b031660a082015260c00190565b600081815260066020526040812054600580549091908110612ad557612ad561354a565b600091825260208220600560069092020190810154909250905b81811015611205576000836005018281548110612b0e57612b0e61354a565b60009182526020808320909101548783526004825260408084206001600160a01b03909216845291528120555080612b458161387c565b915050612aef565b600081815260066020526040812054600580549091908110612b7157612b7161354a565b6000918252602080832060069290920290910160030180546001600160a01b0319166001600160a01b0394851617905591841681526007909152604081208054909190612bc0906001906138bf565b90506000826000018281548110612bd957612bd961354a565b90600052602060002001549050600083600101600086815260200190815260200160002054905081846000018281548110612c1657612c1661354a565b60009182526020808320909101929092558381526001860190915260408082208390558682528120558354849080612c5057612c50613a4a565b60019003818190600052602060002001600090559055505050505050565b600081815260066020526040902054600580548492908110612c9257612c9261354a565b6000918252602080832060069290920290910160030180546001600160a01b0319166001600160a01b03948516179055939091168152600780845260408083208054858552600182810188529285208190559286529082018155825292902090910155565b60006001600160a01b0384163b15158015612d7c57506040516301ffc9a760e01b8152630a85bd0160e11b60048201526001600160a01b038516906301ffc9a790602401602060405180830381865afa158015612d58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d7c91906139d2565b15612e9c57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612db3903390899088908890600401613a60565b6020604051808303816000875af1925050508015612dee575060408051601f3d908101601f19168201909252612deb91810190613a2d565b60015b612e82573d808015612e1c576040519150601f19603f3d011682016040523d82523d6000602084013e612e21565b606091505b508051600003612a095760405162461bcd60e51b815260206004820152602660248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201526531b2b4bb32b960d11b60648201526084016108fd565b6001600160e01b031916630a85bd0160e11b149050610aa0565b506001610aa0565b600580548251600090815260066020818152604080842085905560018501865594909252845192027f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db08101928355818501517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db1820155928401517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db284015560608401517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db3840180546001600160a01b039283166001600160a01b03199182161790915560808601517f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db48601805491909316911617905560a084015180518594611205937f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db5909101920190828054828255906000526020600020908101928215613043579160200282015b8281111561304357825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061300e565b5061304f929150613053565b5090565b5b8082111561304f5760008155600101613054565b6001600160e01b0319811681146114d757600080fd5b60006020828403121561309057600080fd5b8135610a2b81613068565b60005b838110156130b657818101518382015260200161309e565b838111156112055750506000910152565b600081518084526130df81602086016020860161309b565b601f01601f19169290920160200192915050565b602081526000610a2b60208301846130c7565b60006020828403121561311857600080fd5b5035919050565b80356001600160a01b03811681146110ab57600080fd5b6000806040838503121561314957600080fd5b6131528361311f565b946020939093013593505050565b60008060006060848603121561317557600080fd5b833592506131856020850161311f565b9150604084013590509250925092565b803560ff811681146110ab57600080fd5b600080600080600080600060e0888a0312156131c157600080fd5b8735965060208801359550604088013594506131df6060890161311f565b93506131ed60808901613195565b925060a0880135915060c0880135905092959891949750929550565b60008060006060848603121561321e57600080fd5b6132278461311f565b92506131856020850161311f565b60008060006060848603121561324a57600080fd5b505081359360208301359350604090920135919050565b600080600080600080600080610100898b03121561327e57600080fd5b883597506020890135965060408901359550606089013594506132a360808a0161311f565b93506132b160a08a01613195565b925060c0890135915060e089013590509295985092959890939650565b600080602083850312156132e157600080fd5b823567ffffffffffffffff808211156132f957600080fd5b818501915085601f83011261330d57600080fd5b81358181111561331c57600080fd5b86602082850101111561332e57600080fd5b60209290920196919550909350505050565b60006020828403121561335257600080fd5b610a2b8261311f565b80151581146114d757600080fd5b6000806040838503121561337c57600080fd5b6133858361311f565b915060208301356133958161335b565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156133df576133df6133a0565b604052919050565b600067ffffffffffffffff821115613401576134016133a0565b50601f01601f191660200190565b6000806000806080858703121561342557600080fd5b61342e8561311f565b935061343c6020860161311f565b925060408501359150606085013567ffffffffffffffff81111561345f57600080fd5b8501601f8101871361347057600080fd5b803561348361347e826133e7565b6133b6565b81815288602083850101111561349857600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080604083850312156134cd57600080fd5b823591506134dd6020840161311f565b90509250929050565b600080604083850312156134f957600080fd5b6135028361311f565b91506134dd6020840161311f565b600181811c9082168061352457607f821691505b60208210810361354457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60208082526022908201527f455243333532353a20617070726f76616c20746f2063757272656e74206f776e60408201526132b960f11b606082015260800190565b60208082526039908201527f455243333532353a20617070726f76652063616c6c6572206973206e6f74206f60408201527f776e6572206e6f7220617070726f76656420666f7220616c6c00000000000000606082015260800190565b6000835161361181846020880161309b565b64736c6f742f60d81b908301908152835161363381600584016020880161309b565b01600501949350505050565b60006020828403121561365157600080fd5b815167ffffffffffffffff81111561366857600080fd5b8201601f8101841361367957600080fd5b805161368761347e826133e7565b81815285602083850101111561369c57600080fd5b6136ad82602083016020860161309b565b95945050505050565b6020808252601d908201527f546f6b656e20646f6573206e6f7420616c6c6f77207472616e73666572000000604082015260600190565b601f82111561094857600081815260208120601f850160051c810160208610156137145750805b601f850160051c820191505b8181101561247d57828155600101613720565b67ffffffffffffffff83111561374b5761374b6133a0565b61375f836137598354613510565b836136ed565b6000601f841160018114613793576000851561377b5750838201355b600019600387901b1c1916600186901b178355611811565b600083815260209020601f19861690835b828110156137c457868501358255602094850194600190920191016137a4565b50868210156137e15760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6000835161380581846020880161309b565b83519083019061381981836020880161309b565b01949350505050565b6000835161383481846020880161309b565b68636f6e74726163742f60b81b908301908152835161385a81600984016020880161309b565b01600901949350505050565b634e487b7160e01b600052601160045260246000fd5b60006001820161388e5761388e613866565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826138ba576138ba613895565b500490565b6000828210156138d1576138d1613866565b500390565b6000826138e5576138e5613895565b500690565b600082198211156138fd576138fd613866565b500190565b60208082526032908201527f455243333532353a207472616e736665722063616c6c6572206973206e6f74206040820152711bdddb995c881b9bdc88185c1c1c9bdd995960721b606082015260800190565b60208082526028908201527f455243333532353a207472616e7366657220746f206e6f6e20455243333532356040820152672932b1b2b4bb32b960c11b606082015260800190565b60008160001904831182151516156139b6576139b6613866565b500290565b6000816139ca576139ca613866565b506000190190565b6000602082840312156139e457600080fd5b8151610a2b8161335b565b60018060a01b038616815284602082015283604082015282606082015260a060808201526000613a2260a08301846130c7565b979650505050505050565b600060208284031215613a3f57600080fd5b8151610a2b81613068565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613a93908301846130c7565b969550505050505056fea2646970667358221220e2ad52a24bcfe504f6e72a3537011dff23006983c70992647239373d09abd19664736f6c634300080f0033

Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.