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

difftreelog

added `collectionNestingPermissions` funtion in `Collection` interface

PraetorP2022-12-06parent: #5223dbe.patch.diff
in: master

13 files changed

modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -26,7 +26,7 @@
 	weight,
 };
 use pallet_evm_coder_substrate::dispatch_to_evm;
-use sp_std::vec::Vec;
+use sp_std::{vec, vec::Vec};
 use up_data_structs::{
 	AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property,
 	SponsoringRateLimit, SponsorshipState,
@@ -35,7 +35,9 @@
 
 use crate::{
 	Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,
-	eth::{EthCrossAccount, convert_cross_account_to_uint256},
+	eth::{
+		EthCrossAccount, convert_cross_account_to_uint256, CollectionPermissions as EvmPermissions,
+	},
 	weights::WeightInfo,
 };
 
@@ -508,6 +510,14 @@
 		))
 	}
 
+	/// Returns permissions for a collection
+	fn collection_nesting_permissions(&self) -> Result<Vec<(EvmPermissions, bool)>> {
+		let nesting = self.collection.permissions.nesting();
+		Ok(vec![
+			(EvmPermissions::CollectionAdmin, nesting.collection_admin),
+			(EvmPermissions::TokenOwner, nesting.token_owner),
+		])
+	}
 	/// Set the collection access method.
 	/// @param mode Access mode
 	/// 	0 for Normal
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
before · pallets/common/src/eth.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! The module contains a number of functions for converting and checking ethereum identifiers.1819use evm_coder::{20	AbiCoder,21	types::{uint256, address},22};23pub use pallet_evm::{Config, account::CrossAccountId};24use sp_core::H160;25use up_data_structs::CollectionId;2627// 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection 128// TODO: Unhardcode prefix29const ETH_COLLECTION_PREFIX: [u8; 16] = [30	0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,31];3233/// Maps the ethereum address of the collection in substrate.34pub fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {35	if eth[0..16] != ETH_COLLECTION_PREFIX {36		return None;37	}38	let mut id_bytes = [0; 4];39	id_bytes.copy_from_slice(&eth[16..20]);40	Some(CollectionId(u32::from_be_bytes(id_bytes)))41}4243/// Maps the substrate collection id in ethereum.44pub fn collection_id_to_address(id: CollectionId) -> H160 {45	let mut out = [0; 20];46	out[0..16].copy_from_slice(&ETH_COLLECTION_PREFIX);47	out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));48	H160(out)49}5051/// Check if the ethereum address is a collection.52pub fn is_collection(address: &H160) -> bool {53	address[0..16] == ETH_COLLECTION_PREFIX54}5556/// Convert `CrossAccountId` to `uint256`.57pub fn convert_cross_account_to_uint256<T: Config>(from: &T::CrossAccountId) -> uint25658where59	T::AccountId: AsRef<[u8; 32]>,60{61	let slice = from.as_sub().as_ref();62	uint256::from_big_endian(slice)63}6465/// Convert `uint256` to `CrossAccountId`.66pub fn convert_uint256_to_cross_account<T: Config>(from: uint256) -> T::CrossAccountId67where68	T::AccountId: From<[u8; 32]>,69{70	let mut new_admin_arr = [0_u8; 32];71	from.to_big_endian(&mut new_admin_arr);72	let account_id = T::AccountId::from(new_admin_arr);73	T::CrossAccountId::from_sub(account_id)74}7576/// Convert `CrossAccountId` to `(address, uint256)`.77pub fn convert_cross_account_to_tuple<T: Config>(78	cross_account_id: &T::CrossAccountId,79) -> (address, uint256)80where81	T::AccountId: AsRef<[u8; 32]>,82{83	if cross_account_id.is_canonical_substrate() {84		let sub = convert_cross_account_to_uint256::<T>(cross_account_id);85		(Default::default(), sub)86	} else {87		let eth = *cross_account_id.as_eth();88		(eth, Default::default())89	}90}9192/// Convert tuple `(address, uint256)` to `CrossAccountId`.93///94/// If `address` in the tuple has *default* value, then the canonical form is substrate,95/// if `uint256` has *default* value, then the ethereum form is canonical,96/// if both values are *default* or *non default*, then this is considered an invalid address and `Error` is returned.97pub fn convert_tuple_to_cross_account<T: Config>(98	eth_cross_account_id: (address, uint256),99) -> evm_coder::execution::Result<T::CrossAccountId>100where101	T::AccountId: From<[u8; 32]>,102{103	if eth_cross_account_id == Default::default() {104		Err("All fields of cross account is zeroed".into())105	} else if eth_cross_account_id.0 == Default::default() {106		Ok(convert_uint256_to_cross_account::<T>(107			eth_cross_account_id.1,108		))109	} else if eth_cross_account_id.1 == Default::default() {110		Ok(T::CrossAccountId::from_eth(eth_cross_account_id.0))111	} else {112		Err("All fields of cross account is non zeroed".into())113	}114}115116/// Cross account struct117#[derive(Debug, Default, AbiCoder)]118pub struct EthCrossAccount {119	pub(crate) eth: address,120	pub(crate) sub: uint256,121}122123impl EthCrossAccount {124	pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self125	where126		T: pallet_evm::Config,127		T::AccountId: AsRef<[u8; 32]>,128	{129		if cross_account_id.is_canonical_substrate() {130			Self {131				eth: Default::default(),132				sub: convert_cross_account_to_uint256::<T>(cross_account_id),133			}134		} else {135			Self {136				eth: *cross_account_id.as_eth(),137				sub: Default::default(),138			}139		}140	}141142	pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>143	where144		T: pallet_evm::Config,145		T::AccountId: From<[u8; 32]>,146	{147		if self.eth == Default::default() && self.sub == Default::default() {148			Err("All fields of cross account is zeroed".into())149		} else if self.eth == Default::default() {150			Ok(convert_uint256_to_cross_account::<T>(self.sub))151		} else if self.sub == Default::default() {152			Ok(T::CrossAccountId::from_eth(self.eth))153		} else {154			Err("All fields of cross account is non zeroed".into())155		}156	}157}
modifiedpallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth
--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -18,7 +18,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
 contract Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -263,6 +263,15 @@
 		return Tuple21(false, new uint256[](0));
 	}
 
