difftreelog
doc(refungible-pallet): add documentation for ERC-721 implementation
in: master
1 file changed
pallets/refungible/src/erc.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! # Refungible Pallet EVM API for tokens18//!19//! Provides ERC-721 standart support implementation and EVM API for unique extensions for Refungible Pallet.20//! Method implementations are mostly doing parameter conversion and calling Refungible Pallet methods.162117extern crate alloc;22extern crate alloc;182345 TokenProperties, TokensMinted, weights::WeightInfo,50 TokenProperties, TokensMinted, weights::WeightInfo,46};51};475253/// @title A contract that allows to set and delete token properties and change token property permissions.48#[solidity_interface(name = "TokenProperties")]54#[solidity_interface(name = "TokenProperties")]49impl<T: Config> RefungibleHandle<T> {55impl<T: Config> RefungibleHandle<T> {56 /// @notice Set permissions for token property.57 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.58 /// @param key Property key.59 /// @param is_mutable Permission to mutate property.60 /// @param collection_admin Permission to mutate property by collection admin if property is mutable.61 /// @param token_owner Permission to mutate property by token owner if property is mutable.50 fn set_token_property_permission(62 fn set_token_property_permission(51 &mut self,63 &mut self,52 caller: caller,64 caller: caller,73 .map_err(dispatch_to_evm::<T>)85 .map_err(dispatch_to_evm::<T>)74 }86 }758788 /// @notice Set token property value.89 /// @dev Throws error if `msg.sender` has no permission to edit the property.90 /// @param tokenId ID of the token.91 /// @param key Property key.92 /// @param value Property value.76 fn set_property(93 fn set_property(77 &mut self,94 &mut self,78 caller: caller,95 caller: caller,101 .map_err(dispatch_to_evm::<T>)118 .map_err(dispatch_to_evm::<T>)102 }119 }103120121 /// @notice Delete token property value.122 /// @dev Throws error if `msg.sender` has no permission to edit the property.123 /// @param tokenId ID of the token.124 /// @param key Property key.104 fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> {125 fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> {105 let caller = T::CrossAccountId::from_eth(caller);126 let caller = T::CrossAccountId::from_eth(caller);106 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;127 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;116 .map_err(dispatch_to_evm::<T>)137 .map_err(dispatch_to_evm::<T>)117 }138 }118139140 /// @notice Get token property value.119 /// Throws error if key not found141 /// @dev Throws error if key not found142 /// @param tokenId ID of the token.143 /// @param key Property key.144 /// @return Property value bytes120 fn property(&self, token_id: uint256, key: string) -> Result<bytes> {145 fn property(&self, token_id: uint256, key: string) -> Result<bytes> {121 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;146 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;122 let key = <Vec<u8>>::from(key)147 let key = <Vec<u8>>::from(key)132157133#[derive(ToLog)]158#[derive(ToLog)]134pub enum ERC721Events {159pub enum ERC721Events {160 /// @dev This event emits when NFTs are created (`from` == 0) and destroyed161 /// (`to` == 0). Exception: during contract creation, any number of RFTs162 /// may be created and assigned without emitting Transfer.135 Transfer {163 Transfer {136 #[indexed]164 #[indexed]137 from: address,165 from: address,169197170#[solidity_interface(name = "ERC721Metadata")]198#[solidity_interface(name = "ERC721Metadata")]171impl<T: Config> RefungibleHandle<T> {199impl<T: Config> RefungibleHandle<T> {200 /// @notice A descriptive name for a collection of RFTs in this contract172 fn name(&self) -> Result<string> {201 fn name(&self) -> Result<string> {173 Ok(decode_utf16(self.name.iter().copied())202 Ok(decode_utf16(self.name.iter().copied())174 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))203 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))175 .collect::<string>())204 .collect::<string>())176 }205 }177206207 /// @notice An abbreviated name for RFTs in this contract178 fn symbol(&self) -> Result<string> {208 fn symbol(&self) -> Result<string> {179 Ok(string::from_utf8_lossy(&self.token_prefix).into())209 Ok(string::from_utf8_lossy(&self.token_prefix).into())180 }210 }224 }254 }225}255}226256257/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension258/// @dev See https://eips.ethereum.org/EIPS/eip-721227#[solidity_interface(name = "ERC721Enumerable")]259#[solidity_interface(name = "ERC721Enumerable")]228impl<T: Config> RefungibleHandle<T> {260impl<T: Config> RefungibleHandle<T> {261 /// @notice Enumerate valid RFTs262 /// @param index A counter less than `totalSupply()`263 /// @return The token identifier for the `index`th NFT,264 /// (sort order not specified)229 fn token_by_index(&self, index: uint256) -> Result<uint256> {265 fn token_by_index(&self, index: uint256) -> Result<uint256> {230 Ok(index)266 Ok(index)231 }267 }236 Err("not implemented".into())272 Err("not implemented".into())237 }273 }238274275 /// @notice Count RFTs tracked by this contract276 /// @return A count of valid RFTs tracked by this contract, where each one of277 /// them has an assigned and queryable owner not equal to the zero address239 fn total_supply(&self) -> Result<uint256> {278 fn total_supply(&self) -> Result<uint256> {240 self.consume_store_reads(1)?;279 self.consume_store_reads(1)?;241 Ok(<Pallet<T>>::total_supply(self).into())280 Ok(<Pallet<T>>::total_supply(self).into())242 }281 }243}282}244283284/// @title ERC-721 Non-Fungible Token Standard285/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md245#[solidity_interface(name = "ERC721", events(ERC721Events))]286#[solidity_interface(name = "ERC721", events(ERC721Events))]246impl<T: Config> RefungibleHandle<T> {287impl<T: Config> RefungibleHandle<T> {288 /// @notice Count all RFTs assigned to an owner289 /// @dev RFTs assigned to the zero address are considered invalid, and this290 /// function throws for queries about the zero address.291 /// @param owner An address for whom to query the balance292 /// @return The number of RFTs owned by `owner`, possibly zero247 fn balance_of(&self, owner: address) -> Result<uint256> {293 fn balance_of(&self, owner: address) -> Result<uint256> {248 self.consume_store_reads(1)?;294 self.consume_store_reads(1)?;249 let owner = T::CrossAccountId::from_eth(owner);295 let owner = T::CrossAccountId::from_eth(owner);332 }378 }333}379}334380381/// @title ERC721 Token that can be irreversibly burned (destroyed).335#[solidity_interface(name = "ERC721Burnable")]382#[solidity_interface(name = "ERC721Burnable")]336impl<T: Config> RefungibleHandle<T> {383impl<T: Config> RefungibleHandle<T> {337 /// @dev Not implemented384 /// @dev Not implemented340 }387 }341}388}342389390/// @title ERC721 minting logic.343#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]391#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]344impl<T: Config> RefungibleHandle<T> {392impl<T: Config> RefungibleHandle<T> {345 fn minting_finished(&self) -> Result<bool> {393 fn minting_finished(&self) -> Result<bool> {346 Ok(false)394 Ok(false)347 }395 }348396397 /// @notice Function to mint token.349 /// `token_id` should be obtained with `next_token_id` method,398 /// @dev `tokenId` should be obtained with `nextTokenId` method,350 /// unlike standard, you can't specify it manually399 /// unlike standard, you can't specify it manually400 /// @param to The new owner401 /// @param tokenId ID of the minted RFT351 #[weight(<SelfWeightOf<T>>::create_item())]402 #[weight(<SelfWeightOf<T>>::create_item())]352 fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {403 fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {353 let caller = T::CrossAccountId::from_eth(caller);404 let caller = T::CrossAccountId::from_eth(caller);386 Ok(true)437 Ok(true)387 }438 }388439440 /// @notice Function to mint token with the given tokenUri.389 /// `token_id` should be obtained with `next_token_id` method,441 /// @dev `tokenId` should be obtained with `nextTokenId` method,390 /// unlike standard, you can't specify it manually442 /// unlike standard, you can't specify it manually443 /// @param to The new owner444 /// @param tokenId ID of the minted RFT445 /// @param tokenUri Token URI that would be stored in the RFT properties391 #[solidity(rename_selector = "mintWithTokenURI")]446 #[solidity(rename_selector = "mintWithTokenURI")]392 #[weight(<SelfWeightOf<T>>::create_item())]447 #[weight(<SelfWeightOf<T>>::create_item())]393 fn mint_with_token_uri(448 fn mint_with_token_uri(497 Ok(a)552 Ok(a)498}553}499554555/// @title Unique extensions for ERC721.500#[solidity_interface(name = "ERC721UniqueExtensions")]556#[solidity_interface(name = "ERC721UniqueExtensions")]501impl<T: Config> RefungibleHandle<T> {557impl<T: Config> RefungibleHandle<T> {502 /// @notice Returns next free RFT ID.558 /// @notice Returns next free RFT ID.508 .into())564 .into())509 }565 }510566567 /// @notice Function to mint multiple tokens.568 /// @dev `tokenIds` should be an array of consecutive numbers and first number569 /// should be obtained with `nextTokenId` method570 /// @param to The new owner571 /// @param tokenIds IDs of the minted RFTs511 #[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]572 #[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]512 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {573 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {513 let caller = T::CrossAccountId::from_eth(caller);574 let caller = T::CrossAccountId::from_eth(caller);547 Ok(true)608 Ok(true)548 }609 }549610611 /// @notice Function to mint multiple tokens with the given tokenUris.612 /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive613 /// numbers and first number should be obtained with `nextTokenId` method614 /// @param to The new owner615 /// @param tokens array of pairs of token ID and token URI for minted tokens550 #[solidity(rename_selector = "mintBulkWithTokenURI")]616 #[solidity(rename_selector = "mintBulkWithTokenURI")]551 #[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]617 #[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]552 fn mint_bulk_with_token_uri(618 fn mint_bulk_with_token_uri(