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

difftreelog

refactor Remove variable data from tokens

Daniel Shiposha2022-05-14parent: #c4410a4.patch.diff
in: master

23 files changed

modifiedclient/rpc/src/lib.rsdiffbeforeafterboth
--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -71,13 +71,6 @@
 		token: TokenId,
 		at: Option<BlockHash>,
 	) -> Result<Vec<u8>>;
-	#[rpc(name = "unique_variableMetadata")]
-	fn variable_metadata(
-		&self,
-		collection: CollectionId,
-		token: TokenId,
-		at: Option<BlockHash>,
-	) -> Result<Vec<u8>>;
 
 	#[rpc(name = "unique_collectionProperties")]
 	fn collection_properties(
@@ -279,7 +272,6 @@
 	);
 	pass_method!(topmost_token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>);
 	pass_method!(const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);
-	pass_method!(variable_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);
 
 	pass_method!(collection_properties(
 		collection: CollectionId,
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -33,7 +33,7 @@
 	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,
+	CUSTOM_DATA_LIMIT, CollectionLimits, CreateCollectionData, SponsorshipState,
 	CreateItemExData, SponsoringRateLimit, budget::Budget, COLLECTION_FIELD_LIMIT, CollectionField,
 	PhantomType, Property, Properties, PropertiesPermissionMap, PropertyKey, PropertyPermission,
 	PropertiesError, PropertyKeyPermission, TokenData, TrySet,
@@ -312,8 +312,6 @@
 		CollectionTokenPrefixLimitExceeded,
 		/// Total collections bound exceeded.
 		TotalCollectionsLimitExceeded,
-		/// variable_data exceeded data limit.
-		TokenVariableDataLimitExceeded,
 		/// Exceeded max admin count
 		CollectionAdminCountExceeded,
 		/// Collection limit bounds per collection exceeded
@@ -1073,7 +1071,6 @@
 	fn approve() -> Weight;
 	fn transfer_from() -> Weight;
 	fn burn_from() -> Weight;
-	fn set_variable_metadata(bytes: u32) -> Weight;
 }
 
 pub trait CommonCollectionOperations<T: Config> {
@@ -1163,13 +1160,6 @@
 		nesting_budget: &dyn Budget,
 	) -> DispatchResultWithPostInfo;
 
-	fn set_variable_metadata(
-		&self,
-		sender: T::CrossAccountId,
-		token: TokenId,
-		data: BoundedVec<u8, CustomDataLimit>,
-	) -> DispatchResultWithPostInfo;
-
 	fn check_nesting(
 		&self,
 		sender: T::CrossAccountId,
@@ -1185,7 +1175,6 @@
 
 	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>;
 	/// Amount of unique collection tokens
 	fn total_supply(&self) -> u32;
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,
@@ -85,11 +85,6 @@
 	fn burn_from() -> Weight {
 		<SelfWeightOf<T>>::burn_from()
 	}
-
-	fn set_variable_metadata(_bytes: u32) -> Weight {
-		// Error
-		0
-	}
 }
 
 impl<T: Config> CommonCollectionOperations<T> for FungibleHandle<T> {
@@ -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,9 +316,6 @@
 		None
 	}
 	fn const_metadata(&self, _token: TokenId) -> Vec<u8> {
-		Vec::new()
-	}
-	fn variable_metadata(&self, _token: TokenId) -> Vec<u8> {
 		Vec::new()
 	}
 
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,10 +28,8 @@
 
 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,
 	}
 }
@@ -125,14 +123,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,9 +16,9 @@
 
 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,
+	TokenId, CreateItemExData, CollectionId, budget::Budget, Property,
 	PropertyKey, PropertyKeyPermission,
 };
 use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
@@ -85,10 +85,6 @@
 
 	fn burn_from() -> Weight {
 		<SelfWeightOf<T>>::burn_from()
-	}
-
-	fn set_variable_metadata(bytes: u32) -> Weight {
-		<SelfWeightOf<T>>::set_variable_metadata(bytes)
 	}
 }
 
@@ -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(),
 		}),
@@ -325,19 +320,6 @@
 		} else {
 			Ok(().into())
 		}
-	}
-
-	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(
@@ -376,12 +358,6 @@
 	fn const_metadata(&self, token: TokenId) -> Vec<u8> {
 		<TokenData<T>>::get((self.id, token))
 			.map(|t| t.const_data)
-			.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()
 	}
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -24,7 +24,7 @@
 use up_data_structs::{TokenId, SchemaVersion};
 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,
@@ -274,7 +274,6 @@
 			&caller,
 			CreateItemData::<T> {
 				const_data: BoundedVec::default(),
-				variable_data: BoundedVec::default(),
 				properties: BoundedVec::default(),
 				owner: to,
 			},
@@ -322,7 +321,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 +385,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 +407,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 +450,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(),
 			});
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -49,17 +49,22 @@
 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 +83,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 +141,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>);
@@ -577,7 +598,6 @@
 				(collection.id, token),
 				ItemData {
 					const_data: data.const_data,
-					variable_data: data.variable_data,
 					owner: data.owner.clone(),
 				},
 			);
@@ -773,28 +793,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.soldiffbeforeafterboth
--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -61,6 +61,24 @@
 	}
 }
 
+// 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;
+	}
+}
+
 // Selector: 58800161
 contract ERC721 is Dummy, ERC165, ERC721Events {
 	// Selector: balanceOf(address) 70a08231
@@ -276,7 +294,7 @@
 	}
 }
 
-// Selector: e562194d
+// Selector: d74d154f
 contract ERC721UniqueExtensions is Dummy, ERC165 {
 	// Selector: transfer(address,uint256) a9059cbb
 	function transfer(address to, uint256 tokenId) public {
@@ -301,26 +319,6 @@
 		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
 	function mintBulk(address to, uint256[] memory tokenIds)
 		public
@@ -354,5 +352,6 @@
 	ERC721Enumerable,
 	ERC721UniqueExtensions,
 	ERC721Mintable,
-	ERC721Burnable
+	ERC721Burnable,
+	CollectionProperties
 {}
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,9 +17,9 @@
 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,
+	CollectionId, TokenId, CreateItemExData, CreateRefungibleExData,
 	budget::Budget, Property, PropertyKey, PropertyKeyPermission,
 };
 use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
@@ -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,
@@ -355,11 +337,6 @@
 	fn const_metadata(&self, token: TokenId) -> Vec<u8> {
 		<TokenData<T>>::get((self.id, token))
 			.const_data
-			.into_inner()
-	}
-	fn variable_metadata(&self, token: TokenId) -> Vec<u8> {
-		<TokenData<T>>::get((self.id, token))
-			.variable_data
 			.into_inner()
 	}
 
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -41,16 +41,20 @@
 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 +77,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 +153,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 +514,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 +662,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/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -38,7 +38,7 @@
 	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,
+	SchemaVersion, SponsorshipState, MetaUpdatePermission, CreateCollectionData,
 	CreateItemExData, budget, CollectionField, Property, PropertyKey, PropertyKeyPermission,
 };
 use pallet_evm::account::CrossAccountId;
@@ -238,9 +238,6 @@
 		pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
 		//#endregion
 
-		/// Variable metadata sponsoring
-		/// Collection id (controlled?2), token id (controlled?2)
-		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>;
@@ -333,7 +330,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,31 +925,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
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -364,28 +364,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)]
@@ -393,6 +371,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
@@ -490,9 +470,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"))]
@@ -512,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>,
 	pub pieces: u128,
 }
 
@@ -545,8 +519,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,
@@ -557,8 +529,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>>,
 }
@@ -586,8 +556,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,
 		}
 	}
modifiedprimitives/rpc/src/lib.rsdiffbeforeafterboth
--- a/primitives/rpc/src/lib.rs
+++ b/primitives/rpc/src/lib.rs
@@ -42,7 +42,6 @@
 		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>>;
 
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -32,9 +32,6 @@
                 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,
modifiedruntime/common/src/sponsoring.rsdiffbeforeafterboth
--- a/runtime/common/src/sponsoring.rs
+++ b/runtime/common/src/sponsoring.rs
@@ -21,7 +21,7 @@
 	storage::{StorageMap, StorageDoubleMap, StorageNMap},
 };
 use up_data_structs::{
-	CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,
+	CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
 	NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode,
 	CreateItemData,
 };
