git.delta.rocks / unique-network / refs/commits / 876ef621bd1e

difftreelog

feat add conditional supportInterface for ERC721Metadata

Grigoriy Simonov2022-09-13parent: #ba7ab8a.patch.diff
in: master

29 files changed

modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -684,6 +684,11 @@
 		pub fn parent_nft() -> up_data_structs::PropertyKey {
 			property_key_from_bytes(b"parentNft").expect(EXPECT_CONVERT_ERROR)
 		}
+
+		/// Key "parentNft".
+		pub fn erc721_metadata() -> up_data_structs::PropertyKey {
+			property_key_from_bytes(b"ERC721Metadata").expect(EXPECT_CONVERT_ERROR)
+		}
 	}
 
 	/// Values.
@@ -693,10 +698,21 @@
 		/// Value "ERC721Metadata".
 		pub const ERC721_METADATA: &[u8] = b"ERC721Metadata";
 
+		/// Value "1" ERC721 metadata supported.
+		pub const ERC721_METADATA_SUPPORTED: &[u8] = b"1";
+
+		/// Value "0" ERC721 metadata supported.
+		pub const ERC721_METADATA_UNSUPPORTED: &[u8] = b"0";
+
 		/// Value for [`ERC721_METADATA`].
 		pub fn erc721() -> up_data_structs::PropertyValue {
 			property_value_from_bytes(ERC721_METADATA).expect(EXPECT_CONVERT_ERROR)
 		}
+
+		/// Value for [`ERC721_METADATA`].
+		pub fn erc721_metadata_supported() -> up_data_structs::PropertyValue {
+			property_value_from_bytes(ERC721_METADATA_SUPPORTED).expect(EXPECT_CONVERT_ERROR)
+		}
 	}
 
 	/// Convert `byte` to [`PropertyKey`].
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -232,7 +232,7 @@
 			if !url.is_empty() {
 				return Ok(url);
 			}
-		} else if !is_erc721_metadata_compatible::<T>(self.id) {
+		} else if !self.supports_metadata() {
 			return Err("tokenURI not set".into());
 		}
 
@@ -548,17 +548,6 @@
 	}
 
 	Err("Property tokenURI not found".into())
-}
-
-fn is_erc721_metadata_compatible<T: Config>(collection_id: CollectionId) -> bool {
-	if let Some(shema_name) =
-		pallet_common::Pallet::<T>::get_collection_property(collection_id, &key::schema_name())
-	{
-		let shema_name = shema_name.into_inner();
-		shema_name == property_value::ERC721_METADATA
-	} else {
-		false
-	}
 }
 
 fn get_token_permission<T: Config>(
@@ -577,16 +566,6 @@
 	Ok(a)
 }
 
-fn has_token_permission<T: Config>(collection_id: CollectionId, key: &PropertyKey) -> bool {
-	if let Ok(token_property_permissions) =
-		CollectionPropertyPermissions::<T>::try_get(collection_id)
-	{
-		return token_property_permissions.contains_key(key);
-	}
-
-	false
-}
-
 /// @title Unique extensions for ERC721.
 #[solidity_interface(name = ERC721UniqueExtensions)]
 impl<T: Config> NonfungibleHandle<T> {
@@ -731,7 +710,7 @@
 	name = UniqueNFT,
 	is(
 		ERC721,
-		ERC721Metadata,
+		ERC721Metadata(if(this.supports_metadata())),
 		ERC721Enumerable,
 		ERC721UniqueExtensions,
 		ERC721Mintable,
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -108,6 +108,7 @@
 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
 use pallet_common::{
 	Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, CollectionHandle,
+	erc::static_property::{key, value},
 	eth::collection_id_to_address,
 };
 use pallet_structure::{Pallet as PalletStructure, Error as StructureError};
@@ -295,6 +296,19 @@
 		&mut self.0
 	}
 }
+
+impl<T: Config> NonfungibleHandle<T> {
+	pub fn supports_metadata(&self) -> bool {
+		if let Some(erc721_metadata) =
+			pallet_common::Pallet::<T>::get_collection_property(self.id, &key::erc721_metadata())
+		{
+			*erc721_metadata.into_inner() == *value::ERC721_METADATA_SUPPORTED
+		} else {
+			false
+		}
+	}
+}
+
 impl<T: Config> WithRecorder<T> for NonfungibleHandle<T> {
 	fn recorder(&self) -> &SubstrateRecorder<T> {
 		self.0.recorder()
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -228,7 +228,7 @@
 			if !url.is_empty() {
 				return Ok(url);
 			}
-		} else if !is_erc721_metadata_compatible::<T>(self.id) {
+		} else if !self.supports_metadata() {
 			return Err("tokenURI not set".into());
 		}
 
@@ -578,17 +578,6 @@
 	Err("Property tokenURI not found".into())
 }
 
-fn is_erc721_metadata_compatible<T: Config>(collection_id: CollectionId) -> bool {
-	if let Some(shema_name) =
-		pallet_common::Pallet::<T>::get_collection_property(collection_id, &key::schema_name())
-	{
-		let shema_name = shema_name.into_inner();
-		shema_name == property_value::ERC721_METADATA
-	} else {
-		false
-	}
-}
-
 fn get_token_permission<T: Config>(
 	collection_id: CollectionId,
 	key: &PropertyKey,
@@ -780,7 +769,7 @@
 	name = UniqueRefungible,
 	is(
 		ERC721,
-		ERC721Metadata,
+		ERC721Metadata(if(this.supports_metadata())),
 		ERC721Enumerable,
 		ERC721UniqueExtensions,
 		ERC721Mintable,
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -92,14 +92,19 @@
 
 use codec::{Encode, Decode, MaxEncodedLen};
 use core::ops::Deref;
+use derivative::Derivative;
 use evm_coder::ToLog;
 use frame_support::{
-	BoundedVec, ensure, fail, storage::with_transaction, transactional, pallet_prelude::ConstU32,
+	BoundedBTreeMap, BoundedVec, ensure, fail, storage::with_transaction, transactional,
+	pallet_prelude::ConstU32,
 };
 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
 use pallet_evm_coder_substrate::WithRecorder;
 use pallet_common::{
-	CommonCollectionOperations, Error as CommonError, eth::collection_id_to_address,
+	CommonCollectionOperations,
+	erc::static_property::{key, value},
+	Error as CommonError,
+	eth::collection_id_to_address,
 	Event as CommonEvent, Pallet as PalletCommon,
 };
 use pallet_structure::Pallet as PalletStructure;
@@ -113,8 +118,6 @@
 	MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission,
 	PropertyScope, PropertyValue, TokenId, TrySetProperty,
 };
-use frame_support::BoundedBTreeMap;
-use derivative::Derivative;
 
 pub use pallet::*;
 #[cfg(feature = "runtime-benchmarks")]
@@ -301,6 +304,18 @@
 	}
 }
 
