git.delta.rocks / unique-network / refs/commits / bf0e967f70e3

difftreelog

feat set/get tokenPropertyPermissions for NFT

Trubnikov Sergey2022-12-14parent: #7fd4751.patch.diff
in: master

7 files changed

modifiedpallets/common/src/eth.rsdiffbeforeafterboth
--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -162,3 +162,12 @@
 	CollectionAdmin,
 	TokenOwner,
 }
+
+#[derive(AbiCoder, Copy, Clone, Default, Debug)]
+#[repr(u8)]
+pub enum EthTokenPermissions {
+	#[default]
+	Mutable,
+	TokenOwner,
+	CollectionAdmin,
+}
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
38use pallet_common::{38use pallet_common::{
39 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,39 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
40 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},40 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},
41 eth::EthCrossAccount,41 eth::{EthCrossAccount, EthTokenPermissions},
42};42};
43use pallet_evm::{account::CrossAccountId, PrecompileHandle};43use pallet_evm::{account::CrossAccountId, PrecompileHandle};
44use pallet_evm_coder_substrate::call;44use pallet_evm_coder_substrate::call;
60 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.60 /// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
61 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.61 /// @param tokenOwner Permission to mutate property by token owner if property is mutable.
62 #[weight(<SelfWeightOf<T>>::set_token_property_permissions(1))]62 #[weight(<SelfWeightOf<T>>::set_token_property_permissions(1))]
63 #[solidity(hide)]
63 fn set_token_property_permission(64 fn set_token_property_permission(
64 &mut self,65 &mut self,
65 caller: caller,66 caller: caller,
69 token_owner: bool,70 token_owner: bool,
70 ) -> Result<()> {71 ) -> Result<()> {
71 let caller = T::CrossAccountId::from_eth(caller);72 let caller = T::CrossAccountId::from_eth(caller);
72 <Pallet<T>>::set_property_permission(73 <Pallet<T>>::set_property_permissions(
73 self,74 self,
74 &caller,75 &caller,
75 PropertyKeyPermission {76 [PropertyKeyPermission {
76 key: <Vec<u8>>::from(key)77 key: <Vec<u8>>::from(key)
77 .try_into()78 .try_into()
78 .map_err(|_| "too long key")?,79 .map_err(|_| "too long key")?,
81 collection_admin,82 collection_admin,
82 token_owner,83 token_owner,
83 },84 },
84 },85 }]
86 .into(),
85 )87 )
86 .map_err(dispatch_to_evm::<T>)88 .map_err(dispatch_to_evm::<T>)
87 }89 }
90
91 /// @notice Set permissions for token property.
92 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
93 /// @param permissions Permissions for keys.
94 fn set_token_property_permissions(
95 &mut self,
96 caller: caller,
97 permissions: Vec<(string, Vec<(EthTokenPermissions, bool)>)>,
98 ) -> Result<()> {
99 let caller = T::CrossAccountId::from_eth(caller);
100 const PERMISSIONS_FIELDS_COUNT: usize = 3;
101
102 let mut perms = <Vec<_>>::new();
103
104 for (key, pp) in permissions {
105 if pp.len() > PERMISSIONS_FIELDS_COUNT {
106 return Err(alloc::format!(
107 "Actual number of fields {} for {}, which exceeds the maximum value of {}",
108 pp.len(),
109 stringify!(EthTokenPermissions),
110 PERMISSIONS_FIELDS_COUNT
111 )
112 .as_str()
113 .into());
114 }
115
116 let mut token_permission = PropertyPermission {
117 mutable: false,
118 collection_admin: false,
119 token_owner: false,
120 };
121
122 for (perm, value) in pp {
123 match perm {
124 EthTokenPermissions::Mutable => token_permission.mutable = value,
125 EthTokenPermissions::TokenOwner => token_permission.token_owner = value,
126 EthTokenPermissions::CollectionAdmin => {
127 token_permission.collection_admin = value
128 }
129 }
130 }
131
132 perms.push(PropertyKeyPermission {
133 key: <Vec<u8>>::from(key)
134 .try_into()
135 .map_err(|_| "too long key")?,
136 permission: token_permission,
137 });
138 }
139
140 <Pallet<T>>::set_property_permissions(self, &caller, perms).map_err(dispatch_to_evm::<T>)
141 }
142
143 fn token_property_permissions(
144 &self,
145 ) -> Result<Vec<(string, Vec<(EthTokenPermissions, bool)>)>> {
146 let mut res = <Vec<_>>::new();
147 for (key, pp) in <Pallet<T>>::token_property_permission(self.id) {
148 let key = string::from_utf8(key.into_inner()).unwrap();
149 let pp = [
150 (EthTokenPermissions::Mutable, pp.mutable),
151 (EthTokenPermissions::TokenOwner, pp.token_owner),
152 (EthTokenPermissions::CollectionAdmin, pp.collection_admin),
153 ]
154 .into();
155 res.push((key, pp));
156 }
157 Ok(res)
158 }
88159
89 /// @notice Set token property value.160 /// @notice Set token property value.
90 /// @dev Throws error if `msg.sender` has no permission to edit the property.161 /// @dev Throws error if `msg.sender` has no permission to edit the property.
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -103,7 +103,7 @@
 	AccessMode, CollectionId, CollectionFlags, CustomDataLimit, TokenId, CreateCollectionData,
 	CreateNftExData, mapping::TokenAddressMapping, budget::Budget, Property, PropertyPermission,
 	PropertyKey, PropertyValue, PropertyKeyPermission, Properties, PropertyScope, TrySetProperty,