+	/// Returns permissions for a collection
+	/// @dev EVM selector for this function is: 0x5b2eaf4b,
+	///  or in textual repr: collectionNestingPermissions()
+	function collectionNestingPermissions() public view returns (Tuple24[] memory) {
+		require(false, stub_error);
+		dummy;
+		return new Tuple24[](0);
+	}
+
 	/// Set the collection access method.
 	/// @param mode Access mode
 	/// 	0 for Normal
@@ -434,6 +443,17 @@
 	uint256 sub;
 }
 
+enum CollectionPermissions {
+	CollectionAdmin,
+	TokenOwner
+}
+
+/// @dev anonymous struct
+struct Tuple24 {
+	CollectionPermissions field_0;
+	bool field_1;
+}
+
 /// @dev anonymous struct
 struct Tuple21 {
 	bool field_0;
modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -119,7 +119,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
 contract Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -364,6 +364,15 @@
 		return Tuple34(false, new uint256[](0));
 	}
 
+	/// Returns permissions for a collection
+	/// @dev EVM selector for this function is: 0x5b2eaf4b,
+	///  or in textual repr: collectionNestingPermissions()
+	function collectionNestingPermissions() public view returns (Tuple37[] memory) {
+		require(false, stub_error);
+		dummy;
+		return new Tuple37[](0);
+	}
+
 	/// Set the collection access method.
 	/// @param mode Access mode
 	/// 	0 for Normal
@@ -535,6 +544,17 @@
 	uint256 sub;
 }
 
