ERC-721
Overview
Max Total Supply
4,444 BUSH
Holders
784
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 BUSHLoading...
Loading
Loading...
Loading
Loading...
Loading
Minimal Proxy Contract for 0x8888596f6c3a142a11e408610f2f4560905f3065
Contract Name:
Migrated721
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity)
/** *Submitted for verification at apescan.io on 2025-01-09 */ // SPDX-License-Identifier: MIT pragma solidity <0.9.0 >=0.8.4 ^0.8.0 ^0.8.1 ^0.8.2; // node_modules/@lambdalf-dev/ethereum-contracts/contracts/interfaces/IERC165.sol /** * @dev Required interface of an ERC165 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * Note: the ERC-165 identifier for this interface is 0x01ffc9a7. */ interface IERC165 { // ************************************** // ***** VIEW ***** // ************************************** /// @dev Returns if a contract implements an interface. /// Interface identification is specified in ERC-165. This function uses less than 30,000 gas. function supportsInterface(bytes4 interfaceId_) external view returns (bool); // ************************************** } // node_modules/@lambdalf-dev/ethereum-contracts/contracts/interfaces/IERC173.sol // import "./IERC165.sol"; /** * @dev Required interface of an ERC173 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-173[EIP]. * Note: the ERC-165 identifier for this interface is 0x7f5828d0. */ interface IERC173 /* is IERC165 */ { // ************************************** // ***** ERRORS ***** // ************************************** /// @dev Thrown when `operator` is not the contract owner. /// /// @param operator address trying to use a function reserved to contract owner without authorization error IERC173_NOT_OWNER(address operator); // ************************************** // ************************************** // ***** EVENTS ***** // ************************************** /// @dev This emits when ownership of a contract changes. /// /// @param previousOwner the previous contract owner /// @param newOwner the new contract owner event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // ************************************** // ************************************** // ***** CONTRACT_OWNER ***** // ************************************** /// @dev Set the address of the new owner of the contract. /// Set `newOwner_` to address(0) to renounce any ownership. function transferOwnership(address newOwner_) external; // ************************************** // ************************************** // ***** VIEW ***** // ************************************** /// @dev Returns the address of the owner. function owner() external view returns(address); // ************************************** } // node_modules/@lambdalf-dev/ethereum-contracts/contracts/interfaces/IERC2981.sol // import "./IERC165.sol"; /** * @dev Required interface of an ERC2981 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-2981[EIP]. * Note: the ERC-165 identifier for this interface is 0x2a55205a. */ interface IERC2981 /* is IERC165 */ { // ************************************** // ***** ERRORS ***** // ************************************** /// @dev Thrown when the desired royalty rate is higher than 10,000 error IERC2981_INVALID_ROYALTIES(); // ************************************** // ************************************** // ***** VIEW ***** // ************************************** /// @dev Called with the sale price to determine how much royalty is owed and to whom. function royaltyInfo(uint256 tokenId_, uint256 salePrice_) external view returns (address receiver, uint256 royaltyAmount); // ************************************** } // node_modules/@lambdalf-dev/ethereum-contracts/contracts/interfaces/IERC721.sol // import "./IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-721[EIP]. * Note: the ERC-165 identifier for this interface is 0x80ac58cd. */ interface IERC721 /* is IERC165 */ { // ************************************** // ***** ERRORS ***** // ************************************** /// @dev Thrown when `operator` is not allowed to manage `tokenId`. /// /// @param operator address trying to manage the token /// @param tokenId identifier of the NFT being referenced error IERC721_CALLER_NOT_APPROVED(address operator, uint256 tokenId); /// @dev Thrown when user tries to approve themselves for managing a token they own. error IERC721_INVALID_APPROVAL(); /// @dev Thrown when a token is being transferred to a contract unable to handle it or the zero address. /// /// @param receiver address unable to receive the token error IERC721_INVALID_RECEIVER(address receiver); /// @dev Thrown when checking ownership of the wrong token owner. error IERC721_INVALID_TOKEN_OWNER(); /// @dev Thrown when the requested token doesn"t exist. /// /// @param tokenId identifier of the NFT being referenced error IERC721_NONEXISTANT_TOKEN(uint256 tokenId); // ************************************** // ************************************** // ***** EVENTS ***** // ************************************** /// @dev This emits when the approved address for an NFT is changed or reaffirmed. /// The zero address indicates there is no approved address. /// When a Transfer event emits, this also indicates that the approved address for that NFT (if any) is reset to none. /// /// @param owner address that owns the token /// @param approved address that is allowed to manage the token /// @param tokenId identifier of the token being approved event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /// @dev This emits when an operator is enabled or disabled for an owner. The operator can manage all NFTs of the owner. /// /// @param owner address that owns the tokens /// @param operator address that is allowed or not to manage the tokens /// @param approved whether the operator is allowed or not event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /// @dev This emits when ownership of any NFT changes by any mechanism. /// This event emits when NFTs are created (`from` == 0) and destroyed (`to` == 0). /// Exception: during contract creation, any number of NFTs may be created and assigned without emitting Transfer. /// At the time of any transfer, the approved address for that NFT (if any) is reset to none. /// /// @param from address the token is being transferred from /// @param to address the token is being transferred to /// @param tokenId identifier of the token being transferred event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); // ************************************** // ************************************** // ***** PUBLIC ***** // ************************************** /// @notice Change or reaffirm the approved address for an NFT /// @dev The zero address indicates there is no approved address. /// Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. function approve(address approved_, uint256 tokenId_) external; /// @notice Transfers the ownership of an NFT from one address to another address /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. /// Throws if `from_` is not the current owner. /// Throws if `to_` is the zero address. /// Throws if `tokenId_` is not a valid NFT. /// When transfer is complete, this function checks if `to_` is a smart contract (code size > 0). /// If so, it calls {onERC721Received} on `to_` and throws if the return value is not /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. function safeTransferFrom(address from_, address to_, uint256 tokenId_, bytes calldata data_) external; /// @notice Transfers the ownership of an NFT from one address to another address /// @dev This works identically to the other function with an extra data parameter, /// except this function just sets data to "". function safeTransferFrom(address from_, address to_, uint256 tokenId_) external; /// @notice Enable or disable approval for a third party ("operator") to manage all of `msg.sender`'s assets. /// @dev Emits the ApprovalForAll event. The contract MUST allow multiple operators per owner. function setApprovalForAll(address operator_, bool approved_) external; /// @notice Transfer ownership of an NFT. /// The caller is responsible to confirm that `to_` is capable of receiving nfts or /// else they may be permanently lost /// @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this NFT. /// Throws if `from_` is not the current owner. /// Throws if `to_` is the zero address. /// Throws if `tokenId_` is not a valid NFT. function transferFrom(address from_, address to_, uint256 tokenId_) external; // ************************************** // ************************************** // ***** VIEW ***** // ************************************** /// @notice Count all NFTs assigned to an owner /// @dev NFTs assigned to the zero address are considered invalid. Throws for queries about the zero address. function balanceOf(address owner_) external view returns (uint256); /// @notice Get the approved address for a single NFT /// @dev Throws if `tokenId_` is not a valid NFT. function getApproved(uint256 tokenId_) external view returns (address); /// @notice Query if an address is an authorized operator for another address function isApprovedForAll(address owner_, address operator_) external view returns (bool); /// @notice Find the owner of an NFT /// @dev NFTs assigned to zero address are considered invalid, and queries /// about them do throw. function ownerOf(uint256 tokenId_) external view returns (address); // ************************************** } // node_modules/@lambdalf-dev/ethereum-contracts/contracts/interfaces/IERC721Enumerable.sol // import "./IERC721.sol"; /** * @dev Required interface of an ERC721 compliant contract, optional enumeration extension, as defined in the * https://eips.ethereum.org/EIPS/eip-721[EIP]. * Note: the ERC-165 identifier for this interface is 0x780e9d63. */ interface IERC721Enumerable /* is IERC721 */ { // ************************************** // ***** ERRORS ***** // ************************************** /// @dev Thrown when trying to get the token at an index that doesn"t exist. /// /// @param index the inexistant index error IERC721Enumerable_INDEX_OUT_OF_BOUNDS(uint256 index); /// @dev Thrown when trying to get the token owned by `tokenOwner` at an index that doesn"t exist. /// /// @param index the inexistant index error IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS(uint256 index); // ************************************** // ************************************** // ***** VIEW ***** // ************************************** /// @dev Enumerate valid NFTs /// Throws if `index_` >= {totalSupply()}. function tokenByIndex(uint256 index_) external view returns (uint256); /// @dev Enumerate NFTs assigned to an owner /// Throws if `index_` >= {balanceOf(owner_)} or if `owner_` is the zero address, representing invalid NFTs. function tokenOfOwnerByIndex(address owner_, uint256 index_) external view returns (uint256); /// @dev Count NFTs tracked by this contract function totalSupply() external view returns (uint256); // ************************************** } // node_modules/@lambdalf-dev/ethereum-contracts/contracts/interfaces/IERC721Metadata.sol // import "./IERC721.sol"; /** * @dev Required interface of an ERC721 compliant contract, optional metadata extension, as defined in the * https://eips.ethereum.org/EIPS/eip-721[EIP]. * Note: the ERC-165 identifier for this interface is 0x5b5e139f. */ interface IERC721Metadata /* is IERC721 */ { // ************************************** // ***** VIEW ***** // ************************************** /// @dev A descriptive name for a collection of NFTs in this contract function name() external view returns (string memory); /// @dev An abbreviated name for NFTs in this contract function symbol() external view returns (string memory); /// @dev A distinct Uniform Resource Identifier (URI) for a given asset. /// Throws if `tokenId_` is not a valid NFT. URIs are defined in RFC 3986. /// The URI may point to a JSON file that conforms to the "ERC721 Metadata JSON Schema". function tokenURI(uint256 tokenId_) external view returns (string memory); // ************************************** } // node_modules/@lambdalf-dev/ethereum-contracts/contracts/interfaces/IERC721Receiver.sol /** * @dev Required interface of an ERC721 receiver compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-721[EIP]. * Note: the ERC-165 identifier for this interface is 0x150b7a02. */ interface IERC721Receiver { // ************************************** // ***** VIEW ***** // ************************************** /// @dev Handle the receipt of an NFT /// The ERC721 smart contract calls this function on the recipient after a `transfer`. /// This function MAY throw to revert and reject the transfer. /// Return of other than the magic value MUST result in the transaction being reverted. /// Note: the contract address is always the message sender. function onERC721Received( address operator_, address from_, uint256 tokenId_, bytes calldata data_ ) external returns(bytes4); // ************************************** } // node_modules/@openzeppelin/contracts/utils/Address.sol // OpenZeppelin Contracts (last updated v4.9.0) (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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/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.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } // node_modules/@openzeppelin/contracts/utils/structs/BitMaps.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/BitMaps.sol) /** * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential. * Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor]. */ library BitMaps { struct BitMap { mapping(uint256 => uint256) _data; } /** * @dev Returns whether the bit at `index` is set. */ function get(BitMap storage bitmap, uint256 index) internal view returns (bool) { uint256 bucket = index >> 8; uint256 mask = 1 << (index & 0xff); return bitmap._data[bucket] & mask != 0; } /** * @dev Sets the bit at `index` to the boolean `value`. */ function setTo(BitMap storage bitmap, uint256 index, bool value) internal { if (value) { set(bitmap, index); } else { unset(bitmap, index); } } /** * @dev Sets the bit at `index`. */ function set(BitMap storage bitmap, uint256 index) internal { uint256 bucket = index >> 8; uint256 mask = 1 << (index & 0xff); bitmap._data[bucket] |= mask; } /** * @dev Unsets the bit at `index`. */ function unset(BitMap storage bitmap, uint256 index) internal { uint256 bucket = index >> 8; uint256 mask = 1 << (index & 0xff); bitmap._data[bucket] &= ~mask; } } // node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } } // src/ERC173Initializable.sol /** * Author: Lambdalf the White */ abstract contract ERC173Initializable is IERC173, Initializable { // ************************************** // ***** STORAGE VARIABLES ***** // ************************************** /// @dev The current contract owner. address private _owner; // ************************************** function _init_ERC173(address owner_) internal onlyInitializing { _owner = owner_; } // ************************************** // ***** MODIFIERS ***** // ************************************** /// @dev Throws if called by any account other than the owner. modifier onlyOwner() { if (owner() != msg.sender) { revert IERC173_NOT_OWNER(msg.sender); } _; } // ************************************** // ************************************** // ***** CONTRACT_OWNER ***** // ************************************** /// @dev Transfers ownership of the contract to `newOwner_`. /// /// @param newOwner_ address of the new contract owner /// /// Requirements: /// /// - Caller must be the contract owner. function transferOwnership(address newOwner_) public virtual override onlyOwner { address _oldOwner_ = _owner; _owner = newOwner_; emit OwnershipTransferred(_oldOwner_, newOwner_); } // ************************************** // ************************************** // ***** VIEW ***** // ************************************** /// @dev Returns the address of the current contract owner. /// /// @return contractOwner the current contract owner function owner() public view virtual override returns (address contractOwner) { return _owner; } // ************************************** } // src/ERC2981Initializable.sol /** * Author: Lambdalf the White */ abstract contract ERC2981Initializable is IERC2981, Initializable { // ************************************** // ***** DATA TYPES ***** // ************************************** /// @dev A structure representing royalties struct RoyaltyData { address recipient; uint96 rate; } // ************************************** // ************************************** // ***** BYTECODE VARIABLES ***** // ************************************** /// @dev Royalty rate is stored out of 10,000 instead of a percentage /// to allow for up to two digits below the unit such as 2.5% or 1.25%. uint256 public constant ROYALTY_BASE = 10_000; // ************************************** // ************************************** // ***** STORAGE VARIABLES ***** // ************************************** /// @dev Represents the royalties on each sale on secondary markets. /// Set rate to 0 to have no royalties. RoyaltyData private _royaltyData; // ************************************** function _init_ERC2981(address royaltyRecipient_, uint96 royaltyRate_) internal onlyInitializing { _setRoyaltyInfo(royaltyRecipient_, royaltyRate_); } // ************************************** // ***** VIEW ***** // ************************************** /// @dev Called with the sale price to determine how much royalty is owed and to whom. /// /// @param tokenId_ identifier of the NFT being referenced /// @param salePrice_ the sale price of the token sold /// /// @return receiver the address receiving the royalties /// @return royaltyAmount the royalty payment amount /* solhint-disable no-unused-vars */ function royaltyInfo( uint256 tokenId_, uint256 salePrice_ ) public view virtual override returns (address receiver, uint256 royaltyAmount) { RoyaltyData memory _data_ = _royaltyData; if (salePrice_ == 0 || _data_.rate == 0 || _data_.recipient == address(0)) { return (address(0), 0); } uint256 _royaltyAmount_ = _data_.rate * salePrice_ / ROYALTY_BASE; return (_data_.recipient, _royaltyAmount_); } /* solhint-enable no-unused-vars */ // ************************************** // ************************************** // ***** INTERNAL ***** // ************************************** /// @dev Sets the royalty rate to `newRoyaltyRate_` and the royalty recipient to `newRoyaltyRecipient_`. /// /// @param newRoyaltyRecipient_ the address that will receive royalty payments /// @param newRoyaltyRate_ the percentage of the sale price that will be taken off as royalties, /// expressed in Basis Points (100 BP = 1%) /// /// Requirements: /// /// - `newRoyaltyRate_` cannot be higher than {ROYALTY_BASE}; function _setRoyaltyInfo(address newRoyaltyRecipient_, uint96 newRoyaltyRate_) internal virtual { if (newRoyaltyRate_ > ROYALTY_BASE) { revert IERC2981_INVALID_ROYALTIES(); } _royaltyData = RoyaltyData(newRoyaltyRecipient_, newRoyaltyRate_); } // ************************************** } // src/Migrated721.sol /** * Author: Lambdalf the White */ contract Migrated721 is IERC165, ERC173Initializable, ERC2981Initializable, IERC721, IERC721Metadata, IERC721Enumerable { // ************************************** // ***** ERRORS ***** // ************************************** /// @dev Thrown when trying to withdraw from the contract with no balance. error ETHER_NO_BALANCE(); /// @dev Thrown when contract fails to send ether to recipient. /// /// @param to the recipient of the ether /// @param amount the amount of ether being sent error ETHER_TRANSFER_FAIL(address to, uint256 amount); // ************************************** // ************************************** // ***** STORAGE VARIABLES ***** // ************************************** IERC721 public underlyingAsset; // List of burned tokens BitMaps.BitMap private _burned; // *********** // * IERC721 * // *********** /// @dev Identifier of the next token to be minted uint256 private _nextId; /// @dev Token ID mapped to approved address mapping(uint256 => address) private _approvals; /// @dev Token owner mapped to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /// @dev List of owner addresses mapping(uint256 => address) private _owners; // *********** // ******************* // * IERC721Metadata * // ******************* /// @dev The token's base URI. string private _baseUri; /// @dev The name of the tokens, for token trackers. string private _name; /// @dev The symbol of the tokens, for token trackers. string private _symbol; // ******************* // ************************************** constructor() { initialize(address(0), address(0), address(0), 0, 0, "", "", ""); } function initialize( address admin_, address asset_, address royaltyRecipient_, uint96 royaltyRate_, uint256 supply_, string memory name_, string memory symbol_, string memory baseUri_ ) public initializer { underlyingAsset = IERC721(asset_); _nextId = supply_ + 1; _name = name_; _symbol = symbol_; _setBaseUri(baseUri_); _init_ERC173(admin_); _init_ERC2981(royaltyRecipient_, royaltyRate_); } function indexTokens(uint256 fromTokenId_, uint256 toTokenId_) public { for (uint256 i = fromTokenId_; i < toTokenId_; ++i) { emit Transfer(address(0), ownerOf(i), i); } } // ************************************** // ***** FALLBACK ***** // ************************************** fallback() external payable {} // solhint-disable no-empty-blocks receive() external payable {} // solhint-disable no-empty-blocks // ************************************** // ************************************** // ***** MODIFIER ***** // ************************************** // *********** // * IERC721 * // *********** /// @dev Throws if `tokenId_` doesn't exist. /// A token exists if it has been minted and is not owned by the zero address. /// /// @param tokenId_ identifier of the NFT being referenced modifier exists(uint256 tokenId_) { if (!_exists(tokenId_)) { revert IERC721_NONEXISTANT_TOKEN(tokenId_); } _; } // *********** // ************************************** // ************************************** // ***** PUBLIC ***** // ************************************** // *********** // * IERC721 * // *********** /// @dev Gives permission to `to_` to transfer the token number `tokenId_` on behalf of its owner. /// 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. /// /// @param to_ The new approved NFT controller /// @param tokenId_ The NFT to approve /// /// Requirements: /// /// - The token number `tokenId_` must exist. /// - The caller must own the token or be an approved operator. /// - Must emit an {Approval} event. function approve(address to_, uint256 tokenId_) public virtual override { address _tokenOwner_ = ownerOf(tokenId_); if (to_ == _tokenOwner_) { revert IERC721_INVALID_APPROVAL(); } bool _isApproved_ = _isApprovedOrOwner(_tokenOwner_, msg.sender, tokenId_); if (!_isApproved_) { revert IERC721_CALLER_NOT_APPROVED(msg.sender, tokenId_); } _approvals[tokenId_] = to_; emit Approval(_tokenOwner_, to_, tokenId_); } /// @dev Transfers the token number `tokenId_` from `from_` to `to_`. /// /// @param from_ The current owner of the NFT /// @param to_ The new owner /// @param tokenId_ identifier of the NFT being referenced /// /// Requirements: /// /// - The token number `tokenId_` must exist. /// - `from_` must be the token owner. /// - The caller must own the token or be an approved operator. /// - `to_` must not be the zero address. /// - If `to_` is a contract, it must implement {IERC721Receiver-onERC721Received} with a return value of `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, /// - Must emit a {Transfer} event. function safeTransferFrom(address from_, address to_, uint256 tokenId_) public virtual override { safeTransferFrom(from_, to_, tokenId_, ""); } /// @dev Transfers the token number `tokenId_` from `from_` to `to_`. /// /// @param from_ The current owner of the NFT /// @param to_ The new owner /// @param tokenId_ identifier of the NFT being referenced /// @param data_ Additional data with no specified format, sent in call to `to_` /// /// Requirements: /// /// - The token number `tokenId_` must exist. /// - `from_` must be the token owner. /// - The caller must own the token or be an approved operator. /// - `to_` must not be the zero address. /// - If `to_` is a contract, it must implement {IERC721Receiver-onERC721Received} with a return value of `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, /// - Must emit a {Transfer} event. function safeTransferFrom(address from_, address to_, uint256 tokenId_, bytes memory data_) public virtual override { transferFrom(from_, to_, tokenId_); if (!_checkOnERC721Received(from_, to_, tokenId_, data_)) { revert IERC721_INVALID_RECEIVER(to_); } } /// @dev Allows or disallows `operator_` to manage the caller's tokens on their behalf. /// /// @param operator_ Address to add to the set of authorized operators /// @param approved_ True if the operator is approved, false to revoke approval /// /// Requirements: /// /// - Must emit an {ApprovalForAll} event. function setApprovalForAll(address operator_, bool approved_) public virtual override { if (operator_ == msg.sender) { revert IERC721_INVALID_APPROVAL(); } _operatorApprovals[msg.sender][operator_] = approved_; emit ApprovalForAll(msg.sender, operator_, approved_); } /// @dev Transfers the token number `tokenId_` from `from_` to `to_`. /// /// @param from_ the current owner of the NFT /// @param to_ the new owner /// @param tokenId_ identifier of the NFT being referenced /// /// Requirements: /// /// - The token number `tokenId_` must exist. /// - `from_` must be the token owner. /// - The caller must own the token or be an approved operator. /// - `to_` must not be the zero address. /// - Must emit a {Transfer} event. function transferFrom(address from_, address to_, uint256 tokenId_) public virtual override { if (to_ == address(0)) { revert IERC721_INVALID_RECEIVER(to_); } address _tokenOwner_ = ownerOf(tokenId_); if (from_ != _tokenOwner_) { revert IERC721_INVALID_TOKEN_OWNER(); } if (!_isApprovedOrOwner(_tokenOwner_, msg.sender, tokenId_)) { revert IERC721_CALLER_NOT_APPROVED(msg.sender, tokenId_); } _transfer(from_, to_, tokenId_); } // *********** // *********************** // * ERC721BatchBurnable * // *********************** /// @dev Burns `tokenId_`. /// /// Requirements: /// /// - `tokenId_` must exist /// - The caller must own `tokenId_` or be an approved operator function burn(uint256 tokenId_) public { address _tokenOwner_ = ownerOf(tokenId_); if (!_isApprovedOrOwner(_tokenOwner_, msg.sender, tokenId_)) { revert IERC721_CALLER_NOT_APPROVED(msg.sender, tokenId_); } BitMaps.set(_burned, tokenId_); _transfer(_tokenOwner_, address(0), tokenId_); } // *********************** // ************************************** // ************************************** // ***** CONTRACT_OWNER ***** // ************************************** /// @notice Withdraws all the money stored in the contract and sends it to the treasury. /// /// Requirements: /// /// - Caller must be the contract owner. /// - Contract must have a positive balance. /// - Caller must be able to receive the funds. function withdraw() public onlyOwner { uint256 _balance_ = address(this).balance; if (_balance_ == 0) { revert ETHER_NO_BALANCE(); } // solhint-disable-next-line (bool _success_,) = payable(msg.sender).call{value: _balance_}(""); if (!_success_) { revert ETHER_TRANSFER_FAIL(msg.sender, _balance_); } } // ******************* // * IERC721Metadata * // ******************* /// @notice Updates the baseUri for the tokens. /// /// @param newBaseUri_ the new baseUri for the tokens /// /// Requirements: /// /// - Caller must be the contract owner. function setBaseUri(string memory newBaseUri_) public onlyOwner { _setBaseUri(newBaseUri_); } // ******************* // ************ // * IERC2981 * // ************ /// @dev Sets the royalty rate to `newRoyaltyRate_` and the royalty recipient to `newRoyaltyRecipient_`. /// /// @param newRoyaltyRecipient_ the address that will receive royalty payments /// @param newRoyaltyRate_ the percentage of the sale price that will be taken off as royalties, /// expressed in Basis Points (100 BP = 1%) /// /// Requirements: /// /// - Caller must be the contract owner. /// - `newRoyaltyRate_` cannot be higher than {ROYALTY_BASE}; function setRoyaltyInfo(address newRoyaltyRecipient_, uint96 newRoyaltyRate_) public onlyOwner { _setRoyaltyInfo(newRoyaltyRecipient_, newRoyaltyRate_); } // ************ // ************************************** // ************************************** // ***** VIEW ***** // ************************************** // *********** // * IERC721 * // *********** /// @dev Returns the number of tokens in `tokenOwner_`'s account. /// /// @param tokenOwner_ address that owns tokens /// /// @return ownerBalance the nomber of tokens owned by `tokenOwner_` /// /// Requirements: /// /// - `tokenOwner_` must not be the zero address function balanceOf(address tokenOwner_) public view virtual override returns (uint256 ownerBalance) { if (tokenOwner_ == address(0)) { revert IERC721_INVALID_TOKEN_OWNER(); } uint256 _index_; address _currentTokenOwner_; uint256 _supplyMinted_ = _nextId - 1; while (_index_ < _supplyMinted_) { if (_exists(_index_)) { _currentTokenOwner_ = _ownerOf(_index_); if (_currentTokenOwner_ == address(0)) { _currentTokenOwner_ = underlyingAsset.ownerOf(_index_); } if (_currentTokenOwner_ == tokenOwner_) { unchecked { ++ownerBalance; } } } unchecked { ++_index_; } } } /// @dev Returns the address that has been specifically allowed to manage `tokenId_` on behalf of its owner. /// /// @param tokenId_ the NFT that has been approved /// /// @return approved the address allowed to manage `tokenId_` /// /// Requirements: /// /// - `tokenId_` must exist. /// /// Note: See {Approve} function getApproved(uint256 tokenId_) public view virtual override exists(tokenId_) returns (address approved) { return _approvals[tokenId_]; } /// @dev Returns whether `operator_` is allowed to manage tokens on behalf of `tokenOwner_`. /// /// @param tokenOwner_ address that owns tokens /// @param operator_ address that tries to manage tokens /// /// @return isApproved whether `operator_` is allowed to handle `tokenOwner`'s tokens /// /// Note: See {setApprovalForAll} function isApprovedForAll( address tokenOwner_, address operator_ ) public view virtual override returns (bool isApproved) { return _operatorApprovals[tokenOwner_][operator_]; } /// @dev Returns the owner of the token number `tokenId_`. /// /// @param tokenId_ the NFT to verify ownership of /// /// @return tokenOwner the owner of token number `tokenId_` /// /// Requirements: /// /// - `tokenId_` must exist. function ownerOf(uint256 tokenId_) public view virtual override exists(tokenId_) returns (address tokenOwner) { tokenOwner = _ownerOf(tokenId_); if (tokenOwner == address(0)) { tokenOwner = underlyingAsset.ownerOf(tokenId_); } } // *********** // ********************* // * IERC721Enumerable * // ********************* /// @dev Enumerate valid NFTs /// /// @param index_ the index requested /// /// @return tokenId the identifier of the token at the specified index /// /// Requirements: /// /// - `index_` must be less than {totalSupply()} function tokenByIndex(uint256 index_) public view virtual override returns (uint256) { if (index_ >= _nextId) { revert IERC721Enumerable_INDEX_OUT_OF_BOUNDS(index_); } return index_; } /// @dev Enumerate NFTs assigned to an owner /// /// @param tokenOwner_ the address requested /// @param index_ the index requested /// /// @return tokenId the identifier of the token at the specified index /// /// Requirements: /// /// - `index_` must be less than {balanceOf(tokenOwner_)} /// - `tokenOwner_` must not be the zero address function tokenOfOwnerByIndex(address tokenOwner_, uint256 index_) public view virtual override returns (uint256) { if (tokenOwner_ == address(0)) { revert IERC721_INVALID_TOKEN_OWNER(); } address _currentTokenOwner_; uint256 _index_; uint256 _ownerBalance_; uint256 _supplyMinted_ = _nextId - 1; while (_index_ < _supplyMinted_) { if (_exists(_index_)) { _currentTokenOwner_ = _ownerOf(_index_); if (_currentTokenOwner_ == address(0)) { _currentTokenOwner_ = underlyingAsset.ownerOf(_index_); } if (_currentTokenOwner_ == tokenOwner_) { if (index_ == _ownerBalance_) { return _index_; } unchecked { ++_ownerBalance_; } } } unchecked { ++_index_; } } revert IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS(index_); } /// @notice Count NFTs tracked by this contract /// /// @return supply the number of NFTs in existence function totalSupply() public view virtual override returns (uint256 supply) { uint256 _supplyMinted_ = _nextId - 1; uint256 _index_ = _supplyMinted_; supply = _supplyMinted_; while (_index_ > 0) { if (!_exists(_index_)) { unchecked { --supply; } } unchecked { --_index_; } } } // ********************* // ******************* // * IERC721Metadata * // ******************* /// @dev A descriptive name for a collection of NFTs in this contract /// /// @return tokenName The descriptive name of the NFTs function name() public view virtual override returns (string memory tokenName) { return _name; } /// @dev An abbreviated name for NFTs in this contract /// /// @return tokenSymbol The abbreviated name of the NFTs function symbol() public view virtual override returns (string memory tokenSymbol) { return _symbol; } /// @dev A distinct Uniform Resource Identifier (URI) for a given asset. /// /// @param tokenId_ the NFT that has been approved /// /// @return uri the URI of the token /// /// Requirements: /// /// - `tokenId_` must exist. function tokenURI(uint256 tokenId_) public view virtual override exists(tokenId_) returns (string memory uri) { return bytes(_baseUri).length > 0 ? string(abi.encodePacked(_baseUri, _toString(tokenId_))) : _toString(tokenId_); } // ******************* // *********** // * IERC165 * // *********** /// @dev Query if a contract implements an interface. /// @dev see https://eips.ethereum.org/EIPS/eip-165 /// /// @param interfaceId_ the interface identifier, as specified in ERC-165 /// /// @return bool true if the contract implements the specified interface, false otherwise /// /// Requirements: /// /// - This function must use less than 30,000 gas. function supportsInterface(bytes4 interfaceId_) public pure override returns (bool) { return interfaceId_ == type(IERC721).interfaceId || interfaceId_ == type(IERC721Enumerable).interfaceId || interfaceId_ == type(IERC721Metadata).interfaceId || interfaceId_ == type(IERC173).interfaceId || interfaceId_ == type(IERC165).interfaceId || interfaceId_ == type(IERC2981).interfaceId; } // *********** // ************************************** // ************************************** // ***** INTERNAL ***** // ************************************** // *********** // * IERC721 * // *********** /// @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 owning the token being transferred /// @param to_ address the token is being transferred to /// @param tokenId_ identifier of the NFT being referenced /// @param data_ optional data to send along with the call /// /// @return isValidReceiver whether the call correctly returned the expected value function _checkOnERC721Received( address from_, address to_, uint256 tokenId_, bytes memory data_ ) internal virtual returns (bool isValidReceiver) { // 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. // // IMPORTANT // It is unsafe to assume that an address not flagged by this method // is an externally-owned account (EOA) and not a contract. // // Among others, the following types of addresses will not be flagged: // // - 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 uint256 _size_; assembly { _size_ := extcodesize(to_) } // If address is a contract, check that it is aware of how to handle ERC721 tokens if (_size_ > 0) { try IERC721Receiver(to_).onERC721Received(msg.sender, from_, tokenId_, data_) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert IERC721_INVALID_RECEIVER(to_); } else { assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /// @dev Internal function returning whether a token exists. /// A token exists if it has been minted and is not owned by the zero address. /// /// @param tokenId_ identifier of the NFT being referenced /// /// @return tokenExist whether the token exists function _exists(uint256 tokenId_) internal view virtual returns (bool tokenExist) { return !BitMaps.get(_burned, tokenId_) && tokenId_ < _nextId; } /// @dev Internal function returning whether `operator_` is allowed to handle `tokenId_` /// /// Note: To avoid multiple checks for the same data, it is assumed /// that existence of `tokenId_` has been verified prior via {_exists} /// If it hasn't been verified, this function might panic /// /// @param operator_ address that tries to handle the token /// @param tokenId_ identifier of the NFT being referenced /// /// @return isApproved whether `operator_` is allowed to manage the token function _isApprovedOrOwner( address tokenOwner_, address operator_, uint256 tokenId_ ) internal view virtual returns (bool isApproved) { return operator_ == tokenOwner_ || operator_ == getApproved(tokenId_) || _operatorApprovals[tokenOwner_][operator_]; } /// @dev Returns the owner of the token number `tokenId_`. /// /// @param tokenId_ the NFT to verify ownership of /// /// @return tokenOwner the owner of token number `tokenId_` /// /// Requirements: /// /// - `tokenId_` must exist. function _ownerOf(uint256 tokenId_) internal view virtual returns (address tokenOwner) { tokenOwner = _owners[tokenId_]; } /// @dev Transfers `tokenId_` from `fromAddress_` to `toAddress_`. /// /// Emits a {Transfer} event. /// /// @param fromAddress_ the current owner of the NFT /// @param toAddress_ the new owner /// @param tokenId_ identifier of the NFT being referenced function _transfer(address fromAddress_, address toAddress_, uint256 tokenId_) internal virtual { _approvals[tokenId_] = address(0); _owners[tokenId_] = toAddress_; emit Transfer(fromAddress_, toAddress_, tokenId_); } // *********** // ******************* // * IERC721Metadata * // ******************* /// @notice Updates the baseUri for the tokens. /// /// @param newBaseUri_ the new baseUri for the tokens /// /// Requirements: /// /// - Caller must be the contract owner. function _setBaseUri(string memory newBaseUri_) internal virtual { _baseUri = newBaseUri_; } /// @dev Converts a `uint256` to its ASCII `string` decimal representation. /// /// @param value_ the value to convert to string. /// /// @return str the string representation of `value_` function _toString(uint256 value_) internal pure virtual returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0. let m := add(mload(0x40), 0xa0) // Update the free memory pointer to allocate. mstore(0x40, m) // Assign the `str` to the end. str := sub(m, 0x20) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value_ } 1 {} { // solhint-disable-line str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } // ******************* // ************************************** }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ETHER_NO_BALANCE","type":"error"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHER_TRANSFER_FAIL","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"IERC173_NOT_OWNER","type":"error"},{"inputs":[],"name":"IERC2981_INVALID_ROYALTIES","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"IERC721Enumerable_INDEX_OUT_OF_BOUNDS","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"IERC721_CALLER_NOT_APPROVED","type":"error"},{"inputs":[],"name":"IERC721_INVALID_APPROVAL","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"IERC721_INVALID_RECEIVER","type":"error"},{"inputs":[],"name":"IERC721_INVALID_TOKEN_OWNER","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"IERC721_NONEXISTANT_TOKEN","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"ROYALTY_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"ownerBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"approved","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"fromTokenId_","type":"uint256"},{"internalType":"uint256","name":"toTokenId_","type":"uint256"}],"name":"indexTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin_","type":"address"},{"internalType":"address","name":"asset_","type":"address"},{"internalType":"address","name":"royaltyRecipient_","type":"address"},{"internalType":"uint96","name":"royaltyRate_","type":"uint96"},{"internalType":"uint256","name":"supply_","type":"uint256"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"baseUri_","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"},{"internalType":"address","name":"operator_","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"isApproved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"tokenName","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"contractOwner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"tokenOwner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"uint256","name":"salePrice_","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator_","type":"address"},{"internalType":"bool","name":"approved_","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newBaseUri_","type":"string"}],"name":"setBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRoyaltyRecipient_","type":"address"},{"internalType":"uint96","name":"newRoyaltyRate_","type":"uint96"}],"name":"setRoyaltyInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId_","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"tokenSymbol","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":"tokenOwner_","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":"uri","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"supply","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner_","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"underlyingAsset","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.