+impl<T: Config> RefungibleHandle<T> {
+	pub fn supports_metadata(&self) -> bool {
+		if let Some(erc721_metadata) =
+			pallet_common::Pallet::<T>::get_collection_property(self.id, &key::erc721_metadata())
+		{
+			*erc721_metadata.into_inner() == *value::ERC721_METADATA_SUPPORTED
+		} else {
+			false
+		}
+	}
+}
+
 impl<T: Config> Deref for RefungibleHandle<T> {
 	type Target = pallet_common::CollectionHandle<T>;
 
modifiedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
--- a/pallets/unique/src/eth/mod.rs
+++ b/pallets/unique/src/eth/mod.rs
@@ -130,6 +130,13 @@
 			})
 			.map_err(|e| Error::Revert(format!("{:?}", e)))?;
 
+		properties
+			.try_push(up_data_structs::Property {
+				key: key::erc721_metadata(),
+				value: property_value::erc721_metadata_supported(),
+			})
+			.map_err(|e| Error::Revert(format!("{:?}", e)))?;
+
 		if !base_uri_value.is_empty() {
 			properties
 				.try_push(up_data_structs::Property {
@@ -212,7 +219,8 @@
 	/// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications
 	/// @return address Address of the newly created collection
 	#[weight(<SelfWeightOf<T>>::create_collection())]
-	fn create_nonfungible_collection(
+	#[solidity(rename_selector = "createNFTCollection")]
+	fn create_nft_collection(
 		&mut self,
 		caller: caller,
 		value: value,
@@ -239,9 +247,26 @@
 		let address = pallet_common::eth::collection_id_to_address(collection_id);
 		Ok(address)
 	}
+	/// Create an NFT collection
+	/// @param name Name of the collection
+	/// @param description Informative description of the collection
+	/// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications
+	/// @return address Address of the newly created collection
+	#[weight(<SelfWeightOf<T>>::create_collection())]
+	#[deprecated(note = "mathod was renamed to `create_nft_collection`, prefer it instead")]
+	fn create_nonfungible_collection(
+		&mut self,
+		caller: caller,
+		value: value,
+		name: string,
+		description: string,
+		token_prefix: string,
+	) -> Result<address> {
+		self.create_nft_collection(caller, value, name, description, token_prefix)
+	}
 
 	#[weight(<SelfWeightOf<T>>::create_collection())]
-	#[solidity(rename_selector = "createERC721MetadataCompatibleCollection")]
+	#[solidity(rename_selector = "createERC721MetadataNFTCollection")]
 	fn create_nonfungible_collection_with_properties(
 		&mut self,
 		caller: caller,
@@ -273,6 +298,27 @@
 
 	#[weight(<SelfWeightOf<T>>::create_collection())]
 	#[solidity(rename_selector = "createRFTCollection")]
+	fn create_rft_collection(
+		&mut self,
+		caller: caller,
+		value: value,
+		name: string,
+		description: string,
+		token_prefix: string,
+	) -> Result<address> {
+		create_refungible_collection_internal::<T>(
+			caller,
+			value,
+			name,
+			description,
+			token_prefix,
+			Default::default(),
+			false,
+		)
+	}
+
+	#[weight(<SelfWeightOf<T>>::create_collection())]
+	#[deprecated(note = "mathod was renamed to `create_rft_collection`, prefer it instead")]
 	fn create_refungible_collection(
 		&mut self,
 		caller: caller,
@@ -293,7 +339,7 @@
 	}
 
 	#[weight(<SelfWeightOf<T>>::create_collection())]
-	#[solidity(rename_selector = "createERC721MetadataCompatibleRFTCollection")]
+	#[solidity(rename_selector = "createERC721MetadataRFTCollection")]
 	fn create_refungible_collection_with_properties(
 		&mut self,
 		caller: caller,
modifiedpallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth
--- a/pallets/unique/src/eth/stubs/CollectionHelpers.sol
+++ b/pallets/unique/src/eth/stubs/CollectionHelpers.sol
@@ -23,13 +23,33 @@
 }
 
 /// @title Contract, which allows users to operate with collections
-/// @dev the ERC-165 identifier for this interface is 0x5ad4f440
+/// @dev the ERC-165 identifier for this interface is 0xf62c7aa9
 contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {
 	/// Create an NFT collection
 	/// @param name Name of the collection
 	/// @param description Informative description of the collection
 	/// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications
 	/// @return address Address of the newly created collection
+	/// @dev EVM selector for this function is: 0x844af658,
+	///  or in textual repr: createNFTCollection(string,string,string)
+	function createNFTCollection(
+		string memory name,
+		string memory description,
+		string memory tokenPrefix
+	) public payable returns (address) {
+		require(false, stub_error);
+		name;
+		description;
+		tokenPrefix;
+		dummy = 0;
+		return 0x0000000000000000000000000000000000000000;
+	}
+
+	/// Create an NFT collection
+	/// @param name Name of the collection
+	/// @param description Informative description of the collection
+	/// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications
+	/// @return address Address of the newly created collection
 	/// @dev EVM selector for this function is: 0xe34a6844,
 	///  or in textual repr: createNonfungibleCollection(string,string,string)
 	function createNonfungibleCollection(
@@ -45,9 +65,9 @@
 		return 0x0000000000000000000000000000000000000000;
 	}
 
-	/// @dev EVM selector for this function is: 0xa634a5f9,
-	///  or in textual repr: createERC721MetadataCompatibleCollection(string,string,string,string)
-	function createERC721MetadataCompatibleCollection(
+	/// @dev EVM selector for this function is: 0xd1df968c,
+	///  or in textual repr: createERC721MetadataNFTCollection(string,string,string,string)
+	function createERC721MetadataNFTCollection(
 		string memory name,
 		string memory description,
 		string memory tokenPrefix,
@@ -77,9 +97,24 @@
 		return 0x0000000000000000000000000000000000000000;
 	}
 
-	/// @dev EVM selector for this function is: 0xa5596388,
-	///  or in textual repr: createERC721MetadataCompatibleRFTCollection(string,string,string,string)
-	function createERC721MetadataCompatibleRFTCollection(
+	/// @dev EVM selector for this function is: 0x44a68ad5,
+	///  or in textual repr: createRefungibleCollection(string,string,string)
+	function createRefungibleCollection(
+		string memory name,
+		string memory description,
+		string memory tokenPrefix
+	) public payable returns (address) {
+		require(false, stub_error);
+		name;
+		description;
+		tokenPrefix;
+		dummy = 0;
+		return 0x0000000000000000000000000000000000000000;
+	}
+
+	/// @dev EVM selector for this function is: 0xbea6a299,
+	///  or in textual repr: createERC721MetadataRFTCollection(string,string,string,string)
+	function createERC721MetadataRFTCollection(
 		string memory name,
 		string memory description,
 		string memory tokenPrefix,
modifiedtests/src/deprecated-helpers/eth/helpers.tsdiffbeforeafterboth
--- a/tests/src/deprecated-helpers/eth/helpers.ts
+++ b/tests/src/deprecated-helpers/eth/helpers.ts
@@ -150,10 +150,10 @@
 }
 
 
-export async function createNonfungibleCollection(api: ApiPromise, web3: Web3, owner: string) {
+export async function createNFTCollection(api: ApiPromise, web3: Web3, owner: string) {
   const collectionHelper = evmCollectionHelpers(web3, owner);
   const result = await collectionHelper.methods
-    .createNonfungibleCollection('A', 'B', 'C')
+    .createNFTCollection('A', 'B', 'C')
     .send({value: Number(2n * UNIQUE)});
   return await getCollectionAddressFromResult(api, result);
 }
modifiedtests/src/deprecated-helpers/helpers.tsdiffbeforeafterboth
--- a/tests/src/deprecated-helpers/helpers.ts
+++ b/tests/src/deprecated-helpers/helpers.ts
@@ -433,6 +433,7 @@
   mode: {type: 'NFT'},
   name: 'name',
   tokenPrefix: 'prefix',
+  properties: [{key: 'ERC721Metadata', value: '1'}],
 };
 
 export async function
@@ -441,7 +442,7 @@
   sender: IKeyringPair,
   params: Partial<CreateCollectionParams> = {},
 ): Promise<CreateCollectionResult> {
-  const {name, description, mode, tokenPrefix} = {...defaultCreateCollectionParams, ...params};
+  const {name, description, mode, tokenPrefix, properties} = {...defaultCreateCollectionParams, ...params};
 
   let modeprm = {};
   if (mode.type === 'NFT') {
@@ -457,6 +458,7 @@
     description: strToUTF16(description),
     tokenPrefix: strToUTF16(tokenPrefix),
     mode: modeprm as any,
+    properties,
   });
   const events = await executeTransaction(api, sender, tx);
   return getCreateCollectionResult(events);
modifiedtests/src/eth/allowlist.test.tsdiffbeforeafterboth
--- a/tests/src/eth/allowlist.test.ts
+++ b/tests/src/eth/allowlist.test.ts
@@ -78,7 +78,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor);
     const user = helper.eth.createAccount();
 
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
     expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
@@ -94,7 +94,7 @@
   //   const owner = await helper.eth.createAccountWithBalance(donor);
   //   const user = donor;
 
-  //   const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+  //   const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
   //   const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
   //   expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
@@ -110,7 +110,7 @@
     const notOwner = await helper.eth.createAccountWithBalance(donor);
     const user = helper.eth.createAccount();
 
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
     expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
@@ -129,7 +129,7 @@
   //   const notOwner = await helper.eth.createAccountWithBalance(donor);
   //   const user = donor;
 
-  //   const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+  //   const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
   //   const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
   //   expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
modifiedtests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth
18}18}
1919
20/// @title Contract, which allows users to operate with collections20/// @title Contract, which allows users to operate with collections
21/// @dev the ERC-165 identifier for this interface is 0x5ad4f44021/// @dev the ERC-165 identifier for this interface is 0xf62c7aa9
22interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {22interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {
23 /// Create an NFT collection23 /// Create an NFT collection
24 /// @param name Name of the collection24 /// @param name Name of the collection
25 /// @param description Informative description of the collection25 /// @param description Informative description of the collection
26 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications
27 /// @return address Address of the newly created collection
28 /// @dev EVM selector for this function is: 0x844af658,
29 /// or in textual repr: createNFTCollection(string,string,string)
30 function createNFTCollection(
31 string memory name,
32 string memory description,
33 string memory tokenPrefix
34 ) external payable returns (address);
35
36 /// Create an NFT collection
37 /// @param name Name of the collection
38 /// @param description Informative description of the collection
26 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications39 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications
27 /// @return address Address of the newly created collection40 /// @return address Address of the newly created collection
28 /// @dev EVM selector for this function is: 0xe34a6844,41 /// @dev EVM selector for this function is: 0xe34a6844,
33 string memory tokenPrefix46 string memory tokenPrefix
34 ) external payable returns (address);47 ) external payable returns (address);
3548
36 /// @dev EVM selector for this function is: 0xa634a5f9,49 /// @dev EVM selector for this function is: 0xd1df968c,
37 /// or in textual repr: createERC721MetadataCompatibleCollection(string,string,string,string)50 /// or in textual repr: createERC721MetadataNFTCollection(string,string,string,string)
38 function createERC721MetadataCompatibleCollection(51 function createERC721MetadataNFTCollection(
39 string memory name,52 string memory name,
40 string memory description,53 string memory description,
41 string memory tokenPrefix,54 string memory tokenPrefix,
50 string memory tokenPrefix63 string memory tokenPrefix
51 ) external payable returns (address);64 ) external payable returns (address);
65
66 /// @dev EVM selector for this function is: 0x44a68ad5,
67 /// or in textual repr: createRefungibleCollection(string,string,string)
68 function createRefungibleCollection(
69 string memory name,
70 string memory description,
71 string memory tokenPrefix
72 ) external payable returns (address);
5273
53 /// @dev EVM selector for this function is: 0xa5596388,74 /// @dev EVM selector for this function is: 0xbea6a299,
54 /// or in textual repr: createERC721MetadataCompatibleRFTCollection(string,string,string,string)75 /// or in textual repr: createERC721MetadataRFTCollection(string,string,string,string)
55 function createERC721MetadataCompatibleRFTCollection(76 function createERC721MetadataRFTCollection(
56 string memory name,77 string memory name,
57 string memory description,78 string memory description,
58 string memory tokenPrefix,79 string memory tokenPrefix,
modifiedtests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/eth/collectionAdmin.test.ts
+++ b/tests/src/eth/collectionAdmin.test.ts
@@ -38,7 +38,7 @@
 
   itEth('Add admin by owner', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
     const newAdmin = helper.eth.createAccount();
@@ -51,7 +51,7 @@
 
   itEth.skip('Add substrate admin by owner', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
     const [newAdmin] = await helper.arrange.createAccounts([10n], donor);
@@ -64,7 +64,7 @@
 
   itEth('Verify owner or admin', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const newAdmin = helper.eth.createAccount();
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
@@ -75,7 +75,7 @@
 
   itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const admin = await helper.eth.createAccountWithBalance(donor);
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
@@ -93,7 +93,7 @@
 
   itEth('(!negative tests!) Add admin by USER is not allowed', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const notAdmin = await helper.eth.createAccountWithBalance(donor);
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
@@ -108,7 +108,7 @@
 
   itEth.skip('(!negative tests!) Add substrate admin by ADMIN is not allowed', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const admin = await helper.eth.createAccountWithBalance(donor);
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
@@ -126,7 +126,7 @@
 
   itEth.skip('(!negative tests!) Add substrate admin by USER is not allowed', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const notAdmin0 = await helper.eth.createAccountWithBalance(donor);
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
@@ -150,7 +150,7 @@
 
   itEth('Remove admin by owner', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const newAdmin = helper.eth.createAccount();
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
@@ -170,7 +170,7 @@
 
   itEth.skip('Remove substrate admin by owner', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const [newAdmin] = await helper.arrange.createAccounts([10n], donor);
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
@@ -188,7 +188,7 @@
 
   itEth('(!negative tests!) Remove admin by ADMIN is not allowed', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
@@ -210,7 +210,7 @@
 
   itEth('(!negative tests!) Remove admin by USER is not allowed', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
@@ -230,7 +230,7 @@
 
   itEth.skip('(!negative tests!) Remove substrate admin by ADMIN is not allowed', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const [adminSub] = await helper.arrange.createAccounts([10n], donor);
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
@@ -250,7 +250,7 @@
 
   itEth.skip('(!negative tests!) Remove substrate admin by USER is not allowed', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
     const [adminSub] = await helper.arrange.createAccounts([10n], donor);
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
@@ -279,7 +279,7 @@
   itEth('Change owner', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
     const newOwner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
     await collectionEvm.methods.setOwner(newOwner).send();
@@ -291,7 +291,7 @@
   itEth('change owner call fee', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
     const newOwner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
     const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwner(newOwner).send());
     expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
@@ -301,7 +301,7 @@
   itEth('(!negative tests!) call setOwner by non owner', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
     const newOwner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
     await expect(collectionEvm.methods.setOwner(newOwner).send({from: newOwner})).to.be.rejected;
@@ -321,7 +321,7 @@
   itEth.skip('Change owner', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
     const [newOwner] = await helper.arrange.createAccounts([10n], donor);
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
     expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.true;
@@ -336,7 +336,7 @@
   itEth.skip('change owner call fee', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
     const [newOwner] = await helper.arrange.createAccounts([10n], donor);
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
     const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send());
@@ -348,7 +348,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor);
     const otherReceiver = await helper.eth.createAccountWithBalance(donor);
     const [newOwner] = await helper.arrange.createAccounts([10n], donor);
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
 
     await expect(collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send({from: otherReceiver})).to.be.rejected;
modifiedtests/src/eth/collectionHelpersAbi.jsondiffbeforeafterboth
--- a/tests/src/eth/collectionHelpersAbi.json
+++ b/tests/src/eth/collectionHelpersAbi.json
@@ -32,7 +32,7 @@
       { "internalType": "string", "name": "tokenPrefix", "type": "string" },
       { "internalType": "string", "name": "baseUri", "type": "string" }
     ],
-    "name": "createERC721MetadataCompatibleCollection",
+    "name": "createERC721MetadataNFTCollection",
     "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
     "stateMutability": "payable",
     "type": "function"
@@ -44,7 +44,18 @@
       { "internalType": "string", "name": "tokenPrefix", "type": "string" },
       { "internalType": "string", "name": "baseUri", "type": "string" }
     ],
-    "name": "createERC721MetadataCompatibleRFTCollection",
+    "name": "createERC721MetadataRFTCollection",
+    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
+    "stateMutability": "payable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      { "internalType": "string", "name": "name", "type": "string" },
+      { "internalType": "string", "name": "description", "type": "string" },
+      { "internalType": "string", "name": "tokenPrefix", "type": "string" }
+    ],
+    "name": "createNFTCollection",
     "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
     "stateMutability": "payable",
     "type": "function"
@@ -73,6 +84,17 @@
   },
   {
     "inputs": [
+      { "internalType": "string", "name": "name", "type": "string" },
+      { "internalType": "string", "name": "description", "type": "string" },
+      { "internalType": "string", "name": "tokenPrefix", "type": "string" }
+    ],
+    "name": "createRefungibleCollection",
+    "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
+    "stateMutability": "payable",
+    "type": "function"
+  },
+  {
+    "inputs": [
       {
         "internalType": "address",
         "name": "collectionAddress",
modifiedtests/src/eth/collectionProperties.test.tsdiffbeforeafterboth
--- a/tests/src/eth/collectionProperties.test.ts
+++ b/tests/src/eth/collectionProperties.test.ts
@@ -24,7 +24,7 @@
 
     const raw = (await collection.getData())?.raw;
 
-    expect(raw.properties[0].value).to.equal('testValue');
+    expect(raw.properties[1].value).to.equal('testValue');
   });
 
   itEth('Can be deleted', async({helper}) => {
@@ -54,3 +54,46 @@
     expect(value).to.equal(helper.getWeb3().utils.toHex('testValue'));
   });
 });
+
+describe('Supports ERC721Metadata', () => {
+  let donor: IKeyringPair;
+
+  before(async function() {
+    await usingEthPlaygrounds(async (_helper, privateKey) => {
+      donor = privateKey('//Alice');
+    });
+  });
+
+  itEth('ERC721Metadata property can be set for NFT collection', async({helper}) => {
+    const caller = await helper.eth.createAccountWithBalance(donor);
+    const collection = await helper.nft.mintCollection(donor, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+
+    await collection.addAdmin(donor, {Ethereum: caller});
+    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);
+
+    await contract.methods.setCollectionProperty('ERC721Metadata', Buffer.from('1')).send({from: caller});
+
+    expect(await contract.methods.supportsInterface('0x5b5e139f').call()).to.be.true;
+
+    await contract.methods.setCollectionProperty('ERC721Metadata', Buffer.from('0')).send({from: caller});
+
+    expect(await contract.methods.supportsInterface('0x5b5e139f').call()).to.be.false;
+  });
+
+  itEth('ERC721Metadata property can be set for RFT collection', async({helper}) => {
+    const caller = await helper.eth.createAccountWithBalance(donor);
+    const collection = await helper.rft.mintCollection(donor, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+
+    await collection.addAdmin(donor, {Ethereum: caller});
+
+    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);
+
+    await contract.methods.setCollectionProperty('ERC721Metadata', Buffer.from('1')).send({from: caller});
+
+    expect(await contract.methods.supportsInterface('0x5b5e139f').call()).to.be.true;
+
+    await contract.methods.setCollectionProperty('ERC721Metadata', Buffer.from('0')).send({from: caller});
+
+    expect(await contract.methods.supportsInterface('0x5b5e139f').call()).to.be.false;
+  });
+});
modifiedtests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/collectionSponsoring.test.ts
+++ b/tests/src/eth/collectionSponsoring.test.ts
@@ -54,7 +54,7 @@
   // itWeb3('Set substrate sponsor', async ({api, web3, privateKeyWrapper}) => {
   //   const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
   //   const collectionHelpers = evmCollectionHelpers(web3, owner);
-  //   let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
+  //   let result = await collectionHelpers.methods.createNFTCollection('Sponsor collection', '1', '1').send();
   //   const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
   //   const sponsor = privateKeyWrapper('//Alice');
   //   const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
@@ -75,7 +75,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor);
     const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
 
-    let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});
+    let result = await collectionHelpers.methods.createNFTCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});
     const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
     const sponsor = await helper.eth.createAccountWithBalance(donor);
     const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);
@@ -97,7 +97,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor);
     const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
 
-    let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});
+    let result = await collectionHelpers.methods.createERC721MetadataNFTCollection('Sponsor collection', '1', '1', '').send({value: Number(2n * nominal)});
     const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
     const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);
     const collection = helper.nft.getCollectionObject(collectionId);
@@ -167,7 +167,7 @@
   // itWeb3('Sponsoring collection from substrate address via access list', async ({api, web3, privateKeyWrapper}) => {
   //   const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
   //   const collectionHelpers = evmCollectionHelpers(web3, owner);
-  //   const result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
+  //   const result = await collectionHelpers.methods.createERC721MetadataNFTCollection('Sponsor collection', '1', '1', '').send();
   //   const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
   //   const sponsor = privateKeyWrapper('//Alice');
   //   const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
@@ -223,7 +223,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor);
     const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
 
-    let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});
+    let result = await collectionHelpers.methods.createERC721MetadataNFTCollection('Sponsor collection', '1', '1', '').send({value: Number(2n * nominal)});
     const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
     const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);
     const collection = helper.nft.getCollectionObject(collectionId);
modifiedtests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createNFTCollection.test.ts
+++ b/tests/src/eth/createNFTCollection.test.ts
@@ -37,7 +37,7 @@
 
     // todo:playgrounds this might fail when in async environment.
     const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;
-    const {collectionId} = await helper.eth.createNonfungibleCollection(owner, name, description, prefix);
+    const {collectionId} = await helper.eth.createNFTCollection(owner, name, description, prefix);
     const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;
 
     const collection = helper.nft.getCollectionObject(collectionId);
@@ -64,7 +64,7 @@
       .call()).to.be.false;
 
     await collectionHelpers.methods
-      .createNonfungibleCollection('A', 'A', 'A')
+      .createNFTCollection('A', 'A', 'A')
       .send({value: Number(2n * helper.balance.getOneTokenNominal())});
     
     expect(await collectionHelpers.methods
@@ -76,7 +76,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor);
     const sponsor = await helper.eth.createAccountWithBalance(donor);
     const ss58Format = helper.chain.getChainProperties().ss58Format;
-    const {collectionId, collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');
+    const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');
 
     const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
     await collection.methods.setCollectionSponsor(sponsor).send();
@@ -95,7 +95,7 @@
 
   itEth('Set limits', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionId, collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Limits', 'absolutely anything', 'FLO');
+    const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'FLO');
     const limits = {
       accountTokenOwnershipLimit: 1000,
       sponsoredDataSize: 1024,
@@ -138,7 +138,7 @@
       .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())
       .to.be.false;
     
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Exister', 'absolutely anything', 'EVC');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Exister', 'absolutely anything', 'EVC');
     expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)
       .methods.isCollectionExist(collectionAddress).call())
       .to.be.true;
@@ -166,7 +166,7 @@
       const tokenPrefix = 'A';
 
       await expect(collectionHelper.methods
-        .createNonfungibleCollection(collectionName, description, tokenPrefix)
+        .createNFTCollection(collectionName, description, tokenPrefix)
         .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);
       
     }