+enum CollectionPermissions {
+	CollectionAdmin,
+	TokenOwner
+}
+
+/// @dev anonymous struct
+struct Tuple37 {
+	CollectionPermissions field_0;
+	bool field_1;
+}
+
 /// @dev anonymous struct
 struct Tuple34 {
 	bool field_0;
modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -119,7 +119,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
 contract Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -364,6 +364,15 @@
 		return Tuple33(false, new uint256[](0));
 	}
 
+	/// Returns permissions for a collection
+	/// @dev EVM selector for this function is: 0x5b2eaf4b,
+	///  or in textual repr: collectionNestingPermissions()
+	function collectionNestingPermissions() public view returns (Tuple36[] memory) {
+		require(false, stub_error);
+		dummy;
+		return new Tuple36[](0);
+	}
+
 	/// Set the collection access method.
 	/// @param mode Access mode
 	/// 	0 for Normal
@@ -535,6 +544,17 @@
 	uint256 sub;
 }
 
+enum CollectionPermissions {
+	CollectionAdmin,
+	TokenOwner
+}
+
+/// @dev anonymous struct
+struct Tuple36 {
+	CollectionPermissions field_0;
+	bool field_1;
+}
+
 /// @dev anonymous struct
 struct Tuple33 {
 	bool field_0;
modifiedtests/src/eth/abi/fungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/fungible.json
+++ b/tests/src/eth/abi/fungible.json
@@ -208,6 +208,27 @@
   },
   {
     "inputs": [],
+    "name": "collectionNestingPermissions",
+    "outputs": [
+      {
+        "components": [
+          {
+            "internalType": "enum CollectionPermissions",
+            "name": "field_0",
+            "type": "uint8"
+          },
+          { "internalType": "bool", "name": "field_1", "type": "bool" }
+        ],
+        "internalType": "struct Tuple24[]",
+        "name": "",
+        "type": "tuple[]"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [],
     "name": "collectionNestingRestrictedCollectionIds",
     "outputs": [
       {
modifiedtests/src/eth/abi/nonFungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/nonFungible.json
+++ b/tests/src/eth/abi/nonFungible.json
@@ -238,6 +238,27 @@
   },
   {
     "inputs": [],
+    "name": "collectionNestingPermissions",
+    "outputs": [
+      {
+        "components": [
+          {
+            "internalType": "enum CollectionPermissions",
+            "name": "field_0",
+            "type": "uint8"
+          },
+          { "internalType": "bool", "name": "field_1", "type": "bool" }
+        ],
+        "internalType": "struct Tuple37[]",
+        "name": "",
+        "type": "tuple[]"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [],
     "name": "collectionNestingRestrictedCollectionIds",
     "outputs": [
       {
modifiedtests/src/eth/abi/reFungible.jsondiffbeforeafterboth
--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -220,6 +220,27 @@
   },
   {
     "inputs": [],
+    "name": "collectionNestingPermissions",
+    "outputs": [
+      {
+        "components": [
+          {
+            "internalType": "enum CollectionPermissions",
+            "name": "field_0",
+            "type": "uint8"
+          },
+          { "internalType": "bool", "name": "field_1", "type": "bool" }
+        ],
+        "internalType": "struct Tuple36[]",
+        "name": "",
+        "type": "tuple[]"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [],
     "name": "collectionNestingRestrictedCollectionIds",
     "outputs": [
       {
modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -13,7 +13,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
 interface Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -171,6 +171,11 @@
 	///  or in textual repr: collectionNestingRestrictedCollectionIds()
 	function collectionNestingRestrictedCollectionIds() external view returns (Tuple20 memory);
 
+	/// Returns permissions for a collection
+	/// @dev EVM selector for this function is: 0x5b2eaf4b,
+	///  or in textual repr: collectionNestingPermissions()
+	function collectionNestingPermissions() external view returns (Tuple23[] memory);
+
 	/// Set the collection access method.
 	/// @param mode Access mode
 	/// 	0 for Normal
@@ -284,6 +289,17 @@
 }
 
 /// @dev anonymous struct
+struct Tuple23 {
+	CollectionPermissions field_0;
+	bool field_1;
+}
+
+enum CollectionPermissions {
+	CollectionAdmin,
+	TokenOwner
+}
+
+/// @dev anonymous struct
 struct Tuple20 {
 	bool field_0;
 	uint256[] field_1;
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -80,7 +80,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
 interface Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -238,6 +238,11 @@
 	///  or in textual repr: collectionNestingRestrictedCollectionIds()
 	function collectionNestingRestrictedCollectionIds() external view returns (Tuple31 memory);
 
+	/// Returns permissions for a collection
+	/// @dev EVM selector for this function is: 0x5b2eaf4b,
+	///  or in textual repr: collectionNestingPermissions()
+	function collectionNestingPermissions() external view returns (Tuple34[] memory);
+
 	/// Set the collection access method.
 	/// @param mode Access mode
 	/// 	0 for Normal
@@ -351,6 +356,17 @@
 }
 
 /// @dev anonymous struct
+struct Tuple34 {
+	CollectionPermissions field_0;
+	bool field_1;
+}
+
+enum CollectionPermissions {
+	CollectionAdmin,
+	TokenOwner
+}
+
+/// @dev anonymous struct
 struct Tuple31 {
 	bool field_0;
 	uint256[] field_1;
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -80,7 +80,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xeecfdb34
+/// @dev the ERC-165 identifier for this interface is 0xb5e1747f
 interface Collection is Dummy, ERC165 {
 	// /// Set collection property.
 	// ///
@@ -238,6 +238,11 @@
 	///  or in textual repr: collectionNestingRestrictedCollectionIds()
 	function collectionNestingRestrictedCollectionIds() external view returns (Tuple30 memory);
 
+	/// Returns permissions for a collection
+	/// @dev EVM selector for this function is: 0x5b2eaf4b,
+	///  or in textual repr: collectionNestingPermissions()
+	function collectionNestingPermissions() external view returns (Tuple33[] memory);
+
 	/// Set the collection access method.
 	/// @param mode Access mode
 	/// 	0 for Normal
@@ -351,6 +356,17 @@
 }
 
 /// @dev anonymous struct
+struct Tuple33 {
+	CollectionPermissions field_0;
+	bool field_1;
+}
+
+enum CollectionPermissions {
+	CollectionAdmin,
+	TokenOwner
+}
+
+/// @dev anonymous struct
 struct Tuple30 {
 	bool field_0;
 	uint256[] field_1;
modifiedtests/src/eth/nesting/nest.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nesting/nest.test.ts
+++ b/tests/src/eth/nesting/nest.test.ts
@@ -52,7 +52,7 @@
       expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(owner);
     });
     
-    itEth('NFT: collectionNestingRestrictedCollectionIds()', async ({helper}) => {
+    itEth('NFT: collectionNestingRestrictedCollectionIds() & collectionNestingPermissions', async ({helper}) => {
       const owner = await helper.eth.createAccountWithBalance(donor);
       const {collectionId: unnestedCollsectionId, collectionAddress: unnsetedCollectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
       const unnestedContract = helper.ethNativeContract.collection(unnsetedCollectionAddress, 'nft', owner);
@@ -62,7 +62,9 @@
       expect(await contract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([true, []]);
       await contract.methods.setCollectionNesting(true, [unnsetedCollectionAddress]).send({from: owner});
       expect(await contract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([true, [unnestedCollsectionId.toString()]]);
-      
+      expect(await contract.methods.collectionNestingPermissions().call({from: owner})).to.be.like([['0', false], ['1', true]]);
+      await contract.methods.setCollectionNesting(false).send({from: owner});
+      expect(await contract.methods.collectionNestingPermissions().call({from: owner})).to.be.like([['0', false], ['1', false]]);
     });
     
     itEth('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {