ETH Price: $3,920.82 (-0.33%)

Token

VeeCon 2023 Tickets (VCT23)
 

Overview

Max Total Supply

10,255 VCT23

Holders

6,033

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
4 VCT23
0xee095d8c0986bd3729a04812ccde0e42f0103055
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

VeeCon 2023 is a multi-day superconference where VeeCon 2023 NFT ticket holders will experience a lineup of content, including iconic keynote speeches; innovative educational talks, panels and Q&A sessions; and many empowering collaborative experiences.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
VFTicket

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
No with 200 runs

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

pragma solidity ^0.8.4;

import "../token/ERC4907VF.sol";
import "./VFTokenBaseExtensions.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";

contract VFTicket is ERC4907VF, VFTokenBaseExtensions {
    //Token base URI
    string private _baseUri;

    /**
     * @dev Initializes the contract by setting a `initialBaseUri`, `name`, `symbol`,
     * `controlContractAddress`, `royaltiesContractAddress` and `signer` to the token.
     */
    constructor(
        string memory initialBaseUri,
        string memory name,
        string memory symbol,
        address controlContractAddress,
        address royaltiesContractAddress,
        address signer
    )
        ERC4907VF(name, symbol, signer)
        VFTokenBaseExtensions(controlContractAddress, royaltiesContractAddress)
    {
        string memory contractAddress = Strings.toHexString(
            uint160(address(this)),
            20
        );
        setBaseURI(
            string(
                abi.encodePacked(initialBaseUri, contractAddress, "/tokens/")
            )
        );
    }

    /**
     * @dev Get the base token URI
     */
    function _baseURI() internal view virtual override returns (string memory) {
        return _baseUri;
    }

    /**
     * @dev Update the base token URI
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function setBaseURI(string memory baseUri) public onlyRole(getAdminRole()) {
        _baseUri = baseUri;
    }

    /**
     * @dev Update the set user signer address with `signer`
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function setSigner(address signer)
        public
        override
        onlyRole(getAdminRole())
    {
        super.setSigner(signer);
    }

    /**
     * @dev Permanently lock minting
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function lockMintingPermanently() external onlyRole(getAdminRole()) {
        _lockMintingPermanently();
    }

    /**
     * @dev Set the active/inactive state of minting
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function toggleMintActive() external onlyRole(getAdminRole()) {
        _toggleMintActive();
    }

    /**
     * @dev Set the active/inactive state of burning
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function toggleBurnActive() external onlyRole(getAdminRole()) {
        _toggleBurnActive();
    }

    /**
     * @dev Airdrop `addresses` for `quantity` starting at `startTokenId`
     *
     * Requirements:
     *
     * - the caller must be a minter role
     * - minting must not be locked and must be active
     * - `addresses` and `quantities` must have the same length
     */
    function airdrop(
        address[] calldata addresses,
        uint256[] calldata quantities,
        uint256 startTokenId
    ) external onlyRoles(getMinterRoles()) notLocked mintActive {
        _airdrop(addresses, quantities, startTokenId);
    }

    /**
     * @dev burn `from` token `tokenId`
     *
     * Requirements:
     *
     * - the caller must be a burner role
     * - burning must be active
     */
    function burn(address from, uint256 tokenId)
        external
        onlyRole(getBurnerRole())
        burnActive
    {
        _burn(from, tokenId, false);
    }

    /**
     * @dev setUser `user` for `tokenId` with `expires`
     *
     * Requirements:
     *
     * - the caller must be a minter role
     * - `tokenId` must be minted
     */
    function setUserAdmin(
        uint256 tokenId,
        address user,
        uint64 expires
    ) public onlyRoles(getMinterRoles()) {
        _setUser(tokenId, user, expires);
    }
}

File 2 of 24 : IERC2981.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;

import "../utils/introspection/IERC165.sol";

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

File 3 of 24 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

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

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

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

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

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

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

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

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

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

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

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

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

File 4 of 24 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

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

File 5 of 24 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.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 functionCallWithValue(target, data, 0, "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");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or 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 {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // 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 6 of 24 : 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 7 of 24 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 8 of 24 : 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 9 of 24 : 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 10 of 24 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

File 11 of 24 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _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) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @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] = _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 12 of 24 : IAccessControlVF.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

interface IAccessControlVF {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(
        bytes32 indexed role,
        bytes32 indexed previousAdminRole,
        bytes32 indexed newAdminRole
    );

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(
        bytes32 indexed role,
        address indexed account,
        address indexed sender
    );

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account)
        external
        view
        returns (bool);

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function checkRole(bytes32 role, address account) external view;

    /**
     * @dev Returns bytes of default admin role
     */
    function getAdminRole() external view returns (bytes32);

    /**
     * @dev Returns bytes of token contract role
     */
    function getTokenContractRole() external view returns (bytes32);

    /**
     * @dev Returns bytes of sales contract role
     */
    function getSalesContractRole() external view returns (bytes32);

    /**
     * @dev Returns bytes of burner role
     */
    function getBurnerRole() external view returns (bytes32);

    /**
     * @dev Returns bytes of minter role
     */
    function getMinterRole() external view returns (bytes32);

    /**
     * @dev Returns a bytes array of roles that can be minters
     */
    function getMinterRoles() external view returns (bytes32[] memory);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;

    /**
     * @dev Selects the next minter from the minters array using the current minter index.
     * The current minter index should be incremented after each selection.  If the
     * current minter index + 1 is equal to the minters array length then the current
     * minter index should be set back to 0
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function selectNextMinter() external returns (address payable);

    /**
     * @dev Grants `minter` minter role and adds `minter` to minters array
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function grantMinterRole(address minter) external;

    /**
     * @dev Revokes minter role from `minter` and removes `minter` from minters array
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function revokeMinterRole(address minter) external;

    /**
     * @dev Distributes ETH evenly to all addresses in minters array
     */
    function fundMinters() external payable;
}

File 13 of 24 : VFTokenBaseExtensions.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {AccessControlVFExtension} from "../extensions/accesscontrol/AccessControlVFExtension.sol";
import {RoyaltiesVFExtension} from "../extensions/royalties/RoyaltiesVFExtension.sol";
import {WithdrawVFExtension} from "../extensions/withdraw/WithdrawVFExtension.sol";

abstract contract VFTokenBaseExtensions is
    AccessControlVFExtension,
    RoyaltiesVFExtension,
    WithdrawVFExtension
{
    constructor(
        address controlContractAddress,
        address royaltiesContractAddress
    )
        AccessControlVFExtension(controlContractAddress)
        RoyaltiesVFExtension(royaltiesContractAddress)
    {}

    function setRoyaltiesContract(address royaltiesContractAddress)
        external
        onlyRole(getAdminRole())
    {
        super._setRoyaltiesContract(royaltiesContractAddress);
    }

    function withdrawMoney() external onlyRole(getAdminRole()) {
        super._withdrawMoney();
    }

    function withdrawToken(
        address contractAddress,
        address to,
        uint256 tokenId
    ) external onlyRole(getAdminRole()) {
        super._withdrawToken(contractAddress, to, tokenId);
    }
}

File 14 of 24 : AccessControlVFExtension.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {IAccessControlVF} from "../../access/IAccessControlVF.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

abstract contract AccessControlVFExtension is Context, IERC165 {
    //Contract for function access control
    IAccessControlVF private _controlContract;

    constructor(address controlContractAddress) {
        _controlContract = IAccessControlVF(controlContractAddress);
    }

    modifier onlyRole(bytes32 role) virtual {
        _controlContract.checkRole(role, _msgSender());
        _;
    }

    modifier onlyRoles(bytes32[] memory roles) virtual {
        bool hasRequiredRole = false;
        for (uint256 i; i < roles.length; i++) {
            bytes32 role = roles[i];
            if (_controlContract.hasRole(role, _msgSender())) {
                hasRequiredRole = true;
                break;
            }
        }
        require(hasRequiredRole, "Missing required role");
        _;
    }

    function getAdminRole() public view returns (bytes32) {
        return _controlContract.getAdminRole();
    }

    function getMinterRoles() public view returns (bytes32[] memory) {
        return _controlContract.getMinterRoles();
    }

    function getBurnerRole() public view returns (bytes32) {
        return _controlContract.getBurnerRole();
    }

    /**
     * @dev Update the access control contract
     *
     * Requirements:
     *
     * - the caller must be an admin role
     * - `controlContractAddress` must support the IVFAccesControl interface
     */
    function setControlContract(address controlContractAddress)
        external
        onlyRole(_controlContract.getAdminRole())
    {
        require(
            IERC165(controlContractAddress).supportsInterface(
                type(IAccessControlVF).interfaceId
            ),
            "Contract does not support required interface"
        );
        _controlContract = IAccessControlVF(controlContractAddress);
    }
}

File 15 of 24 : RoyaltiesVFExtension.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {IRoyaltiesVF} from "../../royalties/IRoyaltiesVF.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol";

abstract contract RoyaltiesVFExtension is Context, IERC165, IERC2981 {
    //Contract for function access control
    IRoyaltiesVF private _royaltiesContract;

    constructor(address royaltiesContractAddress) {
        _royaltiesContract = IRoyaltiesVF(royaltiesContractAddress);
    }

    /**
     * @dev Get royalty information for a token based on the `salePrice`
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount)
    {
        return
            _royaltiesContract.royaltyInfo(tokenId, address(this), salePrice);
    }

    /**
     * @dev Update the royalties contract
     *
     * Requirements:
     *
     * - the caller must be an admin role
     * - `royaltiesContractAddress` must support the IRoyaltiesVF interface
     */
    function _setRoyaltiesContract(address royaltiesContractAddress) internal {
        require(
            IERC165(royaltiesContractAddress).supportsInterface(
                type(IRoyaltiesVF).interfaceId
            ),
            "Contract does not support required interface"
        );
        _royaltiesContract = IRoyaltiesVF(royaltiesContractAddress);
    }
}

File 16 of 24 : WithdrawVFExtension.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";

abstract contract WithdrawVFExtension is Context {
    constructor() {}

    /**
     * @dev Withdraw balance on contact to msg sender
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function _withdrawMoney() internal {
        address payable to = payable(_msgSender());
        to.transfer(address(this).balance);
    }

    /**
     * @dev Withdraw token if we need to refund
     *
     * Requirements:
     *
     * - `contractAddress` must support the IVFToken interface
     * - the caller must be an admin role
     */
    function _withdrawToken(
        address contractAddress,
        address to,
        uint256 tokenId
    ) internal {
        IERC721(contractAddress).transferFrom(address(this), to, tokenId);
    }
}

File 17 of 24 : IRoyaltiesVF.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

interface IRoyaltiesVF {
    /**
     * @dev Update the access control contract
     *
     * Requirements:
     *
     * - the caller must be an admin role
     * - `controlContractAddress` must support the IVFAccesControl interface
     */
    function setControlContract(address controlContractAddress) external;

    /**
     * @dev Get royalty information for a contract based on the `salePrice` of a token
     */
    function royaltyInfo(
        uint256,
        address contractAddress,
        uint256 salePrice
    ) external view returns (address receiver, uint256 royaltyAmount);

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function setDefaultRoyalty(address receiver, uint96 feeNumerator) external;

    /**
     * @dev Removes default royalty information.
     */
    function deleteDefaultRoyalty() external;

    /**
     * @dev Sets the royalty information for `contractAddress`.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function setContractRoyalties(
        address contractAddress,
        address receiver,
        uint96 feeNumerator
    ) external;

    /**
     * @dev Removes royalty information for `contractAddress`.
     */
    function resetContractRoyalty(address contractAddress) external;
}

File 18 of 24 : ERC4907VF.sol
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import "./ERC721VF.sol";
import "./IERC4907VF.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

contract ERC4907VF is ERC721VF, IERC4907VF {
    using ECDSA for bytes32;

    struct UserInfo {
        address user;
        uint64 expires;
    }

    mapping(uint256 => UserInfo) internal _users;
    mapping(bytes32 => bool) internal _executed;

    //Address of set user signer
    address private _signer;

    constructor(
        string memory name_,
        string memory symbol_,
        address signer
    ) ERC721VF(name_, symbol_) {
        _signer = signer;
    }

    /**
     * @dev Update the set user signer address with `signer`
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function setSigner(address signer) public virtual {
        _signer = signer;
    }

    function setUser(
        uint256 tokenId,
        address user,
        uint64 expires,
        string calldata orderId,
        uint256 timestamp,
        bytes calldata signature
    ) public virtual {
        bytes32 txHash = _getTxHash(
            _msgSender(),
            tokenId,
            user,
            expires,
            orderId,
            timestamp
        );

        if (!_isValidSignature(txHash, signature)) {
            revert ERC4907VFInvalidSignature();
        }

        if ((timestamp + 15 minutes) <= block.timestamp) {
            revert ERC4907VFTransactionExpired();
        }

        if (!_isApprovedOrOwner(msg.sender, tokenId)) {
            revert ERC4907VFTransferCallerIsNotOwnerNorApproved();
        }

        _setUser(tokenId, user, expires);
    }

    function userOf(uint256 tokenId) public view virtual returns (address) {
        _requireMinted(tokenId);
        return _userOf(tokenId);
    }

    function tokensOfUserIn(
        address user,
        uint256 startIndex,
        uint256 endIndex
    ) public view returns (uint256[] memory userTokens) {
        address currentUserAddress;
        uint256 tokenCount = endIndex - startIndex + 1;

        if (tokenCount == 0) {
            return new uint256[](0);
        } else {
            uint256[] memory result = new uint256[](tokenCount);
            uint256 resultIndex = 0;

            uint256 index = startIndex;
            for (index; index <= endIndex; index++) {
                currentUserAddress = _userOf(index);
                if (currentUserAddress == user) {
                    result[resultIndex++] = index;
                }
            }

            // Downsize the array to fit.
            assembly {
                mstore(result, resultIndex)
            }

            return result;
        }
    }

    function userExpires(uint256 tokenId)
        public
        view
        virtual
        returns (uint256)
    {
        return _users[tokenId].expires;
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool)
    {
        return
            interfaceId == type(IERC4907VF).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    function _userOf(uint256 tokenId) internal view virtual returns (address) {
        if (uint256(_users[tokenId].expires) >= block.timestamp) {
            return _users[tokenId].user;
        } else {
            return _ownerOf(tokenId);
        }
    }

    function _setUser(
        uint256 tokenId,
        address user,
        uint64 expires
    ) internal virtual {
        _requireMinted(tokenId);

        UserInfo storage info = _users[tokenId];

        info.user = user;
        info.expires = 0;

        if (info.user != address(0)) {
            info.expires = expires;
        }

        emit UpdateUser(tokenId, user, expires);
    }

    /**
     * @dev Get the hash of a transaction
     */
    function _getTxHash(
        address sender,
        uint256 tokenId,
        address user,
        uint64 expires,
        string calldata orderId,
        uint256 timestamp
    ) internal pure returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(
                    sender,
                    tokenId,
                    user,
                    expires,
                    orderId,
                    timestamp
                )
            );
    }

    /**
     * @dev Validate a tx is signed by the signer address
     */
    function _isValidSignature(bytes32 txHash, bytes calldata signature)
        internal
        view
        returns (bool isValid)
    {
        address signer = txHash.toEthSignedMessageHash().recover(signature);
        return signer == _signer;
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId,
        uint256 batch
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId, batch);

        if (from == to) {
            return;
        }

        address user = _users[tokenId].user;
        if (user == address(0)) {
            return;
        }

        delete _users[tokenId];
        emit UpdateUser(tokenId, address(0), 0);
    }
}

File 19 of 24 : ERC721VF.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721VF.sol";
import "operator-filter-registry/src/DefaultOperatorFilterer.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension.
 */
contract ERC721VF is Context, ERC165, IERC721VF, DefaultOperatorFilterer {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

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

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

    // The number of tokens minted
    uint256 private _mintCounter;

    // The number of tokens burned
    uint256 private _burnCounter;

    //Flag to permanently lock minting
    bool public mintingPermanentlyLocked = false;
    //Flag to activate or disable minting
    bool public isMintActive = false;
    //Flag to activate or disable burning
    bool public isBurnActive = false;

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

    modifier notLocked() virtual {
        if (mintingPermanentlyLocked) {
            revert ERC721VFMintingPermanentlyLocked();
        }
        _;
    }

    modifier mintActive() virtual {
        if (!isMintActive) {
            revert ERC721VFMintIsNotActive();
        }
        _;
    }

    modifier burnActive() virtual {
        if (!isBurnActive) {
            revert ERC721VFBurnIsNotActive();
        }
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC165, IERC165)
        returns (bool)
    {
        return
            interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721
            interfaceId == 0x5b5e139f || // ERC165 interface ID for ERC721Metadata
            interfaceId == type(IERC721VF).interfaceId || // ERC165 interface ID for ERC721VF.
            super.supportsInterface(interfaceId); // ERC165 interface ID for ERC165
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner)
        public
        view
        virtual
        override
        returns (uint256)
    {
        if (owner == address(0)) {
            revert ERC721VFAddressZeroIsNotAValidOwner();
        }

        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        address owner = _ownerOf(tokenId);
        if (owner == address(0)) {
            revert ERC721VFInvalidTokenID(tokenId);
        }
        return owner;
    }

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

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

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

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

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

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

        if (_msgSender() != owner && !isApprovedForAll(owner, _msgSender())) {
            revert ERC721VFApproveCallerIsNotTokenOwnerOrApprovedForAll(
                to,
                tokenId
            );
        }

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId)
        public
        view
        virtual
        override
        returns (address)
    {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

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

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

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override onlyAllowedOperator(from) {
        _transferFrom(from, to, tokenId, true);
    }

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

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public virtual override onlyAllowedOperator(from) {
        _safeTransferFrom(from, to, tokenId, true, data);
    }

    /**
     * @dev See {IERC721VF-totalSupply}.
     */
    function totalSupply() public view returns (uint256) {
        unchecked {
            return _mintCounter - _burnCounter;
        }
    }

    /**
     * @dev See {IERC721VF-totalMinted}.
     */
    function totalMinted() public view returns (uint256) {
        unchecked {
            return _mintCounter;
        }
    }

    /**
     * @dev See {IERC721VF-totalBurned}.
     */
    function totalBurned() public view returns (uint256) {
        unchecked {
            return _burnCounter;
        }
    }

    /**
     * @dev See {IERC721VF-tokensOfOwner}.
     */
    function tokensOfOwner(address owner)
        public
        view
        returns (uint256[] memory ownerTokens)
    {
        address currentOwnerAddress;
        uint256 tokenCount = balanceOf(owner);

        if (tokenCount == 0) {
            return new uint256[](0);
        } else {
            uint256[] memory result = new uint256[](tokenCount);
            uint256 resultIndex = 0;

            uint256 index;
            for (index = 0; resultIndex != tokenCount; index++) {
                currentOwnerAddress = _owners[index];
                if (currentOwnerAddress == owner) {
                    result[resultIndex++] = index;
                }
            }

            return result;
        }
    }

    /**
     * @dev See {IERC721VF-tokensOfOwnerIn}.
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 startIndex,
        uint256 endIndex
    ) public view returns (uint256[] memory ownerTokens) {
        address currentOwnerAddress;
        uint256 tokenCount = balanceOf(owner);

        if (tokenCount == 0) {
            return new uint256[](0);
        } else {
            uint256[] memory result = new uint256[](tokenCount);
            uint256 resultIndex = 0;

            uint256 index = startIndex;
            for (index; index <= endIndex; index++) {
                currentOwnerAddress = _owners[index];
                if (currentOwnerAddress == owner) {
                    result[resultIndex++] = index;
                }
            }

            // Downsize the array to fit.
            assembly {
                mstore(result, resultIndex)
            }

            return result;
        }
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function _transferFrom(
        address from,
        address to,
        uint256 tokenId,
        bool approvalCheck
    ) internal virtual {
        //solhint-disable-next-line max-line-length

        if (approvalCheck) {
            if (!_isApprovedOrOwner(_msgSender(), tokenId)) {
                revert ERC721VFCallerIsNotTokenOwnerOrApproved(
                    from,
                    to,
                    tokenId
                );
            }
        }

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function _safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bool approvalCheck
    ) internal virtual {
        _safeTransferFrom(from, to, tokenId, approvalCheck, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function _safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bool approvalCheck,
        bytes memory data
    ) internal virtual {
        if (approvalCheck) {
            if (!_isApprovedOrOwner(_msgSender(), tokenId)) {
                revert ERC721VFCallerIsNotTokenOwnerOrApproved(
                    from,
                    to,
                    tokenId
                );
            }
        }
        _safeTransfer(from, to, tokenId, data);
    }

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

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

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

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

    /**
     * @dev Permanently lock minting
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function _lockMintingPermanently() internal {
        mintingPermanentlyLocked = true;
    }

    /**
     * @dev Set the active/inactive state of minting
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function _toggleMintActive() internal {
        isMintActive = !isMintActive;
    }

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

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _mint(to, tokenId);
        if (!_checkOnERC721Received(address(0), to, tokenId, data)) {
            revert ERC721VFTransferToNonERC721VFReceiverImplementer(
                to,
                tokenId
            );
        }
    }

    /**
     * @dev Safely batch mints tokens starting at `startTokenId` until `quantity` is met and transfers them to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     * - Transfer to only ERC721Reciever implementers
     *
     * Emits a {Transfer} event.
     */
    function _safeMintBatch(
        address to,
        uint256 quantity,
        uint256 startTokenId
    ) internal returns (uint256 endToken) {
        uint256 tokenId = startTokenId;
        for (uint256 i; i < quantity; i++) {
            if (to == address(0)) {
                revert ERC721VFMintToTheZeroAddress();
            }

            if (_exists(tokenId)) {
                revert ERC721VFTokenAlreadyMinted(tokenId);
            }

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

            _balances[to] += 1;
            _owners[tokenId] = to;

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

            _afterTokenTransfer(address(0), to, tokenId, 1);

            if (!_checkOnERC721Received(address(0), to, tokenId, "")) {
                revert ERC721VFTransferToNonERC721VFReceiverImplementer(
                    to,
                    tokenId
                );
            }

            tokenId++;
        }

        unchecked {
            _mintCounter += quantity;
        }

        return tokenId;
    }

    /**
     * @dev Airdrop `addresses` for `quantity` starting at `startTokenId`
     *
     * Requirements:
     *
     * - the caller must be a minter role
     * - minting must not be locked and must be active
     * - `addresses` and `quantities` must have the same length
     */
    function _airdrop(
        address[] calldata addresses,
        uint256[] calldata quantities,
        uint256 startTokenId
    ) internal virtual {
        if (addresses.length != quantities.length) {
            revert ERC721VFAddressAndQuantitiesNeedToBeEqualLength();
        }

        for (uint256 i; i < addresses.length; i++) {
            startTokenId = _mintBatch(
                addresses[i],
                quantities[i],
                startTokenId
            );
        }
    }

    /**
     * @dev Batch mints tokens starting at `startTokenId` until `quantity` is met and transfers them to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _mintBatch(
        address to,
        uint256 quantity,
        uint256 startTokenId
    ) internal virtual returns (uint256 endToken) {
        uint256 tokenId = startTokenId;
        for (uint256 i; i < quantity; i++) {
            if (to == address(0)) {
                revert ERC721VFMintToTheZeroAddress();
            }

            if (_exists(tokenId)) {
                revert ERC721VFTokenAlreadyMinted(tokenId);
            }

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

            _owners[tokenId] = to;

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

            _afterTokenTransfer(address(0), to, tokenId, 1);

            tokenId++;
        }

        unchecked {
            _balances[to] += quantity;
            _mintCounter += quantity;
        }

        return tokenId;
    }

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

        if (_exists(tokenId)) {
            revert ERC721VFTokenAlreadyMinted(tokenId);
        }

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

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

        unchecked {
            _mintCounter++;
        }

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

        _afterTokenTransfer(address(0), to, tokenId, 1);
    }

    /**
     * @dev Set the active/inactive state of burning
     *
     * Requirements:
     *
     * - the caller must be an admin role
     */
    function _toggleBurnActive() internal {
        isBurnActive = !isBurnActive;
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(
        address from,
        uint256 tokenId,
        bool approvalCheck
    ) internal virtual {
        if (approvalCheck) {
            if (!_isApprovedOrOwner(from, tokenId)) {
                revert ERC721VFBurnCallerIsNotTokenOwnerOrApproved(
                    from,
                    tokenId
                );
            }
        }
        _burn(tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721VF.ownerOf(tokenId);

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

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

        unchecked {
            _burnCounter++;
        }

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

        _afterTokenTransfer(owner, address(0), tokenId, 1);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        if (to == address(0)) {
            revert ERC721VFTransferToTheZeroAddress();
        }

        if (ERC721VF.ownerOf(tokenId) != from) {
            revert ERC721VFTransferFromIncorrectOwner(from, tokenId);
        }

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

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

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        if (owner == operator) {
            revert ERC721VFApproveToCaller();
        }
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        if (!_exists(tokenId)) {
            revert ERC721VFInvalidTokenID(tokenId);
        }
    }

    /**
     * @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()) {
            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 ERC721VFTransferToNonERC721VFReceiverImplementer(
                        to,
                        tokenId
                    );
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

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

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual {}
}

File 20 of 24 : IERC4907VF.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IERC4907VF {
    error ERC4907VFTransferCallerIsNotOwnerNorApproved();
    error ERC4907VFTransactionExpired();
    error ERC4907VFInvalidSignature();

    // Logged when the user of an NFT is changed or expires is changed
    /// @notice Emitted when the `user` of an NFT or the `expires` of the `user` is changed
    /// The zero address for user indicates that there is no user address
    event UpdateUser(
        uint256 indexed tokenId,
        address indexed user,
        uint64 expires
    );

    function setSigner(address signer) external;

    /// @notice set the user and expires of an NFT
    /// @dev The zero address indicates there is no user
    /// Throws if `tokenId` is not valid NFT
    /// @param user  The new user of the NFT
    /// @param expires  UNIX timestamp, The new user could use the NFT before expires
    function setUser(
        uint256 tokenId,
        address user,
        uint64 expires,
        string calldata orderId,
        uint256 timestamp,
        bytes calldata signature
    ) external;

    /// @notice Get the user address of an NFT
    /// @dev The zero address indicates that there is no user or the user is expired
    /// @param tokenId The NFT to get the user address for
    /// @return The user address for this NFT
    function userOf(uint256 tokenId) external view returns (address);

    /// @notice Get the user expires of an NFT
    /// @dev The zero value indicates that there is no user
    /// @param tokenId The NFT to get the user expires for
    /// @return The user expires for this NFT
    function userExpires(uint256 tokenId) external view returns (uint256);

    /// @notice Get the NFTs of an address in a range
    /// @param user The user address to get the NFTs for
    /// @param startIndex The start index of the range
    /// @param endIndex The end index of the range
    function tokensOfUserIn(
        address user,
        uint256 startIndex,
        uint256 endIndex
    ) external view returns (uint256[] memory userTokens);
}

File 21 of 24 : IERC721VF.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

/**
 * @dev Required interface of an ERC721VF compliant contract.
 */
interface IERC721VF is IERC165 {
    error ERC721VFAddressZeroIsNotAValidOwner();
    error ERC721VFInvalidTokenID(uint256 tokenId);
    error ERC721VFApprovalToCurrentOwner(address to, uint256 tokenId);
    error ERC721VFApproveCallerIsNotTokenOwnerOrApprovedForAll(
        address to,
        uint256 tokenId
    );
    error ERC721VFCallerIsNotTokenOwnerOrApproved(
        address from,
        address to,
        uint256 tokenId
    );
    error ERC721VFTransferToNonERC721VFReceiverImplementer(
        address to,
        uint256 tokenId
    );
    error ERC721VFAddressAndQuantitiesNeedToBeEqualLength();
    error ERC721VFMintToTheZeroAddress();
    error ERC721VFTokenAlreadyMinted(uint256 tokenId);
    error ERC721VFTransferToTheZeroAddress();
    error ERC721VFTransferFromIncorrectOwner(address from, uint256 tokenId);
    error ERC721VFApproveToCaller();
    error ERC721VFBurnCallerIsNotTokenOwnerOrApproved(
        address from,
        uint256 tokenId
    );
    error ERC721VFMintingPermanentlyLocked();
    error ERC721VFMintIsNotActive();
    error ERC721VFBurnIsNotActive();

    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

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

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

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

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

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

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

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

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

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

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

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

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

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

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

File 22 of 24 : DefaultOperatorFilterer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {OperatorFilterer} from "./OperatorFilterer.sol";

/**
 * @title  DefaultOperatorFilterer
 * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription.
 */
abstract contract DefaultOperatorFilterer is OperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

    constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {}
}

File 23 of 24 : IOperatorFilterRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

interface IOperatorFilterRegistry {
    function isOperatorAllowed(address registrant, address operator) external view returns (bool);
    function register(address registrant) external;
    function registerAndSubscribe(address registrant, address subscription) external;
    function registerAndCopyEntries(address registrant, address registrantToCopy) external;
    function unregister(address addr) external;
    function updateOperator(address registrant, address operator, bool filtered) external;
    function updateOperators(address registrant, address[] calldata operators, bool filtered) external;
    function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;
    function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;
    function subscribe(address registrant, address registrantToSubscribe) external;
    function unsubscribe(address registrant, bool copyExistingEntries) external;
    function subscriptionOf(address addr) external returns (address registrant);
    function subscribers(address registrant) external returns (address[] memory);
    function subscriberAt(address registrant, uint256 index) external returns (address);
    function copyEntriesOf(address registrant, address registrantToCopy) external;
    function isOperatorFiltered(address registrant, address operator) external returns (bool);
    function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);
    function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);
    function filteredOperators(address addr) external returns (address[] memory);
    function filteredCodeHashes(address addr) external returns (bytes32[] memory);
    function filteredOperatorAt(address registrant, uint256 index) external returns (address);
    function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);
    function isRegistered(address addr) external returns (bool);
    function codeHashOf(address addr) external returns (bytes32);
}