@@ -176,7 +176,7 @@
       const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);
       const tokenPrefix = 'A';
       await expect(collectionHelper.methods
-        .createNonfungibleCollection(collectionName, description, tokenPrefix)
+        .createNFTCollection(collectionName, description, tokenPrefix)
         .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);
     }
     {
@@ -185,7 +185,7 @@
       const description = 'A';
       const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);
       await expect(collectionHelper.methods
-        .createNonfungibleCollection(collectionName, description, tokenPrefix)
+        .createNFTCollection(collectionName, description, tokenPrefix)
         .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);
     }
   });
@@ -194,14 +194,14 @@
     const owner = await helper.eth.createAccountWithBalance(donor);
     const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
     await expect(collectionHelper.methods
-      .createNonfungibleCollection('Peasantry', 'absolutely anything', 'CVE')
+      .createNFTCollection('Peasantry', 'absolutely anything', 'CVE')
       .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');
   });
 
   itEth('(!negative test!) Check owner', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
     const malfeasant = helper.eth.createAccount();
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Transgressed', 'absolutely anything', 'COR');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Transgressed', 'absolutely anything', 'COR');
     const malfeasantCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant);
     const EXPECTED_ERROR = 'NoPermission';
     {
@@ -224,7 +224,7 @@
 
   itEth('(!negative test!) Set limits', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Limits', 'absolutely anything', 'OLF');
+    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
     await expect(collectionEvm.methods
       .setCollectionLimit('badLimit', 'true')
modifiedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -39,7 +39,7 @@
   
     // todo:playgrounds this might fail when in async environment.
     const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;
-    const {collectionId} = await helper.eth.createRefungibleCollection(owner, name, description, prefix);
+    const {collectionId} = await helper.eth.createRFTCollection(owner, name, description, prefix);
     const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;
   
     const data = (await helper.rft.getData(collectionId))!;
@@ -77,7 +77,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor);
     const sponsor = await helper.eth.createAccountWithBalance(donor);
     const ss58Format = helper.chain.getChainProperties().ss58Format;
-    const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');
+    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');
 
     const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
     await collection.methods.setCollectionSponsor(sponsor).send();
@@ -96,7 +96,7 @@
 
   itEth('Set limits', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Limits', 'absolutely anything', 'INSI');
+    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'INSI');
     const limits = {
       accountTokenOwnershipLimit: 1000,
       sponsoredDataSize: 1024,
@@ -139,7 +139,7 @@
       .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())
       .to.be.false;
     
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Exister', 'absolutely anything', 'WIWT');
+    const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Exister', 'absolutely anything', 'WIWT');
     expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)
       .methods.isCollectionExist(collectionAddress).call())
       .to.be.true;
