Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
Gaming
Overview
Max Total Supply
10,255 VCT23
Holders
6,032
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 VCT23Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
VFTicket
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// 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); } }
// 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); }
// 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); }
// 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); }
// 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); } } }
// 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; } }
// 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)); } }
// 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; } }
// 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); }
// 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); } } }
// 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); } }
// 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; }
// 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); } }
// 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); } }
// 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); } }
// 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); } }
// 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; }
// 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); } }
// 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 {} }
// 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); }
// 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); }
// 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) {} }
// 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); }
// 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); } } } }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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.