@@ -30,7 +30,7 @@
 use pallet_evm::account::CrossAccountId;
 use pallet_unique::{
 	Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,
-	NftApproveBasket, VariableMetaDataBasket, CreateItemBasket, ReFungibleTransferBasket,
+	NftApproveBasket, CreateItemBasket, ReFungibleTransferBasket,
 	FungibleTransferBasket, NftTransferBasket,
 };
 use pallet_fungible::Config as FungibleConfig;
@@ -139,64 +139,7 @@
 
 	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(())
-}
-
 pub fn withdraw_approve<T: Config>(
 	collection: &CollectionHandle<T>,
 	who: &T::AccountId,
@@ -290,20 +233,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}
after · 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	}51}5253fn default_fungible_data() -> CreateFungibleData {54	CreateFungibleData { value: 5 }55}5657fn default_re_fungible_data() -> CreateReFungibleData {58	CreateReFungibleData {59		const_data: vec![1, 2, 3].try_into().unwrap(),60		pieces: 1023,61	}62}6364fn create_test_collection_for_owner(65	mode: &CollectionMode,66	owner: u64,67	id: CollectionId,68) -> CollectionId {69	add_balance(owner, CollectionCreationPrice::get() as u64 + 1);7071	let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();72	let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();73	let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();7475	let data: CreateCollectionData<u64> = CreateCollectionData {76		name: col_name1.try_into().unwrap(),77		description: col_desc1.try_into().unwrap(),78		token_prefix: token_prefix1.try_into().unwrap(),79		mode: mode.clone(),80		..Default::default()81	};8283	let origin1 = Origin::signed(owner);84	assert_ok!(Unique::create_collection_ex(origin1, data));8586	let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();87	let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();88	let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();89	assert_eq!(90		<pallet_common::CollectionById<Test>>::get(id)91			.unwrap()92			.owner,93		owner94	);95	assert_eq!(96		<pallet_common::CollectionById<Test>>::get(id).unwrap().name,97		saved_col_name98	);99	assert_eq!(100		<pallet_common::CollectionById<Test>>::get(id).unwrap().mode,101		*mode102	);103	assert_eq!(104		<pallet_common::CollectionById<Test>>::get(id)105			.unwrap()106			.description,107		saved_description108	);109	assert_eq!(110		<pallet_common::CollectionById<Test>>::get(id)111			.unwrap()112			.token_prefix,113		saved_prefix114	);115	id116}117118fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {119	create_test_collection_for_owner(&mode, 1, id)120}121122fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {123	let origin1 = Origin::signed(1);124	assert_ok!(Unique::create_item(125		origin1,126		collection_id,127		account(1),128		data.clone()129	));130}131132fn account(sub: u64) -> TestCrossAccountId {133	TestCrossAccountId::from_sub(sub)134}135136// Use cases tests region137// #region138139#[test]140fn set_version_schema() {141	new_test_ext().execute_with(|| {142		let origin1 = Origin::signed(1);143		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));144145		assert_ok!(Unique::set_schema_version(146			origin1,147			collection_id,148			SchemaVersion::Unique149		));150		assert_eq!(151			<pallet_common::CollectionById<Test>>::get(collection_id)152				.unwrap()153				.schema_version,154			SchemaVersion::Unique155		);156	});157}158159#[test]160fn check_not_sufficient_founds() {161	new_test_ext().execute_with(|| {162		let acc: u64 = 1;163		<pallet_balances::Pallet<Test>>::set_balance(Origin::root(), acc, 0, 0).unwrap();164165		let name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();166		let description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();167		let token_prefix: Vec<u8> = b"token_prefix1\0".to_vec();168169		let data: CreateCollectionData<<Test as frame_system::Config>::AccountId> =170			CreateCollectionData {171				name: name.try_into().unwrap(),172				description: description.try_into().unwrap(),173				token_prefix: token_prefix.try_into().unwrap(),174				mode: CollectionMode::NFT,175				..Default::default()176			};177178		let result = Unique::create_collection_ex(Origin::signed(acc), data);179		assert_err!(result, <CommonError<Test>>::NotSufficientFounds);180	});181}182183#[test]184fn create_fungible_collection_fails_with_large_decimal_numbers() {185	new_test_ext().execute_with(|| {186		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();187		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();188		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();189190		let data: CreateCollectionData<u64> = CreateCollectionData {191			name: col_name1.try_into().unwrap(),192			description: col_desc1.try_into().unwrap(),193			token_prefix: token_prefix1.try_into().unwrap(),194			mode: CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1),195			..Default::default()196		};197198		let origin1 = Origin::signed(1);199		assert_noop!(200			Unique::create_collection_ex(origin1, data),201			UniqueError::<Test>::CollectionDecimalPointLimitExceeded202		);203	});204}205206#[test]207fn create_nft_item() {208	new_test_ext().execute_with(|| {209		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));210211		let data = default_nft_data();212		create_test_item(collection_id, &data.clone().into());213214		let item = <pallet_nonfungible::TokenData<Test>>::get((collection_id, 1)).unwrap();215		assert_eq!(item.const_data, data.const_data.into_inner());216	});217}218219// Use cases tests region220// #region221#[test]222fn create_nft_multiple_items() {223	new_test_ext().execute_with(|| {224		create_test_collection(&CollectionMode::NFT, CollectionId(1));225226		let origin1 = Origin::signed(1);227228		let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];229230		assert_ok!(Unique::create_multiple_items(231			origin1,232			CollectionId(1),233			account(1),234			items_data235				.clone()236				.into_iter()237				.map(|d| { d.into() })238				.collect()239		));240		for (index, data) in items_data.into_iter().enumerate() {241			let item = <pallet_nonfungible::TokenData<Test>>::get((242				CollectionId(1),243				TokenId((index + 1) as u32),244			))245			.unwrap();246			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());247		}248	});249}250251#[test]252fn create_refungible_item() {253	new_test_ext().execute_with(|| {254		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));255256		let data = default_re_fungible_data();257		create_test_item(collection_id, &data.clone().into());258		let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));259		let balance =260			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1)));261		assert_eq!(item.const_data, data.const_data.into_inner());262		assert_eq!(balance, 1023);263	});264}265266#[test]267fn create_multiple_refungible_items() {268	new_test_ext().execute_with(|| {269		create_test_collection(&CollectionMode::ReFungible, CollectionId(1));270271		let origin1 = Origin::signed(1);272273		let items_data = vec![274			default_re_fungible_data(),275			default_re_fungible_data(),276			default_re_fungible_data(),277		];278279		assert_ok!(Unique::create_multiple_items(280			origin1,281			CollectionId(1),282			account(1),283			items_data284				.clone()285				.into_iter()286				.map(|d| { d.into() })287				.collect()288		));289		for (index, data) in items_data.into_iter().enumerate() {290			let item = <pallet_refungible::TokenData<Test>>::get((291				CollectionId(1),292				TokenId((index + 1) as u32),293			));294			let balance =295				<pallet_refungible::Balance<Test>>::get((CollectionId(1), TokenId(1), account(1)));296			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());297			assert_eq!(balance, 1023);298		}299	});300}301302#[test]303fn create_fungible_item() {304	new_test_ext().execute_with(|| {305		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));306307		let data = default_fungible_data();308		create_test_item(collection_id, &data.into());309310		assert_eq!(311			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),312			5313		);314	});315}316317//#[test]318// fn create_multiple_fungible_items() {319//     new_test_ext().execute_with(|| {320//         default_limits();321322//         create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));323324//         let origin1 = Origin::signed(1);325326//         let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];327328//         assert_ok!(Unique::create_multiple_items(329//             origin1.clone(),330//             1,331//             1,332//             items_data.clone().into_iter().map(|d| { d.into() }).collect()333//         ));334335//         for (index, _) in items_data.iter().enumerate() {336//             assert_eq!(Unique::fungible_item_id(1, (index + 1) as TokenId).value, 5);337//         }338//         assert_eq!(Unique::balance_count(1, 1), 3000);339//         assert_eq!(Unique::address_tokens(1, 1), [1, 2, 3]);340//     });341// }342343#[test]344fn transfer_fungible_item() {345	new_test_ext().execute_with(|| {346		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));347348		let origin1 = Origin::signed(1);349		let origin2 = Origin::signed(2);350351		let data = default_fungible_data();352		create_test_item(collection_id, &data.into());353354		assert_eq!(355			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),356			5357		);358359		// change owner scenario360		assert_ok!(Unique::transfer(361			origin1,362			account(2),363			CollectionId(1),364			TokenId(0),365			5366		));367		assert_eq!(368			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),369			0370		);371372		// split item scenario373		assert_ok!(Unique::transfer(374			origin2.clone(),375			account(3),376			CollectionId(1),377			TokenId(0),378			3379		));380381		// split item and new owner has account scenario382		assert_ok!(Unique::transfer(383			origin2,384			account(3),385			CollectionId(1),386			TokenId(0),387			1388		));389		assert_eq!(390			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(2))),391			1392		);393		assert_eq!(394			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(3))),395			4396		);397	});398}399400#[test]401fn transfer_refungible_item() {402	new_test_ext().execute_with(|| {403		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));404405		// Create RFT 1 in 1023 pieces for account 1406		let data = default_re_fungible_data();407		create_test_item(collection_id, &data.clone().into());408		let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));409		assert_eq!(item.const_data, data.const_data.into_inner());410		assert_eq!(411			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),412			1413		);414		assert_eq!(415			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),416			1023417		);418		assert_eq!(419			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),420			true421		);422423		// Account 1 transfers all 1023 pieces of RFT 1 to account 2424		let origin1 = Origin::signed(1);425		let origin2 = Origin::signed(2);426		assert_ok!(Unique::transfer(427			origin1,428			account(2),429			CollectionId(1),430			TokenId(1),431			1023432		));433		assert_eq!(434			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),435			1023436		);437		assert_eq!(438			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),439			0440		);441		assert_eq!(442			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),443			1444		);445		assert_eq!(446			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),447			false448		);449		assert_eq!(450			<pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),451			true452		);453454		// Account 2 transfers 500 pieces of RFT 1 to account 3455		assert_ok!(Unique::transfer(456			origin2.clone(),457			account(3),458			CollectionId(1),459			TokenId(1),460			500461		));462		assert_eq!(463			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),464			523465		);466		assert_eq!(467			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),468			500469		);470		assert_eq!(471			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),472			1473		);474		assert_eq!(475			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),476			1477		);478		assert_eq!(479			<pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),480			true481		);482		assert_eq!(483			<pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),484			true485		);486487		// Account 2 transfers 200 more pieces of RFT 1 to account 3 with pre-existing balance488		assert_ok!(Unique::transfer(489			origin2,490			account(3),491			CollectionId(1),492			TokenId(1),493			200494		));495		assert_eq!(496			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),497			323498		);499		assert_eq!(500			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),501			700502		);503		assert_eq!(504			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),505			1506		);507		assert_eq!(508			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),509			1510		);511		assert_eq!(512			<pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),513			true514		);515		assert_eq!(516			<pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),517			true518		);519	});520}521522#[test]523fn transfer_nft_item() {524	new_test_ext().execute_with(|| {525		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));526527		let data = default_nft_data();528		create_test_item(collection_id, &data.into());529		assert_eq!(530			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),531			1532		);533		assert_eq!(534			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),535			true536		);537538		let origin1 = Origin::signed(1);539		// default scenario540		assert_ok!(Unique::transfer(541			origin1,542			account(2),543			CollectionId(1),544			TokenId(1),545			1546		));547		assert_eq!(548			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),549			0550		);551		assert_eq!(552			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),553			1554		);555		assert_eq!(556			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),557			false558		);559		assert_eq!(560			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),561			true562		);563	});564}565566#[test]567fn transfer_nft_item_wrong_value() {568	new_test_ext().execute_with(|| {569		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));570571		let data = default_nft_data();572		create_test_item(collection_id, &data.into());573		assert_eq!(574			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),575			1576		);577		assert_eq!(578			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),579			true580		);581582		let origin1 = Origin::signed(1);583584		assert_noop!(585			Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 2)586				.map_err(|e| e.error),587			<pallet_nonfungible::Error::<Test>>::NonfungibleItemsHaveNoAmount588		);589	});590}591592#[test]593fn transfer_nft_item_zero_value() {594	new_test_ext().execute_with(|| {595		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));596597		let data = default_nft_data();598		create_test_item(collection_id, &data.into());599		assert_eq!(600			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),601			1602		);603		assert_eq!(604			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),605			true606		);607608		let origin1 = Origin::signed(1);609610		// Transferring 0 amount works on NFT...611		assert_ok!(Unique::transfer(612			origin1,613			account(2),614			CollectionId(1),615			TokenId(1),616			0617		));618		// ... and results in no transfer619		assert_eq!(620			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),621			1622		);623		assert_eq!(624			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),625			true626		);627	});628}629630#[test]631fn nft_approve_and_transfer_from() {632	new_test_ext().execute_with(|| {633		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));634635		let data = default_nft_data();636		create_test_item(collection_id, &data.into());637638		let origin1 = Origin::signed(1);639		let origin2 = Origin::signed(2);640641		assert_eq!(642			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),643			1644		);645		assert_eq!(646			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),647			true648		);649650		// neg transfer_from651		assert_noop!(652			Unique::transfer_from(653				origin2.clone(),654				account(1),655				account(2),656				CollectionId(1),657				TokenId(1),658				1659			)660			.map_err(|e| e.error),661			CommonError::<Test>::ApprovedValueTooLow662		);663664		// do approve665		assert_ok!(Unique::approve(666			origin1,667			account(2),668			CollectionId(1),669			TokenId(1),670			1671		));672		assert_eq!(673			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),674			account(2)675		);676677		assert_ok!(Unique::transfer_from(678			origin2,679			account(1),680			account(3),681			CollectionId(1),682			TokenId(1),683			1684		));685		assert!(686			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()687		);688	});689}690691#[test]692fn nft_approve_and_transfer_from_allow_list() {693	new_test_ext().execute_with(|| {694		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));695696		let origin1 = Origin::signed(1);697		let origin2 = Origin::signed(2);698699		// Create NFT 1 for account 1700		let data = default_nft_data();701		create_test_item(collection_id, &data.clone().into());702		assert_eq!(703			&<pallet_nonfungible::TokenData<Test>>::get((collection_id, TokenId(1)))704				.unwrap()705				.const_data,706			&data.const_data.into_inner()707		);708		assert_eq!(709			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),710			1711		);712		assert_eq!(713			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),714			true715		);716717		// Allow allow-list users to mint and add accounts 1, 2, and 3 to allow-list718		assert_ok!(Unique::set_mint_permission(719			origin1.clone(),720			CollectionId(1),721			true722		));723		assert_ok!(Unique::set_public_access_mode(724			origin1.clone(),725			CollectionId(1),726			AccessMode::AllowList727		));728		assert_ok!(Unique::add_to_allow_list(729			origin1.clone(),730			CollectionId(1),731			account(1)732		));733		assert_ok!(Unique::add_to_allow_list(734			origin1.clone(),735			CollectionId(1),736			account(2)737		));738		assert_ok!(Unique::add_to_allow_list(739			origin1.clone(),740			CollectionId(1),741			account(3)742		));743744		// Account 1 approves account 2 for NFT 1745		assert_ok!(Unique::approve(746			origin1.clone(),747			account(2),748			CollectionId(1),749			TokenId(1),750			1751		));752		assert_eq!(753			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),754			account(2)755		);756757		// Account 2 transfers NFT 1 from account 1 to account 3758		assert_ok!(Unique::transfer_from(759			origin2,760			account(1),761			account(3),762			CollectionId(1),763			TokenId(1),764			1765		));766		assert!(767			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()768		);769	});770}771772#[test]773fn refungible_approve_and_transfer_from() {774	new_test_ext().execute_with(|| {775		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));776777		let origin1 = Origin::signed(1);778		let origin2 = Origin::signed(2);779780		// Create RFT 1 in 1023 pieces for account 1781		let data = default_re_fungible_data();782		create_test_item(collection_id, &data.into());783784		assert_eq!(785			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),786			1787		);788		assert_eq!(789			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),790			1023791		);792		assert_eq!(793			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),794			true795		);796797		// Allow public minting, enable allow-list and add accounts 1, 2, 3 to allow-list798		assert_ok!(Unique::set_mint_permission(799			origin1.clone(),800			CollectionId(1),801			true802		));803		assert_ok!(Unique::set_public_access_mode(804			origin1.clone(),805			CollectionId(1),806			AccessMode::AllowList807		));808		assert_ok!(Unique::add_to_allow_list(809			origin1.clone(),810			CollectionId(1),811			account(1)812		));813		assert_ok!(Unique::add_to_allow_list(814			origin1.clone(),815			CollectionId(1),816			account(2)817		));818		assert_ok!(Unique::add_to_allow_list(819			origin1.clone(),820			CollectionId(1),821			account(3)822		));823824		// Account 1 approves account 2 for 1023 pieces of RFT 1825		assert_ok!(Unique::approve(826			origin1,827			account(2),828			CollectionId(1),829			TokenId(1),830			1023831		));832		assert_eq!(833			<pallet_refungible::Allowance<Test>>::get((834				CollectionId(1),835				TokenId(1),836				account(1),837				account(2)838			)),839			1023840		);841842		// Account 2 transfers 100 pieces of RFT 1 from account 1 to account 3843		assert_ok!(Unique::transfer_from(844			origin2,845			account(1),846			account(3),847			CollectionId(1),848			TokenId(1),849			100850		));851		assert_eq!(852			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),853			1854		);855		assert_eq!(856			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),857			1858		);859		assert_eq!(860			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),861			923862		);863		assert_eq!(864			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),865			100866		);867		assert_eq!(868			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),869			true870		);871		assert_eq!(872			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),873			true874		);875		assert_eq!(876			<pallet_refungible::Allowance<Test>>::get((877				CollectionId(1),878				TokenId(1),879				account(1),880				account(2)881			)),882			923883		);884	});885}886887#[test]888fn fungible_approve_and_transfer_from() {889	new_test_ext().execute_with(|| {890		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));891892		let data = default_fungible_data();893		create_test_item(collection_id, &data.into());894895		let origin1 = Origin::signed(1);896		let origin2 = Origin::signed(2);897898		assert_ok!(Unique::set_mint_permission(899			origin1.clone(),900			CollectionId(1),901			true902		));903		assert_ok!(Unique::set_public_access_mode(904			origin1.clone(),905			CollectionId(1),906			AccessMode::AllowList907		));908		assert_ok!(Unique::add_to_allow_list(909			origin1.clone(),910			CollectionId(1),911			account(1)912		));913		assert_ok!(Unique::add_to_allow_list(914			origin1.clone(),915			CollectionId(1),916			account(2)917		));918		assert_ok!(Unique::add_to_allow_list(919			origin1.clone(),920			CollectionId(1),921			account(3)922		));923924		// do approve925		assert_ok!(Unique::approve(926			origin1.clone(),927			account(2),928			CollectionId(1),929			TokenId(0),930			5931		));932		assert_eq!(933			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),934			5935		);936		assert_ok!(Unique::approve(937			origin1,938			account(3),939			CollectionId(1),940			TokenId(0),941			5942		));943		assert_eq!(944			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),945			5946		);947		assert_eq!(948			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(3))),949			5950		);951952		assert_ok!(Unique::transfer_from(953			origin2.clone(),954			account(1),955			account(3),956			CollectionId(1),957			TokenId(0),958			4959		));960961		assert_eq!(962			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),963			1964		);965966		assert_noop!(967			Unique::transfer_from(968				origin2,969				account(1),970				account(3),971				CollectionId(1),972				TokenId(0),973				4974			)975			.map_err(|e| e.error),976			CommonError::<Test>::ApprovedValueTooLow977		);978	});979}980981#[test]982fn change_collection_owner() {983	new_test_ext().execute_with(|| {984		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));985986		let origin1 = Origin::signed(1);987		assert_ok!(Unique::change_collection_owner(origin1, collection_id, 2));988		assert_eq!(989			<pallet_common::CollectionById<Test>>::get(collection_id)990				.unwrap()991				.owner,992			2993		);994	});995}996997#[test]998fn destroy_collection() {999	new_test_ext().execute_with(|| {1000		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10011002		let origin1 = Origin::signed(1);1003		assert_ok!(Unique::destroy_collection(origin1, collection_id));1004	});1005}10061007#[test]1008fn burn_nft_item() {1009	new_test_ext().execute_with(|| {1010		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10111012		let origin1 = Origin::signed(1);10131014		let data = default_nft_data();1015		create_test_item(collection_id, &data.into());10161017		// check balance (collection with id = 1, user id = 1)1018		assert_eq!(1019			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1020			11021		);10221023		// burn item1024		assert_ok!(Unique::burn_item(1025			origin1.clone(),1026			collection_id,1027			TokenId(1),1028			11029		));1030		assert_eq!(1031			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1032			01033		);1034	});1035}10361037#[test]1038fn burn_same_nft_item_twice() {1039	new_test_ext().execute_with(|| {1040		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10411042		let origin1 = Origin::signed(1);10431044		let data = default_nft_data();1045		create_test_item(collection_id, &data.into());10461047		// check balance (collection with id = 1, user id = 1)1048		assert_eq!(1049			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1050			11051		);10521053		// burn item1054		assert_ok!(Unique::burn_item(1055			origin1.clone(),1056			collection_id,1057			TokenId(1),1058			11059		));10601061		// burn item again1062		assert_noop!(1063			Unique::burn_item(origin1, collection_id, TokenId(1), 1).map_err(|e| e.error),1064			CommonError::<Test>::TokenNotFound1065		);10661067		assert_eq!(1068			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1069			01070		);1071	});1072}10731074#[test]1075fn burn_fungible_item() {1076	new_test_ext().execute_with(|| {1077		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));10781079		let origin1 = Origin::signed(1);1080		assert_ok!(Unique::add_collection_admin(1081			origin1.clone(),1082			collection_id,1083			account(2)1084		));10851086		let data = default_fungible_data();1087		create_test_item(collection_id, &data.into());10881089		// check balance (collection with id = 1, user id = 1)1090		assert_eq!(1091			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1092			51093		);10941095		// burn item1096		assert_ok!(Unique::burn_item(1097			origin1.clone(),1098			CollectionId(1),1099			TokenId(0),1100			51101		));1102		assert_noop!(1103			Unique::burn_item(origin1, CollectionId(1), TokenId(0), 5).map_err(|e| e.error),1104			CommonError::<Test>::TokenValueTooLow1105		);11061107		assert_eq!(1108			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1109			01110		);1111	});1112}11131114#[test]1115fn burn_fungible_item_with_token_id() {1116	new_test_ext().execute_with(|| {1117		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));11181119		let origin1 = Origin::signed(1);1120		assert_ok!(Unique::add_collection_admin(1121			origin1.clone(),1122			collection_id,1123			account(2)1124		));11251126		let data = default_fungible_data();1127		create_test_item(collection_id, &data.into());11281129		// check balance (collection with id = 1, user id = 1)1130		assert_eq!(1131			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1132			51133		);11341135		// Try to burn item using Token ID1136		assert_noop!(1137			Unique::burn_item(origin1, CollectionId(1), TokenId(1), 5).map_err(|e| e.error),1138			<pallet_fungible::Error::<Test>>::FungibleItemsHaveNoId1139		);1140	});1141}1142#[test]1143fn burn_refungible_item() {1144	new_test_ext().execute_with(|| {1145		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));1146		let origin1 = Origin::signed(1);11471148		assert_ok!(Unique::set_mint_permission(1149			origin1.clone(),1150			collection_id,1151			true1152		));1153		assert_ok!(Unique::set_public_access_mode(1154			origin1.clone(),1155			collection_id,1156			AccessMode::AllowList1157		));1158		assert_ok!(Unique::add_to_allow_list(1159			origin1.clone(),1160			collection_id,1161			account(1)1162		));11631164		assert_ok!(Unique::add_collection_admin(1165			origin1.clone(),1166			collection_id,1167			account(2)1168		));11691170		let data = default_re_fungible_data();1171		create_test_item(collection_id, &data.into());11721173		// check balance (collection with id = 1, user id = 2)1174		assert_eq!(1175			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),1176			11177		);1178		assert_eq!(1179			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1180			10231181		);11821183		// burn item1184		assert_ok!(Unique::burn_item(1185			origin1.clone(),1186			collection_id,1187			TokenId(1),1188			10231189		));1190		assert_noop!(1191			Unique::burn_item(origin1, collection_id, TokenId(1), 1023).map_err(|e| e.error),1192			CommonError::<Test>::TokenValueTooLow1193		);11941195		assert_eq!(1196			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1197			01198		);1199	});1200}12011202#[test]1203fn add_collection_admin() {1204	new_test_ext().execute_with(|| {1205		let collection1_id =1206			create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1207		let origin1 = Origin::signed(1);12081209		// Add collection admins1210		assert_ok!(Unique::add_collection_admin(1211			origin1.clone(),1212			collection1_id,1213			account(2)1214		));1215		assert_ok!(Unique::add_collection_admin(1216			origin1,1217			collection1_id,1218			account(3)1219		));12201221		// Owner is not an admin by default1222		assert_eq!(1223			<pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(1))),1224			false1225		);1226		assert!(<pallet_common::IsAdmin<Test>>::get((1227			CollectionId(1),1228			account(2)1229		)));1230		assert!(<pallet_common::IsAdmin<Test>>::get((1231			CollectionId(1),1232			account(3)1233		)));1234	});1235}12361237#[test]1238fn remove_collection_admin() {1239	new_test_ext().execute_with(|| {1240		let collection1_id =1241			create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1242		let origin1 = Origin::signed(1);1243		let origin2 = Origin::signed(2);12441245		// Add collection admins 2 and 31246		assert_ok!(Unique::add_collection_admin(1247			origin1.clone(),1248			collection1_id,1249			account(2)1250		));1251		assert_ok!(Unique::add_collection_admin(1252			origin1,1253			collection1_id,1254			account(3)1255		));12561257		assert!(<pallet_common::IsAdmin<Test>>::get((1258			CollectionId(1),1259			account(2)1260		)));1261		assert!(<pallet_common::IsAdmin<Test>>::get((1262			CollectionId(1),1263			account(3)1264		)));12651266		// remove admin 31267		assert_ok!(Unique::remove_collection_admin(1268			origin2,1269			CollectionId(1),1270			account(3)1271		));12721273		// 2 is still admin, 3 is not an admin anymore1274		assert!(<pallet_common::IsAdmin<Test>>::get((1275			CollectionId(1),1276			account(2)1277		)));1278		assert_eq!(1279			<pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(3))),1280			false1281		);1282	});1283}12841285#[test]1286fn balance_of() {1287	new_test_ext().execute_with(|| {1288		let nft_collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1289		let fungible_collection_id =1290			create_test_collection(&CollectionMode::Fungible(3), CollectionId(2));1291		let re_fungible_collection_id =1292			create_test_collection(&CollectionMode::ReFungible, CollectionId(3));12931294		// check balance before1295		assert_eq!(1296			<pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1297			01298		);1299		assert_eq!(1300			<pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1301			01302		);1303		assert_eq!(1304			<pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1305			01306		);13071308		let nft_data = default_nft_data();1309		create_test_item(nft_collection_id, &nft_data.into());13101311		let fungible_data = default_fungible_data();1312		create_test_item(fungible_collection_id, &fungible_data.into());13131314		let re_fungible_data = default_re_fungible_data();1315		create_test_item(re_fungible_collection_id, &re_fungible_data.into());13161317		// check balance (collection with id = 1, user id = 1)1318		assert_eq!(1319			<pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1320			11321		);1322		assert_eq!(1323			<pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1324			51325		);1326		assert_eq!(1327			<pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1328			11329		);13301331		assert_eq!(1332			<pallet_nonfungible::Owned<Test>>::get((nft_collection_id, account(1), TokenId(1))),1333			true1334		);1335		assert_eq!(1336			<pallet_refungible::Owned<Test>>::get((1337				re_fungible_collection_id,1338				account(1),1339				TokenId(1)1340			)),1341			true1342		);1343	});1344}13451346#[test]1347fn approve() {1348	new_test_ext().execute_with(|| {1349		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));13501351		let data = default_nft_data();1352		create_test_item(collection_id, &data.into());13531354		let origin1 = Origin::signed(1);13551356		// approve1357		assert_ok!(Unique::approve(1358			origin1,1359			account(2),1360			CollectionId(1),1361			TokenId(1),1362			11363		));1364		assert_eq!(1365			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1366			account(2)1367		);1368	});1369}13701371#[test]1372fn transfer_from() {1373	new_test_ext().execute_with(|| {1374		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1375		let origin1 = Origin::signed(1);1376		let origin2 = Origin::signed(2);13771378		let data = default_nft_data();1379		create_test_item(collection_id, &data.into());13801381		// approve1382		assert_ok!(Unique::approve(1383			origin1.clone(),1384			account(2),1385			CollectionId(1),1386			TokenId(1),1387			11388		));1389		assert_eq!(1390			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1391			account(2)1392		);13931394		assert_ok!(Unique::set_mint_permission(1395			origin1.clone(),1396			CollectionId(1),1397			true1398		));1399		assert_ok!(Unique::set_public_access_mode(1400			origin1.clone(),1401			CollectionId(1),1402			AccessMode::AllowList1403		));1404		assert_ok!(Unique::add_to_allow_list(1405			origin1.clone(),1406			CollectionId(1),1407			account(1)1408		));1409		assert_ok!(Unique::add_to_allow_list(1410			origin1.clone(),1411			CollectionId(1),1412			account(2)1413		));1414		assert_ok!(Unique::add_to_allow_list(1415			origin1,1416			CollectionId(1),1417			account(3)1418		));14191420		assert_ok!(Unique::transfer_from(1421			origin2,1422			account(1),1423			account(2),1424			CollectionId(1),1425			TokenId(1),1426			11427		));14281429		// after transfer1430		assert_eq!(1431			<pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(1))),1432			01433		);1434		assert_eq!(1435			<pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(2))),1436			11437		);1438	});1439}14401441// #endregion14421443// Coverage tests region1444// #region14451446#[test]1447fn owner_can_add_address_to_allow_list() {1448	new_test_ext().execute_with(|| {1449		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));14501451		let origin1 = Origin::signed(1);1452		assert_ok!(Unique::add_to_allow_list(1453			origin1,1454			collection_id,1455			account(2)1456		));1457		assert!(<pallet_common::Allowlist<Test>>::get((1458			collection_id,1459			account(2)1460		)));1461	});1462}14631464#[test]1465fn admin_can_add_address_to_allow_list() {1466	new_test_ext().execute_with(|| {1467		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1468		let origin1 = Origin::signed(1);1469		let origin2 = Origin::signed(2);14701471		assert_ok!(Unique::add_collection_admin(1472			origin1,1473			collection_id,1474			account(2)1475		));1476		assert_ok!(Unique::add_to_allow_list(1477			origin2,1478			collection_id,1479			account(3)1480		));1481		assert!(<pallet_common::Allowlist<Test>>::get((1482			collection_id,1483			account(3)1484		)));1485	});1486}14871488#[test]1489fn nonprivileged_user_cannot_add_address_to_allow_list() {1490	new_test_ext().execute_with(|| {1491		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));14921493		let origin2 = Origin::signed(2);1494		assert_noop!(1495			Unique::add_to_allow_list(origin2, collection_id, account(3)),1496			CommonError::<Test>::NoPermission1497		);1498	});1499}15001501#[test]1502fn nobody_can_add_address_to_allow_list_of_nonexisting_collection() {1503	new_test_ext().execute_with(|| {1504		let origin1 = Origin::signed(1);15051506		assert_noop!(1507			Unique::add_to_allow_list(origin1, CollectionId(1), account(2)),1508			CommonError::<Test>::CollectionNotFound1509		);1510	});1511}15121513#[test]1514fn nobody_can_add_address_to_allow_list_of_deleted_collection() {1515	new_test_ext().execute_with(|| {1516		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15171518		let origin1 = Origin::signed(1);1519		assert_ok!(Unique::destroy_collection(origin1.clone(), collection_id));1520		assert_noop!(1521			Unique::add_to_allow_list(origin1, collection_id, account(2)),1522			CommonError::<Test>::CollectionNotFound1523		);1524	});1525}15261527// If address is already added to allow list, nothing happens1528#[test]1529fn address_is_already_added_to_allow_list() {1530	new_test_ext().execute_with(|| {1531		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1532		let origin1 = Origin::signed(1);15331534		assert_ok!(Unique::add_to_allow_list(1535			origin1.clone(),1536			collection_id,1537			account(2)1538		));1539		assert_ok!(Unique::add_to_allow_list(1540			origin1,1541			collection_id,1542			account(2)1543		));1544		assert!(<pallet_common::Allowlist<Test>>::get((1545			collection_id,1546			account(2)1547		)));1548	});1549}15501551#[test]1552fn owner_can_remove_address_from_allow_list() {1553	new_test_ext().execute_with(|| {1554		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15551556		let origin1 = Origin::signed(1);1557		assert_ok!(Unique::add_to_allow_list(1558			origin1.clone(),1559			collection_id,1560			account(2)1561		));1562		assert_ok!(Unique::remove_from_allow_list(1563			origin1,1564			collection_id,1565			account(2)1566		));1567		assert_eq!(1568			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1569			false1570		);1571	});1572}15731574#[test]1575fn admin_can_remove_address_from_allow_list() {1576	new_test_ext().execute_with(|| {1577		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1578		let origin1 = Origin::signed(1);1579		let origin2 = Origin::signed(2);15801581		// Owner adds admin1582		assert_ok!(Unique::add_collection_admin(1583			origin1.clone(),1584			collection_id,1585			account(2)1586		));15871588		// Owner adds address 3 to allow list1589		assert_ok!(Unique::add_to_allow_list(1590			origin1,1591			collection_id,1592			account(3)1593		));15941595		// Admin removes address 3 from allow list1596		assert_ok!(Unique::remove_from_allow_list(1597			origin2,1598			collection_id,1599			account(3)1600		));1601		assert_eq!(1602			<pallet_common::Allowlist<Test>>::get((collection_id, account(3))),1603			false1604		);1605	});1606}16071608#[test]1609fn nonprivileged_user_cannot_remove_address_from_allow_list() {1610	new_test_ext().execute_with(|| {1611		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1612		let origin1 = Origin::signed(1);1613		let origin2 = Origin::signed(2);16141615		assert_ok!(Unique::add_to_allow_list(1616			origin1,1617			collection_id,1618			account(2)1619		));1620		assert_noop!(1621			Unique::remove_from_allow_list(origin2, collection_id, account(2)),1622			CommonError::<Test>::NoPermission1623		);1624		assert!(<pallet_common::Allowlist<Test>>::get((1625			collection_id,1626			account(2)1627		)));1628	});1629}16301631#[test]1632fn nobody_can_remove_address_from_allow_list_of_nonexisting_collection() {1633	new_test_ext().execute_with(|| {1634		let origin1 = Origin::signed(1);16351636		assert_noop!(1637			Unique::remove_from_allow_list(origin1, CollectionId(1), account(2)),1638			CommonError::<Test>::CollectionNotFound1639		);1640	});1641}16421643#[test]1644fn nobody_can_remove_address_from_allow_list_of_deleted_collection() {1645	new_test_ext().execute_with(|| {1646		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1647		let origin1 = Origin::signed(1);1648		let origin2 = Origin::signed(2);16491650		// Add account 2 to allow list1651		assert_ok!(Unique::add_to_allow_list(1652			origin1.clone(),1653			collection_id,1654			account(2)1655		));16561657		// Account 2 is in collection allow-list1658		assert!(<pallet_common::Allowlist<Test>>::get((1659			collection_id,1660			account(2)1661		)));16621663		// Destroy collection1664		assert_ok!(Unique::destroy_collection(origin1, collection_id));16651666		// Attempt to remove account 2 from collection allow-list => error1667		assert_noop!(1668			Unique::remove_from_allow_list(origin2, collection_id, account(2)),1669			CommonError::<Test>::CollectionNotFound1670		);16711672		// Account 2 is not found in collection allow-list anyway1673		assert_eq!(1674			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1675			false1676		);1677	});1678}16791680// If address is already removed from allow list, nothing happens1681#[test]1682fn address_is_already_removed_from_allow_list() {1683	new_test_ext().execute_with(|| {1684		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1685		let origin1 = Origin::signed(1);16861687		assert_ok!(Unique::add_to_allow_list(1688			origin1.clone(),1689			collection_id,1690			account(2)1691		));1692		assert_ok!(Unique::remove_from_allow_list(1693			origin1.clone(),1694			collection_id,1695			account(2)1696		));1697		assert_eq!(1698			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1699			false1700		);1701		assert_ok!(Unique::remove_from_allow_list(1702			origin1,1703			collection_id,1704			account(2)1705		));1706		assert_eq!(1707			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1708			false1709		);1710	});1711}17121713// If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom (2 tests)1714#[test]1715fn allow_list_test_1() {1716	new_test_ext().execute_with(|| {1717		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));17181719		let origin1 = Origin::signed(1);17201721		let data = default_nft_data();1722		create_test_item(collection_id, &data.into());17231724		assert_ok!(Unique::set_public_access_mode(1725			origin1.clone(),1726			collection_id,1727			AccessMode::AllowList1728		));1729		assert_ok!(Unique::add_to_allow_list(1730			origin1.clone(),1731			collection_id,1732			account(2)1733		));17341735		assert_noop!(1736			Unique::transfer(origin1, account(3), CollectionId(1), TokenId(1), 1)1737				.map_err(|e| e.error),1738			CommonError::<Test>::AddressNotInAllowlist1739		);1740	});1741}17421743#[test]1744fn allow_list_test_2() {1745	new_test_ext().execute_with(|| {1746		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1747		let origin1 = Origin::signed(1);17481749		let data = default_nft_data();1750		create_test_item(collection_id, &data.into());17511752		assert_ok!(Unique::set_public_access_mode(1753			origin1.clone(),1754			collection_id,1755			AccessMode::AllowList1756		));1757		assert_ok!(Unique::add_to_allow_list(1758			origin1.clone(),1759			collection_id,1760			account(1)1761		));1762		assert_ok!(Unique::add_to_allow_list(1763			origin1.clone(),1764			collection_id,1765			account(2)1766		));17671768		// do approve1769		assert_ok!(Unique::approve(1770			origin1.clone(),1771			account(1),1772			collection_id,1773			TokenId(1),1774			11775		));1776		assert_eq!(1777			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1778			account(1)1779		);17801781		assert_ok!(Unique::remove_from_allow_list(1782			origin1.clone(),1783			collection_id,1784			account(1)1785		));17861787		assert_noop!(1788			Unique::transfer_from(1789				origin1,1790				account(1),1791				account(3),1792				CollectionId(1),1793				TokenId(1),1794				11795			)1796			.map_err(|e| e.error),1797			CommonError::<Test>::AddressNotInAllowlist1798		);1799	});1800}18011802// If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom (2 tests)1803#[test]1804fn allow_list_test_3() {1805	new_test_ext().execute_with(|| {1806		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18071808		let origin1 = Origin::signed(1);18091810		let data = default_nft_data();1811		create_test_item(collection_id, &data.into());18121813		assert_ok!(Unique::set_public_access_mode(1814			origin1.clone(),1815			collection_id,1816			AccessMode::AllowList1817		));1818		assert_ok!(Unique::add_to_allow_list(1819			origin1.clone(),1820			collection_id,1821			account(1)1822		));18231824		assert_noop!(1825			Unique::transfer(origin1, account(3), collection_id, TokenId(1), 1)1826				.map_err(|e| e.error),1827			CommonError::<Test>::AddressNotInAllowlist1828		);1829	});1830}18311832#[test]1833fn allow_list_test_4() {1834	new_test_ext().execute_with(|| {1835		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18361837		let origin1 = Origin::signed(1);18381839		let data = default_nft_data();1840		create_test_item(collection_id, &data.into());18411842		assert_ok!(Unique::set_public_access_mode(1843			origin1.clone(),1844			collection_id,1845			AccessMode::AllowList1846		));1847		assert_ok!(Unique::add_to_allow_list(1848			origin1.clone(),1849			collection_id,1850			account(1)1851		));1852		assert_ok!(Unique::add_to_allow_list(1853			origin1.clone(),1854			collection_id,1855			account(2)1856		));18571858		// do approve1859		assert_ok!(Unique::approve(1860			origin1.clone(),1861			account(1),1862			collection_id,1863			TokenId(1),1864			11865		));1866		assert_eq!(1867			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1868			account(1)1869		);18701871		assert_ok!(Unique::remove_from_allow_list(1872			origin1.clone(),1873			collection_id,1874			account(2)1875		));18761877		assert_noop!(1878			Unique::transfer_from(1879				origin1,1880				account(1),1881				account(3),1882				collection_id,1883				TokenId(1),1884				11885			)1886			.map_err(|e| e.error),1887			CommonError::<Test>::AddressNotInAllowlist1888		);1889	});1890}18911892// 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)1893#[test]1894fn allow_list_test_5() {1895	new_test_ext().execute_with(|| {1896		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18971898		let origin1 = Origin::signed(1);18991900		let data = default_nft_data();1901		create_test_item(collection_id, &data.into());19021903		assert_ok!(Unique::set_public_access_mode(1904			origin1.clone(),1905			collection_id,1906			AccessMode::AllowList1907		));1908		assert_noop!(1909			Unique::burn_item(origin1.clone(), CollectionId(1), TokenId(1), 1).map_err(|e| e.error),1910			CommonError::<Test>::AddressNotInAllowlist1911		);1912	});1913}19141915// If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method).1916#[test]1917fn allow_list_test_6() {1918	new_test_ext().execute_with(|| {1919		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19201921		let origin1 = Origin::signed(1);19221923		let data = default_nft_data();1924		create_test_item(collection_id, &data.into());19251926		assert_ok!(Unique::set_public_access_mode(1927			origin1.clone(),1928			collection_id,1929			AccessMode::AllowList1930		));19311932		// do approve1933		assert_noop!(1934			Unique::approve(origin1, account(1), CollectionId(1), TokenId(1), 1)1935				.map_err(|e| e.error),1936			CommonError::<Test>::AddressNotInAllowlist1937		);1938	});1939}19401941// If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests) and1942//          tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests)1943#[test]1944fn allow_list_test_7() {1945	new_test_ext().execute_with(|| {1946		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19471948		let data = default_nft_data();1949		create_test_item(collection_id, &data.into());19501951		let origin1 = Origin::signed(1);19521953		assert_ok!(Unique::set_public_access_mode(1954			origin1.clone(),1955			collection_id,1956			AccessMode::AllowList1957		));1958		assert_ok!(Unique::add_to_allow_list(1959			origin1.clone(),1960			collection_id,1961			account(1)1962		));1963		assert_ok!(Unique::add_to_allow_list(1964			origin1.clone(),1965			collection_id,1966			account(2)1967		));19681969		assert_ok!(Unique::transfer(1970			origin1,1971			account(2),1972			CollectionId(1),1973			TokenId(1),1974			11975		));1976	});1977}19781979#[test]1980fn allow_list_test_8() {1981	new_test_ext().execute_with(|| {1982		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19831984		// Create NFT for account 11985		let data = default_nft_data();1986		create_test_item(collection_id, &data.into());19871988		let origin1 = Origin::signed(1);19891990		// Toggle Allow List mode and add accounts 1 and 21991		assert_ok!(Unique::set_public_access_mode(1992			origin1.clone(),1993			collection_id,1994			AccessMode::AllowList1995		));1996		assert_ok!(Unique::add_to_allow_list(1997			origin1.clone(),1998			collection_id,1999			account(1)2000		));2001		assert_ok!(Unique::add_to_allow_list(2002			origin1.clone(),2003			collection_id,2004			account(2)2005		));20062007		// Sself-approve account 1 for NFT 12008		assert_ok!(Unique::approve(2009			origin1.clone(),2010			account(1),2011			CollectionId(1),2012			TokenId(1),2013			12014		));2015		assert_eq!(2016			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),2017			account(1)2018		);20192020		// Transfer from 1 to 22021		assert_ok!(Unique::transfer_from(2022			origin1,2023			account(1),2024			account(2),2025			CollectionId(1),2026			TokenId(1),2027			12028		));2029	});2030}20312032// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner.2033#[test]2034fn allow_list_test_9() {2035	new_test_ext().execute_with(|| {2036		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2037		let origin1 = Origin::signed(1);20382039		assert_ok!(Unique::set_public_access_mode(2040			origin1.clone(),2041			collection_id,2042			AccessMode::AllowList2043		));2044		assert_ok!(Unique::set_mint_permission(origin1, collection_id, false));20452046		let data = default_nft_data();2047		create_test_item(collection_id, &data.into());2048	});2049}20502051// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin.2052#[test]2053fn allow_list_test_10() {2054	new_test_ext().execute_with(|| {2055		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));20562057		let origin1 = Origin::signed(1);2058		let origin2 = Origin::signed(2);20592060		assert_ok!(Unique::set_public_access_mode(2061			origin1.clone(),2062			collection_id,2063			AccessMode::AllowList2064		));2065		assert_ok!(Unique::set_mint_permission(2066			origin1.clone(),2067			collection_id,2068			false2069		));20702071		assert_ok!(Unique::add_collection_admin(2072			origin1,2073			collection_id,2074			account(2)2075		));20762077		assert_ok!(Unique::create_item(2078			origin2,2079			collection_id,2080			account(2),2081			default_nft_data().into()2082		));2083	});2084}20852086// 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.2087#[test]2088fn allow_list_test_11() {2089	new_test_ext().execute_with(|| {2090		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));20912092		let origin1 = Origin::signed(1);2093		let origin2 = Origin::signed(2);20942095		assert_ok!(Unique::set_public_access_mode(2096			origin1.clone(),2097			collection_id,2098			AccessMode::AllowList2099		));2100		assert_ok!(Unique::set_mint_permission(2101			origin1.clone(),2102			collection_id,2103			false2104		));2105		assert_ok!(Unique::add_to_allow_list(2106			origin1,2107			collection_id,2108			account(2)2109		));21102111		assert_noop!(2112			Unique::create_item(2113				origin2,2114				CollectionId(1),2115				account(2),2116				default_nft_data().into()2117			)2118			.map_err(|e| e.error),2119			CommonError::<Test>::PublicMintingNotAllowed2120		);2121	});2122}21232124// 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.2125#[test]2126fn allow_list_test_12() {2127	new_test_ext().execute_with(|| {2128		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21292130		let origin1 = Origin::signed(1);2131		let origin2 = Origin::signed(2);21322133		assert_ok!(Unique::set_public_access_mode(2134			origin1.clone(),2135			collection_id,2136			AccessMode::AllowList2137		));2138		assert_ok!(Unique::set_mint_permission(origin1, collection_id, false));21392140		assert_noop!(2141			Unique::create_item(2142				origin2,2143				CollectionId(1),2144				account(2),2145				default_nft_data().into()2146			)2147			.map_err(|e| e.error),2148			CommonError::<Test>::PublicMintingNotAllowed2149		);2150	});2151}21522153// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner.2154#[test]2155fn allow_list_test_13() {2156	new_test_ext().execute_with(|| {2157		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21582159		let origin1 = Origin::signed(1);21602161		assert_ok!(Unique::set_public_access_mode(2162			origin1.clone(),2163			collection_id,2164			AccessMode::AllowList2165		));2166		assert_ok!(Unique::set_mint_permission(origin1, collection_id, true));21672168		let data = default_nft_data();2169		create_test_item(collection_id, &data.into());2170	});2171}21722173// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin.2174#[test]2175fn allow_list_test_14() {2176	new_test_ext().execute_with(|| {2177		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21782179		let origin1 = Origin::signed(1);2180		let origin2 = Origin::signed(2);21812182		assert_ok!(Unique::set_public_access_mode(2183			origin1.clone(),2184			collection_id,2185			AccessMode::AllowList2186		));2187		assert_ok!(Unique::set_mint_permission(2188			origin1.clone(),2189			collection_id,2190			true2191		));21922193		assert_ok!(Unique::add_collection_admin(2194			origin1,2195			collection_id,2196			account(2)2197		));21982199		assert_ok!(Unique::create_item(2200			origin2,2201			collection_id,2202			account(2),2203			default_nft_data().into()2204		));2205	});2206}22072208// 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.2209#[test]2210fn allow_list_test_15() {2211	new_test_ext().execute_with(|| {2212		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22132214		let origin1 = Origin::signed(1);2215		let origin2 = Origin::signed(2);22162217		assert_ok!(Unique::set_public_access_mode(2218			origin1.clone(),2219			collection_id,2220			AccessMode::AllowList2221		));2222		assert_ok!(Unique::set_mint_permission(origin1, collection_id, true));22232224		assert_noop!(2225			Unique::create_item(2226				origin2,2227				collection_id,2228				account(2),2229				default_nft_data().into()2230			)2231			.map_err(|e| e.error),2232			CommonError::<Test>::AddressNotInAllowlist2233		);2234	});2235}22362237// 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.2238#[test]2239fn allow_list_test_16() {2240	new_test_ext().execute_with(|| {2241		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22422243		let origin1 = Origin::signed(1);2244		let origin2 = Origin::signed(2);22452246		assert_ok!(Unique::set_public_access_mode(2247			origin1.clone(),2248			collection_id,2249			AccessMode::AllowList2250		));2251		assert_ok!(Unique::set_mint_permission(2252			origin1.clone(),2253			collection_id,2254			true2255		));2256		assert_ok!(Unique::add_to_allow_list(2257			origin1,2258			collection_id,2259			account(2)2260		));22612262		assert_ok!(Unique::create_item(2263			origin2,2264			collection_id,2265			account(2),2266			default_nft_data().into()2267		));2268	});2269}22702271// Total number of collections. Positive test2272#[test]2273fn total_number_collections_bound() {2274	new_test_ext().execute_with(|| {2275		create_test_collection(&CollectionMode::NFT, CollectionId(1));2276	});2277}22782279#[test]2280fn create_max_collections() {2281	new_test_ext().execute_with(|| {2282		for i in 1..COLLECTION_NUMBER_LIMIT {2283			create_test_collection(&CollectionMode::NFT, CollectionId(i));2284		}2285	});2286}22872288// Total number of collections. Negative test2289#[test]2290fn total_number_collections_bound_neg() {2291	new_test_ext().execute_with(|| {2292		let origin1 = Origin::signed(1);22932294		for i in 1..=COLLECTION_NUMBER_LIMIT {2295			create_test_collection(&CollectionMode::NFT, CollectionId(i));2296		}22972298		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();2299		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();2300		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();23012302		let data: CreateCollectionData<u64> = CreateCollectionData {2303			name: col_name1.try_into().unwrap(),2304			description: col_desc1.try_into().unwrap(),2305			token_prefix: token_prefix1.try_into().unwrap(),2306			mode: CollectionMode::NFT,2307			..Default::default()2308		};23092310		// 11-th collection in chain. Expects error2311		assert_noop!(2312			Unique::create_collection_ex(origin1, data),2313			CommonError::<Test>::TotalCollectionsLimitExceeded2314		);2315	});2316}23172318// Owned tokens by a single address. Positive test2319#[test]2320fn owned_tokens_bound() {2321	new_test_ext().execute_with(|| {2322		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23232324		let data = default_nft_data();2325		create_test_item(collection_id, &data.clone().into());2326		create_test_item(collection_id, &data.into());2327	});2328}23292330// Owned tokens by a single address. Negotive test2331#[test]2332fn owned_tokens_bound_neg() {2333	new_test_ext().execute_with(|| {2334		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23352336		let origin1 = Origin::signed(1);23372338		for _ in 1..=MAX_TOKEN_OWNERSHIP {2339			let data = default_nft_data();2340			create_test_item(collection_id, &data.clone().into());2341		}23422343		let data = default_nft_data();2344		assert_noop!(2345			Unique::create_item(origin1, CollectionId(1), account(1), data.into())2346				.map_err(|e| e.error),2347			CommonError::<Test>::AccountTokenLimitExceeded2348		);2349	});2350}23512352// Number of collection admins. Positive test2353#[test]2354fn collection_admins_bound() {2355	new_test_ext().execute_with(|| {2356		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23572358		let origin1 = Origin::signed(1);23592360		assert_ok!(Unique::add_collection_admin(2361			origin1.clone(),2362			collection_id,2363			account(2)2364		));2365		assert_ok!(Unique::add_collection_admin(2366			origin1,2367			collection_id,2368			account(3)2369		));2370	});2371}23722373// Number of collection admins. Negotive test2374#[test]2375fn collection_admins_bound_neg() {2376	new_test_ext().execute_with(|| {2377		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23782379		let origin1 = Origin::signed(1);23802381		for i in 0..COLLECTION_ADMINS_LIMIT {2382			assert_ok!(Unique::add_collection_admin(2383				origin1.clone(),2384				collection_id,2385				account((2 + i).into())2386			));2387		}2388		assert_noop!(2389			Unique::add_collection_admin(2390				origin1,2391				collection_id,2392				account((3 + COLLECTION_ADMINS_LIMIT).into())2393			),2394			CommonError::<Test>::CollectionAdminCountExceeded2395		);2396	});2397}2398// #endregion23992400#[test]2401fn set_const_on_chain_schema() {2402	new_test_ext().execute_with(|| {2403		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24042405		let origin1 = Origin::signed(1);2406		assert_ok!(Unique::set_const_on_chain_schema(2407			origin1,2408			collection_id,2409			b"test const on chain schema".to_vec().try_into().unwrap()2410		));24112412		assert_eq!(2413			<pallet_common::CollectionData<Test>>::get((2414				collection_id,2415				CollectionField::ConstOnChainSchema2416			)),2417			b"test const on chain schema".to_vec()2418		);2419	});2420}24212422#[test]2423fn collection_transfer_flag_works() {2424	new_test_ext().execute_with(|| {2425		let origin1 = Origin::signed(1);24262427		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2428		assert_ok!(Unique::set_transfers_enabled_flag(2429			origin1,2430			collection_id,2431			true2432		));24332434		let data = default_nft_data();2435		create_test_item(collection_id, &data.into());2436		assert_eq!(2437			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2438			12439		);2440		assert_eq!(2441			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2442			true2443		);24442445		let origin1 = Origin::signed(1);24462447		// default scenario2448		assert_ok!(Unique::transfer(2449			origin1,2450			account(2),2451			collection_id,2452			TokenId(1),2453			12454		));2455		assert_eq!(2456			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2457			false2458		);2459		assert_eq!(2460			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2461			true2462		);2463		assert_eq!(2464			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2465			02466		);2467		assert_eq!(2468			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2469			12470		);2471	});2472}24732474#[test]2475fn set_variable_meta_flag_after_freeze() {2476	new_test_ext().execute_with(|| {2477		// default_limits();24782479		let collection_id =2480			create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));24812482		let origin2 = Origin::signed(2);24832484		assert_ok!(Unique::set_meta_update_permission_flag(2485			origin2.clone(),2486			collection_id,2487			MetaUpdatePermission::None,2488		));2489		assert_noop!(2490			Unique::set_meta_update_permission_flag(2491				origin2.clone(),2492				collection_id,2493				MetaUpdatePermission::Admin2494			),2495			CommonError::<Test>::MetadataFlagFrozen2496		);2497	});2498}24992500#[test]2501fn collection_transfer_flag_works_neg() {2502	new_test_ext().execute_with(|| {2503		let origin1 = Origin::signed(1);25042505		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2506		assert_ok!(Unique::set_transfers_enabled_flag(2507			origin1,2508			collection_id,2509			false2510		));25112512		let data = default_nft_data();2513		create_test_item(collection_id, &data.into());2514		assert_eq!(2515			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2516			12517		);2518		assert_eq!(2519			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2520			true2521		);25222523		let origin1 = Origin::signed(1);25242525		// default scenario2526		assert_noop!(2527			Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 1)2528				.map_err(|e| e.error),2529			CommonError::<Test>::TransferNotAllowed2530		);2531		assert_eq!(2532			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2533			12534		);2535		assert_eq!(2536			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2537			02538		);2539		assert_eq!(2540			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2541			true2542		);2543		assert_eq!(2544			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2545			false2546		);2547	});2548}25492550#[test]2551fn collection_sponsoring() {2552	new_test_ext().execute_with(|| {2553		// default_limits();2554		let user1 = 1_u64;2555		let user2 = 777_u64;2556		let origin1 = Origin::signed(user1);2557		let origin2 = Origin::signed(user2);2558		let account2 = account(user2);25592560		let collection_id =2561			create_test_collection_for_owner(&CollectionMode::NFT, user1, CollectionId(1));2562		assert_ok!(Unique::set_collection_sponsor(2563			origin1.clone(),2564			collection_id,2565			user12566		));2567		assert_ok!(Unique::confirm_sponsorship(origin1.clone(), collection_id));25682569		// Expect error while have no permissions2570		assert!(Unique::create_item(2571			origin2.clone(),2572			collection_id,2573			account2.clone(),2574			default_nft_data().into()2575		)2576		.is_err());25772578		assert_ok!(Unique::set_public_access_mode(2579			origin1.clone(),2580			collection_id,2581			AccessMode::AllowList2582		));2583		assert_ok!(Unique::add_to_allow_list(2584			origin1.clone(),2585			collection_id,2586			account2.clone()2587		));2588		assert_ok!(Unique::set_mint_permission(2589			origin1.clone(),2590			collection_id,2591			true2592		));25932594		assert_ok!(Unique::create_item(2595			origin2,2596			collection_id,2597			account2,2598			default_nft_data().into()2599		));2600	});2601}
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) {