@@ -202,7 +202,7 @@
   itEth('(!negative test!) Check owner', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
     const peasant = helper.eth.createAccount();
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');
+    const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');
     const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant);
     const EXPECTED_ERROR = 'NoPermission';
     {
@@ -225,7 +225,7 @@
 
   itEth('(!negative test!) Set limits', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Limits', 'absolutely anything', 'ISNI');
+    const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'ISNI');
     const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
     await expect(collectionEvm.methods
       .setCollectionLimit('badLimit', 'true')
modifiedtests/src/eth/evmCoder.test.tsdiffbeforeafterboth
--- a/tests/src/eth/evmCoder.test.ts
+++ b/tests/src/eth/evmCoder.test.ts
@@ -65,7 +65,7 @@
   
   itEth('Call non-existing function', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const collection = await helper.eth.createNonfungibleCollection(owner, 'EVMCODER', '', 'TEST');
+    const collection = await helper.eth.createNFTCollection(owner, 'EVMCODER', '', 'TEST');
     const contract = await helper.ethContract.deployByCode(owner, 'Test', getContractSource(collection.collectionAddress, '0x1bfed5D614b886b9Ab2eA4CBAc22A96B7EC29c9c'));
     const testContract = await helper.ethContract.deployByCode(owner, 'Test', getContractSource(collection.collectionAddress, contract.options.address));
     {
modifiedtests/src/eth/fractionalizer/fractionalizer.test.tsdiffbeforeafterboth
--- a/tests/src/eth/fractionalizer/fractionalizer.test.ts
+++ b/tests/src/eth/fractionalizer/fractionalizer.test.ts
@@ -62,7 +62,7 @@
 const mintRFTToken = async (helper: EthUniqueHelper, owner: string, fractionalizer: Contract, amount: bigint): Promise<{
   nftCollectionAddress: string, nftTokenId: number, rftTokenAddress: string
 }> => {
-  const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');
+  const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');
   const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);
   const nftTokenId = await nftContract.methods.nextTokenId().call();
   await nftContract.methods.mint(owner, nftTokenId).send({from: owner});
@@ -92,7 +92,7 @@
   itEth('Set RFT collection', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor, 10n);
     const fractionalizer = await deployContract(helper, owner);
-    const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');
+    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');
     const rftContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);
 
     await rftContract.methods.addCollectionAdmin(fractionalizer.options.address).send({from: owner});
@@ -121,7 +121,7 @@
   itEth('Set Allowlist', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
     const {contract: fractionalizer} = await initContract(helper, owner);
-    const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');
+    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');
 
     const result1 = await fractionalizer.methods.setNftCollectionIsAllowed(nftCollection.collectionAddress, true).send({from: owner});
     expect(result1.events).to.be.like({
@@ -146,7 +146,7 @@
   itEth('NFT to RFT', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
 
-    const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');
+    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');
     const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);
     const nftTokenId = await nftContract.methods.nextTokenId().call();
     await nftContract.methods.mint(owner, nftTokenId).send({from: owner});
@@ -231,7 +231,7 @@
 
   itEth('call setRFTCollection twice', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
-    const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');
+    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');
     const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);
 
     const fractionalizer = await deployContract(helper, owner);
@@ -244,7 +244,7 @@
 
   itEth('call setRFTCollection with NFT collection', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
-    const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');
+    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');
     const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);
 
     const fractionalizer = await deployContract(helper, owner);
@@ -257,7 +257,7 @@
   itEth('call setRFTCollection while not collection admin', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
     const fractionalizer = await deployContract(helper, owner);
-    const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');
+    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');
 
     await expect(fractionalizer.methods.setRFTCollection(rftCollection.collectionAddress).call())
       .to.be.rejectedWith(/Fractionalizer contract should be an admin of the collection$/g);
@@ -278,7 +278,7 @@
   itEth('call nft2rft without setting RFT collection for contract', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
 
-    const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');
+    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');
     const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);
     const nftTokenId = await nftContract.methods.nextTokenId().call();
     await nftContract.methods.mint(owner, nftTokenId).send({from: owner});
@@ -293,7 +293,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
     const nftOwner = await helper.eth.createAccountWithBalance(donor, 10n);
 
-    const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');
+    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');
     const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);
     const nftTokenId = await nftContract.methods.nextTokenId().call();
     await nftContract.methods.mint(owner, nftTokenId).send({from: owner});
@@ -310,7 +310,7 @@
   itEth('call nft2rft while not in list of allowed accounts', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
 
-    const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');
+    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');
     const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);
     const nftTokenId = await nftContract.methods.nextTokenId().call();
     await nftContract.methods.mint(owner, nftTokenId).send({from: owner});
@@ -325,7 +325,7 @@
   itEth('call nft2rft while fractionalizer doesnt have approval for nft token', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
 
-    const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');
+    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');
     const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);
     const nftTokenId = await nftContract.methods.nextTokenId().call();
     await nftContract.methods.mint(owner, nftTokenId).send({from: owner});
@@ -341,7 +341,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
 
     const fractionalizer = await deployContract(helper, owner);
-    const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');
+    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');
     const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);
     const rftTokenId = await refungibleContract.methods.nextTokenId().call();
     await refungibleContract.methods.mint(owner, rftTokenId).send({from: owner});
@@ -354,7 +354,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
 
     const {contract: fractionalizer} = await initContract(helper, owner);
-    const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');
+    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');
     const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);
     const rftTokenId = await refungibleContract.methods.nextTokenId().call();
     await refungibleContract.methods.mint(owner, rftTokenId).send({from: owner});
@@ -365,7 +365,7 @@
 
   itEth('call rft2nft for RFT token that was not minted by fractionalizer contract', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor, 20n);
-    const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');
+    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');
     const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);
 
     const fractionalizer = await deployContract(helper, owner);
@@ -432,7 +432,7 @@
     await fractionalizer.methods.setRFTCollection(rftCollectionAddress).send({from: owner});
     await helper.executeExtrinsic(donor, 'api.tx.unique.setTransfersEnabledFlag', [rftCollection.collectionId, false], true);
 
-    const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');
+    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');
     const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);
     const nftTokenId = await nftContract.methods.nextTokenId().call();
     await nftContract.methods.mint(owner, nftTokenId).send({from: owner});
modifiedtests/src/eth/nesting/nest.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nesting/nest.test.ts
+++ b/tests/src/eth/nesting/nest.test.ts
@@ -7,7 +7,7 @@
   helper: EthUniqueHelper,
   owner: string,
 ): Promise<{ collectionId: number, collectionAddress: string, contract: Contract }> => {
-  const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+  const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
 
   const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
   await contract.methods.setCollectionNesting(true).send({from: owner});
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -84,7 +84,7 @@
     const receiver = helper.eth.createAccount();
 
     const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
-    let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * helper.balance.getOneTokenNominal())});
+    let result = await collectionHelper.methods.createERC721MetadataNFTCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * helper.balance.getOneTokenNominal())});
     const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
     const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
     
