git.delta.rocks / unique-network / refs/commits / 30c8dcd3e73a

difftreelog

doc(refungible-pallet): add documentation for ERC-721 implementation

Grigoriy Simonov2022-07-27parent: #62ad43e.patch.diff
in: master

1 file changed

modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// 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/>.
16
17//! # Refungible Pallet EVM API for tokens
18//!
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.
1621
17extern crate alloc;22extern crate alloc;
1823
45 TokenProperties, TokensMinted, weights::WeightInfo,50 TokenProperties, TokensMinted, weights::WeightInfo,
46};51};
4752
53/// @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 }
7587
88 /// @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 }
103120
121 /// @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 }
118139
140 /// @notice Get token property value.
119 /// Throws error if key not found141 /// @dev Throws error if key not found
142 /// @param tokenId ID of the token.
143 /// @param key Property key.
144 /// @return Property value bytes
120 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)
132157
133#[derive(ToLog)]158#[derive(ToLog)]
134pub enum ERC721Events {159pub enum ERC721Events {
160 /// @dev This event emits when NFTs are created (`from` == 0) and destroyed
161 /// (`to` == 0). Exception: during contract creation, any number of RFTs
162 /// may be created and assigned without emitting Transfer.
135 Transfer {163 Transfer {
136 #[indexed]164 #[indexed]
137 from: address,165 from: address,
169197
170#[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 contract
172 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 }
177206
207 /// @notice An abbreviated name for RFTs in this contract
178 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}
226256
257/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
258/// @dev See https://eips.ethereum.org/EIPS/eip-721
227#[solidity_interface(name = "ERC721Enumerable")]259#[solidity_interface(name = "ERC721Enumerable")]
228impl<T: Config> RefungibleHandle<T> {260impl<T: Config> RefungibleHandle<T> {
261 /// @notice Enumerate valid RFTs
262 /// @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 }
238274
275 /// @notice Count RFTs tracked by this contract
276 /// @return A count of valid RFTs tracked by this contract, where each one of
277 /// them has an assigned and queryable owner not equal to the zero address
239 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}
244283
284/// @title ERC-721 Non-Fungible Token Standard
285/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
245#[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 owner
289 /// @dev RFTs assigned to the zero address are considered invalid, and this
290 /// function throws for queries about the zero address.
291 /// @param owner An address for whom to query the balance
292 /// @return The number of RFTs owned by `owner`, possibly zero
247 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}
334380
381/// @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 implemented
340 }387 }
341}388}
342389
390/// @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 }
348396
397 /// @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 manually
400 /// @param to The new owner
401 /// @param tokenId ID of the minted RFT
351 #[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 }
388439
440 /// @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 manually
443 /// @param to The new owner
444 /// @param tokenId ID of the minted RFT
445 /// @param tokenUri Token URI that would be stored in the RFT properties
391 #[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}
499554
555/// @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 }
510566
567 /// @notice Function to mint multiple tokens.
568 /// @dev `tokenIds` should be an array of consecutive numbers and first number
569 /// should be obtained with `nextTokenId` method
570 /// @param to The new owner
571 /// @param tokenIds IDs of the minted RFTs
511 #[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 }
549610
611 /// @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 consecutive
613 /// numbers and first number should be obtained with `nextTokenId` method
614 /// @param to The new owner
615 /// @param tokens array of pairs of token ID and token URI for minted tokens
550 #[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(