File 24 of 24 : OperatorFilterer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol";

/**
 * @title  OperatorFilterer
 * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another
 *         registrant's entries in the OperatorFilterRegistry.
 * @dev    This smart contract is meant to be inherited by token contracts so they can use the following:
 *         - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods.
 *         - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods.
 */
abstract contract OperatorFilterer {
    error OperatorNotAllowed(address operator);

    IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY =
        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

    constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
        // If an inheriting token contract is deployed to a network without the registry deployed, the modifier
        // will not revert, but the contract will need to be registered with the registry once it is deployed in
        // order for the modifier to filter addresses.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (subscribe) {
                OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
            } else {
                if (subscriptionOrRegistrantToCopy != address(0)) {
                    OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);
                } else {
                    OPERATOR_FILTER_REGISTRY.register(address(this));
                }
            }
        }
    }

    modifier onlyAllowedOperator(address from) virtual {
        // Allow spending tokens from addresses with balance
        // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
        // from an EOA.
        if (from != msg.sender) {
            _checkFilterOperator(msg.sender);
        }
        _;
    }

    modifier onlyAllowedOperatorApproval(address operator) virtual {
        _checkFilterOperator(operator);
        _;
    }

    function _checkFilterOperator(address operator) internal view virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) {
                revert OperatorNotAllowed(operator);
            }
        }
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"initialBaseUri","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"controlContractAddress","type":"address"},{"internalType":"address","name":"royaltiesContractAddress","type":"address"},{"internalType":"address","name":"signer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ERC4907VFInvalidSignature","type":"error"},{"inputs":[],"name":"ERC4907VFTransactionExpired","type":"error"},{"inputs":[],"name":"ERC4907VFTransferCallerIsNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ERC721VFAddressAndQuantitiesNeedToBeEqualLength","type":"error"},{"inputs":[],"name":"ERC721VFAddressZeroIsNotAValidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721VFApprovalToCurrentOwner","type":"error"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721VFApproveCallerIsNotTokenOwnerOrApprovedForAll","type":"error"},{"inputs":[],"name":"ERC721VFApproveToCaller","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721VFBurnCallerIsNotTokenOwnerOrApproved","type":"error"},{"inputs":[],"name":"ERC721VFBurnIsNotActive","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721VFCallerIsNotTokenOwnerOrApproved","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721VFInvalidTokenID","type":"error"},{"inputs":[],"name":"ERC721VFMintIsNotActive","type":"error"},{"inputs":[],"name":"ERC721VFMintToTheZeroAddress","type":"error"},{"inputs":[],"name":"ERC721VFMintingPermanentlyLocked","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721VFTokenAlreadyMinted","type":"error"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721VFTransferFromIncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721VFTransferToNonERC721VFReceiverImplementer","type":"error"},{"inputs":[],"name":"ERC721VFTransferToTheZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"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":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint64","name":"expires","type":"uint64"}],"name":"UpdateUser","type":"event"},{"inputs":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"quantities","type":"uint256[]"},{"internalType":"uint256","name":"startTokenId","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAdminRole","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"getBurnerRole","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinterRoles","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"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":"isBurnActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockMintingPermanently","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintingPermanentlyLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"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":"controlContractAddress","type":"address"}],"name":"setControlContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"royaltiesContractAddress","type":"address"}],"name":"setRoyaltiesContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"expires","type":"uint64"},{"internalType":"string","name":"orderId","type":"string"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"setUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"expires","type":"uint64"}],"name":"setUserAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleBurnActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleMintActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"ownerTokens","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"endIndex","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"ownerTokens","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"endIndex","type":"uint256"}],"name":"tokensOfUserIn","outputs":[{"internalType":"uint256[]","name":"userTokens","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"userExpires","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"userOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawMoney","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526000600860006101000a81548160ff0219169083151502179055506000600860016101000a81548160ff0219169083151502179055506000600860026101000a81548160ff0219169083151502179055503480156200006257600080fd5b5060405162006e3338038062006e338339818101604052810190620000889190620009be565b828280828888868282733cc6cdda760b79bafa08df41ecfa224f810dceb6600160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156200029d57801562000163576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b81526004016200012992919062000ac8565b600060405180830381600087803b1580156200014457600080fd5b505af115801562000159573d6000803e3d6000fd5b505050506200029c565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146200021d576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b8152600401620001e392919062000ac8565b600060405180830381600087803b158015620001fe57600080fd5b505af115801562000213573d6000803e3d6000fd5b505050506200029b565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b815260040162000266919062000af5565b600060405180830381600087803b1580156200028157600080fd5b505af115801562000296573d6000803e3d6000fd5b505050505b5b5b50508160009081620002b0919062000d5d565b508060019081620002c2919062000d5d565b50505080600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505080600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505080600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050506000620003bf3073ffffffffffffffffffffffffffffffffffffffff1660146200040260201b6200225f1760201c565b9050620003f58782604051602001620003da92919062000ed6565b6040516020818303038152906040526200065d60201b60201c565b505050505050506200114b565b60606000600283600262000417919062000f3a565b62000423919062000f85565b67ffffffffffffffff8111156200043f576200043e620007f5565b5b6040519080825280601f01601f191660200182016040528015620004725781602001600182028036833780820191505090505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110620004ad57620004ac62000fc0565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811062000514576200051362000fc0565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000600184600262000556919062000f3a565b62000562919062000f85565b90505b60018111156200060c577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110620005a857620005a762000fc0565b5b1a60f81b828281518110620005c257620005c162000fc0565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c945080620006049062000fef565b905062000565565b506000841462000653576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200064a906200107e565b60405180910390fd5b8091505092915050565b6200066d6200072360201b60201c565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82620006bc620007be60201b60201c565b6040518363ffffffff1660e01b8152600401620006db929190620010bb565b60006040518083038186803b158015620006f457600080fd5b505afa15801562000709573d6000803e3d6000fd5b5050505081600e90816200071e919062000d5d565b505050565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b3ecf2366040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000793573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620007b9919062001119565b905090565b600033905090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200082f82620007e4565b810181811067ffffffffffffffff82111715620008515762000850620007f5565b5b80604052505050565b600062000866620007c6565b905062000874828262000824565b919050565b600067ffffffffffffffff821115620008975762000896620007f5565b5b620008a282620007e4565b9050602081019050919050565b60005b83811015620008cf578082015181840152602081019050620008b2565b60008484015250505050565b6000620008f2620008ec8462000879565b6200085a565b905082815260208101848484011115620009115762000910620007df565b5b6200091e848285620008af565b509392505050565b600082601f8301126200093e576200093d620007da565b5b815162000950848260208601620008db565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620009868262000959565b9050919050565b620009988162000979565b8114620009a457600080fd5b50565b600081519050620009b8816200098d565b92915050565b60008060008060008060c08789031215620009de57620009dd620007d0565b5b600087015167ffffffffffffffff811115620009ff57620009fe620007d5565b5b62000a0d89828a0162000926565b965050602087015167ffffffffffffffff81111562000a315762000a30620007d5565b5b62000a3f89828a0162000926565b955050604087015167ffffffffffffffff81111562000a635762000a62620007d5565b5b62000a7189828a0162000926565b945050606062000a8489828a01620009a7565b935050608062000a9789828a01620009a7565b92505060a062000aaa89828a01620009a7565b9150509295509295509295565b62000ac28162000979565b82525050565b600060408201905062000adf600083018562000ab7565b62000aee602083018462000ab7565b9392505050565b600060208201905062000b0c600083018462000ab7565b92915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168062000b6557607f821691505b60208210810362000b7b5762000b7a62000b1d565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830262000be57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000ba6565b62000bf1868362000ba6565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b600062000c3e62000c3862000c328462000c09565b62000c13565b62000c09565b9050919050565b6000819050919050565b62000c5a8362000c1d565b62000c7262000c698262000c45565b84845462000bb3565b825550505050565b600090565b62000c8962000c7a565b62000c9681848462000c4f565b505050565b5b8181101562000cbe5762000cb260008262000c7f565b60018101905062000c9c565b5050565b601f82111562000d0d5762000cd78162000b81565b62000ce28462000b96565b8101602085101562000cf2578190505b62000d0a62000d018562000b96565b83018262000c9b565b50505b505050565b600082821c905092915050565b600062000d326000198460080262000d12565b1980831691505092915050565b600062000d4d838362000d1f565b9150826002028217905092915050565b62000d688262000b12565b67ffffffffffffffff81111562000d845762000d83620007f5565b5b62000d90825462000b4c565b62000d9d82828562000cc2565b600060209050601f83116001811462000dd5576000841562000dc0578287015190505b62000dcc858262000d3f565b86555062000e3c565b601f19841662000de58662000b81565b60005b8281101562000e0f5784890151825560018201915060208501945060208101905062000de8565b8683101562000e2f578489015162000e2b601f89168262000d1f565b8355505b6001600288020188555050505b505050505050565b600081905092915050565b600062000e5c8262000b12565b62000e68818562000e44565b935062000e7a818560208601620008af565b80840191505092915050565b7f2f746f6b656e732f000000000000000000000000000000000000000000000000600082015250565b600062000ebe60088362000e44565b915062000ecb8262000e86565b600882019050919050565b600062000ee4828562000e4f565b915062000ef2828462000e4f565b915062000eff8262000eaf565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600062000f478262000c09565b915062000f548362000c09565b925082820262000f648162000c09565b9150828204841483151762000f7e5762000f7d62000f0b565b5b5092915050565b600062000f928262000c09565b915062000f9f8362000c09565b925082820190508082111562000fba5762000fb962000f0b565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600062000ffc8262000c09565b91506000820362001012576200101162000f0b565b5b600182039050919050565b600082825260208201905092915050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b6000620010666020836200101d565b915062001073826200102e565b602082019050919050565b60006020820190508181036000830152620010998162001057565b9050919050565b6000819050919050565b620010b581620010a0565b82525050565b6000604082019050620010d26000830185620010aa565b620010e1602083018462000ab7565b9392505050565b620010f381620010a0565b8114620010ff57600080fd5b50565b6000815190506200111381620010e8565b92915050565b600060208284031215620011325762001131620007d0565b5b6000620011428482850162001102565b91505092915050565b615cd8806200115b6000396000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c806395d89b4111610146578063bb7648b6116100c3578063ca35e8a011610087578063ca35e8a01461070c578063d02c2bf214610728578063d89135cd14610732578063dd5adf0c14610750578063e985e9c51461076e578063f5e92b951461079e5761025e565b8063bb7648b614610668578063c2f1f14a14610672578063c43c7696146106a2578063c5b66dc9146106be578063c87b56dd146106dc5761025e565b8063ac4460021161010a578063ac446002146105ea578063b166da42146105f4578063b1a6676e14610610578063b3ecf2361461062e578063b88d4fde1461064c5761025e565b806395d89b411461054657806399a2557a146105645780639dc29fac14610594578063a22cb465146105b0578063a2309ff8146105cc5761025e565b80634aad9676116101df5780636c19e783116101a35780636c19e7831461046257806370a082311461047e578063731186eb146104ae5780637f867deb146104ca5780638462151c146104e65780638fc88c48146105165761025e565b80634aad9676146103be57806355f804b3146103ee5780635b92ac0d1461040a5780635bc0997c146104285780636352211e146104325761025e565b806318160ddd1161022657806318160ddd1461031957806323b872dd146103375780632a55205a1461035357806341f434341461038457806342842e0e146103a25761025e565b806301e336671461026357806301ffc9a71461027f57806306fdde03146102af578063081812fc146102cd578063095ea7b3146102fd575b600080fd5b61027d600480360381019061027891906141c0565b6107bc565b005b6102996004803603810190610294919061426b565b610869565b6040516102a691906142b3565b60405180910390f35b6102b76108e3565b6040516102c4919061435e565b60405180910390f35b6102e760048036038101906102e29190614380565b610975565b6040516102f491906143bc565b60405180910390f35b610317600480360381019061031291906143d7565b6109bb565b005b610321610ae9565b60405161032e9190614426565b60405180910390f35b610351600480360381019061034c91906141c0565b610af7565b005b61036d60048036038101906103689190614441565b610b48565b60405161037b929190614481565b60405180910390f35b61038c610bf5565b6040516103999190614509565b60405180910390f35b6103bc60048036038101906103b791906141c0565b610c07565b005b6103d860048036038101906103d39190614524565b610c58565b6040516103e59190614635565b60405180910390f35b6104086004803603810190610403919061478c565b610dbe565b005b610412610e6e565b60405161041f91906142b3565b60405180910390f35b610430610e81565b005b61044c60048036038101906104479190614380565b610f28565b60405161045991906143bc565b60405180910390f35b61047c600480360381019061047791906147d5565b610fb0565b005b610498600480360381019061049391906147d5565b611059565b6040516104a59190614426565b60405180910390f35b6104c860048036038101906104c391906148b8565b611107565b005b6104e460048036038101906104df919061498d565b6112e7565b005b61050060048036038101906104fb91906147d5565b611436565b60405161050d9190614635565b60405180910390f35b610530600480360381019061052b9190614380565b6115b0565b60405161053d9190614426565b60405180910390f35b61054e6115ee565b60405161055b919061435e565b60405180910390f35b61057e60048036038101906105799190614524565b611680565b60405161058b9190614635565b60405180910390f35b6105ae60048036038101906105a991906143d7565b611802565b005b6105ca60048036038101906105c59190614a0c565b6118f5565b005b6105d4611916565b6040516105e19190614426565b60405180910390f35b6105f2611920565b005b61060e600480360381019061060991906147d5565b6119c7565b005b610618611a70565b60405161062591906142b3565b60405180910390f35b610636611a83565b6040516106439190614a65565b60405180910390f35b61066660048036038101906106619190614b21565b611b1b565b005b610670611b6e565b005b61068c60048036038101906106879190614380565b611c15565b60405161069991906143bc565b60405180910390f35b6106bc60048036038101906106b79190614c50565b611c30565b005b6106c6611d27565b6040516106d39190614a65565b60405180910390f35b6106f660048036038101906106f19190614380565b611dbf565b604051610703919061435e565b60405180910390f35b610726600480360381019061072191906147d5565b611e27565b005b61073061206a565b005b61073a612111565b6040516107479190614426565b60405180910390f35b61075861211b565b6040516107659190614ddd565b60405180910390f35b61078860048036038101906107839190614dff565b6121b8565b60405161079591906142b3565b60405180910390f35b6107a661224c565b6040516107b391906142b3565b60405180910390f35b6107c4611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad8261080b61249b565b6040518363ffffffff1660e01b8152600401610828929190614e3f565b60006040518083038186803b15801561084057600080fd5b505afa158015610854573d6000803e3d6000fd5b505050506108638484846124a3565b50505050565b60007fafb17a61000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108dc57506108db82612517565b5b9050919050565b6060600080546108f290614e97565b80601f016020809104026020016040519081016040528092919081815260200182805461091e90614e97565b801561096b5780601f106109405761010080835404028352916020019161096b565b820191906000526020600020905b81548152906001019060200180831161094e57829003601f168201915b5050505050905090565b6000610980826125f1565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b816109c58161263e565b60006109d083610f28565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610a445783836040517f26ac089f000000000000000000000000000000000000000000000000000000008152600401610a3b929190614481565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610a6361249b565b73ffffffffffffffffffffffffffffffffffffffff1614158015610a955750610a9381610a8e61249b565b6121b8565b155b15610ad95783836040517fb1ab84a4000000000000000000000000000000000000000000000000000000008152600401610ad0929190614481565b60405180910390fd5b610ae3848461273b565b50505050565b600060075460065403905090565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610b3557610b343361263e565b5b610b4284848460016127f4565b50505050565b600080600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b8ca29d58530866040518463ffffffff1660e01b8152600401610baa93929190614ec8565b6040805180830381865afa158015610bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bea9190614f29565b915091509250929050565b6daaeb6d7670e522a718067333cd4e81565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c4557610c443361263e565b5b610c528484846001612862565b50505050565b606060008060018585610c6b9190614f98565b610c759190614fcc565b905060008103610cd257600067ffffffffffffffff811115610c9a57610c99614661565b5b604051908082528060200260200182016040528015610cc85781602001602082028036833780820191505090505b5092505050610db7565b60008167ffffffffffffffff811115610cee57610ced614661565b5b604051908082528060200260200182016040528015610d1c5781602001602082028036833780820191505090505b5090506000808790505b868111610dab57610d3681612884565b94508873ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610d985780838380610d7890615000565b945081518110610d8b57610d8a615048565b5b6020026020010181815250505b8080610da390615000565b915050610d26565b81835282955050505050505b9392505050565b610dc6611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82610e0d61249b565b6040518363ffffffff1660e01b8152600401610e2a929190614e3f565b60006040518083038186803b158015610e4257600080fd5b505afa158015610e56573d6000803e3d6000fd5b5050505081600e9081610e699190615219565b505050565b600860019054906101000a900460ff1681565b610e89611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82610ed061249b565b6040518363ffffffff1660e01b8152600401610eed929190614e3f565b60006040518083038186803b158015610f0557600080fd5b505afa158015610f19573d6000803e3d6000fd5b50505050610f25612910565b50565b600080610f348361293c565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610fa757826040517fb718b687000000000000000000000000000000000000000000000000000000008152600401610f9e9190614426565b60405180910390fd5b80915050919050565b610fb8611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82610fff61249b565b6040518363ffffffff1660e01b815260040161101c929190614e3f565b60006040518083038186803b15801561103457600080fd5b505afa158015611048573d6000803e3d6000fd5b5050505061105582612979565b5050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036110c0576040517f560440d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b61110f61211b565b6000805b825181101561120357600083828151811061113157611130615048565b5b60200260200101519050600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166391d148548261118261249b565b6040518363ffffffff1660e01b815260040161119f929190614e3f565b602060405180830381865afa1580156111bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e09190615300565b156111ef576001925050611203565b5080806111fb90615000565b915050611113565b5080611244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161123b90615379565b60405180910390fd5b600860009054906101000a900460ff161561128b576040517fb8ef635100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600860019054906101000a900460ff166112d1576040517f59e4eebe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112de87878787876129bd565b50505050505050565b6112ef61211b565b6000805b82518110156113e357600083828151811061131157611310615048565b5b60200260200101519050600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166391d148548261136261249b565b6040518363ffffffff1660e01b815260040161137f929190614e3f565b602060405180830381865afa15801561139c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c09190615300565b156113cf5760019250506113e3565b5080806113db90615000565b9150506112f3565b5080611424576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141b90615379565b60405180910390fd5b61142f858585612a72565b5050505050565b606060008061144484611059565b9050600081036114a157600067ffffffffffffffff81111561146957611468614661565b5b6040519080825280602002602001820160405280156114975781602001602082028036833780820191505090505b50925050506115ab565b60008167ffffffffffffffff8111156114bd576114bc614661565b5b6040519080825280602002602001820160405280156114eb5781602001602082028036833780820191505090505b5090506000805b8382146115a2576002600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1694508673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361158f578083838061156f90615000565b94508151811061158257611581615048565b5b6020026020010181815250505b808061159a90615000565b9150506114f2565b82955050505050505b919050565b60006009600083815260200190815260200160002060000160149054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b6060600180546115fd90614e97565b80601f016020809104026020016040519081016040528092919081815260200182805461162990614e97565b80156116765780601f1061164b57610100808354040283529160200191611676565b820191906000526020600020905b81548152906001019060200180831161165957829003601f168201915b5050505050905090565b606060008061168e86611059565b9050600081036116eb57600067ffffffffffffffff8111156116b3576116b2614661565b5b6040519080825280602002602001820160405280156116e15781602001602082028036833780820191505090505b50925050506117fb565b60008167ffffffffffffffff81111561170757611706614661565b5b6040519080825280602002602001820160405280156117355781602001602082028036833780820191505090505b5090506000808790505b8681116117ef576002600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1694508873ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036117dc57808383806117bc90615000565b9450815181106117cf576117ce615048565b5b6020026020010181815250505b80806117e790615000565b91505061173f565b81835282955050505050505b9392505050565b61180a611d27565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad8261185161249b565b6040518363ffffffff1660e01b815260040161186e929190614e3f565b60006040518083038186803b15801561188657600080fd5b505afa15801561189a573d6000803e3d6000fd5b50505050600860029054906101000a900460ff166118e4576040517febb5afac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118f083836000612bda565b505050565b816118ff8161263e565b61191161190a61249b565b8484612c3c565b505050565b6000600654905090565b611928611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad8261196f61249b565b6040518363ffffffff1660e01b815260040161198c929190614e3f565b60006040518083038186803b1580156119a457600080fd5b505afa1580156119b8573d6000803e3d6000fd5b505050506119c4612d9f565b50565b6119cf611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82611a1661249b565b6040518363ffffffff1660e01b8152600401611a33929190614e3f565b60006040518083038186803b158015611a4b57600080fd5b505afa158015611a5f573d6000803e3d6000fd5b50505050611a6c82612df5565b5050565b600860029054906101000a900460ff1681565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b3ecf2366040518163ffffffff1660e01b8152600401602060405180830381865afa158015611af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1691906153c5565b905090565b833373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b5957611b583361263e565b5b611b67858585600186612f12565b5050505050565b611b76611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82611bbd61249b565b6040518363ffffffff1660e01b8152600401611bda929190614e3f565b60006040518083038186803b158015611bf257600080fd5b505afa158015611c06573d6000803e3d6000fd5b50505050611c12612f82565b50565b6000611c20826125f1565b611c2982612884565b9050919050565b6000611c48611c3d61249b565b8a8a8a8a8a8a612f9f565b9050611c55818484612fe1565b611c8b576040517f4a484b6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4261038485611c9a9190614fcc565b11611cd1576040517fa0724e6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdb338a6130a0565b611d11576040517f795cf3b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d1c898989612a72565b505050505050505050565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c5b66dc96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dba91906153c5565b905090565b6060611dca826125f1565b6000611dd4613135565b90506000815111611df45760405180602001604052806000815250611e1f565b80611dfe846131c7565b604051602001611e0f92919061542e565b6040516020818303038152906040525b915050919050565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b3ecf2366040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eb891906153c5565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82611eff61249b565b6040518363ffffffff1660e01b8152600401611f1c929190614e3f565b60006040518083038186803b158015611f3457600080fd5b505afa158015611f48573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff166301ffc9a77f0b7162d4000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b8152600401611fa59190615461565b602060405180830381865afa158015611fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe69190615300565b612025576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161201c906154ee565b60405180910390fd5b81600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b612072611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad826120b961249b565b6040518363ffffffff1660e01b81526004016120d6929190614e3f565b60006040518083038186803b1580156120ee57600080fd5b505afa158015612102573d6000803e3d6000fd5b5050505061210e613295565b50565b6000600754905090565b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd5adf0c6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906121b391906155d1565b905090565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600860009054906101000a900460ff1681565b606060006002836002612272919061561a565b61227c9190614fcc565b67ffffffffffffffff81111561229557612294614661565b5b6040519080825280601f01601f1916602001820160405280156122c75781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106122ff576122fe615048565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061236357612362615048565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026123a3919061561a565b6123ad9190614fcc565b90505b600181111561244d577f3031323334353637383961626364656600000000000000000000000000000000600f8616601081106123ef576123ee615048565b5b1a60f81b82828151811061240657612405615048565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806124469061565c565b90506123b0565b5060008414612491576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612488906156d1565b60405180910390fd5b8091505092915050565b600033905090565b8273ffffffffffffffffffffffffffffffffffffffff166323b872dd3084846040518463ffffffff1660e01b81526004016124e0939291906156f1565b600060405180830381600087803b1580156124fa57600080fd5b505af115801561250e573d6000803e3d6000fd5b50505050505050565b60006380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806125725750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806125da57507fdbf24b52000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806125ea57506125e9826132c1565b5b9050919050565b6125fa8161332b565b61263b57806040517fb718b6870000000000000000000000000000000000000000000000000000000081526004016126329190614426565b60405180910390fd5b50565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115612738576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b81526004016126b5929190615728565b602060405180830381865afa1580156126d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f69190615300565b61273757806040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161272e91906143bc565b60405180910390fd5b5b50565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166127ae83610f28565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b80156128515761280b61280561249b565b836130a0565b612850578383836040517f0957569f000000000000000000000000000000000000000000000000000000008152600401612847939291906156f1565b60405180910390fd5b5b61285c84848461336c565b50505050565b61287e8484848460405180602001604052806000815250612f12565b50505050565b6000426009600084815260200190815260200160002060000160149054906101000a900467ffffffffffffffff1667ffffffffffffffff16106128ff576009600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061290b565b6129088261293c565b90505b919050565b600860029054906101000a900460ff1615600860026101000a81548160ff021916908315150217905550565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8282905085859050146129fc576040517fa21d27a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85859050811015612a6a57612a55868683818110612a2057612a1f615048565b5b9050602002016020810190612a3591906147d5565b858584818110612a4857612a47615048565b5b90506020020135846135ea565b91508080612a6290615000565b9150506129ff565b505050505050565b612a7b836125f1565b6000600960008581526020019081526020016000209050828160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612b8557818160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b8273ffffffffffffffffffffffffffffffffffffffff16847f4e06b4e7000e659094299b3533b47b6aa8ad048e95e872d23d1f4ee55af89cfe84604051612bcc9190615760565b60405180910390a350505050565b8015612c2e57612bea83836130a0565b612c2d5782826040517fb2b70f89000000000000000000000000000000000000000000000000000000008152600401612c24929190614481565b60405180910390fd5b5b612c3782613800565b505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612ca1576040517ffa447c3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612d9291906142b3565b60405180910390a3505050565b6000612da961249b565b90508073ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015612df1573d6000803e3d6000fd5b5050565b8073ffffffffffffffffffffffffffffffffffffffff166301ffc9a77f84648494000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b8152600401612e4e9190615461565b602060405180830381865afa158015612e6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e8f9190615300565b612ece576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ec5906154ee565b60405180910390fd5b80600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8115612f6f57612f29612f2361249b565b846130a0565b612f6e578484846040517f0957569f000000000000000000000000000000000000000000000000000000008152600401612f65939291906156f1565b60405180910390fd5b5b612f7b85858584613955565b5050505050565b6001600860006101000a81548160ff021916908315150217905550565b600087878787878787604051602001612fbe979695949392919061583f565b604051602081830303815290604052805190602001209050979650505050505050565b60008061304384848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613035876139b5565b6139e590919063ffffffff16565b9050600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16149150509392505050565b6000806130ac83610f28565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806130ee57506130ed81856121b8565b5b8061312c57508373ffffffffffffffffffffffffffffffffffffffff1661311484610975565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b6060600e805461314490614e97565b80601f016020809104026020016040519081016040528092919081815260200182805461317090614e97565b80156131bd5780601f10613192576101008083540402835291602001916131bd565b820191906000526020600020905b8154815290600101906020018083116131a057829003601f168201915b5050505050905090565b6060600060016131d684613a0c565b01905060008167ffffffffffffffff8111156131f5576131f4614661565b5b6040519080825280601f01601f1916602001820160405280156132275781602001600182028036833780820191505090505b509050600082602001820190505b60011561328a578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161327e5761327d6158ad565b5b04945060008503613235575b819350505050919050565b600860019054906101000a900460ff1615600860016101000a81548160ff021916908315150217905550565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff1661334d8361293c565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036133d2576040517fa4aa808000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff166133f282610f28565b73ffffffffffffffffffffffffffffffffffffffff161461344c5782816040517fb04a7806000000000000000000000000000000000000000000000000000000008152600401613443929190614481565b60405180910390fd5b6134598383836001613b5f565b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46135e58383836001613cc5565b505050565b60008082905060005b8481101561379757600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603613661576040517fe7070eb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61366a8261332b565b156136ac57816040517f3dd6ca500000000000000000000000000000000000000000000000000000000081526004016136a39190614426565b60405180910390fd5b6136ba600087846001613b5f565b856002600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613776600087846001613cc5565b818061378190615000565b925050808061378f90615000565b9150506135f3565b5083600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555083600660008282540192505081905550809150509392505050565b600061380b82610f28565b905061381b816000846001613b5f565b6004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560076000815480929190600101919050555081600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613951816000846001613cc5565b5050565b61396084848461336c565b61396c84848484613ccb565b6139af5782826040517ffbf98f280000000000000000000000000000000000000000000000000000000081526004016139a6929190614481565b60405180910390fd5b50505050565b6000816040516020016139c89190615949565b604051602081830303815290604052805190602001209050919050565b60008060006139f48585613e56565b91509150613a0181613ea7565b819250505092915050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310613a6a577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381613a6057613a5f6158ad565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310613aa7576d04ee2d6d415b85acef81000000008381613a9d57613a9c6158ad565b5b0492506020810190505b662386f26fc100008310613ad657662386f26fc100008381613acc57613acb6158ad565b5b0492506010810190505b6305f5e1008310613aff576305f5e1008381613af557613af46158ad565b5b0492506008810190505b6127108310613b24576127108381613b1a57613b196158ad565b5b0492506004810190505b60648310613b475760648381613b3d57613b3c6158ad565b5b0492506002810190505b600a8310613b56576001810190505b80915050919050565b613b6b8484848461400d565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160315613cbf5760006009600084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613c145750613cbf565b60096000848152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a81549067ffffffffffffffff02191690555050600073ffffffffffffffffffffffffffffffffffffffff16837f4e06b4e7000e659094299b3533b47b6aa8ad048e95e872d23d1f4ee55af89cfe6000604051613cb591906159aa565b60405180910390a3505b50505050565b50505050565b6000613cec8473ffffffffffffffffffffffffffffffffffffffff16614013565b15613e49578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613d1561249b565b8786866040518563ffffffff1660e01b8152600401613d379493929190615a1a565b6020604051808303816000875af1925050508015613d7357506040513d601f19601f82011682018060405250810190613d709190615a7b565b60015b613df9573d8060008114613da3576040519150601f19603f3d011682016040523d82523d6000602084013e613da8565b606091505b506000815103613df15784846040517ffbf98f28000000000000000000000000000000000000000000000000000000008152600401613de8929190614481565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613e4e565b600190505b949350505050565b6000806041835103613e975760008060006020860151925060408601519150606086015160001a9050613e8b87828585614036565b94509450505050613ea0565b60006002915091505b9250929050565b60006004811115613ebb57613eba615aa8565b5b816004811115613ece57613ecd615aa8565b5b031561400a5760016004811115613ee857613ee7615aa8565b5b816004811115613efb57613efa615aa8565b5b03613f3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613f3290615b23565b60405180910390fd5b60026004811115613f4f57613f4e615aa8565b5b816004811115613f6257613f61615aa8565b5b03613fa2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613f9990615b8f565b60405180910390fd5b60036004811115613fb657613fb5615aa8565b5b816004811115613fc957613fc8615aa8565b5b03614009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161400090615c21565b60405180910390fd5b5b50565b50505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c111561407157600060039150915061410f565b6000600187878787604051600081526020016040526040516140969493929190615c5d565b6020604051602081039080840390855afa1580156140b8573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036141065760006001925092505061410f565b80600092509250505b94509492505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006141578261412c565b9050919050565b6141678161414c565b811461417257600080fd5b50565b6000813590506141848161415e565b92915050565b6000819050919050565b61419d8161418a565b81146141a857600080fd5b50565b6000813590506141ba81614194565b92915050565b6000806000606084860312156141d9576141d8614122565b5b60006141e786828701614175565b93505060206141f886828701614175565b9250506040614209868287016141ab565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61424881614213565b811461425357600080fd5b50565b6000813590506142658161423f565b92915050565b60006020828403121561428157614280614122565b5b600061428f84828501614256565b91505092915050565b60008115159050919050565b6142ad81614298565b82525050565b60006020820190506142c860008301846142a4565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156143085780820151818401526020810190506142ed565b60008484015250505050565b6000601f19601f8301169050919050565b6000614330826142ce565b61433a81856142d9565b935061434a8185602086016142ea565b61435381614314565b840191505092915050565b600060208201905081810360008301526143788184614325565b905092915050565b60006020828403121561439657614395614122565b5b60006143a4848285016141ab565b91505092915050565b6143b68161414c565b82525050565b60006020820190506143d160008301846143ad565b92915050565b600080604083850312156143ee576143ed614122565b5b60006143fc85828601614175565b925050602061440d858286016141ab565b9150509250929050565b6144208161418a565b82525050565b600060208201905061443b6000830184614417565b92915050565b6000806040838503121561445857614457614122565b5b6000614466858286016141ab565b9250506020614477858286016141ab565b9150509250929050565b600060408201905061449660008301856143ad565b6144a36020830184614417565b9392505050565b6000819050919050565b60006144cf6144ca6144c58461412c565b6144aa565b61412c565b9050919050565b60006144e1826144b4565b9050919050565b60006144f3826144d6565b9050919050565b614503816144e8565b82525050565b600060208201905061451e60008301846144fa565b92915050565b60008060006060848603121561453d5761453c614122565b5b600061454b86828701614175565b935050602061455c868287016141ab565b925050604061456d868287016141ab565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6145ac8161418a565b82525050565b60006145be83836145a3565b60208301905092915050565b6000602082019050919050565b60006145e282614577565b6145ec8185614582565b93506145f783614593565b8060005b8381101561462857815161460f88826145b2565b975061461a836145ca565b9250506001810190506145fb565b5085935050505092915050565b6000602082019050818103600083015261464f81846145d7565b905092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61469982614314565b810181811067ffffffffffffffff821117156146b8576146b7614661565b5b80604052505050565b60006146cb614118565b90506146d78282614690565b919050565b600067ffffffffffffffff8211156146f7576146f6614661565b5b61470082614314565b9050602081019050919050565b82818337600083830152505050565b600061472f61472a846146dc565b6146c1565b90508281526020810184848401111561474b5761474a61465c565b5b61475684828561470d565b509392505050565b600082601f83011261477357614772614657565b5b813561478384826020860161471c565b91505092915050565b6000602082840312156147a2576147a1614122565b5b600082013567ffffffffffffffff8111156147c0576147bf614127565b5b6147cc8482850161475e565b91505092915050565b6000602082840312156147eb576147ea614122565b5b60006147f984828501614175565b91505092915050565b600080fd5b600080fd5b60008083601f84011261482257614821614657565b5b8235905067ffffffffffffffff81111561483f5761483e614802565b5b60208301915083602082028301111561485b5761485a614807565b5b9250929050565b60008083601f84011261487857614877614657565b5b8235905067ffffffffffffffff81111561489557614894614802565b5b6020830191508360208202830111156148b1576148b0614807565b5b9250929050565b6000806000806000606086880312156148d4576148d3614122565b5b600086013567ffffffffffffffff8111156148f2576148f1614127565b5b6148fe8882890161480c565b9550955050602086013567ffffffffffffffff81111561492157614920614127565b5b61492d88828901614862565b93509350506040614940888289016141ab565b9150509295509295909350565b600067ffffffffffffffff82169050919050565b61496a8161494d565b811461497557600080fd5b50565b60008135905061498781614961565b92915050565b6000806000606084860312156149a6576149a5614122565b5b60006149b4868287016141ab565b93505060206149c586828701614175565b92505060406149d686828701614978565b9150509250925092565b6149e981614298565b81146149f457600080fd5b50565b600081359050614a06816149e0565b92915050565b60008060408385031215614a2357614a22614122565b5b6000614a3185828601614175565b9250506020614a42858286016149f7565b9150509250929050565b6000819050919050565b614a5f81614a4c565b82525050565b6000602082019050614a7a6000830184614a56565b92915050565b600067ffffffffffffffff821115614a9b57614a9a614661565b5b614aa482614314565b9050602081019050919050565b6000614ac4614abf84614a80565b6146c1565b905082815260208101848484011115614ae057614adf61465c565b5b614aeb84828561470d565b509392505050565b600082601f830112614b0857614b07614657565b5b8135614b18848260208601614ab1565b91505092915050565b60008060008060808587031215614b3b57614b3a614122565b5b6000614b4987828801614175565b9450506020614b5a87828801614175565b9350506040614b6b878288016141ab565b925050606085013567ffffffffffffffff811115614b8c57614b8b614127565b5b614b9887828801614af3565b91505092959194509250565b60008083601f840112614bba57614bb9614657565b5b8235905067ffffffffffffffff811115614bd757614bd6614802565b5b602083019150836001820283011115614bf357614bf2614807565b5b9250929050565b60008083601f840112614c1057614c0f614657565b5b8235905067ffffffffffffffff811115614c2d57614c2c614802565b5b602083019150836001820283011115614c4957614c48614807565b5b9250929050565b60008060008060008060008060c0898b031215614c7057614c6f614122565b5b6000614c7e8b828c016141ab565b9850506020614c8f8b828c01614175565b9750506040614ca08b828c01614978565b965050606089013567ffffffffffffffff811115614cc157614cc0614127565b5b614ccd8b828c01614ba4565b95509550506080614ce08b828c016141ab565b93505060a089013567ffffffffffffffff811115614d0157614d00614127565b5b614d0d8b828c01614bfa565b92509250509295985092959890939650565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614d5481614a4c565b82525050565b6000614d668383614d4b565b60208301905092915050565b6000602082019050919050565b6000614d8a82614d1f565b614d948185614d2a565b9350614d9f83614d3b565b8060005b83811015614dd0578151614db78882614d5a565b9750614dc283614d72565b925050600181019050614da3565b5085935050505092915050565b60006020820190508181036000830152614df78184614d7f565b905092915050565b60008060408385031215614e1657614e15614122565b5b6000614e2485828601614175565b9250506020614e3585828601614175565b9150509250929050565b6000604082019050614e546000830185614a56565b614e6160208301846143ad565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614eaf57607f821691505b602082108103614ec257614ec1614e68565b5b50919050565b6000606082019050614edd6000830186614417565b614eea60208301856143ad565b614ef76040830184614417565b949350505050565b600081519050614f0e8161415e565b92915050565b600081519050614f2381614194565b92915050565b60008060408385031215614f4057614f3f614122565b5b6000614f4e85828601614eff565b9250506020614f5f85828601614f14565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614fa38261418a565b9150614fae8361418a565b9250828203905081811115614fc657614fc5614f69565b5b92915050565b6000614fd78261418a565b9150614fe28361418a565b9250828201905080821115614ffa57614ff9614f69565b5b92915050565b600061500b8261418a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361503d5761503c614f69565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026150d97fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261509c565b6150e3868361509c565b95508019841693508086168417925050509392505050565b600061511661511161510c8461418a565b6144aa565b61418a565b9050919050565b6000819050919050565b615130836150fb565b61514461513c8261511d565b8484546150a9565b825550505050565b600090565b61515961514c565b615164818484615127565b505050565b5b818110156151885761517d600082615151565b60018101905061516a565b5050565b601f8211156151cd5761519e81615077565b6151a78461508c565b810160208510156151b6578190505b6151ca6151c28561508c565b830182615169565b50505b505050565b600082821c905092915050565b60006151f0600019846008026151d2565b1980831691505092915050565b600061520983836151df565b9150826002028217905092915050565b615222826142ce565b67ffffffffffffffff81111561523b5761523a614661565b5b6152458254614e97565b61525082828561518c565b600060209050601f8311600181146152835760008415615271578287015190505b61527b85826151fd565b8655506152e3565b601f19841661529186615077565b60005b828110156152b957848901518255600182019150602085019450602081019050615294565b868310156152d657848901516152d2601f8916826151df565b8355505b6001600288020188555050505b505050505050565b6000815190506152fa816149e0565b92915050565b60006020828403121561531657615315614122565b5b6000615324848285016152eb565b91505092915050565b7f4d697373696e6720726571756972656420726f6c650000000000000000000000600082015250565b60006153636015836142d9565b915061536e8261532d565b602082019050919050565b6000602082019050818103600083015261539281615356565b9050919050565b6153a281614a4c565b81146153ad57600080fd5b50565b6000815190506153bf81615399565b92915050565b6000602082840312156153db576153da614122565b5b60006153e9848285016153b0565b91505092915050565b600081905092915050565b6000615408826142ce565b61541281856153f2565b93506154228185602086016142ea565b80840191505092915050565b600061543a82856153fd565b915061544682846153fd565b91508190509392505050565b61545b81614213565b82525050565b60006020820190506154766000830184615452565b92915050565b7f436f6e747261637420646f6573206e6f7420737570706f72742072657175697260008201527f656420696e746572666163650000000000000000000000000000000000000000602082015250565b60006154d8602c836142d9565b91506154e38261547c565b604082019050919050565b60006020820190508181036000830152615507816154cb565b9050919050565b600067ffffffffffffffff82111561552957615528614661565b5b602082029050602081019050919050565b600061554d6155488461550e565b6146c1565b905080838252602082019050602084028301858111156155705761556f614807565b5b835b81811015615599578061558588826153b0565b845260208401935050602081019050615572565b5050509392505050565b600082601f8301126155b8576155b7614657565b5b81516155c884826020860161553a565b91505092915050565b6000602082840312156155e7576155e6614122565b5b600082015167ffffffffffffffff81111561560557615604614127565b5b615611848285016155a3565b91505092915050565b60006156258261418a565b91506156308361418a565b925082820261563e8161418a565b9150828204841483151761565557615654614f69565b5b5092915050565b60006156678261418a565b91506000820361567a57615679614f69565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b60006156bb6020836142d9565b91506156c682615685565b602082019050919050565b600060208201905081810360008301526156ea816156ae565b9050919050565b600060608201905061570660008301866143ad565b61571360208301856143ad565b6157206040830184614417565b949350505050565b600060408201905061573d60008301856143ad565b61574a60208301846143ad565b9392505050565b61575a8161494d565b82525050565b60006020820190506157756000830184615751565b92915050565b60008160601b9050919050565b60006157938261577b565b9050919050565b60006157a582615788565b9050919050565b6157bd6157b88261414c565b61579a565b82525050565b6000819050919050565b6157de6157d98261418a565b6157c3565b82525050565b60008160c01b9050919050565b60006157fc826157e4565b9050919050565b61581461580f8261494d565b6157f1565b82525050565b600061582683856153f2565b935061583383858461470d565b82840190509392505050565b600061584b828a6157ac565b60148201915061585b82896157cd565b60208201915061586b82886157ac565b60148201915061587b8287615803565b60088201915061588c82858761581a565b915061589882846157cd565b60208201915081905098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000615912601c836153f2565b915061591d826158dc565b601c82019050919050565b6000819050919050565b61594361593e82614a4c565b615928565b82525050565b600061595482615905565b91506159608284615932565b60208201915081905092915050565b6000819050919050565b600061599461598f61598a8461596f565b6144aa565b61494d565b9050919050565b6159a481615979565b82525050565b60006020820190506159bf600083018461599b565b92915050565b600081519050919050565b600082825260208201905092915050565b60006159ec826159c5565b6159f681856159d0565b9350615a068185602086016142ea565b615a0f81614314565b840191505092915050565b6000608082019050615a2f60008301876143ad565b615a3c60208301866143ad565b615a496040830185614417565b8181036060830152615a5b81846159e1565b905095945050505050565b600081519050615a758161423f565b92915050565b600060208284031215615a9157615a90614122565b5b6000615a9f84828501615a66565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b6000615b0d6018836142d9565b9150615b1882615ad7565b602082019050919050565b60006020820190508181036000830152615b3c81615b00565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000615b79601f836142d9565b9150615b8482615b43565b602082019050919050565b60006020820190508181036000830152615ba881615b6c565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000615c0b6022836142d9565b9150615c1682615baf565b604082019050919050565b60006020820190508181036000830152615c3a81615bfe565b9050919050565b600060ff82169050919050565b615c5781615c41565b82525050565b6000608082019050615c726000830187614a56565b615c7f6020830186615c4e565b615c8c6040830185614a56565b615c996060830184614a56565b9594505050505056fea26469706673582212209684551364b5ce7eca20b1c986d55c92f1e68f163e343061174c9b85bb8f373764736f6c6343000811003300000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000cdf831868185c4e92433b2f66a88123523011ecf00000000000000000000000021bbb2f84053197a2455a6c230c2883030b15d0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f68747470733a2f2f6d657461646174612e766565667269656e64732e636f6d2f76322f636f6c6c656374696f6e732f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013566565436f6e2032303233205469636b6574730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055643543233000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061025e5760003560e01c806395d89b4111610146578063bb7648b6116100c3578063ca35e8a011610087578063ca35e8a01461070c578063d02c2bf214610728578063d89135cd14610732578063dd5adf0c14610750578063e985e9c51461076e578063f5e92b951461079e5761025e565b8063bb7648b614610668578063c2f1f14a14610672578063c43c7696146106a2578063c5b66dc9146106be578063c87b56dd146106dc5761025e565b8063ac4460021161010a578063ac446002146105ea578063b166da42146105f4578063b1a6676e14610610578063b3ecf2361461062e578063b88d4fde1461064c5761025e565b806395d89b411461054657806399a2557a146105645780639dc29fac14610594578063a22cb465146105b0578063a2309ff8146105cc5761025e565b80634aad9676116101df5780636c19e783116101a35780636c19e7831461046257806370a082311461047e578063731186eb146104ae5780637f867deb146104ca5780638462151c146104e65780638fc88c48146105165761025e565b80634aad9676146103be57806355f804b3146103ee5780635b92ac0d1461040a5780635bc0997c146104285780636352211e146104325761025e565b806318160ddd1161022657806318160ddd1461031957806323b872dd146103375780632a55205a1461035357806341f434341461038457806342842e0e146103a25761025e565b806301e336671461026357806301ffc9a71461027f57806306fdde03146102af578063081812fc146102cd578063095ea7b3146102fd575b600080fd5b61027d600480360381019061027891906141c0565b6107bc565b005b6102996004803603810190610294919061426b565b610869565b6040516102a691906142b3565b60405180910390f35b6102b76108e3565b6040516102c4919061435e565b60405180910390f35b6102e760048036038101906102e29190614380565b610975565b6040516102f491906143bc565b60405180910390f35b610317600480360381019061031291906143d7565b6109bb565b005b610321610ae9565b60405161032e9190614426565b60405180910390f35b610351600480360381019061034c91906141c0565b610af7565b005b61036d60048036038101906103689190614441565b610b48565b60405161037b929190614481565b60405180910390f35b61038c610bf5565b6040516103999190614509565b60405180910390f35b6103bc60048036038101906103b791906141c0565b610c07565b005b6103d860048036038101906103d39190614524565b610c58565b6040516103e59190614635565b60405180910390f35b6104086004803603810190610403919061478c565b610dbe565b005b610412610e6e565b60405161041f91906142b3565b60405180910390f35b610430610e81565b005b61044c60048036038101906104479190614380565b610f28565b60405161045991906143bc565b60405180910390f35b61047c600480360381019061047791906147d5565b610fb0565b005b610498600480360381019061049391906147d5565b611059565b6040516104a59190614426565b60405180910390f35b6104c860048036038101906104c391906148b8565b611107565b005b6104e460048036038101906104df919061498d565b6112e7565b005b61050060048036038101906104fb91906147d5565b611436565b60405161050d9190614635565b60405180910390f35b610530600480360381019061052b9190614380565b6115b0565b60405161053d9190614426565b60405180910390f35b61054e6115ee565b60405161055b919061435e565b60405180910390f35b61057e60048036038101906105799190614524565b611680565b60405161058b9190614635565b60405180910390f35b6105ae60048036038101906105a991906143d7565b611802565b005b6105ca60048036038101906105c59190614a0c565b6118f5565b005b6105d4611916565b6040516105e19190614426565b60405180910390f35b6105f2611920565b005b61060e600480360381019061060991906147d5565b6119c7565b005b610618611a70565b60405161062591906142b3565b60405180910390f35b610636611a83565b6040516106439190614a65565b60405180910390f35b61066660048036038101906106619190614b21565b611b1b565b005b610670611b6e565b005b61068c60048036038101906106879190614380565b611c15565b60405161069991906143bc565b60405180910390f35b6106bc60048036038101906106b79190614c50565b611c30565b005b6106c6611d27565b6040516106d39190614a65565b60405180910390f35b6106f660048036038101906106f19190614380565b611dbf565b604051610703919061435e565b60405180910390f35b610726600480360381019061072191906147d5565b611e27565b005b61073061206a565b005b61073a612111565b6040516107479190614426565b60405180910390f35b61075861211b565b6040516107659190614ddd565b60405180910390f35b61078860048036038101906107839190614dff565b6121b8565b60405161079591906142b3565b60405180910390f35b6107a661224c565b6040516107b391906142b3565b60405180910390f35b6107c4611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad8261080b61249b565b6040518363ffffffff1660e01b8152600401610828929190614e3f565b60006040518083038186803b15801561084057600080fd5b505afa158015610854573d6000803e3d6000fd5b505050506108638484846124a3565b50505050565b60007fafb17a61000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806108dc57506108db82612517565b5b9050919050565b6060600080546108f290614e97565b80601f016020809104026020016040519081016040528092919081815260200182805461091e90614e97565b801561096b5780601f106109405761010080835404028352916020019161096b565b820191906000526020600020905b81548152906001019060200180831161094e57829003601f168201915b5050505050905090565b6000610980826125f1565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b816109c58161263e565b60006109d083610f28565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610a445783836040517f26ac089f000000000000000000000000000000000000000000000000000000008152600401610a3b929190614481565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610a6361249b565b73ffffffffffffffffffffffffffffffffffffffff1614158015610a955750610a9381610a8e61249b565b6121b8565b155b15610ad95783836040517fb1ab84a4000000000000000000000000000000000000000000000000000000008152600401610ad0929190614481565b60405180910390fd5b610ae3848461273b565b50505050565b600060075460065403905090565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610b3557610b343361263e565b5b610b4284848460016127f4565b50505050565b600080600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b8ca29d58530866040518463ffffffff1660e01b8152600401610baa93929190614ec8565b6040805180830381865afa158015610bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bea9190614f29565b915091509250929050565b6daaeb6d7670e522a718067333cd4e81565b823373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c4557610c443361263e565b5b610c528484846001612862565b50505050565b606060008060018585610c6b9190614f98565b610c759190614fcc565b905060008103610cd257600067ffffffffffffffff811115610c9a57610c99614661565b5b604051908082528060200260200182016040528015610cc85781602001602082028036833780820191505090505b5092505050610db7565b60008167ffffffffffffffff811115610cee57610ced614661565b5b604051908082528060200260200182016040528015610d1c5781602001602082028036833780820191505090505b5090506000808790505b868111610dab57610d3681612884565b94508873ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610d985780838380610d7890615000565b945081518110610d8b57610d8a615048565b5b6020026020010181815250505b8080610da390615000565b915050610d26565b81835282955050505050505b9392505050565b610dc6611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82610e0d61249b565b6040518363ffffffff1660e01b8152600401610e2a929190614e3f565b60006040518083038186803b158015610e4257600080fd5b505afa158015610e56573d6000803e3d6000fd5b5050505081600e9081610e699190615219565b505050565b600860019054906101000a900460ff1681565b610e89611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82610ed061249b565b6040518363ffffffff1660e01b8152600401610eed929190614e3f565b60006040518083038186803b158015610f0557600080fd5b505afa158015610f19573d6000803e3d6000fd5b50505050610f25612910565b50565b600080610f348361293c565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610fa757826040517fb718b687000000000000000000000000000000000000000000000000000000008152600401610f9e9190614426565b60405180910390fd5b80915050919050565b610fb8611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82610fff61249b565b6040518363ffffffff1660e01b815260040161101c929190614e3f565b60006040518083038186803b15801561103457600080fd5b505afa158015611048573d6000803e3d6000fd5b5050505061105582612979565b5050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036110c0576040517f560440d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b61110f61211b565b6000805b825181101561120357600083828151811061113157611130615048565b5b60200260200101519050600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166391d148548261118261249b565b6040518363ffffffff1660e01b815260040161119f929190614e3f565b602060405180830381865afa1580156111bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e09190615300565b156111ef576001925050611203565b5080806111fb90615000565b915050611113565b5080611244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161123b90615379565b60405180910390fd5b600860009054906101000a900460ff161561128b576040517fb8ef635100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600860019054906101000a900460ff166112d1576040517f59e4eebe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112de87878787876129bd565b50505050505050565b6112ef61211b565b6000805b82518110156113e357600083828151811061131157611310615048565b5b60200260200101519050600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166391d148548261136261249b565b6040518363ffffffff1660e01b815260040161137f929190614e3f565b602060405180830381865afa15801561139c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c09190615300565b156113cf5760019250506113e3565b5080806113db90615000565b9150506112f3565b5080611424576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141b90615379565b60405180910390fd5b61142f858585612a72565b5050505050565b606060008061144484611059565b9050600081036114a157600067ffffffffffffffff81111561146957611468614661565b5b6040519080825280602002602001820160405280156114975781602001602082028036833780820191505090505b50925050506115ab565b60008167ffffffffffffffff8111156114bd576114bc614661565b5b6040519080825280602002602001820160405280156114eb5781602001602082028036833780820191505090505b5090506000805b8382146115a2576002600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1694508673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff160361158f578083838061156f90615000565b94508151811061158257611581615048565b5b6020026020010181815250505b808061159a90615000565b9150506114f2565b82955050505050505b919050565b60006009600083815260200190815260200160002060000160149054906101000a900467ffffffffffffffff1667ffffffffffffffff169050919050565b6060600180546115fd90614e97565b80601f016020809104026020016040519081016040528092919081815260200182805461162990614e97565b80156116765780601f1061164b57610100808354040283529160200191611676565b820191906000526020600020905b81548152906001019060200180831161165957829003601f168201915b5050505050905090565b606060008061168e86611059565b9050600081036116eb57600067ffffffffffffffff8111156116b3576116b2614661565b5b6040519080825280602002602001820160405280156116e15781602001602082028036833780820191505090505b50925050506117fb565b60008167ffffffffffffffff81111561170757611706614661565b5b6040519080825280602002602001820160405280156117355781602001602082028036833780820191505090505b5090506000808790505b8681116117ef576002600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1694508873ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036117dc57808383806117bc90615000565b9450815181106117cf576117ce615048565b5b6020026020010181815250505b80806117e790615000565b91505061173f565b81835282955050505050505b9392505050565b61180a611d27565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad8261185161249b565b6040518363ffffffff1660e01b815260040161186e929190614e3f565b60006040518083038186803b15801561188657600080fd5b505afa15801561189a573d6000803e3d6000fd5b50505050600860029054906101000a900460ff166118e4576040517febb5afac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118f083836000612bda565b505050565b816118ff8161263e565b61191161190a61249b565b8484612c3c565b505050565b6000600654905090565b611928611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad8261196f61249b565b6040518363ffffffff1660e01b815260040161198c929190614e3f565b60006040518083038186803b1580156119a457600080fd5b505afa1580156119b8573d6000803e3d6000fd5b505050506119c4612d9f565b50565b6119cf611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82611a1661249b565b6040518363ffffffff1660e01b8152600401611a33929190614e3f565b60006040518083038186803b158015611a4b57600080fd5b505afa158015611a5f573d6000803e3d6000fd5b50505050611a6c82612df5565b5050565b600860029054906101000a900460ff1681565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b3ecf2366040518163ffffffff1660e01b8152600401602060405180830381865afa158015611af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1691906153c5565b905090565b833373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611b5957611b583361263e565b5b611b67858585600186612f12565b5050505050565b611b76611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82611bbd61249b565b6040518363ffffffff1660e01b8152600401611bda929190614e3f565b60006040518083038186803b158015611bf257600080fd5b505afa158015611c06573d6000803e3d6000fd5b50505050611c12612f82565b50565b6000611c20826125f1565b611c2982612884565b9050919050565b6000611c48611c3d61249b565b8a8a8a8a8a8a612f9f565b9050611c55818484612fe1565b611c8b576040517f4a484b6100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4261038485611c9a9190614fcc565b11611cd1576040517fa0724e6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdb338a6130a0565b611d11576040517f795cf3b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d1c898989612a72565b505050505050505050565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c5b66dc96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dba91906153c5565b905090565b6060611dca826125f1565b6000611dd4613135565b90506000815111611df45760405180602001604052806000815250611e1f565b80611dfe846131c7565b604051602001611e0f92919061542e565b6040516020818303038152906040525b915050919050565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b3ecf2366040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eb891906153c5565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad82611eff61249b565b6040518363ffffffff1660e01b8152600401611f1c929190614e3f565b60006040518083038186803b158015611f3457600080fd5b505afa158015611f48573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff166301ffc9a77f0b7162d4000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b8152600401611fa59190615461565b602060405180830381865afa158015611fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe69190615300565b612025576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161201c906154ee565b60405180910390fd5b81600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b612072611a83565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312d9a6ad826120b961249b565b6040518363ffffffff1660e01b81526004016120d6929190614e3f565b60006040518083038186803b1580156120ee57600080fd5b505afa158015612102573d6000803e3d6000fd5b5050505061210e613295565b50565b6000600754905090565b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd5adf0c6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561218a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906121b391906155d1565b905090565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600860009054906101000a900460ff1681565b606060006002836002612272919061561a565b61227c9190614fcc565b67ffffffffffffffff81111561229557612294614661565b5b6040519080825280601f01601f1916602001820160405280156122c75781602001600182028036833780820191505090505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106122ff576122fe615048565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061236357612362615048565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026123a3919061561a565b6123ad9190614fcc565b90505b600181111561244d577f3031323334353637383961626364656600000000000000000000000000000000600f8616601081106123ef576123ee615048565b5b1a60f81b82828151811061240657612405615048565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806124469061565c565b90506123b0565b5060008414612491576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612488906156d1565b60405180910390fd5b8091505092915050565b600033905090565b8273ffffffffffffffffffffffffffffffffffffffff166323b872dd3084846040518463ffffffff1660e01b81526004016124e0939291906156f1565b600060405180830381600087803b1580156124fa57600080fd5b505af115801561250e573d6000803e3d6000fd5b50505050505050565b60006380ac58cd60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806125725750635b5e139f60e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806125da57507fdbf24b52000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806125ea57506125e9826132c1565b5b9050919050565b6125fa8161332b565b61263b57806040517fb718b6870000000000000000000000000000000000000000000000000000000081526004016126329190614426565b60405180910390fd5b50565b60006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115612738576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b81526004016126b5929190615728565b602060405180830381865afa1580156126d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f69190615300565b61273757806040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161272e91906143bc565b60405180910390fd5b5b50565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166127ae83610f28565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b80156128515761280b61280561249b565b836130a0565b612850578383836040517f0957569f000000000000000000000000000000000000000000000000000000008152600401612847939291906156f1565b60405180910390fd5b5b61285c84848461336c565b50505050565b61287e8484848460405180602001604052806000815250612f12565b50505050565b6000426009600084815260200190815260200160002060000160149054906101000a900467ffffffffffffffff1667ffffffffffffffff16106128ff576009600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061290b565b6129088261293c565b90505b919050565b600860029054906101000a900460ff1615600860026101000a81548160ff021916908315150217905550565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b80600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8282905085859050146129fc576040517fa21d27a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b85859050811015612a6a57612a55868683818110612a2057612a1f615048565b5b9050602002016020810190612a3591906147d5565b858584818110612a4857612a47615048565b5b90506020020135846135ea565b91508080612a6290615000565b9150506129ff565b505050505050565b612a7b836125f1565b6000600960008581526020019081526020016000209050828160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612b8557818160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b8273ffffffffffffffffffffffffffffffffffffffff16847f4e06b4e7000e659094299b3533b47b6aa8ad048e95e872d23d1f4ee55af89cfe84604051612bcc9190615760565b60405180910390a350505050565b8015612c2e57612bea83836130a0565b612c2d5782826040517fb2b70f89000000000000000000000000000000000000000000000000000000008152600401612c24929190614481565b60405180910390fd5b5b612c3782613800565b505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612ca1576040517ffa447c3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051612d9291906142b3565b60405180910390a3505050565b6000612da961249b565b90508073ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015612df1573d6000803e3d6000fd5b5050565b8073ffffffffffffffffffffffffffffffffffffffff166301ffc9a77f84648494000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b8152600401612e4e9190615461565b602060405180830381865afa158015612e6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e8f9190615300565b612ece576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ec5906154ee565b60405180910390fd5b80600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b8115612f6f57612f29612f2361249b565b846130a0565b612f6e578484846040517f0957569f000000000000000000000000000000000000000000000000000000008152600401612f65939291906156f1565b60405180910390fd5b5b612f7b85858584613955565b5050505050565b6001600860006101000a81548160ff021916908315150217905550565b600087878787878787604051602001612fbe979695949392919061583f565b604051602081830303815290604052805190602001209050979650505050505050565b60008061304384848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050613035876139b5565b6139e590919063ffffffff16565b9050600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16149150509392505050565b6000806130ac83610f28565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806130ee57506130ed81856121b8565b5b8061312c57508373ffffffffffffffffffffffffffffffffffffffff1661311484610975565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b6060600e805461314490614e97565b80601f016020809104026020016040519081016040528092919081815260200182805461317090614e97565b80156131bd5780601f10613192576101008083540402835291602001916131bd565b820191906000526020600020905b8154815290600101906020018083116131a057829003601f168201915b5050505050905090565b6060600060016131d684613a0c565b01905060008167ffffffffffffffff8111156131f5576131f4614661565b5b6040519080825280601f01601f1916602001820160405280156132275781602001600182028036833780820191505090505b509050600082602001820190505b60011561328a578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a858161327e5761327d6158ad565b5b04945060008503613235575b819350505050919050565b600860019054906101000a900460ff1615600860016101000a81548160ff021916908315150217905550565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff1661334d8361293c565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036133d2576040517fa4aa808000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff166133f282610f28565b73ffffffffffffffffffffffffffffffffffffffff161461344c5782816040517fb04a7806000000000000000000000000000000000000000000000000000000008152600401613443929190614481565b60405180910390fd5b6134598383836001613b5f565b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46135e58383836001613cc5565b505050565b60008082905060005b8481101561379757600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603613661576040517fe7070eb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61366a8261332b565b156136ac57816040517f3dd6ca500000000000000000000000000000000000000000000000000000000081526004016136a39190614426565b60405180910390fd5b6136ba600087846001613b5f565b856002600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613776600087846001613cc5565b818061378190615000565b925050808061378f90615000565b9150506135f3565b5083600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555083600660008282540192505081905550809150509392505050565b600061380b82610f28565b905061381b816000846001613b5f565b6004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560076000815480929190600101919050555081600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613951816000846001613cc5565b5050565b61396084848461336c565b61396c84848484613ccb565b6139af5782826040517ffbf98f280000000000000000000000000000000000000000000000000000000081526004016139a6929190614481565b60405180910390fd5b50505050565b6000816040516020016139c89190615949565b604051602081830303815290604052805190602001209050919050565b60008060006139f48585613e56565b91509150613a0181613ea7565b819250505092915050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310613a6a577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381613a6057613a5f6158ad565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310613aa7576d04ee2d6d415b85acef81000000008381613a9d57613a9c6158ad565b5b0492506020810190505b662386f26fc100008310613ad657662386f26fc100008381613acc57613acb6158ad565b5b0492506010810190505b6305f5e1008310613aff576305f5e1008381613af557613af46158ad565b5b0492506008810190505b6127108310613b24576127108381613b1a57613b196158ad565b5b0492506004810190505b60648310613b475760648381613b3d57613b3c6158ad565b5b0492506002810190505b600a8310613b56576001810190505b80915050919050565b613b6b8484848461400d565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160315613cbf5760006009600084815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613c145750613cbf565b60096000848152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a81549067ffffffffffffffff02191690555050600073ffffffffffffffffffffffffffffffffffffffff16837f4e06b4e7000e659094299b3533b47b6aa8ad048e95e872d23d1f4ee55af89cfe6000604051613cb591906159aa565b60405180910390a3505b50505050565b50505050565b6000613cec8473ffffffffffffffffffffffffffffffffffffffff16614013565b15613e49578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613d1561249b565b8786866040518563ffffffff1660e01b8152600401613d379493929190615a1a565b6020604051808303816000875af1925050508015613d7357506040513d601f19601f82011682018060405250810190613d709190615a7b565b60015b613df9573d8060008114613da3576040519150601f19603f3d011682016040523d82523d6000602084013e613da8565b606091505b506000815103613df15784846040517ffbf98f28000000000000000000000000000000000000000000000000000000008152600401613de8929190614481565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613e4e565b600190505b949350505050565b6000806041835103613e975760008060006020860151925060408601519150606086015160001a9050613e8b87828585614036565b94509450505050613ea0565b60006002915091505b9250929050565b60006004811115613ebb57613eba615aa8565b5b816004811115613ece57613ecd615aa8565b5b031561400a5760016004811115613ee857613ee7615aa8565b5b816004811115613efb57613efa615aa8565b5b03613f3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613f3290615b23565b60405180910390fd5b60026004811115613f4f57613f4e615aa8565b5b816004811115613f6257613f61615aa8565b5b03613fa2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613f9990615b8f565b60405180910390fd5b60036004811115613fb657613fb5615aa8565b5b816004811115613fc957613fc8615aa8565b5b03614009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161400090615c21565b60405180910390fd5b5b50565b50505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c111561407157600060039150915061410f565b6000600187878787604051600081526020016040526040516140969493929190615c5d565b6020604051602081039080840390855afa1580156140b8573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036141065760006001925092505061410f565b80600092509250505b94509492505050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006141578261412c565b9050919050565b6141678161414c565b811461417257600080fd5b50565b6000813590506141848161415e565b92915050565b6000819050919050565b61419d8161418a565b81146141a857600080fd5b50565b6000813590506141ba81614194565b92915050565b6000806000606084860312156141d9576141d8614122565b5b60006141e786828701614175565b93505060206141f886828701614175565b9250506040614209868287016141ab565b9150509250925092565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61424881614213565b811461425357600080fd5b50565b6000813590506142658161423f565b92915050565b60006020828403121561428157614280614122565b5b600061428f84828501614256565b91505092915050565b60008115159050919050565b6142ad81614298565b82525050565b60006020820190506142c860008301846142a4565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156143085780820151818401526020810190506142ed565b60008484015250505050565b6000601f19601f8301169050919050565b6000614330826142ce565b61433a81856142d9565b935061434a8185602086016142ea565b61435381614314565b840191505092915050565b600060208201905081810360008301526143788184614325565b905092915050565b60006020828403121561439657614395614122565b5b60006143a4848285016141ab565b91505092915050565b6143b68161414c565b82525050565b60006020820190506143d160008301846143ad565b92915050565b600080604083850312156143ee576143ed614122565b5b60006143fc85828601614175565b925050602061440d858286016141ab565b9150509250929050565b6144208161418a565b82525050565b600060208201905061443b6000830184614417565b92915050565b6000806040838503121561445857614457614122565b5b6000614466858286016141ab565b9250506020614477858286016141ab565b9150509250929050565b600060408201905061449660008301856143ad565b6144a36020830184614417565b9392505050565b6000819050919050565b60006144cf6144ca6144c58461412c565b6144aa565b61412c565b9050919050565b60006144e1826144b4565b9050919050565b60006144f3826144d6565b9050919050565b614503816144e8565b82525050565b600060208201905061451e60008301846144fa565b92915050565b60008060006060848603121561453d5761453c614122565b5b600061454b86828701614175565b935050602061455c868287016141ab565b925050604061456d868287016141ab565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6145ac8161418a565b82525050565b60006145be83836145a3565b60208301905092915050565b6000602082019050919050565b60006145e282614577565b6145ec8185614582565b93506145f783614593565b8060005b8381101561462857815161460f88826145b2565b975061461a836145ca565b9250506001810190506145fb565b5085935050505092915050565b6000602082019050818103600083015261464f81846145d7565b905092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61469982614314565b810181811067ffffffffffffffff821117156146b8576146b7614661565b5b80604052505050565b60006146cb614118565b90506146d78282614690565b919050565b600067ffffffffffffffff8211156146f7576146f6614661565b5b61470082614314565b9050602081019050919050565b82818337600083830152505050565b600061472f61472a846146dc565b6146c1565b90508281526020810184848401111561474b5761474a61465c565b5b61475684828561470d565b509392505050565b600082601f83011261477357614772614657565b5b813561478384826020860161471c565b91505092915050565b6000602082840312156147a2576147a1614122565b5b600082013567ffffffffffffffff8111156147c0576147bf614127565b5b6147cc8482850161475e565b91505092915050565b6000602082840312156147eb576147ea614122565b5b60006147f984828501614175565b91505092915050565b600080fd5b600080fd5b60008083601f84011261482257614821614657565b5b8235905067ffffffffffffffff81111561483f5761483e614802565b5b60208301915083602082028301111561485b5761485a614807565b5b9250929050565b60008083601f84011261487857614877614657565b5b8235905067ffffffffffffffff81111561489557614894614802565b5b6020830191508360208202830111156148b1576148b0614807565b5b9250929050565b6000806000806000606086880312156148d4576148d3614122565b5b600086013567ffffffffffffffff8111156148f2576148f1614127565b5b6148fe8882890161480c565b9550955050602086013567ffffffffffffffff81111561492157614920614127565b5b61492d88828901614862565b93509350506040614940888289016141ab565b9150509295509295909350565b600067ffffffffffffffff82169050919050565b61496a8161494d565b811461497557600080fd5b50565b60008135905061498781614961565b92915050565b6000806000606084860312156149a6576149a5614122565b5b60006149b4868287016141ab565b93505060206149c586828701614175565b92505060406149d686828701614978565b9150509250925092565b6149e981614298565b81146149f457600080fd5b50565b600081359050614a06816149e0565b92915050565b60008060408385031215614a2357614a22614122565b5b6000614a3185828601614175565b9250506020614a42858286016149f7565b9150509250929050565b6000819050919050565b614a5f81614a4c565b82525050565b6000602082019050614a7a6000830184614a56565b92915050565b600067ffffffffffffffff821115614a9b57614a9a614661565b5b614aa482614314565b9050602081019050919050565b6000614ac4614abf84614a80565b6146c1565b905082815260208101848484011115614ae057614adf61465c565b5b614aeb84828561470d565b509392505050565b600082601f830112614b0857614b07614657565b5b8135614b18848260208601614ab1565b91505092915050565b60008060008060808587031215614b3b57614b3a614122565b5b6000614b4987828801614175565b9450506020614b5a87828801614175565b9350506040614b6b878288016141ab565b925050606085013567ffffffffffffffff811115614b8c57614b8b614127565b5b614b9887828801614af3565b91505092959194509250565b60008083601f840112614bba57614bb9614657565b5b8235905067ffffffffffffffff811115614bd757614bd6614802565b5b602083019150836001820283011115614bf357614bf2614807565b5b9250929050565b60008083601f840112614c1057614c0f614657565b5b8235905067ffffffffffffffff811115614c2d57614c2c614802565b5b602083019150836001820283011115614c4957614c48614807565b5b9250929050565b60008060008060008060008060c0898b031215614c7057614c6f614122565b5b6000614c7e8b828c016141ab565b9850506020614c8f8b828c01614175565b9750506040614ca08b828c01614978565b965050606089013567ffffffffffffffff811115614cc157614cc0614127565b5b614ccd8b828c01614ba4565b95509550506080614ce08b828c016141ab565b93505060a089013567ffffffffffffffff811115614d0157614d00614127565b5b614d0d8b828c01614bfa565b92509250509295985092959890939650565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b614d5481614a4c565b82525050565b6000614d668383614d4b565b60208301905092915050565b6000602082019050919050565b6000614d8a82614d1f565b614d948185614d2a565b9350614d9f83614d3b565b8060005b83811015614dd0578151614db78882614d5a565b9750614dc283614d72565b925050600181019050614da3565b5085935050505092915050565b60006020820190508181036000830152614df78184614d7f565b905092915050565b60008060408385031215614e1657614e15614122565b5b6000614e2485828601614175565b9250506020614e3585828601614175565b9150509250929050565b6000604082019050614e546000830185614a56565b614e6160208301846143ad565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614eaf57607f821691505b602082108103614ec257614ec1614e68565b5b50919050565b6000606082019050614edd6000830186614417565b614eea60208301856143ad565b614ef76040830184614417565b949350505050565b600081519050614f0e8161415e565b92915050565b600081519050614f2381614194565b92915050565b60008060408385031215614f4057614f3f614122565b5b6000614f4e85828601614eff565b9250506020614f5f85828601614f14565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614fa38261418a565b9150614fae8361418a565b9250828203905081811115614fc657614fc5614f69565b5b92915050565b6000614fd78261418a565b9150614fe28361418a565b9250828201905080821115614ffa57614ff9614f69565b5b92915050565b600061500b8261418a565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361503d5761503c614f69565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026150d97fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261509c565b6150e3868361509c565b95508019841693508086168417925050509392505050565b600061511661511161510c8461418a565b6144aa565b61418a565b9050919050565b6000819050919050565b615130836150fb565b61514461513c8261511d565b8484546150a9565b825550505050565b600090565b61515961514c565b615164818484615127565b505050565b5b818110156151885761517d600082615151565b60018101905061516a565b5050565b601f8211156151cd5761519e81615077565b6151a78461508c565b810160208510156151b6578190505b6151ca6151c28561508c565b830182615169565b50505b505050565b600082821c905092915050565b60006151f0600019846008026151d2565b1980831691505092915050565b600061520983836151df565b9150826002028217905092915050565b615222826142ce565b67ffffffffffffffff81111561523b5761523a614661565b5b6152458254614e97565b61525082828561518c565b600060209050601f8311600181146152835760008415615271578287015190505b61527b85826151fd565b8655506152e3565b601f19841661529186615077565b60005b828110156152b957848901518255600182019150602085019450602081019050615294565b868310156152d657848901516152d2601f8916826151df565b8355505b6001600288020188555050505b505050505050565b6000815190506152fa816149e0565b92915050565b60006020828403121561531657615315614122565b5b6000615324848285016152eb565b91505092915050565b7f4d697373696e6720726571756972656420726f6c650000000000000000000000600082015250565b60006153636015836142d9565b915061536e8261532d565b602082019050919050565b6000602082019050818103600083015261539281615356565b9050919050565b6153a281614a4c565b81146153ad57600080fd5b50565b6000815190506153bf81615399565b92915050565b6000602082840312156153db576153da614122565b5b60006153e9848285016153b0565b91505092915050565b600081905092915050565b6000615408826142ce565b61541281856153f2565b93506154228185602086016142ea565b80840191505092915050565b600061543a82856153fd565b915061544682846153fd565b91508190509392505050565b61545b81614213565b82525050565b60006020820190506154766000830184615452565b92915050565b7f436f6e747261637420646f6573206e6f7420737570706f72742072657175697260008201527f656420696e746572666163650000000000000000000000000000000000000000602082015250565b60006154d8602c836142d9565b91506154e38261547c565b604082019050919050565b60006020820190508181036000830152615507816154cb565b9050919050565b600067ffffffffffffffff82111561552957615528614661565b5b602082029050602081019050919050565b600061554d6155488461550e565b6146c1565b905080838252602082019050602084028301858111156155705761556f614807565b5b835b81811015615599578061558588826153b0565b845260208401935050602081019050615572565b5050509392505050565b600082601f8301126155b8576155b7614657565b5b81516155c884826020860161553a565b91505092915050565b6000602082840312156155e7576155e6614122565b5b600082015167ffffffffffffffff81111561560557615604614127565b5b615611848285016155a3565b91505092915050565b60006156258261418a565b91506156308361418a565b925082820261563e8161418a565b9150828204841483151761565557615654614f69565b5b5092915050565b60006156678261418a565b91506000820361567a57615679614f69565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b60006156bb6020836142d9565b91506156c682615685565b602082019050919050565b600060208201905081810360008301526156ea816156ae565b9050919050565b600060608201905061570660008301866143ad565b61571360208301856143ad565b6157206040830184614417565b949350505050565b600060408201905061573d60008301856143ad565b61574a60208301846143ad565b9392505050565b61575a8161494d565b82525050565b60006020820190506157756000830184615751565b92915050565b60008160601b9050919050565b60006157938261577b565b9050919050565b60006157a582615788565b9050919050565b6157bd6157b88261414c565b61579a565b82525050565b6000819050919050565b6157de6157d98261418a565b6157c3565b82525050565b60008160c01b9050919050565b60006157fc826157e4565b9050919050565b61581461580f8261494d565b6157f1565b82525050565b600061582683856153f2565b935061583383858461470d565b82840190509392505050565b600061584b828a6157ac565b60148201915061585b82896157cd565b60208201915061586b82886157ac565b60148201915061587b8287615803565b60088201915061588c82858761581a565b915061589882846157cd565b60208201915081905098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000615912601c836153f2565b915061591d826158dc565b601c82019050919050565b6000819050919050565b61594361593e82614a4c565b615928565b82525050565b600061595482615905565b91506159608284615932565b60208201915081905092915050565b6000819050919050565b600061599461598f61598a8461596f565b6144aa565b61494d565b9050919050565b6159a481615979565b82525050565b60006020820190506159bf600083018461599b565b92915050565b600081519050919050565b600082825260208201905092915050565b60006159ec826159c5565b6159f681856159d0565b9350615a068185602086016142ea565b615a0f81614314565b840191505092915050565b6000608082019050615a2f60008301876143ad565b615a3c60208301866143ad565b615a496040830185614417565b8181036060830152615a5b81846159e1565b905095945050505050565b600081519050615a758161423f565b92915050565b600060208284031215615a9157615a90614122565b5b6000615a9f84828501615a66565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f45434453413a20696e76616c6964207369676e61747572650000000000000000600082015250565b6000615b0d6018836142d9565b9150615b1882615ad7565b602082019050919050565b60006020820190508181036000830152615b3c81615b00565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800600082015250565b6000615b79601f836142d9565b9150615b8482615b43565b602082019050919050565b60006020820190508181036000830152615ba881615b6c565b9050919050565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c60008201527f7565000000000000000000000000000000000000000000000000000000000000602082015250565b6000615c0b6022836142d9565b9150615c1682615baf565b604082019050919050565b60006020820190508181036000830152615c3a81615bfe565b9050919050565b600060ff82169050919050565b615c5781615c41565b82525050565b6000608082019050615c726000830187614a56565b615c7f6020830186615c4e565b615c8c6040830185614a56565b615c996060830184614a56565b9594505050505056fea26469706673582212209684551364b5ce7eca20b1c986d55c92f1e68f163e343061174c9b85bb8f373764736f6c63430008110033

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

00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000cdf831868185c4e92433b2f66a88123523011ecf00000000000000000000000021bbb2f84053197a2455a6c230c2883030b15d0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f68747470733a2f2f6d657461646174612e766565667269656e64732e636f6d2f76322f636f6c6c656374696f6e732f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013566565436f6e2032303233205469636b6574730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055643543233000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : initialBaseUri (string): https://metadata.veefriends.com/v2/collections/
Arg [1] : name (string): VeeCon 2023 Tickets
Arg [2] : symbol (string): VCT23
Arg [3] : controlContractAddress (address): 0xcDf831868185C4e92433B2f66a88123523011ecf
Arg [4] : royaltiesContractAddress (address): 0x21bbB2F84053197A2455a6C230C2883030B15d0c
Arg [5] : signer (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
13 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [3] : 000000000000000000000000cdf831868185c4e92433b2f66a88123523011ecf
Arg [4] : 00000000000000000000000021bbb2f84053197a2455a6c230c2883030b15d0c
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 000000000000000000000000000000000000000000000000000000000000002f
Arg [7] : 68747470733a2f2f6d657461646174612e766565667269656e64732e636f6d2f
Arg [8] : 76322f636f6c6c656374696f6e732f0000000000000000000000000000000000
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000013
Arg [10] : 566565436f6e2032303233205469636b65747300000000000000000000000000
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [12] : 5643543233000000000000000000000000000000000000000000000000000000


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.