@@ -146,7 +146,7 @@
     const owner = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
 
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Minty', '6', '6');
+    const {collectionAddress} = await helper.eth.createERC721MetadataNFTCollection(owner, 'Mint collection', '6', '6', '');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
     const nextTokenId = await contract.methods.nextTokenId().call();
 
modifiedtests/src/eth/payable.test.tsdiffbeforeafterboth
--- a/tests/src/eth/payable.test.ts
+++ b/tests/src/eth/payable.test.ts
@@ -146,7 +146,7 @@
     const caller = await helper.eth.createAccountWithBalance(donor);
     const contract = await deployProxyContract(helper, deployer);
 
-    const collectionAddress = (await contract.methods.createNonfungibleCollection().send({from: caller, value: Number(CONTRACT_BALANCE)})).events.CollectionCreated.returnValues.collection;
+    const collectionAddress = (await contract.methods.createNFTCollection().send({from: caller, value: Number(CONTRACT_BALANCE)})).events.CollectionCreated.returnValues.collection;
     const initialCallerBalance = await helper.balance.getEthereum(caller);
     const initialContractBalance = await helper.balance.getEthereum(contract.options.address);
     await contract.methods.mintNftToken(collectionAddress).send({from: caller});
@@ -164,7 +164,7 @@
 
     const initialCallerBalance = await helper.balance.getEthereum(caller);
     const initialContractBalance = await helper.balance.getEthereum(contract.options.address);