-	TokenChild, AuxPropertyValue,
+	TokenChild, AuxPropertyValue, PropertiesPermissionMap,
 };
 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
 use pallet_common::{
@@ -827,12 +827,16 @@
 	/// Set property permissions for the collection.
 	///
 	/// Sender should be the owner or admin of the collection.
-	pub fn set_property_permission(
+	pub fn set_property_permissions(
 		collection: &CollectionHandle<T>,
 		sender: &T::CrossAccountId,
-		permission: PropertyKeyPermission,
+		permission: Vec<PropertyKeyPermission>,
 	) -> DispatchResult {
-		<PalletCommon<T>>::set_property_permission(collection, sender, permission)
+		<PalletCommon<T>>::set_token_property_permissions(collection, sender, permission)
+	}
+
+	pub fn token_property_permission(collection_id: CollectionId) -> PropertiesPermissionMap {
+		<PalletCommon<T>>::property_permissions(collection_id)
 	}
 
 	pub fn check_token_immediate_ownership(
modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -18,30 +18,44 @@
 }
 
 /// @title A contract that allows to set and delete token properties and change token property permissions.
-/// @dev the ERC-165 identifier for this interface is 0x91a97a68
+/// @dev the ERC-165 identifier for this interface is 0xde0695c2
 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 isMutable Permission to mutate property.
+	// /// @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.
+	// /// @dev EVM selector for this function is: 0x222d97fa,
+	// ///  or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
+	// function setTokenPropertyPermission(string memory key, bool isMutable, bool collectionAdmin, bool tokenOwner) public {
+	// 	require(false, stub_error);
+	// 	key;
+	// 	isMutable;
+	// 	collectionAdmin;
+	// 	tokenOwner;
+	// 	dummy = 0;
+	// }
+
 	/// @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 isMutable Permission to mutate property.
-	/// @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.
-	/// @dev EVM selector for this function is: 0x222d97fa,
-	///  or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
-	function setTokenPropertyPermission(
-		string memory key,
-		bool isMutable,
-		bool collectionAdmin,
-		bool tokenOwner
-	) public {
+	/// @param permissions Permissions for keys.
+	/// @dev EVM selector for this function is: 0xbd92983a,
+	///  or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
+	function setTokenPropertyPermissions(Tuple48[] memory permissions) public {
 		require(false, stub_error);
-		key;
-		isMutable;
-		collectionAdmin;
-		tokenOwner;
+		permissions;
 		dummy = 0;
 	}
 
+	/// @dev EVM selector for this function is: 0xf23d7790,
+	///  or in textual repr: tokenPropertyPermissions()
+	function tokenPropertyPermissions() public view returns (Tuple48[] memory) {
+		require(false, stub_error);
+		dummy;
+		return new Tuple48[](0);
+	}
+
 	// /// @notice Set token property value.
 	// /// @dev Throws error if `msg.sender` has no permission to edit the property.
 	// /// @param tokenId ID of the token.
@@ -118,6 +132,24 @@
 	bytes value;
 }
 
+enum EthTokenPermissions {
+	Mutable,
+	TokenOwner,
+	CollectionAdmin
+}
+
+/// @dev anonymous struct
+struct Tuple48 {
+	string field_0;
+	Tuple46[] field_1;
+}
+
+/// @dev anonymous struct
+struct Tuple46 {
+	EthTokenPermissions field_0;
+	bool field_1;
+}
+
 /// @title A contract that allows you to work with collections.
 /// @dev the ERC-165 identifier for this interface is 0xb5e1747f
 contract Collection is Dummy, ERC165 {
modifiedtests/src/eth/abi/nonFungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/nonFungible.json
+++ b/tests/src/eth/abi/nonFungible.json
@@ -697,12 +697,29 @@
   },
   {
     "inputs": [
-      { "internalType": "string", "name": "key", "type": "string" },
-      { "internalType": "bool", "name": "isMutable", "type": "bool" },
-      { "internalType": "bool", "name": "collectionAdmin", "type": "bool" },
-      { "internalType": "bool", "name": "tokenOwner", "type": "bool" }
+      {
+        "components": [
+          { "internalType": "string", "name": "field_0", "type": "string" },
+          {
+            "components": [
+              {
+                "internalType": "enum EthTokenPermissions",
+                "name": "field_0",
+                "type": "uint8"
+              },
+              { "internalType": "bool", "name": "field_1", "type": "bool" }
+            ],
+            "internalType": "struct Tuple46[]",
+            "name": "field_1",
+            "type": "tuple[]"
+          }
+        ],
+        "internalType": "struct Tuple48[]",
+        "name": "permissions",
+        "type": "tuple[]"
+      }
     ],
-    "name": "setTokenPropertyPermission",
+    "name": "setTokenPropertyPermissions",
     "outputs": [],
     "stateMutability": "nonpayable",
     "type": "function"
@@ -743,6 +760,35 @@
     "type": "function"
   },
   {
+    "inputs": [],
+    "name": "tokenPropertyPermissions",
+    "outputs": [
+      {
+        "components": [
+          { "internalType": "string", "name": "field_0", "type": "string" },
+          {
+            "components": [
+              {
+                "internalType": "enum EthTokenPermissions",
+                "name": "field_0",
+                "type": "uint8"
+              },
+              { "internalType": "bool", "name": "field_1", "type": "bool" }
+            ],
+            "internalType": "struct Tuple46[]",
+            "name": "field_1",
+            "type": "tuple[]"
+          }
+        ],
+        "internalType": "struct Tuple48[]",
+        "name": "",
+        "type": "tuple[]"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
     "inputs": [
       { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
     ],
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -13,22 +13,28 @@
 }
 
 /// @title A contract that allows to set and delete token properties and change token property permissions.
-/// @dev the ERC-165 identifier for this interface is 0x91a97a68
+/// @dev the ERC-165 identifier for this interface is 0xde0695c2
 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 isMutable Permission to mutate property.
+	// /// @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.
+	// /// @dev EVM selector for this function is: 0x222d97fa,
+	// ///  or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
+	// function setTokenPropertyPermission(string memory key, bool isMutable, bool collectionAdmin, bool tokenOwner) external;
+
 	/// @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 isMutable Permission to mutate property.
-	/// @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.
-	/// @dev EVM selector for this function is: 0x222d97fa,
-	///  or in textual repr: setTokenPropertyPermission(string,bool,bool,bool)
-	function setTokenPropertyPermission(
-		string memory key,
-		bool isMutable,
-		bool collectionAdmin,
-		bool tokenOwner
-	) external;
+	/// @param permissions Permissions for keys.
+	/// @dev EVM selector for this function is: 0xbd92983a,
+	///  or in textual repr: setTokenPropertyPermissions((string,(uint8,bool)[])[])
+	function setTokenPropertyPermissions(Tuple43[] memory permissions) external;
+
+	/// @dev EVM selector for this function is: 0xf23d7790,
+	///  or in textual repr: tokenPropertyPermissions()
+	function tokenPropertyPermissions() external view returns (Tuple43[] memory);
 
 	// /// @notice Set token property value.
 	// /// @dev Throws error if `msg.sender` has no permission to edit the property.
@@ -79,6 +85,24 @@
 	bytes value;
 }
 
+enum EthTokenPermissions {
+	Mutable,
+	TokenOwner,
+	CollectionAdmin
+}
+
+/// @dev anonymous struct
+struct Tuple43 {
+	string field_0;
+	Tuple41[] field_1;
+}
+
+/// @dev anonymous struct
+struct Tuple41 {
+	EthTokenPermissions field_0;
+	bool field_1;
+}
+
 /// @title A contract that allows you to work with collections.
 /// @dev the ERC-165 identifier for this interface is 0xb5e1747f
 interface Collection is Dummy, ERC165 {
modifiedtests/src/eth/tokenProperties.test.tsdiffbeforeafterboth
--- a/tests/src/eth/tokenProperties.test.ts
+++ b/tests/src/eth/tokenProperties.test.ts
@@ -32,7 +32,7 @@
     });
   });
 
-  itEth('Can be reconfigured', async({helper}) => {
+  itEth.only('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);
@@ -41,12 +41,16 @@
       const address = helper.ethAddress.fromCollectionId(collection.collectionId);
       const contract = helper.ethNativeContract.collection(address, 'nft', caller);
   
-      await contract.methods.setTokenPropertyPermission('testKey', mutable, collectionAdmin, tokenOwner).send({from: caller});
+      await contract.methods.setTokenPropertyPermissions([['testKey', [[0, mutable], [1, tokenOwner], [2, collectionAdmin]]]]).send({from: caller});
   
       expect(await collection.getPropertyPermissions()).to.be.deep.equal([{
         key: 'testKey',
         permission: {mutable, collectionAdmin, tokenOwner},
       }]);
+
+      expect(await contract.methods.tokenPropertyPermissions().call({from: caller})).to.be.like([
+        ['testKey', [['0', mutable], ['1', tokenOwner], ['2', collectionAdmin]]]
+      ]);
     }
   });