Contract
0x3151b7dd9f6e806d2709153765925c373af47089
2
Contract Overview
[ Download CSV Export ]
View more zero value Internal Transactions in Advanced View mode
Contract Name:
Cryptostamp3_1L2
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at gnosisscan.io on 2022-08-04 */ /* * Crypto stamp 3.1 (Layer 2) * digital-physical collectible postage stamp * * Developed by Capacity Blockchain Solutions GmbH <capacity.at> * for Österreichische Post AG <post.at> * * Any usage of or interaction with this set of contracts is subject to the * Terms & Conditions available at https://crypto.post.at/ */ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; // File: @openzeppelin/contracts/token/ERC20/IERC20.sol /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: @openzeppelin/contracts/utils/cryptography/ECDSA.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 } 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"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' 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) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ 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. 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 if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return tryRecover(hash, r, vs); } 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; uint8 v; assembly { s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) v := add(shr(255, vs), 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 (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // 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 Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } } // File: @openzeppelin/contracts/utils/introspection/IERC165.sol /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: @openzeppelin/contracts/token/ERC721/IERC721.sol /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; } // File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } // File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); } // File: @openzeppelin/contracts/utils/Address.sol /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: @openzeppelin/contracts/utils/Context.sol /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File: @openzeppelin/contracts/utils/Strings.sol /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } } // File: @openzeppelin/contracts/utils/introspection/ERC165.sol /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File: @openzeppelin/contracts/token/ERC721/ERC721.sol /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { 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; /** * @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_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: owner query for nonexistent token"); 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) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); 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 overriden 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 { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { require(operator != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransfer(from, to, tokenId, _data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `_data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory _data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[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) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ERC721.ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @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); require( _checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, 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("ERC721: transfer to non ERC721Receiver implementer"); } else { 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. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} } // File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); } // File: contracts/ERC721EnumerableSimple.sol /* * This is a simplified (and cheaper) version of OpenZeppelin's ERC721Enumerable. * ERC721Enumerable's allTokens array and allTokensIndex mapping are eliminated. * Side effects: _burn cannot be used any more with this, and creation needs to be * in ascending order, starting with 0, and have no holes in the sequence of IDs. */ /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721EnumerableSimple is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; uint256 internal totalSupply_; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return totalSupply_; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < totalSupply(), "Index is out of bounds."); return index; } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 /*tokenId*/) private { totalSupply_++; } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This is not possible with this variant. * param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 /*tokenId*/) private pure { revert("This token cannot be burned."); } } // File: contracts/ERC721SignedTransferI.sol /* * Interface for ERC721 Signed Transfers. */ /** * @dev Outward-facing interface of a Collections contract. */ interface ERC721SignedTransferI is IERC721 { /** * @dev Emitted when a signed transfer is being executed. */ event SignedTransfer(address operator, address indexed from, address indexed to, uint256 indexed tokenId, uint256 signedTransferNonce); /** * @dev The signed transfer nonce for an account. */ function signedTransferNonce(address account) external view returns (uint256); /** * @dev Outward-facing function for signed transfer: assembles the expected data and then calls the internal function to do the rest. * Can called by anyone knowing about the right signature, but can only transfer to the given specific target. */ function signedTransfer(uint256 tokenId, address to, bytes memory signature) external; /** * @dev Outward-facing function for operator-driven signed transfer: assembles the expected data and then calls the internal function to do the rest. * Can transfer to any target, but only be called by the trusted operator contained in the signature. */ function signedTransferWithOperator(uint256 tokenId, address to, bytes memory signature) external; } // File: contracts/ERC721ExistsI.sol /* * Interface for an ERC721 compliant contract with an exists() function. */ /** * @dev ERC721 compliant contract with an exists() function. */ interface ERC721ExistsI is IERC721 { // Returns whether the specified token exists function exists(uint256 tokenId) external view returns (bool); } // File: contracts/ENSReverseRegistrarI.sol /* * Interfaces for ENS Reverse Registrar * See https://github.com/ensdomains/ens/blob/master/contracts/ReverseRegistrar.sol for full impl * Also see https://github.com/wealdtech/wealdtech-solidity/blob/master/contracts/ens/ENSReverseRegister.sol * * Use this as follows (registryAddress is the address of the ENS registry to use): * ----- * // This hex value is caclulated by namehash('addr.reverse') * bytes32 public constant ENS_ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; * function registerReverseENS(address registryAddress, string memory calldata) external { * require(registryAddress != address(0), "need a valid registry"); * address reverseRegistrarAddress = ENSRegistryOwnerI(registryAddress).owner(ENS_ADDR_REVERSE_NODE) * require(reverseRegistrarAddress != address(0), "need a valid reverse registrar"); * ENSReverseRegistrarI(reverseRegistrarAddress).setName(name); * } * ----- * or * ----- * function registerReverseENS(address reverseRegistrarAddress, string memory calldata) external { * require(reverseRegistrarAddress != address(0), "need a valid reverse registrar"); * ENSReverseRegistrarI(reverseRegistrarAddress).setName(name); * } * ----- * ENS deployments can be found at https://docs.ens.domains/ens-deployments * E.g. Etherscan can be used to look up that owner on those contracts. * namehash.hash("addr.reverse") == "0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2" * Ropsten: ens.owner(namehash.hash("addr.reverse")) == "0x6F628b68b30Dc3c17f345c9dbBb1E483c2b7aE5c" * Mainnet: ens.owner(namehash.hash("addr.reverse")) == "0x084b1c3C81545d370f3634392De611CaaBFf8148" */ interface ENSRegistryOwnerI { function owner(bytes32 node) external view returns (address); } interface ENSReverseRegistrarI { event NameChanged(bytes32 indexed node, string name); /** * @dev Sets the `name()` record for the reverse ENS record associated with * the calling account. * @param name The name to set for this address. * @return The ENS node hash of the reverse record. */ function setName(string calldata name) external returns (bytes32); } // File: contracts/BridgeDataI.sol /* * Interface for data storage of the bridge. */ interface BridgeDataI { event AddressChanged(string name, address previousAddress, address newAddress); event ConnectedChainChanged(string previousConnectedChainName, string newConnectedChainName); event TokenURIBaseChanged(string previousTokenURIBase, string newTokenURIBase); event TokenSunsetAnnounced(uint256 indexed timestamp); /** * @dev The name of the chain connected to / on the other side of this bridge head. */ function connectedChainName() external view returns (string memory); /** * @dev The name of our own chain, used in token URIs handed to deployed tokens. */ function ownChainName() external view returns (string memory); /** * @dev The base of ALL token URIs, e.g. https://example.com/ */ function tokenURIBase() external view returns (string memory); /** * @dev The sunset timestamp for all deployed tokens. * If 0, no sunset is in place. Otherwise, if older than block timestamp, * all transfers of the tokens are frozen. */ function tokenSunsetTimestamp() external view returns (uint256); /** * @dev Set a token sunset timestamp. */ function setTokenSunsetTimestamp(uint256 _timestamp) external; /** * @dev Set an address for a name. */ function setAddress(string memory name, address newAddress) external; /** * @dev Get an address for a name. */ function getAddress(string memory name) external view returns (address); } // File: contracts/CS3_1PropertiesI.sol /* * Interface for CS3.1 properties. */ interface CS3_1PropertiesI { enum AssetType { Rhino, Kitty } enum SColors { Sleeping, Black, Green, Blue, Yellow, Red } function getType(uint256 tokenId) external view returns (AssetType); function getSColor(uint256 tokenId) external view returns (SColors); } // File: contracts/Cryptostamp3_1L2.sol /* * Implements ERC 721 NFT standard: https://github.com/ethereum/EIPs/issues/721. */ contract Cryptostamp3_1L2 is ERC721EnumerableSimple, ERC721ExistsI, ERC721SignedTransferI, CS3_1PropertiesI { BridgeDataI public bridgeData; uint256 immutable finalSupply; uint256 immutable type1Supply; uint256 immutable type2Supply; uint256 constant maxSupportedSupply = 2 ** 24; uint8[maxSupportedSupply] private properties; mapping(uint256 => uint256) public colorRevealBlock; uint256[] public revealList; uint256 public revealFinishedCount; uint256[5][2] public unrevealedColorCount; bool public transferCanFinishPendingReveal; uint256 public upgradesDone = 0; uint256 public upgradeMaximum; uint256[5][2] public colorSupply; mapping(uint256 => bool) public usedInUpgrade; mapping(address => uint256) public override signedTransferNonce; event BridgeDataChanged(address indexed previousBridgeData, address indexed newBridgeData); event UpgradeMaximumChanged(uint256 previousUpgradeMaximum, uint256 newUpgradeMaximum); event TransferCanFinishPendingRevealSet(bool newTransferCanFinishPendingReveal); event ColorRevealStarted(uint256 indexed tokenId); event ColorRevealed(uint256 indexed tokenId, SColors indexed newColor); event StampUpgraded(uint256 indexed changedTokenId, SColors previousColor, SColors newColor, uint256 usedTokedId1, uint256 usedTokenId2); constructor(address _bridgeDataAddress, uint256 _finalSupply, uint256[2] memory _typeSupplies, uint256[5][2] memory _totalColorSupply) ERC721("Crypto stamp Edition 3.1", "CS3.1") { bridgeData = BridgeDataI(_bridgeDataAddress); require(address(bridgeData) != address(0x0), "You need to provide an actual bridge data contract."); require(_finalSupply <= maxSupportedSupply, "The final supply is too high."); finalSupply = _finalSupply; require(_finalSupply == _typeSupplies[0] + _typeSupplies[1], "Final supply needs to match the type supplies."); type1Supply = _typeSupplies[0]; type2Supply = _typeSupplies[1]; for (uint256 i = 0; i < 2; i++) { require(_totalColorSupply[i][0] + _totalColorSupply[i][1] + _totalColorSupply[i][2] + _totalColorSupply[i][3] + _totalColorSupply[i][4] == _typeSupplies[i], "The total color supplies need to match the type supplies."); } colorSupply = _totalColorSupply; unrevealedColorCount = _totalColorSupply; transferCanFinishPendingReveal = true; } modifier onlyCreateControl() { require(msg.sender == bridgeData.getAddress("createControl"), "createControl key required for this function."); _; } modifier onlyBridgeControl() { require(msg.sender == bridgeData.getAddress("bridgeControl"), "bridgeControl key required for this function."); _; } modifier onlyTokenAssignmentControl() { require(msg.sender == bridgeData.getAddress("tokenAssignmentControl"), "tokenAssignmentControl key required for this function."); _; } modifier requireTransferEnabled() { require(transferEnabled() == true, "This call only works when transfers are enabled."); _; } modifier requireMinting() { require(mintingFinished() == false, "This call only works when minting is not finished."); _; } /*** Enable adjusting variables after deployment ***/ function setBridgeData(BridgeDataI _newBridgeData) external onlyBridgeControl { require(address(_newBridgeData) != address(0x0), "You need to provide an actual bridge data contract."); emit BridgeDataChanged(address(bridgeData), address(_newBridgeData)); bridgeData = _newBridgeData; } function setTransferCanFinishPendingReveal(bool _newTransferCanFinishPendingReveal) external onlyBridgeControl { transferCanFinishPendingReveal = _newTransferCanFinishPendingReveal; emit TransferCanFinishPendingRevealSet(transferCanFinishPendingReveal); } function setUpgradeMaximum(uint256 _newUpgradeMaximum) public onlyBridgeControl { require(upgradesDone <= _newUpgradeMaximum, "Already more upgrades done than the requested limit."); emit UpgradeMaximumChanged(upgradeMaximum, _newUpgradeMaximum); upgradeMaximum = _newUpgradeMaximum; } // Return true if transfers are possible. // This can have additional conditions to just the sunset variable. function transferEnabled() public view returns (bool) { uint256 tokenSunsetTimestamp = bridgeData.tokenSunsetTimestamp(); // solhint-disable-next-line not-rely-on-time return (tokenSunsetTimestamp == 0 || tokenSunsetTimestamp > block.timestamp); } /*** Base functionality: minting, URI, property getters, etc. ***/ /** * @dev Gets the actually minted amount of tokens in the contract. * @return uint256 representing the minted amount of tokens */ function mintedSupply() public view returns (uint256) { return super.totalSupply(); } // Issue a new crypto stamp asset, giving it to a specific owner address. function create(uint256 _tokenId, address _owner) public onlyCreateControl requireMinting { // _mint already ends up checking if owner != 0 and that tokenId doesn't exist yet. _mint(_owner, _tokenId); } // Batch-issue multiple crypto stamps with adjacent IDs. function createMulti(uint256 _tokenIdStart, address[] memory _owners) public onlyCreateControl requireMinting { uint256 addrcount = _owners.length; for (uint256 i = 0; i < addrcount; i++) { // Make sure this is in sync with what create() does. _mint(_owners[i], _tokenIdStart + i); } } // Determine if the creation/minting process is done. function mintingFinished() public view returns (bool) { return (super.totalSupply() >= finalSupply); } // Get type of the given token. function getType(uint256 _tokenId) public view override returns (AssetType) { require(_exists(_tokenId), "Token ID needs to exist."); if (_tokenId < type1Supply) { return AssetType.Rhino; } return AssetType.Kitty; } // Get sleeping or color of the given token. function getSColor(uint256 _tokenId) public view override returns (SColors) { require(_exists(_tokenId), "Token ID needs to exist."); return SColors(properties[_tokenId]); } function baseURI() public view returns (string memory) { return _baseURI(); } function _baseURI() internal view override returns (string memory) { return string(abi.encodePacked(bridgeData.tokenURIBase(), symbol(), "/meta/")); } // Returns whether the specified token exists function exists(uint256 _tokenId) public view override returns (bool) { return _exists(_tokenId); } /*** Color reveal functionality: "sleeping" stamps get a random actual color via a two-step process ***/ // Start color reveal of of the given token. function startColorReveal(uint256 _tokenId, bool _finishOnePending) public { require(msg.sender == bridgeData.getAddress("colorRevealAPI") || msg.sender == ownerOf(_tokenId), "You cannot start color reveal for this token."); require(SColors(properties[_tokenId]) == SColors.Sleeping, "Color needs to be unrevealed."); require(colorRevealBlock[_tokenId] == 0, "Color reveal already started."); _startColorReveal(_tokenId, _finishOnePending); } // Start color reveal of of the given token. function _startColorReveal(uint256 _tokenId, bool _finishOnePending) internal { colorRevealBlock[_tokenId] = block.number; revealList.push(_tokenId); emit ColorRevealStarted(_tokenId); if (_finishOnePending) { _finishNextColorReveal(false); } } // Finish color reveal of potentially multiple tokens, doing fewer if fewer are in process. function finishColorReveals(uint256 _maxCount) public { for (uint256 i = 0; i < _maxCount; i++) { _finishNextColorReveal(false); } } // Finish color reveal of the next token in the list. function finishNextColorReveal() public { _finishNextColorReveal(true); } // Finish color reveal of the next token in the list. function _finishNextColorReveal(bool _revertForFailures) internal { if (revealPendingCount() == 0) { if (_revertForFailures) { revert("No pending color reveals."); } return; // We could revert here but we do not want to fail when called by other contract functions. } uint256 tokenId = revealList[revealFinishedCount]; // The list index of the next reveal to finish equals the number of already finished reveals. if (colorRevealBlock[tokenId] == block.number || colorRevealBlock[tokenId] == 0 || SColors(properties[tokenId]) != SColors.Sleeping) { if (_revertForFailures) { revert("Cannot reveal this token."); } return; // We could revert here but we do not want to fail when called by other contract functions. } uint256 aTypeNum = uint256(getType(tokenId)); uint256 allUnrevealedCount = unrevealedColorCount[aTypeNum][0] + unrevealedColorCount[aTypeNum][1] + unrevealedColorCount[aTypeNum][2] + unrevealedColorCount[aTypeNum][3] + unrevealedColorCount[aTypeNum][4]; uint256 colorIndex = _getSemiRandomNumber(colorRevealBlock[tokenId], tokenId, allUnrevealedCount); SColors newColor; if (colorIndex < unrevealedColorCount[aTypeNum][0]) { newColor = SColors.Black; } else if (colorIndex < unrevealedColorCount[aTypeNum][0] + unrevealedColorCount[aTypeNum][1]) { newColor = SColors.Green; } else if (colorIndex < unrevealedColorCount[aTypeNum][0] + unrevealedColorCount[aTypeNum][1] + unrevealedColorCount[aTypeNum][2]) { newColor = SColors.Blue; } else if (colorIndex < unrevealedColorCount[aTypeNum][0] + unrevealedColorCount[aTypeNum][1] + unrevealedColorCount[aTypeNum][2] + unrevealedColorCount[aTypeNum][3]) { newColor = SColors.Yellow; } else { newColor = SColors.Red; } colorRevealBlock[tokenId] = 0; // Set to 0 again for state hygiene. properties[tokenId] = uint8(newColor); unrevealedColorCount[aTypeNum][uint8(newColor) - 1] = unrevealedColorCount[aTypeNum][uint8(newColor) - 1] - 1; emit ColorRevealed(tokenId, newColor); revealFinishedCount = revealFinishedCount + 1; } // Get a semi-random number based on the block has of the given block number, a salt and an exclusive max value. function _getSemiRandomNumber(uint256 _blockNumber, uint256 _salt, uint256 _maxValueExclusive) internal view returns (uint256) { // Get block hash. As this only works for the last 256 blocks, fall back to the empty keccak256 hash to keep getting stable results. bytes32 bhash; if (_blockNumber == block.number) { revert("Wait for next block please."); } else if (block.number < 256 || _blockNumber >= block.number - 256) { bhash = blockhash(_blockNumber); } else { bhash = keccak256(""); } return uint256(keccak256(abi.encodePacked(_salt, bhash))) % _maxValueExclusive; } // Indicate if a color reveal is pending for the given token. function colorRevealPending(uint256 _tokenId) public view returns (bool) { // User getSColor() so this reverts on non-existing tokens. return getSColor(_tokenId) == SColors.Sleeping && colorRevealBlock[_tokenId] > 0; } // Get number of started reveal processes. function revealStartedCount() public view returns (uint256) { return revealList.length; } // Get number of pendiung reveal processes. function revealPendingCount() public view returns (uint256) { return revealList.length - revealFinishedCount; } /*** Upgrading functionality: upgrade color of the stamp using other stamps of the same color ***/ // Returns whether upgrading is possible at this time. function upgradesAllowed() public view returns (bool) { return upgradesDone < upgradeMaximum; } // Upgrade 1 CS3 stamp by "upgrading" with 2 other CS3 of same type and color. function upgradeStamp(uint256 _upgradeTokenId, uint256 _helperTokenId1, uint256 _helperTokenId2) public { require(upgradesDone < upgradeMaximum, "Maximum upgrades reached"); require(_upgradeTokenId != _helperTokenId1 && _upgradeTokenId != _helperTokenId2 && _helperTokenId1 != _helperTokenId2, "You actually need to use 3 different tokens to upgrade"); require(msg.sender == ownerOf(_upgradeTokenId) && msg.sender == ownerOf(_helperTokenId1) && msg.sender == ownerOf(_helperTokenId2), "Caller has to be owner of all tokens."); require(usedInUpgrade[_upgradeTokenId] == false && usedInUpgrade[_helperTokenId1] == false && usedInUpgrade[_helperTokenId2] == false, "Cannot used stamps already used in a upgrade."); SColors previousColor = getSColor(_upgradeTokenId); require(previousColor != SColors.Sleeping, "Sleeping stamps cannot be upgraded."); AssetType aType = getType(_upgradeTokenId); require(getType(_helperTokenId1) == aType && getSColor(_helperTokenId1) == previousColor && getType(_helperTokenId2) == aType && getSColor(_helperTokenId2) == previousColor, "All tokens involved must have the same type and color"); usedInUpgrade[_helperTokenId1] = true; usedInUpgrade[_helperTokenId2] = true; // Now, actually upgrade the color and notify the achievements contract. SColors newColor = _upgradeColor(_upgradeTokenId, previousColor); emit StampUpgraded(_upgradeTokenId, previousColor, newColor, _helperTokenId1, _helperTokenId2); } function _upgradeColor(uint256 _upgradeTokenId, SColors _previousColor) private returns(SColors) { SColors newColor = SColors(uint256(_previousColor) + 1); properties[_upgradeTokenId] = uint8(newColor); uint256 aTypeNum = uint256(getType(_upgradeTokenId)); colorSupply[aTypeNum][uint256(_previousColor) - 1] = colorSupply[aTypeNum][uint256(_previousColor) - 1] - 1; colorSupply[aTypeNum][uint256(newColor) - 1] = colorSupply[aTypeNum][uint256(newColor) - 1] + 1; upgradesDone++; return newColor; } /*** Override internal functionality for special rules on approvals and transfers ***/ // When the bridge is sunset, all token actions will be blocked. function _beforeTokenTransfer(address _from, address _to, uint256 _tokenId) internal override requireTransferEnabled { if (_to == bridgeData.getAddress("tokenHolder") && SColors(properties[_tokenId]) == SColors.Sleeping) { revert("Reveal color before depositing!"); } if (_from != address(0) && SColors(properties[_tokenId]) == SColors.Sleeping && colorRevealBlock[_tokenId] == 0) { _startColorReveal(_tokenId, transferCanFinishPendingReveal); } super._beforeTokenTransfer(_from, _to, _tokenId); } // Override totalSupply() so it reports the target final supply. function totalSupply() public view override returns (uint256) { return finalSupply; } /*** Allows any user to initiate a transfer with the signature of the current stamp owner ***/ // Outward-facing function for signed transfer: assembles the expected data and then calls the internal function to do the rest. // Can called by anyone knowing about the right signature, but can only transfer to the given specific target. function signedTransfer(uint256 _tokenId, address _to, bytes memory _signature) public override requireTransferEnabled { address currentOwner = ownerOf(_tokenId); // The signed data contains the token ID, the transfer target and a nonce. bytes32 data = keccak256(abi.encodePacked(address(this), this.signedTransfer.selector, currentOwner, _to, _tokenId, signedTransferNonce[currentOwner])); _signedTransferInternal(currentOwner, data, _tokenId, _to, _signature); } // Outward-facing function for operator-driven signed transfer: assembles the expected data and then calls the internal function to do the rest. // Can transfer to any target, but only be called by the trusted operator contained in the signature. function signedTransferWithOperator(uint256 _tokenId, address _to, bytes memory _signature) public override requireTransferEnabled { address currentOwner = ownerOf(_tokenId); // The signed data contains the operator, the token ID, and a nonce. Note that we use the selector of the external function here! bytes32 data = keccak256(abi.encodePacked(address(this), this.signedTransferWithOperator.selector, msg.sender, currentOwner, _tokenId, signedTransferNonce[currentOwner])); _signedTransferInternal(currentOwner, data, _tokenId, _to, _signature); } // Actually check the signature and perform a signed transfer. function _signedTransferInternal(address _currentOwner, bytes32 _data, uint256 _tokenId, address _to, bytes memory _signature) internal { bytes32 hash = ECDSA.toEthSignedMessageHash(_data); address signer = ECDSA.recover(hash, _signature); require(signer == _currentOwner, "Signature needs to match parameters, nonce, and current owner."); // Now that we checked that the signature is correct, do the actual transfer and increase the nonce. emit SignedTransfer(msg.sender, _currentOwner, _to, _tokenId, signedTransferNonce[_currentOwner]); signedTransferNonce[_currentOwner]++; _safeTransfer(_currentOwner, _to, _tokenId, ""); } /*** Enable reverse ENS registration ***/ // Call this with the address of the reverse registrar for the respective network and the ENS name to register. // The reverse registrar can be found as the owner of 'addr.reverse' in the ENS system. // For Mainnet, the address needed is 0x9062c0a6dbd6108336bcbe4593a3d1ce05512069 function registerReverseENS(address _reverseRegistrarAddress, string calldata _name) external onlyTokenAssignmentControl { require(_reverseRegistrarAddress != address(0), "need a valid reverse registrar"); ENSReverseRegistrarI(_reverseRegistrarAddress).setName(_name); } /*** Make sure currency or NFT doesn't get stranded in this contract ***/ // If this contract gets a balance in some ERC20 contract after it's finished, then we can rescue it. function rescueToken(IERC20 _foreignToken, address _to) external onlyTokenAssignmentControl { _foreignToken.transfer(_to, _foreignToken.balanceOf(address(this))); } // If this contract gets a balance in some ERC721 contract after it's finished, then we can rescue it. function approveNFTrescue(IERC721 _foreignNFT, address _to) external onlyTokenAssignmentControl { _foreignNFT.setApprovalForAll(_to, true); } }
[{"inputs":[{"internalType":"address","name":"_bridgeDataAddress","type":"address"},{"internalType":"uint256","name":"_finalSupply","type":"uint256"},{"internalType":"uint256[2]","name":"_typeSupplies","type":"uint256[2]"},{"internalType":"uint256[5][2]","name":"_totalColorSupply","type":"uint256[5][2]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousBridgeData","type":"address"},{"indexed":true,"internalType":"address","name":"newBridgeData","type":"address"}],"name":"BridgeDataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ColorRevealStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"enum CS3_1PropertiesI.SColors","name":"newColor","type":"uint8"}],"name":"ColorRevealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"signedTransferNonce","type":"uint256"}],"name":"SignedTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"changedTokenId","type":"uint256"},{"indexed":false,"internalType":"enum CS3_1PropertiesI.SColors","name":"previousColor","type":"uint8"},{"indexed":false,"internalType":"enum CS3_1PropertiesI.SColors","name":"newColor","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"usedTokedId1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usedTokenId2","type":"uint256"}],"name":"StampUpgraded","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":false,"internalType":"bool","name":"newTransferCanFinishPendingReveal","type":"bool"}],"name":"TransferCanFinishPendingRevealSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousUpgradeMaximum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newUpgradeMaximum","type":"uint256"}],"name":"UpgradeMaximumChanged","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_foreignNFT","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"approveNFTrescue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeData","outputs":[{"internalType":"contract BridgeDataI","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"colorRevealBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"colorRevealPending","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"colorSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_owner","type":"address"}],"name":"create","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenIdStart","type":"uint256"},{"internalType":"address[]","name":"_owners","type":"address[]"}],"name":"createMulti","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxCount","type":"uint256"}],"name":"finishColorReveals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finishNextColorReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getSColor","outputs":[{"internalType":"enum CS3_1PropertiesI.SColors","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getType","outputs":[{"internalType":"enum CS3_1PropertiesI.AssetType","name":"","type":"uint8"}],"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":"mintedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintingFinished","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":"address","name":"_reverseRegistrarAddress","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"name":"registerReverseENS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_foreignToken","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"rescueToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealFinishedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"revealList","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revealPendingCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revealStartedCount","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":"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":"contract BridgeDataI","name":"_newBridgeData","type":"address"}],"name":"setBridgeData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_newTransferCanFinishPendingReveal","type":"bool"}],"name":"setTransferCanFinishPendingReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newUpgradeMaximum","type":"uint256"}],"name":"setUpgradeMaximum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"signedTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signedTransferNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"signedTransferWithOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bool","name":"_finishOnePending","type":"bool"}],"name":"startColorReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferCanFinishPendingReveal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"unrevealedColorCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upgradeMaximum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_upgradeTokenId","type":"uint256"},{"internalType":"uint256","name":"_helperTokenId1","type":"uint256"},{"internalType":"uint256","name":"_helperTokenId2","type":"uint256"}],"name":"upgradeStamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upgradesAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upgradesDone","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"usedInUpgrade","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60e0604052600062080018553480156200001857600080fd5b5060405162004f8e38038062004f8e8339810160408190526200003b91620005ee565b604080518082018252601881527f43727970746f207374616d702045646974696f6e20332e3100000000000000006020808301918252835180850190945260058452644353332e3160d81b9084015281519192916200009d91600091620003e7565b508051620000b3906001906020840190620003e7565b5050600980546001600160a01b0319166001600160a01b038716908117909155151590506200014f5760405162461bcd60e51b815260206004820152603360248201527f596f75206e65656420746f2070726f7669646520616e2061637475616c20627260448201527f69646765206461746120636f6e74726163742e0000000000000000000000000060648201526084015b60405180910390fd5b6301000000831115620001a55760405162461bcd60e51b815260206004820152601d60248201527f5468652066696e616c20737570706c7920697320746f6f20686967682e000000604482015260640162000146565b608083905260208201518251620001bd919062000705565b8314620002245760405162461bcd60e51b815260206004820152602e60248201527f46696e616c20737570706c79206e6565647320746f206d61746368207468652060448201526d3a3cb8329039bab8383634b2b99760911b606482015260840162000146565b815160a052602082015160c05260005b6002811015620003a85782816002811062000253576200025362000791565b60200201518282600281106200026d576200026d62000791565b6020020151608001518383600281106200028b576200028b62000791565b602002015160600151848460028110620002a957620002a962000791565b602002015160400151858560028110620002c757620002c762000791565b602002015160016020020151868660028110620002e857620002e862000791565b602002015151620002fa919062000705565b62000306919062000705565b62000312919062000705565b6200031e919062000705565b14620003935760405162461bcd60e51b815260206004820152603960248201527f54686520746f74616c20636f6c6f7220737570706c696573206e65656420746f60448201527f206d6174636820746865207479706520737570706c6965732e00000000000000606482015260840162000146565b806200039f816200075d565b91505062000234565b50620003ba6208001a82600262000476565b50620003cc6208000d82600262000476565b505062080017805460ff1916600117905550620007a7915050565b828054620003f59062000720565b90600052602060002090601f01602090048101928262000419576000855562000464565b82601f106200043457805160ff191683800117855562000464565b8280016001018555821562000464579182015b828111156200046457825182559160200191906001019062000447565b5062000472929150620004c4565b5090565b600a83019183908215620004b6579160200282015b82811115620004b6578251620004a59083906005620004db565b50916020019190600501906200048b565b50620004729291506200050b565b5b80821115620004725760008155600101620004c5565b82600581019282156200046457916020028201828111156200046457825182559160200191906001019062000447565b808211156200047257600080825560018201819055600282018190556003820181905560048201556005016200050b565b6000601f83818401126200054f57600080fd5b620005596200069d565b808486610140870111156200056d57600080fd5b60005b6002811015620005e25787858301126200058957600080fd5b62000593620006d4565b808360a085018b811115620005a757600080fd5b60005b6005811015620005cb578251855260209485019490920191600101620005aa565b509187525060209095019492505060010162000570565b50909695505050505050565b6000806000806101c085870312156200060657600080fd5b84516001600160a01b03811681146200061e57600080fd5b80945050602080860151935086605f8701126200063a57600080fd5b620006446200069d565b8060408801608089018a8111156200065b57600080fd5b60005b60028110156200067d578251855293850193918501916001016200065e565b508296506200068d8b826200053c565b9550505050505092959194509250565b604080519081016001600160401b0381118282101715620006ce57634e487b7160e01b600052604160045260246000fd5b60405290565b60405160a081016001600160401b0381118282101715620006ce57634e487b7160e01b600052604160045260246000fd5b600082198211156200071b576200071b6200077b565b500190565b600181811c908216806200073557607f821691505b602082108114156200075757634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156200077457620007746200077b565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60805160a05160c0516147ac620007e260003960005050600061121c0152600081816103e70152818161076c01526114f301526147ac6000f3fe608060405234801561001057600080fd5b506004361061030c5760003560e01c806353cdef021161019d578063a22cb465116100e9578063dd48f774116100a2578063ee534a521161007c578063ee534a5214610702578063f01fe69214610715578063f87b704914610728578063fe8d18191461073257600080fd5b8063dd48f774146106a0578063e44bbb0f146106b3578063e985e9c5146106c657600080fd5b8063a22cb4651461062b578063a2cfb1691461063e578063b0ef747114610663578063b88d4fde14610672578063c1bd8cf914610685578063c87b56dd1461068d57600080fd5b80636c0360eb116101565780637b29ef2e116101305780637b29ef2e146105ea5780638e8fa11f146105fd57806395d89b41146106105780639e1276d51461061857600080fd5b80636c0360eb146105bc57806370a08231146105c457806371f03793146105d757600080fd5b806353cdef021461055d578063548d0a23146105705780635921a6e71461057b5780635b2a80bc1461058e5780635ba13abf146105965780636352211e146105a957600080fd5b80632cb6b0cf1161025c5780634707d000116102155780634f558e79116101ef5780634f558e79146105025780634f6ccce71461051557806350373a8c1461052857806353a1397c1461053b57600080fd5b80634707d000146104d45780634c76aff2146104e75780634cd412d5146104fa57600080fd5b80632cb6b0cf146104395780632dabf8fd1461045b5780632f745c591461046e57806333c186fd146104815780634036ab78146104a157806342842e0e146104c157600080fd5b8063099ea2d3116102c957806318160ddd116102a357806318160ddd146103e55780631c0d52761461040b57806323b872dd146104135780632481bb5c1461042657600080fd5b8063099ea2d3146103a95780630f574625146103b9578063119485d6146103cc57600080fd5b806301ffc9a71461031157806305d2035b1461033957806305e0ddcb1461034157806306fdde0314610356578063081812fc1461036b578063095ea7b314610396575b600080fd5b61032461031f366004613ea4565b61073d565b60405190151581526020015b60405180910390f35b610324610768565b61035461034f366004613f4c565b61079b565b005b61035e610908565b60405161033091906142db565b61037e610379366004613f4c565b61099a565b6040516001600160a01b039091168152602001610330565b6103546103a4366004613e25565b610a22565b6208001954620800185410610324565b6103546103c7366004613f8a565b610b38565b6103d7620800185481565b604051908152602001610330565b7f00000000000000000000000000000000000000000000000000000000000000006103d7565b610354610bd8565b610354610421366004613cc5565b610be4565b60095461037e906001600160a01b031681565b6103d7610447366004613f4c565b6208000a6020526000908152604090205481565b6103546104693660046140ef565b610c15565b6103d761047c366004613e25565b6110a3565b61049461048f366004613f4c565b611139565b6040516103309190614271565b6104b46104af366004613f4c565b6111c8565b6040516103309190614257565b6103546104cf366004613cc5565b611252565b6103546104e2366004613c8c565b61126d565b6103d76104f53660046140cd565b61141a565b610324611447565b610324610510366004613f4c565b6114e4565b6103d7610523366004613f4c565b6114ef565b6103d7610536366004613f4c565b611564565b6103d7610549366004613c52565b620800256020526000908152604090205481565b61035461056b366004613c52565b611587565b6103d7620800195481565b6103d76105893660046140cd565b611703565b6103d7611715565b6103546105a4366004613fe3565b611730565b61037e6105b7366004613f4c565b611871565b61035e6118e8565b6103d76105d2366004613c52565b6118f2565b6103546105e5366004613f8a565b611979565b6103546105f83660046140a8565b6119ed565b61035461060b366004613da0565b611c2a565b61035e611dae565b610354610626366004613e51565b611dbd565b610354610639366004613d72565b611eba565b61032461064c366004613f4c565b620800246020526000908152604090205460ff1681565b62080017546103249060ff1681565b610354610680366004613d06565b611f7f565b6103d7611fb1565b61035e61069b366004613f4c565b611fbc565b6103546106ae366004613c8c565b612087565b6103546106c1366004613f4c565b61219b565b6103246106d4366004613c8c565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b610324610710366004613f4c565b6121c2565b610354610723366004613f65565b6121fe565b6208000b546103d7565b6103d76208000c5481565b60006001600160e01b0319821663780e9d6360e01b14806107625750610762826122f6565b92915050565b60007f000000000000000000000000000000000000000000000000000000000000000061079460085490565b1015905090565b60095460405163bf40fac160e01b81526001600160a01b039091169063bf40fac1906107c99060040161440a565b60206040518083038186803b1580156107e157600080fd5b505afa1580156107f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108199190613c6f565b6001600160a01b0316336001600160a01b0316146108525760405162461bcd60e51b815260040161084990614370565b60405180910390fd5b80620800185411156108c35760405162461bcd60e51b815260206004820152603460248201527f416c7265616479206d6f726520757067726164657320646f6e65207468616e206044820152733a3432903932b8bab2b9ba32b2103634b6b4ba1760611b6064820152608401610849565b620800195460408051918252602082018390527f3651ff1393f20c815aec9fd17e87b2e765be1a16a740d604a1803a4d66fc6eb0910160405180910390a16208001955565b60606000805461091790614665565b80601f016020809104026020016040519081016040528092919081815260200182805461094390614665565b80156109905780601f1061096557610100808354040283529160200191610990565b820191906000526020600020905b81548152906001019060200180831161097357829003601f168201915b5050505050905090565b60006109a582612346565b610a065760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610849565b506000908152600460205260409020546001600160a01b031690565b6000610a2d82611871565b9050806001600160a01b0316836001600160a01b03161415610a9b5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610849565b336001600160a01b0382161480610ab75750610ab781336106d4565b610b295760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610849565b610b338383612363565b505050565b610b40611447565b1515600114610b615760405162461bcd60e51b815260040161084990614431565b6000610b6c84611871565b6001600160a01b038116600090815262080025602090815260408083205490519394509192610bac923092630f57462560e01b92339288928c920161415b565b604051602081830303815290604052805190602001209050610bd182828787876123d1565b5050505050565b610be2600161256a565b565b610bee3382612aaf565b610c0a5760405162461bcd60e51b8152600401610849906144d7565b610b33838383612b99565b6208001954620800185410610c6c5760405162461bcd60e51b815260206004820152601860248201527f4d6178696d756d207570677261646573207265616368656400000000000000006044820152606401610849565b818314158015610c7c5750808314155b8015610c885750808214155b610cf35760405162461bcd60e51b815260206004820152603660248201527f596f752061637475616c6c79206e65656420746f20757365203320646966666560448201527572656e7420746f6b656e7320746f207570677261646560501b6064820152608401610849565b610cfc83611871565b6001600160a01b0316336001600160a01b0316148015610d355750610d2082611871565b6001600160a01b0316336001600160a01b0316145b8015610d5a5750610d4581611871565b6001600160a01b0316336001600160a01b0316145b610db45760405162461bcd60e51b815260206004820152602560248201527f43616c6c65722068617320746f206265206f776e6572206f6620616c6c20746f60448201526435b2b7399760d91b6064820152608401610849565b600083815262080024602052604090205460ff16158015610de65750600082815262080024602052604090205460ff16155b8015610e035750600081815262080024602052604090205460ff16155b610e655760405162461bcd60e51b815260206004820152602d60248201527f43616e6e6f742075736564207374616d707320616c726561647920757365642060448201526c34b71030903ab833b930b2329760991b6064820152608401610849565b6000610e7084611139565b90506000816005811115610e8657610e866146fb565b1415610ee05760405162461bcd60e51b815260206004820152602360248201527f536c656570696e67207374616d70732063616e6e6f742062652075706772616460448201526232b21760e91b6064820152608401610849565b6000610eeb856111c8565b9050806001811115610eff57610eff6146fb565b610f08856111c8565b6001811115610f1957610f196146fb565b148015610f4f5750816005811115610f3357610f336146fb565b610f3c85611139565b6005811115610f4d57610f4d6146fb565b145b8015610f845750806001811115610f6857610f686146fb565b610f71846111c8565b6001811115610f8257610f826146fb565b145b8015610fb95750816005811115610f9d57610f9d6146fb565b610fa684611139565b6005811115610fb757610fb76146fb565b145b6110235760405162461bcd60e51b815260206004820152603560248201527f416c6c20746f6b656e7320696e766f6c766564206d7573742068617665207468604482015274329039b0b6b2903a3cb8329030b7321031b7b637b960591b6064820152608401610849565b60008481526208002460205260408082208054600160ff199182168117909255868452918320805490921617905561105b8684612d44565b9050857f896e9cf88136ab3715e7b8819d000d2840d5cdf2e3f882523b01a7c36b3b8e3084838888604051611093949392919061427f565b60405180910390a2505050505050565b60006110ae836118f2565b82106111105760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610849565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b600061114482612346565b61118b5760405162461bcd60e51b81526020600482015260186024820152772a37b5b2b71024a2103732b2b239903a379032bc34b9ba1760411b6044820152606401610849565b600a82630100000081106111a1576111a1614711565b602081049091015460ff601f9092166101000a9004166005811115610762576107626146fb565b60006111d382612346565b61121a5760405162461bcd60e51b81526020600482015260186024820152772a37b5b2b71024a2103732b2b239903a379032bc34b9ba1760411b6044820152606401610849565b7f000000000000000000000000000000000000000000000000000000000000000082101561124a57506000919050565b506001919050565b610b3383838360405180602001604052806000815250611f7f565b60095460405163bf40fac160e01b81526001600160a01b039091169063bf40fac19061129b90600401614340565b60206040518083038186803b1580156112b357600080fd5b505afa1580156112c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112eb9190613c6f565b6001600160a01b0316336001600160a01b03161461131b5760405162461bcd60e51b815260040161084990614481565b6040516370a0823160e01b81523060048201526001600160a01b0383169063a9059cbb90839083906370a082319060240160206040518083038186803b15801561136457600080fd5b505afa158015611378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139c9190613e8b565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b1580156113e257600080fd5b505af11580156113f6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b339190613e6e565b6208001a826002811061142c57600080fd5b60050201816005811061143e57600080fd5b01549150829050565b600080600960009054906101000a90046001600160a01b03166001600160a01b031663a564a2e06040518163ffffffff1660e01b815260040160206040518083038186803b15801561149857600080fd5b505afa1580156114ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d09190613e8b565b90508015806114de57504281115b91505090565b600061076282612346565b60007f000000000000000000000000000000000000000000000000000000000000000082106115605760405162461bcd60e51b815260206004820152601760248201527f496e646578206973206f7574206f6620626f756e64732e0000000000000000006044820152606401610849565b5090565b6208000b818154811061157657600080fd5b600091825260209091200154905081565b60095460405163bf40fac160e01b81526001600160a01b039091169063bf40fac1906115b59060040161440a565b60206040518083038186803b1580156115cd57600080fd5b505afa1580156115e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116059190613c6f565b6001600160a01b0316336001600160a01b0316146116355760405162461bcd60e51b815260040161084990614370565b6001600160a01b0381166116a75760405162461bcd60e51b815260206004820152603360248201527f596f75206e65656420746f2070726f7669646520616e2061637475616c20627260448201527234b233b2903230ba309031b7b73a3930b1ba1760691b6064820152608401610849565b6009546040516001600160a01b038084169216907f6a6e057f21cc834cf349d8150e92867f52cb34d54375f174c09c431538c3dfb990600090a3600980546001600160a01b0319166001600160a01b0392909216919091179055565b6208000d826002811061142c57600080fd5b6208000c546208000b5460009161172b916145ff565b905090565b60095460405163bf40fac160e01b815260206004820152600d60248201526c18dc99585d1950dbdb9d1c9bdb609a1b60448201526001600160a01b039091169063bf40fac19060640160206040518083038186803b15801561179157600080fd5b505afa1580156117a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c99190613c6f565b6001600160a01b0316336001600160a01b0316146117f95760405162461bcd60e51b8152600401610849906143bd565b611801610768565b1561181e5760405162461bcd60e51b815260040161084990614528565b805160005b8181101561186b5761185983828151811061184057611840614711565b6020026020010151828661185491906145d3565b612f38565b80611863816146a0565b915050611823565b50505050565b6000818152600260205260408120546001600160a01b0316806107625760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610849565b606061172b613077565b60006001600160a01b03821661195d5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610849565b506001600160a01b031660009081526003602052604090205490565b611981611447565b15156001146119a25760405162461bcd60e51b815260040161084990614431565b60006119ad84611871565b6001600160a01b038116600090815262080025602090815260408083205490519394509192610bac9230926371f0379360e01b9287928a928c920161415b565b60095460405163bf40fac160e01b815260206004820152600e60248201526d636f6c6f7252657665616c41504960901b60448201526001600160a01b039091169063bf40fac19060640160206040518083038186803b158015611a4f57600080fd5b505afa158015611a63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a879190613c6f565b6001600160a01b0316336001600160a01b03161480611abf5750611aaa82611871565b6001600160a01b0316336001600160a01b0316145b611b215760405162461bcd60e51b815260206004820152602d60248201527f596f752063616e6e6f7420737461727420636f6c6f722072657665616c20666f60448201526c39103a3434b9903a37b5b2b71760991b6064820152608401610849565b6000600a8363010000008110611b3957611b39614711565b602081049091015460ff601f9092166101000a9004166005811115611b6057611b606146fb565b6005811115611b7157611b716146fb565b14611bbe5760405162461bcd60e51b815260206004820152601d60248201527f436f6c6f72206e6565647320746f20626520756e72657665616c65642e0000006044820152606401610849565b60008281526208000a602052604090205415611c1c5760405162461bcd60e51b815260206004820152601d60248201527f436f6c6f722072657665616c20616c726561647920737461727465642e0000006044820152606401610849565b611c268282613125565b5050565b60095460405163bf40fac160e01b81526001600160a01b039091169063bf40fac190611c5890600401614340565b60206040518083038186803b158015611c7057600080fd5b505afa158015611c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca89190613c6f565b6001600160a01b0316336001600160a01b031614611cd85760405162461bcd60e51b815260040161084990614481565b6001600160a01b038316611d2e5760405162461bcd60e51b815260206004820152601e60248201527f6e65656420612076616c696420726576657273652072656769737472617200006044820152606401610849565b60405163c47f002760e01b81526001600160a01b0384169063c47f002790611d5c90859085906004016142ac565b602060405180830381600087803b158015611d7657600080fd5b505af1158015611d8a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186b9190613e8b565b60606001805461091790614665565b60095460405163bf40fac160e01b81526001600160a01b039091169063bf40fac190611deb9060040161440a565b60206040518083038186803b158015611e0357600080fd5b505afa158015611e17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3b9190613c6f565b6001600160a01b0316336001600160a01b031614611e6b5760405162461bcd60e51b815260040161084990614370565b62080017805460ff191682151590811790915560405160ff909116151581527f3e2361887bfc8618df045a4717e2ba4806adde3fc956485bef8271a994af77a19060200160405180910390a150565b6001600160a01b038216331415611f135760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610849565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611f893383612aaf565b611fa55760405162461bcd60e51b8152600401610849906144d7565b61186b848484846131a3565b600061172b60085490565b6060611fc782612346565b61202b5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610849565b6000612035613077565b905060008151116120555760405180602001604052806000815250612080565b8061205f846131d6565b6040516020016120709291906141ab565b6040516020818303038152906040525b9392505050565b60095460405163bf40fac160e01b81526001600160a01b039091169063bf40fac1906120b590600401614340565b60206040518083038186803b1580156120cd57600080fd5b505afa1580156120e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121059190613c6f565b6001600160a01b0316336001600160a01b0316146121355760405162461bcd60e51b815260040161084990614481565b60405163a22cb46560e01b81526001600160a01b0382811660048301526001602483015283169063a22cb46590604401600060405180830381600087803b15801561217f57600080fd5b505af1158015612193573d6000803e3d6000fd5b505050505050565b60005b81811015611c26576121b0600061256a565b806121ba816146a0565b91505061219e565b6000806121ce83611139565b60058111156121df576121df6146fb565b14801561076257505060009081526208000a6020526040902054151590565b60095460405163bf40fac160e01b815260206004820152600d60248201526c18dc99585d1950dbdb9d1c9bdb609a1b60448201526001600160a01b039091169063bf40fac19060640160206040518083038186803b15801561225f57600080fd5b505afa158015612273573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122979190613c6f565b6001600160a01b0316336001600160a01b0316146122c75760405162461bcd60e51b8152600401610849906143bd565b6122cf610768565b156122ec5760405162461bcd60e51b815260040161084990614528565b611c268183612f38565b60006001600160e01b031982166380ac58cd60e01b148061232757506001600160e01b03198216635b5e139f60e01b145b8061076257506301ffc9a760e01b6001600160e01b0319831614610762565b6000908152600260205260409020546001600160a01b0316151590565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061239882611871565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061242a856040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9050600061243882846132d4565b9050866001600160a01b0316816001600160a01b0316146124c15760405162461bcd60e51b815260206004820152603e60248201527f5369676e6174757265206e6565647320746f206d6174636820706172616d657460448201527f6572732c206e6f6e63652c20616e642063757272656e74206f776e65722e00006064820152608401610849565b6001600160a01b038781166000818152620800256020908152604091829020548251338152918201528893881692917fba05f551fcc429cba611372aa0055e3573f26273f66d1a48bdb5b4f7896bf022910160405180910390a46001600160a01b03871660009081526208002560205260408120805491612541836146a0565b9190505550612561878587604051806020016040528060008152506131a3565b50505050505050565b612572611715565b6125c75780156125c45760405162461bcd60e51b815260206004820152601960248201527f4e6f2070656e64696e6720636f6c6f722072657665616c732e000000000000006044820152606401610849565b50565b60006208000b6208000c54815481106125e2576125e2614711565b90600052602060002001549050436208000a6000838152602001908152602001600020541480612620575060008181526208000a6020526040902054155b8061267957506000600a826301000000811061263e5761263e614711565b602081049091015460ff601f9092166101000a9004166005811115612665576126656146fb565b6005811115612676576126766146fb565b14155b156126cc578115611c265760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f742072657665616c207468697320746f6b656e2e000000000000006044820152606401610849565b60006126d7826111c8565b60018111156126e8576126e86146fb565b905060006208000d826002811061270157612701614711565b60050201600401546208000d836002811061271e5761271e614711565b60050201600301546208000d846002811061273b5761273b614711565b60050201600201546208000d856002811061275857612758614711565b60050201600101546208000d866002811061277557612775614711565b600502015461278491906145d3565b61278e91906145d3565b61279891906145d3565b6127a291906145d3565b60008481526208000a6020526040812054919250906127c29085846132f8565b905060006208000d84600281106127db576127db614711565b60050201548210156127ef57506001612958565b6208000d846002811061280457612804614711565b60050201600101546208000d856002811061282157612821614711565b600502015461283091906145d3565b82101561283f57506002612958565b6208000d846002811061285457612854614711565b60050201600201546208000d856002811061287157612871614711565b60050201600101546208000d866002811061288e5761288e614711565b600502015461289d91906145d3565b6128a791906145d3565b8210156128b657506003612958565b6208000d84600281106128cb576128cb614711565b60050201600301546208000d85600281106128e8576128e8614711565b60050201600201546208000d866002811061290557612905614711565b60050201600101546208000d876002811061292257612922614711565b600502015461293191906145d3565b61293b91906145d3565b61294591906145d3565b82101561295457506004612958565b5060055b60008581526208000a602052604081205580600581111561297b5761297b6146fb565b600a866301000000811061299157612991614711565b602091828204019190066101000a81548160ff021916908360ff16021790555060016208000d85600281106129c8576129c8614711565b6005020160018360058111156129e0576129e06146fb565b6129ea9190614616565b60ff16600581106129fd576129fd614711565b0154612a0991906145ff565b6208000d8560028110612a1e57612a1e614711565b600502016001836005811115612a3657612a366146fb565b612a409190614616565b60ff1660058110612a5357612a53614711565b0155806005811115612a6757612a676146fb565b60405186907fad75059ecf48e7676bf13822559780f67d815e3fded0f493bc1d471386af315190600090a36208000c54612aa29060016145d3565b6208000c55505050505050565b6000612aba82612346565b612b1b5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610849565b6000612b2683611871565b9050806001600160a01b0316846001600160a01b03161480612b615750836001600160a01b0316612b568461099a565b6001600160a01b0316145b80612b9157506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b0316612bac82611871565b6001600160a01b031614612c145760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610849565b6001600160a01b038216612c765760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610849565b612c818383836133d2565b612c8c600082612363565b6001600160a01b0383166000908152600360205260408120805460019290612cb59084906145ff565b90915550506001600160a01b0382166000908152600360205260408120805460019290612ce39084906145d3565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600080826005811115612d5957612d596146fb565b612d649060016145d3565b6005811115612d7557612d756146fb565b9050806005811115612d8957612d896146fb565b600a8563010000008110612d9f57612d9f614711565b602091828204019190066101000a81548160ff021916908360ff1602179055506000612dca856111c8565b6001811115612ddb57612ddb6146fb565b905060016208001a8260028110612df457612df4614711565b600502016001866005811115612e0c57612e0c6146fb565b612e1691906145ff565b60058110612e2657612e26614711565b0154612e3291906145ff565b6208001a8260028110612e4757612e47614711565b600502016001866005811115612e5f57612e5f6146fb565b612e6991906145ff565b60058110612e7957612e79614711565b01556208001a8160028110612e9057612e90614711565b600502016001836005811115612ea857612ea86146fb565b612eb291906145ff565b60058110612ec257612ec2614711565b0154612ecf9060016145d3565b6208001a8260028110612ee457612ee4614711565b600502016001846005811115612efc57612efc6146fb565b612f0691906145ff565b60058110612f1657612f16614711565b0155620800188054906000612f2a836146a0565b909155509195945050505050565b6001600160a01b038216612f8e5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610849565b612f9781612346565b15612fe45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610849565b612ff0600083836133d2565b6001600160a01b03821660009081526003602052604081208054600192906130199084906145d3565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6009546040805163261220a360e01b815290516060926001600160a01b03169163261220a3916004808301926000929190829003018186803b1580156130bc57600080fd5b505afa1580156130d0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526130f89190810190613ede565b613100611dae565b6040516020016131119291906141da565b604051602081830303815290604052905090565b60008281526208000a60205260408082204390556208000b80546001810182559083527f5cda0c2ed41a786f13eb8950670e905590fce5dde6d8bf2faed5993ed4e04473018490555183917f94f1c40a3d78b2ae313cac6344c707738bbd4b641f71bd1e8a9d5765a0cb3be191a28015611c2657611c26600061256a565b6131ae848484612b99565b6131ba848484846135ee565b61186b5760405162461bcd60e51b8152600401610849906142ee565b6060816131fa5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613224578061320e816146a0565b915061321d9050600a836145eb565b91506131fe565b60008167ffffffffffffffff81111561323f5761323f614727565b6040519080825280601f01601f191660200182016040528015613269576020820181803683370190505b5090505b8415612b915761327e6001836145ff565b915061328b600a866146bb565b6132969060306145d3565b60f81b8183815181106132ab576132ab614711565b60200101906001600160f81b031916908160001a9053506132cd600a866145eb565b945061326d565b60008060006132e385856136fb565b915091506132f08161376b565b509392505050565b6000804385141561334b5760405162461bcd60e51b815260206004820152601b60248201527f5761697420666f72206e65787420626c6f636b20706c656173652e00000000006044820152606401610849565b6101004310806133665750613362610100436145ff565b8510155b1561337357508340613396565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4705b604080516020808201879052818301849052825180830384018152606090920190925280519101206133c99084906146bb565b95945050505050565b6133da611447565b15156001146133fb5760405162461bcd60e51b815260040161084990614431565b60095460405163bf40fac160e01b815260206004820152600b60248201526a3a37b5b2b72437b63232b960a91b60448201526001600160a01b039091169063bf40fac19060640160206040518083038186803b15801561345a57600080fd5b505afa15801561346e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134929190613c6f565b6001600160a01b0316826001600160a01b03161480156134ff57506000600a82630100000081106134c5576134c5614711565b602081049091015460ff601f9092166101000a90041660058111156134ec576134ec6146fb565b60058111156134fd576134fd6146fb565b145b1561354c5760405162461bcd60e51b815260206004820152601f60248201527f52657665616c20636f6c6f72206265666f7265206465706f736974696e6721006044820152606401610849565b6001600160a01b038316158015906135b157506000600a826301000000811061357757613577614711565b602081049091015460ff601f9092166101000a900416600581111561359e5761359e6146fb565b60058111156135af576135af6146fb565b145b80156135cb575060008181526208000a6020526040902054155b156135e35762080017546135e390829060ff16613125565b610b33838383613926565b60006001600160a01b0384163b156136f057604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061363290339089908890889060040161421a565b602060405180830381600087803b15801561364c57600080fd5b505af192505050801561367c575060408051601f3d908101601f1916820190925261367991810190613ec1565b60015b6136d6573d8080156136aa576040519150601f19603f3d011682016040523d82523d6000602084013e6136af565b606091505b5080516136ce5760405162461bcd60e51b8152600401610849906142ee565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612b91565b506001949350505050565b6000808251604114156137325760208301516040840151606085015160001a6137268782858561399f565b94509450505050613764565b82516040141561375c5760208301516040840151613751868383613a8c565b935093505050613764565b506000905060025b9250929050565b600081600481111561377f5761377f6146fb565b14156137885750565b600181600481111561379c5761379c6146fb565b14156137ea5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610849565b60028160048111156137fe576137fe6146fb565b141561384c5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610849565b6003816004811115613860576138606146fb565b14156138b95760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610849565b60048160048111156138cd576138cd6146fb565b14156125c45760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610849565b6001600160a01b0383166139425761393d81613abb565b613965565b816001600160a01b0316836001600160a01b031614613965576139658382613ad3565b6001600160a01b03821661397c57610b3381613b70565b826001600160a01b0316826001600160a01b031614610b3357610b338282613bb8565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156139d65750600090506003613a83565b8460ff16601b141580156139ee57508460ff16601c14155b156139ff5750600090506004613a83565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613a53573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613a7c57600060019250925050613a83565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b01613aad8782888561399f565b935093505050935093915050565b60088054906000613acb836146a0565b919050555050565b60006001613ae0846118f2565b613aea91906145ff565b600083815260076020526040902054909150808214613b3d576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b60405162461bcd60e51b815260206004820152601c60248201527f5468697320746f6b656e2063616e6e6f74206265206275726e65642e000000006044820152606401610849565b6000613bc3836118f2565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b600082601f830112613c0d57600080fd5b8135613c20613c1b826145ab565b61457a565b818152846020838601011115613c3557600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613c6457600080fd5b81356120808161473d565b600060208284031215613c8157600080fd5b81516120808161473d565b60008060408385031215613c9f57600080fd5b8235613caa8161473d565b91506020830135613cba8161473d565b809150509250929050565b600080600060608486031215613cda57600080fd5b8335613ce58161473d565b92506020840135613cf58161473d565b929592945050506040919091013590565b60008060008060808587031215613d1c57600080fd5b8435613d278161473d565b93506020850135613d378161473d565b925060408501359150606085013567ffffffffffffffff811115613d5a57600080fd5b613d6687828801613bfc565b91505092959194509250565b60008060408385031215613d8557600080fd5b8235613d908161473d565b91506020830135613cba81614752565b600080600060408486031215613db557600080fd5b8335613dc08161473d565b9250602084013567ffffffffffffffff80821115613ddd57600080fd5b818601915086601f830112613df157600080fd5b813581811115613e0057600080fd5b876020828501011115613e1257600080fd5b6020830194508093505050509250925092565b60008060408385031215613e3857600080fd5b8235613e438161473d565b946020939093013593505050565b600060208284031215613e6357600080fd5b813561208081614752565b600060208284031215613e8057600080fd5b815161208081614752565b600060208284031215613e9d57600080fd5b5051919050565b600060208284031215613eb657600080fd5b813561208081614760565b600060208284031215613ed357600080fd5b815161208081614760565b600060208284031215613ef057600080fd5b815167ffffffffffffffff811115613f0757600080fd5b8201601f81018413613f1857600080fd5b8051613f26613c1b826145ab565b818152856020838501011115613f3b57600080fd5b6133c9826020830160208601614639565b600060208284031215613f5e57600080fd5b5035919050565b60008060408385031215613f7857600080fd5b823591506020830135613cba8161473d565b600080600060608486031215613f9f57600080fd5b833592506020840135613fb18161473d565b9150604084013567ffffffffffffffff811115613fcd57600080fd5b613fd986828701613bfc565b9150509250925092565b60008060408385031215613ff657600080fd5b8235915060208084013567ffffffffffffffff8082111561401657600080fd5b818601915086601f83011261402a57600080fd5b81358181111561403c5761403c614727565b8060051b915061404d84830161457a565b8181528481019084860184860187018b101561406857600080fd5b600095505b8386101561409757803594506140828561473d565b8483526001959095019491860191860161406d565b508096505050505050509250929050565b600080604083850312156140bb57600080fd5b823591506020830135613cba81614752565b600080604083850312156140e057600080fd5b50508035926020909101359150565b60008060006060848603121561410457600080fd5b505081359360208301359350604090920135919050565b60008151808452614133816020860160208601614639565b601f01601f19169290920160200192915050565b60068110614157576141576146fb565b9052565b6bffffffffffffffffffffffff19606097881b811682526001600160e01b031996909616601482015293861b8516601885015291851b909316602c83015260408201929092529182015260800190565b600083516141bd818460208801614639565b8351908301906141d1818360208801614639565b01949350505050565b600083516141ec818460208801614639565b835190830190614200818360208801614639565b652f6d6574612f60d01b9101908152600601949350505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061424d9083018461411b565b9695505050505050565b602081016002831061426b5761426b6146fb565b91905290565b602081016107628284614147565b6080810161428d8287614147565b61429a6020830186614147565b60408201939093526060015292915050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b602081526000612080602083018461411b565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252601690820152751d1bdad95b905cdcda59db9b595b9d10dbdb9d1c9bdb60521b604082015260600190565b6020808252602d908201527f627269646765436f6e74726f6c206b657920726571756972656420666f72207460408201526c3434b990333ab731ba34b7b71760991b606082015260800190565b6020808252602d908201527f637265617465436f6e74726f6c206b657920726571756972656420666f72207460408201526c3434b990333ab731ba34b7b71760991b606082015260800190565b6020808252600d908201526c189c9a5919d950dbdb9d1c9bdb609a1b604082015260600190565b60208082526030908201527f546869732063616c6c206f6e6c7920776f726b73207768656e207472616e736660408201526f32b9399030b9329032b730b13632b21760811b606082015260800190565b60208082526036908201527f746f6b656e41737369676e6d656e74436f6e74726f6c206b65792072657175696040820152753932b2103337b9103a3434b990333ab731ba34b7b71760511b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526032908201527f546869732063616c6c206f6e6c7920776f726b73207768656e206d696e74696e604082015271339034b9903737ba103334b734b9b432b21760711b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff811182821017156145a3576145a3614727565b604052919050565b600067ffffffffffffffff8211156145c5576145c5614727565b50601f01601f191660200190565b600082198211156145e6576145e66146cf565b500190565b6000826145fa576145fa6146e5565b500490565b600082821015614611576146116146cf565b500390565b600060ff821660ff841680821015614630576146306146cf565b90039392505050565b60005b8381101561465457818101518382015260200161463c565b8381111561186b5750506000910152565b600181811c9082168061467957607f821691505b6020821081141561469a57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156146b4576146b46146cf565b5060010190565b6000826146ca576146ca6146e5565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146125c457600080fd5b80151581146125c457600080fd5b6001600160e01b0319811681146125c457600080fdfea2646970667358221220eef371d70eae50d77d863fd22282832d02d313840a72ea5442669d797c93535464736f6c634300080700330000000000000000000000000884fc15e31b1b634732e140cb3f94b3cbfdd1c500000000000000000000000000000000000000000000000000000000000222e0000000000000000000000000000000000000000000000000000000000001117000000000000000000000000000000000000000000000000000000000000111700000000000000000000000000000000000000000000000000000000000008f1900000000000000000000000000000000000000000000000000000000000048eb0000000000000000000000000000000000000000000000000000000000002475000000000000000000000000000000000000000000000000000000000000123b00000000000000000000000000000000000000000000000000000000000002bc0000000000000000000000000000000000000000000000000000000000008f1900000000000000000000000000000000000000000000000000000000000048eb0000000000000000000000000000000000000000000000000000000000002475000000000000000000000000000000000000000000000000000000000000123b00000000000000000000000000000000000000000000000000000000000002bc
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000884fc15e31b1b634732e140cb3f94b3cbfdd1c500000000000000000000000000000000000000000000000000000000000222e0000000000000000000000000000000000000000000000000000000000001117000000000000000000000000000000000000000000000000000000000000111700000000000000000000000000000000000000000000000000000000000008f1900000000000000000000000000000000000000000000000000000000000048eb0000000000000000000000000000000000000000000000000000000000002475000000000000000000000000000000000000000000000000000000000000123b00000000000000000000000000000000000000000000000000000000000002bc0000000000000000000000000000000000000000000000000000000000008f1900000000000000000000000000000000000000000000000000000000000048eb0000000000000000000000000000000000000000000000000000000000002475000000000000000000000000000000000000000000000000000000000000123b00000000000000000000000000000000000000000000000000000000000002bc
-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 0000000000000000000000000884fc15e31b1b634732e140cb3f94b3cbfdd1c5
Arg [1] : 00000000000000000000000000000000000000000000000000000000000222e0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000011170
Arg [3] : 0000000000000000000000000000000000000000000000000000000000011170
Arg [4] : 0000000000000000000000000000000000000000000000000000000000008f19
Arg [5] : 00000000000000000000000000000000000000000000000000000000000048eb
Arg [6] : 0000000000000000000000000000000000000000000000000000000000002475
Arg [7] : 000000000000000000000000000000000000000000000000000000000000123b
Arg [8] : 00000000000000000000000000000000000000000000000000000000000002bc
Arg [9] : 0000000000000000000000000000000000000000000000000000000000008f19
Arg [10] : 00000000000000000000000000000000000000000000000000000000000048eb
Arg [11] : 0000000000000000000000000000000000000000000000000000000000002475
Arg [12] : 000000000000000000000000000000000000000000000000000000000000123b
Arg [13] : 00000000000000000000000000000000000000000000000000000000000002bc
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.