From 08e7d2834a5cb6b433b58971e6308721970a16f5 Mon Sep 17 00:00:00 2001 From: Trubnikov Sergey Date: Wed, 14 Dec 2022 13:36:17 +0000 Subject: [PATCH] feat: set/get tokenPropertyPermissions for NFT --- --- a/pallets/nonfungible/src/erc.rs +++ b/pallets/nonfungible/src/erc.rs @@ -34,7 +34,7 @@ CollectionPropertiesVec, }; use pallet_evm_coder_substrate::dispatch_to_evm; -use sp_std::vec::Vec; +use sp_std::{vec::Vec, vec}; use pallet_common::{ CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations, erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key}, @@ -70,10 +70,10 @@ token_owner: bool, ) -> Result<()> { let caller = T::CrossAccountId::from_eth(caller); - >::set_property_permissions( + >::set_token_property_permissions( self, &caller, - [PropertyKeyPermission { + vec![PropertyKeyPermission { key: >::from(key) .try_into() .map_err(|_| "too long key")?, @@ -82,8 +82,7 @@ collection_admin, token_owner, }, - }] - .into(), + }], ) .map_err(dispatch_to_evm::) } @@ -137,7 +136,8 @@ }); } - >::set_property_permissions(self, &caller, perms).map_err(dispatch_to_evm::) + >::set_token_property_permissions(self, &caller, perms) + .map_err(dispatch_to_evm::) } fn token_property_permissions( --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -824,17 +824,6 @@ ) } - /// Set property permissions for the collection. - /// - /// Sender should be the owner or admin of the collection. - pub fn set_property_permissions( - collection: &CollectionHandle, - sender: &T::CrossAccountId, - permission: Vec, - ) -> DispatchResult { - >::set_token_property_permissions(collection, sender, permission) - } - pub fn token_property_permission(collection_id: CollectionId) -> PropertiesPermissionMap { >::property_permissions(collection_id) } --- a/pallets/refungible/src/erc.rs +++ b/pallets/refungible/src/erc.rs @@ -33,7 +33,7 @@ use pallet_common::{ CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations, erc::{CommonEvmHandler, CollectionCall, static_property::key}, - eth::EthCrossAccount, + eth::{EthCrossAccount, EthTokenPermissions}, Error as CommonError, }; use pallet_evm::{account::CrossAccountId, PrecompileHandle}; @@ -63,6 +63,7 @@ /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable. /// @param tokenOwner Permission to mutate property by token owner if property is mutable. #[weight(>::set_token_property_permissions(1))] + #[solidity(hide)] fn set_token_property_permission( &mut self, caller: caller, @@ -89,6 +90,76 @@ .map_err(dispatch_to_evm::) } + /// @notice Set permissions for token property. + /// @dev Throws error if `msg.sender` is not admin or owner of the collection. + /// @param permissions Permissions for keys. + fn set_token_property_permissions( + &mut self, + caller: caller, + permissions: Vec<(string, Vec<(EthTokenPermissions, bool)>)>, + ) -> Result<()> { + let caller = T::CrossAccountId::from_eth(caller); + const PERMISSIONS_FIELDS_COUNT: usize = 3; + + let mut perms = >::new(); + + for (key, pp) in permissions { + if pp.len() > PERMISSIONS_FIELDS_COUNT { + return Err(alloc::format!( + "Actual number of fields {} for {}, which exceeds the maximum value of {}", + pp.len(), + stringify!(EthTokenPermissions), + PERMISSIONS_FIELDS_COUNT + ) + .as_str() + .into()); + } + + let mut token_permission = PropertyPermission { + mutable: false, + collection_admin: false, + token_owner: false, + }; + + for (perm, value) in pp { + match perm { + EthTokenPermissions::Mutable => token_permission.mutable = value, + EthTokenPermissions::TokenOwner => token_permission.token_owner = value, + EthTokenPermissions::CollectionAdmin => { + token_permission.collection_admin = value + } + } + } + + perms.push(PropertyKeyPermission { + key: >::from(key) + .try_into() + .map_err(|_| "too long key")?, + permission: token_permission, + }); + } + + >::set_token_property_permissions(self, &caller, perms) + .map_err(dispatch_to_evm::) + } + + fn token_property_permissions( + &self, + ) -> Result)>> { + let mut res = >::new(); + for (key, pp) in >::token_property_permission(self.id) { + let key = string::from_utf8(key.into_inner()).unwrap(); + let pp = [ + (EthTokenPermissions::Mutable, pp.mutable), + (EthTokenPermissions::TokenOwner, pp.token_owner), + (EthTokenPermissions::CollectionAdmin, pp.collection_admin), + ] + .into(); + res.push((key, pp)); + } + Ok(res) + } + /// @notice Set token property value. /// @dev Throws error if `msg.sender` has no permission to edit the property. /// @param tokenId ID of the token. --- a/pallets/refungible/src/lib.rs +++ b/pallets/refungible/src/lib.rs @@ -113,7 +113,7 @@ AccessMode, budget::Budget, CollectionId, CollectionFlags, CollectionPropertiesVec, CreateCollectionData, CustomDataLimit, mapping::TokenAddressMapping, MAX_ITEMS_PER_BATCH, MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission, - PropertyScope, PropertyValue, TokenId, TrySetProperty, + PropertyScope, PropertyValue, TokenId, TrySetProperty, PropertiesPermissionMap, }; pub use pallet::*; @@ -1378,6 +1378,10 @@ >::set_token_property_permissions(collection, sender, property_permissions) } + pub fn token_property_permission(collection_id: CollectionId) -> PropertiesPermissionMap { + >::property_permissions(collection_id) + } + pub fn set_scoped_token_property_permissions( collection: &RefungibleHandle, sender: &T::CrossAccountId, --- a/tests/src/eth/tokenProperties.test.ts +++ b/tests/src/eth/tokenProperties.test.ts @@ -32,7 +32,7 @@ }); }); - itEth.only('Can be reconfigured', async({helper}) => { + itEth('Can be reconfigured', async({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) { const collection = await helper.nft.mintCollection(alice); -- gitstuff