--- a/pallets/nonfungible/src/erc.rs +++ b/pallets/nonfungible/src/erc.rs @@ -14,6 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . +//! # Nonfungible Pallet EVM API +//! +//! Provides ERC-721 standart support implementation and EVM API for unique extensions for Nonfungible Pallet. +//! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods. + extern crate alloc; use core::{ char::{REPLACEMENT_CHARACTER, decode_utf16}, @@ -40,8 +45,16 @@ SelfWeightOf, weights::WeightInfo, TokenProperties, }; +/// @title A contract that allows to set and delete token properties and change token property permissions. +/// #[solidity_interface(name = "TokenProperties")] impl NonfungibleHandle { + /// @notice Set permissions for token property. + /// @dev Throws error if `msg.sender` is not admin or owner of the collection. + /// @param key Property key. + /// @param is_mutable Permission to mutate property. + /// @param collection_admin Permission to mutate property by collection admin if property is mutable. + /// @param token_owner Permission to mutate property by token owner if property is mutable. fn set_token_property_permission( &mut self, caller: caller, @@ -68,6 +81,11 @@ .map_err(dispatch_to_evm::) } + /// @notice Set token property value. + /// @dev Throws error if `msg.sender` has no permission to edit the property. + /// @param tokenId ID of the token. + /// @param key Property key. + /// @param value Property value. fn set_property( &mut self, caller: caller, @@ -96,6 +114,10 @@ .map_err(dispatch_to_evm::) } + /// @notice Delete token property value. + /// @dev Throws error if `msg.sender` has no permission to edit the property. + /// @param tokenId ID of the token. + /// @param key Property key. fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; @@ -111,7 +133,10 @@ .map_err(dispatch_to_evm::) } - /// Throws error if key not found + /// @notice Get token property value. + /// @dev Throws error if key not found + /// @param tokenId ID of the token. + /// @param key Property key. fn property(&self, token_id: uint256, key: string) -> Result { let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?; let key = >::from(key) @@ -127,6 +152,11 @@ #[derive(ToLog)] pub enum ERC721Events { + /// @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. Transfer { #[indexed] from: address, @@ -135,6 +165,10 @@ #[indexed] token_id: uint256, }, + /// @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. Approval { #[indexed] owner: address, @@ -143,6 +177,8 @@ #[indexed] token_id: uint256, }, + /// @dev This emits when an operator is enabled or disabled for an owner. + /// The operator can manage all NFTs of the owner. #[allow(dead_code)] ApprovalForAll { #[indexed] @@ -159,19 +195,27 @@ MintingFinished {}, } +/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension +/// @dev See https://eips.ethereum.org/EIPS/eip-721 #[solidity_interface(name = "ERC721Metadata")] impl NonfungibleHandle { + /// @notice A descriptive name for a collection of NFTs in this contract fn name(&self) -> Result { Ok(decode_utf16(self.name.iter().copied()) .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) .collect::()) } + /// @notice An abbreviated name for NFTs in this contract fn symbol(&self) -> Result { Ok(string::from_utf8_lossy(&self.token_prefix).into()) } - /// Returns token's const_metadata + /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. + /// @dev Throws if `tokenId` is not a valid NFT. URIs are defined in RFC + /// 3986. The URI may point to a JSON file that conforms to the "ERC721 + /// Metadata JSON Schema". + /// @return token's const_metadata #[solidity(rename_selector = "tokenURI")] fn token_uri(&self, token_id: uint256) -> Result { let key = token_uri_key(); @@ -192,32 +236,53 @@ } } +/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension +/// @dev See https://eips.ethereum.org/EIPS/eip-721 #[solidity_interface(name = "ERC721Enumerable")] impl NonfungibleHandle { + /// @notice Enumerate valid NFTs + /// @param index A counter less than `totalSupply()` + /// @return The token identifier for the `index`th NFT, + /// (sort order not specified) fn token_by_index(&self, index: uint256) -> Result { Ok(index) } - /// Not implemented + /// @dev Not implemented fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result { // TODO: Not implemetable Err("not implemented".into()) } + /// @notice Count NFTs tracked by this contract + /// @return A count of valid NFTs tracked by this contract, where each one of + /// them has an assigned and queryable owner not equal to the zero address fn total_supply(&self) -> Result { self.consume_store_reads(1)?; Ok(>::total_supply(self).into()) } } +/// @title ERC-721 Non-Fungible Token Standard +/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md #[solidity_interface(name = "ERC721", events(ERC721Events))] impl NonfungibleHandle { + /// @notice Count all NFTs assigned to an owner + /// @dev NFTs assigned to the zero address are considered invalid, and this + /// function throws for queries about the zero address. + /// @param owner An address for whom to query the balance + /// @return The number of NFTs owned by `owner`, possibly zero fn balance_of(&self, owner: address) -> Result { self.consume_store_reads(1)?; let owner = T::CrossAccountId::from_eth(owner); let balance = >::get((self.id, owner)); Ok(balance.into()) } + /// @notice Find the owner of an NFT + /// @dev NFTs assigned to zero address are considered invalid, and queries + /// about them do throw. + /// @param tokenId The identifier for an NFT + /// @return The address of the owner of the NFT fn owner_of(&self, token_id: uint256) -> Result
{ self.consume_store_reads(1)?; let token: TokenId = token_id.try_into()?; @@ -226,7 +291,7 @@ .owner .as_eth()) } - /// Not implemented + /// @dev Not implemented fn safe_transfer_from_with_data( &mut self, _from: address, @@ -238,7 +303,7 @@ // TODO: Not implemetable Err("not implemented".into()) } - /// Not implemented + /// @dev Not implemented fn safe_transfer_from( &mut self, _from: address, @@ -250,6 +315,16 @@ Err("not implemented".into()) } + /// @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 or an authorized + /// operator for this NFT. Throws if `from` is not the current owner. Throws + /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT. + /// @param from The current owner of the NFT + /// @param to The new owner + /// @param tokenId The NFT to transfer + /// @param _value Not used for an NFT #[weight(>::transfer_from())] fn transfer_from( &mut self, @@ -272,6 +347,12 @@ Ok(()) } + /// @notice Set or reaffirm the approved address for an NFT + /// @dev The zero address indicates there is no approved address. + /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized + /// operator of the current owner. + /// @param approved The new approved NFT controller + /// @param tokenId The NFT to approve #[weight(>::approve())] fn approve( &mut self, @@ -289,7 +370,7 @@ Ok(()) } - /// Not implemented + /// @dev Not implemented fn set_approval_for_all( &mut self, _caller: caller, @@ -300,21 +381,26 @@ Err("not implemented".into()) } - /// Not implemented + /// @dev Not implemented fn get_approved(&self, _token_id: uint256) -> Result
{ // TODO: Not implemetable Err("not implemented".into()) } - /// Not implemented + /// @dev Not implemented fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result
{ // TODO: Not implemetable Err("not implemented".into()) } } +/// @title ERC721 Token that can be irreversibly burned (destroyed). #[solidity_interface(name = "ERC721Burnable")] impl NonfungibleHandle { + /// @notice Burns a specific ERC721 token. + /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized + /// operator of the current owner. + /// @param tokenId The NFT to approve #[weight(>::burn_item())] fn burn(&mut self, caller: caller, token_id: uint256) -> Result { let caller = T::CrossAccountId::from_eth(caller); @@ -325,14 +411,18 @@ } } +/// @title ERC721 minting logic. #[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))] impl NonfungibleHandle { fn minting_finished(&self) -> Result { Ok(false) } - /// `token_id` should be obtained with `next_token_id` method, - /// unlike standard, you can't specify it manually + /// @notice Function to mint token. + /// @dev `tokenId` should be obtained with `nextTokenId` method, + /// unlike standard, you can't specify it manually + /// @param to The new owner + /// @param tokenId ID of the minted NFT #[weight(>::create_item())] fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result { let caller = T::CrossAccountId::from_eth(caller); @@ -364,8 +454,12 @@ Ok(true) } - /// `token_id` should be obtained with `next_token_id` method, - /// unlike standard, you can't specify it manually + /// @notice Function to mint token with the given tokenUri. + /// @dev `tokenId` should be obtained with `nextTokenId` method, + /// unlike standard, you can't specify it manually + /// @param to The new owner + /// @param tokenId ID of the minted NFT + /// @param tokenUri Token URI that would be stored in the NFT properties #[solidity(rename_selector = "mintWithTokenURI")] #[weight(>::create_item())] fn mint_with_token_uri( @@ -420,7 +514,7 @@ Ok(true) } - /// Not implemented + /// @dev Not implemented fn finish_minting(&mut self, _caller: caller) -> Result { Err("not implementable".into()) } @@ -449,8 +543,15 @@ false } +/// @title Unique extensions for ERC721. #[solidity_interface(name = "ERC721UniqueExtensions")] impl NonfungibleHandle { + /// @notice Transfer ownership of an NFT + /// @dev Throws unless `msg.sender` is the current owner. Throws if `to` + /// is the zero address. Throws if `tokenId` is not a valid NFT. + /// @param to The new owner + /// @param tokenId The NFT to transfer + /// @param _value Not used for an NFT #[weight(>::transfer())] fn transfer( &mut self, @@ -470,6 +571,13 @@ Ok(()) } + /// @notice Burns a specific ERC721 token. + /// @dev Throws unless `msg.sender` is the current owner or an authorized + /// operator for this NFT. Throws if `from` is not the current owner. Throws + /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT. + /// @param from The current owner of the NFT + /// @param tokenId The NFT to transfer + /// @param _value Not used for an NFT #[weight(>::burn_from())] fn burn_from( &mut self, @@ -490,6 +598,7 @@ Ok(()) } + /// @notice Returns next free NFT ID. fn next_token_id(&self) -> Result { self.consume_store_reads(1)?; Ok(>::get(self.id) @@ -498,6 +607,11 @@ .into()) } + /// @notice Function to mint multiple tokens. + /// @dev `tokenIds` should be an array of consecutive numbers and first number + /// should be obtained with `nextTokenId` method + /// @param to The new owner + /// @param tokenIds IDs of the minted NFTs #[weight(>::create_multiple_items(token_ids.len() as u32))] fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec) -> Result { let caller = T::CrossAccountId::from_eth(caller); @@ -529,6 +643,11 @@ Ok(true) } + /// @notice Function to mint multiple tokens with the given tokenUris. + /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive + /// numbers and first number should be obtained with `nextTokenId` method + /// @param to The new owner + /// @param tokens array of pairs of token ID and token URI for minted tokens #[solidity(rename_selector = "mintBulkWithTokenURI")] #[weight(>::create_multiple_items(tokens.len() as u32))] fn mint_bulk_with_token_uri( --- a/pallets/nonfungible/src/stubs/UniqueNFT.sol +++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol @@ -53,6 +53,13 @@ // Selector: 41369377 contract TokenProperties is Dummy, ERC165 { + // @notice Set permissions for token property. + // @dev Throws error if `msg.sender` is not admin or owner of the collection. + // @param key Property key. + // @param is_mutable Permission to mutate property. + // @param collection_admin Permission to mutate property by collection admin if property is mutable. + // @param token_owner Permission to mutate property by token owner if property is mutable. + // // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa function setTokenPropertyPermission( string memory key, @@ -68,6 +75,12 @@ dummy = 0; } + // @notice Set token property value. + // @dev Throws error if `msg.sender` has no permission to edit the property. + // @param token_id ID of the token. + // @param key Property key. + // @param value Property value. + // // Selector: setProperty(uint256,string,bytes) 1752d67b function setProperty( uint256 tokenId, @@ -81,6 +94,11 @@ dummy = 0; } + // @notice Delete token property value. + // @dev Throws error if `msg.sender` has no permission to edit the property. + // @param token_id ID of the token. + // @param key Property key. + // // Selector: deleteProperty(uint256,string) 066111d1 function deleteProperty(uint256 tokenId, string memory key) public { require(false, stub_error); @@ -89,7 +107,10 @@ dummy = 0; } - // Throws error if key not found + // @notice Get token property value. + // @dev Throws error if key not found + // @param token_id ID of the token. + // @param key Property key. // // Selector: property(uint256,string) 7228c327 function property(uint256 tokenId, string memory key) @@ -107,6 +128,11 @@ // Selector: 42966c68 contract ERC721Burnable is Dummy, ERC165 { + // @notice Burns a specific ERC721 token. + // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized + // operator of the current owner. + // @param tokenId The NFT to approve + // // Selector: burn(uint256) 42966c68 function burn(uint256 tokenId) public { require(false, stub_error); @@ -117,6 +143,12 @@ // Selector: 58800161 contract ERC721 is Dummy, ERC165, ERC721Events { + // @notice Count all NFTs assigned to an owner + // @dev NFTs assigned to the zero address are considered invalid, and this + // function throws for queries about the zero address. + // @param _owner An address for whom to query the balance + // @return The number of NFTs owned by `_owner`, possibly zero + // // Selector: balanceOf(address) 70a08231 function balanceOf(address owner) public view returns (uint256) { require(false, stub_error); @@ -125,6 +157,12 @@ return 0; } + // @notice Find the owner of an NFT + // @dev NFTs assigned to zero address are considered invalid, and queries + // about them do throw. + // @param _tokenId The identifier for an NFT + // @return The address of the owner of the NFT + // // Selector: ownerOf(uint256) 6352211e function ownerOf(uint256 tokenId) public view returns (address) { require(false, stub_error); @@ -133,7 +171,7 @@ return 0x0000000000000000000000000000000000000000; } - // Not implemented + // @dev Not implemented // // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672 function safeTransferFromWithData( @@ -150,7 +188,7 @@ dummy = 0; } - // Not implemented + // @dev Not implemented // // Selector: safeTransferFrom(address,address,uint256) 42842e0e function safeTransferFrom( @@ -165,6 +203,17 @@ dummy = 0; } + // @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 or an authorized + // operator for this NFT. Throws if `from` is not the current owner. Throws + // if `to` is the zero address. Throws if `tokenId` is not a valid NFT. + // @param from The current owner of the NFT + // @param to The new owner + // @param tokenId The NFT to transfer + // @param _value Not used for an NFT + // // Selector: transferFrom(address,address,uint256) 23b872dd function transferFrom( address from, @@ -178,6 +227,13 @@ dummy = 0; } + // @notice Set or reaffirm the approved address for an NFT + // @dev The zero address indicates there is no approved address. + // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized + // operator of the current owner. + // @param approved The new approved NFT controller + // @param tokenId The NFT to approve + // // Selector: approve(address,uint256) 095ea7b3 function approve(address approved, uint256 tokenId) public { require(false, stub_error); @@ -186,7 +242,7 @@ dummy = 0; } - // Not implemented + // @dev Not implemented // // Selector: setApprovalForAll(address,bool) a22cb465 function setApprovalForAll(address operator, bool approved) public { @@ -196,7 +252,7 @@ dummy = 0; } - // Not implemented + // @dev Not implemented // // Selector: getApproved(uint256) 081812fc function getApproved(uint256 tokenId) public view returns (address) { @@ -206,7 +262,7 @@ return 0x0000000000000000000000000000000000000000; } - // Not implemented + // @dev Not implemented // // Selector: isApprovedForAll(address,address) e985e9c5 function isApprovedForAll(address owner, address operator) @@ -224,6 +280,8 @@ // Selector: 5b5e139f contract ERC721Metadata is Dummy, ERC165 { + // @notice A descriptive name for a collection of NFTs in this contract + // // Selector: name() 06fdde03 function name() public view returns (string memory) { require(false, stub_error); @@ -231,6 +289,8 @@ return ""; } + // @notice An abbreviated name for NFTs in this contract + // // Selector: symbol() 95d89b41 function symbol() public view returns (string memory) { require(false, stub_error); @@ -238,7 +298,11 @@ return ""; } - // Returns token's const_metadata + // @notice A distinct Uniform Resource Identifier (URI) for a given asset. + // @dev Throws if `tokenId` is not a valid NFT. URIs are defined in RFC + // 3986. The URI may point to a JSON file that conforms to the "ERC721 + // Metadata JSON Schema". + // @return token's const_metadata // // Selector: tokenURI(uint256) c87b56dd function tokenURI(uint256 tokenId) public view returns (string memory) { @@ -258,8 +322,11 @@ return false; } - // `token_id` should be obtained with `next_token_id` method, - // unlike standard, you can't specify it manually + // @notice Function to mint token. + // @dev `tokenId` should be obtained with `nextTokenId` method, + // unlike standard, you can't specify it manually + // @param to The new owner + // @param tokenId ID of the minted NFT // // Selector: mint(address,uint256) 40c10f19 function mint(address to, uint256 tokenId) public returns (bool) { @@ -270,8 +337,12 @@ return false; } - // `token_id` should be obtained with `next_token_id` method, - // unlike standard, you can't specify it manually + // @notice Function to mint token with the given tokenUri. + // @dev `tokenId` should be obtained with `nextTokenId` method, + // unlike standard, you can't specify it manually + // @param to The new owner + // @param tokenId ID of the minted NFT + // @param tokenUri Token URI that would be stored in the NFT properties // // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f function mintWithTokenURI( @@ -287,7 +358,7 @@ return false; } - // Not implemented + // @dev Not implemented // // Selector: finishMinting() 7d64bcb4 function finishMinting() public returns (bool) { @@ -299,6 +370,12 @@ // Selector: 780e9d63 contract ERC721Enumerable is Dummy, ERC165 { + // @notice Enumerate valid NFTs + // @dev Throws if `index` >= `totalSupply()`. + // @param index A counter less than `totalSupply()` + // @return The token identifier for the `index`th NFT, + // (sort order not specified) + // // Selector: tokenByIndex(uint256) 4f6ccce7 function tokenByIndex(uint256 index) public view returns (uint256) { require(false, stub_error); @@ -307,7 +384,7 @@ return 0; } - // Not implemented + // @dev Not implemented // // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59 function tokenOfOwnerByIndex(address owner, uint256 index) @@ -322,6 +399,10 @@ return 0; } + // @notice Count NFTs tracked by this contract + // @return A count of valid NFTs tracked by this contract, where each one of + // them has an assigned and queryable owner not equal to the zero address + // // Selector: totalSupply() 18160ddd function totalSupply() public view returns (uint256) { require(false, stub_error); @@ -475,6 +556,15 @@ // Selector: d74d154f contract ERC721UniqueExtensions is Dummy, ERC165 { + // @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. Throws if `to` + // is the zero address. Throws if `tokenId` is not a valid NFT. + // @param to The new owner + // @param tokenId The NFT to transfer + // @param _value Not used for an NFT + // // Selector: transfer(address,uint256) a9059cbb function transfer(address to, uint256 tokenId) public { require(false, stub_error); @@ -483,6 +573,14 @@ dummy = 0; } + // @notice Burns a specific ERC721 token. + // @dev Throws unless `msg.sender` is the current owner or an authorized + // operator for this NFT. Throws if `from` is not the current owner. Throws + // if `to` is the zero address. Throws if `tokenId` is not a valid NFT. + // @param from The current owner of the NFT + // @param tokenId The NFT to transfer + // @param _value Not used for an NFT + // // Selector: burnFrom(address,uint256) 79cc6790 function burnFrom(address from, uint256 tokenId) public { require(false, stub_error); @@ -491,6 +589,8 @@ dummy = 0; } + // @notice Returns next free NFT ID. + // // Selector: nextTokenId() 75794a3c function nextTokenId() public view returns (uint256) { require(false, stub_error); @@ -498,6 +598,12 @@ return 0; } + // @notice Function to mint multiple tokens. + // @dev `tokenIds` should be an array of consecutive numbers and first number + // should be obtained with `nextTokenId` method + // @param to The new owner + // @param tokenIds IDs of the minted NFTs + // // Selector: mintBulk(address,uint256[]) 44a9945e function mintBulk(address to, uint256[] memory tokenIds) public @@ -510,6 +616,12 @@ return false; } + // @notice Function to mint multiple tokens with the given tokenUris. + // @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive + // numbers and first number should be obtained with `nextTokenId` method + // @param to The new owner + // @param tokens array of pairs of token ID and token URI for minted tokens + // // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens) public --- a/tests/src/eth/api/UniqueNFT.sol +++ b/tests/src/eth/api/UniqueNFT.sol @@ -44,6 +44,13 @@ // Selector: 41369377 interface TokenProperties is Dummy, ERC165 { + // @notice Set permissions for token property. + // @dev Throws error if `msg.sender` is not admin or owner of the collection. + // @param key Property key. + // @param is_mutable Permission to mutate property. + // @param collection_admin Permission to mutate property by collection admin if property is mutable. + // @param token_owner Permission to mutate property by token owner if property is mutable. + // // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa function setTokenPropertyPermission( string memory key, @@ -52,6 +59,12 @@ bool tokenOwner ) external; + // @notice Set token property value. + // @dev Throws error if `msg.sender` has no permission to edit the property. + // @param token_id ID of the token. + // @param key Property key. + // @param value Property value. + // // Selector: setProperty(uint256,string,bytes) 1752d67b function setProperty( uint256 tokenId, @@ -59,10 +72,18 @@ bytes memory value ) external; + // @notice Delete token property value. + // @dev Throws error if `msg.sender` has no permission to edit the property. + // @param token_id ID of the token. + // @param key Property key. + // // Selector: deleteProperty(uint256,string) 066111d1 function deleteProperty(uint256 tokenId, string memory key) external; - // Throws error if key not found + // @notice Get token property value. + // @dev Throws error if key not found + // @param token_id ID of the token. + // @param key Property key. // // Selector: property(uint256,string) 7228c327 function property(uint256 tokenId, string memory key) @@ -73,19 +94,36 @@ // Selector: 42966c68 interface ERC721Burnable is Dummy, ERC165 { + // @notice Burns a specific ERC721 token. + // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized + // operator of the current owner. + // @param tokenId The NFT to approve + // // Selector: burn(uint256) 42966c68 function burn(uint256 tokenId) external; } // Selector: 58800161 interface ERC721 is Dummy, ERC165, ERC721Events { + // @notice Count all NFTs assigned to an owner + // @dev NFTs assigned to the zero address are considered invalid, and this + // function throws for queries about the zero address. + // @param _owner An address for whom to query the balance + // @return The number of NFTs owned by `_owner`, possibly zero + // // Selector: balanceOf(address) 70a08231 function balanceOf(address owner) external view returns (uint256); + // @notice Find the owner of an NFT + // @dev NFTs assigned to zero address are considered invalid, and queries + // about them do throw. + // @param _tokenId The identifier for an NFT + // @return The address of the owner of the NFT + // // Selector: ownerOf(uint256) 6352211e function ownerOf(uint256 tokenId) external view returns (address); - // Not implemented + // @dev Not implemented // // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672 function safeTransferFromWithData( @@ -95,7 +133,7 @@ bytes memory data ) external; - // Not implemented + // @dev Not implemented // // Selector: safeTransferFrom(address,address,uint256) 42842e0e function safeTransferFrom( @@ -104,6 +142,17 @@ uint256 tokenId ) 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 or an authorized + // operator for this NFT. Throws if `from` is not the current owner. Throws + // if `to` is the zero address. Throws if `tokenId` is not a valid NFT. + // @param from The current owner of the NFT + // @param to The new owner + // @param tokenId The NFT to transfer + // @param _value Not used for an NFT + // // Selector: transferFrom(address,address,uint256) 23b872dd function transferFrom( address from, @@ -111,20 +160,27 @@ uint256 tokenId ) external; + // @notice Set or reaffirm the approved address for an NFT + // @dev The zero address indicates there is no approved address. + // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized + // operator of the current owner. + // @param approved The new approved NFT controller + // @param tokenId The NFT to approve + // // Selector: approve(address,uint256) 095ea7b3 function approve(address approved, uint256 tokenId) external; - // Not implemented + // @dev Not implemented // // Selector: setApprovalForAll(address,bool) a22cb465 function setApprovalForAll(address operator, bool approved) external; - // Not implemented + // @dev Not implemented // // Selector: getApproved(uint256) 081812fc function getApproved(uint256 tokenId) external view returns (address); - // Not implemented + // @dev Not implemented // // Selector: isApprovedForAll(address,address) e985e9c5 function isApprovedForAll(address owner, address operator) @@ -135,13 +191,21 @@ // Selector: 5b5e139f interface ERC721Metadata is Dummy, ERC165 { + // @notice A descriptive name for a collection of NFTs in this contract + // // Selector: name() 06fdde03 function name() external view returns (string memory); + // @notice An abbreviated name for NFTs in this contract + // // Selector: symbol() 95d89b41 function symbol() external view returns (string memory); - // Returns token's const_metadata + // @notice A distinct Uniform Resource Identifier (URI) for a given asset. + // @dev Throws if `tokenId` is not a valid NFT. URIs are defined in RFC + // 3986. The URI may point to a JSON file that conforms to the "ERC721 + // Metadata JSON Schema". + // @return token's const_metadata // // Selector: tokenURI(uint256) c87b56dd function tokenURI(uint256 tokenId) external view returns (string memory); @@ -152,14 +216,21 @@ // Selector: mintingFinished() 05d2035b function mintingFinished() external view returns (bool); - // `token_id` should be obtained with `next_token_id` method, - // unlike standard, you can't specify it manually + // @notice Function to mint token. + // @dev `tokenId` should be obtained with `nextTokenId` method, + // unlike standard, you can't specify it manually + // @param to The new owner + // @param tokenId ID of the minted NFT // // Selector: mint(address,uint256) 40c10f19 function mint(address to, uint256 tokenId) external returns (bool); - // `token_id` should be obtained with `next_token_id` method, - // unlike standard, you can't specify it manually + // @notice Function to mint token with the given tokenUri. + // @dev `tokenId` should be obtained with `nextTokenId` method, + // unlike standard, you can't specify it manually + // @param to The new owner + // @param tokenId ID of the minted NFT + // @param tokenUri Token URI that would be stored in the NFT properties // // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f function mintWithTokenURI( @@ -168,7 +239,7 @@ string memory tokenUri ) external returns (bool); - // Not implemented + // @dev Not implemented // // Selector: finishMinting() 7d64bcb4 function finishMinting() external returns (bool); @@ -176,10 +247,16 @@ // Selector: 780e9d63 interface ERC721Enumerable is Dummy, ERC165 { + // @notice Enumerate valid NFTs + // @dev Throws if `index` >= `totalSupply()`. + // @param index A counter less than `totalSupply()` + // @return The token identifier for the `index`th NFT, + // (sort order not specified) + // // Selector: tokenByIndex(uint256) 4f6ccce7 function tokenByIndex(uint256 index) external view returns (uint256); - // Not implemented + // @dev Not implemented // // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59 function tokenOfOwnerByIndex(address owner, uint256 index) @@ -187,6 +264,10 @@ view returns (uint256); + // @notice Count NFTs tracked by this contract + // @return A count of valid NFTs tracked by this contract, where each one of + // them has an assigned and queryable owner not equal to the zero address + // // Selector: totalSupply() 18160ddd function totalSupply() external view returns (uint256); } @@ -257,20 +338,51 @@ // Selector: d74d154f interface ERC721UniqueExtensions is Dummy, ERC165 { + // @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. Throws if `to` + // is the zero address. Throws if `tokenId` is not a valid NFT. + // @param to The new owner + // @param tokenId The NFT to transfer + // @param _value Not used for an NFT + // // Selector: transfer(address,uint256) a9059cbb function transfer(address to, uint256 tokenId) external; + // @notice Burns a specific ERC721 token. + // @dev Throws unless `msg.sender` is the current owner or an authorized + // operator for this NFT. Throws if `from` is not the current owner. Throws + // if `to` is the zero address. Throws if `tokenId` is not a valid NFT. + // @param from The current owner of the NFT + // @param tokenId The NFT to transfer + // @param _value Not used for an NFT + // // Selector: burnFrom(address,uint256) 79cc6790 function burnFrom(address from, uint256 tokenId) external; + // @notice Returns next free NFT ID. + // // Selector: nextTokenId() 75794a3c function nextTokenId() external view returns (uint256); + // @notice Function to mint multiple tokens. + // @dev `tokenIds` should be an array of consecutive numbers and first number + // should be obtained with `nextTokenId` method + // @param to The new owner + // @param tokenIds IDs of the minted NFTs + // // Selector: mintBulk(address,uint256[]) 44a9945e function mintBulk(address to, uint256[] memory tokenIds) external returns (bool); + // @notice Function to mint multiple tokens with the given tokenUris. + // @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive + // numbers and first number should be obtained with `nextTokenId` method + // @param to The new owner + // @param tokens array of pairs of token ID and token URI for minted tokens + // // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens) external