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

difftreelog

Merge branch 'feature/pallet-structure-rebased' of https://github.com/UniqueNetwork/unique-chain into feature/pallet-structure-rebased

Fahrrader2022-05-19parents: #547ee7a #aa4cd0e.patch.diff
in: master

68 files changed

modified.maintain/scripts/generate_api.shdiffbeforeafterboth
--- a/.maintain/scripts/generate_api.sh
+++ b/.maintain/scripts/generate_api.sh
@@ -7,6 +7,5 @@
 sed -n '/=== SNIP START ===/, /=== SNIP END ===/{ /=== SNIP START ===/! { /=== SNIP END ===/! p } }' $tmp > $raw
 formatted=$(mktemp)
 prettier --use-tabs $raw > $formatted
-solhint --fix $formatted
 
 mv $formatted $OUTPUT
modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6391,6 +6391,7 @@
  "sp-core",
  "sp-runtime",
  "sp-std",
+ "struct-versioning",
  "up-data-structs",
 ]
 
@@ -6508,6 +6509,7 @@
  "sp-core",
  "sp-runtime",
  "sp-std",
+ "struct-versioning",
  "up-data-structs",
 ]
 
modifiedclient/rpc/src/lib.rsdiffbeforeafterboth
--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -30,8 +30,8 @@
 // RMRK
 use rmrk_rpc::RmrkApi as RmrkRuntimeApi;
 use up_data_structs::{
-	RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild,
-	RmrkThemeName, RmrkPropertyKey, RmrkResourceId
+	RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName, RmrkPropertyKey,
+	RmrkResourceId,
 };
 
 pub use rmrk_unique_rpc::RmrkApi;
@@ -75,13 +75,6 @@
 	) -> Result<Option<CrossAccountId>>;
 	#[rpc(name = "unique_constMetadata")]
 	fn const_metadata(
-		&self,
-		collection: CollectionId,
-		token: TokenId,
-		at: Option<BlockHash>,
-	) -> Result<Vec<u8>>;
-	#[rpc(name = "unique_variableMetadata")]
-	fn variable_metadata(
 		&self,
 		collection: CollectionId,
 		token: TokenId,
@@ -92,7 +85,7 @@
 	fn collection_properties(
 		&self,
 		collection: CollectionId,
-		keys: Vec<String>,
+		keys: Option<Vec<String>>,
 		at: Option<BlockHash>,
 	) -> Result<Vec<Property>>;
 
@@ -101,7 +94,7 @@
 		&self,
 		collection: CollectionId,
 		token_id: TokenId,
-		properties: Vec<String>,
+		keys: Option<Vec<String>>,
 		at: Option<BlockHash>,
 	) -> Result<Vec<Property>>;
 
@@ -109,7 +102,7 @@
 	fn property_permissions(
 		&self,
 		collection: CollectionId,
-		keys: Vec<String>,
+		keys: Option<Vec<String>>,
 		at: Option<BlockHash>,
 	) -> Result<Vec<PropertyKeyPermission>>;
 
@@ -118,7 +111,7 @@
 		&self,
 		collection: CollectionId,
 		token_id: TokenId,
-		keys: Vec<String>,
+		keys: Option<Vec<String>>,
 		at: Option<BlockHash>,
 	) -> Result<TokenData<CrossAccountId>>;
 
@@ -428,10 +421,6 @@
 	);
 	pass_method!(
 		const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>, unique_api
-	);
-	pass_method!(
-		variable_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>,
-		unique_api
 	);
 	pass_method!(total_supply(collection: CollectionId) -> u32, unique_api);
 	pass_method!(account_balance(collection: CollectionId, account: CrossAccountId) -> u32, unique_api);
@@ -445,7 +434,7 @@
 		collection: CollectionId,
 
 		#[map(|keys| string_keys_to_bytes_keys(keys))]
-		keys: Vec<String>
+		keys: Option<Vec<String>>
 	) -> Vec<Property>, unique_api);
 
 	pass_method!(token_properties(
@@ -453,14 +442,14 @@
 		token_id: TokenId,
 
 		#[map(|keys| string_keys_to_bytes_keys(keys))]
-		properties: Vec<String>
+		keys: Option<Vec<String>>
 	) -> Vec<Property>, unique_api);
 
 	pass_method!(property_permissions(
 		collection: CollectionId,
 
 		#[map(|keys| string_keys_to_bytes_keys(keys))]
-		keys: Vec<String>
+		keys: Option<Vec<String>>
 	) -> Vec<PropertyKeyPermission>, unique_api);
 
 	pass_method!(token_data(
@@ -468,7 +457,7 @@
 		token_id: TokenId,
 
 		#[map(|keys| string_keys_to_bytes_keys(keys))]
-		keys: Vec<String>,
+		keys: Option<Vec<String>>,
 	) -> TokenData<CrossAccountId>, unique_api);
 
 	pass_method!(adminlist(collection: CollectionId) -> Vec<CrossAccountId>, unique_api);
@@ -549,6 +538,6 @@
 	pass_method!(theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Option<Theme>, rmrk_api);
 }
 
-fn string_keys_to_bytes_keys(keys: Vec<String>) -> Vec<Vec<u8>> {
-	keys.into_iter().map(|key| key.into_bytes()).collect()
+fn string_keys_to_bytes_keys(keys: Option<Vec<String>>) -> Option<Vec<Vec<u8>>> {
+	keys.map(|keys| keys.into_iter().map(|key| key.into_bytes()).collect())
 }
modifiednode/cli/src/service.rsdiffbeforeafterboth
--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -65,25 +65,12 @@
 use fc_rpc_core::types::FilterPool;
 use fc_mapping_sync::{MappingSyncWorker, SyncStrategy};
 
-use unique_runtime_common::types::{
-	AuraId,
-	RuntimeInstance,
-	AccountId,
-	Balance,
-	Index,
-	Hash,
-	Block,
-};
+use unique_runtime_common::types::{AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block};
 
 // RMRK
 use up_data_structs::{
-	RmrkCollectionInfo,
-	RmrkInstanceInfo,
-	RmrkResourceInfo,
-	RmrkPropertyInfo,
-	RmrkBaseInfo,
-	RmrkPartType,
-	RmrkTheme,
+	RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo, RmrkBaseInfo,
+	RmrkPartType, RmrkTheme,
 };
 
 /// Unique native executor instance.
modifiednode/rpc/src/lib.rsdiffbeforeafterboth
--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -41,17 +41,12 @@
 use std::{collections::BTreeMap, sync::Arc};
 
 use unique_runtime_common::types::{
-	Hash,
-	AccountId,
-	RuntimeInstance,
-	Index,
-	Block,
-	BlockNumber,
-	Balance,
+	Hash, AccountId, RuntimeInstance, Index, Block, BlockNumber, Balance,
 };
 // RMRK
 use up_data_structs::{
-	RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo, RmrkBaseInfo, RmrkPartType, RmrkTheme, 
+	RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo, RmrkBaseInfo,
+	RmrkPartType, RmrkTheme,
 };
 
 /// Public io handler for exporting into other modules
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -21,7 +21,7 @@
 use sp_std::vec::Vec;
 use up_data_structs::Property;
 
-use crate::{Pallet, CollectionHandle, Config};
+use crate::{Pallet, CollectionHandle, Config, CollectionProperties};
 
 /// Does not always represent a full collection, for RFT it is either
 /// collection (Implementing ERC721), or specific collection token (Implementing ERC20)
@@ -33,24 +33,35 @@
 
 #[solidity_interface(name = "CollectionProperties")]
 impl<T: Config> CollectionHandle<T> {
-	fn set_property(&mut self, caller: caller, key: string, value: string) -> Result<()> {
-		<Pallet<T>>::set_collection_property(
-			self,
-			&T::CrossAccountId::from_eth(caller),
-			Property {
-				key: <Vec<u8>>::from(key)
-					.try_into()
-					.map_err(|_| "key too large")?,
-				value: <Vec<u8>>::from(value)
-					.try_into()
-					.map_err(|_| "value too large")?,
-			},
-		)
-		.map_err(dispatch_to_evm::<T>)?;
-		Ok(())
+	fn set_collection_property(&mut self, caller: caller, key: string, value: bytes) -> Result<()> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let key = <Vec<u8>>::from(key)
+			.try_into()
+			.map_err(|_| "key too large")?;
+		let value = value.try_into().map_err(|_| "value too large")?;
+
+		<Pallet<T>>::set_collection_property(self, &caller, Property { key, value })
+			.map_err(dispatch_to_evm::<T>)
 	}
 
-	fn delete_property(&mut self, caller: caller, key: string) -> Result<()> {
-		self.set_property(caller, key, string::new())
+	fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let key = <Vec<u8>>::from(key)
+			.try_into()
+			.map_err(|_| "key too large")?;
+
+		<Pallet<T>>::delete_collection_property(self, &caller, key).map_err(dispatch_to_evm::<T>)
+	}
+
+	/// Throws error if key not found
+	fn collection_property(&self, key: string) -> Result<bytes> {
+		let key = <Vec<u8>>::from(key)
+			.try_into()
+			.map_err(|_| "key too large")?;
+
+		let props = <CollectionProperties<T>>::get(self.id);
+		let prop = props.get(&key).ok_or("key not found")?;
+
+		Ok(prop.to_vec())
 	}
 }
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -22,23 +22,56 @@
 use pallet_evm::account::CrossAccountId;
 use frame_support::{
 	dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, Weight, PostDispatchInfo},
-	ensure, fail,
+	ensure,
 	traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement},
 	BoundedVec,
 	weights::Pays,
+	transactional,
 };
 use pallet_evm::GasWeightMapping;
 use up_data_structs::{
-	COLLECTION_NUMBER_LIMIT, Collection, RpcCollection, CollectionId, CreateItemData,
-	MAX_TOKEN_PREFIX_LENGTH, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, TokenId,
-	CollectionStats, MAX_TOKEN_OWNERSHIP, CollectionMode, NFT_SPONSOR_TRANSFER_TIMEOUT,
-	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT,
-	CUSTOM_DATA_LIMIT, CollectionLimits, CustomDataLimit, CreateCollectionData, SponsorshipState,
-	CreateItemExData, SponsoringRateLimit, budget::Budget, COLLECTION_FIELD_LIMIT, CollectionField,
-	PhantomType, Property, Properties, PropertiesPermissionMap, PropertyKey, PropertyPermission,
-	PropertiesError, PropertyKeyPermission, TokenData, TrySet,
+	COLLECTION_NUMBER_LIMIT,
+	Collection,
+	RpcCollection,
+	CollectionId,
+	CreateItemData,
+	MAX_TOKEN_PREFIX_LENGTH,
+	COLLECTION_ADMINS_LIMIT,
+	TokenId,
+	CollectionStats,
+	MAX_TOKEN_OWNERSHIP,
+	CollectionMode,
+	NFT_SPONSOR_TRANSFER_TIMEOUT,
+	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+	REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+	MAX_SPONSOR_TIMEOUT,
+	CUSTOM_DATA_LIMIT,
+	CollectionLimits,
+	CreateCollectionData,
+	SponsorshipState,
+	CreateItemExData,
+	SponsoringRateLimit,
+	budget::Budget,
+	COLLECTION_FIELD_LIMIT,
+	CollectionField,
+	PhantomType,
+	Property,
+	Properties,
+	PropertiesPermissionMap,
+	PropertyKey,
+	PropertyPermission,
+	PropertiesError,
+	PropertyKeyPermission,
+	TokenData,
+	TrySetProperty,
 	// RMRK
-	RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo, RmrkBaseInfo, RmrkPartType, RmrkTheme,
+	RmrkCollectionInfo,
+	RmrkInstanceInfo,
+	RmrkResourceInfo,
+	RmrkPropertyInfo,
+	RmrkBaseInfo,
+	RmrkPartType,
+	RmrkTheme,
 	RmrkNftChild,
 };
 
@@ -138,21 +171,6 @@
 			<Error<T>>::AddressNotInAllowlist
 		);
 		Ok(())
-	}
-
-	pub fn check_can_update_meta(
-		&self,
-		subject: &T::CrossAccountId,
-		item_owner: &T::CrossAccountId,
-	) -> DispatchResult {
-		match self.meta_update_permission {
-			MetaUpdatePermission::ItemOwner => {
-				ensure!(subject == item_owner, <Error<T>>::NoPermission);
-				Ok(())
-			}
-			MetaUpdatePermission::Admin => self.check_is_owner_or_admin(subject),
-			MetaUpdatePermission::None => fail!(<Error<T>>::NoPermission),
-		}
 	}
 }
 
@@ -316,8 +334,6 @@
 		CollectionTokenPrefixLimitExceeded,
 		/// Total collections bound exceeded.
 		TotalCollectionsLimitExceeded,
-		/// variable_data exceeded data limit.
-		TokenVariableDataLimitExceeded,
 		/// Exceeded max admin count
 		CollectionAdminCountExceeded,
 		/// Collection limit bounds per collection exceeded
@@ -366,8 +382,8 @@
 		/// Tried to store more property keys than allowed
 		PropertyLimitReached,
 
-		/// Unable to read array of unbounded keys
-		UnableToReadUnboundedKeys,
+		/// Property key is too long
+		PropertyKeyIsTooLong,
 
 		/// Only ASCII letters, digits, and '_', '-' are allowed
 		InvalidCharacterInPropertyKey,
@@ -580,7 +596,6 @@
 			schema_version,
 			sponsorship,
 			limits,
-			meta_update_permission,
 		} = <CollectionById<T>>::get(collection)?;
 
 		let token_property_permissions = <CollectionPropertyPermissions<T>>::get(collection)
@@ -610,7 +625,6 @@
 			schema_version,
 			sponsorship,
 			limits,
-			meta_update_permission,
 			offchain_schema: <CollectionData<T>>::get((
 				collection,
 				CollectionField::OffchainSchema,
@@ -671,7 +685,6 @@
 				.limits
 				.map(|limits| Self::clamp_limits(data.mode.clone(), &Default::default(), limits))
 				.unwrap_or_else(|| Ok(CollectionLimits::default()))?,
-			meta_update_permission: data.meta_update_permission.unwrap_or_default(),
 		};
 
 		let mut collection_properties = up_data_structs::CollectionProperties::get();
@@ -775,6 +788,7 @@
 		Ok(())
 	}
 
+	#[transactional]
 	pub fn set_collection_properties(
 		collection: &CollectionHandle<T>,
 		sender: &T::CrossAccountId,
@@ -807,6 +821,7 @@
 		Ok(())
 	}
 
+	#[transactional]
 	pub fn delete_collection_properties(
 		collection: &CollectionHandle<T>,
 		sender: &T::CrossAccountId,
@@ -849,6 +864,7 @@
 		Ok(())
 	}
 
+	#[transactional]
 	pub fn set_property_permissions(
 		collection: &CollectionHandle<T>,
 		sender: &T::CrossAccountId,
@@ -867,60 +883,69 @@
 		keys.into_iter()
 			.map(|key| -> Result<PropertyKey, DispatchError> {
 				key.try_into()
-					.map_err(|_| <Error<T>>::UnableToReadUnboundedKeys.into())
+					.map_err(|_| <Error<T>>::PropertyKeyIsTooLong.into())
 			})
 			.collect::<Result<Vec<PropertyKey>, DispatchError>>()
-	}
-
-	pub fn check_property_key(key: &PropertyKey) -> Result<(), DispatchError> {
-		let key_str = sp_std::str::from_utf8(key.as_slice())
-			.map_err(|_| <Error<T>>::InvalidCharacterInPropertyKey)?;
-
-		for ch in key_str.chars() {
-			if !ch.is_ascii_alphanumeric() && ch != '_' && ch != '-' {
-				return Err(<Error<T>>::InvalidCharacterInPropertyKey.into());
-			}
-		}
-
-		Ok(())
 	}
 
 	pub fn filter_collection_properties(
 		collection_id: CollectionId,
-		keys: Vec<PropertyKey>,
+		keys: Option<Vec<PropertyKey>>,
 	) -> Result<Vec<Property>, DispatchError> {
 		let properties = Self::collection_properties(collection_id);
 
 		let properties = keys
-			.into_iter()
-			.filter_map(|key| {
-				properties.get(&key).map(|value| Property {
-					key,
-					value: value.clone(),
-				})
+			.map(|keys| {
+				keys.into_iter()
+					.filter_map(|key| {
+						properties.get(&key).map(|value| Property {
+							key,
+							value: value.clone(),
+						})
+					})
+					.collect()
 			})
-			.collect();
+			.unwrap_or_else(|| {
+				properties
+					.iter()
+					.map(|(key, value)| Property {
+						key: key.clone(),
+						value: value.clone(),
+					})
+					.collect()
+			});
 
 		Ok(properties)
 	}
 
 	pub fn filter_property_permissions(
 		collection_id: CollectionId,
-		keys: Vec<PropertyKey>,
+		keys: Option<Vec<PropertyKey>>,
 	) -> Result<Vec<PropertyKeyPermission>, DispatchError> {
 		let permissions = Self::property_permissions(collection_id);
 
 		let key_permissions = keys
-			.into_iter()
-			.filter_map(|key| {
+			.map(|keys| {
+				keys.into_iter()
+					.filter_map(|key| {
+						permissions
+							.get(&key)
+							.map(|permission| PropertyKeyPermission {
+								key,
+								permission: permission.clone(),
+							})
+					})
+					.collect()
+			})
+			.unwrap_or_else(|| {
 				permissions
-					.get(&key)
-					.map(|permission| PropertyKeyPermission {
-						key,
+					.iter()
+					.map(|(key, permission)| PropertyKeyPermission {
+						key: key.clone(),
 						permission: permission.clone(),
 					})
-			})
-			.collect();
+					.collect()
+			});
 
 		Ok(key_permissions)
 	}
@@ -1086,7 +1111,6 @@
 	fn approve() -> Weight;
 	fn transfer_from() -> Weight;
 	fn burn_from() -> Weight;
-	fn set_variable_metadata(bytes: u32) -> Weight;
 }
 
 pub trait CommonCollectionOperations<T: Config> {
@@ -1174,13 +1198,6 @@
 		token: TokenId,
 		amount: u128,
 		nesting_budget: &dyn Budget,
-	) -> DispatchResultWithPostInfo;
-
-	fn set_variable_metadata(
-		&self,
-		sender: T::CrossAccountId,
-		token: TokenId,
-		data: BoundedVec<u8, CustomDataLimit>,
 	) -> DispatchResultWithPostInfo;
 
 	fn check_nesting(
@@ -1198,8 +1215,7 @@
 
 	fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;
 	fn const_metadata(&self, token: TokenId) -> Vec<u8>;
-	fn variable_metadata(&self, token: TokenId) -> Vec<u8>;
-	fn token_properties(&self, token_id: TokenId, keys: Vec<PropertyKey>) -> Vec<Property>;
+	fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property>;
 	/// Amount of unique collection tokens
 	fn total_supply(&self) -> u32;
 	/// Amount of different tokens account has (Applicable to nonfungible/refungible)
@@ -1232,6 +1248,7 @@
 			PropertiesError::NoSpaceForProperty => Self::NoSpaceForProperty,
 			PropertiesError::PropertyLimitReached => Self::PropertyLimitReached,
 			PropertiesError::InvalidCharacterInPropertyKey => Self::InvalidCharacterInPropertyKey,
+			PropertiesError::PropertyKeyIsTooLong => Self::PropertyKeyIsTooLong,
 			PropertiesError::EmptyPropertyKey => Self::EmptyPropertyKey,
 		}
 	}
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -16,12 +16,12 @@
 
 use core::marker::PhantomData;
 
-use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};
+use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
 use up_data_structs::{TokenId, CollectionId, CreateItemExData, budget::Budget};
 use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
 use sp_runtime::ArithmeticError;
 use sp_std::{vec::Vec, vec};
-use up_data_structs::{CustomDataLimit, Property, PropertyKey, PropertyKeyPermission};
+use up_data_structs::{Property, PropertyKey, PropertyKeyPermission};
 
 use crate::{
 	Allowance, Balance, Config, Error, FungibleHandle, Pallet, SelfWeightOf, weights::WeightInfo,
@@ -84,11 +84,6 @@
 
 	fn burn_from() -> Weight {
 		<SelfWeightOf<T>>::burn_from()
-	}
-
-	fn set_variable_metadata(_bytes: u32) -> Weight {
-		// Error
-		0
 	}
 }
 
@@ -287,15 +282,6 @@
 		fail!(<Error<T>>::SettingPropertiesNotAllowed)
 	}
 
-	fn set_variable_metadata(
-		&self,
-		_sender: T::CrossAccountId,
-		_token: TokenId,
-		_data: BoundedVec<u8, CustomDataLimit>,
-	) -> DispatchResultWithPostInfo {
-		fail!(<Error<T>>::FungibleItemsDontHaveData)
-	}
-
 	fn check_nesting(
 		&self,
 		_sender: <T>::CrossAccountId,
@@ -330,13 +316,14 @@
 		None
 	}
 	fn const_metadata(&self, _token: TokenId) -> Vec<u8> {
-		Vec::new()
-	}
-	fn variable_metadata(&self, _token: TokenId) -> Vec<u8> {
 		Vec::new()
 	}
 
-	fn token_properties(&self, _token_id: TokenId, _keys: Vec<PropertyKey>) -> Vec<Property> {
+	fn token_properties(
+		&self,
+		_token_id: TokenId,
+		_keys: Option<Vec<PropertyKey>>,
+	) -> Vec<Property> {
 		Vec::new()
 	}
 
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
@@ -8,8 +8,13 @@
 	uint8 dummy;
 	string stub_error = "this contract is implemented in native";
 }
+
 contract ERC165 is Dummy {
-	function supportsInterface(bytes4 interfaceID) external view returns (bool) {
+	function supportsInterface(bytes4 interfaceID)
+		external
+		view
+		returns (bool)
+	{
 		require(false, stub_error);
 		interfaceID;
 		return true;
@@ -19,24 +24,11 @@
 // Inline
 contract ERC20Events {
 	event Transfer(address indexed from, address indexed to, uint256 value);
-	event Approval(address indexed owner, address indexed spender, uint256 value);
-}
-
-// Selector: 56fd500b
-contract CollectionProperties is Dummy, ERC165 {
-	// Selector: setProperty(string,string) 62d9491f
-	function setProperty(string memory key, string memory value) public {
-		require(false, stub_error);
-		key;
-		value;
-		dummy = 0;
-	}
-	// Selector: deleteProperty(string) 34241914
-	function deleteProperty(string memory key) public {
-		require(false, stub_error);
-		key;
-		dummy = 0;
-	}
+	event Approval(
+		address indexed owner,
+		address indexed spender,
+		uint256 value
+	);
 }
 
 // Selector: 79cc6790
@@ -59,24 +51,28 @@
 		dummy;
 		return "";
 	}
+
 	// Selector: symbol() 95d89b41
 	function symbol() public view returns (string memory) {
 		require(false, stub_error);
 		dummy;
 		return "";
 	}
+
 	// Selector: totalSupply() 18160ddd
 	function totalSupply() public view returns (uint256) {
 		require(false, stub_error);
 		dummy;
 		return 0;
 	}
+
 	// Selector: decimals() 313ce567
 	function decimals() public view returns (uint8) {
 		require(false, stub_error);
 		dummy;
 		return 0;
 	}
+
 	// Selector: balanceOf(address) 70a08231
 	function balanceOf(address owner) public view returns (uint256) {
 		require(false, stub_error);
@@ -84,6 +80,7 @@
 		dummy;
 		return 0;
 	}
+
 	// Selector: transfer(address,uint256) a9059cbb
 	function transfer(address to, uint256 amount) public returns (bool) {
 		require(false, stub_error);
@@ -92,8 +89,13 @@
 		dummy = 0;
 		return false;
 	}
+
 	// Selector: transferFrom(address,address,uint256) 23b872dd
-	function transferFrom(address from, address to, uint256 amount) public returns (bool) {
+	function transferFrom(
+		address from,
+		address to,
+		uint256 amount
+	) public returns (bool) {
 		require(false, stub_error);
 		from;
 		to;
@@ -101,6 +103,7 @@
 		dummy = 0;
 		return false;
 	}
+
 	// Selector: approve(address,uint256) 095ea7b3
 	function approve(address spender, uint256 amount) public returns (bool) {
 		require(false, stub_error);
@@ -109,8 +112,13 @@
 		dummy = 0;
 		return false;
 	}
+
 	// Selector: allowance(address,address) dd62ed3e
-	function allowance(address owner, address spender) public view returns (uint256) {
+	function allowance(address owner, address spender)
+		public
+		view
+		returns (uint256)
+	{
 		require(false, stub_error);
 		owner;
 		spender;
@@ -119,6 +127,44 @@
 	}
 }
 
-contract UniqueFungible is Dummy, ERC165, ERC20, ERC20UniqueExtensions, CollectionProperties {
+// Selector: 9b5e29c5
+contract CollectionProperties is Dummy, ERC165 {
+	// Selector: setCollectionProperty(string,bytes) 2f073f66
+	function setCollectionProperty(string memory key, bytes memory value)
+		public
+	{
+		require(false, stub_error);
+		key;
+		value;
+		dummy = 0;
+	}
+
+	// Selector: deleteCollectionProperty(string) 7b7debce
+	function deleteCollectionProperty(string memory key) public {
+		require(false, stub_error);
+		key;
+		dummy = 0;
+	}
+
+	// Throws error if key not found
+	//
+	// Selector: collectionProperty(string) cf24fd6d
+	function collectionProperty(string memory key)
+		public
+		view
+		returns (bytes memory)
+	{
+		require(false, stub_error);
+		key;
+		dummy;
+		return hex"";
+	}
 }
 
+contract UniqueFungible is
+	Dummy,
+	ERC165,
+	ERC20,
+	ERC20UniqueExtensions,
+	CollectionProperties
+{}
modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/nonfungible/Cargo.toml
+++ b/pallets/nonfungible/Cargo.toml
@@ -27,6 +27,7 @@
 scale-info = { version = "2.0.1", default-features = false, features = [
     "derive",
 ] }
+struct-versioning = { path = "../../crates/struct-versioning" }
 
 [features]
 default = ["std"]
modifiedpallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -28,12 +28,7 @@
 
 fn create_max_item_data<T: Config>(owner: T::CrossAccountId) -> CreateItemData<T> {
 	let const_data = create_data::<CUSTOM_DATA_LIMIT>();
-	let variable_data = create_data::<CUSTOM_DATA_LIMIT>();
-	CreateItemData::<T> {
-		const_data,
-		variable_data,
-		owner,
-	}
+	CreateItemData::<T> { const_data, owner }
 }
 fn create_max_item<T: Config>(
 	collection: &NonfungibleHandle<T>,
@@ -125,14 +120,4 @@
 		let item = create_max_item(&collection, &owner, sender.clone())?;
 		<Pallet<T>>::set_allowance(&collection, &sender, item, Some(&burner))?;
 	}: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, &Unlimited)?}
-
-	set_variable_metadata {
-		let b in 0..CUSTOM_DATA_LIMIT;
-		bench_init!{
-			owner: sub; collection: collection(owner);
-			owner: cross_from_sub; sender: cross_sub;
-		};
-		let item = create_max_item(&collection, &owner, sender.clone())?;
-		let data = create_var_data(b).try_into().unwrap();
-	}: {<Pallet<T>>::set_variable_metadata(&collection, &sender, item, data)?}
 }
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -16,10 +16,10 @@
 
 use core::marker::PhantomData;
 
-use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};
+use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
 use up_data_structs::{
-	TokenId, CustomDataLimit, CreateItemExData, CollectionId, budget::Budget, Property,
-	PropertyKey, PropertyKeyPermission,
+	TokenId, CreateItemExData, CollectionId, budget::Budget, Property, PropertyKey,
+	PropertyKeyPermission,
 };
 use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
 use sp_runtime::DispatchError;
@@ -86,10 +86,6 @@
 	fn burn_from() -> Weight {
 		<SelfWeightOf<T>>::burn_from()
 	}
-
-	fn set_variable_metadata(bytes: u32) -> Weight {
-		<SelfWeightOf<T>>::set_variable_metadata(bytes)
-	}
 }
 
 fn map_create_data<T: Config>(
@@ -99,7 +95,6 @@
 	match data {
 		up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {
 			const_data: data.const_data,
-			variable_data: data.variable_data,
 			properties: data.properties,
 			owner: to.clone(),
 		}),
@@ -184,7 +179,7 @@
 		let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);
 
 		with_weight(
-			<Pallet<T>>::delete_collection_properties(self, &sender, property_keys),
+			<Pallet<T>>::delete_collection_properties(self, sender, property_keys),
 			weight,
 		)
 	}
@@ -327,19 +322,6 @@
 		}
 	}
 
-	fn set_variable_metadata(
-		&self,
-		sender: T::CrossAccountId,
-		token: TokenId,
-		data: BoundedVec<u8, CustomDataLimit>,
-	) -> DispatchResultWithPostInfo {
-		let len = data.len();
-		with_weight(
-			<Pallet<T>>::set_variable_metadata(self, &sender, token, data),
-			<CommonWeights<T>>::set_variable_metadata(len as u32),
-		)
-	}
-
 	fn check_nesting(
 		&self,
 		sender: T::CrossAccountId,
@@ -379,24 +361,29 @@
 			.unwrap_or_default()
 			.into_inner()
 	}
-	fn variable_metadata(&self, token: TokenId) -> Vec<u8> {
-		<TokenData<T>>::get((self.id, token))
-			.map(|t| t.variable_data)
-			.unwrap_or_default()
-			.into_inner()
-	}
 
-	fn token_properties(&self, token_id: TokenId, keys: Vec<PropertyKey>) -> Vec<Property> {
+	fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property> {
 		let properties = <Pallet<T>>::token_properties((self.id, token_id));
 
-		keys.into_iter()
-			.filter_map(|key| {
-				properties.get(&key).map(|value| Property {
-					key,
+		keys.map(|keys| {
+			keys.into_iter()
+				.filter_map(|key| {
+					properties.get(&key).map(|value| Property {
+						key,
+						value: value.clone(),
+					})
+				})
+				.collect()
+		})
+		.unwrap_or_else(|| {
+			properties
+				.iter()
+				.map(|(key, value)| Property {
+					key: key.clone(),
 					value: value.clone(),
 				})
-			})
-			.collect()
+				.collect()
+		})
 	}
 
 	fn total_supply(&self) -> u32 {
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -21,10 +21,10 @@
 };
 use evm_coder::{ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};
 use frame_support::BoundedVec;
-use up_data_structs::{TokenId, SchemaVersion};
+use up_data_structs::{TokenId, SchemaVersion, PropertyPermission, PropertyKeyPermission, Property};
 use pallet_evm_coder_substrate::dispatch_to_evm;
 use sp_core::{H160, U256};
-use sp_std::{vec::Vec, vec};
+use sp_std::vec::Vec;
 use pallet_common::{
 	erc::{CommonEvmHandler, PrecompileResult, CollectionPropertiesCall},
 	CollectionHandle,
@@ -35,9 +35,80 @@
 
 use crate::{
 	AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,
-	SelfWeightOf, weights::WeightInfo,
+	SelfWeightOf, weights::WeightInfo, TokenProperties,
 };
 
+#[solidity_interface(name = "TokenProperties")]
+impl<T: Config> NonfungibleHandle<T> {
+	fn set_token_property_permission(
+		&mut self,
+		caller: caller,
+		key: string,
+		is_mutable: bool,
+		collection_admin: bool,
+		token_owner: bool,
+	) -> Result<()> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		<Pallet<T>>::set_property_permission(
+			self,
+			&caller,
+			PropertyKeyPermission {
+				key: <Vec<u8>>::from(key)
+					.try_into()
+					.map_err(|_| "too long key")?,
+				permission: PropertyPermission {
+					mutable: is_mutable,
+					collection_admin,
+					token_owner,
+				},
+			},
+		)
+		.map_err(dispatch_to_evm::<T>)
+	}
+
+	fn set_property(
+		&mut self,
+		caller: caller,
+		token_id: uint256,
+		key: string,
+		value: bytes,
+	) -> Result<()> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
+		let key = <Vec<u8>>::from(key)
+			.try_into()
+			.map_err(|_| "key too long")?;
+		let value = value.try_into().map_err(|_| "value too long")?;
+
+		<Pallet<T>>::set_token_property(self, &caller, TokenId(token_id), Property { key, value })
+			.map_err(dispatch_to_evm::<T>)
+	}
+
+	fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
+		let key = <Vec<u8>>::from(key)
+			.try_into()
+			.map_err(|_| "key too long")?;
+
+		<Pallet<T>>::delete_token_property(self, &caller, TokenId(token_id), key)
+			.map_err(dispatch_to_evm::<T>)
+	}
+
+	/// Throws error if key not found
+	fn property(&self, token_id: uint256, key: string) -> Result<bytes> {
+		let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
+		let key = <Vec<u8>>::from(key)
+			.try_into()
+			.map_err(|_| "key too long")?;
+
+		let props = <TokenProperties<T>>::get((self.id, token_id));
+		let prop = props.get(&key).ok_or("key not found")?;
+
+		Ok(prop.to_vec())
+	}
+}
+
 fn error_unsupported_schema_version() -> Error {
 	alloc::format!(
 		"Unsupported schema version! Support only {:?}",
@@ -274,7 +345,6 @@
 			&caller,
 			CreateItemData::<T> {
 				const_data: BoundedVec::default(),
-				variable_data: BoundedVec::default(),
 				properties: BoundedVec::default(),
 				owner: to,
 			},
@@ -322,7 +392,6 @@
 				const_data: Vec::<u8>::from(token_uri)
 					.try_into()
 					.map_err(|_| "token uri is too long")?,
-				variable_data: BoundedVec::default(),
 				properties: BoundedVec::default(),
 				owner: to,
 			},
@@ -387,37 +456,6 @@
 			.into())
 	}
 
-	#[weight(<SelfWeightOf<T>>::set_variable_metadata(data.len() as u32))]
-	fn set_variable_metadata(
-		&mut self,
-		caller: caller,
-		token_id: uint256,
-		data: bytes,
-	) -> Result<void> {
-		let caller = T::CrossAccountId::from_eth(caller);
-		let token = token_id.try_into()?;
-
-		<Pallet<T>>::set_variable_metadata(
-			self,
-			&caller,
-			token,
-			data.try_into()
-				.map_err(|_| "metadata size exceeded limit")?,
-		)
-		.map_err(dispatch_to_evm::<T>)?;
-		Ok(())
-	}
-
-	fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {
-		self.consume_store_reads(1)?;
-		let token: TokenId = token_id.try_into()?;
-
-		Ok(<TokenData<T>>::get((self.id, token))
-			.ok_or("token not found")?
-			.variable_data
-			.into_inner())
-	}
-
 	#[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]
 	fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {
 		let caller = T::CrossAccountId::from_eth(caller);
@@ -440,7 +478,6 @@
 		let data = (0..total_tokens)
 			.map(|_| CreateItemData::<T> {
 				const_data: BoundedVec::default(),
-				variable_data: BoundedVec::default(),
 				properties: BoundedVec::default(),
 				owner: to.clone(),
 			})
@@ -484,7 +521,6 @@
 				const_data: Vec::<u8>::from(token_uri)
 					.try_into()
 					.map_err(|_| "token uri is too long")?,
-				variable_data: vec![].try_into().unwrap(),
 				properties: BoundedVec::default(),
 				owner: to.clone(),
 			});
@@ -505,7 +541,8 @@
 		ERC721UniqueExtensions,
 		ERC721Mintable,
 		ERC721Burnable,
-		via("CollectionHandle<T>", common_mut, CollectionProperties)
+		via("CollectionHandle<T>", common_mut, CollectionProperties),
+		TokenProperties,
 	)
 )]
 impl<T: Config> NonfungibleHandle<T> {}
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -18,11 +18,11 @@
 
 use erc::ERC721Events;
 use evm_coder::ToLog;
-use frame_support::{BoundedVec, ensure, fail};
+use frame_support::{BoundedVec, ensure, fail, transactional};
 use up_data_structs::{
 	AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData, CreateNftExData,
 	mapping::TokenAddressMapping, NestingRule, budget::Budget, Property, PropertyPermission,
-	PropertyKey, PropertyKeyPermission, Properties, TrySet,
+	PropertyKey, PropertyKeyPermission, Properties, TrySetProperty,
 };
 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
 use pallet_common::{
@@ -49,17 +49,24 @@
 pub type CreateItemData<T> = CreateNftExData<<T as pallet_evm::account::Config>::CrossAccountId>;
 pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
 
+#[struct_versioning::versioned(version = 2, upper)]
 #[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]
 pub struct ItemData<CrossAccountId> {
 	pub const_data: BoundedVec<u8, CustomDataLimit>,
+
+	#[version(..2)]
 	pub variable_data: BoundedVec<u8, CustomDataLimit>,
+
 	pub owner: CrossAccountId,
 }
 
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
-	use frame_support::{Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};
+	use frame_support::{
+		Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key, traits::StorageVersion,
+	};
+	use frame_system::pallet_prelude::*;
 	use up_data_structs::{CollectionId, TokenId};
 	use super::weights::WeightInfo;
 
@@ -78,7 +85,10 @@
 		type WeightInfo: WeightInfo;
 	}
 
+	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
+
 	#[pallet::pallet]
+	#[pallet::storage_version(STORAGE_VERSION)]
 	#[pallet::generate_store(pub(super) trait Store)]
 	pub struct Pallet<T>(_);
 
@@ -133,6 +143,19 @@
 		Value = T::CrossAccountId,
 		QueryKind = OptionQuery,
 	>;
+
+	#[pallet::hooks]
+	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
+		fn on_runtime_upgrade() -> Weight {
+			if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {
+				<TokenData<T>>::translate_values::<ItemDataVersion1<T::CrossAccountId>, _>(|v| {
+					Some(<ItemDataVersion2<T::CrossAccountId>>::from(v))
+				})
+			}
+
+			0
+		}
+	}
 }
 
 pub struct NonfungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);
@@ -286,6 +309,7 @@
 		Ok(())
 	}
 
+	#[transactional]
 	pub fn set_token_properties(
 		collection: &NonfungibleHandle<T>,
 		sender: &T::CrossAccountId,
@@ -329,8 +353,8 @@
 	) -> DispatchResult {
 		let permission = <PalletCommon<T>>::property_permissions(collection.id)
 			.get(property_key)
-			.map(|p| p.clone())
-			.unwrap_or(PropertyPermission::none());
+			.cloned()
+			.unwrap_or_else(PropertyPermission::none);
 
 		let token_data = <TokenData<T>>::get((collection.id, token_id))
 			.ok_or(<CommonError<T>>::TokenNotFound)?;
@@ -369,6 +393,7 @@
 		}
 	}
 
+	#[transactional]
 	pub fn delete_token_properties(
 		collection: &NonfungibleHandle<T>,
 		sender: &T::CrossAccountId,
@@ -406,6 +431,14 @@
 		<PalletCommon<T>>::set_property_permissions(collection, sender, property_permissions)
 	}
 
+	pub fn set_property_permission(
+		collection: &CollectionHandle<T>,
+		sender: &T::CrossAccountId,
+		permission: PropertyKeyPermission,
+	) -> DispatchResult {
+		<PalletCommon<T>>::set_property_permission(collection, sender, permission)
+	}
+
 	pub fn transfer(
 		collection: &NonfungibleHandle<T>,
 		from: &T::CrossAccountId,
@@ -577,7 +610,6 @@
 				(collection.id, token),
 				ItemData {
 					const_data: data.const_data,
-					variable_data: data.variable_data,
 					owner: data.owner.clone(),
 				},
 			);
@@ -773,28 +805,6 @@
 		// =========
 
 		Self::burn(collection, from, token)
-	}
-
-	pub fn set_variable_metadata(
-		collection: &NonfungibleHandle<T>,
-		sender: &T::CrossAccountId,
-		token: TokenId,
-		data: BoundedVec<u8, CustomDataLimit>,
-	) -> DispatchResult {
-		let token_data =
-			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
-		collection.check_can_update_meta(sender, &token_data.owner)?;
-
-		// =========
-
-		<TokenData<T>>::insert(
-			(collection.id, token),
-			ItemData {
-				variable_data: data,
-				..token_data
-			},
-		);
-		Ok(())
 	}
 
 	pub fn check_nesting(
modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -51,6 +51,60 @@
 	event MintingFinished();
 }
 
+// Selector: 41369377
+contract TokenProperties is Dummy, ERC165 {
+	// Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
+	function setTokenPropertyPermission(
+		string memory key,
+		bool isMutable,
+		bool collectionAdmin,
+		bool tokenOwner
+	) public {
+		require(false, stub_error);
+		key;
+		isMutable;
+		collectionAdmin;
+		tokenOwner;
+		dummy = 0;
+	}
+
+	// Selector: setProperty(uint256,string,bytes) 1752d67b
+	function setProperty(
+		uint256 tokenId,
+		string memory key,
+		bytes memory value
+	) public {
+		require(false, stub_error);
+		tokenId;
+		key;
+		value;
+		dummy = 0;
+	}
+
+	// Selector: deleteProperty(uint256,string) 066111d1
+	function deleteProperty(uint256 tokenId, string memory key) public {
+		require(false, stub_error);
+		tokenId;
+		key;
+		dummy = 0;
+	}
+
+	// Throws error if key not found
+	//
+	// Selector: property(uint256,string) 7228c327
+	function property(uint256 tokenId, string memory key)
+		public
+		view
+		returns (bytes memory)
+	{
+		require(false, stub_error);
+		tokenId;
+		key;
+		dummy;
+		return hex"";
+	}
+}
+
 // Selector: 42966c68
 contract ERC721Burnable is Dummy, ERC165 {
 	// Selector: burn(uint256) 42966c68
@@ -276,7 +330,41 @@
 	}
 }
 
-// Selector: e562194d
+// Selector: 9b5e29c5
+contract CollectionProperties is Dummy, ERC165 {
+	// Selector: setCollectionProperty(string,bytes) 2f073f66
+	function setCollectionProperty(string memory key, bytes memory value)
+		public
+	{
+		require(false, stub_error);
+		key;
+		value;
+		dummy = 0;
+	}
+
+	// Selector: deleteCollectionProperty(string) 7b7debce
+	function deleteCollectionProperty(string memory key) public {
+		require(false, stub_error);
+		key;
+		dummy = 0;
+	}
+
+	// Throws error if key not found
+	//
+	// Selector: collectionProperty(string) cf24fd6d
+	function collectionProperty(string memory key)
+		public
+		view
+		returns (bytes memory)
+	{
+		require(false, stub_error);
+		key;
+		dummy;
+		return hex"";
+	}
+}
+
+// Selector: d74d154f
 contract ERC721UniqueExtensions is Dummy, ERC165 {
 	// Selector: transfer(address,uint256) a9059cbb
 	function transfer(address to, uint256 tokenId) public {
@@ -299,26 +387,6 @@
 		require(false, stub_error);
 		dummy;
 		return 0;
-	}
-
-	// Selector: setVariableMetadata(uint256,bytes) d4eac26d
-	function setVariableMetadata(uint256 tokenId, bytes memory data) public {
-		require(false, stub_error);
-		tokenId;
-		data;
-		dummy = 0;
-	}
-
-	// Selector: getVariableMetadata(uint256) e6c5ce6f
-	function getVariableMetadata(uint256 tokenId)
-		public
-		view
-		returns (bytes memory)
-	{
-		require(false, stub_error);
-		tokenId;
-		dummy;
-		return hex"";
 	}
 
 	// Selector: mintBulk(address,uint256[]) 44a9945e
@@ -354,5 +422,7 @@
 	ERC721Enumerable,
 	ERC721UniqueExtensions,
 	ERC721Mintable,
-	ERC721Burnable
+	ERC721Burnable,
+	CollectionProperties,
+	TokenProperties
 {}
modifiedpallets/nonfungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/weights.rs
+++ b/pallets/nonfungible/src/weights.rs
@@ -45,7 +45,6 @@
 	fn approve() -> Weight;
 	fn transfer_from() -> Weight;
 	fn burn_from() -> Weight;
-	fn set_variable_metadata(b: u32, ) -> Weight;
 }
 
 /// Weights for pallet_nonfungible using the Substrate node and recommended hardware.
@@ -155,12 +154,6 @@
 		(27_580_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(4 as Weight))
 			.saturating_add(T::DbWeight::get().writes(5 as Weight))
-	}
-	// Storage: Nonfungible TokenData (r:1 w:1)
-	fn set_variable_metadata(_b: u32, ) -> Weight {
-		(7_700_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
 }
 
@@ -270,11 +263,5 @@
 		(27_580_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(4 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(5 as Weight))
-	}
-	// Storage: Nonfungible TokenData (r:1 w:1)
-	fn set_variable_metadata(_b: u32, ) -> Weight {
-		(7_700_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
 }
modifiedpallets/refungible/Cargo.tomldiffbeforeafterboth
--- a/pallets/refungible/Cargo.toml
+++ b/pallets/refungible/Cargo.toml
@@ -24,6 +24,7 @@
 scale-info = { version = "2.0.1", default-features = false, features = [
     "derive",
 ] }
+struct-versioning = { path = "../../crates/struct-versioning" }
 
 [features]
 default = ["std"]
modifiedpallets/refungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -31,10 +31,8 @@
 	users: impl IntoIterator<Item = (CrossAccountId, u128)>,
 ) -> CreateRefungibleExData<CrossAccountId> {
 	let const_data = create_data::<CUSTOM_DATA_LIMIT>();
-	let variable_data = create_data::<CUSTOM_DATA_LIMIT>();
 	CreateRefungibleExData {
 		const_data,
-		variable_data,
 		users: users
 			.into_iter()
 			.collect::<BTreeMap<_, _>>()
@@ -203,14 +201,4 @@
 		let item = create_max_item(&collection, &owner, [(sender.clone(), 200)])?;
 		<Pallet<T>>::set_allowance(&collection, &sender, &burner, item, 200)?;
 	}: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, 200, &Unlimited)?}
-
-	set_variable_metadata {
-		let b in 0..CUSTOM_DATA_LIMIT;
-		bench_init!{
-			owner: sub; collection: collection(owner);
-			sender: cross_from_sub(owner);
-		};
-		let item = create_max_item(&collection, &sender, [(sender.clone(), 200)])?;
-		let data = create_var_data(b).try_into().unwrap();
-	}: {<Pallet<T>>::set_variable_metadata(&collection, &sender, item, data)?}
 }
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -17,10 +17,10 @@
 use core::marker::PhantomData;
 
 use sp_std::collections::btree_map::BTreeMap;
-use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight, BoundedVec};
+use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight};
 use up_data_structs::{
-	CollectionId, TokenId, CustomDataLimit, CreateItemExData, CreateRefungibleExData,
-	budget::Budget, Property, PropertyKey, PropertyKeyPermission,
+	CollectionId, TokenId, CreateItemExData, CreateRefungibleExData, budget::Budget, Property,
+	PropertyKey, PropertyKeyPermission,
 };
 use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
 use sp_runtime::DispatchError;
@@ -110,10 +110,6 @@
 
 	fn burn_from() -> Weight {
 		<SelfWeightOf<T>>::burn_from()
-	}
-
-	fn set_variable_metadata(bytes: u32) -> Weight {
-		<SelfWeightOf<T>>::set_variable_metadata(bytes)
 	}
 }
 
@@ -124,7 +120,6 @@
 	match data {
 		up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateRefungibleExData {
 			const_data: data.const_data,
-			variable_data: data.variable_data,
 			users: {
 				let mut out = BTreeMap::new();
 				out.insert(to.clone(), data.pieces);
@@ -306,19 +301,6 @@
 		fail!(<Error<T>>::SettingPropertiesNotAllowed)
 	}
 
-	fn set_variable_metadata(
-		&self,
-		sender: T::CrossAccountId,
-		token: TokenId,
-		data: BoundedVec<u8, CustomDataLimit>,
-	) -> DispatchResultWithPostInfo {
-		let len = data.len();
-		with_weight(
-			<Pallet<T>>::set_variable_metadata(self, &sender, token, data),
-			<CommonWeights<T>>::set_variable_metadata(len as u32),
-		)
-	}
-
 	fn check_nesting(
 		&self,
 		_sender: <T>::CrossAccountId,
@@ -357,13 +339,12 @@
 			.const_data
 			.into_inner()
 	}
-	fn variable_metadata(&self, token: TokenId) -> Vec<u8> {
-		<TokenData<T>>::get((self.id, token))
-			.variable_data
-			.into_inner()
-	}
 
-	fn token_properties(&self, _token_id: TokenId, _keys: Vec<PropertyKey>) -> Vec<Property> {
+	fn token_properties(
+		&self,
+		_token_id: TokenId,
+		_keys: Option<Vec<PropertyKey>>,
+	) -> Vec<Property> {
 		Vec::new()
 	}
 
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -41,16 +41,23 @@
 pub mod weights;
 pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
 
+#[struct_versioning::versioned(version = 2, upper)]
 #[derive(Encode, Decode, Default, TypeInfo, MaxEncodedLen)]
 pub struct ItemData {
 	pub const_data: BoundedVec<u8, CustomDataLimit>,
+
+	#[version(..2)]
 	pub variable_data: BoundedVec<u8, CustomDataLimit>,
 }
 
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
-	use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};
+	use frame_support::{
+		Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key,
+		traits::StorageVersion,
+	};
+	use frame_system::pallet_prelude::*;
 	use up_data_structs::{CollectionId, TokenId};
 	use super::weights::WeightInfo;
 
@@ -73,7 +80,10 @@
 		type WeightInfo: WeightInfo;
 	}
 
+	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
+
 	#[pallet::pallet]
+	#[pallet::storage_version(STORAGE_VERSION)]
 	#[pallet::generate_store(pub(super) trait Store)]
 	pub struct Pallet<T>(_);
 
@@ -146,6 +156,19 @@
 		Value = u128,
 		QueryKind = ValueQuery,
 	>;
+
+	#[pallet::hooks]
+	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
+		fn on_runtime_upgrade() -> Weight {
+			if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {
+				<TokenData<T>>::translate_values::<ItemDataVersion1, _>(|v| {
+					Some(<ItemDataVersion2>::from(v))
+				})
+			}
+
+			0
+		}
+	}
 }
 
 pub struct RefungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);
@@ -494,7 +517,6 @@
 				(collection.id, token_id),
 				ItemData {
 					const_data: token.const_data,
-					variable_data: token.variable_data,
 				},
 			);
 			for (user, amount) in token.users.into_iter() {
@@ -643,31 +665,6 @@
 		if let Some(allowance) = allowance {
 			Self::set_allowance_unchecked(collection, from, spender, token, allowance);
 		}
-		Ok(())
-	}
-
-	pub fn set_variable_metadata(
-		collection: &RefungibleHandle<T>,
-		sender: &T::CrossAccountId,
-		token: TokenId,
-		data: BoundedVec<u8, CustomDataLimit>,
-	) -> DispatchResult {
-		collection.check_can_update_meta(
-			sender,
-			&T::CrossAccountId::from_sub(collection.owner.clone()),
-		)?;
-
-		let token_data = <TokenData<T>>::get((collection.id, token));
-
-		// =========
-
-		<TokenData<T>>::insert(
-			(collection.id, token),
-			ItemData {
-				variable_data: data,
-				..token_data
-			},
-		);
 		Ok(())
 	}
 
modifiedpallets/refungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/refungible/src/weights.rs
+++ b/pallets/refungible/src/weights.rs
@@ -53,7 +53,6 @@
 	fn transfer_from_removing() -> Weight;
 	fn transfer_from_creating_removing() -> Weight;
 	fn burn_from() -> Weight;
-	fn set_variable_metadata(b: u32, ) -> Weight;
 }
 
 /// Weights for pallet_refungible using the Substrate node and recommended hardware.
@@ -242,12 +241,6 @@
 		(42_043_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(5 as Weight))
 			.saturating_add(T::DbWeight::get().writes(7 as Weight))
-	}
-	// Storage: Refungible TokenData (r:1 w:1)
-	fn set_variable_metadata(_b: u32, ) -> Weight {
-		(7_364_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
 }
 
@@ -436,11 +429,5 @@
 		(42_043_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
-	}
-	// Storage: Refungible TokenData (r:1 w:1)
-	fn set_variable_metadata(_b: u32, ) -> Weight {
-		(7_364_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
 }
modifiedpallets/unique/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/unique/src/benchmarking.rs
+++ b/pallets/unique/src/benchmarking.rs
@@ -168,9 +168,4 @@
 			nesting_rule: None,
 		};
 	}: set_collection_limits(RawOrigin::Signed(caller.clone()), collection, cl)
-
-	set_meta_update_permission_flag {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-	}: _(RawOrigin::Signed(caller.clone()), collection, MetaUpdatePermission::Admin)
 }
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -35,16 +35,16 @@
 use frame_system::{self as system, ensure_signed};
 use sp_runtime::{sp_std::prelude::Vec};
 use up_data_structs::{
-	CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT,
-	MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,
-	AccessMode, CreateItemData, CollectionLimits, CollectionId, CollectionMode, TokenId,
-	SchemaVersion, SponsorshipState, MetaUpdatePermission, CreateCollectionData, CustomDataLimit,
-	CreateItemExData, budget, CollectionField, Property, PropertyKey, PropertyKeyPermission,
+	CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT, MAX_COLLECTION_NAME_LENGTH,
+	MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, AccessMode, CreateItemData,
+	CollectionLimits, CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState,
+	CreateCollectionData, CreateItemExData, budget, CollectionField, Property, PropertyKey,
+	PropertyKeyPermission,
 };
 use pallet_evm::account::CrossAccountId;
 use pallet_common::{
-	CollectionHandle, Pallet as PalletCommon, Error as CommonError, CommonWeightInfo,
-	dispatch::dispatch_call, dispatch::CollectionDispatch,
+	CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_call,
+	dispatch::CollectionDispatch,
 };
 
 #[cfg(feature = "runtime-benchmarks")]
@@ -240,7 +240,9 @@
 
 		/// Variable metadata sponsoring
 		/// Collection id (controlled?2), token id (controlled?2)
+		#[deprecated]
 		pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
+
 		/// Approval sponsoring
 		pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
 		pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
@@ -261,6 +263,14 @@
 			0
 		}
 
+		fn on_runtime_upgrade() -> Weight {
+			let limit = None;
+
+			<VariableMetaDataBasket<T>>::remove_all(limit);
+
+			0
+		}
+
 		/// This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner of the collection is set to the address that signed the transaction and can be changed later.
 		///
 		/// # Permissions
@@ -333,7 +343,6 @@
 			<FungibleTransferBasket<T>>::remove_prefix(collection_id, None);
 			<ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);
 
-			<VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);
 			<NftApproveBasket<T>>::remove_prefix(collection_id, None);
 			<FungibleApproveBasket<T>>::remove_prefix(collection_id, None);
 			<RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);
@@ -929,59 +938,6 @@
 			let budget = budget::Value::new(2);
 
 			dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))
-		}
-
-		/// Set off-chain data schema.
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner
-		/// * Collection Admin
-		///
-		/// # Arguments
-		///
-		/// * collection_id.
-		///
-		/// * schema: String representing the offchain data schema.
-		#[weight = T::CommonWeightInfo::set_variable_metadata(data.len() as u32)]
-		#[transactional]
-		pub fn set_variable_meta_data (
-			origin,
-			collection_id: CollectionId,
-			item_id: TokenId,
-			data: BoundedVec<u8, CustomDataLimit>,
-		) -> DispatchResultWithPostInfo {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
-			dispatch_call::<T, _>(collection_id, |d| d.set_variable_metadata(sender, item_id, data))
-		}
-
-		/// Set meta_update_permission value for particular collection
-		///
-		/// # Permissions
-		///
-		/// * Collection Owner.
-		///
-		/// # Arguments
-		///
-		/// * collection_id: ID of the collection.
-		///
-		/// * value: New flag value.
-		#[weight = <SelfWeightOf<T>>::set_meta_update_permission_flag()]
-		#[transactional]
-		pub fn set_meta_update_permission_flag(origin, collection_id: CollectionId, value: MetaUpdatePermission) -> DispatchResult {
-			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
-
-			ensure!(
-				target_collection.meta_update_permission != MetaUpdatePermission::None,
-				<CommonError<T>>::MetadataFlagFrozen,
-			);
-			target_collection.check_is_owner(&sender)?;
-
-			target_collection.meta_update_permission = value;
-
-			target_collection.save()
 		}
 
 		/// Set schema standard
modifiedpallets/unique/src/weights.rsdiffbeforeafterboth
--- a/pallets/unique/src/weights.rs
+++ b/pallets/unique/src/weights.rs
@@ -49,7 +49,6 @@
 	fn set_const_on_chain_schema(b: u32, ) -> Weight;
 	fn set_schema_version() -> Weight;
 	fn set_collection_limits() -> Weight;
-	fn set_meta_update_permission_flag() -> Weight;
 }
 
 /// Weights for pallet_unique using the Substrate node and recommended hardware.
@@ -167,12 +166,6 @@
 	// Storage: Common CollectionById (r:1 w:1)
 	fn set_collection_limits() -> Weight {
 		(15_339_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(1 as Weight))
-			.saturating_add(T::DbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_meta_update_permission_flag() -> Weight {
-		(7_214_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
@@ -292,12 +285,6 @@
 	// Storage: Common CollectionById (r:1 w:1)
 	fn set_collection_limits() -> Weight {
 		(15_339_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
-	}
-	// Storage: Common CollectionById (r:1 w:1)
-	fn set_meta_update_permission_flag() -> Weight {
-		(7_214_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -22,7 +22,8 @@
 };
 use frame_support::{
 	storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet},
-	traits::Get, parameter_types,
+	traits::Get,
+	parameter_types,
 };
 
 #[cfg(feature = "serde")]
@@ -40,7 +41,10 @@
 	CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme, ThemeProperty,
 };
 pub use rmrk_types::{
-	primitives::{CollectionId as RmrkCollectionId, NftId as RmrkNftId, BaseId as RmrkBaseId, PartId as RmrkPartId, ResourceId as RmrkResourceId},
+	primitives::{
+		CollectionId as RmrkCollectionId, NftId as RmrkNftId, BaseId as RmrkBaseId,
+		PartId as RmrkPartId, ResourceId as RmrkResourceId,
+	},
 	NftChild as RmrkNftChild, AccountIdOrCollectionNftTuple as RmrkAccountIdOrCollectionNftTuple,
 };
 
@@ -85,6 +89,7 @@
 
 // Schema limits
 pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;
+pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;
 pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;
 
 pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;
@@ -318,8 +323,12 @@
 	pub limits: CollectionLimitsVersion2,
 
 	#[version(..2)]
+	pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,
+
+	#[version(..2)]
 	pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,
 
+	#[version(..2)]
 	pub meta_update_permission: MetaUpdatePermission,
 }
 
@@ -339,7 +348,6 @@
 	pub sponsorship: SponsorshipState<AccountId>,
 	pub limits: CollectionLimits,
 	pub const_on_chain_schema: Vec<u8>,
-	pub meta_update_permission: MetaUpdatePermission,
 	pub token_property_permissions: Vec<PropertyKeyPermission>,
 	pub properties: Vec<Property>,
 }
@@ -365,7 +373,6 @@
 	pub pending_sponsor: Option<AccountId>,
 	pub limits: Option<CollectionLimits>,
 	pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,
-	pub meta_update_permission: Option<MetaUpdatePermission>,
 	pub token_property_permissions: CollectionPropertiesPermissionsVec,
 	pub properties: CollectionPropertiesVec,
 }
@@ -376,28 +383,6 @@
 pub type CollectionPropertiesVec =
 	BoundedVec<Property, ConstU32<MAX_COLLECTION_PROPERTIES_ENCODE_LEN>>;
 
-#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct NftItemType<AccountId> {
-	pub owner: AccountId,
-	pub const_data: Vec<u8>,
-	pub variable_data: Vec<u8>,
-}
-
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct FungibleItemType {
-	pub value: u128,
-}
-
-#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
-#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct ReFungibleItemType<AccountId> {
-	pub owner: Vec<Ownership<AccountId>>,
-	pub const_data: Vec<u8>,
-	pub variable_data: Vec<u8>,
-}
-
 /// All fields are wrapped in `Option`s, where None means chain default
 #[struct_versioning::versioned(version = 2, upper)]
 #[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]
@@ -405,6 +390,8 @@
 pub struct CollectionLimits {
 	pub account_token_ownership_limit: Option<u32>,
 	pub sponsored_data_size: Option<u32>,
+
+	/// FIXME should we delete this or repurpose it?
 	/// None - setVariableMetadata is not sponsored
 	/// Some(v) - setVariableMetadata is sponsored
 	///           if there is v block between txs
@@ -502,9 +489,6 @@
 	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
 	#[derivative(Debug(format_with = "bounded::vec_debug"))]
 	pub const_data: BoundedVec<u8, CustomDataLimit>,
-	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
-	#[derivative(Debug(format_with = "bounded::vec_debug"))]
-	pub variable_data: BoundedVec<u8, CustomDataLimit>,
 
 	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
 	#[derivative(Debug(format_with = "bounded::vec_debug"))]
@@ -524,26 +508,16 @@
 	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
 	#[derivative(Debug(format_with = "bounded::vec_debug"))]
 	pub const_data: BoundedVec<u8, CustomDataLimit>,
-	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
-	#[derivative(Debug(format_with = "bounded::vec_debug"))]
-	pub variable_data: BoundedVec<u8, CustomDataLimit>,
 	pub pieces: u128,
 }
 
 #[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub enum MetaUpdatePermission {
 	ItemOwner,
 	Admin,
 	None,
 }
 
-impl Default for MetaUpdatePermission {
-	fn default() -> Self {
-		Self::ItemOwner
-	}
-}
-
 #[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]
 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 pub enum CreateItemData {
@@ -557,8 +531,6 @@
 pub struct CreateNftExData<CrossAccountId> {
 	#[derivative(Debug(format_with = "bounded::vec_debug"))]
 	pub const_data: BoundedVec<u8, CustomDataLimit>,
-	#[derivative(Debug(format_with = "bounded::vec_debug"))]
-	pub variable_data: BoundedVec<u8, CustomDataLimit>,
 	#[derivative(Debug(format_with = "bounded::vec_debug"))]
 	pub properties: CollectionPropertiesVec,
 	pub owner: CrossAccountId,
@@ -569,8 +541,6 @@
 pub struct CreateRefungibleExData<CrossAccountId> {
 	#[derivative(Debug(format_with = "bounded::vec_debug"))]
 	pub const_data: BoundedVec<u8, CustomDataLimit>,
-	#[derivative(Debug(format_with = "bounded::vec_debug"))]
-	pub variable_data: BoundedVec<u8, CustomDataLimit>,
 	#[derivative(Debug(format_with = "bounded::map_debug"))]
 	pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
 }
@@ -598,8 +568,8 @@
 impl CreateItemData {
 	pub fn data_size(&self) -> usize {
 		match self {
-			CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),
-			CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),
+			CreateItemData::NFT(data) => data.const_data.len(),
+			CreateItemData::ReFungible(data) => data.const_data.len(),
 			_ => 0,
 		}
 	}
@@ -700,24 +670,65 @@
 	NoSpaceForProperty,
 	PropertyLimitReached,
 	InvalidCharacterInPropertyKey,
+	PropertyKeyIsTooLong,
 	EmptyPropertyKey,
 }
 
-pub trait TrySet: Sized {
+#[derive(Clone, Copy)]
+pub enum PropertyScope {
+	None,
+	Rmrk,
+}
+
+impl PropertyScope {
+	fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {
+		let scope_str: &[u8] = match self {
+			Self::None => return Ok(key),
+			Self::Rmrk => b"rmrk",
+		};
+
+		[scope_str, b":", key.as_slice()]
+			.concat()
+			.try_into()
+			.map_err(|_| PropertiesError::PropertyKeyIsTooLong)
+	}
+}
+
+pub trait TrySetProperty: Sized {
 	type Value;
 
-	fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError>;
+	fn try_scoped_set(
+		&mut self,
+		scope: PropertyScope,
+		key: PropertyKey,
+		value: Self::Value,
+	) -> Result<(), PropertiesError>;
 
-	fn try_set_from_iter<I>(&mut self, iter: I) -> Result<(), PropertiesError>
+	fn try_scoped_set_from_iter<I>(
+		&mut self,
+		scope: PropertyScope,
+		iter: I,
+	) -> Result<(), PropertiesError>
 	where
 		I: Iterator<Item = (PropertyKey, Self::Value)>,
 	{
 		for (key, value) in iter {
-			self.try_set(key, value)?;
+			self.try_scoped_set(scope, key, value)?;
 		}
 
 		Ok(())
 	}
+
+	fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError> {
+		self.try_scoped_set(PropertyScope::None, key, value)
+	}
+
+	fn try_set_from_iter<I>(&mut self, iter: I) -> Result<(), PropertiesError>
+	where
+		I: Iterator<Item = (PropertyKey, Self::Value)>,
+	{
+		self.try_scoped_set_from_iter(PropertyScope::None, iter)
+	}
 }
 
 #[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]
@@ -751,12 +762,10 @@
 		}
 
 		for byte in key.as_slice().iter() {
-			match char::from_u32(*byte as u32) {
-				Some(ch)
-					if ch.is_ascii_alphanumeric()
-					|| ch == '_'
-					|| ch == '-' => { /* OK */ },
-				_ => return Err(PropertiesError::InvalidCharacterInPropertyKey)
+			let byte = *byte;
+
+			if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' {
+				return Err(PropertiesError::InvalidCharacterInPropertyKey);
 			}
 		}
 
@@ -764,12 +773,18 @@
 	}
 }
 
-impl<Value> TrySet for PropertiesMap<Value> {
+impl<Value> TrySetProperty for PropertiesMap<Value> {
 	type Value = Value;
 
-	fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError> {
+	fn try_scoped_set(
+		&mut self,
+		scope: PropertyScope,
+		key: PropertyKey,
+		value: Self::Value,
+	) -> Result<(), PropertiesError> {
 		Self::check_property_key(&key)?;
 
+		let key = scope.apply(key)?;
 		self.0
 			.try_insert(key, value)
 			.map_err(|_| PropertiesError::PropertyLimitReached)?;
@@ -816,17 +831,22 @@
 	}
 }
 
-impl TrySet for Properties {
+impl TrySetProperty for Properties {
 	type Value = PropertyValue;
 
-	fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError> {
+	fn try_scoped_set(
+		&mut self,
+		scope: PropertyScope,
+		key: PropertyKey,
+		value: Self::Value,
+	) -> Result<(), PropertiesError> {
 		let value_len = value.len();
 
 		if self.consumed_space as usize + value_len > self.space_limit as usize {
 			return Err(PropertiesError::NoSpaceForProperty);
 		}
 
-		self.map.try_set(key, value)?;
+		self.map.try_scoped_set(scope, key, value)?;
 
 		self.consumed_space += value_len as u32;
 
@@ -869,34 +889,23 @@
 	pub const RmrkPartsLimit: u32 = 3;
 }
 
-pub type RmrkCollectionInfo<AccountId> = CollectionInfo<
-	RmrkString,
-	BoundedVec<u8, RmrkCollectionSymbolLimit>,
-	AccountId
->;
-pub type RmrkInstanceInfo<AccountId> = NftInfo<
-	AccountId, 
-	Permill,
-	RmrkString
->;
-pub type RmrkResourceInfo = ResourceInfo::<
+pub type RmrkCollectionInfo<AccountId> =
+	CollectionInfo<RmrkString, BoundedVec<u8, RmrkCollectionSymbolLimit>, AccountId>;
+pub type RmrkInstanceInfo<AccountId> = NftInfo<AccountId, Permill, RmrkString>;
+pub type RmrkResourceInfo = ResourceInfo<
 	BoundedVec<u8, RmrkResourceSymbolLimit>,
 	RmrkString,
-	BoundedVec<RmrkPartId, RmrkPartsLimit>
->;
-pub type RmrkPropertyInfo = PropertyInfo<
-	BoundedVec<u8, RmrkKeyLimit>, 
-	BoundedVec<u8, RmrkValueLimit>
+	BoundedVec<RmrkPartId, RmrkPartsLimit>,
 >;
+pub type RmrkPropertyInfo =
+	PropertyInfo<BoundedVec<u8, RmrkKeyLimit>, BoundedVec<u8, RmrkValueLimit>>;
 pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;
-pub type RmrkPartType = PartType<
-	RmrkString,
-	BoundedVec<RmrkCollectionId, RmrkMaxCollectionsEquippablePerPart>
->;
+pub type RmrkPartType =
+	PartType<RmrkString, BoundedVec<RmrkCollectionId, RmrkMaxCollectionsEquippablePerPart>>;
 pub type RmrkTheme = Theme<RmrkString, Vec<ThemeProperty<RmrkString>>>;
 
 pub type RmrkRpcString = Vec<u8>;
 pub type RmrkThemeName = RmrkRpcString;
 pub type RmrkPropertyKey = RmrkRpcString;
 
-type RmrkString = BoundedVec<u8, RmrkStringLimit>;
\ No newline at end of file
+type RmrkString = BoundedVec<u8, RmrkStringLimit>;
modifiedprimitives/rpc/src/lib.rsdiffbeforeafterboth
--- a/primitives/rpc/src/lib.rs
+++ b/primitives/rpc/src/lib.rs
@@ -42,22 +42,25 @@
 		fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>>;
 		fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>>;
 		fn const_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>>;
-		fn variable_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>>;
 
-		fn collection_properties(collection: CollectionId, properties: Vec<Vec<u8>>) -> Result<Vec<Property>>;
+		fn collection_properties(collection: CollectionId, properties: Option<Vec<Vec<u8>>>) -> Result<Vec<Property>>;
 
 		fn token_properties(
 			collection: CollectionId,
 			token_id: TokenId,
-			properties: Vec<Vec<u8>>
+			properties: Option<Vec<Vec<u8>>>
 		) -> Result<Vec<Property>>;
 
 		fn property_permissions(
 			collection: CollectionId,
-			properties: Vec<Vec<u8>>
+			properties: Option<Vec<Vec<u8>>>
 		) -> Result<Vec<PropertyKeyPermission>>;
 
-		fn token_data(collection: CollectionId, token_id: TokenId, keys: Vec<Vec<u8>>) -> Result<TokenData<CrossAccountId>>;
+		fn token_data(
+			collection: CollectionId,
+			token_id: TokenId,
+			keys: Option<Vec<Vec<u8>>>
+		) -> Result<TokenData<CrossAccountId>>;
 
 		fn total_supply(collection: CollectionId) -> Result<u32>;
 		fn account_balance(collection: CollectionId, account: CrossAccountId) -> Result<u32>;
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -32,15 +32,14 @@
                 fn const_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>, DispatchError> {
                     dispatch_unique_runtime!(collection.const_metadata(token))
                 }
-                fn variable_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>, DispatchError> {
-                    dispatch_unique_runtime!(collection.variable_metadata(token))
-                }
 
                 fn collection_properties(
                     collection: CollectionId,
-                    keys: Vec<Vec<u8>>
+                    keys: Option<Vec<Vec<u8>>>
                 ) -> Result<Vec<Property>, DispatchError> {
-                    let keys = pallet_common::Pallet::<Runtime>::bytes_keys_to_property_keys(keys)?;
+                    let keys = keys.map(
+                        |keys| pallet_common::Pallet::<Runtime>::bytes_keys_to_property_keys(keys)
+                    ).transpose()?;
 
                     pallet_common::Pallet::<Runtime>::filter_collection_properties(collection, keys)
                 }
@@ -48,17 +47,22 @@
                 fn token_properties(
                     collection: CollectionId,
                     token_id: TokenId,
-                    keys: Vec<Vec<u8>>
+                    keys: Option<Vec<Vec<u8>>>
                 ) -> Result<Vec<Property>, DispatchError> {
-                    let keys = pallet_common::Pallet::<Runtime>::bytes_keys_to_property_keys(keys)?;
+                    let keys = keys.map(
+                        |keys| pallet_common::Pallet::<Runtime>::bytes_keys_to_property_keys(keys)
+                    ).transpose()?;
+
                     dispatch_unique_runtime!(collection.token_properties(token_id, keys))
                 }
 
                 fn property_permissions(
                     collection: CollectionId,
-                    keys: Vec<Vec<u8>>
+                    keys: Option<Vec<Vec<u8>>>
                 ) -> Result<Vec<PropertyKeyPermission>, DispatchError> {
-                    let keys = pallet_common::Pallet::<Runtime>::bytes_keys_to_property_keys(keys)?;
+                    let keys = keys.map(
+                        |keys| pallet_common::Pallet::<Runtime>::bytes_keys_to_property_keys(keys)
+                    ).transpose()?;
 
                     pallet_common::Pallet::<Runtime>::filter_property_permissions(collection, keys)
                 }
@@ -66,7 +70,7 @@
                 fn token_data(
                     collection: CollectionId,
                     token_id: TokenId,
-                    keys: Vec<Vec<u8>>
+                    keys: Option<Vec<Vec<u8>>>
                 ) -> Result<TokenData<CrossAccountId>, DispatchError> {
                     let token_data = TokenData {
                         const_data: Self::const_metadata(collection, token_id)?,
@@ -232,7 +236,7 @@
                                     })
                                 })
                                 .collect();
-        
+
                             properties
                         }
                         None => {
@@ -253,7 +257,7 @@
                     let token_id = TokenId(nft_id);
 
 		            let properties = pallet_nonfungible::Pallet::<Runtime>::token_properties((collection_id, token_id)); // todo look into usage of nonfungible
-                    
+
                     return Ok(match filter_keys {
                         Some(keys) => {
                             let keys = pallet_common::Pallet::<Runtime>::bytes_keys_to_property_keys(keys)?;
@@ -266,7 +270,7 @@
                                     })
                                 })
                                 .collect();
-        
+
                             properties
                         }
                         None => {
@@ -300,7 +304,7 @@
                     let keys = pallet_common::Pallet::<Runtime>::bytes_keys_to_property_keys(
                         Vec::from([String::from("rmrk:base-type").into_bytes()])
                     )?;
-                    let properties = pallet_common::Pallet::<Runtime>::filter_collection_properties(collection_id, keys)?;
+                    let properties = pallet_common::Pallet::<Runtime>::filter_collection_properties(collection_id, Some(keys))?;
                     //ensure!(properties.len() == 1); // todo make sure it's fine to have ensure in place // no access to errors from here? displace?
 
                     Ok(Some( RmrkBaseInfo {
modifiedruntime/common/src/sponsoring.rsdiffbeforeafterboth
--- a/runtime/common/src/sponsoring.rs
+++ b/runtime/common/src/sponsoring.rs
@@ -21,17 +21,16 @@
 	storage::{StorageMap, StorageDoubleMap, StorageNMap},
 };
 use up_data_structs::{
-	CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,
-	NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode,
-	CreateItemData,
+	CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, NFT_SPONSOR_TRANSFER_TIMEOUT,
+	REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode, CreateItemData,
 };
 use sp_runtime::traits::Saturating;
 use pallet_common::{CollectionHandle};
 use pallet_evm::account::CrossAccountId;
 use pallet_unique::{
 	Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,
-	NftApproveBasket, VariableMetaDataBasket, CreateItemBasket, ReFungibleTransferBasket,
-	FungibleTransferBasket, NftTransferBasket,
+	NftApproveBasket, CreateItemBasket, ReFungibleTransferBasket, FungibleTransferBasket,
+	NftTransferBasket,
 };
 use pallet_fungible::Config as FungibleConfig;
 use pallet_nonfungible::Config as NonfungibleConfig;
@@ -136,63 +135,6 @@
 	}
 
 	CreateItemBasket::<T>::insert((collection.id, who.as_sub()), block_number);
-
-	Some(())
-}
-
-pub fn withdraw_set_variable_meta_data<T: Config>(
-	who: &T::CrossAccountId,
-	collection: &CollectionHandle<T>,
-	item_id: &TokenId,
-	data: &[u8],
-) -> Option<()> {
-	// TODO: make it work for admins
-	if collection.meta_update_permission != MetaUpdatePermission::ItemOwner {
-		return None;
-	}
-	// preliminary sponsoring correctness check
-	match collection.mode {
-		CollectionMode::NFT => {
-			let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
-			if !owner.conv_eq(who) {
-				return None;
-			}
-		}
-		CollectionMode::Fungible(_) => {
-			if item_id != &TokenId::default() {
-				return None;
-			}
-			if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {
-				return None;
-			}
-		}
-		CollectionMode::ReFungible => {
-			if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
-				return None;
-			}
-		}
-	}
-
-	// Can't sponsor fungible collection, this tx will be rejected
-	// as invalid
-	if matches!(collection.mode, CollectionMode::Fungible(_)) {
-		return None;
-	}
-	if data.len() > collection.limits.sponsored_data_size() as usize {
-		return None;
-	}
-
-	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
-	let limit = collection.limits.sponsored_data_rate_limit()?;
-
-	if let Some(last_tx_block) = VariableMetaDataBasket::<T>::get(collection.id, item_id) {
-		let timeout = last_tx_block + limit.into();
-		if block_number < timeout {
-			return None;
-		}
-	}
-
-	<VariableMetaDataBasket<T>>::insert(collection.id, item_id, block_number);
 
 	Some(())
 }
@@ -290,20 +232,6 @@
 			} => {
 				let (sponsor, collection) = load(*collection_id)?;
 				withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)
-			}
-			UniqueCall::set_variable_meta_data {
-				collection_id,
-				item_id,
-				data,
-			} => {
-				let (sponsor, collection) = load(*collection_id)?;
-				withdraw_set_variable_meta_data::<T>(
-					&T::CrossAccountId::from_sub(who.clone()),
-					&collection,
-					item_id,
-					data,
-				)
-				.map(|()| sponsor)
 			}
 			_ => None,
 		}
modifiedruntime/common/src/weights.rsdiffbeforeafterboth
--- a/runtime/common/src/weights.rs
+++ b/runtime/common/src/weights.rs
@@ -86,10 +86,6 @@
 		dispatch_weight::<T>() + max_weight_of!(transfer_from())
 	}
 
-	fn set_variable_metadata(bytes: u32) -> Weight {
-		dispatch_weight::<T>() + max_weight_of!(set_variable_metadata(bytes))
-	}
-
 	fn burn_from() -> Weight {
 		dispatch_weight::<T>() + max_weight_of!(burn_from())
 	}
modifiedruntime/tests/src/tests.rsdiffbeforeafterboth
before · runtime/tests/src/tests.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// Tests to be written here18use crate::{Test, TestCrossAccountId, CollectionCreationPrice, Origin, Unique, new_test_ext};19use up_data_structs::{20	COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,21	CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission,22	TokenId, MAX_TOKEN_OWNERSHIP, CreateCollectionData, CollectionField, SchemaVersion,23	CollectionMode, AccessMode,24};25use frame_support::{assert_noop, assert_ok, assert_err};26use sp_std::convert::TryInto;27use pallet_evm::account::CrossAccountId;28use pallet_common::Error as CommonError;29use pallet_unique::Error as UniqueError;3031fn add_balance(user: u64, value: u64) {32	const DONOR_USER: u64 = 999;33	assert_ok!(<pallet_balances::Pallet<Test>>::set_balance(34		Origin::root(),35		DONOR_USER,36		value,37		038	));39	assert_ok!(<pallet_balances::Pallet<Test>>::force_transfer(40		Origin::root(),41		DONOR_USER,42		user,43		value44	));45}4647fn default_nft_data() -> CreateNftData {48	CreateNftData {49		const_data: vec![1, 2, 3].try_into().unwrap(),50		variable_data: vec![3, 2, 1].try_into().unwrap(),51	}52}5354fn default_fungible_data() -> CreateFungibleData {55	CreateFungibleData { value: 5 }56}5758fn default_re_fungible_data() -> CreateReFungibleData {59	CreateReFungibleData {60		const_data: vec![1, 2, 3].try_into().unwrap(),61		variable_data: vec![3, 2, 1].try_into().unwrap(),62		pieces: 1023,63	}64}6566fn create_test_collection_for_owner(67	mode: &CollectionMode,68	owner: u64,69	id: CollectionId,70) -> CollectionId {71	add_balance(owner, CollectionCreationPrice::get() as u64 + 1);7273	let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();74	let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();75	let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();7677	let data: CreateCollectionData<u64> = CreateCollectionData {78		name: col_name1.try_into().unwrap(),79		description: col_desc1.try_into().unwrap(),80		token_prefix: token_prefix1.try_into().unwrap(),81		mode: mode.clone(),82		..Default::default()83	};8485	let origin1 = Origin::signed(owner);86	assert_ok!(Unique::create_collection_ex(origin1, data));8788	let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();89	let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();90	let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();91	assert_eq!(92		<pallet_common::CollectionById<Test>>::get(id)93			.unwrap()94			.owner,95		owner96	);97	assert_eq!(98		<pallet_common::CollectionById<Test>>::get(id).unwrap().name,99		saved_col_name100	);101	assert_eq!(102		<pallet_common::CollectionById<Test>>::get(id).unwrap().mode,103		*mode104	);105	assert_eq!(106		<pallet_common::CollectionById<Test>>::get(id)107			.unwrap()108			.description,109		saved_description110	);111	assert_eq!(112		<pallet_common::CollectionById<Test>>::get(id)113			.unwrap()114			.token_prefix,115		saved_prefix116	);117	id118}119120fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {121	create_test_collection_for_owner(&mode, 1, id)122}123124fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {125	let origin1 = Origin::signed(1);126	assert_ok!(Unique::create_item(127		origin1,128		collection_id,129		account(1),130		data.clone()131	));132}133134fn account(sub: u64) -> TestCrossAccountId {135	TestCrossAccountId::from_sub(sub)136}137138// Use cases tests region139// #region140141#[test]142fn set_version_schema() {143	new_test_ext().execute_with(|| {144		let origin1 = Origin::signed(1);145		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));146147		assert_ok!(Unique::set_schema_version(148			origin1,149			collection_id,150			SchemaVersion::Unique151		));152		assert_eq!(153			<pallet_common::CollectionById<Test>>::get(collection_id)154				.unwrap()155				.schema_version,156			SchemaVersion::Unique157		);158	});159}160161#[test]162fn check_not_sufficient_founds() {163	new_test_ext().execute_with(|| {164		let acc: u64 = 1;165		<pallet_balances::Pallet<Test>>::set_balance(Origin::root(), acc, 0, 0).unwrap();166167		let name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();168		let description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();169		let token_prefix: Vec<u8> = b"token_prefix1\0".to_vec();170171		let data: CreateCollectionData<<Test as frame_system::Config>::AccountId> =172			CreateCollectionData {173				name: name.try_into().unwrap(),174				description: description.try_into().unwrap(),175				token_prefix: token_prefix.try_into().unwrap(),176				mode: CollectionMode::NFT,177				..Default::default()178			};179180		let result = Unique::create_collection_ex(Origin::signed(acc), data);181		assert_err!(result, <CommonError<Test>>::NotSufficientFounds);182	});183}184185#[test]186fn create_fungible_collection_fails_with_large_decimal_numbers() {187	new_test_ext().execute_with(|| {188		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();189		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();190		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();191192		let data: CreateCollectionData<u64> = CreateCollectionData {193			name: col_name1.try_into().unwrap(),194			description: col_desc1.try_into().unwrap(),195			token_prefix: token_prefix1.try_into().unwrap(),196			mode: CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1),197			..Default::default()198		};199200		let origin1 = Origin::signed(1);201		assert_noop!(202			Unique::create_collection_ex(origin1, data),203			UniqueError::<Test>::CollectionDecimalPointLimitExceeded204		);205	});206}207208#[test]209fn create_nft_item() {210	new_test_ext().execute_with(|| {211		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));212213		let data = default_nft_data();214		create_test_item(collection_id, &data.clone().into());215216		let item = <pallet_nonfungible::TokenData<Test>>::get((collection_id, 1)).unwrap();217		assert_eq!(item.const_data, data.const_data.into_inner());218		assert_eq!(item.variable_data, data.variable_data.into_inner());219	});220}221222// Use cases tests region223// #region224#[test]225fn create_nft_multiple_items() {226	new_test_ext().execute_with(|| {227		create_test_collection(&CollectionMode::NFT, CollectionId(1));228229		let origin1 = Origin::signed(1);230231		let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];232233		assert_ok!(Unique::create_multiple_items(234			origin1,235			CollectionId(1),236			account(1),237			items_data238				.clone()239				.into_iter()240				.map(|d| { d.into() })241				.collect()242		));243		for (index, data) in items_data.into_iter().enumerate() {244			let item = <pallet_nonfungible::TokenData<Test>>::get((245				CollectionId(1),246				TokenId((index + 1) as u32),247			))248			.unwrap();249			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());250			assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());251		}252	});253}254255#[test]256fn create_refungible_item() {257	new_test_ext().execute_with(|| {258		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));259260		let data = default_re_fungible_data();261		create_test_item(collection_id, &data.clone().into());262		let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));263		let balance =264			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1)));265		assert_eq!(item.const_data, data.const_data.into_inner());266		assert_eq!(item.variable_data, data.variable_data.into_inner());267		assert_eq!(balance, 1023);268	});269}270271#[test]272fn create_multiple_refungible_items() {273	new_test_ext().execute_with(|| {274		create_test_collection(&CollectionMode::ReFungible, CollectionId(1));275276		let origin1 = Origin::signed(1);277278		let items_data = vec![279			default_re_fungible_data(),280			default_re_fungible_data(),281			default_re_fungible_data(),282		];283284		assert_ok!(Unique::create_multiple_items(285			origin1,286			CollectionId(1),287			account(1),288			items_data289				.clone()290				.into_iter()291				.map(|d| { d.into() })292				.collect()293		));294		for (index, data) in items_data.into_iter().enumerate() {295			let item = <pallet_refungible::TokenData<Test>>::get((296				CollectionId(1),297				TokenId((index + 1) as u32),298			));299			let balance =300				<pallet_refungible::Balance<Test>>::get((CollectionId(1), TokenId(1), account(1)));301			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());302			assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());303			assert_eq!(balance, 1023);304		}305	});306}307308#[test]309fn create_fungible_item() {310	new_test_ext().execute_with(|| {311		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));312313		let data = default_fungible_data();314		create_test_item(collection_id, &data.into());315316		assert_eq!(317			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),318			5319		);320	});321}322323//#[test]324// fn create_multiple_fungible_items() {325//     new_test_ext().execute_with(|| {326//         default_limits();327328//         create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));329330//         let origin1 = Origin::signed(1);331332//         let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];333334//         assert_ok!(Unique::create_multiple_items(335//             origin1.clone(),336//             1,337//             1,338//             items_data.clone().into_iter().map(|d| { d.into() }).collect()339//         ));340341//         for (index, _) in items_data.iter().enumerate() {342//             assert_eq!(Unique::fungible_item_id(1, (index + 1) as TokenId).value, 5);343//         }344//         assert_eq!(Unique::balance_count(1, 1), 3000);345//         assert_eq!(Unique::address_tokens(1, 1), [1, 2, 3]);346//     });347// }348349#[test]350fn transfer_fungible_item() {351	new_test_ext().execute_with(|| {352		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));353354		let origin1 = Origin::signed(1);355		let origin2 = Origin::signed(2);356357		let data = default_fungible_data();358		create_test_item(collection_id, &data.into());359360		assert_eq!(361			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),362			5363		);364365		// change owner scenario366		assert_ok!(Unique::transfer(367			origin1,368			account(2),369			CollectionId(1),370			TokenId(0),371			5372		));373		assert_eq!(374			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),375			0376		);377378		// split item scenario379		assert_ok!(Unique::transfer(380			origin2.clone(),381			account(3),382			CollectionId(1),383			TokenId(0),384			3385		));386387		// split item and new owner has account scenario388		assert_ok!(Unique::transfer(389			origin2,390			account(3),391			CollectionId(1),392			TokenId(0),393			1394		));395		assert_eq!(396			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(2))),397			1398		);399		assert_eq!(400			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(3))),401			4402		);403	});404}405406#[test]407fn transfer_refungible_item() {408	new_test_ext().execute_with(|| {409		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));410411		// Create RFT 1 in 1023 pieces for account 1412		let data = default_re_fungible_data();413		create_test_item(collection_id, &data.clone().into());414		let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));415		assert_eq!(item.const_data, data.const_data.into_inner());416		assert_eq!(item.variable_data, data.variable_data.into_inner());417		assert_eq!(418			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),419			1420		);421		assert_eq!(422			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),423			1023424		);425		assert_eq!(426			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),427			true428		);429430		// Account 1 transfers all 1023 pieces of RFT 1 to account 2431		let origin1 = Origin::signed(1);432		let origin2 = Origin::signed(2);433		assert_ok!(Unique::transfer(434			origin1,435			account(2),436			CollectionId(1),437			TokenId(1),438			1023439		));440		assert_eq!(441			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),442			1023443		);444		assert_eq!(445			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),446			0447		);448		assert_eq!(449			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),450			1451		);452		assert_eq!(453			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),454			false455		);456		assert_eq!(457			<pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),458			true459		);460461		// Account 2 transfers 500 pieces of RFT 1 to account 3462		assert_ok!(Unique::transfer(463			origin2.clone(),464			account(3),465			CollectionId(1),466			TokenId(1),467			500468		));469		assert_eq!(470			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),471			523472		);473		assert_eq!(474			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),475			500476		);477		assert_eq!(478			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),479			1480		);481		assert_eq!(482			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),483			1484		);485		assert_eq!(486			<pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),487			true488		);489		assert_eq!(490			<pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),491			true492		);493494		// Account 2 transfers 200 more pieces of RFT 1 to account 3 with pre-existing balance495		assert_ok!(Unique::transfer(496			origin2,497			account(3),498			CollectionId(1),499			TokenId(1),500			200501		));502		assert_eq!(503			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),504			323505		);506		assert_eq!(507			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),508			700509		);510		assert_eq!(511			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),512			1513		);514		assert_eq!(515			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),516			1517		);518		assert_eq!(519			<pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),520			true521		);522		assert_eq!(523			<pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),524			true525		);526	});527}528529#[test]530fn transfer_nft_item() {531	new_test_ext().execute_with(|| {532		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));533534		let data = default_nft_data();535		create_test_item(collection_id, &data.into());536		assert_eq!(537			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),538			1539		);540		assert_eq!(541			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),542			true543		);544545		let origin1 = Origin::signed(1);546		// default scenario547		assert_ok!(Unique::transfer(548			origin1,549			account(2),550			CollectionId(1),551			TokenId(1),552			1553		));554		assert_eq!(555			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),556			0557		);558		assert_eq!(559			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),560			1561		);562		assert_eq!(563			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),564			false565		);566		assert_eq!(567			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),568			true569		);570	});571}572573#[test]574fn transfer_nft_item_wrong_value() {575	new_test_ext().execute_with(|| {576		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));577578		let data = default_nft_data();579		create_test_item(collection_id, &data.into());580		assert_eq!(581			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),582			1583		);584		assert_eq!(585			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),586			true587		);588589		let origin1 = Origin::signed(1);590591		assert_noop!(592			Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 2)593				.map_err(|e| e.error),594			<pallet_nonfungible::Error::<Test>>::NonfungibleItemsHaveNoAmount595		);596	});597}598599#[test]600fn transfer_nft_item_zero_value() {601	new_test_ext().execute_with(|| {602		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));603604		let data = default_nft_data();605		create_test_item(collection_id, &data.into());606		assert_eq!(607			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),608			1609		);610		assert_eq!(611			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),612			true613		);614615		let origin1 = Origin::signed(1);616617		// Transferring 0 amount works on NFT...618		assert_ok!(Unique::transfer(619			origin1,620			account(2),621			CollectionId(1),622			TokenId(1),623			0624		));625		// ... and results in no transfer626		assert_eq!(627			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),628			1629		);630		assert_eq!(631			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),632			true633		);634	});635}636637#[test]638fn nft_approve_and_transfer_from() {639	new_test_ext().execute_with(|| {640		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));641642		let data = default_nft_data();643		create_test_item(collection_id, &data.into());644645		let origin1 = Origin::signed(1);646		let origin2 = Origin::signed(2);647648		assert_eq!(649			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),650			1651		);652		assert_eq!(653			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),654			true655		);656657		// neg transfer_from658		assert_noop!(659			Unique::transfer_from(660				origin2.clone(),661				account(1),662				account(2),663				CollectionId(1),664				TokenId(1),665				1666			)667			.map_err(|e| e.error),668			CommonError::<Test>::ApprovedValueTooLow669		);670671		// do approve672		assert_ok!(Unique::approve(673			origin1,674			account(2),675			CollectionId(1),676			TokenId(1),677			1678		));679		assert_eq!(680			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),681			account(2)682		);683684		assert_ok!(Unique::transfer_from(685			origin2,686			account(1),687			account(3),688			CollectionId(1),689			TokenId(1),690			1691		));692		assert!(693			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()694		);695	});696}697698#[test]699fn nft_approve_and_transfer_from_allow_list() {700	new_test_ext().execute_with(|| {701		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));702703		let origin1 = Origin::signed(1);704		let origin2 = Origin::signed(2);705706		// Create NFT 1 for account 1707		let data = default_nft_data();708		create_test_item(collection_id, &data.clone().into());709		assert_eq!(710			&<pallet_nonfungible::TokenData<Test>>::get((collection_id, TokenId(1)))711				.unwrap()712				.const_data,713			&data.const_data.into_inner()714		);715		assert_eq!(716			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),717			1718		);719		assert_eq!(720			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),721			true722		);723724		// Allow allow-list users to mint and add accounts 1, 2, and 3 to allow-list725		assert_ok!(Unique::set_mint_permission(726			origin1.clone(),727			CollectionId(1),728			true729		));730		assert_ok!(Unique::set_public_access_mode(731			origin1.clone(),732			CollectionId(1),733			AccessMode::AllowList734		));735		assert_ok!(Unique::add_to_allow_list(736			origin1.clone(),737			CollectionId(1),738			account(1)739		));740		assert_ok!(Unique::add_to_allow_list(741			origin1.clone(),742			CollectionId(1),743			account(2)744		));745		assert_ok!(Unique::add_to_allow_list(746			origin1.clone(),747			CollectionId(1),748			account(3)749		));750751		// Account 1 approves account 2 for NFT 1752		assert_ok!(Unique::approve(753			origin1.clone(),754			account(2),755			CollectionId(1),756			TokenId(1),757			1758		));759		assert_eq!(760			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),761			account(2)762		);763764		// Account 2 transfers NFT 1 from account 1 to account 3765		assert_ok!(Unique::transfer_from(766			origin2,767			account(1),768			account(3),769			CollectionId(1),770			TokenId(1),771			1772		));773		assert!(774			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()775		);776	});777}778779#[test]780fn refungible_approve_and_transfer_from() {781	new_test_ext().execute_with(|| {782		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));783784		let origin1 = Origin::signed(1);785		let origin2 = Origin::signed(2);786787		// Create RFT 1 in 1023 pieces for account 1788		let data = default_re_fungible_data();789		create_test_item(collection_id, &data.into());790791		assert_eq!(792			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),793			1794		);795		assert_eq!(796			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),797			1023798		);799		assert_eq!(800			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),801			true802		);803804		// Allow public minting, enable allow-list and add accounts 1, 2, 3 to allow-list805		assert_ok!(Unique::set_mint_permission(806			origin1.clone(),807			CollectionId(1),808			true809		));810		assert_ok!(Unique::set_public_access_mode(811			origin1.clone(),812			CollectionId(1),813			AccessMode::AllowList814		));815		assert_ok!(Unique::add_to_allow_list(816			origin1.clone(),817			CollectionId(1),818			account(1)819		));820		assert_ok!(Unique::add_to_allow_list(821			origin1.clone(),822			CollectionId(1),823			account(2)824		));825		assert_ok!(Unique::add_to_allow_list(826			origin1.clone(),827			CollectionId(1),828			account(3)829		));830831		// Account 1 approves account 2 for 1023 pieces of RFT 1832		assert_ok!(Unique::approve(833			origin1,834			account(2),835			CollectionId(1),836			TokenId(1),837			1023838		));839		assert_eq!(840			<pallet_refungible::Allowance<Test>>::get((841				CollectionId(1),842				TokenId(1),843				account(1),844				account(2)845			)),846			1023847		);848849		// Account 2 transfers 100 pieces of RFT 1 from account 1 to account 3850		assert_ok!(Unique::transfer_from(851			origin2,852			account(1),853			account(3),854			CollectionId(1),855			TokenId(1),856			100857		));858		assert_eq!(859			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),860			1861		);862		assert_eq!(863			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),864			1865		);866		assert_eq!(867			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),868			923869		);870		assert_eq!(871			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),872			100873		);874		assert_eq!(875			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),876			true877		);878		assert_eq!(879			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),880			true881		);882		assert_eq!(883			<pallet_refungible::Allowance<Test>>::get((884				CollectionId(1),885				TokenId(1),886				account(1),887				account(2)888			)),889			923890		);891	});892}893894#[test]895fn fungible_approve_and_transfer_from() {896	new_test_ext().execute_with(|| {897		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));898899		let data = default_fungible_data();900		create_test_item(collection_id, &data.into());901902		let origin1 = Origin::signed(1);903		let origin2 = Origin::signed(2);904905		assert_ok!(Unique::set_mint_permission(906			origin1.clone(),907			CollectionId(1),908			true909		));910		assert_ok!(Unique::set_public_access_mode(911			origin1.clone(),912			CollectionId(1),913			AccessMode::AllowList914		));915		assert_ok!(Unique::add_to_allow_list(916			origin1.clone(),917			CollectionId(1),918			account(1)919		));920		assert_ok!(Unique::add_to_allow_list(921			origin1.clone(),922			CollectionId(1),923			account(2)924		));925		assert_ok!(Unique::add_to_allow_list(926			origin1.clone(),927			CollectionId(1),928			account(3)929		));930931		// do approve932		assert_ok!(Unique::approve(933			origin1.clone(),934			account(2),935			CollectionId(1),936			TokenId(0),937			5938		));939		assert_eq!(940			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),941			5942		);943		assert_ok!(Unique::approve(944			origin1,945			account(3),946			CollectionId(1),947			TokenId(0),948			5949		));950		assert_eq!(951			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),952			5953		);954		assert_eq!(955			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(3))),956			5957		);958959		assert_ok!(Unique::transfer_from(960			origin2.clone(),961			account(1),962			account(3),963			CollectionId(1),964			TokenId(0),965			4966		));967968		assert_eq!(969			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),970			1971		);972973		assert_noop!(974			Unique::transfer_from(975				origin2,976				account(1),977				account(3),978				CollectionId(1),979				TokenId(0),980				4981			)982			.map_err(|e| e.error),983			CommonError::<Test>::ApprovedValueTooLow984		);985	});986}987988#[test]989fn change_collection_owner() {990	new_test_ext().execute_with(|| {991		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));992993		let origin1 = Origin::signed(1);994		assert_ok!(Unique::change_collection_owner(origin1, collection_id, 2));995		assert_eq!(996			<pallet_common::CollectionById<Test>>::get(collection_id)997				.unwrap()998				.owner,999			21000		);1001	});1002}10031004#[test]1005fn destroy_collection() {1006	new_test_ext().execute_with(|| {1007		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10081009		let origin1 = Origin::signed(1);1010		assert_ok!(Unique::destroy_collection(origin1, collection_id));1011	});1012}10131014#[test]1015fn burn_nft_item() {1016	new_test_ext().execute_with(|| {1017		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10181019		let origin1 = Origin::signed(1);10201021		let data = default_nft_data();1022		create_test_item(collection_id, &data.into());10231024		// check balance (collection with id = 1, user id = 1)1025		assert_eq!(1026			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1027			11028		);10291030		// burn item1031		assert_ok!(Unique::burn_item(1032			origin1.clone(),1033			collection_id,1034			TokenId(1),1035			11036		));1037		assert_eq!(1038			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1039			01040		);1041	});1042}10431044#[test]1045fn burn_same_nft_item_twice() {1046	new_test_ext().execute_with(|| {1047		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10481049		let origin1 = Origin::signed(1);10501051		let data = default_nft_data();1052		create_test_item(collection_id, &data.into());10531054		// check balance (collection with id = 1, user id = 1)1055		assert_eq!(1056			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1057			11058		);10591060		// burn item1061		assert_ok!(Unique::burn_item(1062			origin1.clone(),1063			collection_id,1064			TokenId(1),1065			11066		));10671068		// burn item again1069		assert_noop!(1070			Unique::burn_item(origin1, collection_id, TokenId(1), 1).map_err(|e| e.error),1071			CommonError::<Test>::TokenNotFound1072		);10731074		assert_eq!(1075			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1076			01077		);1078	});1079}10801081#[test]1082fn burn_fungible_item() {1083	new_test_ext().execute_with(|| {1084		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));10851086		let origin1 = Origin::signed(1);1087		assert_ok!(Unique::add_collection_admin(1088			origin1.clone(),1089			collection_id,1090			account(2)1091		));10921093		let data = default_fungible_data();1094		create_test_item(collection_id, &data.into());10951096		// check balance (collection with id = 1, user id = 1)1097		assert_eq!(1098			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1099			51100		);11011102		// burn item1103		assert_ok!(Unique::burn_item(1104			origin1.clone(),1105			CollectionId(1),1106			TokenId(0),1107			51108		));1109		assert_noop!(1110			Unique::burn_item(origin1, CollectionId(1), TokenId(0), 5).map_err(|e| e.error),1111			CommonError::<Test>::TokenValueTooLow1112		);11131114		assert_eq!(1115			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1116			01117		);1118	});1119}11201121#[test]1122fn burn_fungible_item_with_token_id() {1123	new_test_ext().execute_with(|| {1124		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));11251126		let origin1 = Origin::signed(1);1127		assert_ok!(Unique::add_collection_admin(1128			origin1.clone(),1129			collection_id,1130			account(2)1131		));11321133		let data = default_fungible_data();1134		create_test_item(collection_id, &data.into());11351136		// check balance (collection with id = 1, user id = 1)1137		assert_eq!(1138			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1139			51140		);11411142		// Try to burn item using Token ID1143		assert_noop!(1144			Unique::burn_item(origin1, CollectionId(1), TokenId(1), 5).map_err(|e| e.error),1145			<pallet_fungible::Error::<Test>>::FungibleItemsHaveNoId1146		);1147	});1148}1149#[test]1150fn burn_refungible_item() {1151	new_test_ext().execute_with(|| {1152		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));1153		let origin1 = Origin::signed(1);11541155		assert_ok!(Unique::set_mint_permission(1156			origin1.clone(),1157			collection_id,1158			true1159		));1160		assert_ok!(Unique::set_public_access_mode(1161			origin1.clone(),1162			collection_id,1163			AccessMode::AllowList1164		));1165		assert_ok!(Unique::add_to_allow_list(1166			origin1.clone(),1167			collection_id,1168			account(1)1169		));11701171		assert_ok!(Unique::add_collection_admin(1172			origin1.clone(),1173			collection_id,1174			account(2)1175		));11761177		let data = default_re_fungible_data();1178		create_test_item(collection_id, &data.into());11791180		// check balance (collection with id = 1, user id = 2)1181		assert_eq!(1182			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),1183			11184		);1185		assert_eq!(1186			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1187			10231188		);11891190		// burn item1191		assert_ok!(Unique::burn_item(1192			origin1.clone(),1193			collection_id,1194			TokenId(1),1195			10231196		));1197		assert_noop!(1198			Unique::burn_item(origin1, collection_id, TokenId(1), 1023).map_err(|e| e.error),1199			CommonError::<Test>::TokenValueTooLow1200		);12011202		assert_eq!(1203			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1204			01205		);1206	});1207}12081209#[test]1210fn add_collection_admin() {1211	new_test_ext().execute_with(|| {1212		let collection1_id =1213			create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1214		let origin1 = Origin::signed(1);12151216		// Add collection admins1217		assert_ok!(Unique::add_collection_admin(1218			origin1.clone(),1219			collection1_id,1220			account(2)1221		));1222		assert_ok!(Unique::add_collection_admin(1223			origin1,1224			collection1_id,1225			account(3)1226		));12271228		// Owner is not an admin by default1229		assert_eq!(1230			<pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(1))),1231			false1232		);1233		assert!(<pallet_common::IsAdmin<Test>>::get((1234			CollectionId(1),1235			account(2)1236		)));1237		assert!(<pallet_common::IsAdmin<Test>>::get((1238			CollectionId(1),1239			account(3)1240		)));1241	});1242}12431244#[test]1245fn remove_collection_admin() {1246	new_test_ext().execute_with(|| {1247		let collection1_id =1248			create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1249		let origin1 = Origin::signed(1);1250		let origin2 = Origin::signed(2);12511252		// Add collection admins 2 and 31253		assert_ok!(Unique::add_collection_admin(1254			origin1.clone(),1255			collection1_id,1256			account(2)1257		));1258		assert_ok!(Unique::add_collection_admin(1259			origin1,1260			collection1_id,1261			account(3)1262		));12631264		assert!(<pallet_common::IsAdmin<Test>>::get((1265			CollectionId(1),1266			account(2)1267		)));1268		assert!(<pallet_common::IsAdmin<Test>>::get((1269			CollectionId(1),1270			account(3)1271		)));12721273		// remove admin 31274		assert_ok!(Unique::remove_collection_admin(1275			origin2,1276			CollectionId(1),1277			account(3)1278		));12791280		// 2 is still admin, 3 is not an admin anymore1281		assert!(<pallet_common::IsAdmin<Test>>::get((1282			CollectionId(1),1283			account(2)1284		)));1285		assert_eq!(1286			<pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(3))),1287			false1288		);1289	});1290}12911292#[test]1293fn balance_of() {1294	new_test_ext().execute_with(|| {1295		let nft_collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1296		let fungible_collection_id =1297			create_test_collection(&CollectionMode::Fungible(3), CollectionId(2));1298		let re_fungible_collection_id =1299			create_test_collection(&CollectionMode::ReFungible, CollectionId(3));13001301		// check balance before1302		assert_eq!(1303			<pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1304			01305		);1306		assert_eq!(1307			<pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1308			01309		);1310		assert_eq!(1311			<pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1312			01313		);13141315		let nft_data = default_nft_data();1316		create_test_item(nft_collection_id, &nft_data.into());13171318		let fungible_data = default_fungible_data();1319		create_test_item(fungible_collection_id, &fungible_data.into());13201321		let re_fungible_data = default_re_fungible_data();1322		create_test_item(re_fungible_collection_id, &re_fungible_data.into());13231324		// check balance (collection with id = 1, user id = 1)1325		assert_eq!(1326			<pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1327			11328		);1329		assert_eq!(1330			<pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1331			51332		);1333		assert_eq!(1334			<pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1335			11336		);13371338		assert_eq!(1339			<pallet_nonfungible::Owned<Test>>::get((nft_collection_id, account(1), TokenId(1))),1340			true1341		);1342		assert_eq!(1343			<pallet_refungible::Owned<Test>>::get((1344				re_fungible_collection_id,1345				account(1),1346				TokenId(1)1347			)),1348			true1349		);1350	});1351}13521353#[test]1354fn approve() {1355	new_test_ext().execute_with(|| {1356		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));13571358		let data = default_nft_data();1359		create_test_item(collection_id, &data.into());13601361		let origin1 = Origin::signed(1);13621363		// approve1364		assert_ok!(Unique::approve(1365			origin1,1366			account(2),1367			CollectionId(1),1368			TokenId(1),1369			11370		));1371		assert_eq!(1372			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1373			account(2)1374		);1375	});1376}13771378#[test]1379fn transfer_from() {1380	new_test_ext().execute_with(|| {1381		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1382		let origin1 = Origin::signed(1);1383		let origin2 = Origin::signed(2);13841385		let data = default_nft_data();1386		create_test_item(collection_id, &data.into());13871388		// approve1389		assert_ok!(Unique::approve(1390			origin1.clone(),1391			account(2),1392			CollectionId(1),1393			TokenId(1),1394			11395		));1396		assert_eq!(1397			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1398			account(2)1399		);14001401		assert_ok!(Unique::set_mint_permission(1402			origin1.clone(),1403			CollectionId(1),1404			true1405		));1406		assert_ok!(Unique::set_public_access_mode(1407			origin1.clone(),1408			CollectionId(1),1409			AccessMode::AllowList1410		));1411		assert_ok!(Unique::add_to_allow_list(1412			origin1.clone(),1413			CollectionId(1),1414			account(1)1415		));1416		assert_ok!(Unique::add_to_allow_list(1417			origin1.clone(),1418			CollectionId(1),1419			account(2)1420		));1421		assert_ok!(Unique::add_to_allow_list(1422			origin1,1423			CollectionId(1),1424			account(3)1425		));14261427		assert_ok!(Unique::transfer_from(1428			origin2,1429			account(1),1430			account(2),1431			CollectionId(1),1432			TokenId(1),1433			11434		));14351436		// after transfer1437		assert_eq!(1438			<pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(1))),1439			01440		);1441		assert_eq!(1442			<pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(2))),1443			11444		);1445	});1446}14471448// #endregion14491450// Coverage tests region1451// #region14521453#[test]1454fn owner_can_add_address_to_allow_list() {1455	new_test_ext().execute_with(|| {1456		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));14571458		let origin1 = Origin::signed(1);1459		assert_ok!(Unique::add_to_allow_list(1460			origin1,1461			collection_id,1462			account(2)1463		));1464		assert!(<pallet_common::Allowlist<Test>>::get((1465			collection_id,1466			account(2)1467		)));1468	});1469}14701471#[test]1472fn admin_can_add_address_to_allow_list() {1473	new_test_ext().execute_with(|| {1474		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1475		let origin1 = Origin::signed(1);1476		let origin2 = Origin::signed(2);14771478		assert_ok!(Unique::add_collection_admin(1479			origin1,1480			collection_id,1481			account(2)1482		));1483		assert_ok!(Unique::add_to_allow_list(1484			origin2,1485			collection_id,1486			account(3)1487		));1488		assert!(<pallet_common::Allowlist<Test>>::get((1489			collection_id,1490			account(3)1491		)));1492	});1493}14941495#[test]1496fn nonprivileged_user_cannot_add_address_to_allow_list() {1497	new_test_ext().execute_with(|| {1498		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));14991500		let origin2 = Origin::signed(2);1501		assert_noop!(1502			Unique::add_to_allow_list(origin2, collection_id, account(3)),1503			CommonError::<Test>::NoPermission1504		);1505	});1506}15071508#[test]1509fn nobody_can_add_address_to_allow_list_of_nonexisting_collection() {1510	new_test_ext().execute_with(|| {1511		let origin1 = Origin::signed(1);15121513		assert_noop!(1514			Unique::add_to_allow_list(origin1, CollectionId(1), account(2)),1515			CommonError::<Test>::CollectionNotFound1516		);1517	});1518}15191520#[test]1521fn nobody_can_add_address_to_allow_list_of_deleted_collection() {1522	new_test_ext().execute_with(|| {1523		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15241525		let origin1 = Origin::signed(1);1526		assert_ok!(Unique::destroy_collection(origin1.clone(), collection_id));1527		assert_noop!(1528			Unique::add_to_allow_list(origin1, collection_id, account(2)),1529			CommonError::<Test>::CollectionNotFound1530		);1531	});1532}15331534// If address is already added to allow list, nothing happens1535#[test]1536fn address_is_already_added_to_allow_list() {1537	new_test_ext().execute_with(|| {1538		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1539		let origin1 = Origin::signed(1);15401541		assert_ok!(Unique::add_to_allow_list(1542			origin1.clone(),1543			collection_id,1544			account(2)1545		));1546		assert_ok!(Unique::add_to_allow_list(1547			origin1,1548			collection_id,1549			account(2)1550		));1551		assert!(<pallet_common::Allowlist<Test>>::get((1552			collection_id,1553			account(2)1554		)));1555	});1556}15571558#[test]1559fn owner_can_remove_address_from_allow_list() {1560	new_test_ext().execute_with(|| {1561		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15621563		let origin1 = Origin::signed(1);1564		assert_ok!(Unique::add_to_allow_list(1565			origin1.clone(),1566			collection_id,1567			account(2)1568		));1569		assert_ok!(Unique::remove_from_allow_list(1570			origin1,1571			collection_id,1572			account(2)1573		));1574		assert_eq!(1575			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1576			false1577		);1578	});1579}15801581#[test]1582fn admin_can_remove_address_from_allow_list() {1583	new_test_ext().execute_with(|| {1584		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1585		let origin1 = Origin::signed(1);1586		let origin2 = Origin::signed(2);15871588		// Owner adds admin1589		assert_ok!(Unique::add_collection_admin(1590			origin1.clone(),1591			collection_id,1592			account(2)1593		));15941595		// Owner adds address 3 to allow list1596		assert_ok!(Unique::add_to_allow_list(1597			origin1,1598			collection_id,1599			account(3)1600		));16011602		// Admin removes address 3 from allow list1603		assert_ok!(Unique::remove_from_allow_list(1604			origin2,1605			collection_id,1606			account(3)1607		));1608		assert_eq!(1609			<pallet_common::Allowlist<Test>>::get((collection_id, account(3))),1610			false1611		);1612	});1613}16141615#[test]1616fn nonprivileged_user_cannot_remove_address_from_allow_list() {1617	new_test_ext().execute_with(|| {1618		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1619		let origin1 = Origin::signed(1);1620		let origin2 = Origin::signed(2);16211622		assert_ok!(Unique::add_to_allow_list(1623			origin1,1624			collection_id,1625			account(2)1626		));1627		assert_noop!(1628			Unique::remove_from_allow_list(origin2, collection_id, account(2)),1629			CommonError::<Test>::NoPermission1630		);1631		assert!(<pallet_common::Allowlist<Test>>::get((1632			collection_id,1633			account(2)1634		)));1635	});1636}16371638#[test]1639fn nobody_can_remove_address_from_allow_list_of_nonexisting_collection() {1640	new_test_ext().execute_with(|| {1641		let origin1 = Origin::signed(1);16421643		assert_noop!(1644			Unique::remove_from_allow_list(origin1, CollectionId(1), account(2)),1645			CommonError::<Test>::CollectionNotFound1646		);1647	});1648}16491650#[test]1651fn nobody_can_remove_address_from_allow_list_of_deleted_collection() {1652	new_test_ext().execute_with(|| {1653		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1654		let origin1 = Origin::signed(1);1655		let origin2 = Origin::signed(2);16561657		// Add account 2 to allow list1658		assert_ok!(Unique::add_to_allow_list(1659			origin1.clone(),1660			collection_id,1661			account(2)1662		));16631664		// Account 2 is in collection allow-list1665		assert!(<pallet_common::Allowlist<Test>>::get((1666			collection_id,1667			account(2)1668		)));16691670		// Destroy collection1671		assert_ok!(Unique::destroy_collection(origin1, collection_id));16721673		// Attempt to remove account 2 from collection allow-list => error1674		assert_noop!(1675			Unique::remove_from_allow_list(origin2, collection_id, account(2)),1676			CommonError::<Test>::CollectionNotFound1677		);16781679		// Account 2 is not found in collection allow-list anyway1680		assert_eq!(1681			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1682			false1683		);1684	});1685}16861687// If address is already removed from allow list, nothing happens1688#[test]1689fn address_is_already_removed_from_allow_list() {1690	new_test_ext().execute_with(|| {1691		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1692		let origin1 = Origin::signed(1);16931694		assert_ok!(Unique::add_to_allow_list(1695			origin1.clone(),1696			collection_id,1697			account(2)1698		));1699		assert_ok!(Unique::remove_from_allow_list(1700			origin1.clone(),1701			collection_id,1702			account(2)1703		));1704		assert_eq!(1705			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1706			false1707		);1708		assert_ok!(Unique::remove_from_allow_list(1709			origin1,1710			collection_id,1711			account(2)1712		));1713		assert_eq!(1714			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1715			false1716		);1717	});1718}17191720// If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom (2 tests)1721#[test]1722fn allow_list_test_1() {1723	new_test_ext().execute_with(|| {1724		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));17251726		let origin1 = Origin::signed(1);17271728		let data = default_nft_data();1729		create_test_item(collection_id, &data.into());17301731		assert_ok!(Unique::set_public_access_mode(1732			origin1.clone(),1733			collection_id,1734			AccessMode::AllowList1735		));1736		assert_ok!(Unique::add_to_allow_list(1737			origin1.clone(),1738			collection_id,1739			account(2)1740		));17411742		assert_noop!(1743			Unique::transfer(origin1, account(3), CollectionId(1), TokenId(1), 1)1744				.map_err(|e| e.error),1745			CommonError::<Test>::AddressNotInAllowlist1746		);1747	});1748}17491750#[test]1751fn allow_list_test_2() {1752	new_test_ext().execute_with(|| {1753		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1754		let origin1 = Origin::signed(1);17551756		let data = default_nft_data();1757		create_test_item(collection_id, &data.into());17581759		assert_ok!(Unique::set_public_access_mode(1760			origin1.clone(),1761			collection_id,1762			AccessMode::AllowList1763		));1764		assert_ok!(Unique::add_to_allow_list(1765			origin1.clone(),1766			collection_id,1767			account(1)1768		));1769		assert_ok!(Unique::add_to_allow_list(1770			origin1.clone(),1771			collection_id,1772			account(2)1773		));17741775		// do approve1776		assert_ok!(Unique::approve(1777			origin1.clone(),1778			account(1),1779			collection_id,1780			TokenId(1),1781			11782		));1783		assert_eq!(1784			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1785			account(1)1786		);17871788		assert_ok!(Unique::remove_from_allow_list(1789			origin1.clone(),1790			collection_id,1791			account(1)1792		));17931794		assert_noop!(1795			Unique::transfer_from(1796				origin1,1797				account(1),1798				account(3),1799				CollectionId(1),1800				TokenId(1),1801				11802			)1803			.map_err(|e| e.error),1804			CommonError::<Test>::AddressNotInAllowlist1805		);1806	});1807}18081809// If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom (2 tests)1810#[test]1811fn allow_list_test_3() {1812	new_test_ext().execute_with(|| {1813		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18141815		let origin1 = Origin::signed(1);18161817		let data = default_nft_data();1818		create_test_item(collection_id, &data.into());18191820		assert_ok!(Unique::set_public_access_mode(1821			origin1.clone(),1822			collection_id,1823			AccessMode::AllowList1824		));1825		assert_ok!(Unique::add_to_allow_list(1826			origin1.clone(),1827			collection_id,1828			account(1)1829		));18301831		assert_noop!(1832			Unique::transfer(origin1, account(3), collection_id, TokenId(1), 1)1833				.map_err(|e| e.error),1834			CommonError::<Test>::AddressNotInAllowlist1835		);1836	});1837}18381839#[test]1840fn allow_list_test_4() {1841	new_test_ext().execute_with(|| {1842		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18431844		let origin1 = Origin::signed(1);18451846		let data = default_nft_data();1847		create_test_item(collection_id, &data.into());18481849		assert_ok!(Unique::set_public_access_mode(1850			origin1.clone(),1851			collection_id,1852			AccessMode::AllowList1853		));1854		assert_ok!(Unique::add_to_allow_list(1855			origin1.clone(),1856			collection_id,1857			account(1)1858		));1859		assert_ok!(Unique::add_to_allow_list(1860			origin1.clone(),1861			collection_id,1862			account(2)1863		));18641865		// do approve1866		assert_ok!(Unique::approve(1867			origin1.clone(),1868			account(1),1869			collection_id,1870			TokenId(1),1871			11872		));1873		assert_eq!(1874			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1875			account(1)1876		);18771878		assert_ok!(Unique::remove_from_allow_list(1879			origin1.clone(),1880			collection_id,1881			account(2)1882		));18831884		assert_noop!(1885			Unique::transfer_from(1886				origin1,1887				account(1),1888				account(3),1889				collection_id,1890				TokenId(1),1891				11892			)1893			.map_err(|e| e.error),1894			CommonError::<Test>::AddressNotInAllowlist1895		);1896	});1897}18981899// If Public Access mode is set to AllowList, tokens can’t be destroyed by a non-allowlisted address (even if it owned them before enabling AllowList mode)1900#[test]1901fn allow_list_test_5() {1902	new_test_ext().execute_with(|| {1903		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19041905		let origin1 = Origin::signed(1);19061907		let data = default_nft_data();1908		create_test_item(collection_id, &data.into());19091910		assert_ok!(Unique::set_public_access_mode(1911			origin1.clone(),1912			collection_id,1913			AccessMode::AllowList1914		));1915		assert_noop!(1916			Unique::burn_item(origin1.clone(), CollectionId(1), TokenId(1), 1).map_err(|e| e.error),1917			CommonError::<Test>::AddressNotInAllowlist1918		);1919	});1920}19211922// If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method).1923#[test]1924fn allow_list_test_6() {1925	new_test_ext().execute_with(|| {1926		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19271928		let origin1 = Origin::signed(1);19291930		let data = default_nft_data();1931		create_test_item(collection_id, &data.into());19321933		assert_ok!(Unique::set_public_access_mode(1934			origin1.clone(),1935			collection_id,1936			AccessMode::AllowList1937		));19381939		// do approve1940		assert_noop!(1941			Unique::approve(origin1, account(1), CollectionId(1), TokenId(1), 1)1942				.map_err(|e| e.error),1943			CommonError::<Test>::AddressNotInAllowlist1944		);1945	});1946}19471948// If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests) and1949//          tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests)1950#[test]1951fn allow_list_test_7() {1952	new_test_ext().execute_with(|| {1953		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19541955		let data = default_nft_data();1956		create_test_item(collection_id, &data.into());19571958		let origin1 = Origin::signed(1);19591960		assert_ok!(Unique::set_public_access_mode(1961			origin1.clone(),1962			collection_id,1963			AccessMode::AllowList1964		));1965		assert_ok!(Unique::add_to_allow_list(1966			origin1.clone(),1967			collection_id,1968			account(1)1969		));1970		assert_ok!(Unique::add_to_allow_list(1971			origin1.clone(),1972			collection_id,1973			account(2)1974		));19751976		assert_ok!(Unique::transfer(1977			origin1,1978			account(2),1979			CollectionId(1),1980			TokenId(1),1981			11982		));1983	});1984}19851986#[test]1987fn allow_list_test_8() {1988	new_test_ext().execute_with(|| {1989		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19901991		// Create NFT for account 11992		let data = default_nft_data();1993		create_test_item(collection_id, &data.into());19941995		let origin1 = Origin::signed(1);19961997		// Toggle Allow List mode and add accounts 1 and 21998		assert_ok!(Unique::set_public_access_mode(1999			origin1.clone(),2000			collection_id,2001			AccessMode::AllowList2002		));2003		assert_ok!(Unique::add_to_allow_list(2004			origin1.clone(),2005			collection_id,2006			account(1)2007		));2008		assert_ok!(Unique::add_to_allow_list(2009			origin1.clone(),2010			collection_id,2011			account(2)2012		));20132014		// Sself-approve account 1 for NFT 12015		assert_ok!(Unique::approve(2016			origin1.clone(),2017			account(1),2018			CollectionId(1),2019			TokenId(1),2020			12021		));2022		assert_eq!(2023			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),2024			account(1)2025		);20262027		// Transfer from 1 to 22028		assert_ok!(Unique::transfer_from(2029			origin1,2030			account(1),2031			account(2),2032			CollectionId(1),2033			TokenId(1),2034			12035		));2036	});2037}20382039// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner.2040#[test]2041fn allow_list_test_9() {2042	new_test_ext().execute_with(|| {2043		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2044		let origin1 = Origin::signed(1);20452046		assert_ok!(Unique::set_public_access_mode(2047			origin1.clone(),2048			collection_id,2049			AccessMode::AllowList2050		));2051		assert_ok!(Unique::set_mint_permission(origin1, collection_id, false));20522053		let data = default_nft_data();2054		create_test_item(collection_id, &data.into());2055	});2056}20572058// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin.2059#[test]2060fn allow_list_test_10() {2061	new_test_ext().execute_with(|| {2062		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));20632064		let origin1 = Origin::signed(1);2065		let origin2 = Origin::signed(2);20662067		assert_ok!(Unique::set_public_access_mode(2068			origin1.clone(),2069			collection_id,2070			AccessMode::AllowList2071		));2072		assert_ok!(Unique::set_mint_permission(2073			origin1.clone(),2074			collection_id,2075			false2076		));20772078		assert_ok!(Unique::add_collection_admin(2079			origin1,2080			collection_id,2081			account(2)2082		));20832084		assert_ok!(Unique::create_item(2085			origin2,2086			collection_id,2087			account(2),2088			default_nft_data().into()2089		));2090	});2091}20922093// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and allow listed address.2094#[test]2095fn allow_list_test_11() {2096	new_test_ext().execute_with(|| {2097		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));20982099		let origin1 = Origin::signed(1);2100		let origin2 = Origin::signed(2);21012102		assert_ok!(Unique::set_public_access_mode(2103			origin1.clone(),2104			collection_id,2105			AccessMode::AllowList2106		));2107		assert_ok!(Unique::set_mint_permission(2108			origin1.clone(),2109			collection_id,2110			false2111		));2112		assert_ok!(Unique::add_to_allow_list(2113			origin1,2114			collection_id,2115			account(2)2116		));21172118		assert_noop!(2119			Unique::create_item(2120				origin2,2121				CollectionId(1),2122				account(2),2123				default_nft_data().into()2124			)2125			.map_err(|e| e.error),2126			CommonError::<Test>::PublicMintingNotAllowed2127		);2128	});2129}21302131// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-allow listed address.2132#[test]2133fn allow_list_test_12() {2134	new_test_ext().execute_with(|| {2135		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21362137		let origin1 = Origin::signed(1);2138		let origin2 = Origin::signed(2);21392140		assert_ok!(Unique::set_public_access_mode(2141			origin1.clone(),2142			collection_id,2143			AccessMode::AllowList2144		));2145		assert_ok!(Unique::set_mint_permission(origin1, collection_id, false));21462147		assert_noop!(2148			Unique::create_item(2149				origin2,2150				CollectionId(1),2151				account(2),2152				default_nft_data().into()2153			)2154			.map_err(|e| e.error),2155			CommonError::<Test>::PublicMintingNotAllowed2156		);2157	});2158}21592160// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner.2161#[test]2162fn allow_list_test_13() {2163	new_test_ext().execute_with(|| {2164		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21652166		let origin1 = Origin::signed(1);21672168		assert_ok!(Unique::set_public_access_mode(2169			origin1.clone(),2170			collection_id,2171			AccessMode::AllowList2172		));2173		assert_ok!(Unique::set_mint_permission(origin1, collection_id, true));21742175		let data = default_nft_data();2176		create_test_item(collection_id, &data.into());2177	});2178}21792180// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin.2181#[test]2182fn allow_list_test_14() {2183	new_test_ext().execute_with(|| {2184		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21852186		let origin1 = Origin::signed(1);2187		let origin2 = Origin::signed(2);21882189		assert_ok!(Unique::set_public_access_mode(2190			origin1.clone(),2191			collection_id,2192			AccessMode::AllowList2193		));2194		assert_ok!(Unique::set_mint_permission(2195			origin1.clone(),2196			collection_id,2197			true2198		));21992200		assert_ok!(Unique::add_collection_admin(2201			origin1,2202			collection_id,2203			account(2)2204		));22052206		assert_ok!(Unique::create_item(2207			origin2,2208			collection_id,2209			account(2),2210			default_nft_data().into()2211		));2212	});2213}22142215// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-allow listed address.2216#[test]2217fn allow_list_test_15() {2218	new_test_ext().execute_with(|| {2219		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22202221		let origin1 = Origin::signed(1);2222		let origin2 = Origin::signed(2);22232224		assert_ok!(Unique::set_public_access_mode(2225			origin1.clone(),2226			collection_id,2227			AccessMode::AllowList2228		));2229		assert_ok!(Unique::set_mint_permission(origin1, collection_id, true));22302231		assert_noop!(2232			Unique::create_item(2233				origin2,2234				collection_id,2235				account(2),2236				default_nft_data().into()2237			)2238			.map_err(|e| e.error),2239			CommonError::<Test>::AddressNotInAllowlist2240		);2241	});2242}22432244// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by non-privileged and allow listed address.2245#[test]2246fn allow_list_test_16() {2247	new_test_ext().execute_with(|| {2248		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22492250		let origin1 = Origin::signed(1);2251		let origin2 = Origin::signed(2);22522253		assert_ok!(Unique::set_public_access_mode(2254			origin1.clone(),2255			collection_id,2256			AccessMode::AllowList2257		));2258		assert_ok!(Unique::set_mint_permission(2259			origin1.clone(),2260			collection_id,2261			true2262		));2263		assert_ok!(Unique::add_to_allow_list(2264			origin1,2265			collection_id,2266			account(2)2267		));22682269		assert_ok!(Unique::create_item(2270			origin2,2271			collection_id,2272			account(2),2273			default_nft_data().into()2274		));2275	});2276}22772278// Total number of collections. Positive test2279#[test]2280fn total_number_collections_bound() {2281	new_test_ext().execute_with(|| {2282		create_test_collection(&CollectionMode::NFT, CollectionId(1));2283	});2284}22852286#[test]2287fn create_max_collections() {2288	new_test_ext().execute_with(|| {2289		for i in 1..COLLECTION_NUMBER_LIMIT {2290			create_test_collection(&CollectionMode::NFT, CollectionId(i));2291		}2292	});2293}22942295// Total number of collections. Negative test2296#[test]2297fn total_number_collections_bound_neg() {2298	new_test_ext().execute_with(|| {2299		let origin1 = Origin::signed(1);23002301		for i in 1..=COLLECTION_NUMBER_LIMIT {2302			create_test_collection(&CollectionMode::NFT, CollectionId(i));2303		}23042305		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();2306		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();2307		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();23082309		let data: CreateCollectionData<u64> = CreateCollectionData {2310			name: col_name1.try_into().unwrap(),2311			description: col_desc1.try_into().unwrap(),2312			token_prefix: token_prefix1.try_into().unwrap(),2313			mode: CollectionMode::NFT,2314			..Default::default()2315		};23162317		// 11-th collection in chain. Expects error2318		assert_noop!(2319			Unique::create_collection_ex(origin1, data),2320			CommonError::<Test>::TotalCollectionsLimitExceeded2321		);2322	});2323}23242325// Owned tokens by a single address. Positive test2326#[test]2327fn owned_tokens_bound() {2328	new_test_ext().execute_with(|| {2329		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23302331		let data = default_nft_data();2332		create_test_item(collection_id, &data.clone().into());2333		create_test_item(collection_id, &data.into());2334	});2335}23362337// Owned tokens by a single address. Negotive test2338#[test]2339fn owned_tokens_bound_neg() {2340	new_test_ext().execute_with(|| {2341		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23422343		let origin1 = Origin::signed(1);23442345		for _ in 1..=MAX_TOKEN_OWNERSHIP {2346			let data = default_nft_data();2347			create_test_item(collection_id, &data.clone().into());2348		}23492350		let data = default_nft_data();2351		assert_noop!(2352			Unique::create_item(origin1, CollectionId(1), account(1), data.into())2353				.map_err(|e| e.error),2354			CommonError::<Test>::AccountTokenLimitExceeded2355		);2356	});2357}23582359// Number of collection admins. Positive test2360#[test]2361fn collection_admins_bound() {2362	new_test_ext().execute_with(|| {2363		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23642365		let origin1 = Origin::signed(1);23662367		assert_ok!(Unique::add_collection_admin(2368			origin1.clone(),2369			collection_id,2370			account(2)2371		));2372		assert_ok!(Unique::add_collection_admin(2373			origin1,2374			collection_id,2375			account(3)2376		));2377	});2378}23792380// Number of collection admins. Negotive test2381#[test]2382fn collection_admins_bound_neg() {2383	new_test_ext().execute_with(|| {2384		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23852386		let origin1 = Origin::signed(1);23872388		for i in 0..COLLECTION_ADMINS_LIMIT {2389			assert_ok!(Unique::add_collection_admin(2390				origin1.clone(),2391				collection_id,2392				account((2 + i).into())2393			));2394		}2395		assert_noop!(2396			Unique::add_collection_admin(2397				origin1,2398				collection_id,2399				account((3 + COLLECTION_ADMINS_LIMIT).into())2400			),2401			CommonError::<Test>::CollectionAdminCountExceeded2402		);2403	});2404}2405// #endregion24062407#[test]2408fn set_const_on_chain_schema() {2409	new_test_ext().execute_with(|| {2410		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24112412		let origin1 = Origin::signed(1);2413		assert_ok!(Unique::set_const_on_chain_schema(2414			origin1,2415			collection_id,2416			b"test const on chain schema".to_vec().try_into().unwrap()2417		));24182419		assert_eq!(2420			<pallet_common::CollectionData<Test>>::get((2421				collection_id,2422				CollectionField::ConstOnChainSchema2423			)),2424			b"test const on chain schema".to_vec()2425		);2426	});2427}24282429#[test]2430fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {2431	new_test_ext().execute_with(|| {2432		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24332434		let origin1 = Origin::signed(1);24352436		let data = default_nft_data();2437		create_test_item(CollectionId(1), &data.into());24382439		let variable_data = b"test data".to_vec();2440		assert_ok!(Unique::set_variable_meta_data(2441			origin1,2442			collection_id,2443			TokenId(1),2444			variable_data.clone().try_into().unwrap()2445		));24462447		assert_eq!(2448			<pallet_nonfungible::TokenData<Test>>::get((collection_id, 1))2449				.unwrap()2450				.variable_data,2451			variable_data2452		);2453	});2454}24552456#[test]2457fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {2458	new_test_ext().execute_with(|| {2459		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));24602461		let origin1 = Origin::signed(1);24622463		let data = default_re_fungible_data();2464		create_test_item(collection_id, &data.into());24652466		let variable_data = b"test data".to_vec();2467		assert_ok!(Unique::set_variable_meta_data(2468			origin1,2469			collection_id,2470			TokenId(1),2471			variable_data.clone().try_into().unwrap()2472		));24732474		assert_eq!(2475			<pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1))).variable_data,2476			variable_data2477		);2478	});2479}24802481#[test]2482fn set_variable_meta_data_on_fungible_token_fails() {2483	new_test_ext().execute_with(|| {2484		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));24852486		let origin1 = Origin::signed(1);24872488		let data = default_fungible_data();2489		create_test_item(collection_id, &data.into());24902491		let variable_data = b"test data".to_vec();2492		assert_noop!(2493			Unique::set_variable_meta_data(2494				origin1,2495				collection_id,2496				TokenId(0),2497				variable_data.try_into().unwrap()2498			)2499			.map_err(|e| e.error),2500			<pallet_fungible::Error<Test>>::FungibleItemsDontHaveData2501		);2502	});2503}25042505#[test]2506fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {2507	new_test_ext().execute_with(|| {2508		//default_limits();25092510		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));25112512		let origin1 = Origin::signed(1);25132514		let data = default_nft_data();2515		create_test_item(collection_id, &data.into());25162517		assert_ok!(Unique::set_meta_update_permission_flag(2518			origin1.clone(),2519			collection_id,2520			MetaUpdatePermission::ItemOwner,2521		));25222523		let variable_data = b"ten chars.".to_vec();2524		assert_ok!(Unique::set_variable_meta_data(2525			origin1,2526			collection_id,2527			TokenId(1),2528			variable_data.clone().try_into().unwrap()2529		));25302531		assert_eq!(2532			<pallet_nonfungible::TokenData<Test>>::get((collection_id, TokenId(1)))2533				.unwrap()2534				.variable_data,2535			variable_data2536		);2537	});2538}25392540#[test]2541fn collection_transfer_flag_works() {2542	new_test_ext().execute_with(|| {2543		let origin1 = Origin::signed(1);25442545		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2546		assert_ok!(Unique::set_transfers_enabled_flag(2547			origin1,2548			collection_id,2549			true2550		));25512552		let data = default_nft_data();2553		create_test_item(collection_id, &data.into());2554		assert_eq!(2555			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2556			12557		);2558		assert_eq!(2559			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2560			true2561		);25622563		let origin1 = Origin::signed(1);25642565		// default scenario2566		assert_ok!(Unique::transfer(2567			origin1,2568			account(2),2569			collection_id,2570			TokenId(1),2571			12572		));2573		assert_eq!(2574			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2575			false2576		);2577		assert_eq!(2578			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2579			true2580		);2581		assert_eq!(2582			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2583			02584		);2585		assert_eq!(2586			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2587			12588		);2589	});2590}25912592#[test]2593fn set_variable_meta_data_on_nft_with_admin_flag() {2594	new_test_ext().execute_with(|| {2595		// default_limits();25962597		let collection_id =2598			create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));25992600		let origin1 = Origin::signed(1);2601		let origin2 = Origin::signed(2);26022603		assert_ok!(Unique::set_mint_permission(2604			origin2.clone(),2605			collection_id,2606			true2607		));2608		assert_ok!(Unique::add_to_allow_list(2609			origin2.clone(),2610			collection_id,2611			account(1)2612		));26132614		assert_ok!(Unique::add_collection_admin(2615			origin2.clone(),2616			collection_id,2617			account(1)2618		));26192620		let data = default_nft_data();2621		create_test_item(collection_id, &data.into());26222623		assert_ok!(Unique::set_meta_update_permission_flag(2624			origin2.clone(),2625			collection_id,2626			MetaUpdatePermission::Admin,2627		));26282629		let variable_data = b"test.".to_vec();2630		assert_ok!(Unique::set_variable_meta_data(2631			origin1,2632			collection_id,2633			TokenId(1),2634			variable_data.clone().try_into().unwrap()2635		));26362637		assert_eq!(2638			<pallet_nonfungible::TokenData<Test>>::get((collection_id, 1))2639				.unwrap()2640				.variable_data,2641			variable_data2642		);2643	});2644}26452646#[test]2647fn set_variable_meta_data_on_nft_with_admin_flag_neg() {2648	new_test_ext().execute_with(|| {2649		// default_limits();26502651		let collection_id =2652			create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));26532654		let origin1 = Origin::signed(1);2655		let origin2 = Origin::signed(2);26562657		assert_ok!(Unique::set_mint_permission(2658			origin2.clone(),2659			collection_id,2660			true2661		));2662		assert_ok!(Unique::add_to_allow_list(2663			origin2.clone(),2664			collection_id,2665			account(1)2666		));26672668		let data = default_nft_data();2669		create_test_item(collection_id, &data.into());26702671		assert_ok!(Unique::set_meta_update_permission_flag(2672			origin2.clone(),2673			collection_id,2674			MetaUpdatePermission::Admin,2675		));26762677		let variable_data = b"test.".to_vec();2678		assert_noop!(2679			Unique::set_variable_meta_data(2680				origin1,2681				collection_id,2682				TokenId(1),2683				variable_data.try_into().unwrap()2684			)2685			.map_err(|e| e.error),2686			CommonError::<Test>::NoPermission2687		);2688	});2689}26902691#[test]2692fn set_variable_meta_flag_after_freeze() {2693	new_test_ext().execute_with(|| {2694		// default_limits();26952696		let collection_id =2697			create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));26982699		let origin2 = Origin::signed(2);27002701		assert_ok!(Unique::set_meta_update_permission_flag(2702			origin2.clone(),2703			collection_id,2704			MetaUpdatePermission::None,2705		));2706		assert_noop!(2707			Unique::set_meta_update_permission_flag(2708				origin2.clone(),2709				collection_id,2710				MetaUpdatePermission::Admin2711			),2712			CommonError::<Test>::MetadataFlagFrozen2713		);2714	});2715}27162717#[test]2718fn set_variable_meta_data_on_nft_with_none_flag_neg() {2719	new_test_ext().execute_with(|| {2720		// default_limits();27212722		let collection_id =2723			create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));2724		let origin1 = Origin::signed(1);27252726		let data = default_nft_data();2727		create_test_item(collection_id, &data.into());27282729		assert_ok!(Unique::set_meta_update_permission_flag(2730			origin1.clone(),2731			collection_id,2732			MetaUpdatePermission::None,2733		));27342735		let variable_data = b"test.".to_vec();2736		assert_noop!(2737			Unique::set_variable_meta_data(2738				origin1.clone(),2739				collection_id,2740				TokenId(1),2741				variable_data.try_into().unwrap()2742			)2743			.map_err(|e| e.error),2744			CommonError::<Test>::NoPermission2745		);2746	});2747}27482749#[test]2750fn collection_transfer_flag_works_neg() {2751	new_test_ext().execute_with(|| {2752		let origin1 = Origin::signed(1);27532754		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2755		assert_ok!(Unique::set_transfers_enabled_flag(2756			origin1,2757			collection_id,2758			false2759		));27602761		let data = default_nft_data();2762		create_test_item(collection_id, &data.into());2763		assert_eq!(2764			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2765			12766		);2767		assert_eq!(2768			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2769			true2770		);27712772		let origin1 = Origin::signed(1);27732774		// default scenario2775		assert_noop!(2776			Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 1)2777				.map_err(|e| e.error),2778			CommonError::<Test>::TransferNotAllowed2779		);2780		assert_eq!(2781			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2782			12783		);2784		assert_eq!(2785			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2786			02787		);2788		assert_eq!(2789			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2790			true2791		);2792		assert_eq!(2793			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2794			false2795		);2796	});2797}27982799#[test]2800fn collection_sponsoring() {2801	new_test_ext().execute_with(|| {2802		// default_limits();2803		let user1 = 1_u64;2804		let user2 = 777_u64;2805		let origin1 = Origin::signed(user1);2806		let origin2 = Origin::signed(user2);2807		let account2 = account(user2);28082809		let collection_id =2810			create_test_collection_for_owner(&CollectionMode::NFT, user1, CollectionId(1));2811		assert_ok!(Unique::set_collection_sponsor(2812			origin1.clone(),2813			collection_id,2814			user12815		));2816		assert_ok!(Unique::confirm_sponsorship(origin1.clone(), collection_id));28172818		// Expect error while have no permissions2819		assert!(Unique::create_item(2820			origin2.clone(),2821			collection_id,2822			account2.clone(),2823			default_nft_data().into()2824		)2825		.is_err());28262827		assert_ok!(Unique::set_public_access_mode(2828			origin1.clone(),2829			collection_id,2830			AccessMode::AllowList2831		));2832		assert_ok!(Unique::add_to_allow_list(2833			origin1.clone(),2834			collection_id,2835			account2.clone()2836		));2837		assert_ok!(Unique::set_mint_permission(2838			origin1.clone(),2839			collection_id,2840			true2841		));28422843		assert_ok!(Unique::create_item(2844			origin2,2845			collection_id,2846			account2,2847			default_nft_data().into()2848		));2849	});2850}
modifiedsmart_contracs/transfer/lib.rsdiffbeforeafterboth
--- a/smart_contracs/transfer/lib.rs
+++ b/smart_contracs/transfer/lib.rs
@@ -58,14 +58,12 @@
 pub enum CreateItemData {
     Nft {
         const_data: Vec<u8>,
-        variable_data: Vec<u8>,
     },
     Fungible {
         value: u128,
     },
     ReFungible {
         const_data: Vec<u8>,
-        variable_data: Vec<u8>,
         pieces: u128,
     },
 }
@@ -88,8 +86,6 @@
     fn approve(spender: DefaultAccountId, collection_id: u32, item_id: u32, amount: u128);
     #[ink(extension = 4, returns_result = false)]
     fn transfer_from(owner: DefaultAccountId, recipient: DefaultAccountId, collection_id: u32, item_id: u32, amount: u128);
-    #[ink(extension = 5, returns_result = false)]
-    fn set_variable_meta_data(collection_id: u32, item_id: u32, data: Vec<u8>);
     #[ink(extension = 6, returns_result = false)]
     fn toggle_allow_list(collection_id: u32, address: DefaultAccountId, allowlisted: bool);
 }
@@ -143,12 +139,6 @@
             let _ = self.env()
                 .extension()
                 .transfer_from(owner, recipient, collection_id, item_id, amount);
-        }
-        #[ink(message)]
-        pub fn set_variable_meta_data(&mut self, collection_id: u32, item_id: u32, data: Vec<u8>) {
-            let _ = self.env()
-                .extension()
-                .set_variable_meta_data(collection_id, item_id, data);
         }
         #[ink(message)]
         pub fn toggle_allow_list(&mut self, collection_id: u32, address: AccountId, allowlisted: bool) {
modifiedtests/package.jsondiffbeforeafterboth
--- a/tests/package.json
+++ b/tests/package.json
@@ -40,7 +40,6 @@
     "testMigrationStructure": "mocha --timeout 9999999 -r ts-node/register ./**/nesting/migration-check.test.ts",
     "testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts",
     "testSetSchemaVersion": "mocha --timeout 9999999 -r ts-node/register ./**/setSchemaVersion.test.ts",
-    "testSetVariableMetaData": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetaData.test.ts",
     "testSetCollectionLimits": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionLimits.test.ts",
     "testSetCollectionSponsor": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionSponsor.test.ts",
     "testConfirmSponsorship": "mocha --timeout 9999999 -r ts-node/register ./**/confirmSponsorship.test.ts",
modifiedtests/src/contracts.test.tsdiffbeforeafterboth
--- a/tests/src/contracts.test.ts
+++ b/tests/src/contracts.test.ts
@@ -111,7 +111,7 @@
       await addToAllowListExpectSuccess(alice, collectionId, contract.address);
       await addToAllowListExpectSuccess(alice, collectionId, bob.address);
 
-      const transferTx = contract.tx.createItem(value, gasLimit, bob.address, collectionId, {Nft: {const_data: '0x010203', variable_data: '0x020304'}});
+      const transferTx = contract.tx.createItem(value, gasLimit, bob.address, collectionId, {Nft: {const_data: '0x010203'}});
       const events = await submitTransactionAsync(alice, transferTx);
       const result = getGenericResult(events);
       expect(result.success).to.be.true;
@@ -121,7 +121,6 @@
         {
           owner: bob.address,
           constData: '0x010203',
-          variableData: '0x020304',
         },
       ]);
     });
@@ -140,9 +139,9 @@
       await addToAllowListExpectSuccess(alice, collectionId, bob.address);
 
       const transferTx = contract.tx.createMultipleItems(value, gasLimit, bob.address, collectionId, [
-        {Nft: {const_data: '0x010203', variable_data: '0x020304'}},
-        {Nft: {const_data: '0x010204', variable_data: '0x020305'}},
-        {Nft: {const_data: '0x010205', variable_data: '0x020306'}},
+        {Nft: {const_data: '0x010203'}},
+        {Nft: {const_data: '0x010204'}},
+        {Nft: {const_data: '0x010205'}},
       ]);
       const events = await submitTransactionAsync(alice, transferTx);
       const result = getGenericResult(events);
@@ -155,17 +154,14 @@
         {
           Owner: bob.address,
           ConstData: '0x010203',
-          VariableData: '0x020304',
         },
         {
           Owner: bob.address,
           ConstData: '0x010204',
-          VariableData: '0x020305',
         },
         {
           Owner: bob.address,
           ConstData: '0x010205',
-          VariableData: '0x020306',
         },
       ]);
     });
@@ -208,24 +204,6 @@
 
       const token: any = (await api.query.unique.nftItemList(collectionId, tokenId) as any).unwrap();
       expect(token.owner.toString()).to.be.equal(charlie.address);
-    });
-  });
-
-  it('SetVariableMetaData CE', async () => {
-    await usingApi(async api => {
-      const alice = privateKey('//Alice');
-
-      const collectionId = await createCollectionExpectSuccess();
-      const [contract] = await deployTransferContract(api);
-      const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', contract.address.toString());
-
-      const transferTx = contract.tx.setVariableMetaData(value, gasLimit, collectionId, tokenId, '0x121314');
-      const events = await submitTransactionAsync(alice, transferTx);
-      const result = getGenericResult(events);
-      expect(result.success).to.be.true;
-
-      const token: any = (await api.query.unique.nftItemList(collectionId, tokenId) as any).unwrap();
-      expect(token.variableData.toString()).to.be.equal('0x121314');
     });
   });
 
modifiedtests/src/createCollection.test.tsdiffbeforeafterboth
--- a/tests/src/createCollection.test.ts
+++ b/tests/src/createCollection.test.ts
@@ -74,7 +74,6 @@
           accountTokenOwnershipLimit: 3,
         },
         constOnChainSchema: '0x333333',
-        metaUpdatePermission: 'Admin',
       });
       const events = await submitTransactionAsync(alice, tx);
       const result = getCreateCollectionResult(events);
@@ -91,7 +90,6 @@
       expect(collection.sponsorship.asUnconfirmed.toString()).to.equal(bob.address);
       expect(collection.limits.accountTokenOwnershipLimit.unwrap().toNumber()).to.equal(3);
       expect(collection.constOnChainSchema.toString()).to.equal('0x333333');
-      expect(collection.metaUpdatePermission.isAdmin).to.be.true;
     });
   });
 });
modifiedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -30,7 +30,6 @@
   getBalance,
   getTokenOwner,
   getLastTokenId,
-  getVariableMetadata,
   getConstMetadata,
   getCreatedCollectionCount,
   createCollectionWithPropsExpectSuccess,
@@ -47,9 +46,9 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       const alice = privateKey('//Alice');
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await submitTransactionAsync(alice, createMultipleItemsTx);
@@ -63,10 +62,6 @@
       expect(await getConstMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
       expect(await getConstMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
       expect(await getConstMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
-
-      expect(await getVariableMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
-      expect(await getVariableMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
-      expect(await getVariableMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
     });
   });
 
@@ -97,9 +92,9 @@
       expect(itemsListIndexBefore).to.be.equal(0);
       const alice = privateKey('//Alice');
       const args = [
-        {ReFungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}},
-        {ReFungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},
-        {ReFungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},
+        {ReFungible: {const_data: [0x31], pieces: 1}},
+        {ReFungible: {const_data: [0x32], pieces: 1}},
+        {ReFungible: {const_data: [0x33], pieces: 1}},
       ];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
@@ -114,10 +109,6 @@
       expect(await getConstMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
       expect(await getConstMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
       expect(await getConstMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
-
-      expect(await getVariableMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
-      expect(await getVariableMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
-      expect(await getVariableMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
     });
   });
 
@@ -130,8 +121,8 @@
         tokenLimit: 2,
       });
       const args = [
-        {NFT: {const_data: 'A', variable_data: 'A'}},
-        {NFT: {const_data: 'B', variable_data: 'B'}},
+        {NFT: {const_data: 'A'}},
+        {NFT: {const_data: 'B'}},
       ];
       const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       const events = await submitTransactionAsync(alice, createMultipleItemsTx);
@@ -146,9 +137,10 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       const alice = privateKey('//Alice');
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      const bob = privateKey('//Bob');
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await submitTransactionAsync(alice, createMultipleItemsTx);
@@ -156,9 +148,9 @@
       expect(itemsListIndexAfter).to.be.equal(3);
 
       await expect(executeTransaction(
-        api, 
-        alice, 
-        api.tx.unique.setPropertyPermissions(collectionId, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]), 
+        api,
+        alice,
+        api.tx.unique.setPropertyPermissions(collectionId, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]),
       )).to.not.be.rejected;
 
       expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));
@@ -168,10 +160,6 @@
       expect(await getConstMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
       expect(await getConstMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
       expect(await getConstMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
-
-      expect(await getVariableMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
-      expect(await getVariableMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
-      expect(await getVariableMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
     });
   });
 
@@ -181,9 +169,10 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       const alice = privateKey('//Alice');
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      const bob = privateKey('//Bob');
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await submitTransactionAsync(alice, createMultipleItemsTx);
@@ -191,9 +180,9 @@
       expect(itemsListIndexAfter).to.be.equal(3);
 
       await expect(executeTransaction(
-        api, 
-        alice, 
-        api.tx.unique.setPropertyPermissions(collectionId, [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]), 
+        api,
+        alice,
+        api.tx.unique.setPropertyPermissions(collectionId, [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]),
       )).to.not.be.rejected;
 
       expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));
@@ -203,10 +192,6 @@
       expect(await getConstMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
       expect(await getConstMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
       expect(await getConstMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
-
-      expect(await getVariableMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
-      expect(await getVariableMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
-      expect(await getVariableMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
     });
   });
 
@@ -216,9 +201,10 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       const alice = privateKey('//Alice');
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      const bob = privateKey('//Bob');
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await submitTransactionAsync(alice, createMultipleItemsTx);
@@ -226,9 +212,9 @@
       expect(itemsListIndexAfter).to.be.equal(3);
 
       await expect(executeTransaction(
-        api, 
-        alice, 
-        api.tx.unique.setPropertyPermissions(collectionId, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]), 
+        api,
+        alice,
+        api.tx.unique.setPropertyPermissions(collectionId, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]),
       )).to.not.be.rejected;
 
       expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));
@@ -238,10 +224,6 @@
       expect(await getConstMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
       expect(await getConstMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
       expect(await getConstMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
-
-      expect(await getVariableMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
-      expect(await getVariableMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
-      expect(await getVariableMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
     });
   });
 });
@@ -264,9 +246,9 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);
       await submitTransactionAsync(bob, createMultipleItemsTx);
@@ -280,10 +262,6 @@
       expect(await getConstMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
       expect(await getConstMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
       expect(await getConstMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
-
-      expect(await getVariableMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
-      expect(await getVariableMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
-      expect(await getVariableMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
     });
   });
 
@@ -314,9 +292,9 @@
       expect(itemsListIndexBefore).to.be.equal(0);
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
       const args = [
-        {ReFungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}},
-        {ReFungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},
-        {ReFungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},
+        {ReFungible: {const_data: [0x31], pieces: 1}},
+        {ReFungible: {const_data: [0x32], pieces: 1}},
+        {ReFungible: {const_data: [0x33], pieces: 1}},
       ];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);
@@ -331,10 +309,6 @@
       expect(await getConstMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
       expect(await getConstMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
       expect(await getConstMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
-
-      expect(await getVariableMetadata(api, collectionId, 1)).to.be.deep.equal([0x31]);
-      expect(await getVariableMetadata(api, collectionId, 2)).to.be.deep.equal([0x32]);
-      expect(await getVariableMetadata(api, collectionId, 3)).to.be.deep.equal([0x33]);
     });
   });
 });
@@ -356,9 +330,9 @@
       const collectionId = await createCollectionExpectSuccess();
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await expect(submitTransactionAsync(bob, createMultipleItemsTx)).to.be.rejected;
@@ -387,9 +361,9 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       const args = [
-        {ReFungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}},
-        {ReFungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},
-        {ReFungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},
+        {ReFungible: {const_data: [0x31], pieces: 1}},
+        {ReFungible: {const_data: [0x32], pieces: 1}},
+        {ReFungible: {const_data: [0x33], pieces: 1}},
       ];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
@@ -412,9 +386,9 @@
       const collectionId = await createCollectionExpectSuccess();
       const alice = privateKey('//Alice');
       const args = [
-        {NFT: {const_data: 'A'.repeat(2049), variable_data: 'A'.repeat(2049)}},
-        {NFT: {const_data: 'B'.repeat(2049), variable_data: 'B'.repeat(2049)}},
-        {NFT: {const_data: 'C'.repeat(2049), variable_data: 'C'.repeat(2049)}},
+        {NFT: {const_data: 'A'.repeat(2049)}},
+        {NFT: {const_data: 'B'.repeat(2049)}},
+        {NFT: {const_data: 'C'.repeat(2049)}},
       ];
       const createMultipleItemsTx = api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
@@ -424,9 +398,9 @@
       const collectionIdReFungible =
         await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
       const argsReFungible = [
-        {ReFungible: ['1'.repeat(2049), '1'.repeat(2049), 10]},
-        {ReFungible: ['2'.repeat(2049), '2'.repeat(2049), 10]},
-        {ReFungible: ['3'.repeat(2049), '3'.repeat(2049), 10]},
+        {ReFungible: ['1'.repeat(2049), 10]},
+        {ReFungible: ['2'.repeat(2049), 10]},
+        {ReFungible: ['3'.repeat(2049), 10]},
       ];
       const createMultipleItemsTxFungible = api.tx.unique
         .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);
@@ -449,9 +423,8 @@
     await usingApi(async (api: ApiPromise) => {
       const collectionId = await createCollectionExpectSuccess();
       const args = [
-        {NFT: {const_data: 'A', variable_data: 'A'}},
-        {NFT: {const_data: 'B', variable_data: 'B'.repeat(2049)}},
-        {NFT: {const_data: 'C'.repeat(2049), variable_data: 'C'}},
+        {NFT: {const_data: 'A'}},
+        {NFT: {const_data: 'B'.repeat(2049)}},
       ];
       const createMultipleItemsTx = await api.tx.unique
         .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
@@ -467,8 +440,8 @@
         tokenLimit: 1,
       });
       const args = [
-        {NFT: {const_data: 'A', variable_data: 'A'}},
-        {NFT: {const_data: 'B', variable_data: 'B'}},
+        {NFT: {const_data: 'A'}},
+        {NFT: {const_data: 'B'}},
       ];
       const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
@@ -482,10 +455,10 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
-      
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
+
       const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
 
       const events = await submitTransactionAsync(alice, createMultipleItemsTx);
@@ -493,9 +466,9 @@
 
       for (const elem of result) {
         await expect(executeTransaction(
-          api, 
-          bob, 
-          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 
+          api,
+          bob,
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]),
         )).to.be.rejected;
       }
 
@@ -510,10 +483,10 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
-      
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
+
       const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
 
       const events = await submitTransactionAsync(alice, createMultipleItemsTx);
@@ -521,9 +494,9 @@
 
       for (const elem of result) {
         await expect(executeTransaction(
-          api, 
-          bob, 
-          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 
+          api,
+          bob,
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]),
         )).to.be.rejected;
       }
     });
@@ -535,10 +508,10 @@
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
       expect(itemsListIndexBefore).to.be.equal(0);
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
-      
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
+
       const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
 
       const events = await submitTransactionAsync(alice, createMultipleItemsTx);
@@ -546,9 +519,9 @@
 
       for (const elem of result) {
         await expect(executeTransaction(
-          api, 
-          bob, 
-          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 
+          api,
+          bob,
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]),
         )).to.be.rejected;
       }
     });
@@ -562,28 +535,28 @@
       expect(itemsListIndexBefore).to.be.equal(0);
       await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
 
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
-      
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
+
       const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
       const events = await submitTransactionAsync(alice, createMultipleItemsTx);
 
       const result = getCreateItemsResult(events);
-      
+
       const prps = [];
-      
+
       for (let i = 0; i < 65; i++) {
         prps.push({key: `key${i}`, value: `value${i}`});
       }
 
       await expect(executeTransaction(api, bob, api.tx.unique.setCollectionProperties(collectionId, prps))).to.be.rejectedWith(/common\.PropertyLimitReached/);
-      
+
       for (const elem of result) {
         await expect(executeTransaction(
-          api, 
-          bob, 
-          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, prps), 
+          api,
+          bob,
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, prps),
         )).to.be.rejected;
       }
     });
@@ -595,10 +568,10 @@
         propPerm:   [{key: 'key1', mutable: true, collectionAdmin: false, tokenOwner: false}]});
       const itemsListIndexBefore = await getLastTokenId(api, collectionId);
       expect(itemsListIndexBefore).to.be.equal(0);
-      const args = [{Nft: {const_data: '0x31', variable_data: '0x31'}},
-        {Nft: {const_data: '0x32', variable_data: '0x32'}},
-        {Nft: {const_data: '0x33', variable_data: '0x33'}}];
-      
+      const args = [{Nft: {const_data: '0x31'}},
+        {Nft: {const_data: '0x32'}},
+        {Nft: {const_data: '0x33'}}];
+
       const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
 
       const events = await submitTransactionAsync(alice, createMultipleItemsTx);
@@ -609,9 +582,9 @@
 
       for (const elem of result) {
         await expect(executeTransaction(
-          api, 
-          bob, 
-          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]), 
+          api,
+          bob,
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]),
         )).to.be.rejected;
       }
     });
modifiedtests/src/createMultipleItemsEx.test.tsdiffbeforeafterboth
--- a/tests/src/createMultipleItemsEx.test.ts
+++ b/tests/src/createMultipleItemsEx.test.ts
@@ -30,15 +30,12 @@
         {
           owner: {substrate: alice.address},
           constData: '0x0000',
-          variableData: '0x1111',
         }, {
           owner: {substrate: bob.address},
           constData: '0x2222',
-          variableData: '0x3333',
         }, {
           owner: {substrate: charlie.address},
           constData: '0x4444',
-          variableData: '0x5555',
         },
       ];
 
@@ -61,22 +58,19 @@
         {
           owner: {substrate: alice.address},
           constData: '0x0000',
-          variableData: '0x1111',
         }, {
           owner: {substrate: bob.address},
           constData: '0x2222',
-          variableData: '0x3333',
         }, {
           owner: {substrate: charlie.address},
           constData: '0x4444',
-          variableData: '0x5555',
         },
       ];
 
       await expect(executeTransaction(
-        api, 
-        alice, 
-        api.tx.unique.setPropertyPermissions(collection, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]), 
+        api,
+        alice,
+        api.tx.unique.setPropertyPermissions(collection, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]),
       )).to.not.be.rejected;
 
       await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {
@@ -98,28 +92,25 @@
         {
           owner: {substrate: alice.address},
           constData: '0x0000',
-          variableData: '0x1111',
         }, {
           owner: {substrate: bob.address},
           constData: '0x2222',
-          variableData: '0x3333',
         }, {
           owner: {substrate: charlie.address},
           constData: '0x4444',
-          variableData: '0x5555',
         },
       ];
       await expect(executeTransaction(
-        api, 
-        alice, 
-        api.tx.unique.setPropertyPermissions(collection, [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]), 
+        api,
+        alice,
+        api.tx.unique.setPropertyPermissions(collection, [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]),
       )).to.not.be.rejected;
 
       await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {
         NFT: data,
       }));
-      
 
+
       const tokens = await api.query.nonfungible.tokenData.entries(collection);
       const json = tokens.map(([, token]) => token.toJSON());
       expect(json).to.be.deep.equal(data);
@@ -136,28 +127,25 @@
         {
           owner: {substrate: alice.address},
           constData: '0x0000',
-          variableData: '0x1111',
         }, {
           owner: {substrate: bob.address},
           constData: '0x2222',
-          variableData: '0x3333',
         }, {
           owner: {substrate: charlie.address},
           constData: '0x4444',
-          variableData: '0x5555',
         },
       ];
       await expect(executeTransaction(
-        api, 
-        alice, 
-        api.tx.unique.setPropertyPermissions(collection, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]), 
+        api,
+        alice,
+        api.tx.unique.setPropertyPermissions(collection, [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]),
       )).to.not.be.rejected;
 
       await executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {
         NFT: data,
       }));
-      
 
+
       const tokens = await api.query.nonfungible.tokenData.entries(collection);
       const json = tokens.map(([, token]) => token.toJSON());
       expect(json).to.be.deep.equal(data);
@@ -184,15 +172,15 @@
 
       const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});
       await executeTransaction(api, alice, tx);
-      
+
       const events = await submitTransactionAsync(alice, tx);
       const result = getCreateItemsResult(events);
-      
+
       for (const elem of result) {
         await expect(executeTransaction(
-          api, 
-          bob, 
-          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 
+          api,
+          bob,
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]),
         )).to.be.rejected;
       }
     });
@@ -218,15 +206,15 @@
 
       const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});
       await executeTransaction(api, alice, tx);
-      
+
       const events = await submitTransactionAsync(alice, tx);
       const result = getCreateItemsResult(events);
-      
+
       for (const elem of result) {
         await expect(executeTransaction(
-          api, 
-          bob, 
-          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 
+          api,
+          bob,
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]),
         )).to.be.rejected;
       }
     });
@@ -251,15 +239,15 @@
 
       const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});
       await executeTransaction(api, alice, tx);
-      
+
       const events = await submitTransactionAsync(alice, tx);
       const result = getCreateItemsResult(events);
-      
+
       for (const elem of result) {
         await expect(executeTransaction(
-          api, 
-          bob, 
-          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]), 
+          api,
+          bob,
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, [{key: 'key1', value: 'v2'}]),
         )).to.be.rejected;
       }
     });
@@ -284,24 +272,24 @@
 
       const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});
       await executeTransaction(api, alice, tx);
-      
+
       const events = await submitTransactionAsync(alice, tx);
       const result = getCreateItemsResult(events);
 
       const prps = [];
-      
+
       for (let i = 0; i < 65; i++) {
         prps.push({key: `key${i}`, value: `value${i}`});
       }
 
       await expect(executeTransaction(api, bob, api.tx.unique.setCollectionProperties(collection, prps))).to.be.rejectedWith(/common\.PropertyLimitReached/);
 
-      
+
       for (const elem of result) {
         await expect(executeTransaction(
-          api, 
-          bob, 
-          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, prps), 
+          api,
+          bob,
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, prps),
         )).to.be.rejected;
       }
     });
@@ -326,7 +314,7 @@
 
       const tx = api.tx.unique.createMultipleItemsEx(collection, {NFT: data});
       await executeTransaction(api, alice, tx);
-      
+
       const events = await submitTransactionAsync(alice, tx);
       const result = getCreateItemsResult(events);
 
@@ -334,12 +322,12 @@
 
       await expect(executeTransaction(api, bob, api.tx.unique.setCollectionProperties(collection, prps))).to.be.rejectedWith(/common\.NoSpaceForProperty/);
 
-      
+
       for (const elem of result) {
         await expect(executeTransaction(
-          api, 
-          bob, 
-          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, prps), 
+          api,
+          bob,
+          api.tx.unique.setTokenProperties(elem.collectionId, elem.itemId, prps),
         )).to.be.rejected;
       }
     });
@@ -355,15 +343,12 @@
         {
           owner: {substrate: alice.address},
           constData: '0x0000',
-          variableData: '0x1111',
         }, {
           owner: {substrate: bob.address},
           constData: '0x2222',
-          variableData: '0x3333',
         }, {
           owner: {substrate: charlie.address},
           constData: '0x4444',
-          variableData: '0x5555',
         },
       ];
 
@@ -386,15 +371,12 @@
         {
           owner: {substrate: alice.address},
           constData: '0x0000',
-          variableData: '0x1111',
         }, {
           owner: {substrate: bob.address},
           constData: '0x2222',
-          variableData: '0x3333',
         }, {
           owner: {substrate: charlie.address},
           constData: '0x4444',
-          variableData: '0x5555',
         },
       ];
 
modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -22,6 +22,12 @@
 	);
 }
 
+// Selector: 79cc6790
+interface ERC20UniqueExtensions is Dummy, ERC165 {
+	// Selector: burnFrom(address,uint256) 79cc6790
+	function burnFrom(address from, uint256 amount) external returns (bool);
+}
+
 // Selector: 942e8b22
 interface ERC20 is Dummy, ERC165, ERC20Events {
 	// Selector: name() 06fdde03
@@ -59,4 +65,28 @@
 		returns (uint256);
 }
 
-interface UniqueFungible is Dummy, ERC165, ERC20 {}
+// Selector: 9b5e29c5
+interface CollectionProperties is Dummy, ERC165 {
+	// Selector: setCollectionProperty(string,bytes) 2f073f66
+	function setCollectionProperty(string memory key, bytes memory value)
+		external;
+
+	// Selector: deleteCollectionProperty(string) 7b7debce
+	function deleteCollectionProperty(string memory key) external;
+
+	// Throws error if key not found
+	//
+	// Selector: collectionProperty(string) cf24fd6d
+	function collectionProperty(string memory key)
+		external
+		view
+		returns (bytes memory);
+}
+
+interface UniqueFungible is
+	Dummy,
+	ERC165,
+	ERC20,
+	ERC20UniqueExtensions,
+	CollectionProperties
+{}
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -42,6 +42,35 @@
 	event MintingFinished();
 }
 
+// Selector: 41369377
+interface TokenProperties is Dummy, ERC165 {
+	// Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa
+	function setTokenPropertyPermission(
+		string memory key,
+		bool isMutable,
+		bool collectionAdmin,
+		bool tokenOwner
+	) external;
+
+	// Selector: setProperty(uint256,string,bytes) 1752d67b
+	function setProperty(
+		uint256 tokenId,
+		string memory key,
+		bytes memory value
+	) external;
+
+	// Selector: deleteProperty(uint256,string) 066111d1
+	function deleteProperty(uint256 tokenId, string memory key) external;
+
+	// Throws error if key not found
+	//
+	// Selector: property(uint256,string) 7228c327
+	function property(uint256 tokenId, string memory key)
+		external
+		view
+		returns (bytes memory);
+}
+
 // Selector: 42966c68
 interface ERC721Burnable is Dummy, ERC165 {
 	// Selector: burn(uint256) 42966c68
@@ -162,7 +191,25 @@
 	function totalSupply() external view returns (uint256);
 }
 
-// Selector: e562194d
+// Selector: 9b5e29c5
+interface CollectionProperties is Dummy, ERC165 {
+	// Selector: setCollectionProperty(string,bytes) 2f073f66
+	function setCollectionProperty(string memory key, bytes memory value)
+		external;
+
+	// Selector: deleteCollectionProperty(string) 7b7debce
+	function deleteCollectionProperty(string memory key) external;
+
+	// Throws error if key not found
+	//
+	// Selector: collectionProperty(string) cf24fd6d
+	function collectionProperty(string memory key)
+		external
+		view
+		returns (bytes memory);
+}
+
+// Selector: d74d154f
 interface ERC721UniqueExtensions is Dummy, ERC165 {
 	// Selector: transfer(address,uint256) a9059cbb
 	function transfer(address to, uint256 tokenId) external;
@@ -172,16 +219,7 @@
 
 	// Selector: nextTokenId() 75794a3c
 	function nextTokenId() external view returns (uint256);
-
-	// Selector: setVariableMetadata(uint256,bytes) d4eac26d
-	function setVariableMetadata(uint256 tokenId, bytes memory data) external;
 
-	// Selector: getVariableMetadata(uint256) e6c5ce6f
-	function getVariableMetadata(uint256 tokenId)
-		external
-		view
-		returns (bytes memory);
-
 	// Selector: mintBulk(address,uint256[]) 44a9945e
 	function mintBulk(address to, uint256[] memory tokenIds)
 		external
@@ -201,5 +239,7 @@
 	ERC721Enumerable,
 	ERC721UniqueExtensions,
 	ERC721Mintable,
-	ERC721Burnable
+	ERC721Burnable,
+	CollectionProperties,
+	TokenProperties
 {}
modifiedtests/src/eth/base.test.tsdiffbeforeafterboth
--- a/tests/src/eth/base.test.ts
+++ b/tests/src/eth/base.test.ts
@@ -79,7 +79,7 @@
       minter = createEthAccount(web3);
     });
   });
-  
+
   itWeb3('interfaceID == 0xffffffff always false', async ({web3}) => {
     expect(await contract(web3).methods.supportsInterface('0xffffffff').call()).to.be.false;
   });
@@ -101,7 +101,7 @@
   });
 
   itWeb3('ERC721UniqueExtensions support', async ({web3}) => {
-    expect(await contract(web3).methods.supportsInterface('0xe562194d').call()).to.be.true;
+    expect(await contract(web3).methods.supportsInterface('0xd74d154f').call()).to.be.true;
   });
 
   itWeb3('ERC721Burnable support', async ({web3}) => {
addedtests/src/eth/collectionProperties.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/collectionProperties.test.ts
@@ -0,0 +1,54 @@
+import privateKey from '../substrate/privateKey';
+import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess} from '../util/helpers';
+import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3} from './util/helpers';
+import nonFungibleAbi from './nonFungibleAbi.json';
+import {expect} from 'chai';
+import {executeTransaction} from '../substrate/substrate-api';
+
+describe('EVM collection properties', () => {
+  itWeb3('Can be set', async({web3, api}) => {
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+
+    await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+    await contract.methods.setCollectionProperty('testKey', Buffer.from('testValue')).send({from: caller});
+
+    const [{value}] = (await api.rpc.unique.collectionProperties(collection, ['testKey'])).toHuman()! as any;
+    expect(value).to.equal('testValue');
+  });
+  itWeb3('Can be deleted', async({web3, api}) => {
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+
+    await executeTransaction(api, alice, api.tx.unique.setCollectionProperties(collection, [{key: 'testKey', value: 'testValue'}]));
+
+    await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+    await contract.methods.deleteCollectionProperty('testKey').send({from: caller});
+
+    const result = (await api.rpc.unique.collectionProperties(collection, ['testKey'])).toJSON()! as any;
+    expect(result.length).to.equal(0);
+  });
+  itWeb3('Can be read', async({web3, api}) => {
+    const alice = privateKey('//Alice');
+    const caller = createEthAccount(web3);
+    const collection = await createCollectionExpectSuccess({mode: {type:'NFT'}});
+
+    await executeTransaction(api, alice, api.tx.unique.setCollectionProperties(collection, [{key: 'testKey', value: 'testValue'}]));
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+    const value = await contract.methods.collectionProperty('testKey').call();
+    expect(value).to.equal(web3.utils.toHex('testValue'));
+  });
+});
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -15,7 +15,7 @@
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
 import privateKey from '../substrate/privateKey';
-import {approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, setVariableMetaDataExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE, setMetadataUpdatePermissionFlagExpectSuccess} from '../util/helpers';
+import {approveExpectSuccess, burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, transferFromExpectSuccess, UNIQUE} from '../util/helpers';
 import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, transferBalanceToEth} from './util/helpers';
 import nonFungibleAbi from './nonFungibleAbi.json';
 import {expect} from 'chai';
@@ -331,41 +331,6 @@
       const balance = await contract.methods.balanceOf(receiver).call();
       expect(+balance).to.equal(1);
     }
-  });
-
-  itWeb3('Can perform getVariableMetadata', async ({web3, api}) => {
-    const collection = await createCollectionExpectSuccess({
-      mode: {type: 'NFT'},
-    });
-    const alice = privateKey('//Alice');
-
-    const owner = await createEthAccountWithBalance(api, web3);
-
-    const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
-    await setMetadataUpdatePermissionFlagExpectSuccess(alice, collection, 'Admin');
-    await setVariableMetaDataExpectSuccess(alice, collection, item, [1, 2, 3]);
-
-    const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
-
-    expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');
-  });
-
-  itWeb3('Can perform setVariableMetadata', async ({web3, api}) => {
-    const collection = await createCollectionExpectSuccess({
-      mode: {type: 'NFT'},
-    });
-    const alice = privateKey('//Alice');
-
-    const owner = await createEthAccountWithBalance(api, web3);
-
-    const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
-
-    const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: owner, ...GAS_ARGS});
-
-    expect(await contract.methods.setVariableMetadata(item, '0x010203').send({from: owner}));
-    expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');
   });
 });
 
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -1,614 +1,738 @@
 [
-    {
-        "anonymous": false,
-        "inputs": [
-            {
-                "indexed": true,
-                "internalType": "address",
-                "name": "owner",
-                "type": "address"
-            },
-            {
-                "indexed": true,
-                "internalType": "address",
-                "name": "approved",
-                "type": "address"
-            },
-            {
-                "indexed": true,
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "Approval",
-        "type": "event"
-    },
-    {
-        "anonymous": false,
-        "inputs": [
-            {
-                "indexed": true,
-                "internalType": "address",
-                "name": "owner",
-                "type": "address"
-            },
-            {
-                "indexed": true,
-                "internalType": "address",
-                "name": "operator",
-                "type": "address"
-            },
-            {
-                "indexed": false,
-                "internalType": "bool",
-                "name": "approved",
-                "type": "bool"
-            }
-        ],
-        "name": "ApprovalForAll",
-        "type": "event"
-    },
-    {
-        "anonymous": false,
-        "inputs": [],
-        "name": "MintingFinished",
-        "type": "event"
-    },
-    {
-        "anonymous": false,
-        "inputs": [
-            {
-                "indexed": true,
-                "internalType": "address",
-                "name": "from",
-                "type": "address"
-            },
-            {
-                "indexed": true,
-                "internalType": "address",
-                "name": "to",
-                "type": "address"
-            },
-            {
-                "indexed": true,
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "Transfer",
-        "type": "event"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "approved",
-                "type": "address"
-            },
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "approve",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "owner",
-                "type": "address"
-            }
-        ],
-        "name": "balanceOf",
-        "outputs": [
-            {
-                "internalType": "uint256",
-                "name": "",
-                "type": "uint256"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "burn",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [],
-        "name": "finishMinting",
-        "outputs": [
-            {
-                "internalType": "bool",
-                "name": "",
-                "type": "bool"
-            }
-        ],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "getApproved",
-        "outputs": [
-            {
-                "internalType": "address",
-                "name": "",
-                "type": "address"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "getVariableMetadata",
-        "outputs": [
-            {
-                "internalType": "bytes",
-                "name": "",
-                "type": "bytes"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "owner",
-                "type": "address"
-            },
-            {
-                "internalType": "address",
-                "name": "operator",
-                "type": "address"
-            }
-        ],
-        "name": "isApprovedForAll",
-        "outputs": [
-            {
-                "internalType": "address",
-                "name": "",
-                "type": "address"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "to",
-                "type": "address"
-            },
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "mint",
-        "outputs": [
-            {
-                "internalType": "bool",
-                "name": "",
-                "type": "bool"
-            }
-        ],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "to",
-                "type": "address"
-            },
-            {
-                "internalType": "uint256[]",
-                "name": "tokenIds",
-                "type": "uint256[]"
-            }
-        ],
-        "name": "mintBulk",
-        "outputs": [
-            {
-                "internalType": "bool",
-                "name": "",
-                "type": "bool"
-            }
-        ],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "to",
-                "type": "address"
-            },
-            {
-                "components": [
-                    {
-                        "internalType": "uint256",
-                        "name": "field_0",
-                        "type": "uint256"
-                    },
-                    {
-                        "internalType": "string",
-                        "name": "field_1",
-                        "type": "string"
-                    }
-                ],
-                "internalType": "struct Tuple0[]",
-                "name": "tokens",
-                "type": "tuple[]"
-            }
-        ],
-        "name": "mintBulkWithTokenURI",
-        "outputs": [
-            {
-                "internalType": "bool",
-                "name": "",
-                "type": "bool"
-            }
-        ],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "to",
-                "type": "address"
-            },
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            },
-            {
-                "internalType": "string",
-                "name": "tokenUri",
-                "type": "string"
-            }
-        ],
-        "name": "mintWithTokenURI",
-        "outputs": [
-            {
-                "internalType": "bool",
-                "name": "",
-                "type": "bool"
-            }
-        ],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [],
-        "name": "mintingFinished",
-        "outputs": [
-            {
-                "internalType": "bool",
-                "name": "",
-                "type": "bool"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [],
-        "name": "name",
-        "outputs": [
-            {
-                "internalType": "string",
-                "name": "",
-                "type": "string"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [],
-        "name": "nextTokenId",
-        "outputs": [
-            {
-                "internalType": "uint256",
-                "name": "",
-                "type": "uint256"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "ownerOf",
-        "outputs": [
-            {
-                "internalType": "address",
-                "name": "",
-                "type": "address"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "from",
-                "type": "address"
-            },
-            {
-                "internalType": "address",
-                "name": "to",
-                "type": "address"
-            },
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "safeTransferFrom",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "from",
-                "type": "address"
-            },
-            {
-                "internalType": "address",
-                "name": "to",
-                "type": "address"
-            },
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            },
-            {
-                "internalType": "bytes",
-                "name": "data",
-                "type": "bytes"
-            }
-        ],
-        "name": "safeTransferFromWithData",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "operator",
-                "type": "address"
-            },
-            {
-                "internalType": "bool",
-                "name": "approved",
-                "type": "bool"
-            }
-        ],
-        "name": "setApprovalForAll",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            },
-            {
-                "internalType": "bytes",
-                "name": "data",
-                "type": "bytes"
-            }
-        ],
-        "name": "setVariableMetadata",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "bytes4",
-                "name": "interfaceId",
-                "type": "bytes4"
-            }
-        ],
-        "name": "supportsInterface",
-        "outputs": [
-            {
-                "internalType": "bool",
-                "name": "",
-                "type": "bool"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [],
-        "name": "symbol",
-        "outputs": [
-            {
-                "internalType": "string",
-                "name": "",
-                "type": "string"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "uint256",
-                "name": "index",
-                "type": "uint256"
-            }
-        ],
-        "name": "tokenByIndex",
-        "outputs": [
-            {
-                "internalType": "uint256",
-                "name": "",
-                "type": "uint256"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "owner",
-                "type": "address"
-            },
-            {
-                "internalType": "uint256",
-                "name": "index",
-                "type": "uint256"
-            }
-        ],
-        "name": "tokenOfOwnerByIndex",
-        "outputs": [
-            {
-                "internalType": "uint256",
-                "name": "",
-                "type": "uint256"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "tokenURI",
-        "outputs": [
-            {
-                "internalType": "string",
-                "name": "",
-                "type": "string"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [],
-        "name": "totalSupply",
-        "outputs": [
-            {
-                "internalType": "uint256",
-                "name": "",
-                "type": "uint256"
-            }
-        ],
-        "stateMutability": "view",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "to",
-                "type": "address"
-            },
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "transfer",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    },
-    {
-        "inputs": [
-            {
-                "internalType": "address",
-                "name": "from",
-                "type": "address"
-            },
-            {
-                "internalType": "address",
-                "name": "to",
-                "type": "address"
-            },
-            {
-                "internalType": "uint256",
-                "name": "tokenId",
-                "type": "uint256"
-            }
-        ],
-        "name": "transferFrom",
-        "outputs": [],
-        "stateMutability": "nonpayable",
-        "type": "function"
-    }
-]
+	{
+		"anonymous": false,
+		"inputs": [
+			{
+				"indexed": true,
+				"internalType": "address",
+				"name": "owner",
+				"type": "address"
+			},
+			{
+				"indexed": true,
+				"internalType": "address",
+				"name": "approved",
+				"type": "address"
+			},
+			{
+				"indexed": true,
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "Approval",
+		"type": "event"
+	},
+	{
+		"anonymous": false,
+		"inputs": [
+			{
+				"indexed": true,
+				"internalType": "address",
+				"name": "owner",
+				"type": "address"
+			},
+			{
+				"indexed": true,
+				"internalType": "address",
+				"name": "operator",
+				"type": "address"
+			},
+			{
+				"indexed": false,
+				"internalType": "bool",
+				"name": "approved",
+				"type": "bool"
+			}
+		],
+		"name": "ApprovalForAll",
+		"type": "event"
+	},
+	{
+		"anonymous": false,
+		"inputs": [],
+		"name": "MintingFinished",
+		"type": "event"
+	},
+	{
+		"anonymous": false,
+		"inputs": [
+			{
+				"indexed": true,
+				"internalType": "address",
+				"name": "from",
+				"type": "address"
+			},
+			{
+				"indexed": true,
+				"internalType": "address",
+				"name": "to",
+				"type": "address"
+			},
+			{
+				"indexed": true,
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "Transfer",
+		"type": "event"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "approved",
+				"type": "address"
+			},
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "approve",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "owner",
+				"type": "address"
+			}
+		],
+		"name": "balanceOf",
+		"outputs": [
+			{
+				"internalType": "uint256",
+				"name": "",
+				"type": "uint256"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "burn",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "from",
+				"type": "address"
+			},
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "burnFrom",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "string",
+				"name": "key",
+				"type": "string"
+			}
+		],
+		"name": "collectionProperty",
+		"outputs": [
+			{
+				"internalType": "bytes",
+				"name": "",
+				"type": "bytes"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "string",
+				"name": "key",
+				"type": "string"
+			}
+		],
+		"name": "deleteCollectionProperty",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			},
+			{
+				"internalType": "string",
+				"name": "key",
+				"type": "string"
+			}
+		],
+		"name": "deleteProperty",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [],
+		"name": "finishMinting",
+		"outputs": [
+			{
+				"internalType": "bool",
+				"name": "",
+				"type": "bool"
+			}
+		],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "getApproved",
+		"outputs": [
+			{
+				"internalType": "address",
+				"name": "",
+				"type": "address"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "owner",
+				"type": "address"
+			},
+			{
+				"internalType": "address",
+				"name": "operator",
+				"type": "address"
+			}
+		],
+		"name": "isApprovedForAll",
+		"outputs": [
+			{
+				"internalType": "address",
+				"name": "",
+				"type": "address"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "to",
+				"type": "address"
+			},
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "mint",
+		"outputs": [
+			{
+				"internalType": "bool",
+				"name": "",
+				"type": "bool"
+			}
+		],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "to",
+				"type": "address"
+			},
+			{
+				"internalType": "uint256[]",
+				"name": "tokenIds",
+				"type": "uint256[]"
+			}
+		],
+		"name": "mintBulk",
+		"outputs": [
+			{
+				"internalType": "bool",
+				"name": "",
+				"type": "bool"
+			}
+		],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "to",
+				"type": "address"
+			},
+			{
+				"components": [
+					{
+						"internalType": "uint256",
+						"name": "field_0",
+						"type": "uint256"
+					},
+					{
+						"internalType": "string",
+						"name": "field_1",
+						"type": "string"
+					}
+				],
+				"internalType": "struct Tuple0[]",
+				"name": "tokens",
+				"type": "tuple[]"
+			}
+		],
+		"name": "mintBulkWithTokenURI",
+		"outputs": [
+			{
+				"internalType": "bool",
+				"name": "",
+				"type": "bool"
+			}
+		],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "to",
+				"type": "address"
+			},
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			},
+			{
+				"internalType": "string",
+				"name": "tokenUri",
+				"type": "string"
+			}
+		],
+		"name": "mintWithTokenURI",
+		"outputs": [
+			{
+				"internalType": "bool",
+				"name": "",
+				"type": "bool"
+			}
+		],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [],
+		"name": "mintingFinished",
+		"outputs": [
+			{
+				"internalType": "bool",
+				"name": "",
+				"type": "bool"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [],
+		"name": "name",
+		"outputs": [
+			{
+				"internalType": "string",
+				"name": "",
+				"type": "string"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [],
+		"name": "nextTokenId",
+		"outputs": [
+			{
+				"internalType": "uint256",
+				"name": "",
+				"type": "uint256"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "ownerOf",
+		"outputs": [
+			{
+				"internalType": "address",
+				"name": "",
+				"type": "address"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			},
+			{
+				"internalType": "string",
+				"name": "key",
+				"type": "string"
+			}
+		],
+		"name": "property",
+		"outputs": [
+			{
+				"internalType": "bytes",
+				"name": "",
+				"type": "bytes"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "from",
+				"type": "address"
+			},
+			{
+				"internalType": "address",
+				"name": "to",
+				"type": "address"
+			},
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "safeTransferFrom",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "from",
+				"type": "address"
+			},
+			{
+				"internalType": "address",
+				"name": "to",
+				"type": "address"
+			},
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			},
+			{
+				"internalType": "bytes",
+				"name": "data",
+				"type": "bytes"
+			}
+		],
+		"name": "safeTransferFromWithData",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "operator",
+				"type": "address"
+			},
+			{
+				"internalType": "bool",
+				"name": "approved",
+				"type": "bool"
+			}
+		],
+		"name": "setApprovalForAll",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "string",
+				"name": "key",
+				"type": "string"
+			},
+			{
+				"internalType": "bytes",
+				"name": "value",
+				"type": "bytes"
+			}
+		],
+		"name": "setCollectionProperty",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			},
+			{
+				"internalType": "string",
+				"name": "key",
+				"type": "string"
+			},
+			{
+				"internalType": "bytes",
+				"name": "value",
+				"type": "bytes"
+			}
+		],
+		"name": "setProperty",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "string",
+				"name": "key",
+				"type": "string"
+			},
+			{
+				"internalType": "bool",
+				"name": "isMutable",
+				"type": "bool"
+			},
+			{
+				"internalType": "bool",
+				"name": "collectionAdmin",
+				"type": "bool"
+			},
+			{
+				"internalType": "bool",
+				"name": "tokenOwner",
+				"type": "bool"
+			}
+		],
+		"name": "setTokenPropertyPermission",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "bytes4",
+				"name": "interfaceID",
+				"type": "bytes4"
+			}
+		],
+		"name": "supportsInterface",
+		"outputs": [
+			{
+				"internalType": "bool",
+				"name": "",
+				"type": "bool"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [],
+		"name": "symbol",
+		"outputs": [
+			{
+				"internalType": "string",
+				"name": "",
+				"type": "string"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "uint256",
+				"name": "index",
+				"type": "uint256"
+			}
+		],
+		"name": "tokenByIndex",
+		"outputs": [
+			{
+				"internalType": "uint256",
+				"name": "",
+				"type": "uint256"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "owner",
+				"type": "address"
+			},
+			{
+				"internalType": "uint256",
+				"name": "index",
+				"type": "uint256"
+			}
+		],
+		"name": "tokenOfOwnerByIndex",
+		"outputs": [
+			{
+				"internalType": "uint256",
+				"name": "",
+				"type": "uint256"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "tokenURI",
+		"outputs": [
+			{
+				"internalType": "string",
+				"name": "",
+				"type": "string"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [],
+		"name": "totalSupply",
+		"outputs": [
+			{
+				"internalType": "uint256",
+				"name": "",
+				"type": "uint256"
+			}
+		],
+		"stateMutability": "view",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "to",
+				"type": "address"
+			},
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "transfer",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	},
+	{
+		"inputs": [
+			{
+				"internalType": "address",
+				"name": "from",
+				"type": "address"
+			},
+			{
+				"internalType": "address",
+				"name": "to",
+				"type": "address"
+			},
+			{
+				"internalType": "uint256",
+				"name": "tokenId",
+				"type": "uint256"
+			}
+		],
+		"name": "transferFrom",
+		"outputs": [],
+		"stateMutability": "nonpayable",
+		"type": "function"
+	}
+]
\ No newline at end of file
modifiedtests/src/eth/proxy/UniqueNFTProxy.abidiffbeforeafterboth
--- a/tests/src/eth/proxy/UniqueNFTProxy.abi
+++ b/tests/src/eth/proxy/UniqueNFTProxy.abi
@@ -1 +1 @@
-[{"inputs":[{"internalType":"address","name":"_proxied","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[],"name":"MintingFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"approved","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finishMinting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getVariableMetadata","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"mintBulk","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"components":[{"internalType":"uint256","name":"field_0","type":"uint256"},{"internalType":"string","name":"field_1","type":"string"}],"internalType":"struct Tuple0[]","name":"tokens","type":"tuple[]"}],"name":"mintBulkWithTokenURI","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"tokenUri","type":"string"}],"name":"mintWithTokenURI","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintingFinished","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFromWithData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setVariableMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"interfaceId","type":"uint32"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
+[{"inputs":[{"internalType":"address","name":"_proxied","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[],"name":"MintingFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"approved","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"deleteProperty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finishMinting","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"mintBulk","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"components":[{"internalType":"uint256","name":"field_0","type":"uint256"},{"internalType":"string","name":"field_1","type":"string"}],"internalType":"struct Tuple0[]","name":"tokens","type":"tuple[]"}],"name":"mintBulkWithTokenURI","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"tokenUri","type":"string"}],"name":"mintWithTokenURI","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintingFinished","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFromWithData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setProperty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
modifiedtests/src/eth/proxy/UniqueNFTProxy.bindiffbeforeafterboth
--- a/tests/src/eth/proxy/UniqueNFTProxy.bin
+++ b/tests/src/eth/proxy/UniqueNFTProxy.bin
@@ -1 +1 @@
-608060405234801561001057600080fd5b5060405161168d38038061168d83398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b6115fa806100936000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c806350bb4e7f116100f9578063a22cb46511610097578063d4eac26d11610071578063d4eac26d1461036b578063e6c5ce6f1461037e578063e985e9c514610391578063f4f4b500146103a457600080fd5b8063a22cb46514610332578063a9059cbb14610345578063c87b56dd1461035857600080fd5b806370a08231116100d357806370a082311461030757806375794a3c1461031a5780637d64bcb41461032257806395d89b411461032a57600080fd5b806350bb4e7f146102ce57806360a11672146102e15780636352211e146102f457600080fd5b80632f745c591161016657806342842e0e1161014057806342842e0e1461028257806342966c681461029557806344a9945e146102a85780634f6ccce7146102bb57600080fd5b80632f745c5914610249578063365430061461025c57806340c10f191461026f57600080fd5b806305d2035b146101ae57806306fdde03146101cb578063081812fc146101e0578063095ea7b31461020b57806318160ddd1461022057806323b872dd14610236575b600080fd5b6101b66103b7565b60405190151581526020015b60405180910390f35b6101d3610443565b6040516101c2919061148a565b6101f36101ee366004611277565b6104c3565b6040516001600160a01b0390911681526020016101c2565b61021e61021936600461118c565b610547565b005b6102286105b2565b6040519081526020016101c2565b61021e610244366004610eff565b610639565b61022861025736600461118c565b6106ad565b6101b661026a366004610fac565b610739565b6101b661027d36600461118c565b6107be565b61021e610290366004610eff565b6107f8565b61021e6102a3366004611277565b610839565b6101b66102b63660046110b1565b61089a565b6102286102c9366004611277565b6108cd565b6101b66102dc3660046111b8565b61094b565b61021e6102ef366004610f40565b6109da565b6101f3610302366004611277565b610a49565b610228610315366004610e8c565b610a7b565b610228610aae565b6101b6610afd565b6101d3610b62565b61021e61034036600461115e565b610ba6565b61021e61035336600461118c565b610be0565b6101d3610366366004611277565b610c19565b61021e6103793660046112a9565b610c9b565b6101d361038c366004611277565b610ccd565b6101f361039f366004610ec6565b610cff565b6101b66103b23660046112f0565b610d85565b60008060009054906101000a90046001600160a01b03166001600160a01b03166305d2035b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561040657600080fd5b505afa15801561041a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043e9190611211565b905090565b60008054604080516306fdde0360e01b815290516060936001600160a01b03909316926306fdde039260048082019391829003018186803b15801561048757600080fd5b505afa15801561049b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261043e919081019061122e565b6000805460405163020604bf60e21b8152600481018490526001600160a01b039091169063081812fc906024015b60206040518083038186803b15801561050957600080fd5b505afa15801561051d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105419190610ea9565b92915050565b60005460405163095ea7b360e01b81526001600160a01b038481166004830152602482018490529091169063095ea7b3906044015b600060405180830381600087803b15801561059657600080fd5b505af11580156105aa573d6000803e3d6000fd5b505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561060157600080fd5b505afa158015610615573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043e9190611290565b6000546040516323b872dd60e01b81526001600160a01b038581166004830152848116602483015260448201849052909116906323b872dd906064015b600060405180830381600087803b15801561069057600080fd5b505af11580156106a4573d6000803e3d6000fd5b50505050505050565b60008054604051632f745c5960e01b81526001600160a01b0385811660048301526024820185905290911690632f745c599060440160206040518083038186803b1580156106fa57600080fd5b505afa15801561070e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107329190611290565b9392505050565b60008054604051631b2a180360e11b81526001600160a01b039091169063365430069061076c908690869060040161137f565b602060405180830381600087803b15801561078657600080fd5b505af115801561079a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107329190611211565b600080546040516340c10f1960e01b81526001600160a01b03858116600483015260248201859052909116906340c10f199060440161076c565b600054604051632142170760e11b81526001600160a01b038581166004830152848116602483015260448201849052909116906342842e0e90606401610676565b600054604051630852cd8d60e31b8152600481018390526001600160a01b03909116906342966c6890602401600060405180830381600087803b15801561087f57600080fd5b505af1158015610893573d6000803e3d6000fd5b5050505050565b60008054604051632254ca2f60e11b81526001600160a01b03909116906344a9945e9061076c9086908690600401611404565b60008054604051634f6ccce760e01b8152600481018490526001600160a01b0390911690634f6ccce7906024015b60206040518083038186803b15801561091357600080fd5b505afa158015610927573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105419190611290565b600080546040516350bb4e7f60e01b81526001600160a01b03909116906350bb4e7f906109809087908790879060040161145a565b602060405180830381600087803b15801561099a57600080fd5b505af11580156109ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d29190611211565b949350505050565b6000546040516330508b3960e11b81526001600160a01b03909116906360a1167290610a10908790879087908790600401611342565b600060405180830381600087803b158015610a2a57600080fd5b505af1158015610a3e573d6000803e3d6000fd5b505050505b50505050565b600080546040516331a9108f60e11b8152600481018490526001600160a01b0390911690636352211e906024016104f1565b600080546040516370a0823160e01b81526001600160a01b038481166004830152909116906370a08231906024016108fb565b60008060009054906101000a90046001600160a01b03166001600160a01b03166375794a3c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561060157600080fd5b60008060009054906101000a90046001600160a01b03166001600160a01b0316637d64bcb46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610b4e57600080fd5b505af115801561041a573d6000803e3d6000fd5b60008054604080516395d89b4160e01b815290516060936001600160a01b03909316926395d89b419260048082019391829003018186803b15801561048757600080fd5b60005460405163a22cb46560e01b81526001600160a01b03848116600483015283151560248301529091169063a22cb4659060440161057c565b60005460405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490529091169063a9059cbb9060440161057c565b60005460405163c87b56dd60e01b8152600481018390526060916001600160a01b03169063c87b56dd906024015b60006040518083038186803b158015610c5f57600080fd5b505afa158015610c73573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610541919081019061122e565b60005460405163d4eac26d60e01b81526001600160a01b039091169063d4eac26d9061057c908590859060040161149d565b60005460405163e6c5ce6f60e01b8152600481018390526060916001600160a01b03169063e6c5ce6f90602401610c47565b6000805460405163e985e9c560e01b81526001600160a01b03858116600483015284811660248301529091169063e985e9c59060440160206040518083038186803b158015610d4d57600080fd5b505afa158015610d61573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107329190610ea9565b6000805460405162f4f4b560e81b815263ffffffff841660048201526001600160a01b039091169063f4f4b5009060240160206040518083038186803b158015610dce57600080fd5b505afa158015610de2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105419190611211565b6000610e19610e1484611534565b6114df565b9050828152838383011115610e2d57600080fd5b61073283602083018461155c565b600082601f830112610e4c57600080fd5b8135610e5a610e1482611534565b818152846020838601011115610e6f57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215610e9e57600080fd5b81356107328161159e565b600060208284031215610ebb57600080fd5b81516107328161159e565b60008060408385031215610ed957600080fd5b8235610ee48161159e565b91506020830135610ef48161159e565b809150509250929050565b600080600060608486031215610f1457600080fd5b8335610f1f8161159e565b92506020840135610f2f8161159e565b929592945050506040919091013590565b60008060008060808587031215610f5657600080fd5b8435610f618161159e565b93506020850135610f718161159e565b925060408501359150606085013567ffffffffffffffff811115610f9457600080fd5b610fa087828801610e3b565b91505092959194509250565b60008060408385031215610fbf57600080fd5b8235610fca8161159e565b915060208381013567ffffffffffffffff80821115610fe857600080fd5b818601915086601f830112610ffc57600080fd5b813561100a610e1482611510565b8082825285820191508585018a878560051b880101111561102a57600080fd5b60005b848110156110a05781358681111561104457600080fd5b87016040818e03601f1901121561105a57600080fd5b6110626114b6565b89820135815260408201358881111561107a57600080fd5b6110888f8c83860101610e3b565b828c015250855250928701929087019060010161102d565b50979a909950975050505050505050565b600080604083850312156110c457600080fd5b82356110cf8161159e565b915060208381013567ffffffffffffffff8111156110ec57600080fd5b8401601f810186136110fd57600080fd5b803561110b610e1482611510565b80828252848201915084840189868560051b870101111561112b57600080fd5b600094505b8385101561114e578035835260019490940193918501918501611130565b5080955050505050509250929050565b6000806040838503121561117157600080fd5b823561117c8161159e565b91506020830135610ef4816115b6565b6000806040838503121561119f57600080fd5b82356111aa8161159e565b946020939093013593505050565b6000806000606084860312156111cd57600080fd5b83356111d88161159e565b925060208401359150604084013567ffffffffffffffff8111156111fb57600080fd5b61120786828701610e3b565b9150509250925092565b60006020828403121561122357600080fd5b8151610732816115b6565b60006020828403121561124057600080fd5b815167ffffffffffffffff81111561125757600080fd5b8201601f8101841361126857600080fd5b6109d284825160208401610e06565b60006020828403121561128957600080fd5b5035919050565b6000602082840312156112a257600080fd5b5051919050565b600080604083850312156112bc57600080fd5b82359150602083013567ffffffffffffffff8111156112da57600080fd5b6112e685828601610e3b565b9150509250929050565b60006020828403121561130257600080fd5b813563ffffffff8116811461073257600080fd5b6000815180845261132e81602086016020860161155c565b601f01601f19169290920160200192915050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061137590830184611316565b9695505050505050565b6001600160a01b0383168152604060208083018290528351828401819052600092916060600583901b860181019290860190878301865b828110156113f557888603605f190184528151805187528501518587018890526113e288880182611316565b96505092840192908401906001016113b6565b50939998505050505050505050565b6001600160a01b038316815260406020808301829052835191830182905260009184820191906060850190845b8181101561144d57845183529383019391830191600101611431565b5090979650505050505050565b60018060a01b03841681528260208201526060604082015260006114816060830184611316565b95945050505050565b6020815260006107326020830184611316565b8281526040602082015260006109d26040830184611316565b6040805190810167ffffffffffffffff811182821017156114d9576114d9611588565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561150857611508611588565b604052919050565b600067ffffffffffffffff82111561152a5761152a611588565b5060051b60200190565b600067ffffffffffffffff82111561154e5761154e611588565b50601f01601f191660200190565b60005b8381101561157757818101518382015260200161155f565b83811115610a435750506000910152565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811681146115b357600080fd5b50565b80151581146115b357600080fdfea2646970667358221220669a75a3efcdc6b60606caa5c7e41cab1d727e89a03fd231d1cda27f4de159a064736f6c63430008070033
\ No newline at end of file
+608060405234801561001057600080fd5b506040516116bb3803806116bb83398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b611628806100936000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c80634f6ccce7116100f957806379cc679011610097578063a22cb46511610071578063a22cb46514610399578063a9059cbb146103ac578063c87b56dd146103bf578063e985e9c5146103d257600080fd5b806379cc6790146103765780637d64bcb41461038957806395d89b411461039157600080fd5b806362d9491f116100d357806362d9491f146103355780636352211e1461034857806370a082311461035b57806375794a3c1461036e57600080fd5b80634f6ccce7146102fc57806350bb4e7f1461030f57806360a116721461032257600080fd5b80632f745c591161016657806340c10f191161014057806340c10f19146102b057806342842e0e146102c357806342966c68146102d657806344a9945e146102e957600080fd5b80632f745c5914610277578063342419141461028a578063365430061461029d57600080fd5b8063081812fc116101a2578063081812fc1461020e578063095ea7b31461023957806318160ddd1461024e57806323b872dd1461026457600080fd5b806301ffc9a7146101c957806305d2035b146101f157806306fdde03146101f9575b600080fd5b6101dc6101d7366004610dca565b6103e5565b60405190151581526020015b60405180910390f35b6101dc610462565b6102016104df565b6040516101e89190610e4c565b61022161021c366004610e5f565b610550565b6040516001600160a01b0390911681526020016101e8565b61024c610247366004610e90565b6105bf565b005b61025661062a565b6040519081526020016101e8565b61024c610272366004610ebc565b6106a2565b610256610285366004610e90565b610716565b61024c610298366004610ff3565b610793565b6101dc6102ab36600461104c565b6107f8565b6101dc6102be366004610e90565b61086e565b61024c6102d1366004610ebc565b6108a8565b61024c6102e4366004610e5f565b6108e9565b6101dc6102f736600461114f565b61091a565b61025661030a366004610e5f565b61094d565b6101dc61031d3660046111f5565b6109bc565b61024c61033036600461124e565b610a3c565b61024c6103433660046112ce565b610aab565b610221610356366004610e5f565b610add565b610256610369366004611332565b610b0f565b610256610b42565b61024c610384366004610e90565b610b96565b6101dc610bcf565b610201610c25565b61024c6103a736600461135d565b610c6e565b61024c6103ba366004610e90565b610ca8565b6102016103cd366004610e5f565b610ce1565b6102216103e0366004611396565b610d53565b600080546040516301ffc9a760e01b81526001600160e01b0319841660048201526001600160a01b03909116906301ffc9a790602401602060405180830381865afa158015610438573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045c91906113c4565b92915050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166305d2035b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104da91906113c4565b905090565b60008054604080516306fdde0360e01b815290516060936001600160a01b03909316926306fdde0392600480820193918290030181865afa158015610528573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104da91908101906113e1565b6000805460405163020604bf60e21b8152600481018490526001600160a01b039091169063081812fc906024015b602060405180830381865afa15801561059b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045c9190611458565b60005460405163095ea7b360e01b81526001600160a01b038481166004830152602482018490529091169063095ea7b3906044015b600060405180830381600087803b15801561060e57600080fd5b505af1158015610622573d6000803e3d6000fd5b505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561067e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104da9190611475565b6000546040516323b872dd60e01b81526001600160a01b038581166004830152848116602483015260448201849052909116906323b872dd906064015b600060405180830381600087803b1580156106f957600080fd5b505af115801561070d573d6000803e3d6000fd5b50505050505050565b60008054604051632f745c5960e01b81526001600160a01b0385811660048301526024820185905290911690632f745c5990604401602060405180830381865afa158015610768573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078c9190611475565b9392505050565b600054604051630d09064560e21b81526001600160a01b03909116906334241914906107c3908490600401610e4c565b600060405180830381600087803b1580156107dd57600080fd5b505af11580156107f1573d6000803e3d6000fd5b5050505050565b60008054604051631b2a180360e11b81526001600160a01b039091169063365430069061082b908690869060040161148e565b6020604051808303816000875af115801561084a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078c91906113c4565b600080546040516340c10f1960e01b81526001600160a01b03858116600483015260248201859052909116906340c10f199060440161082b565b600054604051632142170760e11b81526001600160a01b038581166004830152848116602483015260448201849052909116906342842e0e906064016106df565b600054604051630852cd8d60e31b8152600481018390526001600160a01b03909116906342966c68906024016107c3565b60008054604051632254ca2f60e11b81526001600160a01b03909116906344a9945e9061082b9086908690600401611513565b60008054604051634f6ccce760e01b8152600481018490526001600160a01b0390911690634f6ccce7906024015b602060405180830381865afa158015610998573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045c9190611475565b600080546040516350bb4e7f60e01b81526001600160a01b03909116906350bb4e7f906109f190879087908790600401611569565b6020604051808303816000875af1158015610a10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3491906113c4565b949350505050565b6000546040516330508b3960e11b81526001600160a01b03909116906360a1167290610a72908790879087908790600401611590565b600060405180830381600087803b158015610a8c57600080fd5b505af1158015610aa0573d6000803e3d6000fd5b505050505b50505050565b6000546040516362d9491f60e01b81526001600160a01b03909116906362d9491f906105f490859085906004016115cd565b600080546040516331a9108f60e11b8152600481018490526001600160a01b0390911690636352211e9060240161057e565b600080546040516370a0823160e01b81526001600160a01b038481166004830152909116906370a082319060240161097b565b60008060009054906101000a90046001600160a01b03166001600160a01b03166375794a3c6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561067e573d6000803e3d6000fd5b60005460405163079cc67960e41b81526001600160a01b03848116600483015260248201849052909116906379cc6790906044016105f4565b60008060009054906101000a90046001600160a01b03166001600160a01b0316637d64bcb46040518163ffffffff1660e01b81526004016020604051808303816000875af11580156104b6573d6000803e3d6000fd5b60008054604080516395d89b4160e01b815290516060936001600160a01b03909316926395d89b4192600480820193918290030181865afa158015610528573d6000803e3d6000fd5b60005460405163a22cb46560e01b81526001600160a01b03848116600483015283151560248301529091169063a22cb465906044016105f4565b60005460405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490529091169063a9059cbb906044016105f4565b60005460405163c87b56dd60e01b8152600481018390526060916001600160a01b03169063c87b56dd90602401600060405180830381865afa158015610d2b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261045c91908101906113e1565b6000805460405163e985e9c560e01b81526001600160a01b03858116600483015284811660248301529091169063e985e9c590604401602060405180830381865afa158015610da6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078c9190611458565b600060208284031215610ddc57600080fd5b81356001600160e01b03198116811461078c57600080fd5b60005b83811015610e0f578181015183820152602001610df7565b83811115610aa55750506000910152565b60008151808452610e38816020860160208601610df4565b601f01601f19169290920160200192915050565b60208152600061078c6020830184610e20565b600060208284031215610e7157600080fd5b5035919050565b6001600160a01b0381168114610e8d57600080fd5b50565b60008060408385031215610ea357600080fd5b8235610eae81610e78565b946020939093013593505050565b600080600060608486031215610ed157600080fd5b8335610edc81610e78565b92506020840135610eec81610e78565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610f3657610f36610efd565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610f6557610f65610efd565b604052919050565b600067ffffffffffffffff821115610f8757610f87610efd565b50601f01601f191660200190565b6000610fa8610fa384610f6d565b610f3c565b9050828152838383011115610fbc57600080fd5b828260208301376000602084830101529392505050565b600082601f830112610fe457600080fd5b61078c83833560208501610f95565b60006020828403121561100557600080fd5b813567ffffffffffffffff81111561101c57600080fd5b610a3484828501610fd3565b600067ffffffffffffffff82111561104257611042610efd565b5060051b60200190565b600080604080848603121561106057600080fd5b833561106b81610e78565b925060208481013567ffffffffffffffff8082111561108957600080fd5b818701915087601f83011261109d57600080fd5b81356110ab610fa382611028565b81815260059190911b8301840190848101908a8311156110ca57600080fd5b8585015b8381101561113d578035858111156110e65760008081fd5b8601808d03601f19018913156110fc5760008081fd5b611104610f13565b888201358152898201358781111561111c5760008081fd5b61112a8f8b83860101610fd3565b828b0152508452509186019186016110ce565b50809750505050505050509250929050565b6000806040838503121561116257600080fd5b823561116d81610e78565b915060208381013567ffffffffffffffff81111561118a57600080fd5b8401601f8101861361119b57600080fd5b80356111a9610fa382611028565b81815260059190911b820183019083810190888311156111c857600080fd5b928401925b828410156111e6578335825292840192908401906111cd565b80955050505050509250929050565b60008060006060848603121561120a57600080fd5b833561121581610e78565b925060208401359150604084013567ffffffffffffffff81111561123857600080fd5b61124486828701610fd3565b9150509250925092565b6000806000806080858703121561126457600080fd5b843561126f81610e78565b9350602085013561127f81610e78565b925060408501359150606085013567ffffffffffffffff8111156112a257600080fd5b8501601f810187136112b357600080fd5b6112c287823560208401610f95565b91505092959194509250565b600080604083850312156112e157600080fd5b823567ffffffffffffffff808211156112f957600080fd5b61130586838701610fd3565b9350602085013591508082111561131b57600080fd5b5061132885828601610fd3565b9150509250929050565b60006020828403121561134457600080fd5b813561078c81610e78565b8015158114610e8d57600080fd5b6000806040838503121561137057600080fd5b823561137b81610e78565b9150602083013561138b8161134f565b809150509250929050565b600080604083850312156113a957600080fd5b82356113b481610e78565b9150602083013561138b81610e78565b6000602082840312156113d657600080fd5b815161078c8161134f565b6000602082840312156113f357600080fd5b815167ffffffffffffffff81111561140a57600080fd5b8201601f8101841361141b57600080fd5b8051611429610fa382610f6d565b81815285602083850101111561143e57600080fd5b61144f826020830160208601610df4565b95945050505050565b60006020828403121561146a57600080fd5b815161078c81610e78565b60006020828403121561148757600080fd5b5051919050565b6001600160a01b0383168152604060208083018290528351828401819052600092916060600583901b860181019290860190878301865b8281101561150457888603605f190184528151805187528501518587018890526114f188880182610e20565b96505092840192908401906001016114c5565b50939998505050505050505050565b6001600160a01b038316815260406020808301829052835191830182905260009184820191906060850190845b8181101561155c57845183529383019391830191600101611540565b5090979650505050505050565b60018060a01b038416815282602082015260606040820152600061144f6060830184610e20565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906115c390830184610e20565b9695505050505050565b6040815260006115e06040830185610e20565b828103602084015261144f8185610e2056fea26469706673582212205bdf4275f4b714a1029ccfe77c0f9a0e20e121a932e1e5840cace97dfa886da964736f6c634300080d0033
\ No newline at end of file
modifiedtests/src/eth/proxy/UniqueNFTProxy.soldiffbeforeafterboth
--- a/tests/src/eth/proxy/UniqueNFTProxy.sol
+++ b/tests/src/eth/proxy/UniqueNFTProxy.sol
@@ -148,29 +148,17 @@
         return proxied.nextTokenId();
     }
 
-    function supportsInterface(uint32 interfaceId)
+    function burnFrom(address from, uint256 tokenId) external override {
+        return proxied.burnFrom(from, tokenId);
+    }
+
+    function supportsInterface(bytes4 interfaceId)
         external
         view
         override
         returns (bool)
     {
         return proxied.supportsInterface(interfaceId);
-    }
-
-    function setVariableMetadata(uint256 tokenId, bytes memory data)
-        external
-        override
-    {
-        return proxied.setVariableMetadata(tokenId, data);
-    }
-
-    function getVariableMetadata(uint256 tokenId)
-        external
-        view
-        override
-        returns (bytes memory)
-    {
-        return proxied.getVariableMetadata(tokenId);
     }
 
     function mintBulk(address to, uint256[] memory tokenIds)
@@ -188,4 +176,12 @@
     {
         return proxied.mintBulkWithTokenURI(to, tokens);
     }
+
+    function setProperty(string memory key, string memory value) external override {
+        return proxied.setProperty(key, value);
+    }
+
+	function deleteProperty(string memory key) external override {
+        return proxied.deleteProperty(key);
+    }
 }
modifiedtests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth
--- a/tests/src/eth/proxy/nonFungibleProxy.test.ts
+++ b/tests/src/eth/proxy/nonFungibleProxy.test.ts
@@ -15,7 +15,7 @@
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
 import privateKey from '../../substrate/privateKey';
-import {createCollectionExpectSuccess, createItemExpectSuccess, setVariableMetaDataExpectSuccess, setMetadataUpdatePermissionFlagExpectSuccess} from '../../util/helpers';
+import {createCollectionExpectSuccess, createItemExpectSuccess} from '../../util/helpers';
 import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents} from '../util/helpers';
 import nonFungibleAbi from '../nonFungibleAbi.json';
 import {expect} from 'chai';
@@ -333,36 +333,5 @@
       const balance = await contract.methods.balanceOf(receiver).call();
       expect(+balance).to.equal(1);
     }
-  });
-
-  itWeb3('Can perform getVariableMetadata', async ({web3, api}) => {
-    const collection = await createCollectionExpectSuccess({
-      mode: {type: 'NFT'},
-    });
-    const alice = privateKey('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
-
-    const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
-    const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
-    await setMetadataUpdatePermissionFlagExpectSuccess(alice, collection, 'Admin');
-    await setVariableMetaDataExpectSuccess(alice, collection, item, [1, 2, 3]);
-
-    expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');
-  });
-
-  itWeb3('Can perform setVariableMetadata', async ({web3, api}) => {
-    const collection = await createCollectionExpectSuccess({
-      mode: {type: 'NFT'},
-    });
-    const alice = privateKey('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
-
-    const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
-    const item = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
-
-    expect(await contract.methods.setVariableMetadata(item, '0x010203').send({from: caller}));
-    expect(await contract.methods.getVariableMetadata(item).call()).to.be.equal('0x010203');
   });
 });
addedtests/src/eth/tokenProperties.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/tokenProperties.test.ts
@@ -0,0 +1,95 @@
+import privateKey from '../substrate/privateKey';
+import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess} from '../util/helpers';
+import {cartesian, collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3} from './util/helpers';
+import nonFungibleAbi from './nonFungibleAbi.json';
+import {expect} from 'chai';
+import {executeTransaction} from '../substrate/substrate-api';
+
+describe('EVM token properties', () => {
+  itWeb3('Can be reconfigured', async({web3, api}) => {
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) {
+      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+      await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
+      
+      const address = collectionIdToAddress(collection);
+      const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+  
+      await contract.methods.setTokenPropertyPermission('testKey', mutable, collectionAdmin, tokenOwner).send({from: caller});
+  
+      const state = (await api.query.common.collectionPropertyPermissions(collection)).toJSON();
+      expect(state).to.be.deep.equal({
+        [web3.utils.toHex('testKey')]: {mutable, collectionAdmin, tokenOwner},
+      });
+    }
+  });
+  itWeb3('Can be set', async({web3, api}) => {
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+    const token = await createItemExpectSuccess(alice, collection, 'NFT');
+
+    await executeTransaction(api, alice, api.tx.unique.setPropertyPermissions(collection, [{
+      key: 'testKey',
+      permission: {
+        collectionAdmin: true,
+      },
+    }]));
+
+    await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+    await contract.methods.setProperty(token, 'testKey', Buffer.from('testValue')).send({from: caller});
+
+    const [{value}] = (await api.rpc.unique.tokenProperties(collection, token, ['testKey'])).toHuman()! as any;
+    expect(value).to.equal('testValue');
+  });
+  itWeb3('Can be deleted', async({web3, api}) => {
+    const alice = privateKey('//Alice');
+    const caller = await createEthAccountWithBalance(api, web3);
+    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+    const token = await createItemExpectSuccess(alice, collection, 'NFT');
+
+    await executeTransaction(api, alice, api.tx.unique.setPropertyPermissions(collection, [{
+      key: 'testKey',
+      permission: {
+        mutable: true,
+        collectionAdmin: true,
+      },
+    }]));
+    await executeTransaction(api, alice, api.tx.unique.setTokenProperties(collection, token, [{key: 'testKey', value: 'testValue'}]));
+
+    await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+    await contract.methods.deleteProperty(token, 'testKey').send({from: caller});
+
+    const result = (await api.rpc.unique.tokenProperties(collection, token, ['testKey'])).toJSON()! as any;
+    expect(result.length).to.equal(0);
+  });
+  itWeb3('Can be read', async({web3, api}) => {
+    const alice = privateKey('//Alice');
+    const caller = createEthAccount(web3);
+    const collection = await createCollectionExpectSuccess({mode: {type:'NFT'}});
+    const token = await createItemExpectSuccess(alice, collection, 'NFT');
+
+    await executeTransaction(api, alice, api.tx.unique.setPropertyPermissions(collection, [{
+      key: 'testKey',
+      permission: {
+        collectionAdmin: true,
+      },
+    }]));
+    await executeTransaction(api, alice, api.tx.unique.setTokenProperties(collection, token, [{key: 'testKey', value: 'testValue'}]));
+
+    const address = collectionIdToAddress(collection);
+    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+    const value = await contract.methods.property(token, 'testKey').call();
+    expect(value).to.equal(web3.utils.toHex('testValue'));
+  });
+});
modifiedtests/src/eth/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/eth/util/helpers.ts
+++ b/tests/src/eth/util/helpers.ts
@@ -322,3 +322,15 @@
 
   return before - after;
 }
+
+type ElementOf<A> = A extends readonly (infer T)[] ? T : never;
+// I want a fancier api, not a memory efficiency
+export function* cartesian<T extends Array<Array<any>>, R extends Array<any>>(internalRest: [...R], ...args: [...T]): Generator<[...R, ...{[K in keyof T]: ElementOf<T[K]>}]> {
+  if(args.length === 0) {
+    yield internalRest as any;
+    return;
+  }
+  for(const value of args[0]) {
+    yield* cartesian([...internalRest, value], ...args.slice(1)) as any;
+  }
+}
\ No newline at end of file
modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-errors.ts
+++ b/tests/src/interfaces/augment-api-errors.ts
@@ -137,6 +137,10 @@
        **/
       OwnerPermissionsCantBeReverted: AugmentedError<ApiType>;
       /**
+       * Property key is too long
+       **/
+      PropertyKeyIsTooLong: AugmentedError<ApiType>;
+      /**
        * Tried to store more property keys than allowed
        **/
       PropertyLimitReached: AugmentedError<ApiType>;
@@ -156,10 +160,6 @@
        * Item balance not enough.
        **/
       TokenValueTooLow: AugmentedError<ApiType>;
-      /**
-       * variable_data exceeded data limit.
-       **/
-      TokenVariableDataLimitExceeded: AugmentedError<ApiType>;
       /**
        * Total collections bound exceeded.
        **/
@@ -168,10 +168,6 @@
        * Collection settings not allowing items transferring
        **/
       TransferNotAllowed: AugmentedError<ApiType>;
-      /**
-       * Unable to read array of unbounded keys
-       **/
-      UnableToReadUnboundedKeys: AugmentedError<ApiType>;
       /**
        * Target collection doesn't supports this operation
        **/
modifiedtests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-rpc.ts
+++ b/tests/src/interfaces/augment-api-rpc.ts
@@ -1,7 +1,7 @@
 // Auto-generated via `yarn polkadot-types-from-chain`, do not edit
 /* eslint-disable */
 
-import type { PalletEvmAccountBasicCrossAccountIdRepr, UpDataStructsCollectionLimits, UpDataStructsCollectionStats, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsRpcCollection, UpDataStructsTokenData } from './unique';
+import type { PalletEvmAccountBasicCrossAccountIdRepr, RmrkTypesBaseInfo, RmrkTypesCollectionInfo, RmrkTypesNftChild, RmrkTypesNftInfo, RmrkTypesPartType, RmrkTypesPropertyInfo, RmrkTypesResourceInfo, RmrkTypesTheme, UpDataStructsCollectionLimits, UpDataStructsCollectionStats, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsRpcCollection, UpDataStructsTokenData } from './unique';
 import type { AugmentedRpc } from '@polkadot/rpc-core/types';
 import type { Metadata, StorageKey } from '@polkadot/types';
 import type { Bytes, HashMap, Json, Null, Option, Text, U256, U64, Vec, bool, u128, u32, u64 } from '@polkadot/types-codec';
@@ -401,19 +401,19 @@
       /**
        * Get base info
        **/
-      base: AugmentedRpc<(baseId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTraitsBaseBaseInfo>>>;
+      base: AugmentedRpc<(baseId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTypesBaseInfo>>>;
       /**
        * Get all Base's parts
        **/
-      baseParts: AugmentedRpc<(baseId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTraitsPartPartType>>>;
+      baseParts: AugmentedRpc<(baseId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTypesPartType>>>;
       /**
        * Get collection by id
        **/
-      collectionById: AugmentedRpc<(id: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTraitsCollectionCollectionInfo>>>;
+      collectionById: AugmentedRpc<(id: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTypesCollectionInfo>>>;
       /**
        * Get collection properties
        **/
-      collectionProperties: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTraitsPropertyPropertyInfo>>>;
+      collectionProperties: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTypesPropertyInfo>>>;
       /**
        * Get the latest created collection id
        **/
@@ -421,15 +421,15 @@
       /**
        * Get NFT by collection id and NFT id
        **/
-      nftById: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTraitsNftNftInfo>>>;
+      nftById: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTypesNftInfo>>>;
       /**
        * Get NFT children
        **/
-      nftChildren: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTraitsNftNftChild>>>;
+      nftChildren: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTypesNftChild>>>;
       /**
        * Get NFT properties
        **/
-      nftProperties: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTraitsPropertyPropertyInfo>>>;
+      nftProperties: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTypesPropertyInfo>>>;
       /**
        * Get NFT resource priorities
        **/
@@ -437,7 +437,7 @@
       /**
        * Get NFT resources
        **/
-      nftResources: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTraitsResourceResourceInfo>>>;
+      nftResources: AugmentedRpc<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<RmrkTypesResourceInfo>>>;
       /**
        * Get Base's theme names
        **/
@@ -445,7 +445,7 @@
       /**
        * Get Theme's keys values
        **/
-      themes: AugmentedRpc<(baseId: u32 | AnyNumber | Uint8Array, themeName: Text | string, keys: Option<Vec<Text>> | null | object | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTraitsTheme>>>;
+      themes: AugmentedRpc<(baseId: u32 | AnyNumber | Uint8Array, themeName: Text | string, keys: Option<Vec<Text>> | null | object | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<RmrkTypesTheme>>>;
     };
     rpc: {
       /**
@@ -659,7 +659,7 @@
       /**
        * Get collection properties
        **/
-      collectionProperties: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, propertyKeys: Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<Vec<UpDataStructsProperty>>>;
+      collectionProperties: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, propertyKeys?: Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<Vec<UpDataStructsProperty>>>;
       /**
        * Get collection stats
        **/
@@ -687,11 +687,11 @@
       /**
        * Get property permissions
        **/
-      propertyPermissions: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, propertyKeys: Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<Vec<UpDataStructsPropertyKeyPermission>>>;
+      propertyPermissions: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, propertyKeys?: Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<Vec<UpDataStructsPropertyKeyPermission>>>;
       /**
        * Get token data
        **/
-      tokenData: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, propertyKeys: Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<UpDataStructsTokenData>>;
+      tokenData: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, propertyKeys?: Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<UpDataStructsTokenData>>;
       /**
        * Check if token exists
        **/
@@ -703,7 +703,7 @@
       /**
        * Get token properties
        **/
-      tokenProperties: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, propertyKeys: Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<Vec<UpDataStructsProperty>>>;
+      tokenProperties: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, propertyKeys?: Vec<Text> | (Text | string)[], at?: Hash | string | Uint8Array) => Observable<Vec<UpDataStructsProperty>>>;
       /**
        * Get token owner, in case of nested token - find parent recursive
        **/
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -5,7 +5,7 @@
 import type { Bytes, Compact, Option, U256, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types-codec';
 import type { AnyNumber, IMethod, ITuple } from '@polkadot/types-codec/types';
 import type { AccountId32, Call, H160, H256, MultiAddress, Perbill } from '@polkadot/types/interfaces/runtime';
-import type { CumulusPrimitivesParachainInherentParachainInherentData, EthereumTransactionTransactionV2, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, UpDataStructsAccessMode, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCreateCollectionData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsMetaUpdatePermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsSchemaVersion, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
+import type { CumulusPrimitivesParachainInherentParachainInherentData, EthereumTransactionTransactionV2, OrmlVestingVestingSchedule, PalletEvmAccountBasicCrossAccountIdRepr, UpDataStructsAccessMode, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCreateCollectionData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsSchemaVersion, XcmV1MultiLocation, XcmV2WeightLimit, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
 
 declare module '@polkadot/api-base/types/submittable' {
   export interface AugmentedSubmittables<ApiType extends ApiTypes> {
@@ -679,7 +679,7 @@
        * 
        * Prefer it to deprecated [`created_collection`] method
        **/
-      createCollectionEx: AugmentedSubmittable<(data: UpDataStructsCreateCollectionData | { mode?: any; access?: any; name?: any; description?: any; tokenPrefix?: any; offchainSchema?: any; schemaVersion?: any; pendingSponsor?: any; limits?: any; constOnChainSchema?: any; metaUpdatePermission?: any; tokenPropertyPermissions?: any; properties?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [UpDataStructsCreateCollectionData]>;
+      createCollectionEx: AugmentedSubmittable<(data: UpDataStructsCreateCollectionData | { mode?: any; access?: any; name?: any; description?: any; tokenPrefix?: any; offchainSchema?: any; schemaVersion?: any; pendingSponsor?: any; limits?: any; constOnChainSchema?: any; tokenPropertyPermissions?: any; properties?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [UpDataStructsCreateCollectionData]>;
       /**
        * This method creates a concrete instance of NFT Collection created with CreateCollection method.
        * 
@@ -809,20 +809,6 @@
        **/
       setConstOnChainSchema: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, schema: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, Bytes]>;
       /**
-       * Set meta_update_permission value for particular collection
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner.
-       * 
-       * # Arguments
-       * 
-       * * collection_id: ID of the collection.
-       * 
-       * * value: New flag value.
-       **/
-      setMetaUpdatePermissionFlag: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, value: UpDataStructsMetaUpdatePermission | 'ItemOwner' | 'Admin' | 'None' | number | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsMetaUpdatePermission]>;
-      /**
        * Allows Anyone to create tokens if:
        * * Allow List is enabled, and
        * * Address is added to allow list, and
@@ -900,21 +886,6 @@
        * * value: New flag value.
        **/
       setTransfersEnabledFlag: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, value: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, bool]>;
-      /**
-       * Set off-chain data schema.
-       * 
-       * # Permissions
-       * 
-       * * Collection Owner
-       * * Collection Admin
-       * 
-       * # Arguments
-       * 
-       * * collection_id.
-       * 
-       * * schema: String representing the offchain data schema.
-       **/
-      setVariableMetaData: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, data: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, Bytes]>;
       /**
        * Change ownership of the token.
        * 
modifiedtests/src/interfaces/augment-types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-types.ts
+++ b/tests/src/interfaces/augment-types.ts
@@ -1,7 +1,7 @@
 // Auto-generated via `yarn polkadot-types-from-defs`, do not edit
 /* eslint-disable */
 
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportPalletId, FrameSupportStorageBoundedBTreeSet, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletXcmCall, PalletXcmError, PalletXcmEvent, PhantomTypeUpDataStructsBaseInfo, PhantomTypeUpDataStructsCollectionInfo, PhantomTypeUpDataStructsNftChild, PhantomTypeUpDataStructsNftInfo, PhantomTypeUpDataStructsPartType, PhantomTypeUpDataStructsPropertyInfo, PhantomTypeUpDataStructsResourceInfo, PhantomTypeUpDataStructsRpcCollection, PhantomTypeUpDataStructsTheme, PhantomTypeUpDataStructsTokenData, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTypesAccountIdOrCollectionNftTuple, RmrkTypesBaseInfo, RmrkTypesCollectionInfo, RmrkTypesEquippableList, RmrkTypesFixedPart, RmrkTypesNftChild, RmrkTypesNftInfo, RmrkTypesPartType, RmrkTypesPropertyInfo, RmrkTypesResourceInfo, RmrkTypesRoyaltyInfo, RmrkTypesSlotPart, RmrkTypesTheme, RmrkTypesThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionField, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsMetaUpdatePermission, UpDataStructsNestingRule, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSchemaVersion, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './unique';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletXcmCall, PalletXcmError, PalletXcmEvent, PhantomTypeUpDataStructsBaseInfo, PhantomTypeUpDataStructsCollectionInfo, PhantomTypeUpDataStructsNftChild, PhantomTypeUpDataStructsNftInfo, PhantomTypeUpDataStructsPartType, PhantomTypeUpDataStructsPropertyInfo, PhantomTypeUpDataStructsResourceInfo, PhantomTypeUpDataStructsRpcCollection, PhantomTypeUpDataStructsTheme, PhantomTypeUpDataStructsTokenData, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTypesAccountIdOrCollectionNftTuple, RmrkTypesBaseInfo, RmrkTypesCollectionInfo, RmrkTypesEquippableList, RmrkTypesFixedPart, RmrkTypesNftChild, RmrkTypesNftInfo, RmrkTypesPartType, RmrkTypesPropertyInfo, RmrkTypesResourceInfo, RmrkTypesRoyaltyInfo, RmrkTypesSlotPart, RmrkTypesTheme, RmrkTypesThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionField, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingRule, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSchemaVersion, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './unique';
 import type { Data, StorageKey } from '@polkadot/types';
 import type { BitVec, Bool, Bytes, I128, I16, I256, I32, I64, I8, Json, Null, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec';
 import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';
@@ -478,7 +478,6 @@
     ForkTreePendingChangeNode: ForkTreePendingChangeNode;
     FpRpcTransactionStatus: FpRpcTransactionStatus;
     FrameSupportPalletId: FrameSupportPalletId;
-    FrameSupportStorageBoundedBTreeSet: FrameSupportStorageBoundedBTreeSet;
     FrameSupportTokensMiscBalanceStatus: FrameSupportTokensMiscBalanceStatus;
     FrameSupportWeightsDispatchClass: FrameSupportWeightsDispatchClass;
     FrameSupportWeightsDispatchInfo: FrameSupportWeightsDispatchInfo;
@@ -1204,7 +1203,6 @@
     UpDataStructsCreateNftExData: UpDataStructsCreateNftExData;
     UpDataStructsCreateReFungibleData: UpDataStructsCreateReFungibleData;
     UpDataStructsCreateRefungibleExData: UpDataStructsCreateRefungibleExData;
-    UpDataStructsMetaUpdatePermission: UpDataStructsMetaUpdatePermission;
     UpDataStructsNestingRule: UpDataStructsNestingRule;
     UpDataStructsProperties: UpDataStructsProperties;
     UpDataStructsPropertiesMapBoundedVec: UpDataStructsPropertiesMapBoundedVec;
modifiedtests/src/interfaces/lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -1360,15 +1360,6 @@
         itemId: 'u32',
         value: 'u128',
       },
-      set_variable_meta_data: {
-        collectionId: 'u32',
-        itemId: 'u32',
-        data: 'Bytes',
-      },
-      set_meta_update_permission_flag: {
-        collectionId: 'u32',
-        value: 'UpDataStructsMetaUpdatePermission',
-      },
       set_schema_version: {
         collectionId: 'u32',
         version: 'UpDataStructsSchemaVersion',
@@ -1411,7 +1402,6 @@
     pendingSponsor: 'Option<AccountId32>',
     limits: 'Option<UpDataStructsCollectionLimits>',
     constOnChainSchema: 'Bytes',
-    metaUpdatePermission: 'Option<UpDataStructsMetaUpdatePermission>',
     tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',
     properties: 'Vec<UpDataStructsProperty>'
   },
@@ -1462,20 +1452,14 @@
     }
   },
   /**
-   * Lookup177: up_data_structs::MetaUpdatePermission
+   * Lookup177: up_data_structs::PropertyKeyPermission
    **/
-  UpDataStructsMetaUpdatePermission: {
-    _enum: ['ItemOwner', 'Admin', 'None']
-  },
-  /**
-   * Lookup179: up_data_structs::PropertyKeyPermission
-   **/
   UpDataStructsPropertyKeyPermission: {
     key: 'Bytes',
     permission: 'UpDataStructsPropertyPermission'
   },
   /**
-   * Lookup181: up_data_structs::PropertyPermission
+   * Lookup179: up_data_structs::PropertyPermission
    **/
   UpDataStructsPropertyPermission: {
     mutable: 'bool',
@@ -1483,14 +1467,14 @@
     tokenOwner: 'bool'
   },
   /**
-   * Lookup184: up_data_structs::Property
+   * Lookup182: up_data_structs::Property
    **/
   UpDataStructsProperty: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup186: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>
+   * Lookup184: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>
    **/
   PalletEvmAccountBasicCrossAccountIdRepr: {
     _enum: {
@@ -1499,7 +1483,7 @@
     }
   },
   /**
-   * Lookup188: up_data_structs::CreateItemData
+   * Lookup186: up_data_structs::CreateItemData
    **/
   UpDataStructsCreateItemData: {
     _enum: {
@@ -1509,29 +1493,27 @@
     }
   },
   /**
-   * Lookup189: up_data_structs::CreateNftData
+   * Lookup187: up_data_structs::CreateNftData
    **/
   UpDataStructsCreateNftData: {
     constData: 'Bytes',
-    variableData: 'Bytes',
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup191: up_data_structs::CreateFungibleData
+   * Lookup189: up_data_structs::CreateFungibleData
    **/
   UpDataStructsCreateFungibleData: {
     value: 'u128'
   },
   /**
-   * Lookup192: up_data_structs::CreateReFungibleData
+   * Lookup190: up_data_structs::CreateReFungibleData
    **/
   UpDataStructsCreateReFungibleData: {
     constData: 'Bytes',
-    variableData: 'Bytes',
     pieces: 'u128'
   },
   /**
-   * Lookup196: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup194: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateItemExData: {
     _enum: {
@@ -1542,32 +1524,30 @@
     }
   },
   /**
-   * Lookup198: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup196: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateNftExData: {
     constData: 'Bytes',
-    variableData: 'Bytes',
     properties: 'Vec<UpDataStructsProperty>',
     owner: 'PalletEvmAccountBasicCrossAccountIdRepr'
   },
   /**
-   * Lookup205: up_data_structs::CreateRefungibleExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup203: up_data_structs::CreateRefungibleExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateRefungibleExData: {
     constData: 'Bytes',
-    variableData: 'Bytes',
     users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>'
   },
   /**
-   * Lookup207: pallet_template_transaction_payment::Call<T>
+   * Lookup205: pallet_template_transaction_payment::Call<T>
    **/
   PalletTemplateTransactionPaymentCall: 'Null',
   /**
-   * Lookup208: pallet_structure::pallet::Call<T>
+   * Lookup206: pallet_structure::pallet::Call<T>
    **/
   PalletStructureCall: 'Null',
   /**
-   * Lookup209: pallet_evm::pallet::Call<T>
+   * Lookup207: pallet_evm::pallet::Call<T>
    **/
   PalletEvmCall: {
     _enum: {
@@ -1610,7 +1590,7 @@
     }
   },
   /**
-   * Lookup215: pallet_ethereum::pallet::Call<T>
+   * Lookup213: pallet_ethereum::pallet::Call<T>
    **/
   PalletEthereumCall: {
     _enum: {
@@ -1620,7 +1600,7 @@
     }
   },
   /**
-   * Lookup216: ethereum::transaction::TransactionV2
+   * Lookup214: ethereum::transaction::TransactionV2
    **/
   EthereumTransactionTransactionV2: {
     _enum: {
@@ -1630,7 +1610,7 @@
     }
   },
   /**
-   * Lookup217: ethereum::transaction::LegacyTransaction
+   * Lookup215: ethereum::transaction::LegacyTransaction
    **/
   EthereumTransactionLegacyTransaction: {
     nonce: 'U256',
@@ -1642,7 +1622,7 @@
     signature: 'EthereumTransactionTransactionSignature'
   },
   /**
-   * Lookup218: ethereum::transaction::TransactionAction
+   * Lookup216: ethereum::transaction::TransactionAction
    **/
   EthereumTransactionTransactionAction: {
     _enum: {
@@ -1651,7 +1631,7 @@
     }
   },
   /**
-   * Lookup219: ethereum::transaction::TransactionSignature
+   * Lookup217: ethereum::transaction::TransactionSignature
    **/
   EthereumTransactionTransactionSignature: {
     v: 'u64',
@@ -1659,7 +1639,7 @@
     s: 'H256'
   },
   /**
-   * Lookup221: ethereum::transaction::EIP2930Transaction
+   * Lookup219: ethereum::transaction::EIP2930Transaction
    **/
   EthereumTransactionEip2930Transaction: {
     chainId: 'u64',
@@ -1675,14 +1655,14 @@
     s: 'H256'
   },
   /**
-   * Lookup223: ethereum::transaction::AccessListItem
+   * Lookup221: ethereum::transaction::AccessListItem
    **/
   EthereumTransactionAccessListItem: {
     address: 'H160',
     storageKeys: 'Vec<H256>'
   },
   /**
-   * Lookup224: ethereum::transaction::EIP1559Transaction
+   * Lookup222: ethereum::transaction::EIP1559Transaction
    **/
   EthereumTransactionEip1559Transaction: {
     chainId: 'u64',
@@ -1699,7 +1679,7 @@
     s: 'H256'
   },
   /**
-   * Lookup225: pallet_evm_migration::pallet::Call<T>
+   * Lookup223: pallet_evm_migration::pallet::Call<T>
    **/
   PalletEvmMigrationCall: {
     _enum: {
@@ -1717,7 +1697,7 @@
     }
   },
   /**
-   * Lookup228: pallet_sudo::pallet::Event<T>
+   * Lookup226: pallet_sudo::pallet::Event<T>
    **/
   PalletSudoEvent: {
     _enum: {
@@ -1733,7 +1713,7 @@
     }
   },
   /**
-   * Lookup230: sp_runtime::DispatchError
+   * Lookup228: sp_runtime::DispatchError
    **/
   SpRuntimeDispatchError: {
     _enum: {
@@ -1750,38 +1730,38 @@
     }
   },
   /**
-   * Lookup231: sp_runtime::ModuleError
+   * Lookup229: sp_runtime::ModuleError
    **/
   SpRuntimeModuleError: {
     index: 'u8',
     error: '[u8;4]'
   },
   /**
-   * Lookup232: sp_runtime::TokenError
+   * Lookup230: sp_runtime::TokenError
    **/
   SpRuntimeTokenError: {
     _enum: ['NoFunds', 'WouldDie', 'BelowMinimum', 'CannotCreate', 'UnknownAsset', 'Frozen', 'Unsupported']
   },
   /**
-   * Lookup233: sp_runtime::ArithmeticError
+   * Lookup231: sp_runtime::ArithmeticError
    **/
   SpRuntimeArithmeticError: {
     _enum: ['Underflow', 'Overflow', 'DivisionByZero']
   },
   /**
-   * Lookup234: sp_runtime::TransactionalError
+   * Lookup232: sp_runtime::TransactionalError
    **/
   SpRuntimeTransactionalError: {
     _enum: ['LimitReached', 'NoLayer']
   },
   /**
-   * Lookup235: pallet_sudo::pallet::Error<T>
+   * Lookup233: pallet_sudo::pallet::Error<T>
    **/
   PalletSudoError: {
     _enum: ['RequireSudo']
   },
   /**
-   * Lookup236: frame_system::AccountInfo<Index, pallet_balances::AccountData<Balance>>
+   * Lookup234: frame_system::AccountInfo<Index, pallet_balances::AccountData<Balance>>
    **/
   FrameSystemAccountInfo: {
     nonce: 'u32',
@@ -1791,7 +1771,7 @@
     data: 'PalletBalancesAccountData'
   },
   /**
-   * Lookup237: frame_support::weights::PerDispatchClass<T>
+   * Lookup235: frame_support::weights::PerDispatchClass<T>
    **/
   FrameSupportWeightsPerDispatchClassU64: {
     normal: 'u64',
@@ -1799,13 +1779,13 @@
     mandatory: 'u64'
   },
   /**
-   * Lookup238: sp_runtime::generic::digest::Digest
+   * Lookup236: sp_runtime::generic::digest::Digest
    **/
   SpRuntimeDigest: {
     logs: 'Vec<SpRuntimeDigestDigestItem>'
   },
   /**
-   * Lookup240: sp_runtime::generic::digest::DigestItem
+   * Lookup238: sp_runtime::generic::digest::DigestItem
    **/
   SpRuntimeDigestDigestItem: {
     _enum: {
@@ -1821,7 +1801,7 @@
     }
   },
   /**
-   * Lookup242: frame_system::EventRecord<opal_runtime::Event, primitive_types::H256>
+   * Lookup240: frame_system::EventRecord<opal_runtime::Event, primitive_types::H256>
    **/
   FrameSystemEventRecord: {
     phase: 'FrameSystemPhase',
@@ -1829,7 +1809,7 @@
     topics: 'Vec<H256>'
   },
   /**
-   * Lookup244: frame_system::pallet::Event<T>
+   * Lookup242: frame_system::pallet::Event<T>
    **/
   FrameSystemEvent: {
     _enum: {
@@ -1857,7 +1837,7 @@
     }
   },
   /**
-   * Lookup245: frame_support::weights::DispatchInfo
+   * Lookup243: frame_support::weights::DispatchInfo
    **/
   FrameSupportWeightsDispatchInfo: {
     weight: 'u64',
@@ -1865,19 +1845,19 @@
     paysFee: 'FrameSupportWeightsPays'
   },
   /**
-   * Lookup246: frame_support::weights::DispatchClass
+   * Lookup244: frame_support::weights::DispatchClass
    **/
   FrameSupportWeightsDispatchClass: {
     _enum: ['Normal', 'Operational', 'Mandatory']
   },
   /**
-   * Lookup247: frame_support::weights::Pays
+   * Lookup245: frame_support::weights::Pays
    **/
   FrameSupportWeightsPays: {
     _enum: ['Yes', 'No']
   },
   /**
-   * Lookup248: orml_vesting::module::Event<T>
+   * Lookup246: orml_vesting::module::Event<T>
    **/
   OrmlVestingModuleEvent: {
     _enum: {
@@ -1896,7 +1876,7 @@
     }
   },
   /**
-   * Lookup249: cumulus_pallet_xcmp_queue::pallet::Event<T>
+   * Lookup247: cumulus_pallet_xcmp_queue::pallet::Event<T>
    **/
   CumulusPalletXcmpQueueEvent: {
     _enum: {
@@ -1911,7 +1891,7 @@
     }
   },
   /**
-   * Lookup250: pallet_xcm::pallet::Event<T>
+   * Lookup248: pallet_xcm::pallet::Event<T>
    **/
   PalletXcmEvent: {
     _enum: {
@@ -1934,7 +1914,7 @@
     }
   },
   /**
-   * Lookup251: xcm::v2::traits::Outcome
+   * Lookup249: xcm::v2::traits::Outcome
    **/
   XcmV2TraitsOutcome: {
     _enum: {
@@ -1944,7 +1924,7 @@
     }
   },
   /**
-   * Lookup253: cumulus_pallet_xcm::pallet::Event<T>
+   * Lookup251: cumulus_pallet_xcm::pallet::Event<T>
    **/
   CumulusPalletXcmEvent: {
     _enum: {
@@ -1954,7 +1934,7 @@
     }
   },
   /**
-   * Lookup254: cumulus_pallet_dmp_queue::pallet::Event<T>
+   * Lookup252: cumulus_pallet_dmp_queue::pallet::Event<T>
    **/
   CumulusPalletDmpQueueEvent: {
     _enum: {
@@ -1967,7 +1947,7 @@
     }
   },
   /**
-   * Lookup255: pallet_unique::RawEvent<sp_core::crypto::AccountId32, pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup253: pallet_unique::RawEvent<sp_core::crypto::AccountId32, pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   PalletUniqueRawEvent: {
     _enum: {
@@ -1988,7 +1968,7 @@
     }
   },
   /**
-   * Lookup256: pallet_common::pallet::Event<T>
+   * Lookup254: pallet_common::pallet::Event<T>
    **/
   PalletCommonEvent: {
     _enum: {
@@ -2006,7 +1986,7 @@
     }
   },
   /**
-   * Lookup257: pallet_structure::pallet::Event<T>
+   * Lookup255: pallet_structure::pallet::Event<T>
    **/
   PalletStructureEvent: {
     _enum: {
@@ -2014,7 +1994,7 @@
     }
   },
   /**
-   * Lookup258: pallet_evm::pallet::Event<T>
+   * Lookup256: pallet_evm::pallet::Event<T>
    **/
   PalletEvmEvent: {
     _enum: {
@@ -2028,7 +2008,7 @@
     }
   },
   /**
-   * Lookup259: ethereum::log::Log
+   * Lookup257: ethereum::log::Log
    **/
   EthereumLog: {
     address: 'H160',
@@ -2036,7 +2016,7 @@
     data: 'Bytes'
   },
   /**
-   * Lookup260: pallet_ethereum::pallet::Event
+   * Lookup258: pallet_ethereum::pallet::Event
    **/
   PalletEthereumEvent: {
     _enum: {
@@ -2044,7 +2024,7 @@
     }
   },
   /**
-   * Lookup261: evm_core::error::ExitReason
+   * Lookup259: evm_core::error::ExitReason
    **/
   EvmCoreErrorExitReason: {
     _enum: {
@@ -2055,13 +2035,13 @@
     }
   },
   /**
-   * Lookup262: evm_core::error::ExitSucceed
+   * Lookup260: evm_core::error::ExitSucceed
    **/
   EvmCoreErrorExitSucceed: {
     _enum: ['Stopped', 'Returned', 'Suicided']
   },
   /**
-   * Lookup263: evm_core::error::ExitError
+   * Lookup261: evm_core::error::ExitError
    **/
   EvmCoreErrorExitError: {
     _enum: {
@@ -2083,13 +2063,13 @@
     }
   },
   /**
-   * Lookup266: evm_core::error::ExitRevert
+   * Lookup264: evm_core::error::ExitRevert
    **/
   EvmCoreErrorExitRevert: {
     _enum: ['Reverted']
   },
   /**
-   * Lookup267: evm_core::error::ExitFatal
+   * Lookup265: evm_core::error::ExitFatal
    **/
   EvmCoreErrorExitFatal: {
     _enum: {
@@ -2100,7 +2080,7 @@
     }
   },
   /**
-   * Lookup268: frame_system::Phase
+   * Lookup266: frame_system::Phase
    **/
   FrameSystemPhase: {
     _enum: {
@@ -2110,14 +2090,14 @@
     }
   },
   /**
-   * Lookup270: frame_system::LastRuntimeUpgradeInfo
+   * Lookup268: frame_system::LastRuntimeUpgradeInfo
    **/
   FrameSystemLastRuntimeUpgradeInfo: {
     specVersion: 'Compact<u32>',
     specName: 'Text'
   },
   /**
-   * Lookup271: frame_system::limits::BlockWeights
+   * Lookup269: frame_system::limits::BlockWeights
    **/
   FrameSystemLimitsBlockWeights: {
     baseBlock: 'u64',
@@ -2125,7 +2105,7 @@
     perClass: 'FrameSupportWeightsPerDispatchClassWeightsPerClass'
   },
   /**
-   * Lookup272: frame_support::weights::PerDispatchClass<frame_system::limits::WeightsPerClass>
+   * Lookup270: frame_support::weights::PerDispatchClass<frame_system::limits::WeightsPerClass>
    **/
   FrameSupportWeightsPerDispatchClassWeightsPerClass: {
     normal: 'FrameSystemLimitsWeightsPerClass',
@@ -2133,7 +2113,7 @@
     mandatory: 'FrameSystemLimitsWeightsPerClass'
   },
   /**
-   * Lookup273: frame_system::limits::WeightsPerClass
+   * Lookup271: frame_system::limits::WeightsPerClass
    **/
   FrameSystemLimitsWeightsPerClass: {
     baseExtrinsic: 'u64',
@@ -2142,13 +2122,13 @@
     reserved: 'Option<u64>'
   },
   /**
-   * Lookup275: frame_system::limits::BlockLength
+   * Lookup273: frame_system::limits::BlockLength
    **/
   FrameSystemLimitsBlockLength: {
     max: 'FrameSupportWeightsPerDispatchClassU32'
   },
   /**
-   * Lookup276: frame_support::weights::PerDispatchClass<T>
+   * Lookup274: frame_support::weights::PerDispatchClass<T>
    **/
   FrameSupportWeightsPerDispatchClassU32: {
     normal: 'u32',
@@ -2156,14 +2136,14 @@
     mandatory: 'u32'
   },
   /**
-   * Lookup277: frame_support::weights::RuntimeDbWeight
+   * Lookup275: frame_support::weights::RuntimeDbWeight
    **/
   FrameSupportWeightsRuntimeDbWeight: {
     read: 'u64',
     write: 'u64'
   },
   /**
-   * Lookup278: sp_version::RuntimeVersion
+   * Lookup276: sp_version::RuntimeVersion
    **/
   SpVersionRuntimeVersion: {
     specName: 'Text',
@@ -2176,19 +2156,19 @@
     stateVersion: 'u8'
   },
   /**
-   * Lookup282: frame_system::pallet::Error<T>
+   * Lookup280: frame_system::pallet::Error<T>
    **/
   FrameSystemError: {
     _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered']
   },
   /**
-   * Lookup284: orml_vesting::module::Error<T>
+   * Lookup282: orml_vesting::module::Error<T>
    **/
   OrmlVestingModuleError: {
     _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded']
   },
   /**
-   * Lookup286: cumulus_pallet_xcmp_queue::InboundChannelDetails
+   * Lookup284: cumulus_pallet_xcmp_queue::InboundChannelDetails
    **/
   CumulusPalletXcmpQueueInboundChannelDetails: {
     sender: 'u32',
@@ -2196,19 +2176,19 @@
     messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>'
   },
   /**
-   * Lookup287: cumulus_pallet_xcmp_queue::InboundState
+   * Lookup285: cumulus_pallet_xcmp_queue::InboundState
    **/
   CumulusPalletXcmpQueueInboundState: {
     _enum: ['Ok', 'Suspended']
   },
   /**
-   * Lookup290: polkadot_parachain::primitives::XcmpMessageFormat
+   * Lookup288: polkadot_parachain::primitives::XcmpMessageFormat
    **/
   PolkadotParachainPrimitivesXcmpMessageFormat: {
     _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals']
   },
   /**
-   * Lookup293: cumulus_pallet_xcmp_queue::OutboundChannelDetails
+   * Lookup291: cumulus_pallet_xcmp_queue::OutboundChannelDetails
    **/
   CumulusPalletXcmpQueueOutboundChannelDetails: {
     recipient: 'u32',
@@ -2218,13 +2198,13 @@
     lastIndex: 'u16'
   },
   /**
-   * Lookup294: cumulus_pallet_xcmp_queue::OutboundState
+   * Lookup292: cumulus_pallet_xcmp_queue::OutboundState
    **/
   CumulusPalletXcmpQueueOutboundState: {
     _enum: ['Ok', 'Suspended']
   },
   /**
-   * Lookup296: cumulus_pallet_xcmp_queue::QueueConfigData
+   * Lookup294: cumulus_pallet_xcmp_queue::QueueConfigData
    **/
   CumulusPalletXcmpQueueQueueConfigData: {
     suspendThreshold: 'u32',
@@ -2235,29 +2215,29 @@
     xcmpMaxIndividualWeight: 'u64'
   },
   /**
-   * Lookup298: cumulus_pallet_xcmp_queue::pallet::Error<T>
+   * Lookup296: cumulus_pallet_xcmp_queue::pallet::Error<T>
    **/
   CumulusPalletXcmpQueueError: {
     _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit']
   },
   /**
-   * Lookup299: pallet_xcm::pallet::Error<T>
+   * Lookup297: pallet_xcm::pallet::Error<T>
    **/
   PalletXcmError: {
     _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed']
   },
   /**
-   * Lookup300: cumulus_pallet_xcm::pallet::Error<T>
+   * Lookup298: cumulus_pallet_xcm::pallet::Error<T>
    **/
   CumulusPalletXcmError: 'Null',
   /**
-   * Lookup301: cumulus_pallet_dmp_queue::ConfigData
+   * Lookup299: cumulus_pallet_dmp_queue::ConfigData
    **/
   CumulusPalletDmpQueueConfigData: {
     maxIndividual: 'u64'
   },
   /**
-   * Lookup302: cumulus_pallet_dmp_queue::PageIndexData
+   * Lookup300: cumulus_pallet_dmp_queue::PageIndexData
    **/
   CumulusPalletDmpQueuePageIndexData: {
     beginUsed: 'u32',
@@ -2265,19 +2245,19 @@
     overweightCount: 'u64'
   },
   /**
-   * Lookup305: cumulus_pallet_dmp_queue::pallet::Error<T>
+   * Lookup303: cumulus_pallet_dmp_queue::pallet::Error<T>
    **/
   CumulusPalletDmpQueueError: {
     _enum: ['Unknown', 'OverLimit']
   },
   /**
-   * Lookup309: pallet_unique::Error<T>
+   * Lookup307: pallet_unique::Error<T>
    **/
   PalletUniqueError: {
     _enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument']
   },
   /**
-   * Lookup310: up_data_structs::Collection<sp_core::crypto::AccountId32>
+   * Lookup308: up_data_structs::Collection<sp_core::crypto::AccountId32>
    **/
   UpDataStructsCollection: {
     owner: 'AccountId32',
@@ -2289,11 +2269,10 @@
     mintMode: 'bool',
     schemaVersion: 'UpDataStructsSchemaVersion',
     sponsorship: 'UpDataStructsSponsorshipState',
-    limits: 'UpDataStructsCollectionLimits',
-    metaUpdatePermission: 'UpDataStructsMetaUpdatePermission'
+    limits: 'UpDataStructsCollectionLimits'
   },
   /**
-   * Lookup311: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>
+   * Lookup309: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>
    **/
   UpDataStructsSponsorshipState: {
     _enum: {
@@ -2303,7 +2282,7 @@
     }
   },
   /**
-   * Lookup312: up_data_structs::Properties
+   * Lookup310: up_data_structs::Properties
    **/
   UpDataStructsProperties: {
     map: 'UpDataStructsPropertiesMapBoundedVec',
@@ -2311,21 +2290,21 @@
     spaceLimit: 'u32'
   },
   /**
-   * Lookup313: up_data_structs::PropertiesMap<frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup311: up_data_structs::PropertiesMap<frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   UpDataStructsPropertiesMapBoundedVec: 'BTreeMap<Bytes, Bytes>',
   /**
-   * Lookup318: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>
+   * Lookup316: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>
    **/
   UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap<Bytes, UpDataStructsPropertyPermission>',
   /**
-   * Lookup324: up_data_structs::CollectionField
+   * Lookup322: up_data_structs::CollectionField
    **/
   UpDataStructsCollectionField: {
     _enum: ['ConstOnChainSchema', 'OffchainSchema']
   },
   /**
-   * Lookup327: up_data_structs::CollectionStats
+   * Lookup325: up_data_structs::CollectionStats
    **/
   UpDataStructsCollectionStats: {
     created: 'u32',
@@ -2333,11 +2312,11 @@
     alive: 'u32'
   },
   /**
-   * Lookup328: PhantomType::up_data_structs<up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>>
+   * Lookup326: PhantomType::up_data_structs<up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>>
    **/
-  PhantomTypeUpDataStructsTokenData: '[Lookup329;0]',
+  PhantomTypeUpDataStructsTokenData: '[Lookup327;0]',
   /**
-   * Lookup329: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup327: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsTokenData: {
     constData: 'Bytes',
@@ -2345,11 +2324,11 @@
     owner: 'Option<PalletEvmAccountBasicCrossAccountIdRepr>'
   },
   /**
-   * Lookup332: PhantomType::up_data_structs<up_data_structs::RpcCollection<sp_core::crypto::AccountId32>>
+   * Lookup330: PhantomType::up_data_structs<up_data_structs::RpcCollection<sp_core::crypto::AccountId32>>
    **/
-  PhantomTypeUpDataStructsRpcCollection: '[Lookup333;0]',
+  PhantomTypeUpDataStructsRpcCollection: '[Lookup331;0]',
   /**
-   * Lookup333: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>
+   * Lookup331: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>
    **/
   UpDataStructsRpcCollection: {
     owner: 'AccountId32',
@@ -2364,16 +2343,15 @@
     sponsorship: 'UpDataStructsSponsorshipState',
     limits: 'UpDataStructsCollectionLimits',
     constOnChainSchema: 'Bytes',
-    metaUpdatePermission: 'UpDataStructsMetaUpdatePermission',
     tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup335: PhantomType::up_data_structs<rmrk_types::CollectionInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>>
+   * Lookup333: PhantomType::up_data_structs<rmrk_types::CollectionInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>>
    **/
-  PhantomTypeUpDataStructsCollectionInfo: '[Lookup336;0]',
+  PhantomTypeUpDataStructsCollectionInfo: '[Lookup334;0]',
   /**
-   * Lookup336: rmrk_types::CollectionInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>
+   * Lookup334: rmrk_types::CollectionInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>
    **/
   RmrkTypesCollectionInfo: {
     issuer: 'AccountId32',
@@ -2383,11 +2361,11 @@
     nftsCount: 'u32'
   },
   /**
-   * Lookup340: PhantomType::up_data_structs<rmrk_types::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, frame_support::storage::bounded_vec::BoundedVec<T, S>>>
+   * Lookup338: PhantomType::up_data_structs<rmrk_types::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, frame_support::storage::bounded_vec::BoundedVec<T, S>>>
    **/
-  PhantomTypeUpDataStructsNftInfo: '[Lookup341;0]',
+  PhantomTypeUpDataStructsNftInfo: '[Lookup339;0]',
   /**
-   * Lookup341: rmrk_types::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup339: rmrk_types::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTypesNftInfo: {
     owner: 'RmrkTypesAccountIdOrCollectionNftTuple',
@@ -2397,7 +2375,7 @@
     pending: 'bool'
   },
   /**
-   * Lookup342: rmrk_types::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>
+   * Lookup340: rmrk_types::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>
    **/
   RmrkTypesAccountIdOrCollectionNftTuple: {
     _enum: {
@@ -2406,18 +2384,18 @@
     }
   },
   /**
-   * Lookup344: rmrk_types::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>
+   * Lookup342: rmrk_types::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>
    **/
   RmrkTypesRoyaltyInfo: {
     recipient: 'AccountId32',
     amount: 'Permill'
   },
   /**
-   * Lookup346: PhantomType::up_data_structs<rmrk_types::ResourceInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>>
+   * Lookup344: PhantomType::up_data_structs<rmrk_types::ResourceInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>>
    **/
-  PhantomTypeUpDataStructsResourceInfo: '[Lookup347;0]',
+  PhantomTypeUpDataStructsResourceInfo: '[Lookup345;0]',
   /**
-   * Lookup347: rmrk_types::ResourceInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup345: rmrk_types::ResourceInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTypesResourceInfo: {
     id: 'Bytes',
@@ -2432,22 +2410,22 @@
     thumb: 'Option<Bytes>'
   },
   /**
-   * Lookup353: PhantomType::up_data_structs<rmrk_types::PropertyInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>>
+   * Lookup351: PhantomType::up_data_structs<rmrk_types::PropertyInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>>
    **/
-  PhantomTypeUpDataStructsPropertyInfo: '[Lookup354;0]',
+  PhantomTypeUpDataStructsPropertyInfo: '[Lookup352;0]',
   /**
-   * Lookup354: rmrk_types::PropertyInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup352: rmrk_types::PropertyInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTypesPropertyInfo: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup358: PhantomType::up_data_structs<rmrk_types::BaseInfo<sp_core::crypto::AccountId32, frame_support::storage::bounded_vec::BoundedVec<T, S>>>
+   * Lookup356: PhantomType::up_data_structs<rmrk_types::BaseInfo<sp_core::crypto::AccountId32, frame_support::storage::bounded_vec::BoundedVec<T, S>>>
    **/
-  PhantomTypeUpDataStructsBaseInfo: '[Lookup359;0]',
+  PhantomTypeUpDataStructsBaseInfo: '[Lookup357;0]',
   /**
-   * Lookup359: rmrk_types::BaseInfo<sp_core::crypto::AccountId32, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup357: rmrk_types::BaseInfo<sp_core::crypto::AccountId32, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTypesBaseInfo: {
     issuer: 'AccountId32',
@@ -2455,11 +2433,11 @@
     symbol: 'Bytes'
   },
   /**
-   * Lookup361: PhantomType::up_data_structs<rmrk_types::PartType<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>>
+   * Lookup359: PhantomType::up_data_structs<rmrk_types::PartType<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>>
    **/
-  PhantomTypeUpDataStructsPartType: '[Lookup362;0]',
+  PhantomTypeUpDataStructsPartType: '[Lookup360;0]',
   /**
-   * Lookup362: rmrk_types::PartType<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup360: rmrk_types::PartType<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTypesPartType: {
     _enum: {
@@ -2468,7 +2446,7 @@
     }
   },
   /**
-   * Lookup364: rmrk_types::FixedPart<frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup362: rmrk_types::FixedPart<frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTypesFixedPart: {
     id: 'u32',
@@ -2476,7 +2454,7 @@
     src: 'Bytes'
   },
   /**
-   * Lookup365: rmrk_types::SlotPart<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup363: rmrk_types::SlotPart<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTypesSlotPart: {
     id: 'u32',
@@ -2485,7 +2463,7 @@
     z: 'u32'
   },
   /**
-   * Lookup366: rmrk_types::EquippableList<frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup364: rmrk_types::EquippableList<frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTypesEquippableList: {
     _enum: {
@@ -2495,11 +2473,11 @@
     }
   },
   /**
-   * Lookup368: PhantomType::up_data_structs<rmrk_types::Theme<frame_support::storage::bounded_vec::BoundedVec<T, S>, BoundedPropertyList>>
+   * Lookup366: PhantomType::up_data_structs<rmrk_types::Theme<frame_support::storage::bounded_vec::BoundedVec<T, S>, BoundedPropertyList>>
    **/
-  PhantomTypeUpDataStructsTheme: '[Lookup369;0]',
+  PhantomTypeUpDataStructsTheme: '[Lookup367;0]',
   /**
-   * Lookup369: rmrk_types::Theme<frame_support::storage::bounded_vec::BoundedVec<T, S>, BoundedPropertyList>
+   * Lookup367: rmrk_types::Theme<frame_support::storage::bounded_vec::BoundedVec<T, S>, BoundedPropertyList>
    **/
   RmrkTypesTheme: {
     name: 'Bytes',
@@ -2507,76 +2485,74 @@
     inherit: 'bool'
   },
   /**
-   * Lookup371: rmrk_types::ThemeProperty<frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup369: rmrk_types::ThemeProperty<frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTypesThemeProperty: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup373: PhantomType::up_data_structs<rmrk_types::NftChild>
+   * Lookup371: PhantomType::up_data_structs<rmrk_types::NftChild>
    **/
-  PhantomTypeUpDataStructsNftChild: '[Lookup374;0]',
+  PhantomTypeUpDataStructsNftChild: '[Lookup372;0]',
   /**
-   * Lookup374: rmrk_types::NftChild
+   * Lookup372: rmrk_types::NftChild
    **/
   RmrkTypesNftChild: {
     collectionId: 'u32',
     nftId: 'u32'
   },
   /**
-   * Lookup376: pallet_common::pallet::Error<T>
+   * Lookup374: pallet_common::pallet::Error<T>
    **/
   PalletCommonError: {
-    _enum: ['CollectionNotFound', 'MustBeTokenOwner', 'NoPermission', 'PublicMintingNotAllowed', 'AddressNotInAllowlist', 'CollectionNameLimitExceeded', 'CollectionDescriptionLimitExceeded', 'CollectionTokenPrefixLimitExceeded', 'TotalCollectionsLimitExceeded', 'TokenVariableDataLimitExceeded', 'CollectionAdminCountExceeded', 'CollectionLimitBoundsExceeded', 'OwnerPermissionsCantBeReverted', 'TransferNotAllowed', 'AccountTokenLimitExceeded', 'CollectionTokenLimitExceeded', 'MetadataFlagFrozen', 'TokenNotFound', 'TokenValueTooLow', 'ApprovedValueTooLow', 'CantApproveMoreThanOwned', 'AddressIsZero', 'UnsupportedOperation', 'NotSufficientFounds', 'NestingIsDisabled', 'OnlyOwnerAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'UnableToReadUnboundedKeys', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey']
+    _enum: ['CollectionNotFound', 'MustBeTokenOwner', 'NoPermission', 'PublicMintingNotAllowed', 'AddressNotInAllowlist', 'CollectionNameLimitExceeded', 'CollectionDescriptionLimitExceeded', 'CollectionTokenPrefixLimitExceeded', 'TotalCollectionsLimitExceeded', 'CollectionAdminCountExceeded', 'CollectionLimitBoundsExceeded', 'OwnerPermissionsCantBeReverted', 'TransferNotAllowed', 'AccountTokenLimitExceeded', 'CollectionTokenLimitExceeded', 'MetadataFlagFrozen', 'TokenNotFound', 'TokenValueTooLow', 'ApprovedValueTooLow', 'CantApproveMoreThanOwned', 'AddressIsZero', 'UnsupportedOperation', 'NotSufficientFounds', 'NestingIsDisabled', 'OnlyOwnerAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'PropertyKeyIsTooLong', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey']
   },
   /**
-   * Lookup378: pallet_fungible::pallet::Error<T>
+   * Lookup376: pallet_fungible::pallet::Error<T>
    **/
   PalletFungibleError: {
     _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed']
   },
   /**
-   * Lookup379: pallet_refungible::ItemData
+   * Lookup377: pallet_refungible::ItemData
    **/
   PalletRefungibleItemData: {
-    constData: 'Bytes',
-    variableData: 'Bytes'
+    constData: 'Bytes'
   },
   /**
-   * Lookup383: pallet_refungible::pallet::Error<T>
+   * Lookup381: pallet_refungible::pallet::Error<T>
    **/
   PalletRefungibleError: {
     _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed']
   },
   /**
-   * Lookup384: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup382: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   PalletNonfungibleItemData: {
     constData: 'Bytes',
-    variableData: 'Bytes',
     owner: 'PalletEvmAccountBasicCrossAccountIdRepr'
   },
   /**
-   * Lookup385: pallet_nonfungible::pallet::Error<T>
+   * Lookup383: pallet_nonfungible::pallet::Error<T>
    **/
   PalletNonfungibleError: {
     _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount']
   },
   /**
-   * Lookup386: pallet_structure::pallet::Error<T>
+   * Lookup384: pallet_structure::pallet::Error<T>
    **/
   PalletStructureError: {
     _enum: ['OuroborosDetected', 'DepthLimit', 'TokenNotFound']
   },
   /**
-   * Lookup389: pallet_evm::pallet::Error<T>
+   * Lookup387: pallet_evm::pallet::Error<T>
    **/
   PalletEvmError: {
     _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce']
   },
   /**
-   * Lookup392: fp_rpc::TransactionStatus
+   * Lookup390: fp_rpc::TransactionStatus
    **/
   FpRpcTransactionStatus: {
     transactionHash: 'H256',
@@ -2588,11 +2564,11 @@
     logsBloom: 'EthbloomBloom'
   },
   /**
-   * Lookup394: ethbloom::Bloom
+   * Lookup392: ethbloom::Bloom
    **/
   EthbloomBloom: '[u8;256]',
   /**
-   * Lookup396: ethereum::receipt::ReceiptV3
+   * Lookup394: ethereum::receipt::ReceiptV3
    **/
   EthereumReceiptReceiptV3: {
     _enum: {
@@ -2602,7 +2578,7 @@
     }
   },
   /**
-   * Lookup397: ethereum::receipt::EIP658ReceiptData
+   * Lookup395: ethereum::receipt::EIP658ReceiptData
    **/
   EthereumReceiptEip658ReceiptData: {
     statusCode: 'u8',
@@ -2611,7 +2587,7 @@
     logs: 'Vec<EthereumLog>'
   },
   /**
-   * Lookup398: ethereum::block::Block<ethereum::transaction::TransactionV2>
+   * Lookup396: ethereum::block::Block<ethereum::transaction::TransactionV2>
    **/
   EthereumBlock: {
     header: 'EthereumHeader',
@@ -2619,7 +2595,7 @@
     ommers: 'Vec<EthereumHeader>'
   },
   /**
-   * Lookup399: ethereum::header::Header
+   * Lookup397: ethereum::header::Header
    **/
   EthereumHeader: {
     parentHash: 'H256',
@@ -2639,41 +2615,41 @@
     nonce: 'EthereumTypesHashH64'
   },
   /**
-   * Lookup400: ethereum_types::hash::H64
+   * Lookup398: ethereum_types::hash::H64
    **/
   EthereumTypesHashH64: '[u8;8]',
   /**
-   * Lookup405: pallet_ethereum::pallet::Error<T>
+   * Lookup403: pallet_ethereum::pallet::Error<T>
    **/
   PalletEthereumError: {
     _enum: ['InvalidSignature', 'PreLogExists']
   },
   /**
-   * Lookup406: pallet_evm_coder_substrate::pallet::Error<T>
+   * Lookup404: pallet_evm_coder_substrate::pallet::Error<T>
    **/
   PalletEvmCoderSubstrateError: {
     _enum: ['OutOfGas', 'OutOfFund']
   },
   /**
-   * Lookup407: pallet_evm_contract_helpers::SponsoringModeT
+   * Lookup405: pallet_evm_contract_helpers::SponsoringModeT
    **/
   PalletEvmContractHelpersSponsoringModeT: {
     _enum: ['Disabled', 'Allowlisted', 'Generous']
   },
   /**
-   * Lookup409: pallet_evm_contract_helpers::pallet::Error<T>
+   * Lookup407: pallet_evm_contract_helpers::pallet::Error<T>
    **/
   PalletEvmContractHelpersError: {
     _enum: ['NoPermission']
   },
   /**
-   * Lookup410: pallet_evm_migration::pallet::Error<T>
+   * Lookup408: pallet_evm_migration::pallet::Error<T>
    **/
   PalletEvmMigrationError: {
     _enum: ['AccountNotEmpty', 'AccountIsNotMigrating']
   },
   /**
-   * Lookup412: sp_runtime::MultiSignature
+   * Lookup410: sp_runtime::MultiSignature
    **/
   SpRuntimeMultiSignature: {
     _enum: {
@@ -2683,43 +2659,43 @@
     }
   },
   /**
-   * Lookup413: sp_core::ed25519::Signature
+   * Lookup411: sp_core::ed25519::Signature
    **/
   SpCoreEd25519Signature: '[u8;64]',
   /**
-   * Lookup415: sp_core::sr25519::Signature
+   * Lookup413: sp_core::sr25519::Signature
    **/
   SpCoreSr25519Signature: '[u8;64]',
   /**
-   * Lookup416: sp_core::ecdsa::Signature
+   * Lookup414: sp_core::ecdsa::Signature
    **/
   SpCoreEcdsaSignature: '[u8;65]',
   /**
-   * Lookup419: frame_system::extensions::check_spec_version::CheckSpecVersion<T>
+   * Lookup417: frame_system::extensions::check_spec_version::CheckSpecVersion<T>
    **/
   FrameSystemExtensionsCheckSpecVersion: 'Null',
   /**
-   * Lookup420: frame_system::extensions::check_genesis::CheckGenesis<T>
+   * Lookup418: frame_system::extensions::check_genesis::CheckGenesis<T>
    **/
   FrameSystemExtensionsCheckGenesis: 'Null',
   /**
-   * Lookup423: frame_system::extensions::check_nonce::CheckNonce<T>
+   * Lookup421: frame_system::extensions::check_nonce::CheckNonce<T>
    **/
   FrameSystemExtensionsCheckNonce: 'Compact<u32>',
   /**
-   * Lookup424: frame_system::extensions::check_weight::CheckWeight<T>
+   * Lookup422: frame_system::extensions::check_weight::CheckWeight<T>
    **/
   FrameSystemExtensionsCheckWeight: 'Null',
   /**
-   * Lookup425: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>
+   * Lookup423: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>
    **/
   PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact<u128>',
   /**
-   * Lookup426: opal_runtime::Runtime
+   * Lookup424: opal_runtime::Runtime
    **/
   OpalRuntimeRuntime: 'Null',
   /**
-   * Lookup427: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>
+   * Lookup425: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>
    **/
   PalletEthereumFakeTransactionFinalizer: 'Null'
 };
modifiedtests/src/interfaces/registry.tsdiffbeforeafterboth
--- a/tests/src/interfaces/registry.ts
+++ b/tests/src/interfaces/registry.ts
@@ -1,7 +1,7 @@
 // Auto-generated via `yarn polkadot-types-from-defs`, do not edit
 /* eslint-disable */
 
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletXcmCall, PalletXcmError, PalletXcmEvent, PhantomTypeUpDataStructsBaseInfo, PhantomTypeUpDataStructsCollectionInfo, PhantomTypeUpDataStructsNftChild, PhantomTypeUpDataStructsNftInfo, PhantomTypeUpDataStructsPartType, PhantomTypeUpDataStructsPropertyInfo, PhantomTypeUpDataStructsResourceInfo, PhantomTypeUpDataStructsRpcCollection, PhantomTypeUpDataStructsTheme, PhantomTypeUpDataStructsTokenData, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTypesAccountIdOrCollectionNftTuple, RmrkTypesBaseInfo, RmrkTypesCollectionInfo, RmrkTypesEquippableList, RmrkTypesFixedPart, RmrkTypesNftChild, RmrkTypesNftInfo, RmrkTypesPartType, RmrkTypesPropertyInfo, RmrkTypesResourceInfo, RmrkTypesRoyaltyInfo, RmrkTypesSlotPart, RmrkTypesTheme, RmrkTypesThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionField, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsMetaUpdatePermission, UpDataStructsNestingRule, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSchemaVersion, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletXcmCall, PalletXcmError, PalletXcmEvent, PhantomTypeUpDataStructsBaseInfo, PhantomTypeUpDataStructsCollectionInfo, PhantomTypeUpDataStructsNftChild, PhantomTypeUpDataStructsNftInfo, PhantomTypeUpDataStructsPartType, PhantomTypeUpDataStructsPropertyInfo, PhantomTypeUpDataStructsResourceInfo, PhantomTypeUpDataStructsRpcCollection, PhantomTypeUpDataStructsTheme, PhantomTypeUpDataStructsTokenData, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTypesAccountIdOrCollectionNftTuple, RmrkTypesBaseInfo, RmrkTypesCollectionInfo, RmrkTypesEquippableList, RmrkTypesFixedPart, RmrkTypesNftChild, RmrkTypesNftInfo, RmrkTypesPartType, RmrkTypesPropertyInfo, RmrkTypesResourceInfo, RmrkTypesRoyaltyInfo, RmrkTypesSlotPart, RmrkTypesTheme, RmrkTypesThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionField, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingRule, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSchemaVersion, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
 
 declare module '@polkadot/types/types/registry' {
   export interface InterfaceTypes {
@@ -183,7 +183,6 @@
     UpDataStructsCreateNftExData: UpDataStructsCreateNftExData;
     UpDataStructsCreateReFungibleData: UpDataStructsCreateReFungibleData;
     UpDataStructsCreateRefungibleExData: UpDataStructsCreateRefungibleExData;
-    UpDataStructsMetaUpdatePermission: UpDataStructsMetaUpdatePermission;
     UpDataStructsNestingRule: UpDataStructsNestingRule;
     UpDataStructsProperties: UpDataStructsProperties;
     UpDataStructsPropertiesMapBoundedVec: UpDataStructsPropertiesMapBoundedVec;
modifiedtests/src/interfaces/rmrk/definitions.tsdiffbeforeafterboth
--- a/tests/src/interfaces/rmrk/definitions.ts
+++ b/tests/src/interfaces/rmrk/definitions.ts
@@ -33,14 +33,14 @@
     types,
     rpc: {
         lastCollectionIdx: fn('Get the latest created collection id', [], 'u32'),
-        collectionById: fn('Get collection by id', [{name: 'id', type: 'u32'}], 'Option<RmrkTraitsCollectionCollectionInfo>'),
+        collectionById: fn('Get collection by id', [{name: 'id', type: 'u32'}], 'Option<RmrkTypesCollectionInfo>'),
         nftById: fn(
             'Get NFT by collection id and NFT id',
             [
                 {name: 'collectionId', type: 'u32'},
                 {name: 'nftId', type: 'u32'},
             ],
-            'Option<RmrkTraitsNftNftInfo>'
+            'Option<RmrkTypesNftInfo>'
         ),
         accountTokens: fn(
             'Get tokens owned by an account in a collection',
@@ -56,12 +56,12 @@
                 {name: 'collectionId', type: 'u32'},
                 {name: 'nftId', type: 'u32'},
             ],
-            'Vec<RmrkTraitsNftNftChild>'
+            'Vec<RmrkTypesNftChild>'
         ),
         collectionProperties: fn(
             'Get collection properties',
             [{name: 'collectionId', type: 'u32'}],
-            'Vec<RmrkTraitsPropertyPropertyInfo>'
+            'Vec<RmrkTypesPropertyInfo>'
         ),
         nftProperties: fn(
             'Get NFT properties',
@@ -69,7 +69,7 @@
                 {name: 'collectionId', type: 'u32'},
                 {name: 'nftId', type: 'u32'}
             ],
-            'Vec<RmrkTraitsPropertyPropertyInfo>'
+            'Vec<RmrkTypesPropertyInfo>'
         ),
         nftResources: fn(
             'Get NFT resources',
@@ -77,7 +77,7 @@
                 {name: 'collectionId', type: 'u32'},
                 {name: 'nftId', type: 'u32'}
             ],
-            'Vec<RmrkTraitsResourceResourceInfo>'
+            'Vec<RmrkTypesResourceInfo>'
         ),
         nftResourcePriorities: fn(
             'Get NFT resource priorities',
@@ -90,12 +90,12 @@
         base: fn(
             'Get base info',
             [{name: 'baseId', type: 'u32'}],
-            'Option<RmrkTraitsBaseBaseInfo>'
+            'Option<RmrkTypesBaseInfo>'
         ),
         baseParts: fn(
             'Get all Base\'s parts',
             [{name: 'baseId', type: 'u32'}],
-            'Vec<RmrkTraitsPartPartType>'
+            'Vec<RmrkTypesPartType>'
         ),
         themeNames: fn(
             'Get Base\'s theme names',
@@ -109,7 +109,7 @@
                 {name: 'themeName', type: 'String'},
                 {name: 'keys', type: 'Option<Vec<String>>'}
             ],
-            'Option<RmrkTraitsTheme>'
+            'Option<RmrkTypesTheme>'
         )
     }
 };
modifiedtests/src/interfaces/rmrk/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/rmrk/types.ts
+++ b/tests/src/interfaces/rmrk/types.ts
@@ -446,9 +446,6 @@
 /** @name FrameSupportPalletId */
 export interface FrameSupportPalletId extends U8aFixed {}
 
-/** @name FrameSupportStorageBoundedBTreeSet */
-export interface FrameSupportStorageBoundedBTreeSet extends BTreeSet<u32> {}
-
 /** @name FrameSupportTokensMiscBalanceStatus */
 export interface FrameSupportTokensMiscBalanceStatus extends Enum {
   readonly isFree: boolean;
@@ -875,7 +872,6 @@
   readonly isCollectionDescriptionLimitExceeded: boolean;
   readonly isCollectionTokenPrefixLimitExceeded: boolean;
   readonly isTotalCollectionsLimitExceeded: boolean;
-  readonly isTokenVariableDataLimitExceeded: boolean;
   readonly isCollectionAdminCountExceeded: boolean;
   readonly isCollectionLimitBoundsExceeded: boolean;
   readonly isOwnerPermissionsCantBeReverted: boolean;
@@ -896,10 +892,10 @@
   readonly isCollectionFieldSizeExceeded: boolean;
   readonly isNoSpaceForProperty: boolean;
   readonly isPropertyLimitReached: boolean;
-  readonly isUnableToReadUnboundedKeys: boolean;
+  readonly isPropertyKeyIsTooLong: boolean;
   readonly isInvalidCharacterInPropertyKey: boolean;
   readonly isEmptyPropertyKey: boolean;
-  readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'TokenVariableDataLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'NestingIsDisabled' | 'OnlyOwnerAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'UnableToReadUnboundedKeys' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey';
+  readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'NestingIsDisabled' | 'OnlyOwnerAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey';
 }
 
 /** @name PalletCommonEvent */
@@ -1115,7 +1111,6 @@
 /** @name PalletNonfungibleItemData */
 export interface PalletNonfungibleItemData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
   readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
 }
 
@@ -1131,7 +1126,6 @@
 /** @name PalletRefungibleItemData */
 export interface PalletRefungibleItemData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
 }
 
 /** @name PalletStructureCall */
@@ -1438,17 +1432,6 @@
     readonly collectionId: u32;
     readonly itemId: u32;
     readonly value: u128;
-  } & Struct;
-  readonly isSetVariableMetaData: boolean;
-  readonly asSetVariableMetaData: {
-    readonly collectionId: u32;
-    readonly itemId: u32;
-    readonly data: Bytes;
-  } & Struct;
-  readonly isSetMetaUpdatePermissionFlag: boolean;
-  readonly asSetMetaUpdatePermissionFlag: {
-    readonly collectionId: u32;
-    readonly value: UpDataStructsMetaUpdatePermission;
   } & Struct;
   readonly isSetSchemaVersion: boolean;
   readonly asSetSchemaVersion: {
@@ -1470,7 +1453,7 @@
     readonly collectionId: u32;
     readonly newLimit: UpDataStructsCollectionLimits;
   } & Struct;
-  readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'SetPublicAccessMode' | 'SetMintPermission' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetVariableMetaData' | 'SetMetaUpdatePermissionFlag' | 'SetSchemaVersion' | 'SetOffchainSchema' | 'SetConstOnChainSchema' | 'SetCollectionLimits';
+  readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'SetPublicAccessMode' | 'SetMintPermission' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetSchemaVersion' | 'SetOffchainSchema' | 'SetConstOnChainSchema' | 'SetCollectionLimits';
 }
 
 /** @name PalletUniqueError */
@@ -1632,34 +1615,34 @@
 }
 
 /** @name PhantomTypeUpDataStructsBaseInfo */
-export interface PhantomTypeUpDataStructsBaseInfo extends Vec<Lookup359> {}
+export interface PhantomTypeUpDataStructsBaseInfo extends Vec<Lookup357> {}
 
 /** @name PhantomTypeUpDataStructsCollectionInfo */
-export interface PhantomTypeUpDataStructsCollectionInfo extends Vec<Lookup336> {}
+export interface PhantomTypeUpDataStructsCollectionInfo extends Vec<Lookup334> {}
 
 /** @name PhantomTypeUpDataStructsNftChild */
-export interface PhantomTypeUpDataStructsNftChild extends Vec<Lookup374> {}
+export interface PhantomTypeUpDataStructsNftChild extends Vec<Lookup372> {}
 
 /** @name PhantomTypeUpDataStructsNftInfo */
-export interface PhantomTypeUpDataStructsNftInfo extends Vec<Lookup341> {}
+export interface PhantomTypeUpDataStructsNftInfo extends Vec<Lookup339> {}
 
 /** @name PhantomTypeUpDataStructsPartType */
-export interface PhantomTypeUpDataStructsPartType extends Vec<Lookup362> {}
+export interface PhantomTypeUpDataStructsPartType extends Vec<Lookup360> {}
 
 /** @name PhantomTypeUpDataStructsPropertyInfo */
-export interface PhantomTypeUpDataStructsPropertyInfo extends Vec<Lookup354> {}
+export interface PhantomTypeUpDataStructsPropertyInfo extends Vec<Lookup352> {}
 
 /** @name PhantomTypeUpDataStructsResourceInfo */
-export interface PhantomTypeUpDataStructsResourceInfo extends Vec<Lookup347> {}
+export interface PhantomTypeUpDataStructsResourceInfo extends Vec<Lookup345> {}
 
 /** @name PhantomTypeUpDataStructsRpcCollection */
-export interface PhantomTypeUpDataStructsRpcCollection extends Vec<Lookup333> {}
+export interface PhantomTypeUpDataStructsRpcCollection extends Vec<Lookup331> {}
 
 /** @name PhantomTypeUpDataStructsTheme */
-export interface PhantomTypeUpDataStructsTheme extends Vec<Lookup369> {}
+export interface PhantomTypeUpDataStructsTheme extends Vec<Lookup367> {}
 
 /** @name PhantomTypeUpDataStructsTokenData */
-export interface PhantomTypeUpDataStructsTokenData extends Vec<Lookup329> {}
+export interface PhantomTypeUpDataStructsTokenData extends Vec<Lookup327> {}
 
 /** @name PolkadotCorePrimitivesInboundDownwardMessage */
 export interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct {
@@ -1963,7 +1946,6 @@
   readonly schemaVersion: UpDataStructsSchemaVersion;
   readonly sponsorship: UpDataStructsSponsorshipState;
   readonly limits: UpDataStructsCollectionLimits;
-  readonly metaUpdatePermission: UpDataStructsMetaUpdatePermission;
 }
 
 /** @name UpDataStructsCollectionField */
@@ -2015,7 +1997,6 @@
   readonly pendingSponsor: Option<AccountId32>;
   readonly limits: Option<UpDataStructsCollectionLimits>;
   readonly constOnChainSchema: Bytes;
-  readonly metaUpdatePermission: Option<UpDataStructsMetaUpdatePermission>;
   readonly tokenPropertyPermissions: Vec<UpDataStructsPropertyKeyPermission>;
   readonly properties: Vec<UpDataStructsProperty>;
 }
@@ -2052,14 +2033,12 @@
 /** @name UpDataStructsCreateNftData */
 export interface UpDataStructsCreateNftData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
   readonly properties: Vec<UpDataStructsProperty>;
 }
 
 /** @name UpDataStructsCreateNftExData */
 export interface UpDataStructsCreateNftExData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
   readonly properties: Vec<UpDataStructsProperty>;
   readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
 }
@@ -2067,31 +2046,21 @@
 /** @name UpDataStructsCreateReFungibleData */
 export interface UpDataStructsCreateReFungibleData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
   readonly pieces: u128;
 }
 
 /** @name UpDataStructsCreateRefungibleExData */
 export interface UpDataStructsCreateRefungibleExData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
   readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
 }
 
-/** @name UpDataStructsMetaUpdatePermission */
-export interface UpDataStructsMetaUpdatePermission extends Enum {
-  readonly isItemOwner: boolean;
-  readonly isAdmin: boolean;
-  readonly isNone: boolean;
-  readonly type: 'ItemOwner' | 'Admin' | 'None';
-}
-
 /** @name UpDataStructsNestingRule */
 export interface UpDataStructsNestingRule extends Enum {
   readonly isDisabled: boolean;
   readonly isOwner: boolean;
   readonly isOwnerRestricted: boolean;
-  readonly asOwnerRestricted: FrameSupportStorageBoundedBTreeSet;
+  readonly asOwnerRestricted: BTreeSet<u32>;
   readonly type: 'Disabled' | 'Owner' | 'OwnerRestricted';
 }
 
@@ -2141,7 +2110,6 @@
   readonly sponsorship: UpDataStructsSponsorshipState;
   readonly limits: UpDataStructsCollectionLimits;
   readonly constOnChainSchema: Bytes;
-  readonly metaUpdatePermission: UpDataStructsMetaUpdatePermission;
   readonly tokenPropertyPermissions: Vec<UpDataStructsPropertyKeyPermission>;
   readonly properties: Vec<UpDataStructsProperty>;
 }
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -1493,17 +1493,6 @@
       readonly itemId: u32;
       readonly value: u128;
     } & Struct;
-    readonly isSetVariableMetaData: boolean;
-    readonly asSetVariableMetaData: {
-      readonly collectionId: u32;
-      readonly itemId: u32;
-      readonly data: Bytes;
-    } & Struct;
-    readonly isSetMetaUpdatePermissionFlag: boolean;
-    readonly asSetMetaUpdatePermissionFlag: {
-      readonly collectionId: u32;
-      readonly value: UpDataStructsMetaUpdatePermission;
-    } & Struct;
     readonly isSetSchemaVersion: boolean;
     readonly asSetSchemaVersion: {
       readonly collectionId: u32;
@@ -1524,7 +1513,7 @@
       readonly collectionId: u32;
       readonly newLimit: UpDataStructsCollectionLimits;
     } & Struct;
-    readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'SetPublicAccessMode' | 'SetMintPermission' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetVariableMetaData' | 'SetMetaUpdatePermissionFlag' | 'SetSchemaVersion' | 'SetOffchainSchema' | 'SetConstOnChainSchema' | 'SetCollectionLimits';
+    readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'SetPublicAccessMode' | 'SetMintPermission' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetSchemaVersion' | 'SetOffchainSchema' | 'SetConstOnChainSchema' | 'SetCollectionLimits';
   }
 
   /** @name UpDataStructsCollectionMode (156) */
@@ -1548,7 +1537,6 @@
     readonly pendingSponsor: Option<AccountId32>;
     readonly limits: Option<UpDataStructsCollectionLimits>;
     readonly constOnChainSchema: Bytes;
-    readonly metaUpdatePermission: Option<UpDataStructsMetaUpdatePermission>;
     readonly tokenPropertyPermissions: Vec<UpDataStructsPropertyKeyPermission>;
     readonly properties: Vec<UpDataStructsProperty>;
   }
@@ -1598,34 +1586,26 @@
     readonly type: 'Disabled' | 'Owner' | 'OwnerRestricted';
   }
 
-  /** @name UpDataStructsMetaUpdatePermission (177) */
-  export interface UpDataStructsMetaUpdatePermission extends Enum {
-    readonly isItemOwner: boolean;
-    readonly isAdmin: boolean;
-    readonly isNone: boolean;
-    readonly type: 'ItemOwner' | 'Admin' | 'None';
-  }
-
-  /** @name UpDataStructsPropertyKeyPermission (179) */
+  /** @name UpDataStructsPropertyKeyPermission (177) */
   export interface UpDataStructsPropertyKeyPermission extends Struct {
     readonly key: Bytes;
     readonly permission: UpDataStructsPropertyPermission;
   }
 
-  /** @name UpDataStructsPropertyPermission (181) */
+  /** @name UpDataStructsPropertyPermission (179) */
   export interface UpDataStructsPropertyPermission extends Struct {
     readonly mutable: bool;
     readonly collectionAdmin: bool;
     readonly tokenOwner: bool;
   }
 
-  /** @name UpDataStructsProperty (184) */
+  /** @name UpDataStructsProperty (182) */
   export interface UpDataStructsProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name PalletEvmAccountBasicCrossAccountIdRepr (186) */
+  /** @name PalletEvmAccountBasicCrossAccountIdRepr (184) */
   export interface PalletEvmAccountBasicCrossAccountIdRepr extends Enum {
     readonly isSubstrate: boolean;
     readonly asSubstrate: AccountId32;
@@ -1634,7 +1614,7 @@
     readonly type: 'Substrate' | 'Ethereum';
   }
 
-  /** @name UpDataStructsCreateItemData (188) */
+  /** @name UpDataStructsCreateItemData (186) */
   export interface UpDataStructsCreateItemData extends Enum {
     readonly isNft: boolean;
     readonly asNft: UpDataStructsCreateNftData;
@@ -1645,26 +1625,24 @@
     readonly type: 'Nft' | 'Fungible' | 'ReFungible';
   }
 
-  /** @name UpDataStructsCreateNftData (189) */
+  /** @name UpDataStructsCreateNftData (187) */
   export interface UpDataStructsCreateNftData extends Struct {
     readonly constData: Bytes;
-    readonly variableData: Bytes;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateFungibleData (191) */
+  /** @name UpDataStructsCreateFungibleData (189) */
   export interface UpDataStructsCreateFungibleData extends Struct {
     readonly value: u128;
   }
 
-  /** @name UpDataStructsCreateReFungibleData (192) */
+  /** @name UpDataStructsCreateReFungibleData (190) */
   export interface UpDataStructsCreateReFungibleData extends Struct {
     readonly constData: Bytes;
-    readonly variableData: Bytes;
     readonly pieces: u128;
   }
 
-  /** @name UpDataStructsCreateItemExData (196) */
+  /** @name UpDataStructsCreateItemExData (194) */
   export interface UpDataStructsCreateItemExData extends Enum {
     readonly isNft: boolean;
     readonly asNft: Vec<UpDataStructsCreateNftExData>;
@@ -1677,28 +1655,26 @@
     readonly type: 'Nft' | 'Fungible' | 'RefungibleMultipleItems' | 'RefungibleMultipleOwners';
   }
 
-  /** @name UpDataStructsCreateNftExData (198) */
+  /** @name UpDataStructsCreateNftExData (196) */
   export interface UpDataStructsCreateNftExData extends Struct {
     readonly constData: Bytes;
-    readonly variableData: Bytes;
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name UpDataStructsCreateRefungibleExData (205) */
+  /** @name UpDataStructsCreateRefungibleExData (203) */
   export interface UpDataStructsCreateRefungibleExData extends Struct {
     readonly constData: Bytes;
-    readonly variableData: Bytes;
     readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
   }
 
-  /** @name PalletTemplateTransactionPaymentCall (207) */
+  /** @name PalletTemplateTransactionPaymentCall (205) */
   export type PalletTemplateTransactionPaymentCall = Null;
 
-  /** @name PalletStructureCall (208) */
+  /** @name PalletStructureCall (206) */
   export type PalletStructureCall = Null;
 
-  /** @name PalletEvmCall (209) */
+  /** @name PalletEvmCall (207) */
   export interface PalletEvmCall extends Enum {
     readonly isWithdraw: boolean;
     readonly asWithdraw: {
@@ -1743,7 +1719,7 @@
     readonly type: 'Withdraw' | 'Call' | 'Create' | 'Create2';
   }
 
-  /** @name PalletEthereumCall (215) */
+  /** @name PalletEthereumCall (213) */
   export interface PalletEthereumCall extends Enum {
     readonly isTransact: boolean;
     readonly asTransact: {
@@ -1752,7 +1728,7 @@
     readonly type: 'Transact';
   }
 
-  /** @name EthereumTransactionTransactionV2 (216) */
+  /** @name EthereumTransactionTransactionV2 (214) */
   export interface EthereumTransactionTransactionV2 extends Enum {
     readonly isLegacy: boolean;
     readonly asLegacy: EthereumTransactionLegacyTransaction;
@@ -1763,7 +1739,7 @@
     readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
   }
 
-  /** @name EthereumTransactionLegacyTransaction (217) */
+  /** @name EthereumTransactionLegacyTransaction (215) */
   export interface EthereumTransactionLegacyTransaction extends Struct {
     readonly nonce: U256;
     readonly gasPrice: U256;
@@ -1774,7 +1750,7 @@
     readonly signature: EthereumTransactionTransactionSignature;
   }
 
-  /** @name EthereumTransactionTransactionAction (218) */
+  /** @name EthereumTransactionTransactionAction (216) */
   export interface EthereumTransactionTransactionAction extends Enum {
     readonly isCall: boolean;
     readonly asCall: H160;
@@ -1782,14 +1758,14 @@
     readonly type: 'Call' | 'Create';
   }
 
-  /** @name EthereumTransactionTransactionSignature (219) */
+  /** @name EthereumTransactionTransactionSignature (217) */
   export interface EthereumTransactionTransactionSignature extends Struct {
     readonly v: u64;
     readonly r: H256;
     readonly s: H256;
   }
 
-  /** @name EthereumTransactionEip2930Transaction (221) */
+  /** @name EthereumTransactionEip2930Transaction (219) */
   export interface EthereumTransactionEip2930Transaction extends Struct {
     readonly chainId: u64;
     readonly nonce: U256;
@@ -1804,13 +1780,13 @@
     readonly s: H256;
   }
 
-  /** @name EthereumTransactionAccessListItem (223) */
+  /** @name EthereumTransactionAccessListItem (221) */
   export interface EthereumTransactionAccessListItem extends Struct {
     readonly address: H160;
     readonly storageKeys: Vec<H256>;
   }
 
-  /** @name EthereumTransactionEip1559Transaction (224) */
+  /** @name EthereumTransactionEip1559Transaction (222) */
   export interface EthereumTransactionEip1559Transaction extends Struct {
     readonly chainId: u64;
     readonly nonce: U256;
@@ -1826,7 +1802,7 @@
     readonly s: H256;
   }
 
-  /** @name PalletEvmMigrationCall (225) */
+  /** @name PalletEvmMigrationCall (223) */
   export interface PalletEvmMigrationCall extends Enum {
     readonly isBegin: boolean;
     readonly asBegin: {
@@ -1845,7 +1821,7 @@
     readonly type: 'Begin' | 'SetData' | 'Finish';
   }
 
-  /** @name PalletSudoEvent (228) */
+  /** @name PalletSudoEvent (226) */
   export interface PalletSudoEvent extends Enum {
     readonly isSudid: boolean;
     readonly asSudid: {
@@ -1862,7 +1838,7 @@
     readonly type: 'Sudid' | 'KeyChanged' | 'SudoAsDone';
   }
 
-  /** @name SpRuntimeDispatchError (230) */
+  /** @name SpRuntimeDispatchError (228) */
   export interface SpRuntimeDispatchError extends Enum {
     readonly isOther: boolean;
     readonly isCannotLookup: boolean;
@@ -1881,13 +1857,13 @@
     readonly type: 'Other' | 'CannotLookup' | 'BadOrigin' | 'Module' | 'ConsumerRemaining' | 'NoProviders' | 'TooManyConsumers' | 'Token' | 'Arithmetic' | 'Transactional';
   }
 
-  /** @name SpRuntimeModuleError (231) */
+  /** @name SpRuntimeModuleError (229) */
   export interface SpRuntimeModuleError extends Struct {
     readonly index: u8;
     readonly error: U8aFixed;
   }
 
-  /** @name SpRuntimeTokenError (232) */
+  /** @name SpRuntimeTokenError (230) */
   export interface SpRuntimeTokenError extends Enum {
     readonly isNoFunds: boolean;
     readonly isWouldDie: boolean;
@@ -1899,7 +1875,7 @@
     readonly type: 'NoFunds' | 'WouldDie' | 'BelowMinimum' | 'CannotCreate' | 'UnknownAsset' | 'Frozen' | 'Unsupported';
   }
 
-  /** @name SpRuntimeArithmeticError (233) */
+  /** @name SpRuntimeArithmeticError (231) */
   export interface SpRuntimeArithmeticError extends Enum {
     readonly isUnderflow: boolean;
     readonly isOverflow: boolean;
@@ -1907,20 +1883,20 @@
     readonly type: 'Underflow' | 'Overflow' | 'DivisionByZero';
   }
 
-  /** @name SpRuntimeTransactionalError (234) */
+  /** @name SpRuntimeTransactionalError (232) */
   export interface SpRuntimeTransactionalError extends Enum {
     readonly isLimitReached: boolean;
     readonly isNoLayer: boolean;
     readonly type: 'LimitReached' | 'NoLayer';
   }
 
-  /** @name PalletSudoError (235) */
+  /** @name PalletSudoError (233) */
   export interface PalletSudoError extends Enum {
     readonly isRequireSudo: boolean;
     readonly type: 'RequireSudo';
   }
 
-  /** @name FrameSystemAccountInfo (236) */
+  /** @name FrameSystemAccountInfo (234) */
   export interface FrameSystemAccountInfo extends Struct {
     readonly nonce: u32;
     readonly consumers: u32;
@@ -1929,19 +1905,19 @@
     readonly data: PalletBalancesAccountData;
   }
 
-  /** @name FrameSupportWeightsPerDispatchClassU64 (237) */
+  /** @name FrameSupportWeightsPerDispatchClassU64 (235) */
   export interface FrameSupportWeightsPerDispatchClassU64 extends Struct {
     readonly normal: u64;
     readonly operational: u64;
     readonly mandatory: u64;
   }
 
-  /** @name SpRuntimeDigest (238) */
+  /** @name SpRuntimeDigest (236) */
   export interface SpRuntimeDigest extends Struct {
     readonly logs: Vec<SpRuntimeDigestDigestItem>;
   }
 
-  /** @name SpRuntimeDigestDigestItem (240) */
+  /** @name SpRuntimeDigestDigestItem (238) */
   export interface SpRuntimeDigestDigestItem extends Enum {
     readonly isOther: boolean;
     readonly asOther: Bytes;
@@ -1955,14 +1931,14 @@
     readonly type: 'Other' | 'Consensus' | 'Seal' | 'PreRuntime' | 'RuntimeEnvironmentUpdated';
   }
 
-  /** @name FrameSystemEventRecord (242) */
+  /** @name FrameSystemEventRecord (240) */
   export interface FrameSystemEventRecord extends Struct {
     readonly phase: FrameSystemPhase;
     readonly event: Event;
     readonly topics: Vec<H256>;
   }
 
-  /** @name FrameSystemEvent (244) */
+  /** @name FrameSystemEvent (242) */
   export interface FrameSystemEvent extends Enum {
     readonly isExtrinsicSuccess: boolean;
     readonly asExtrinsicSuccess: {
@@ -1990,14 +1966,14 @@
     readonly type: 'ExtrinsicSuccess' | 'ExtrinsicFailed' | 'CodeUpdated' | 'NewAccount' | 'KilledAccount' | 'Remarked';
   }
 
-  /** @name FrameSupportWeightsDispatchInfo (245) */
+  /** @name FrameSupportWeightsDispatchInfo (243) */
   export interface FrameSupportWeightsDispatchInfo extends Struct {
     readonly weight: u64;
     readonly class: FrameSupportWeightsDispatchClass;
     readonly paysFee: FrameSupportWeightsPays;
   }
 
-  /** @name FrameSupportWeightsDispatchClass (246) */
+  /** @name FrameSupportWeightsDispatchClass (244) */
   export interface FrameSupportWeightsDispatchClass extends Enum {
     readonly isNormal: boolean;
     readonly isOperational: boolean;
@@ -2005,14 +1981,14 @@
     readonly type: 'Normal' | 'Operational' | 'Mandatory';
   }
 
-  /** @name FrameSupportWeightsPays (247) */
+  /** @name FrameSupportWeightsPays (245) */
   export interface FrameSupportWeightsPays extends Enum {
     readonly isYes: boolean;
     readonly isNo: boolean;
     readonly type: 'Yes' | 'No';
   }
 
-  /** @name OrmlVestingModuleEvent (248) */
+  /** @name OrmlVestingModuleEvent (246) */
   export interface OrmlVestingModuleEvent extends Enum {
     readonly isVestingScheduleAdded: boolean;
     readonly asVestingScheduleAdded: {
@@ -2032,7 +2008,7 @@
     readonly type: 'VestingScheduleAdded' | 'Claimed' | 'VestingSchedulesUpdated';
   }
 
-  /** @name CumulusPalletXcmpQueueEvent (249) */
+  /** @name CumulusPalletXcmpQueueEvent (247) */
   export interface CumulusPalletXcmpQueueEvent extends Enum {
     readonly isSuccess: boolean;
     readonly asSuccess: Option<H256>;
@@ -2053,7 +2029,7 @@
     readonly type: 'Success' | 'Fail' | 'BadVersion' | 'BadFormat' | 'UpwardMessageSent' | 'XcmpMessageSent' | 'OverweightEnqueued' | 'OverweightServiced';
   }
 
-  /** @name PalletXcmEvent (250) */
+  /** @name PalletXcmEvent (248) */
   export interface PalletXcmEvent extends Enum {
     readonly isAttempted: boolean;
     readonly asAttempted: XcmV2TraitsOutcome;
@@ -2090,7 +2066,7 @@
     readonly type: 'Attempted' | 'Sent' | 'UnexpectedResponse' | 'ResponseReady' | 'Notified' | 'NotifyOverweight' | 'NotifyDispatchError' | 'NotifyDecodeFailed' | 'InvalidResponder' | 'InvalidResponderVersion' | 'ResponseTaken' | 'AssetsTrapped' | 'VersionChangeNotified' | 'SupportedVersionChanged' | 'NotifyTargetSendFail' | 'NotifyTargetMigrationFail';
   }
 
-  /** @name XcmV2TraitsOutcome (251) */
+  /** @name XcmV2TraitsOutcome (249) */
   export interface XcmV2TraitsOutcome extends Enum {
     readonly isComplete: boolean;
     readonly asComplete: u64;
@@ -2101,7 +2077,7 @@
     readonly type: 'Complete' | 'Incomplete' | 'Error';
   }
 
-  /** @name CumulusPalletXcmEvent (253) */
+  /** @name CumulusPalletXcmEvent (251) */
   export interface CumulusPalletXcmEvent extends Enum {
     readonly isInvalidFormat: boolean;
     readonly asInvalidFormat: U8aFixed;
@@ -2112,7 +2088,7 @@
     readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward';
   }
 
-  /** @name CumulusPalletDmpQueueEvent (254) */
+  /** @name CumulusPalletDmpQueueEvent (252) */
   export interface CumulusPalletDmpQueueEvent extends Enum {
     readonly isInvalidFormat: boolean;
     readonly asInvalidFormat: U8aFixed;
@@ -2129,7 +2105,7 @@
     readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward' | 'WeightExhausted' | 'OverweightEnqueued' | 'OverweightServiced';
   }
 
-  /** @name PalletUniqueRawEvent (255) */
+  /** @name PalletUniqueRawEvent (253) */
   export interface PalletUniqueRawEvent extends Enum {
     readonly isCollectionSponsorRemoved: boolean;
     readonly asCollectionSponsorRemoved: u32;
@@ -2162,7 +2138,7 @@
     readonly type: 'CollectionSponsorRemoved' | 'CollectionAdminAdded' | 'CollectionOwnedChanged' | 'CollectionSponsorSet' | 'ConstOnChainSchemaSet' | 'SponsorshipConfirmed' | 'CollectionAdminRemoved' | 'AllowListAddressRemoved' | 'AllowListAddressAdded' | 'CollectionLimitSet' | 'MintPermissionSet' | 'OffchainSchemaSet' | 'PublicAccessModeSet' | 'SchemaVersionSet';
   }
 
-  /** @name PalletCommonEvent (256) */
+  /** @name PalletCommonEvent (254) */
   export interface PalletCommonEvent extends Enum {
     readonly isCollectionCreated: boolean;
     readonly asCollectionCreated: ITuple<[u32, u8, AccountId32]>;
@@ -2189,14 +2165,14 @@
     readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet';
   }
 
-  /** @name PalletStructureEvent (257) */
+  /** @name PalletStructureEvent (255) */
   export interface PalletStructureEvent extends Enum {
     readonly isExecuted: boolean;
     readonly asExecuted: Result<Null, SpRuntimeDispatchError>;
     readonly type: 'Executed';
   }
 
-  /** @name PalletEvmEvent (258) */
+  /** @name PalletEvmEvent (256) */
   export interface PalletEvmEvent extends Enum {
     readonly isLog: boolean;
     readonly asLog: EthereumLog;
@@ -2215,21 +2191,21 @@
     readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed' | 'BalanceDeposit' | 'BalanceWithdraw';
   }
 
-  /** @name EthereumLog (259) */
+  /** @name EthereumLog (257) */
   export interface EthereumLog extends Struct {
     readonly address: H160;
     readonly topics: Vec<H256>;
     readonly data: Bytes;
   }
 
-  /** @name PalletEthereumEvent (260) */
+  /** @name PalletEthereumEvent (258) */
   export interface PalletEthereumEvent extends Enum {
     readonly isExecuted: boolean;
     readonly asExecuted: ITuple<[H160, H160, H256, EvmCoreErrorExitReason]>;
     readonly type: 'Executed';
   }
 
-  /** @name EvmCoreErrorExitReason (261) */
+  /** @name EvmCoreErrorExitReason (259) */
   export interface EvmCoreErrorExitReason extends Enum {
     readonly isSucceed: boolean;
     readonly asSucceed: EvmCoreErrorExitSucceed;
@@ -2242,7 +2218,7 @@
     readonly type: 'Succeed' | 'Error' | 'Revert' | 'Fatal';
   }
 
-  /** @name EvmCoreErrorExitSucceed (262) */
+  /** @name EvmCoreErrorExitSucceed (260) */
   export interface EvmCoreErrorExitSucceed extends Enum {
     readonly isStopped: boolean;
     readonly isReturned: boolean;
@@ -2250,7 +2226,7 @@
     readonly type: 'Stopped' | 'Returned' | 'Suicided';
   }
 
-  /** @name EvmCoreErrorExitError (263) */
+  /** @name EvmCoreErrorExitError (261) */
   export interface EvmCoreErrorExitError extends Enum {
     readonly isStackUnderflow: boolean;
     readonly isStackOverflow: boolean;
@@ -2271,13 +2247,13 @@
     readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode';
   }
 
-  /** @name EvmCoreErrorExitRevert (266) */
+  /** @name EvmCoreErrorExitRevert (264) */
   export interface EvmCoreErrorExitRevert extends Enum {
     readonly isReverted: boolean;
     readonly type: 'Reverted';
   }
 
-  /** @name EvmCoreErrorExitFatal (267) */
+  /** @name EvmCoreErrorExitFatal (265) */
   export interface EvmCoreErrorExitFatal extends Enum {
     readonly isNotSupported: boolean;
     readonly isUnhandledInterrupt: boolean;
@@ -2288,7 +2264,7 @@
     readonly type: 'NotSupported' | 'UnhandledInterrupt' | 'CallErrorAsFatal' | 'Other';
   }
 
-  /** @name FrameSystemPhase (268) */
+  /** @name FrameSystemPhase (266) */
   export interface FrameSystemPhase extends Enum {
     readonly isApplyExtrinsic: boolean;
     readonly asApplyExtrinsic: u32;
@@ -2297,27 +2273,27 @@
     readonly type: 'ApplyExtrinsic' | 'Finalization' | 'Initialization';
   }
 
-  /** @name FrameSystemLastRuntimeUpgradeInfo (270) */
+  /** @name FrameSystemLastRuntimeUpgradeInfo (268) */
   export interface FrameSystemLastRuntimeUpgradeInfo extends Struct {
     readonly specVersion: Compact<u32>;
     readonly specName: Text;
   }
 
-  /** @name FrameSystemLimitsBlockWeights (271) */
+  /** @name FrameSystemLimitsBlockWeights (269) */
   export interface FrameSystemLimitsBlockWeights extends Struct {
     readonly baseBlock: u64;
     readonly maxBlock: u64;
     readonly perClass: FrameSupportWeightsPerDispatchClassWeightsPerClass;
   }
 
-  /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (272) */
+  /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (270) */
   export interface FrameSupportWeightsPerDispatchClassWeightsPerClass extends Struct {
     readonly normal: FrameSystemLimitsWeightsPerClass;
     readonly operational: FrameSystemLimitsWeightsPerClass;
     readonly mandatory: FrameSystemLimitsWeightsPerClass;
   }
 
-  /** @name FrameSystemLimitsWeightsPerClass (273) */
+  /** @name FrameSystemLimitsWeightsPerClass (271) */
   export interface FrameSystemLimitsWeightsPerClass extends Struct {
     readonly baseExtrinsic: u64;
     readonly maxExtrinsic: Option<u64>;
@@ -2325,25 +2301,25 @@
     readonly reserved: Option<u64>;
   }
 
-  /** @name FrameSystemLimitsBlockLength (275) */
+  /** @name FrameSystemLimitsBlockLength (273) */
   export interface FrameSystemLimitsBlockLength extends Struct {
     readonly max: FrameSupportWeightsPerDispatchClassU32;
   }
 
-  /** @name FrameSupportWeightsPerDispatchClassU32 (276) */
+  /** @name FrameSupportWeightsPerDispatchClassU32 (274) */
   export interface FrameSupportWeightsPerDispatchClassU32 extends Struct {
     readonly normal: u32;
     readonly operational: u32;
     readonly mandatory: u32;
   }
 
-  /** @name FrameSupportWeightsRuntimeDbWeight (277) */
+  /** @name FrameSupportWeightsRuntimeDbWeight (275) */
   export interface FrameSupportWeightsRuntimeDbWeight extends Struct {
     readonly read: u64;
     readonly write: u64;
   }
 
-  /** @name SpVersionRuntimeVersion (278) */
+  /** @name SpVersionRuntimeVersion (276) */
   export interface SpVersionRuntimeVersion extends Struct {
     readonly specName: Text;
     readonly implName: Text;
@@ -2355,7 +2331,7 @@
     readonly stateVersion: u8;
   }
 
-  /** @name FrameSystemError (282) */
+  /** @name FrameSystemError (280) */
   export interface FrameSystemError extends Enum {
     readonly isInvalidSpecName: boolean;
     readonly isSpecVersionNeedsToIncrease: boolean;
@@ -2366,7 +2342,7 @@
     readonly type: 'InvalidSpecName' | 'SpecVersionNeedsToIncrease' | 'FailedToExtractRuntimeVersion' | 'NonDefaultComposite' | 'NonZeroRefCount' | 'CallFiltered';
   }
 
-  /** @name OrmlVestingModuleError (284) */
+  /** @name OrmlVestingModuleError (282) */
   export interface OrmlVestingModuleError extends Enum {
     readonly isZeroVestingPeriod: boolean;
     readonly isZeroVestingPeriodCount: boolean;
@@ -2377,21 +2353,21 @@
     readonly type: 'ZeroVestingPeriod' | 'ZeroVestingPeriodCount' | 'InsufficientBalanceToLock' | 'TooManyVestingSchedules' | 'AmountLow' | 'MaxVestingSchedulesExceeded';
   }
 
-  /** @name CumulusPalletXcmpQueueInboundChannelDetails (286) */
+  /** @name CumulusPalletXcmpQueueInboundChannelDetails (284) */
   export interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct {
     readonly sender: u32;
     readonly state: CumulusPalletXcmpQueueInboundState;
     readonly messageMetadata: Vec<ITuple<[u32, PolkadotParachainPrimitivesXcmpMessageFormat]>>;
   }
 
-  /** @name CumulusPalletXcmpQueueInboundState (287) */
+  /** @name CumulusPalletXcmpQueueInboundState (285) */
   export interface CumulusPalletXcmpQueueInboundState extends Enum {
     readonly isOk: boolean;
     readonly isSuspended: boolean;
     readonly type: 'Ok' | 'Suspended';
   }
 
-  /** @name PolkadotParachainPrimitivesXcmpMessageFormat (290) */
+  /** @name PolkadotParachainPrimitivesXcmpMessageFormat (288) */
   export interface PolkadotParachainPrimitivesXcmpMessageFormat extends Enum {
     readonly isConcatenatedVersionedXcm: boolean;
     readonly isConcatenatedEncodedBlob: boolean;
@@ -2399,7 +2375,7 @@
     readonly type: 'ConcatenatedVersionedXcm' | 'ConcatenatedEncodedBlob' | 'Signals';
   }
 
-  /** @name CumulusPalletXcmpQueueOutboundChannelDetails (293) */
+  /** @name CumulusPalletXcmpQueueOutboundChannelDetails (291) */
   export interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct {
     readonly recipient: u32;
     readonly state: CumulusPalletXcmpQueueOutboundState;
@@ -2408,14 +2384,14 @@
     readonly lastIndex: u16;
   }
 
-  /** @name CumulusPalletXcmpQueueOutboundState (294) */
+  /** @name CumulusPalletXcmpQueueOutboundState (292) */
   export interface CumulusPalletXcmpQueueOutboundState extends Enum {
     readonly isOk: boolean;
     readonly isSuspended: boolean;
     readonly type: 'Ok' | 'Suspended';
   }
 
-  /** @name CumulusPalletXcmpQueueQueueConfigData (296) */
+  /** @name CumulusPalletXcmpQueueQueueConfigData (294) */
   export interface CumulusPalletXcmpQueueQueueConfigData extends Struct {
     readonly suspendThreshold: u32;
     readonly dropThreshold: u32;
@@ -2425,7 +2401,7 @@
     readonly xcmpMaxIndividualWeight: u64;
   }
 
-  /** @name CumulusPalletXcmpQueueError (298) */
+  /** @name CumulusPalletXcmpQueueError (296) */
   export interface CumulusPalletXcmpQueueError extends Enum {
     readonly isFailedToSend: boolean;
     readonly isBadXcmOrigin: boolean;
@@ -2435,7 +2411,7 @@
     readonly type: 'FailedToSend' | 'BadXcmOrigin' | 'BadXcm' | 'BadOverweightIndex' | 'WeightOverLimit';
   }
 
-  /** @name PalletXcmError (299) */
+  /** @name PalletXcmError (297) */
   export interface PalletXcmError extends Enum {
     readonly isUnreachable: boolean;
     readonly isSendFailure: boolean;
@@ -2453,29 +2429,29 @@
     readonly type: 'Unreachable' | 'SendFailure' | 'Filtered' | 'UnweighableMessage' | 'DestinationNotInvertible' | 'Empty' | 'CannotReanchor' | 'TooManyAssets' | 'InvalidOrigin' | 'BadVersion' | 'BadLocation' | 'NoSubscription' | 'AlreadySubscribed';
   }
 
-  /** @name CumulusPalletXcmError (300) */
+  /** @name CumulusPalletXcmError (298) */
   export type CumulusPalletXcmError = Null;
 
-  /** @name CumulusPalletDmpQueueConfigData (301) */
+  /** @name CumulusPalletDmpQueueConfigData (299) */
   export interface CumulusPalletDmpQueueConfigData extends Struct {
     readonly maxIndividual: u64;
   }
 
-  /** @name CumulusPalletDmpQueuePageIndexData (302) */
+  /** @name CumulusPalletDmpQueuePageIndexData (300) */
   export interface CumulusPalletDmpQueuePageIndexData extends Struct {
     readonly beginUsed: u32;
     readonly endUsed: u32;
     readonly overweightCount: u64;
   }
 
-  /** @name CumulusPalletDmpQueueError (305) */
+  /** @name CumulusPalletDmpQueueError (303) */
   export interface CumulusPalletDmpQueueError extends Enum {
     readonly isUnknown: boolean;
     readonly isOverLimit: boolean;
     readonly type: 'Unknown' | 'OverLimit';
   }
 
-  /** @name PalletUniqueError (309) */
+  /** @name PalletUniqueError (307) */
   export interface PalletUniqueError extends Enum {
     readonly isCollectionDecimalPointLimitExceeded: boolean;
     readonly isConfirmUnsetSponsorFail: boolean;
@@ -2483,7 +2459,7 @@
     readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument';
   }
 
-  /** @name UpDataStructsCollection (310) */
+  /** @name UpDataStructsCollection (308) */
   export interface UpDataStructsCollection extends Struct {
     readonly owner: AccountId32;
     readonly mode: UpDataStructsCollectionMode;
@@ -2495,10 +2471,9 @@
     readonly schemaVersion: UpDataStructsSchemaVersion;
     readonly sponsorship: UpDataStructsSponsorshipState;
     readonly limits: UpDataStructsCollectionLimits;
-    readonly metaUpdatePermission: UpDataStructsMetaUpdatePermission;
   }
 
-  /** @name UpDataStructsSponsorshipState (311) */
+  /** @name UpDataStructsSponsorshipState (309) */
   export interface UpDataStructsSponsorshipState extends Enum {
     readonly isDisabled: boolean;
     readonly isUnconfirmed: boolean;
@@ -2508,47 +2483,47 @@
     readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
   }
 
-  /** @name UpDataStructsProperties (312) */
+  /** @name UpDataStructsProperties (310) */
   export interface UpDataStructsProperties extends Struct {
     readonly map: UpDataStructsPropertiesMapBoundedVec;
     readonly consumedSpace: u32;
     readonly spaceLimit: u32;
   }
 
-  /** @name UpDataStructsPropertiesMapBoundedVec (313) */
+  /** @name UpDataStructsPropertiesMapBoundedVec (311) */
   export interface UpDataStructsPropertiesMapBoundedVec extends BTreeMap<Bytes, Bytes> {}
 
-  /** @name UpDataStructsPropertiesMapPropertyPermission (318) */
+  /** @name UpDataStructsPropertiesMapPropertyPermission (316) */
   export interface UpDataStructsPropertiesMapPropertyPermission extends BTreeMap<Bytes, UpDataStructsPropertyPermission> {}
 
-  /** @name UpDataStructsCollectionField (324) */
+  /** @name UpDataStructsCollectionField (322) */
   export interface UpDataStructsCollectionField extends Enum {
     readonly isConstOnChainSchema: boolean;
     readonly isOffchainSchema: boolean;
     readonly type: 'ConstOnChainSchema' | 'OffchainSchema';
   }
 
-  /** @name UpDataStructsCollectionStats (327) */
+  /** @name UpDataStructsCollectionStats (325) */
   export interface UpDataStructsCollectionStats extends Struct {
     readonly created: u32;
     readonly destroyed: u32;
     readonly alive: u32;
   }
 
-  /** @name PhantomTypeUpDataStructsTokenData (328) */
+  /** @name PhantomTypeUpDataStructsTokenData (326) */
   export interface PhantomTypeUpDataStructsTokenData extends Vec<UpDataStructsTokenData> {}
 
-  /** @name UpDataStructsTokenData (329) */
+  /** @name UpDataStructsTokenData (327) */
   export interface UpDataStructsTokenData extends Struct {
     readonly constData: Bytes;
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: Option<PalletEvmAccountBasicCrossAccountIdRepr>;
   }
 
-  /** @name PhantomTypeUpDataStructsRpcCollection (332) */
+  /** @name PhantomTypeUpDataStructsRpcCollection (330) */
   export interface PhantomTypeUpDataStructsRpcCollection extends Vec<UpDataStructsRpcCollection> {}
 
-  /** @name UpDataStructsRpcCollection (333) */
+  /** @name UpDataStructsRpcCollection (331) */
   export interface UpDataStructsRpcCollection extends Struct {
     readonly owner: AccountId32;
     readonly mode: UpDataStructsCollectionMode;
@@ -2562,15 +2537,14 @@
     readonly sponsorship: UpDataStructsSponsorshipState;
     readonly limits: UpDataStructsCollectionLimits;
     readonly constOnChainSchema: Bytes;
-    readonly metaUpdatePermission: UpDataStructsMetaUpdatePermission;
     readonly tokenPropertyPermissions: Vec<UpDataStructsPropertyKeyPermission>;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name PhantomTypeUpDataStructsCollectionInfo (335) */
+  /** @name PhantomTypeUpDataStructsCollectionInfo (333) */
   export interface PhantomTypeUpDataStructsCollectionInfo extends Vec<RmrkTypesCollectionInfo> {}
 
-  /** @name RmrkTypesCollectionInfo (336) */
+  /** @name RmrkTypesCollectionInfo (334) */
   export interface RmrkTypesCollectionInfo extends Struct {
     readonly issuer: AccountId32;
     readonly metadata: Bytes;
@@ -2579,10 +2553,10 @@
     readonly nftsCount: u32;
   }
 
-  /** @name PhantomTypeUpDataStructsNftInfo (340) */
+  /** @name PhantomTypeUpDataStructsNftInfo (338) */
   export interface PhantomTypeUpDataStructsNftInfo extends Vec<RmrkTypesNftInfo> {}
 
-  /** @name RmrkTypesNftInfo (341) */
+  /** @name RmrkTypesNftInfo (339) */
   export interface RmrkTypesNftInfo extends Struct {
     readonly owner: RmrkTypesAccountIdOrCollectionNftTuple;
     readonly royalty: Option<RmrkTypesRoyaltyInfo>;
@@ -2591,7 +2565,7 @@
     readonly pending: bool;
   }
 
-  /** @name RmrkTypesAccountIdOrCollectionNftTuple (342) */
+  /** @name RmrkTypesAccountIdOrCollectionNftTuple (340) */
   export interface RmrkTypesAccountIdOrCollectionNftTuple extends Enum {
     readonly isAccountId: boolean;
     readonly asAccountId: AccountId32;
@@ -2600,16 +2574,16 @@
     readonly type: 'AccountId' | 'CollectionAndNftTuple';
   }
 
-  /** @name RmrkTypesRoyaltyInfo (344) */
+  /** @name RmrkTypesRoyaltyInfo (342) */
   export interface RmrkTypesRoyaltyInfo extends Struct {
     readonly recipient: AccountId32;
     readonly amount: Permill;
   }
 
-  /** @name PhantomTypeUpDataStructsResourceInfo (346) */
+  /** @name PhantomTypeUpDataStructsResourceInfo (344) */
   export interface PhantomTypeUpDataStructsResourceInfo extends Vec<RmrkTypesResourceInfo> {}
 
-  /** @name RmrkTypesResourceInfo (347) */
+  /** @name RmrkTypesResourceInfo (345) */
   export interface RmrkTypesResourceInfo extends Struct {
     readonly id: Bytes;
     readonly pending: bool;
@@ -2623,29 +2597,29 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name PhantomTypeUpDataStructsPropertyInfo (353) */
+  /** @name PhantomTypeUpDataStructsPropertyInfo (351) */
   export interface PhantomTypeUpDataStructsPropertyInfo extends Vec<RmrkTypesPropertyInfo> {}
 
-  /** @name RmrkTypesPropertyInfo (354) */
+  /** @name RmrkTypesPropertyInfo (352) */
   export interface RmrkTypesPropertyInfo extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name PhantomTypeUpDataStructsBaseInfo (358) */
+  /** @name PhantomTypeUpDataStructsBaseInfo (356) */
   export interface PhantomTypeUpDataStructsBaseInfo extends Vec<RmrkTypesBaseInfo> {}
 
-  /** @name RmrkTypesBaseInfo (359) */
+  /** @name RmrkTypesBaseInfo (357) */
   export interface RmrkTypesBaseInfo extends Struct {
     readonly issuer: AccountId32;
     readonly baseType: Bytes;
     readonly symbol: Bytes;
   }
 
-  /** @name PhantomTypeUpDataStructsPartType (361) */
+  /** @name PhantomTypeUpDataStructsPartType (359) */
   export interface PhantomTypeUpDataStructsPartType extends Vec<RmrkTypesPartType> {}
 
-  /** @name RmrkTypesPartType (362) */
+  /** @name RmrkTypesPartType (360) */
   export interface RmrkTypesPartType extends Enum {
     readonly isFixedPart: boolean;
     readonly asFixedPart: RmrkTypesFixedPart;
@@ -2654,14 +2628,14 @@
     readonly type: 'FixedPart' | 'SlotPart';
   }
 
-  /** @name RmrkTypesFixedPart (364) */
+  /** @name RmrkTypesFixedPart (362) */
   export interface RmrkTypesFixedPart extends Struct {
     readonly id: u32;
     readonly z: u32;
     readonly src: Bytes;
   }
 
-  /** @name RmrkTypesSlotPart (365) */
+  /** @name RmrkTypesSlotPart (363) */
   export interface RmrkTypesSlotPart extends Struct {
     readonly id: u32;
     readonly equippable: RmrkTypesEquippableList;
@@ -2669,7 +2643,7 @@
     readonly z: u32;
   }
 
-  /** @name RmrkTypesEquippableList (366) */
+  /** @name RmrkTypesEquippableList (364) */
   export interface RmrkTypesEquippableList extends Enum {
     readonly isAll: boolean;
     readonly isEmpty: boolean;
@@ -2678,32 +2652,32 @@
     readonly type: 'All' | 'Empty' | 'Custom';
   }
 
-  /** @name PhantomTypeUpDataStructsTheme (368) */
+  /** @name PhantomTypeUpDataStructsTheme (366) */
   export interface PhantomTypeUpDataStructsTheme extends Vec<RmrkTypesTheme> {}
 
-  /** @name RmrkTypesTheme (369) */
+  /** @name RmrkTypesTheme (367) */
   export interface RmrkTypesTheme extends Struct {
     readonly name: Bytes;
     readonly properties: Vec<RmrkTypesThemeProperty>;
     readonly inherit: bool;
   }
 
-  /** @name RmrkTypesThemeProperty (371) */
+  /** @name RmrkTypesThemeProperty (369) */
   export interface RmrkTypesThemeProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name PhantomTypeUpDataStructsNftChild (373) */
+  /** @name PhantomTypeUpDataStructsNftChild (371) */
   export interface PhantomTypeUpDataStructsNftChild extends Vec<RmrkTypesNftChild> {}
 
-  /** @name RmrkTypesNftChild (374) */
+  /** @name RmrkTypesNftChild (372) */
   export interface RmrkTypesNftChild extends Struct {
     readonly collectionId: u32;
     readonly nftId: u32;
   }
 
-  /** @name PalletCommonError (376) */
+  /** @name PalletCommonError (374) */
   export interface PalletCommonError extends Enum {
     readonly isCollectionNotFound: boolean;
     readonly isMustBeTokenOwner: boolean;
@@ -2714,7 +2688,6 @@
     readonly isCollectionDescriptionLimitExceeded: boolean;
     readonly isCollectionTokenPrefixLimitExceeded: boolean;
     readonly isTotalCollectionsLimitExceeded: boolean;
-    readonly isTokenVariableDataLimitExceeded: boolean;
     readonly isCollectionAdminCountExceeded: boolean;
     readonly isCollectionLimitBoundsExceeded: boolean;
     readonly isOwnerPermissionsCantBeReverted: boolean;
@@ -2735,13 +2708,13 @@
     readonly isCollectionFieldSizeExceeded: boolean;
     readonly isNoSpaceForProperty: boolean;
     readonly isPropertyLimitReached: boolean;
-    readonly isUnableToReadUnboundedKeys: boolean;
+    readonly isPropertyKeyIsTooLong: boolean;
     readonly isInvalidCharacterInPropertyKey: boolean;
     readonly isEmptyPropertyKey: boolean;
-    readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'TokenVariableDataLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'NestingIsDisabled' | 'OnlyOwnerAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'UnableToReadUnboundedKeys' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey';
+    readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'NestingIsDisabled' | 'OnlyOwnerAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey';
   }
 
-  /** @name PalletFungibleError (378) */
+  /** @name PalletFungibleError (376) */
   export interface PalletFungibleError extends Enum {
     readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isFungibleItemsHaveNoId: boolean;
@@ -2751,13 +2724,12 @@
     readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
   }
 
-  /** @name PalletRefungibleItemData (379) */
+  /** @name PalletRefungibleItemData (377) */
   export interface PalletRefungibleItemData extends Struct {
     readonly constData: Bytes;
-    readonly variableData: Bytes;
   }
 
-  /** @name PalletRefungibleError (383) */
+  /** @name PalletRefungibleError (381) */
   export interface PalletRefungibleError extends Enum {
     readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isWrongRefungiblePieces: boolean;
@@ -2766,21 +2738,20 @@
     readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
   }
 
-  /** @name PalletNonfungibleItemData (384) */
+  /** @name PalletNonfungibleItemData (382) */
   export interface PalletNonfungibleItemData extends Struct {
     readonly constData: Bytes;
-    readonly variableData: Bytes;
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name PalletNonfungibleError (385) */
+  /** @name PalletNonfungibleError (383) */
   export interface PalletNonfungibleError extends Enum {
     readonly isNotNonfungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isNonfungibleItemsHaveNoAmount: boolean;
     readonly type: 'NotNonfungibleDataUsedToMintFungibleCollectionToken' | 'NonfungibleItemsHaveNoAmount';
   }
 
-  /** @name PalletStructureError (386) */
+  /** @name PalletStructureError (384) */
   export interface PalletStructureError extends Enum {
     readonly isOuroborosDetected: boolean;
     readonly isDepthLimit: boolean;
@@ -2788,7 +2759,7 @@
     readonly type: 'OuroborosDetected' | 'DepthLimit' | 'TokenNotFound';
   }
 
-  /** @name PalletEvmError (389) */
+  /** @name PalletEvmError (387) */
   export interface PalletEvmError extends Enum {
     readonly isBalanceLow: boolean;
     readonly isFeeOverflow: boolean;
@@ -2799,7 +2770,7 @@
     readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce';
   }
 
-  /** @name FpRpcTransactionStatus (392) */
+  /** @name FpRpcTransactionStatus (390) */
   export interface FpRpcTransactionStatus extends Struct {
     readonly transactionHash: H256;
     readonly transactionIndex: u32;
@@ -2810,10 +2781,10 @@
     readonly logsBloom: EthbloomBloom;
   }
 
-  /** @name EthbloomBloom (394) */
+  /** @name EthbloomBloom (392) */
   export interface EthbloomBloom extends U8aFixed {}
 
-  /** @name EthereumReceiptReceiptV3 (396) */
+  /** @name EthereumReceiptReceiptV3 (394) */
   export interface EthereumReceiptReceiptV3 extends Enum {
     readonly isLegacy: boolean;
     readonly asLegacy: EthereumReceiptEip658ReceiptData;
@@ -2824,7 +2795,7 @@
     readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
   }
 
-  /** @name EthereumReceiptEip658ReceiptData (397) */
+  /** @name EthereumReceiptEip658ReceiptData (395) */
   export interface EthereumReceiptEip658ReceiptData extends Struct {
     readonly statusCode: u8;
     readonly usedGas: U256;
@@ -2832,14 +2803,14 @@
     readonly logs: Vec<EthereumLog>;
   }
 
-  /** @name EthereumBlock (398) */
+  /** @name EthereumBlock (396) */
   export interface EthereumBlock extends Struct {
     readonly header: EthereumHeader;
     readonly transactions: Vec<EthereumTransactionTransactionV2>;
     readonly ommers: Vec<EthereumHeader>;
   }
 
-  /** @name EthereumHeader (399) */
+  /** @name EthereumHeader (397) */
   export interface EthereumHeader extends Struct {
     readonly parentHash: H256;
     readonly ommersHash: H256;
@@ -2858,24 +2829,24 @@
     readonly nonce: EthereumTypesHashH64;
   }
 
-  /** @name EthereumTypesHashH64 (400) */
+  /** @name EthereumTypesHashH64 (398) */
   export interface EthereumTypesHashH64 extends U8aFixed {}
 
-  /** @name PalletEthereumError (405) */
+  /** @name PalletEthereumError (403) */
   export interface PalletEthereumError extends Enum {
     readonly isInvalidSignature: boolean;
     readonly isPreLogExists: boolean;
     readonly type: 'InvalidSignature' | 'PreLogExists';
   }
 
-  /** @name PalletEvmCoderSubstrateError (406) */
+  /** @name PalletEvmCoderSubstrateError (404) */
   export interface PalletEvmCoderSubstrateError extends Enum {
     readonly isOutOfGas: boolean;
     readonly isOutOfFund: boolean;
     readonly type: 'OutOfGas' | 'OutOfFund';
   }
 
-  /** @name PalletEvmContractHelpersSponsoringModeT (407) */
+  /** @name PalletEvmContractHelpersSponsoringModeT (405) */
   export interface PalletEvmContractHelpersSponsoringModeT extends Enum {
     readonly isDisabled: boolean;
     readonly isAllowlisted: boolean;
@@ -2883,20 +2854,20 @@
     readonly type: 'Disabled' | 'Allowlisted' | 'Generous';
   }
 
-  /** @name PalletEvmContractHelpersError (409) */
+  /** @name PalletEvmContractHelpersError (407) */
   export interface PalletEvmContractHelpersError extends Enum {
     readonly isNoPermission: boolean;
     readonly type: 'NoPermission';
   }
 
-  /** @name PalletEvmMigrationError (410) */
+  /** @name PalletEvmMigrationError (408) */
   export interface PalletEvmMigrationError extends Enum {
     readonly isAccountNotEmpty: boolean;
     readonly isAccountIsNotMigrating: boolean;
     readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating';
   }
 
-  /** @name SpRuntimeMultiSignature (412) */
+  /** @name SpRuntimeMultiSignature (410) */
   export interface SpRuntimeMultiSignature extends Enum {
     readonly isEd25519: boolean;
     readonly asEd25519: SpCoreEd25519Signature;
@@ -2907,34 +2878,34 @@
     readonly type: 'Ed25519' | 'Sr25519' | 'Ecdsa';
   }
 
-  /** @name SpCoreEd25519Signature (413) */
+  /** @name SpCoreEd25519Signature (411) */
   export interface SpCoreEd25519Signature extends U8aFixed {}
 
-  /** @name SpCoreSr25519Signature (415) */
+  /** @name SpCoreSr25519Signature (413) */
   export interface SpCoreSr25519Signature extends U8aFixed {}
 
-  /** @name SpCoreEcdsaSignature (416) */
+  /** @name SpCoreEcdsaSignature (414) */
   export interface SpCoreEcdsaSignature extends U8aFixed {}
 
-  /** @name FrameSystemExtensionsCheckSpecVersion (419) */
+  /** @name FrameSystemExtensionsCheckSpecVersion (417) */
   export type FrameSystemExtensionsCheckSpecVersion = Null;
 
-  /** @name FrameSystemExtensionsCheckGenesis (420) */
+  /** @name FrameSystemExtensionsCheckGenesis (418) */
   export type FrameSystemExtensionsCheckGenesis = Null;
 
-  /** @name FrameSystemExtensionsCheckNonce (423) */
+  /** @name FrameSystemExtensionsCheckNonce (421) */
   export interface FrameSystemExtensionsCheckNonce extends Compact<u32> {}
 
-  /** @name FrameSystemExtensionsCheckWeight (424) */
+  /** @name FrameSystemExtensionsCheckWeight (422) */
   export type FrameSystemExtensionsCheckWeight = Null;
 
-  /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (425) */
+  /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (423) */
   export interface PalletTemplateTransactionPaymentChargeTransactionPayment extends Compact<u128> {}
 
-  /** @name OpalRuntimeRuntime (426) */
+  /** @name OpalRuntimeRuntime (424) */
   export type OpalRuntimeRuntime = Null;
 
-  /** @name PalletEthereumFakeTransactionFinalizer (427) */
+  /** @name PalletEthereumFakeTransactionFinalizer (425) */
   export type PalletEthereumFakeTransactionFinalizer = Null;
 
 } // declare module
modifiedtests/src/interfaces/unique/definitions.tsdiffbeforeafterboth
--- a/tests/src/interfaces/unique/definitions.ts
+++ b/tests/src/interfaces/unique/definitions.ts
@@ -26,7 +26,7 @@
 
 const collectionParam = {name: 'collection', type: 'u32'};
 const tokenParam = {name: 'tokenId', type: 'u32'};
-const propertyKeysParam = {name: 'propertyKeys', type: 'Vec<String>'};
+const propertyKeysParam = {name: 'propertyKeys', type: 'Vec<String>', isOptional: true};
 const crossAccountParam = (name = 'account') => ({name, type: CROSS_ACCOUNT_ID_TYPE});
 const atParam = {name: 'at', type: 'Hash', isOptional: true};
 
modifiedtests/src/interfaces/unique/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/unique/types.ts
+++ b/tests/src/interfaces/unique/types.ts
@@ -446,9 +446,6 @@
 /** @name FrameSupportPalletId */
 export interface FrameSupportPalletId extends U8aFixed {}
 
-/** @name FrameSupportStorageBoundedBTreeSet */
-export interface FrameSupportStorageBoundedBTreeSet extends BTreeSet<u32> {}
-
 /** @name FrameSupportTokensMiscBalanceStatus */
 export interface FrameSupportTokensMiscBalanceStatus extends Enum {
   readonly isFree: boolean;
@@ -875,7 +872,6 @@
   readonly isCollectionDescriptionLimitExceeded: boolean;
   readonly isCollectionTokenPrefixLimitExceeded: boolean;
   readonly isTotalCollectionsLimitExceeded: boolean;
-  readonly isTokenVariableDataLimitExceeded: boolean;
   readonly isCollectionAdminCountExceeded: boolean;
   readonly isCollectionLimitBoundsExceeded: boolean;
   readonly isOwnerPermissionsCantBeReverted: boolean;
@@ -896,10 +892,10 @@
   readonly isCollectionFieldSizeExceeded: boolean;
   readonly isNoSpaceForProperty: boolean;
   readonly isPropertyLimitReached: boolean;
-  readonly isUnableToReadUnboundedKeys: boolean;
+  readonly isPropertyKeyIsTooLong: boolean;
   readonly isInvalidCharacterInPropertyKey: boolean;
   readonly isEmptyPropertyKey: boolean;
-  readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'TokenVariableDataLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'NestingIsDisabled' | 'OnlyOwnerAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'UnableToReadUnboundedKeys' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey';
+  readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'NestingIsDisabled' | 'OnlyOwnerAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey';
 }
 
 /** @name PalletCommonEvent */
@@ -1115,7 +1111,6 @@
 /** @name PalletNonfungibleItemData */
 export interface PalletNonfungibleItemData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
   readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
 }
 
@@ -1131,7 +1126,6 @@
 /** @name PalletRefungibleItemData */
 export interface PalletRefungibleItemData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
 }
 
 /** @name PalletStructureCall */
@@ -1438,17 +1432,6 @@
     readonly collectionId: u32;
     readonly itemId: u32;
     readonly value: u128;
-  } & Struct;
-  readonly isSetVariableMetaData: boolean;
-  readonly asSetVariableMetaData: {
-    readonly collectionId: u32;
-    readonly itemId: u32;
-    readonly data: Bytes;
-  } & Struct;
-  readonly isSetMetaUpdatePermissionFlag: boolean;
-  readonly asSetMetaUpdatePermissionFlag: {
-    readonly collectionId: u32;
-    readonly value: UpDataStructsMetaUpdatePermission;
   } & Struct;
   readonly isSetSchemaVersion: boolean;
   readonly asSetSchemaVersion: {
@@ -1470,7 +1453,7 @@
     readonly collectionId: u32;
     readonly newLimit: UpDataStructsCollectionLimits;
   } & Struct;
-  readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'SetPublicAccessMode' | 'SetMintPermission' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetVariableMetaData' | 'SetMetaUpdatePermissionFlag' | 'SetSchemaVersion' | 'SetOffchainSchema' | 'SetConstOnChainSchema' | 'SetCollectionLimits';
+  readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'SetPublicAccessMode' | 'SetMintPermission' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetSchemaVersion' | 'SetOffchainSchema' | 'SetConstOnChainSchema' | 'SetCollectionLimits';
 }
 
 /** @name PalletUniqueError */
@@ -1632,34 +1615,34 @@
 }
 
 /** @name PhantomTypeUpDataStructsBaseInfo */
-export interface PhantomTypeUpDataStructsBaseInfo extends Vec<Lookup359> {}
+export interface PhantomTypeUpDataStructsBaseInfo extends Vec<Lookup357> {}
 
 /** @name PhantomTypeUpDataStructsCollectionInfo */
-export interface PhantomTypeUpDataStructsCollectionInfo extends Vec<Lookup336> {}
+export interface PhantomTypeUpDataStructsCollectionInfo extends Vec<Lookup334> {}
 
 /** @name PhantomTypeUpDataStructsNftChild */
-export interface PhantomTypeUpDataStructsNftChild extends Vec<Lookup374> {}
+export interface PhantomTypeUpDataStructsNftChild extends Vec<Lookup372> {}
 
 /** @name PhantomTypeUpDataStructsNftInfo */
-export interface PhantomTypeUpDataStructsNftInfo extends Vec<Lookup341> {}
+export interface PhantomTypeUpDataStructsNftInfo extends Vec<Lookup339> {}
 
 /** @name PhantomTypeUpDataStructsPartType */
-export interface PhantomTypeUpDataStructsPartType extends Vec<Lookup362> {}
+export interface PhantomTypeUpDataStructsPartType extends Vec<Lookup360> {}
 
 /** @name PhantomTypeUpDataStructsPropertyInfo */
-export interface PhantomTypeUpDataStructsPropertyInfo extends Vec<Lookup354> {}
+export interface PhantomTypeUpDataStructsPropertyInfo extends Vec<Lookup352> {}
 
 /** @name PhantomTypeUpDataStructsResourceInfo */
-export interface PhantomTypeUpDataStructsResourceInfo extends Vec<Lookup347> {}
+export interface PhantomTypeUpDataStructsResourceInfo extends Vec<Lookup345> {}
 
 /** @name PhantomTypeUpDataStructsRpcCollection */
-export interface PhantomTypeUpDataStructsRpcCollection extends Vec<Lookup333> {}
+export interface PhantomTypeUpDataStructsRpcCollection extends Vec<Lookup331> {}
 
 /** @name PhantomTypeUpDataStructsTheme */
-export interface PhantomTypeUpDataStructsTheme extends Vec<Lookup369> {}
+export interface PhantomTypeUpDataStructsTheme extends Vec<Lookup367> {}
 
 /** @name PhantomTypeUpDataStructsTokenData */
-export interface PhantomTypeUpDataStructsTokenData extends Vec<Lookup329> {}
+export interface PhantomTypeUpDataStructsTokenData extends Vec<Lookup327> {}
 
 /** @name PolkadotCorePrimitivesInboundDownwardMessage */
 export interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct {
@@ -1963,7 +1946,6 @@
   readonly schemaVersion: UpDataStructsSchemaVersion;
   readonly sponsorship: UpDataStructsSponsorshipState;
   readonly limits: UpDataStructsCollectionLimits;
-  readonly metaUpdatePermission: UpDataStructsMetaUpdatePermission;
 }
 
 /** @name UpDataStructsCollectionField */
@@ -2015,7 +1997,6 @@
   readonly pendingSponsor: Option<AccountId32>;
   readonly limits: Option<UpDataStructsCollectionLimits>;
   readonly constOnChainSchema: Bytes;
-  readonly metaUpdatePermission: Option<UpDataStructsMetaUpdatePermission>;
   readonly tokenPropertyPermissions: Vec<UpDataStructsPropertyKeyPermission>;
   readonly properties: Vec<UpDataStructsProperty>;
 }
@@ -2052,14 +2033,12 @@
 /** @name UpDataStructsCreateNftData */
 export interface UpDataStructsCreateNftData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
   readonly properties: Vec<UpDataStructsProperty>;
 }
 
 /** @name UpDataStructsCreateNftExData */
 export interface UpDataStructsCreateNftExData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
   readonly properties: Vec<UpDataStructsProperty>;
   readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
 }
@@ -2067,31 +2046,21 @@
 /** @name UpDataStructsCreateReFungibleData */
 export interface UpDataStructsCreateReFungibleData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
   readonly pieces: u128;
 }
 
 /** @name UpDataStructsCreateRefungibleExData */
 export interface UpDataStructsCreateRefungibleExData extends Struct {
   readonly constData: Bytes;
-  readonly variableData: Bytes;
   readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
 }
 
-/** @name UpDataStructsMetaUpdatePermission */
-export interface UpDataStructsMetaUpdatePermission extends Enum {
-  readonly isItemOwner: boolean;
-  readonly isAdmin: boolean;
-  readonly isNone: boolean;
-  readonly type: 'ItemOwner' | 'Admin' | 'None';
-}
-
 /** @name UpDataStructsNestingRule */
 export interface UpDataStructsNestingRule extends Enum {
   readonly isDisabled: boolean;
   readonly isOwner: boolean;
   readonly isOwnerRestricted: boolean;
-  readonly asOwnerRestricted: FrameSupportStorageBoundedBTreeSet;
+  readonly asOwnerRestricted: BTreeSet<u32>;
   readonly type: 'Disabled' | 'Owner' | 'OwnerRestricted';
 }
 
@@ -2141,7 +2110,6 @@
   readonly sponsorship: UpDataStructsSponsorshipState;
   readonly limits: UpDataStructsCollectionLimits;
   readonly constOnChainSchema: Bytes;
-  readonly metaUpdatePermission: UpDataStructsMetaUpdatePermission;
   readonly tokenPropertyPermissions: Vec<UpDataStructsPropertyKeyPermission>;
   readonly properties: Vec<UpDataStructsProperty>;
 }
deletedtests/src/metadataUpdate.test.tsdiffbeforeafterboth
--- a/tests/src/metadataUpdate.test.ts
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import privateKey from './substrate/privateKey';
-import usingApi from './substrate/substrate-api';
-import {
-  createItemExpectSuccess,
-  createCollectionExpectSuccess,
-  enablePublicMintingExpectSuccess,
-  enableAllowListExpectSuccess,
-  setMetadataUpdatePermissionFlagExpectSuccess,
-  setVariableMetaDataExpectSuccess,
-  setMintPermissionExpectSuccess,
-  addToAllowListExpectSuccess,
-  addCollectionAdminExpectSuccess,
-  setVariableMetaDataExpectFailure,
-  setMetadataUpdatePermissionFlagExpectFailure,
-} from './util/helpers';
-
-chai.use(chaiAsPromised);
-
-describe('Metadata update permissions with ItemOwner flag', () => {
-  it('ItemOwner can set variable metadata with ItemOwner permission flag', async () => {
-    await usingApi(async () => {
-      const alice = privateKey('//Alice');
-
-      const data = [1, 2, 254, 255];
-
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, nftCollectionId, 'ItemOwner');
-
-      await setVariableMetaDataExpectSuccess(alice, nftCollectionId, newNftTokenId, data);
-    });
-  });
-
-  it('Admin can\'n set variable metadata with ItemOwner permission flag', async () => {
-    await usingApi(async () => {
-      const alice = privateKey('//Alice');
-      const bob = privateKey('//Bob');
-
-      const data = [1, 2, 254, 255];
-
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, nftCollectionId, 'ItemOwner');
-
-      await setMintPermissionExpectSuccess(alice, nftCollectionId, true);
-      await addToAllowListExpectSuccess(alice, nftCollectionId, bob.address);
-      await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);
-
-      await setVariableMetaDataExpectFailure(bob, nftCollectionId, newNftTokenId, data);
-    });
-  });
-
-  it('User can\'n set variable metadata with ItemOwner permission flag', async () => {
-    await usingApi(async () => {
-      const alice = privateKey('//Alice');
-      const bob = privateKey('//Bob');
-
-      const data = [1, 2, 254, 255];
-
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, nftCollectionId, 'ItemOwner');
-
-      await setMintPermissionExpectSuccess(alice, nftCollectionId, true);
-      await setVariableMetaDataExpectFailure(bob, nftCollectionId, newNftTokenId, data);
-    });
-  });
-});
-
-describe('Metadata update permissions with Admin flag', () => {
-  it('Admin can set variable metadata with Admin permission flag', async () => {
-    await usingApi(async () => {
-      const alice = privateKey('//Alice');
-      const bob = privateKey('//Bob');
-
-      const data = [1, 2, 254, 255];
-
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, nftCollectionId, 'Admin');
-
-      await setMintPermissionExpectSuccess(alice, nftCollectionId, true);
-      await addToAllowListExpectSuccess(alice, nftCollectionId, bob.address);
-      await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);
-
-      await setVariableMetaDataExpectSuccess(bob, nftCollectionId, newNftTokenId, data);
-    });
-  });
-
-  it('User can\'n can set variable metadata with Admin permission flag', async () => {
-    await usingApi(async () => {
-      const alice = privateKey('//Alice');
-      const bob = privateKey('//Bob');
-
-      const data = [1, 2, 254, 255];
-
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, nftCollectionId, 'Admin');
-
-      await setMintPermissionExpectSuccess(alice, nftCollectionId, true);
-      await addToAllowListExpectSuccess(alice, nftCollectionId, bob.address);
-      await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);
-
-      await setVariableMetaDataExpectSuccess(bob, nftCollectionId, newNftTokenId, data);
-    });
-  });
-
-  it('ItemOwner can\'n can set variable metadata with Admin permission flag', async () => {
-    await usingApi(async () => {
-      const alice = privateKey('//Alice');
-      const bob = privateKey('//Bob');
-
-      const data = [1, 2, 254, 255];
-
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      await enablePublicMintingExpectSuccess(alice, nftCollectionId);
-      await addToAllowListExpectSuccess(alice, nftCollectionId, bob.address);
-      await enableAllowListExpectSuccess(alice, nftCollectionId);
-      const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, nftCollectionId, 'Admin');
-
-      await setVariableMetaDataExpectFailure(bob, nftCollectionId, newNftTokenId, data);
-    });
-  });
-});
-
-describe('Metadata update permissions with None flag', () => {
-  it('Nobody can set variable metadata with None flag (Regular)', async () => {
-    await usingApi(async () => {
-      const alice = privateKey('//Alice');
-      const bob = privateKey('//Bob');
-
-      const data = [1, 2, 254, 255];
-
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, nftCollectionId, 'None');
-
-      await setVariableMetaDataExpectFailure(bob, nftCollectionId, newNftTokenId, data);
-    });
-  });
-
-  it('Nobody can set variable metadata with None flag (Admin)', async () => {
-    await usingApi(async () => {
-      const alice = privateKey('//Alice');
-      const bob = privateKey('//Bob');
-
-      const data = [1, 2, 254, 255];
-
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, nftCollectionId, 'None');
-
-      await setMintPermissionExpectSuccess(alice, nftCollectionId, true);
-      await addToAllowListExpectSuccess(alice, nftCollectionId, bob.address);
-      await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);
-
-      await setVariableMetaDataExpectFailure(bob, nftCollectionId, newNftTokenId, data);
-    });
-  });
-
-  it('Nobody can set variable metadata with None flag (ItemOwner)', async () => {
-    await usingApi(async () => {
-      const alice = privateKey('//Alice');
-
-      const data = [1, 2, 254, 255];
-
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, nftCollectionId, 'None');
-
-      await setVariableMetaDataExpectFailure(alice, nftCollectionId, newNftTokenId, data);
-    });
-  });
-
-  it('Nobody can set variable metadata flag after freeze', async () => {
-    await usingApi(async () => {
-      const alice = privateKey('//Alice');
-
-      // nft
-      const nftCollectionId = await createCollectionExpectSuccess();
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, nftCollectionId, 'None');
-      await setMetadataUpdatePermissionFlagExpectFailure(alice, nftCollectionId, 'Admin');
-    });
-  });
-});
modifiedtests/src/nesting/migration-check.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/migration-check.test.ts
+++ b/tests/src/nesting/migration-check.test.ts
@@ -37,7 +37,6 @@
           accountTokenOwnershipLimit: 3,
         },
         constOnChainSchema: '0x333333',
-        metaUpdatePermission: 'Admin',
       });
       const events = await submitTransactionAsync(alice, tx);
       const result = getCreateCollectionResult(events);
modifiedtests/src/nesting/rules-smoke.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/rules-smoke.test.ts
+++ b/tests/src/nesting/rules-smoke.test.ts
@@ -23,7 +23,7 @@
       nestTarget = {Ethereum: tokenIdToAddress(collection, token)};
     });
   });
-  
+
   it('called for fungible', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'Fungible',decimalPoints:0}});
@@ -39,7 +39,7 @@
   it('called for nonfungible', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await expect(executeTransaction(api, alice, api.tx.unique.createItem(collection, nestTarget, {NFT: {ConstData: [], VariableData: {}}})))
+      await expect(executeTransaction(api, alice, api.tx.unique.createItem(collection, nestTarget, {NFT: {ConstData: []}})))
         .to.be.rejectedWith(/^common\.SourceCollectionIsNotAllowedToNest$/);
 
       const token = await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
@@ -51,7 +51,7 @@
   it('called for refungible', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
-      await expect(executeTransaction(api, alice, api.tx.unique.createItem(collection, nestTarget, {ReFungible: {ConstData: [], VariableData: {}}})))
+      await expect(executeTransaction(api, alice, api.tx.unique.createItem(collection, nestTarget, {ReFungible: {ConstData: []}})))
         .to.be.rejectedWith(/^common\.SourceCollectionIsNotAllowedToNest$/);
 
       const token = await createItemExpectSuccess(alice, collection, 'ReFungible', {Substrate: alice.address});
@@ -60,4 +60,3 @@
     });
   });
 });
-  
\ No newline at end of file
deletedtests/src/setVariableMetaData.test.tsdiffbeforeafterboth
--- a/tests/src/setVariableMetaData.test.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-import {IKeyringPair} from '@polkadot/types/types';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import privateKey from './substrate/privateKey';
-import usingApi from './substrate/substrate-api';
-import {
-  burnItemExpectSuccess,
-  createCollectionExpectSuccess,
-  createItemExpectSuccess,
-  destroyCollectionExpectSuccess,
-  findNotExistingCollection,
-  setVariableMetaDataExpectFailure,
-  setVariableMetaDataExpectSuccess,
-  addCollectionAdminExpectSuccess,
-  setMetadataUpdatePermissionFlagExpectSuccess,
-  getVariableMetadata,
-} from './util/helpers';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
-describe('Integration Test setVariableMetaData', () => {
-  const data = [1, 2, 254, 255];
-
-  let alice: IKeyringPair;
-  let collectionId: number;
-  let tokenId: number;
-  before(async () => {
-    await usingApi(async () => {
-      alice = privateKey('//Alice');
-      collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
-    });
-  });
-
-  it('execute setVariableMetaData', async () => {
-    await setVariableMetaDataExpectSuccess(alice, collectionId, tokenId, data);
-  });
-
-  it('verify data was set', async () => {
-    await usingApi(async api => {
-      expect(await getVariableMetadata(api, collectionId, tokenId)).to.deep.equal(data);
-    });
-  });
-});
-
-describe('Integration Test collection admin setVariableMetaData', () => {
-  const data = [1, 2, 254, 255];
-
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-  let collectionId: number;
-  let tokenId: number;
-  before(async () => {
-    await usingApi(async () => {
-      alice = privateKey('//Alice');
-      bob = privateKey('//Bob');
-      collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
-      await setMetadataUpdatePermissionFlagExpectSuccess(alice, collectionId, 'Admin');
-      await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
-    });
-  });
-
-  it('execute setVariableMetaData', async () => {
-    await setVariableMetaDataExpectSuccess(bob, collectionId, tokenId, data);
-  });
-
-  it('verify data was set', async () => {
-    await usingApi(async api => {
-      expect(await getVariableMetadata(api, collectionId, tokenId)).to.deep.equal(data);
-    });
-  });
-});
-
-describe('Negative Integration Test setVariableMetaData', () => {
-  const data = [1];
-
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-
-  let validCollectionId: number;
-  let validTokenId: number;
-
-  before(async () => {
-    await usingApi(async () => {
-      alice = privateKey('//Alice');
-      bob = privateKey('//Bob');
-
-      validCollectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      validTokenId = await createItemExpectSuccess(alice, validCollectionId, 'NFT');
-    });
-  });
-
-  it('fails on not existing collection id', async () => {
-    await usingApi(async api => {
-      const nonExistingCollectionId = await findNotExistingCollection(api);
-      await setVariableMetaDataExpectFailure(alice, nonExistingCollectionId, 1, data);
-    });
-  });
-  it('fails on removed collection id', async () => {
-    const removedCollectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-    const removedCollectionTokenId = await createItemExpectSuccess(alice, removedCollectionId, 'NFT');
-
-    await destroyCollectionExpectSuccess(removedCollectionId);
-    await setVariableMetaDataExpectFailure(alice, removedCollectionId, removedCollectionTokenId, data);
-  });
-  it('fails on removed token', async () => {
-    const removedTokenCollectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-    const removedTokenId = await createItemExpectSuccess(alice, removedTokenCollectionId, 'NFT');
-    await burnItemExpectSuccess(alice, removedTokenCollectionId, removedTokenId);
-
-    await setVariableMetaDataExpectFailure(alice, removedTokenCollectionId, removedTokenId, data);
-  });
-  it('fails on not existing token', async () => {
-    const nonExistingTokenId = validTokenId + 1;
-
-    await setVariableMetaDataExpectFailure(alice, validCollectionId, nonExistingTokenId, data);
-  });
-  it('fails on too long data', async () => {
-    const tooLongData = new Array(4097).fill(0xff);
-
-    await setVariableMetaDataExpectFailure(alice, validCollectionId, validTokenId, tooLongData);
-  });
-  it('fails on fungible token', async () => {
-    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
-    const fungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
-
-    await setVariableMetaDataExpectFailure(alice, fungibleCollectionId, fungibleTokenId, data);
-  });
-  it('fails on bad sender', async () => {
-    await setVariableMetaDataExpectFailure(bob, validCollectionId, validTokenId, data);
-  });
-});
deletedtests/src/setVariableMetadataSponsoringRateLimit.test.tsdiffbeforeafterboth
--- a/tests/src/setVariableMetadataSponsoringRateLimit.test.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-import {IKeyringPair} from '@polkadot/types/types';
-import {expect} from 'chai';
-import privateKey from './substrate/privateKey';
-import usingApi from './substrate/substrate-api';
-import {
-  confirmSponsorshipExpectSuccess,
-  createCollectionExpectSuccess,
-  createItemExpectSuccess,
-  findUnusedAddress,
-  getDetailedCollectionInfo,
-  setCollectionLimitsExpectSuccess,
-  setCollectionSponsorExpectSuccess,
-  setVariableMetaDataExpectFailure,
-  setVariableMetaDataExpectSuccess,
-} from './util/helpers';
-
-describe('Integration Test setVariableMetadataSponsoringRateLimit', () => {
-  let alice: IKeyringPair;
-  let userWithNoBalance: IKeyringPair;
-
-  before(async () => {
-    await usingApi(async (api) => {
-      alice = privateKey('//Alice');
-      userWithNoBalance = await findUnusedAddress(api);
-    });
-  });
-
-  it('sponsored setVariableMetaData can be called twice with pause for free', async () => {
-    const collectionId = await createCollectionExpectSuccess();
-    await setCollectionSponsorExpectSuccess(collectionId, alice.address);
-    await confirmSponsorshipExpectSuccess(collectionId);
-    await setCollectionLimitsExpectSuccess(alice, collectionId, {
-      sponsoredDataRateLimit: {Blocks: 0},
-    });
-
-    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', userWithNoBalance.address);
-    await setVariableMetaDataExpectSuccess(userWithNoBalance, collectionId, itemId, [1, 2, 3]);
-    await setVariableMetaDataExpectSuccess(userWithNoBalance, collectionId, itemId, [1, 2, 3]);
-  });
-
-  it('sponsored setVariableMetaData can\'t be called twice without pause for free', async () => {
-    const collectionId = await createCollectionExpectSuccess();
-    await setCollectionSponsorExpectSuccess(collectionId, alice.address);
-    await confirmSponsorshipExpectSuccess(collectionId);
-    await setCollectionLimitsExpectSuccess(alice, collectionId, {
-      sponsoredDataRateLimit: {Blocks: 10},
-    });
-
-    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', userWithNoBalance.address);
-    await setVariableMetaDataExpectSuccess(userWithNoBalance, collectionId, itemId, [1, 2, 3]);
-    await setVariableMetaDataExpectFailure(userWithNoBalance, collectionId, itemId, [1, 2, 3]);
-  });
-
-  it('sponsored setVariableMetaData can\'t be called for free with variable metadata above collection limits', async () => {
-    const collectionId = await createCollectionExpectSuccess();
-    await setCollectionSponsorExpectSuccess(collectionId, alice.address);
-    await confirmSponsorshipExpectSuccess(collectionId);
-    await setCollectionLimitsExpectSuccess(alice, collectionId, {
-      sponsoredDataRateLimit: {Blocks: 0},
-      sponsoredDataSize: 1,
-    });
-    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', userWithNoBalance.address);
-
-    await setVariableMetaDataExpectSuccess(userWithNoBalance, collectionId, itemId, [1]);
-    await setVariableMetaDataExpectFailure(userWithNoBalance, collectionId, itemId, [1, 2]);
-  });
-
-  it('Default value of rate limit does not sponsor setting variable metadata', async () => {
-    const collectionId = await createCollectionExpectSuccess();
-    await setCollectionSponsorExpectSuccess(collectionId, alice.address);
-    await confirmSponsorshipExpectSuccess(collectionId);
-
-    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', userWithNoBalance.address);
-    await setVariableMetaDataExpectFailure(userWithNoBalance, collectionId, itemId, [1]);
-  });
-
-  it('sponsoring of data is disabled by default', async () => {
-    await usingApi(async api => {
-      const collectionId = await createCollectionExpectSuccess();
-
-      const collection = (await getDetailedCollectionInfo(api, collectionId))!;
-      // limit is none = default is used
-      expect(collection?.limits.sponsoredDataRateLimit.isNone);
-    });
-  });
-
-  it('sponsoring can be disabled explicitly', async () => {
-    await usingApi(async api => {
-      const collectionId = await createCollectionExpectSuccess();
-
-      await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsoredDataRateLimit: {Blocks: 6}});
-      {
-        const collection = (await getDetailedCollectionInfo(api, collectionId))!;
-        expect(collection?.limits.sponsoredDataRateLimit.unwrap().asBlocks.toNumber()).to.equal(6);
-      }
-
-      await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsoredDataRateLimit: 'SponsoringDisabled'});
-      {
-        const collection = (await getDetailedCollectionInfo(api, collectionId))!;
-        // disabled sponsoring = default value
-        expect(collection?.limits.sponsoredDataRateLimit.unwrap().isNone).to.true;
-      }
-    });
-  });
-});
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -142,7 +142,6 @@
 export interface IReFungibleTokenDataType {
   owner: IReFungibleOwner[];
   constData: number[];
-  variableData: number[];
 }
 
 export function uniqueEventMessage(events: EventRecord[]): IGetMessage {
@@ -648,28 +647,6 @@
     const sender = privateKey(senderSeed);
     const tx = api.tx.unique.confirmSponsorship(collectionId);
     await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
-  });
-}
-
-export async function setMetadataUpdatePermissionFlagExpectSuccess(sender: IKeyringPair, collectionId: number, flag: string) {
-
-  await usingApi(async (api) => {
-    const tx = api.tx.unique.setMetaUpdatePermissionFlag(collectionId, flag as any);
-    const events = await submitTransactionAsync(sender, tx);
-    const result = getGenericResult(events);
-
-    expect(result.success).to.be.true;
-  });
-}
-
-export async function setMetadataUpdatePermissionFlagExpectFailure(sender: IKeyringPair, collectionId: number, flag: string) {
-
-  await usingApi(async (api) => {
-    const tx = api.tx.unique.setMetaUpdatePermissionFlag(collectionId, flag as any);
-    const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
-    const result = getGenericResult(events);
-
-    expect(result.success).to.be.false;
   });
 }
 
@@ -794,23 +771,6 @@
   });
 }
 
-export async function setVariableMetaDataExpectSuccess(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {
-  await usingApi(async (api) => {
-    const tx = api.tx.unique.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));
-    const events = await submitTransactionAsync(sender, tx);
-    const result = getGenericResult(events);
-
-    expect(result.success).to.be.true;
-  });
-}
-
-export async function setVariableMetaDataExpectFailure(sender: IKeyringPair, collectionId: number, itemId: number, data: number[]) {
-  await usingApi(async (api) => {
-    const tx = api.tx.unique.setVariableMetaData(collectionId, itemId, '0x' + Buffer.from(data).toString('hex'));
-    await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected;
-  });
-}
-
 export async function setOffchainSchemaExpectSuccess(sender: IKeyringPair, collectionId: number, data: number[]) {
   await usingApi(async (api) => {
     const tx = api.tx.unique.setOffchainSchema(collectionId, '0x' + Buffer.from(data).toString('hex'));
@@ -1137,13 +1097,6 @@
   collectionId: number,
 ): Promise<string[]> {
   return (await api.rpc.unique.adminlist(collectionId)).toHuman() as any;
-}
-export async function getVariableMetadata(
-  api: ApiPromise,
-  collectionId: number,
-  tokenId: number,
-): Promise<number[]> {
-  return [...(await api.rpc.unique.variableMetadata(collectionId, tokenId))];
 }
 export async function getConstMetadata(
   api: ApiPromise,
@@ -1182,10 +1135,10 @@
       const createData = {fungible: {value: 10}};
       tx = api.tx.unique.createItem(collectionId, to, createData as any);
     } else if (createMode === 'ReFungible') {
-      const createData = {refungible: {const_data: [], variable_data: [], pieces: 100}};
+      const createData = {refungible: {const_data: [], pieces: 100}};
       tx = api.tx.unique.createItem(collectionId, to, createData as any);
     } else {
-      const createData = {nft: {const_data: [], variable_data: []}};
+      const createData = {nft: {const_data: []}};
       tx = api.tx.unique.createItem(collectionId, to, createData as any);
     }