-    await contract.methods.createNonfungibleCollection().send({from: caller, value: Number(CONTRACT_BALANCE)});
+    await contract.methods.createNFTCollection().send({from: caller, value: Number(CONTRACT_BALANCE)});
     const finalCallerBalance = await helper.balance.getEthereum(caller);
     const finalContractBalance = await helper.balance.getEthereum(contract.options.address);
     expect(finalCallerBalance < initialCallerBalance).to.be.true;
@@ -177,8 +177,8 @@
     const caller = await helper.eth.createAccountWithBalance(donor);
     const collectionHelper = helper.ethNativeContract.collectionHelpers(caller);
         
-    await expect(collectionHelper.methods.createNonfungibleCollection('A', 'B', 'C').call({value: Number(SMALL_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');
-    await expect(collectionHelper.methods.createNonfungibleCollection('A', 'B', 'C').call({value: Number(BIG_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');
+    await expect(collectionHelper.methods.createNFTCollection('A', 'B', 'C').call({value: Number(SMALL_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');
+    await expect(collectionHelper.methods.createNFTCollection('A', 'B', 'C').call({value: Number(BIG_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');
   });
 
   itEth('Negative test: call createRFTCollection with wrong fee', async({helper}) => {
@@ -227,9 +227,9 @@
           InnerContract(innerContract).flip();
         }
 
-        function createNonfungibleCollection() external payable {
+        function createNFTCollection() external payable {
           address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;
-		      address nftCollection = CollectionHelpers(collectionHelpers).createNonfungibleCollection{value: msg.value}("A", "B", "C");
+		      address nftCollection = CollectionHelpers(collectionHelpers).createNFTCollection{value: msg.value}("A", "B", "C");
           emit CollectionCreated(nftCollection);
         }
 
modifiedtests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth
--- a/tests/src/eth/proxy/nonFungibleProxy.test.ts
+++ b/tests/src/eth/proxy/nonFungibleProxy.test.ts
@@ -101,7 +101,7 @@
 
   itEth('Can perform mint()', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'A', 'A');
+    const {collectionAddress} = await helper.eth.createERC721MetadataNFTCollection(owner, 'A', 'A', 'A', '');
     const caller = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
 
modifiedtests/src/eth/reFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/reFungible.test.ts
+++ b/tests/src/eth/reFungible.test.ts
@@ -31,7 +31,7 @@
 
   itEth('totalSupply', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'TotalSupply', '6', '6');
+    const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'TotalSupply', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
     const nextTokenId = await contract.methods.nextTokenId().call();
     await contract.methods.mint(caller, nextTokenId).send();
@@ -41,7 +41,7 @@
 
   itEth('balanceOf', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'BalanceOf', '6', '6');
+    const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'BalanceOf', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     {
@@ -63,7 +63,7 @@
 
   itEth('ownerOf', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'OwnerOf', '6', '6');
+    const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -76,7 +76,7 @@
   itEth('ownerOf after burn', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
-    const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'OwnerOf-AfterBurn', '6', '6');
+    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf-AfterBurn', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -95,7 +95,7 @@
   itEth('ownerOf for partial ownership', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
-    const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Partial-OwnerOf', '6', '6');
+    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Partial-OwnerOf', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -124,7 +124,7 @@
   itEth('Can perform mint()', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Minty', '6', '6');
+    const {collectionAddress} = await helper.eth.createERC721MetadataRFTCollection(owner, 'Minty', '6', '6', '');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
     
     const nextTokenId = await contract.methods.nextTokenId().call();
@@ -147,7 +147,7 @@
   itEth('Can perform mintBulk()', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'MintBulky', '6', '6');
+    const {collectionAddress} = await helper.eth.createERC721MetadataRFTCollection(owner, 'MintBulky', '6', '6', '');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
 
     {
@@ -179,7 +179,7 @@
 
   itEth('Can perform burn()', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Burny', '6', '6');
+    const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Burny', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -197,7 +197,7 @@
   itEth('Can perform transferFrom()', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
-    const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'TransferFromy', '6', '6');
+    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'TransferFromy', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -241,7 +241,7 @@
   itEth('Can perform transfer()', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry', '6', '6');
+    const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -271,7 +271,7 @@
   itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
-    const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry-Partial-to-Full', '6', '6');
+    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry-Partial-to-Full', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -298,7 +298,7 @@
   itEth('transfer event on transfer from full ownership to partial ownership', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
-    const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry-Full-to-Partial', '6', '6');
+    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry-Full-to-Partial', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -336,7 +336,7 @@
   itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Feeful-Transfer-From', '6', '6');
+    const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Feeful-Transfer-From', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -350,7 +350,7 @@
   itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
     const receiver = helper.eth.createAccount();
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Feeful-Transfer', '6', '6');
+    const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Feeful-Transfer', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -386,8 +386,8 @@
 
   itEth('Returns symbol name', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
-    const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Leviathan', '', '12');
-    const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
+    const {collectionId} = await helper.rft.mintCollection(alice, {name: 'Leviathan', tokenPrefix: '12'});
+    const contract = helper.ethNativeContract.collectionById(collectionId, 'rft', caller);
     const symbol = await contract.methods.symbol().call();
     expect(symbol).to.equal('12');
   });
modifiedtests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth
--- a/tests/src/eth/reFungibleToken.test.ts
+++ b/tests/src/eth/reFungibleToken.test.ts
@@ -81,7 +81,7 @@
     const receiver = helper.eth.createAccount();
 
     const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
-    let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * helper.balance.getOneTokenNominal())});
+    let result = await collectionHelper.methods.createERC721MetadataNFTCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * helper.balance.getOneTokenNominal())});
     const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
     
@@ -294,7 +294,7 @@
   itEth('Receiving Transfer event on burning into full ownership', async ({helper}) => {
     const caller = await helper.eth.createAccountWithBalance(donor);
     const receiver = await helper.eth.createAccountWithBalance(donor);
-    const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Devastation', '6', '6');
+    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Devastation', '6', '6');
     const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);
 
     const tokenId = await contract.methods.nextTokenId().call();
@@ -479,7 +479,7 @@
   itEth('Default parent token address and id', async ({helper}) => {
     const owner = await helper.eth.createAccountWithBalance(donor);
 
-    const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Sands', '', 'GRAIN');
+    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sands', '', 'GRAIN');
     const collectionContract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
     
     const tokenId = await collectionContract.methods.nextTokenId().call();
modifiedtests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth
--- a/tests/src/eth/util/playgrounds/unique.dev.ts
+++ b/tests/src/eth/util/playgrounds/unique.dev.ts
@@ -174,11 +174,23 @@
     return await this.helper.callRpc('api.rpc.eth.call', [{from: signer, to: contractAddress, data: abi}]);
   }
 
-  async createNonfungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {
+  async createNFTCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {
     const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();
     const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);
         
-    const result = await collectionHelper.methods.createNonfungibleCollection(name, description, tokenPrefix).send({value: Number(collectionCreationPrice)});
+    const result = await collectionHelper.methods.createNFTCollection(name, description, tokenPrefix).send({value: Number(collectionCreationPrice)});
+
+    const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
+    const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);
+
+    return {collectionId, collectionAddress};
+  }
+
+  async createERC721MetadataNFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string}> {
+    const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();
+    const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);
+        
+    const result = await collectionHelper.methods.createERC721MetadataNFTCollection(name, description, tokenPrefix, baseUri).send({value: Number(collectionCreationPrice)});
 
     const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
     const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);
@@ -186,7 +198,7 @@
     return {collectionId, collectionAddress};
   }
 
-  async createRefungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {
+  async createRFTCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {
     const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();
     const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);
         
@@ -198,6 +210,18 @@
     return {collectionId, collectionAddress};
   }
 
+  async createERC721MetadataRFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string}> {
+    const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();
+    const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);
+        
+    const result = await collectionHelper.methods.createERC721MetadataRFTCollection(name, description, tokenPrefix, baseUri).send({value: Number(collectionCreationPrice)});
+
+    const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
+    const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);
+
+    return {collectionId, collectionAddress};
+  }
+
   async deployCollectorContract(signer: string): Promise<Contract> {
     return await this.helper.ethContract.deployByCode(signer, 'Collector', `
     // SPDX-License-Identifier: UNLICENSED
modifiedtests/src/nesting/properties.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/properties.test.ts
+++ b/tests/src/nesting/properties.test.ts
@@ -18,6 +18,52 @@
 import {itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds, expect} from '../util/playgrounds';
 import {UniqueHelper, UniqueBaseCollection, UniqueNFTCollection, UniqueNFToken, UniqueRFTCollection, UniqueRFToken} from '../util/playgrounds/unique';
 
+
+describe('Composite Properties Test', () => {
+  let alice: IKeyringPair;
+
+  before(async () => {
+    await usingPlaygrounds(async (helper, privateKey) => {
+      const donor = privateKey('//Alice');
+      [alice] = await helper.arrange.createAccounts([50n], donor);
+    });
+  });
+
+  async function testMakeSureSuppliesRequired(baseCollection: UniqueNFTCollection | UniqueRFTCollection) {
+
+    const collectionOption = await baseCollection.getOptions();
+    expect(collectionOption).is.not.null;
+    let collection = collectionOption;
+    expect(collection.tokenPropertyPermissions).to.be.empty;
+    expect(collection.properties).to.be.deep.equal([{key: 'ERC721Metadata', value: '1'}]);
+
+    const propertyPermissions = [
+      {key: 'mindgame', permission: {collectionAdmin: true, mutable: false, tokenOwner: true}},
+      {key: 'skullduggery', permission: {collectionAdmin: false, mutable: true, tokenOwner: false}},
+    ];
+    await expect(await baseCollection.setTokenPropertyPermissions(alice, propertyPermissions)).to.be.true;
+
+    const collectionProperties = [
+      {key: 'ERC721Metadata', value: '1'}, 
+      {key: 'black_hole', value: 'LIGO'},
+      {key: 'electron', value: 'come bond'}, 
+    ];
+    
+    await expect(await baseCollection.setProperties(alice, collectionProperties)).to.be.true;
+
+    collection = await baseCollection.getOptions();
+    expect(collection.tokenPropertyPermissions).to.be.deep.equal(propertyPermissions);
+    expect(collection.properties).to.be.deep.equal(collectionProperties);
+  }
+
+  itSub('Makes sure collectionById supplies required fields for NFT',  async ({helper}) => {
+    await testMakeSureSuppliesRequired(await helper.nft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}));
+  });
+
+  itSub.ifWithPallets('Makes sure collectionById supplies required fields for ReFungible', [Pallets.ReFungible],  async ({helper}) => {
+    await testMakeSureSuppliesRequired(await helper.rft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}));
+  });
+});
 // ---------- COLLECTION PROPERTIES
 
 describe('Integration Test: Collection Properties', () => {
@@ -33,7 +79,11 @@
 
   itSub('Properties are initially empty', async ({helper}) => {
     const collection = await helper.nft.mintCollection(alice);
-    expect(await collection.getProperties()).to.be.empty;
+    const properties = await collection.getProperties();
+    expect(properties).to.be.deep.equal([{
+      'key': 'ERC721Metadata',
+      'value': '1',
+    }]);
   });
 
   async function testSetsPropertiesForCollection(collection: UniqueBaseCollection) {
@@ -150,7 +200,11 @@
     await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))
       .to.be.rejectedWith(/common\.NoPermission/);
 
-    expect(await collection.getProperties()).to.be.empty;
+    const properties = await collection.getProperties();
+    expect(properties).to.be.deep.equal([{
+      'key': 'ERC721Metadata',
+      'value': '1',
+    }]);
   }
 
   itSub('Fails to set properties in a NFT collection if not its onwer/administrator', async ({helper}) =>  {
@@ -202,7 +256,11 @@
     await expect(collection.setProperties(alice, propertiesToBeSet)).
       to.be.rejectedWith(/common\.PropertyLimitReached/);
 
-    expect(await collection.getProperties()).to.be.empty;
+    const properties = await collection.getProperties();
+    expect(properties).to.be.deep.equal([{
+      'key': 'ERC721Metadata',
+      'value': '1',
+    }]);
   }
 
   itSub('Fails to set more properties than it is allowed (NFT)', async ({helper}) =>  {
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -981,6 +981,10 @@
     return (await this.helper.callRpc('api.rpc.unique.collectionProperties', [collectionId, propertyKeys])).toHuman();
   }
 
+  async getCollectionOptions(collectionId: number) {
+    return (await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId])).toHuman();
+  }
+
   /**
    * Deletes onchain properties from the collection.
    *
@@ -1293,6 +1297,7 @@
   async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT'): Promise<UniqueBaseCollection> {
     collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object
     collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};
+    collectionOptions.properties = collectionOptions.properties || [{key: 'ERC721Metadata', value: '1'}];
     for (const key of ['name', 'description', 'tokenPrefix']) {
       if (typeof collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] === 'string') collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] = this.helper.util.str2vec(collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] as string);
     }
@@ -2476,6 +2481,10 @@
     return await this.helper.collection.getTokenNextSponsored(this.collectionId, tokenId, addressObj);
   }
 
+  async getOptions() {
+    return await this.helper.collection.getCollectionOptions(this.collectionId);
+  }
+
   async setSponsor(signer: TSigner, sponsorAddress: TSubstrateAccount) {
     return await this.helper.collection.setSponsor(signer, this.collectionId, sponsorAddress);
   }