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

difftreelog

test fix unit

Yaroslav Bolyukin2022-04-13parent: #f082ca5.patch.diff
in: master

19 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6829,37 +6829,18 @@
 name = "pallet-unique"
 version = "0.1.0"
 dependencies = [
- "ethereum",
- "evm-coder",
- "fp-evm",
- "fp-evm-mapping",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
- "hex-literal",
- "pallet-balances",
  "pallet-common",
- "pallet-ethereum",
  "pallet-evm",
- "pallet-evm-coder-substrate",
- "pallet-fungible",
- "pallet-nonfungible",
- "pallet-randomness-collective-flip",
- "pallet-refungible",
- "pallet-timestamp",
- "pallet-transaction-payment",
  "parity-scale-codec",
- "primitive-types",
- "rlp",
  "scale-info",
- "serde",
- "sp-api",
  "sp-core",
  "sp-io",
  "sp-runtime",
  "sp-std",
  "up-data-structs",
- "up-sponsorship",
 ]
 
 [[package]]
@@ -11918,6 +11899,35 @@
 ]
 
 [[package]]
+name = "tests"
+version = "0.1.0"
+dependencies = [
+ "fp-evm-mapping",
+ "frame-support",
+ "frame-system",
+ "pallet-balances",
+ "pallet-common",
+ "pallet-ethereum",
+ "pallet-evm",
+ "pallet-evm-coder-substrate",
+ "pallet-fungible",
+ "pallet-nonfungible",
+ "pallet-refungible",
+ "pallet-structure",
+ "pallet-timestamp",
+ "pallet-transaction-payment",
+ "pallet-unique",
+ "parity-scale-codec",
+ "scale-info",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+ "unique-runtime-common",
+ "up-data-structs",
+]
+
+[[package]]
 name = "textwrap"
 version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -12677,6 +12687,7 @@
 name = "unique-runtime-common"
 version = "0.9.18"
 dependencies = [
+ "evm-coder",
  "fp-rpc",
  "frame-support",
  "frame-system",
@@ -12693,6 +12704,7 @@
  "sp-runtime",
  "sp-std",
  "up-data-structs",
+ "up-sponsorship",
 ]
 
 [[package]]
modifiedCargo.tomldiffbeforeafterboth
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,16 @@
 [workspace]
 resolver = "2"
-members = ['node/*', 'pallets/*', 'client/*', 'primitives/*', 'crates/*']
-exclude = ["runtime/unique", "runtime/quartz"]
+members = [
+    'node/*',
+    'pallets/*',
+    'client/*',
+    'primitives/*',
+    'crates/*',
+    'runtime/tests',
+]
+exclude = [
+    "runtime/unique",
+    "runtime/quartz"
+]
 [profile.release]
 panic = 'unwind'
modifiedpallets/unique/Cargo.tomldiffbeforeafterboth
--- a/pallets/unique/Cargo.toml
+++ b/pallets/unique/Cargo.toml
@@ -19,32 +19,14 @@
 runtime-benchmarks = ['frame-benchmarking', 'pallet-common/runtime-benchmarks']
 std = [
     'codec/std',
-    'serde/std',
     'frame-support/std',
     'frame-system/std',
-    'pallet-balances/std',
     'pallet-evm/std',
-    'pallet-timestamp/std',
-    'pallet-randomness-collective-flip/std',
-    'pallet-transaction-payment/std',
     'pallet-common/std',
-    'pallet-fungible/std',
-    'pallet-nonfungible/std',
-    'pallet-refungible/std',
-    'fp-evm/std',
     'up-data-structs/std',
-    'up-sponsorship/std',
-    'fp-evm-mapping/std',
     'sp-std/std',
-    'sp-api/std',
     'sp-runtime/std',
     'frame-benchmarking/std',
-    'ethereum/std',
-    'rlp/std',
-
-    'primitive-types/std',
-    'evm-coder/std',
-    'pallet-evm-coder-substrate/std',
 ]
 limit-testing = ["up-data-structs/limit-testing"]
 
@@ -69,21 +51,6 @@
 branch = "polkadot-v0.9.20"
 
 [dependencies.frame-system]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.20"
-
-[dependencies.pallet-balances]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.20"
-
-[dependencies.pallet-timestamp]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.20"
-
-[dependencies.pallet-randomness-collective-flip]
 default-features = false
 git = "https://github.com/paritytech/substrate"
 branch = "polkadot-v0.9.20"
@@ -93,16 +60,6 @@
 git = "https://github.com/paritytech/substrate"
 branch = "polkadot-v0.9.20"
 
-[dependencies.pallet-transaction-payment]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.20"
-
-[dependencies.serde]
-default-features = false
-features = ['derive']
-version = '1.0.130'
-
 [dependencies.sp-runtime]
 default-features = false
 git = "https://github.com/paritytech/substrate"
@@ -123,28 +80,8 @@
 # Local Dependencies
 [dependencies]
 up-data-structs = { default-features = false, path = "../../primitives/data-structs" }
-
 scale-info = { version = "2.0.1", default-features = false, features = [
     "derive",
 ] }
-ethereum = { version = "0.12.0", default-features = false }
-rlp = { default-features = false, version = "0.5.0" }
-sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }
-
-up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.20" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
-evm-coder = { default-features = false, path = "../../crates/evm-coder" }
-pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }
-primitive-types = { version = "0.11.1", default-features = false, features = [
-    "serde_no_std",
-] }
-
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
-fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
-hex-literal = "0.3.3"
-
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.18-2" }
 pallet-common = { default-features = false, path = "../common" }
-pallet-fungible = { default-features = false, path = "../fungible" }
-pallet-nonfungible = { default-features = false, path = "../nonfungible" }
-pallet-refungible = { default-features = false, path = "../refungible" }
deletedpallets/unique/src/common.rsdiffbeforeafterboth
--- a/pallets/unique/src/common.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-use core::marker::PhantomData;
-use frame_support::{weights::Weight};
-use pallet_common::{CommonWeightInfo, dispatch::dispatch_weight};
-
-use pallet_fungible::{common::CommonWeights as FungibleWeights};
-use pallet_nonfungible::{common::CommonWeights as NonfungibleWeights};
-use pallet_refungible::{common::CommonWeights as RefungibleWeights};
-use up_data_structs::CreateItemExData;
-
-use crate::Config;
-
-macro_rules! max_weight_of {
-	($method:ident ( $($args:tt)* )) => {
-		<FungibleWeights<T>>::$method($($args)*)
-		.max(<NonfungibleWeights<T>>::$method($($args)*))
-		.max(<RefungibleWeights<T>>::$method($($args)*))
-	};
-}
-
-pub struct CommonWeights<T: Config>(PhantomData<T>);
-impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {
-	fn create_item() -> Weight {
-		dispatch_weight::<T>() + max_weight_of!(create_item())
-	}
-
-	fn create_multiple_items(amount: u32) -> Weight {
-		dispatch_weight::<T>() + max_weight_of!(create_multiple_items(amount))
-	}
-
-	fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {
-		dispatch_weight::<T>() + max_weight_of!(create_multiple_items_ex(data))
-	}
-
-	fn burn_item() -> Weight {
-		dispatch_weight::<T>() + max_weight_of!(burn_item())
-	}
-
-	fn transfer() -> Weight {
-		dispatch_weight::<T>() + max_weight_of!(transfer())
-	}
-
-	fn approve() -> Weight {
-		dispatch_weight::<T>() + max_weight_of!(approve())
-	}
-
-	fn transfer_from() -> Weight {
-		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())
-	}
-}
deletedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
--- a/pallets/unique/src/eth/mod.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-pub mod sponsoring;
deletedpallets/unique/src/eth/sponsoring.rsdiffbeforeafterboth
--- a/pallets/unique/src/eth/sponsoring.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-//! Implements EVM sponsoring logic via TransactionValidityHack
-
-use crate::{Config, sponsorship::*};
-use evm_coder::{Call, abi::AbiReader};
-use pallet_common::{CollectionHandle, eth::map_eth_to_id};
-use sp_core::H160;
-use sp_std::prelude::*;
-use up_sponsorship::SponsorshipHandler;
-use core::marker::PhantomData;
-use core::convert::TryInto;
-use pallet_evm::account::CrossAccountId;
-use up_data_structs::{TokenId, CreateItemData, CreateNftData};
-
-use pallet_nonfungible::erc::{
-	UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call,
-};
-use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};
-
-pub struct UniqueEthSponsorshipHandler<T: Config>(PhantomData<*const T>);
-impl<T: Config> SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)>
-	for UniqueEthSponsorshipHandler<T>
-{
-	fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {
-		let collection_id = map_eth_to_id(&call.0)?;
-		let collection = <CollectionHandle<T>>::new(collection_id)?;
-		let sponsor = collection.sponsorship.sponsor()?.clone();
-		let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;
-		Some(T::CrossAccountId::from_sub(match &collection.mode {
-			crate::CollectionMode::NFT => {
-				let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;
-				match call {
-					UniqueNFTCall::ERC721UniqueExtensions(
-						ERC721UniqueExtensionsCall::Transfer { token_id, .. },
-					) => {
-						let token_id: TokenId = token_id.try_into().ok()?;
-						withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)
-					}
-					UniqueNFTCall::ERC721Mintable(
-						ERC721MintableCall::Mint { token_id, .. }
-						| ERC721MintableCall::MintWithTokenUri { token_id, .. },
-					) => {
-						let _token_id: TokenId = token_id.try_into().ok()?;
-						withdraw_create_item::<T>(
-							&collection,
-							&who,
-							&CreateItemData::NFT(CreateNftData::default()),
-						)
-						.map(|()| sponsor)
-					}
-					UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {
-						let token_id: TokenId = token_id.try_into().ok()?;
-						let from = T::CrossAccountId::from_eth(from);
-						withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)
-					}
-					UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {
-						let token_id: TokenId = token_id.try_into().ok()?;
-						withdraw_approve::<T>(&collection, who.as_sub(), &token_id)
-							.map(|()| sponsor)
-					}
-					_ => None,
-				}
-			}
-			crate::CollectionMode::Fungible(_) => {
-				let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;
-				#[allow(clippy::single_match)]
-				match call {
-					UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
-						withdraw_transfer::<T>(&collection, who, &TokenId::default())
-							.map(|()| sponsor)
-					}
-					UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {
-						let from = T::CrossAccountId::from_eth(from);
-						withdraw_transfer::<T>(&collection, &from, &TokenId::default())
-							.map(|()| sponsor)
-					}
-					UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {
-						withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())
-							.map(|()| sponsor)
-					}
-					_ => None,
-				}
-			}
-			_ => None,
-		}?))
-	}
-}
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -22,10 +22,6 @@
 	clippy::unused_unit
 )]
 
-extern crate alloc;
-
-pub use serde::{Serialize, Deserialize};
-
 use frame_support::{
 	decl_module, decl_storage, decl_error, decl_event,
 	dispatch::DispatchResult,
@@ -50,20 +46,6 @@
 	CollectionHandle, Pallet as PalletCommon, Error as CommonError, CommonWeightInfo,
 	dispatch::dispatch_call, dispatch::CollectionDispatch,
 };
-
-#[cfg(test)]
-mod mock;
-
-#[cfg(test)]
-mod tests;
-
-mod eth;
-mod sponsorship;
-pub use sponsorship::{UniqueSponsorshipHandler, UniqueSponsorshipPredict};
-pub use eth::sponsoring::UniqueEthSponsorshipHandler;
-
-pub mod common;
-use common::CommonWeights;
 
 #[cfg(feature = "runtime-benchmarks")]
 mod benchmarking;
@@ -88,20 +70,12 @@
 	}
 }
 
-pub trait Config:
-	system::Config
-	+ pallet_evm_coder_substrate::Config
-	+ pallet_common::Config
-	+ pallet_nonfungible::Config
-	+ pallet_refungible::Config
-	+ pallet_fungible::Config
-	+ Sized
-	+ TypeInfo
-{
+pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {
 	type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;
 
 	/// Weight information for extrinsics in this pallet.
 	type WeightInfo: WeightInfo;
+	type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;
 }
 
 decl_event! {
@@ -689,7 +663,7 @@
 		/// * owner: Address, initial owner of the NFT.
 		///
 		/// * data: Token data to store on chain.
-		#[weight = <CommonWeights<T>>::create_item()]
+		#[weight = T::CommonWeightInfo::create_item()]
 		#[transactional]
 		pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -716,7 +690,7 @@
 		/// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].
 		///
 		/// * owner: Address, initial owner of the NFT.
-		#[weight = <CommonWeights<T>>::create_multiple_items(items_data.len() as u32)]
+		#[weight = T::CommonWeightInfo::create_multiple_items(items_data.len() as u32)]
 		#[transactional]
 		pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {
 			ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);
@@ -726,7 +700,7 @@
 			dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))
 		}
 
-		#[weight = <CommonWeights<T>>::create_multiple_items_ex(&data)]
+		#[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]
 		#[transactional]
 		pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -774,7 +748,7 @@
 		/// * collection_id: ID of the collection.
 		///
 		/// * item_id: ID of NFT to burn.
-		#[weight = <CommonWeights<T>>::burn_item()]
+		#[weight = T::CommonWeightInfo::burn_item()]
 		#[transactional]
 		pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -806,7 +780,7 @@
 		/// * item_id: ID of NFT to burn.
 		///
 		/// * from: owner of item
-		#[weight = <CommonWeights<T>>::burn_from()]
+		#[weight = T::CommonWeightInfo::burn_from()]
 		#[transactional]
 		pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -838,7 +812,7 @@
 		///     * Non-Fungible Mode: Ignored
 		///     * Fungible Mode: Must specify transferred amount
 		///     * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)
-		#[weight = <CommonWeights<T>>::transfer()]
+		#[weight = T::CommonWeightInfo::transfer()]
 		#[transactional]
 		pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -862,7 +836,7 @@
 		/// * collection_id.
 		///
 		/// * item_id: ID of the item.
-		#[weight = <CommonWeights<T>>::approve()]
+		#[weight = T::CommonWeightInfo::approve()]
 		#[transactional]
 		pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -889,7 +863,7 @@
 		/// * item_id: ID of the item.
 		///
 		/// * value: Amount to transfer.
-		#[weight = <CommonWeights<T>>::transfer_from()]
+		#[weight = T::CommonWeightInfo::transfer_from()]
 		#[transactional]
 		pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -910,7 +884,7 @@
 		/// * collection_id.
 		///
 		/// * schema: String representing the offchain data schema.
-		#[weight = <CommonWeights<T>>::set_variable_metadata(data.len() as u32)]
+		#[weight = T::CommonWeightInfo::set_variable_metadata(data.len() as u32)]
 		#[transactional]
 		pub fn set_variable_meta_data (
 			origin,
deletedpallets/unique/src/mock.rsdiffbeforeafterboth
--- a/pallets/unique/src/mock.rs
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-#![allow(clippy::from_over_into)]
-
-use crate as pallet_template;
-use sp_core::{H160, H256};
-use frame_support::{parameter_types, traits::Everything, weights::IdentityFee};
-use sp_runtime::{
-	traits::{BlakeTwo256, IdentityLookup},
-	testing::Header,
-};
-use pallet_transaction_payment::{CurrencyAdapter};
-use frame_system as system;
-use pallet_evm::{AddressMapping, runner::stack::MaybeMirroredLog, account::CrossAccountId};
-use fp_evm_mapping::EvmBackwardsAddressMapping;
-use codec::{Encode, Decode, MaxEncodedLen};
-use scale_info::TypeInfo;
-use up_data_structs::ConstU32;
-
-type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
-type Block = frame_system::mocking::MockBlock<Test>;
-
-// Configure a mock runtime to test the pallet.
-frame_support::construct_runtime!(
-	pub enum Test where
-		Block = Block,
-		NodeBlock = Block,
-		UncheckedExtrinsic = UncheckedExtrinsic,
-	{
-		System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
-		TemplateModule: pallet_template::{Pallet, Call, Storage},
-		Balances: pallet_balances::{Pallet, Call, Storage},
-		Common: pallet_common::{Pallet, Storage, Event<T>},
-		Fungible: pallet_fungible::{Pallet, Storage},
-		Refungible: pallet_refungible::{Pallet, Storage},
-		Nonfungible: pallet_nonfungible::{Pallet, Storage},
-	}
-);
-
-parameter_types! {
-	pub const BlockHashCount: u64 = 250;
-	pub const SS58Prefix: u8 = 42;
-}
-
-impl system::Config for Test {
-	type BaseCallFilter = Everything;
-	type BlockWeights = ();
-	type BlockLength = ();
-	type DbWeight = ();
-	type Origin = Origin;
-	type Call = Call;
-	type Index = u64;
-	type BlockNumber = u64;
-	type Hash = H256;
-	type Hashing = BlakeTwo256;
-	type AccountId = u64;
-	type Lookup = IdentityLookup<Self::AccountId>;
-	type Header = Header;
-	type Event = ();
-	type BlockHashCount = BlockHashCount;
-	type Version = ();
-	type PalletInfo = PalletInfo;
-	type AccountData = pallet_balances::AccountData<u64>;
-	type OnNewAccount = ();
-	type OnKilledAccount = ();
-	type SystemWeightInfo = ();
-	type SS58Prefix = SS58Prefix;
-	type OnSetCode = ();
-	type MaxConsumers = ConstU32<16>;
-}
-
-parameter_types! {
-	pub const ExistentialDeposit: u64 = 1;
-	pub const MaxLocks: u32 = 50;
-}
-//frame_system::Module<Test>;
-impl pallet_balances::Config for Test {
-	type AccountStore = System;
-	type Balance = u64;
-	type DustRemoval = ();
-	type Event = ();
-	type ExistentialDeposit = ExistentialDeposit;
-	type WeightInfo = ();
-	type MaxLocks = MaxLocks;
-	type MaxReserves = ();
-	type ReserveIdentifier = [u8; 8];
-}
-
-parameter_types! {
-	pub const OperationalFeeMultiplier: u8 = 5;
-}
-
-impl pallet_transaction_payment::Config for Test {
-	type OnChargeTransaction = CurrencyAdapter<pallet_balances::Pallet<Test>, ()>;
-	type LengthToFee = IdentityFee<u64>;
-	type WeightToFee = IdentityFee<u64>;
-	type FeeMultiplierUpdate = ();
-	type OperationalFeeMultiplier = OperationalFeeMultiplier;
-}
-
-parameter_types! {
-	pub const MinimumPeriod: u64 = 1;
-}
-impl pallet_timestamp::Config for Test {
-	type Moment = u64;
-	type OnTimestampSet = ();
-	type MinimumPeriod = MinimumPeriod;
-	type WeightInfo = ();
-}
-
-parameter_types! {
-	pub const CollectionCreationPrice: u32 = 100;
-	pub TreasuryAccountId: u64 = 1234;
-	pub EthereumChainId: u32 = 1111;
-}
-
-pub struct TestEvmAddressMapping;
-impl AddressMapping<u64> for TestEvmAddressMapping {
-	fn into_account_id(_addr: sp_core::H160) -> u64 {
-		unimplemented!()
-	}
-}
-
-pub struct TestEvmBackwardsAddressMapping;
-impl EvmBackwardsAddressMapping<u64> for TestEvmBackwardsAddressMapping {
-	fn from_account_id(_account_id: u64) -> sp_core::H160 {
-		unimplemented!()
-	}
-}
-
-#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, TypeInfo, MaxEncodedLen)]
-pub struct TestCrossAccountId(u64, sp_core::H160);
-impl CrossAccountId<u64> for TestCrossAccountId {
-	fn as_sub(&self) -> &u64 {
-		&self.0
-	}
-	fn as_eth(&self) -> &sp_core::H160 {
-		&self.1
-	}
-	fn from_sub(sub: u64) -> Self {
-		let mut eth = [0; 20];
-		eth[12..20].copy_from_slice(&sub.to_be_bytes());
-		Self(sub, sp_core::H160(eth))
-	}
-	fn from_eth(eth: sp_core::H160) -> Self {
-		let mut sub_raw = [0; 8];
-		sub_raw.copy_from_slice(&eth.0[0..8]);
-		let sub = u64::from_be_bytes(sub_raw);
-		Self(sub, eth)
-	}
-	fn conv_eq(&self, other: &Self) -> bool {
-		self.as_sub() == other.as_sub()
-	}
-}
-
-impl Default for TestCrossAccountId {
-	fn default() -> Self {
-		Self::from_sub(0)
-	}
-}
-
-pub struct TestEtheremTransactionSender;
-impl pallet_ethereum::EthereumTransactionSender for TestEtheremTransactionSender {
-	fn submit_logs_transaction(_source: H160, _logs: Vec<MaybeMirroredLog>) {}
-}
-
-impl pallet_evm_coder_substrate::Config for Test {
-	type EthereumTransactionSender = TestEtheremTransactionSender;
-	type GasWeightMapping = ();
-}
-
-impl pallet_common::Config for Test {
-	type Event = ();
-	type Currency = Balances;
-	type CollectionCreationPrice = CollectionCreationPrice;
-	type TreasuryAccountId = TreasuryAccountId;
-}
-
-impl pallet_evm::account::Config for Test {
-	type CrossAccountId = TestCrossAccountId;
-	type EvmAddressMapping = TestEvmAddressMapping;
-	type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;
-}
-
-impl pallet_fungible::Config for Test {
-	type WeightInfo = ();
-}
-impl pallet_refungible::Config for Test {
-	type WeightInfo = ();
-}
-impl pallet_nonfungible::Config for Test {
-	type WeightInfo = ();
-}
-
-impl pallet_template::Config for Test {
-	type Event = ();
-	type WeightInfo = ();
-}
-
-// Build genesis storage according to the mock runtime.
-pub fn new_test_ext() -> sp_io::TestExternalities {
-	system::GenesisConfig::default()
-		.build_storage::<Test>()
-		.unwrap()
-		.into()
-}
deletedpallets/unique/src/sponsorship.rsdiffbeforeafterboth
--- a/pallets/unique/src/sponsorship.rs
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-use crate::{
-	Config, Call, CreateItemBasket, VariableMetaDataBasket, ReFungibleTransferBasket,
-	FungibleTransferBasket, NftTransferBasket, CreateItemData, CollectionMode, NftApproveBasket,
-	FungibleApproveBasket, RefungibleApproveBasket,
-};
-use core::marker::PhantomData;
-use up_sponsorship::SponsorshipHandler;
-use frame_support::{
-	traits::{IsSubType},
-	storage::{StorageMap, StorageDoubleMap, StorageNMap},
-};
-use up_data_structs::{
-	CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,
-	NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId,
-};
-use sp_runtime::traits::Saturating;
-use pallet_common::{CollectionHandle};
-use pallet_evm::account::CrossAccountId;
-
-pub fn withdraw_transfer<T: Config>(
-	collection: &CollectionHandle<T>,
-	who: &T::CrossAccountId,
-	item_id: &TokenId,
-) -> Option<()> {
-	// 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;
-			}
-		}
-	}
-
-	// sponsor timeout
-	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
-	let limit = collection
-		.limits
-		.sponsor_transfer_timeout(match collection.mode {
-			CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
-			CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-			CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-		});
-
-	let last_tx_block = match collection.mode {
-		CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, item_id),
-		CollectionMode::Fungible(_) => {
-			<FungibleTransferBasket<T>>::get(collection.id, who.as_sub())
-		}
-		CollectionMode::ReFungible => {
-			<ReFungibleTransferBasket<T>>::get((collection.id, item_id, who.as_sub()))
-		}
-	};
-
-	if let Some(last_tx_block) = last_tx_block {
-		let timeout = last_tx_block + limit.into();
-		if block_number < timeout {
-			return None;
-		}
-	}
-
-	match collection.mode {
-		CollectionMode::NFT => <NftTransferBasket<T>>::insert(collection.id, item_id, block_number),
-		CollectionMode::Fungible(_) => {
-			<FungibleTransferBasket<T>>::insert(collection.id, who.as_sub(), block_number)
-		}
-		CollectionMode::ReFungible => <ReFungibleTransferBasket<T>>::insert(
-			(collection.id, item_id, who.as_sub()),
-			block_number,
-		),
-	};
-
-	Some(())
-}
-
-pub fn withdraw_create_item<T: Config>(
-	collection: &CollectionHandle<T>,
-	who: &T::CrossAccountId,
-	_properties: &CreateItemData,
-) -> Option<()> {
-	if _properties.data_size() as u32 > collection.limits.sponsored_data_size() {
-		return None;
-	}
-
-	// sponsor timeout
-	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
-	let limit = collection
-		.limits
-		.sponsor_transfer_timeout(match _properties {
-			CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,
-			CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-			CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-		});
-
-	if let Some(last_tx_block) = <CreateItemBasket<T>>::get((collection.id, who.as_sub())) {
-		let timeout = last_tx_block + limit.into();
-		if block_number < timeout {
-			return None;
-		}
-	}
-
-	CreateItemBasket::<T>::insert((collection.id, who.as_sub()), block_number);
-
-	Some(())
-}
-
-pub fn withdraw_set_variable_meta_data<T: Config>(
-	who: &T::CrossAccountId,
-	collection: &CollectionHandle<T>,
-	item_id: &TokenId,
-	data: &[u8],
-) -> Option<()> {
-	// TODO: make it work for admins
-	if collection.meta_update_permission != MetaUpdatePermission::ItemOwner {
-		return None;
-	}
-	// preliminary sponsoring correctness check
-	match collection.mode {
-		CollectionMode::NFT => {
-			let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
-			if !owner.conv_eq(who) {
-				return None;
-			}
-		}
-		CollectionMode::Fungible(_) => {
-			if item_id != &TokenId::default() {
-				return None;
-			}
-			if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {
-				return None;
-			}
-		}
-		CollectionMode::ReFungible => {
-			if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
-				return None;
-			}
-		}
-	}
-
-	// Can't sponsor fungible collection, this tx will be rejected
-	// as invalid
-	if matches!(collection.mode, CollectionMode::Fungible(_)) {
-		return None;
-	}
-	if data.len() > collection.limits.sponsored_data_size() as usize {
-		return None;
-	}
-
-	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
-	let limit = collection.limits.sponsored_data_rate_limit()?;
-
-	if let Some(last_tx_block) = VariableMetaDataBasket::<T>::get(collection.id, item_id) {
-		let timeout = last_tx_block + limit.into();
-		if block_number < timeout {
-			return None;
-		}
-	}
-
-	<VariableMetaDataBasket<T>>::insert(collection.id, item_id, block_number);
-
-	Some(())
-}
-
-pub fn withdraw_approve<T: Config>(
-	collection: &CollectionHandle<T>,
-	who: &T::AccountId,
-	item_id: &TokenId,
-) -> Option<()> {
-	// sponsor timeout
-	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
-	let limit = collection.limits.sponsor_approve_timeout();
-
-	let last_tx_block = match collection.mode {
-		CollectionMode::NFT => <NftApproveBasket<T>>::get(collection.id, item_id),
-		CollectionMode::Fungible(_) => <FungibleApproveBasket<T>>::get(collection.id, who),
-		CollectionMode::ReFungible => {
-			<RefungibleApproveBasket<T>>::get((collection.id, item_id, who))
-		}
-	};
-
-	if let Some(last_tx_block) = last_tx_block {
-		let timeout = last_tx_block + limit.into();
-		if block_number < timeout {
-			return None;
-		}
-	}
-
-	match collection.mode {
-		CollectionMode::NFT => <NftApproveBasket<T>>::insert(collection.id, item_id, block_number),
-		CollectionMode::Fungible(_) => {
-			<FungibleApproveBasket<T>>::insert(collection.id, who, block_number)
-		}
-		CollectionMode::ReFungible => {
-			<RefungibleApproveBasket<T>>::insert((collection.id, item_id, who), block_number)
-		}
-	};
-
-	Some(())
-}
-
-fn load<T: Config>(id: CollectionId) -> Option<(T::AccountId, CollectionHandle<T>)> {
-	let collection = CollectionHandle::new(id)?;
-	let sponsor = collection.sponsorship.sponsor().cloned()?;
-	Some((sponsor, collection))
-}
-
-pub struct UniqueSponsorshipHandler<T>(PhantomData<T>);
-impl<T, C> SponsorshipHandler<T::AccountId, C> for UniqueSponsorshipHandler<T>
-where
-	T: Config,
-	C: IsSubType<Call<T>>,
-{
-	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {
-		match IsSubType::<Call<T>>::is_sub_type(call)? {
-			Call::create_item {
-				collection_id,
-				data,
-				..
-			} => {
-				let (sponsor, collection) = load(*collection_id)?;
-				withdraw_create_item::<T>(
-					&collection,
-					&T::CrossAccountId::from_sub(who.clone()),
-					data,
-				)
-				.map(|()| sponsor)
-			}
-			Call::transfer {
-				collection_id,
-				item_id,
-				..
-			} => {
-				let (sponsor, collection) = load(*collection_id)?;
-				withdraw_transfer::<T>(
-					&collection,
-					&T::CrossAccountId::from_sub(who.clone()),
-					item_id,
-				)
-				.map(|()| sponsor)
-			}
-			Call::transfer_from {
-				collection_id,
-				item_id,
-				from,
-				..
-			} => {
-				let (sponsor, collection) = load(*collection_id)?;
-				withdraw_transfer::<T>(&collection, from, item_id).map(|()| sponsor)
-			}
-			Call::approve {
-				collection_id,
-				item_id,
-				..
-			} => {
-				let (sponsor, collection) = load(*collection_id)?;
-				withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)
-			}
-			Call::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,
-		}
-	}
-}
-
-use crate::SponsorshipPredict;
-pub struct UniqueSponsorshipPredict<T>(PhantomData<T>);
-
-impl<T> SponsorshipPredict<T> for UniqueSponsorshipPredict<T>
-where
-	T: Config,
-{
-	fn predict(collection_id: CollectionId, who: T::CrossAccountId, token: TokenId) -> Option<u64>
-	where
-		u64: From<<T as frame_system::Config>::BlockNumber>,
-	{
-		let collection = <CollectionHandle<T>>::try_get(collection_id).ok()?;
-		let _ = collection.sponsorship.sponsor()?;
-
-		// sponsor timeout
-		let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
-		let limit = collection
-			.limits
-			.sponsor_transfer_timeout(match collection.mode {
-				CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
-				CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-				CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
-			});
-
-		let last_tx_block = match collection.mode {
-			CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, token),
-			CollectionMode::Fungible(_) => {
-				<FungibleTransferBasket<T>>::get(collection.id, who.as_sub())
-			}
-			CollectionMode::ReFungible => {
-				<ReFungibleTransferBasket<T>>::get((collection.id, token, who.as_sub()))
-			}
-		};
-
-		if let Some(last_tx_block) = last_tx_block {
-			return Some(
-				last_tx_block
-					.saturating_add(limit.into())
-					.saturating_sub(block_number)
-					.into(),
-			);
-		}
-
-		let token_exists = match collection.mode {
-			CollectionMode::NFT => {
-				<pallet_nonfungible::TokenData<T>>::contains_key((collection.id, token))
-			}
-			CollectionMode::Fungible(_) => true,
-			CollectionMode::ReFungible => {
-				<pallet_refungible::TotalSupply<T>>::contains_key((collection.id, token))
-			}
-		};
-
-		if token_exists {
-			Some(0)
-		} else {
-			None
-		}
-	}
-}
deletedpallets/unique/src/tests.rsdiffbeforeafterboth
--- a/pallets/unique/src/tests.rs
+++ /dev/null
@@ -1,2912 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-// Tests to be written here
-use super::*;
-use crate::mock::*;
-use crate::{AccessMode, CollectionMode};
-use up_data_structs::{
-	COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,
-	CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission,
-	TokenId, MAX_TOKEN_OWNERSHIP,
-};
-use frame_support::{assert_noop, assert_ok, assert_err};
-use sp_std::convert::TryInto;
-use pallet_balances;
-
-fn add_balance(user: u64, value: u64) {
-	const DONOR_USER: u64 = 999;
-	assert_ok!(<pallet_balances::Pallet<Test>>::set_balance(
-		Origin::root(),
-		DONOR_USER,
-		value,
-		0
-	));
-	assert_ok!(<pallet_balances::Pallet<Test>>::force_transfer(
-		Origin::root(),
-		DONOR_USER,
-		user,
-		value
-	));
-}
-
-fn default_nft_data() -> CreateNftData {
-	CreateNftData {
-		const_data: vec![1, 2, 3].try_into().unwrap(),
-		variable_data: vec![3, 2, 1].try_into().unwrap(),
-	}
-}
-
-fn default_fungible_data() -> CreateFungibleData {
-	CreateFungibleData { value: 5 }
-}
-
-fn default_re_fungible_data() -> CreateReFungibleData {
-	CreateReFungibleData {
-		const_data: vec![1, 2, 3].try_into().unwrap(),
-		variable_data: vec![3, 2, 1].try_into().unwrap(),
-		pieces: 1023,
-	}
-}
-
-fn create_test_collection_for_owner(
-	mode: &CollectionMode,
-	owner: u64,
-	id: CollectionId,
-) -> CollectionId {
-	add_balance(owner, CollectionCreationPrice::get() as u64 + 1);
-
-	let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
-	let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
-	let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
-
-	let data: CreateCollectionData<u64> = CreateCollectionData {
-		name: col_name1.try_into().unwrap(),
-		description: col_desc1.try_into().unwrap(),
-		token_prefix: token_prefix1.try_into().unwrap(),
-		mode: mode.clone(),
-		..Default::default()
-	};
-
-	let origin1 = Origin::signed(owner);
-	assert_ok!(TemplateModule::create_collection_ex(origin1, data));
-
-	let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
-	let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
-	let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();
-	assert_eq!(
-		<pallet_common::CollectionById<Test>>::get(id)
-			.unwrap()
-			.owner,
-		owner
-	);
-	assert_eq!(
-		<pallet_common::CollectionById<Test>>::get(id).unwrap().name,
-		saved_col_name
-	);
-	assert_eq!(
-		<pallet_common::CollectionById<Test>>::get(id).unwrap().mode,
-		*mode
-	);
-	assert_eq!(
-		<pallet_common::CollectionById<Test>>::get(id)
-			.unwrap()
-			.description,
-		saved_description
-	);
-	assert_eq!(
-		<pallet_common::CollectionById<Test>>::get(id)
-			.unwrap()
-			.token_prefix,
-		saved_prefix
-	);
-	id
-}
-
-fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {
-	create_test_collection_for_owner(&mode, 1, id)
-}
-
-fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {
-	let origin1 = Origin::signed(1);
-	assert_ok!(TemplateModule::create_item(
-		origin1,
-		collection_id,
-		account(1),
-		data.clone()
-	));
-}
-
-fn account(sub: u64) -> TestCrossAccountId {
-	TestCrossAccountId::from_sub(sub)
-}
-
-// Use cases tests region
-// #region
-
-#[test]
-fn set_version_schema() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		assert_ok!(TemplateModule::set_schema_version(
-			origin1,
-			collection_id,
-			SchemaVersion::Unique
-		));
-		assert_eq!(
-			<pallet_common::CollectionById<Test>>::get(collection_id)
-				.unwrap()
-				.schema_version,
-			SchemaVersion::Unique
-		);
-	});
-}
-
-#[test]
-fn check_not_sufficient_founds() {
-	new_test_ext().execute_with(|| {
-		let acc: u64 = 1;
-		<pallet_balances::Pallet<Test>>::set_balance(Origin::root(), acc, 0, 0).unwrap();
-
-		let name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
-		let description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
-		let token_prefix: Vec<u8> = b"token_prefix1\0".to_vec();
-
-		let data: CreateCollectionData<<Test as system::Config>::AccountId> =
-			CreateCollectionData {
-				name: name.try_into().unwrap(),
-				description: description.try_into().unwrap(),
-				token_prefix: token_prefix.try_into().unwrap(),
-				mode: CollectionMode::NFT,
-				..Default::default()
-			};
-
-		let result = TemplateModule::create_collection_ex(Origin::signed(acc), data);
-		assert_err!(result, <CommonError<Test>>::NotSufficientFounds);
-	});
-}
-
-#[test]
-fn create_fungible_collection_fails_with_large_decimal_numbers() {
-	new_test_ext().execute_with(|| {
-		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
-		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
-		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
-
-		let data: CreateCollectionData<u64> = CreateCollectionData {
-			name: col_name1.try_into().unwrap(),
-			description: col_desc1.try_into().unwrap(),
-			token_prefix: token_prefix1.try_into().unwrap(),
-			mode: CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1),
-			..Default::default()
-		};
-
-		let origin1 = Origin::signed(1);
-		assert_noop!(
-			TemplateModule::create_collection_ex(origin1, data),
-			Error::<Test>::CollectionDecimalPointLimitExceeded
-		);
-	});
-}
-
-#[test]
-fn create_nft_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.clone().into());
-
-		let item = <pallet_nonfungible::TokenData<Test>>::get((collection_id, 1)).unwrap();
-		assert_eq!(item.const_data, data.const_data.into_inner());
-		assert_eq!(item.variable_data, data.variable_data.into_inner());
-	});
-}
-
-// Use cases tests region
-// #region
-#[test]
-fn create_nft_multiple_items() {
-	new_test_ext().execute_with(|| {
-		create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];
-
-		assert_ok!(TemplateModule::create_multiple_items(
-			origin1,
-			CollectionId(1),
-			account(1),
-			items_data
-				.clone()
-				.into_iter()
-				.map(|d| { d.into() })
-				.collect()
-		));
-		for (index, data) in items_data.into_iter().enumerate() {
-			let item = <pallet_nonfungible::TokenData<Test>>::get((
-				CollectionId(1),
-				TokenId((index + 1) as u32),
-			))
-			.unwrap();
-			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
-			assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
-		}
-	});
-}
-
-#[test]
-fn create_refungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-
-		let data = default_re_fungible_data();
-		create_test_item(collection_id, &data.clone().into());
-		let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));
-		let balance =
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1)));
-		assert_eq!(item.const_data, data.const_data.into_inner());
-		assert_eq!(item.variable_data, data.variable_data.into_inner());
-		assert_eq!(balance, 1023);
-	});
-}
-
-#[test]
-fn create_multiple_refungible_items() {
-	new_test_ext().execute_with(|| {
-		create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let items_data = vec![
-			default_re_fungible_data(),
-			default_re_fungible_data(),
-			default_re_fungible_data(),
-		];
-
-		assert_ok!(TemplateModule::create_multiple_items(
-			origin1,
-			CollectionId(1),
-			account(1),
-			items_data
-				.clone()
-				.into_iter()
-				.map(|d| { d.into() })
-				.collect()
-		));
-		for (index, data) in items_data.into_iter().enumerate() {
-			let item = <pallet_refungible::TokenData<Test>>::get((
-				CollectionId(1),
-				TokenId((index + 1) as u32),
-			));
-			let balance =
-				<pallet_refungible::Balance<Test>>::get((CollectionId(1), TokenId(1), account(1)));
-			assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
-			assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
-			assert_eq!(balance, 1023);
-		}
-	});
-}
-
-#[test]
-fn create_fungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
-		let data = default_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_eq!(
-			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),
-			5
-		);
-	});
-}
-
-//#[test]
-// fn create_multiple_fungible_items() {
-//     new_test_ext().execute_with(|| {
-//         default_limits();
-
-//         create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
-//         let origin1 = Origin::signed(1);
-
-//         let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];
-
-//         assert_ok!(TemplateModule::create_multiple_items(
-//             origin1.clone(),
-//             1,
-//             1,
-//             items_data.clone().into_iter().map(|d| { d.into() }).collect()
-//         ));
-
-//         for (index, _) in items_data.iter().enumerate() {
-//             assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).value, 5);
-//         }
-//         assert_eq!(TemplateModule::balance_count(1, 1), 3000);
-//         assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);
-//     });
-// }
-
-#[test]
-fn transfer_fungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		let data = default_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_eq!(
-			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),
-			5
-		);
-
-		// change owner scenario
-		assert_ok!(TemplateModule::transfer(
-			origin1,
-			account(2),
-			CollectionId(1),
-			TokenId(0),
-			5
-		));
-		assert_eq!(
-			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),
-			0
-		);
-
-		// split item scenario
-		assert_ok!(TemplateModule::transfer(
-			origin2.clone(),
-			account(3),
-			CollectionId(1),
-			TokenId(0),
-			3
-		));
-
-		// split item and new owner has account scenario
-		assert_ok!(TemplateModule::transfer(
-			origin2,
-			account(3),
-			CollectionId(1),
-			TokenId(0),
-			1
-		));
-		assert_eq!(
-			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(2))),
-			1
-		);
-		assert_eq!(
-			<pallet_fungible::Balance<Test>>::get((CollectionId(1), account(3))),
-			4
-		);
-	});
-}
-
-#[test]
-fn transfer_refungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-
-		// Create RFT 1 in 1023 pieces for account 1
-		let data = default_re_fungible_data();
-		create_test_item(collection_id, &data.clone().into());
-		let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));
-		assert_eq!(item.const_data, data.const_data.into_inner());
-		assert_eq!(item.variable_data, data.variable_data.into_inner());
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),
-			1023
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-
-		// Account 1 transfers all 1023 pieces of RFT 1 to account 2
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-		assert_ok!(TemplateModule::transfer(
-			origin1,
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			1023
-		));
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),
-			1023
-		);
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			0
-		);
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),
-			1
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			false
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),
-			true
-		);
-
-		// Account 2 transfers 500 pieces of RFT 1 to account 3
-		assert_ok!(TemplateModule::transfer(
-			origin2.clone(),
-			account(3),
-			CollectionId(1),
-			TokenId(1),
-			500
-		));
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),
-			523
-		);
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),
-			500
-		);
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),
-			1
-		);
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),
-			1
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),
-			true
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),
-			true
-		);
-
-		// Account 2 transfers 200 more pieces of RFT 1 to account 3 with pre-existing balance
-		assert_ok!(TemplateModule::transfer(
-			origin2,
-			account(3),
-			CollectionId(1),
-			TokenId(1),
-			200
-		));
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),
-			323
-		);
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),
-			700
-		);
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),
-			1
-		);
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),
-			1
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),
-			true
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),
-			true
-		);
-	});
-}
-
-#[test]
-fn transfer_nft_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-
-		let origin1 = Origin::signed(1);
-		// default scenario
-		assert_ok!(TemplateModule::transfer(
-			origin1,
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			0
-		);
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),
-			1
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			false
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),
-			true
-		);
-	});
-}
-
-#[test]
-fn transfer_nft_item_wrong_value() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-
-		let origin1 = Origin::signed(1);
-
-		assert_noop!(
-			TemplateModule::transfer(origin1, account(2), CollectionId(1), TokenId(1), 2)
-				.map_err(|e| e.error),
-			<pallet_nonfungible::Error::<Test>>::NonfungibleItemsHaveNoAmount
-		);
-	});
-}
-
-#[test]
-fn transfer_nft_item_zero_value() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-
-		let origin1 = Origin::signed(1);
-
-		// Transferring 0 amount works on NFT...
-		assert_ok!(TemplateModule::transfer(
-			origin1,
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			0
-		));
-		// ... and results in no transfer
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-	});
-}
-
-#[test]
-fn nft_approve_and_transfer_from() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-
-		// neg transfer_from
-		assert_noop!(
-			TemplateModule::transfer_from(
-				origin2.clone(),
-				account(1),
-				account(2),
-				CollectionId(1),
-				TokenId(1),
-				1
-			)
-			.map_err(|e| e.error),
-			CommonError::<Test>::ApprovedValueTooLow
-		);
-
-		// do approve
-		assert_ok!(TemplateModule::approve(
-			origin1,
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-		assert_eq!(
-			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),
-			account(2)
-		);
-
-		assert_ok!(TemplateModule::transfer_from(
-			origin2,
-			account(1),
-			account(3),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-		assert!(
-			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()
-		);
-	});
-}
-
-#[test]
-fn nft_approve_and_transfer_from_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		// Create NFT 1 for account 1
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.clone().into());
-		assert_eq!(
-			&<pallet_nonfungible::TokenData<Test>>::get((collection_id, TokenId(1)))
-				.unwrap()
-				.const_data,
-			&data.const_data.into_inner()
-		);
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-
-		// Allow allow-list users to mint and add accounts 1, 2, and 3 to allow-list
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			CollectionId(1),
-			true
-		));
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			CollectionId(1),
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(3)
-		));
-
-		// Account 1 approves account 2 for NFT 1
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-		assert_eq!(
-			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),
-			account(2)
-		);
-
-		// Account 2 transfers NFT 1 from account 1 to account 3
-		assert_ok!(TemplateModule::transfer_from(
-			origin2,
-			account(1),
-			account(3),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-		assert!(
-			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()
-		);
-	});
-}
-
-#[test]
-fn refungible_approve_and_transfer_from() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		// Create RFT 1 in 1023 pieces for account 1
-		let data = default_re_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),
-			1023
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-
-		// Allow public minting, enable allow-list and add accounts 1, 2, 3 to allow-list
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			CollectionId(1),
-			true
-		));
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			CollectionId(1),
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(3)
-		));
-
-		// Account 1 approves account 2 for 1023 pieces of RFT 1
-		assert_ok!(TemplateModule::approve(
-			origin1,
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			1023
-		));
-		assert_eq!(
-			<pallet_refungible::Allowance<Test>>::get((
-				CollectionId(1),
-				TokenId(1),
-				account(1),
-				account(2)
-			)),
-			1023
-		);
-
-		// Account 2 transfers 100 pieces of RFT 1 from account 1 to account 3
-		assert_ok!(TemplateModule::transfer_from(
-			origin2,
-			account(1),
-			account(3),
-			CollectionId(1),
-			TokenId(1),
-			100
-		));
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),
-			1
-		);
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),
-			923
-		);
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),
-			100
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-		assert_eq!(
-			<pallet_refungible::Allowance<Test>>::get((
-				CollectionId(1),
-				TokenId(1),
-				account(1),
-				account(2)
-			)),
-			923
-		);
-	});
-}
-
-#[test]
-fn fungible_approve_and_transfer_from() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
-		let data = default_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			CollectionId(1),
-			true
-		));
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			CollectionId(1),
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(3)
-		));
-
-		// do approve
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(2),
-			CollectionId(1),
-			TokenId(0),
-			5
-		));
-		assert_eq!(
-			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),
-			5
-		);
-		assert_ok!(TemplateModule::approve(
-			origin1,
-			account(3),
-			CollectionId(1),
-			TokenId(0),
-			5
-		));
-		assert_eq!(
-			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),
-			5
-		);
-		assert_eq!(
-			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(3))),
-			5
-		);
-
-		assert_ok!(TemplateModule::transfer_from(
-			origin2.clone(),
-			account(1),
-			account(3),
-			CollectionId(1),
-			TokenId(0),
-			4
-		));
-
-		assert_eq!(
-			<pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),
-			1
-		);
-
-		assert_noop!(
-			TemplateModule::transfer_from(
-				origin2,
-				account(1),
-				account(3),
-				CollectionId(1),
-				TokenId(0),
-				4
-			)
-			.map_err(|e| e.error),
-			CommonError::<Test>::ApprovedValueTooLow
-		);
-	});
-}
-
-#[test]
-fn change_collection_owner() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::change_collection_owner(
-			origin1,
-			collection_id,
-			2
-		));
-		assert_eq!(
-			<pallet_common::CollectionById<Test>>::get(collection_id)
-				.unwrap()
-				.owner,
-			2
-		);
-	});
-}
-
-#[test]
-fn destroy_collection() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));
-	});
-}
-
-#[test]
-fn burn_nft_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		// check balance (collection with id = 1, user id = 1)
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-
-		// burn item
-		assert_ok!(TemplateModule::burn_item(
-			origin1.clone(),
-			collection_id,
-			TokenId(1),
-			1
-		));
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			0
-		);
-	});
-}
-
-#[test]
-fn burn_same_nft_item_twice() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		// check balance (collection with id = 1, user id = 1)
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-
-		// burn item
-		assert_ok!(TemplateModule::burn_item(
-			origin1.clone(),
-			collection_id,
-			TokenId(1),
-			1
-		));
-
-		// burn item again
-		assert_noop!(
-			TemplateModule::burn_item(origin1, collection_id, TokenId(1), 1).map_err(|e| e.error),
-			CommonError::<Test>::TokenNotFound
-		);
-
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			0
-		);
-	});
-}
-
-#[test]
-fn burn_fungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		let data = default_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		// check balance (collection with id = 1, user id = 1)
-		assert_eq!(
-			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),
-			5
-		);
-
-		// burn item
-		assert_ok!(TemplateModule::burn_item(
-			origin1.clone(),
-			CollectionId(1),
-			TokenId(0),
-			5
-		));
-		assert_noop!(
-			TemplateModule::burn_item(origin1, CollectionId(1), TokenId(0), 5).map_err(|e| e.error),
-			CommonError::<Test>::TokenValueTooLow
-		);
-
-		assert_eq!(
-			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),
-			0
-		);
-	});
-}
-
-#[test]
-fn burn_fungible_item_with_token_id() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		let data = default_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		// check balance (collection with id = 1, user id = 1)
-		assert_eq!(
-			<pallet_fungible::Balance<Test>>::get((collection_id, account(1))),
-			5
-		);
-
-		// Try to burn item using Token ID
-		assert_noop!(
-			TemplateModule::burn_item(origin1, CollectionId(1), TokenId(1), 5).map_err(|e| e.error),
-			<pallet_fungible::Error::<Test>>::FungibleItemsHaveNoId
-		);
-	});
-}
-#[test]
-fn burn_refungible_item() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			true
-		));
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		let data = default_re_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		// check balance (collection with id = 1, user id = 2)
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),
-			1023
-		);
-
-		// burn item
-		assert_ok!(TemplateModule::burn_item(
-			origin1.clone(),
-			collection_id,
-			TokenId(1),
-			1023
-		));
-		assert_noop!(
-			TemplateModule::burn_item(origin1, collection_id, TokenId(1), 1023)
-				.map_err(|e| e.error),
-			CommonError::<Test>::TokenValueTooLow
-		);
-
-		assert_eq!(
-			<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),
-			0
-		);
-	});
-}
-
-#[test]
-fn add_collection_admin() {
-	new_test_ext().execute_with(|| {
-		let collection1_id =
-			create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));
-		let origin1 = Origin::signed(1);
-
-		// Add collection admins
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection1_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection1_id,
-			account(3)
-		));
-
-		// Owner is not an admin by default
-		assert_eq!(
-			<pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(1))),
-			false
-		);
-		assert!(<pallet_common::IsAdmin<Test>>::get((
-			CollectionId(1),
-			account(2)
-		)));
-		assert!(<pallet_common::IsAdmin<Test>>::get((
-			CollectionId(1),
-			account(3)
-		)));
-	});
-}
-
-#[test]
-fn remove_collection_admin() {
-	new_test_ext().execute_with(|| {
-		let collection1_id =
-			create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		// Add collection admins 2 and 3
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection1_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection1_id,
-			account(3)
-		));
-
-		assert!(<pallet_common::IsAdmin<Test>>::get((
-			CollectionId(1),
-			account(2)
-		)));
-		assert!(<pallet_common::IsAdmin<Test>>::get((
-			CollectionId(1),
-			account(3)
-		)));
-
-		// remove admin 3
-		assert_ok!(TemplateModule::remove_collection_admin(
-			origin2,
-			CollectionId(1),
-			account(3)
-		));
-
-		// 2 is still admin, 3 is not an admin anymore
-		assert!(<pallet_common::IsAdmin<Test>>::get((
-			CollectionId(1),
-			account(2)
-		)));
-		assert_eq!(
-			<pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(3))),
-			false
-		);
-	});
-}
-
-#[test]
-fn balance_of() {
-	new_test_ext().execute_with(|| {
-		let nft_collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		let fungible_collection_id =
-			create_test_collection(&CollectionMode::Fungible(3), CollectionId(2));
-		let re_fungible_collection_id =
-			create_test_collection(&CollectionMode::ReFungible, CollectionId(3));
-
-		// check balance before
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),
-			0
-		);
-		assert_eq!(
-			<pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),
-			0
-		);
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),
-			0
-		);
-
-		let nft_data = default_nft_data();
-		create_test_item(nft_collection_id, &nft_data.into());
-
-		let fungible_data = default_fungible_data();
-		create_test_item(fungible_collection_id, &fungible_data.into());
-
-		let re_fungible_data = default_re_fungible_data();
-		create_test_item(re_fungible_collection_id, &re_fungible_data.into());
-
-		// check balance (collection with id = 1, user id = 1)
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),
-			5
-		);
-		assert_eq!(
-			<pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),
-			1
-		);
-
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((nft_collection_id, account(1), TokenId(1))),
-			true
-		);
-		assert_eq!(
-			<pallet_refungible::Owned<Test>>::get((
-				re_fungible_collection_id,
-				account(1),
-				TokenId(1)
-			)),
-			true
-		);
-	});
-}
-
-#[test]
-fn approve() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		let origin1 = Origin::signed(1);
-
-		// approve
-		assert_ok!(TemplateModule::approve(
-			origin1,
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-		assert_eq!(
-			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),
-			account(2)
-		);
-	});
-}
-
-#[test]
-fn transfer_from() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		// approve
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-		assert_eq!(
-			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),
-			account(2)
-		);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			CollectionId(1),
-			true
-		));
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			CollectionId(1),
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			CollectionId(1),
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			CollectionId(1),
-			account(3)
-		));
-
-		assert_ok!(TemplateModule::transfer_from(
-			origin2,
-			account(1),
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-
-		// after transfer
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(1))),
-			0
-		);
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(2))),
-			1
-		);
-	});
-}
-
-// #endregion
-
-// Coverage tests region
-// #region
-
-#[test]
-fn owner_can_add_address_to_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert!(<pallet_common::Allowlist<Test>>::get((
-			collection_id,
-			account(2)
-		)));
-	});
-}
-
-#[test]
-fn admin_can_add_address_to_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin2,
-			collection_id,
-			account(3)
-		));
-		assert!(<pallet_common::Allowlist<Test>>::get((
-			collection_id,
-			account(3)
-		)));
-	});
-}
-
-#[test]
-fn nonprivileged_user_cannot_add_address_to_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin2 = Origin::signed(2);
-		assert_noop!(
-			TemplateModule::add_to_allow_list(origin2, collection_id, account(3)),
-			CommonError::<Test>::NoPermission
-		);
-	});
-}
-
-#[test]
-fn nobody_can_add_address_to_allow_list_of_nonexisting_collection() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-
-		assert_noop!(
-			TemplateModule::add_to_allow_list(origin1, CollectionId(1), account(2)),
-			CommonError::<Test>::CollectionNotFound
-		);
-	});
-}
-
-#[test]
-fn nobody_can_add_address_to_allow_list_of_deleted_collection() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::destroy_collection(
-			origin1.clone(),
-			collection_id
-		));
-		assert_noop!(
-			TemplateModule::add_to_allow_list(origin1, collection_id, account(2)),
-			CommonError::<Test>::CollectionNotFound
-		);
-	});
-}
-
-// If address is already added to allow list, nothing happens
-#[test]
-fn address_is_already_added_to_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert!(<pallet_common::Allowlist<Test>>::get((
-			collection_id,
-			account(2)
-		)));
-	});
-}
-
-#[test]
-fn owner_can_remove_address_from_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert_eq!(
-			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),
-			false
-		);
-	});
-}
-
-#[test]
-fn admin_can_remove_address_from_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		// Owner adds admin
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		// Owner adds address 3 to allow list
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(3)
-		));
-
-		// Admin removes address 3 from allow list
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin2,
-			collection_id,
-			account(3)
-		));
-		assert_eq!(
-			<pallet_common::Allowlist<Test>>::get((collection_id, account(3))),
-			false
-		);
-	});
-}
-
-#[test]
-fn nonprivileged_user_cannot_remove_address_from_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert_noop!(
-			TemplateModule::remove_from_allow_list(origin2, collection_id, account(2)),
-			CommonError::<Test>::NoPermission
-		);
-		assert!(<pallet_common::Allowlist<Test>>::get((
-			collection_id,
-			account(2)
-		)));
-	});
-}
-
-#[test]
-fn nobody_can_remove_address_from_allow_list_of_nonexisting_collection() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-
-		assert_noop!(
-			TemplateModule::remove_from_allow_list(origin1, CollectionId(1), account(2)),
-			CommonError::<Test>::CollectionNotFound
-		);
-	});
-}
-
-#[test]
-fn nobody_can_remove_address_from_allow_list_of_deleted_collection() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		// Add account 2 to allow list
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		// Account 2 is in collection allow-list
-		assert!(<pallet_common::Allowlist<Test>>::get((
-			collection_id,
-			account(2)
-		)));
-
-		// Destroy collection
-		assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));
-
-		// Attempt to remove account 2 from collection allow-list => error
-		assert_noop!(
-			TemplateModule::remove_from_allow_list(origin2, collection_id, account(2)),
-			CommonError::<Test>::CollectionNotFound
-		);
-
-		// Account 2 is not found in collection allow-list anyway
-		assert_eq!(
-			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),
-			false
-		);
-	});
-}
-
-// If address is already removed from allow list, nothing happens
-#[test]
-fn address_is_already_removed_from_allow_list() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_eq!(
-			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),
-			false
-		);
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-		assert_eq!(
-			<pallet_common::Allowlist<Test>>::get((collection_id, account(2))),
-			false
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom (2 tests)
-#[test]
-fn allow_list_test_1() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		assert_noop!(
-			TemplateModule::transfer(origin1, account(3), CollectionId(1), TokenId(1), 1)
-				.map_err(|e| e.error),
-			CommonError::<Test>::AddressNotInAllowlist
-		);
-	});
-}
-
-#[test]
-fn allow_list_test_2() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		// do approve
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(1),
-			collection_id,
-			TokenId(1),
-			1
-		));
-		assert_eq!(
-			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),
-			account(1)
-		);
-
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-
-		assert_noop!(
-			TemplateModule::transfer_from(
-				origin1,
-				account(1),
-				account(3),
-				CollectionId(1),
-				TokenId(1),
-				1
-			)
-			.map_err(|e| e.error),
-			CommonError::<Test>::AddressNotInAllowlist
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom (2 tests)
-#[test]
-fn allow_list_test_3() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-
-		assert_noop!(
-			TemplateModule::transfer(origin1, account(3), collection_id, TokenId(1), 1)
-				.map_err(|e| e.error),
-			CommonError::<Test>::AddressNotInAllowlist
-		);
-	});
-}
-
-#[test]
-fn allow_list_test_4() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		// do approve
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(1),
-			collection_id,
-			TokenId(1),
-			1
-		));
-		assert_eq!(
-			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),
-			account(1)
-		);
-
-		assert_ok!(TemplateModule::remove_from_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		assert_noop!(
-			TemplateModule::transfer_from(
-				origin1,
-				account(1),
-				account(3),
-				collection_id,
-				TokenId(1),
-				1
-			)
-			.map_err(|e| e.error),
-			CommonError::<Test>::AddressNotInAllowlist
-		);
-	});
-}
-
-// 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)
-#[test]
-fn allow_list_test_5() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_noop!(
-			TemplateModule::burn_item(origin1.clone(), CollectionId(1), TokenId(1), 1)
-				.map_err(|e| e.error),
-			CommonError::<Test>::AddressNotInAllowlist
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method).
-#[test]
-fn allow_list_test_6() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-
-		// do approve
-		assert_noop!(
-			TemplateModule::approve(origin1, account(1), CollectionId(1), TokenId(1), 1)
-				.map_err(|e| e.error),
-			CommonError::<Test>::AddressNotInAllowlist
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests) and
-//          tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests)
-#[test]
-fn allow_list_test_7() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		assert_ok!(TemplateModule::transfer(
-			origin1,
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-	});
-}
-
-#[test]
-fn allow_list_test_8() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		// Create NFT for account 1
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		let origin1 = Origin::signed(1);
-
-		// Toggle Allow List mode and add accounts 1 and 2
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(1)
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-
-		// Sself-approve account 1 for NFT 1
-		assert_ok!(TemplateModule::approve(
-			origin1.clone(),
-			account(1),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-		assert_eq!(
-			<pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),
-			account(1)
-		);
-
-		// Transfer from 1 to 2
-		assert_ok!(TemplateModule::transfer_from(
-			origin1,
-			account(1),
-			account(2),
-			CollectionId(1),
-			TokenId(1),
-			1
-		));
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner.
-#[test]
-fn allow_list_test_9() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1,
-			collection_id,
-			false
-		));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin.
-#[test]
-fn allow_list_test_10() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			false
-		));
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection_id,
-			account(2)
-		));
-
-		assert_ok!(TemplateModule::create_item(
-			origin2,
-			collection_id,
-			account(2),
-			default_nft_data().into()
-		));
-	});
-}
-
-// 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.
-#[test]
-fn allow_list_test_11() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			false
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-
-		assert_noop!(
-			TemplateModule::create_item(
-				origin2,
-				CollectionId(1),
-				account(2),
-				default_nft_data().into()
-			)
-			.map_err(|e| e.error),
-			CommonError::<Test>::PublicMintingNotAllowed
-		);
-	});
-}
-
-// 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.
-#[test]
-fn allow_list_test_12() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1,
-			collection_id,
-			false
-		));
-
-		assert_noop!(
-			TemplateModule::create_item(
-				origin2,
-				CollectionId(1),
-				account(2),
-				default_nft_data().into()
-			)
-			.map_err(|e| e.error),
-			CommonError::<Test>::PublicMintingNotAllowed
-		);
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner.
-#[test]
-fn allow_list_test_13() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1,
-			collection_id,
-			true
-		));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-	});
-}
-
-// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin.
-#[test]
-fn allow_list_test_14() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			true
-		));
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection_id,
-			account(2)
-		));
-
-		assert_ok!(TemplateModule::create_item(
-			origin2,
-			collection_id,
-			account(2),
-			default_nft_data().into()
-		));
-	});
-}
-
-// 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.
-#[test]
-fn allow_list_test_15() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1,
-			collection_id,
-			true
-		));
-
-		assert_noop!(
-			TemplateModule::create_item(
-				origin2,
-				collection_id,
-				account(2),
-				default_nft_data().into()
-			)
-			.map_err(|e| e.error),
-			CommonError::<Test>::AddressNotInAllowlist
-		);
-	});
-}
-
-// 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.
-#[test]
-fn allow_list_test_16() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			true
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1,
-			collection_id,
-			account(2)
-		));
-
-		assert_ok!(TemplateModule::create_item(
-			origin2,
-			collection_id,
-			account(2),
-			default_nft_data().into()
-		));
-	});
-}
-
-// Total number of collections. Positive test
-#[test]
-fn total_number_collections_bound() {
-	new_test_ext().execute_with(|| {
-		create_test_collection(&CollectionMode::NFT, CollectionId(1));
-	});
-}
-
-#[test]
-fn create_max_collections() {
-	new_test_ext().execute_with(|| {
-		for i in 1..COLLECTION_NUMBER_LIMIT {
-			create_test_collection(&CollectionMode::NFT, CollectionId(i));
-		}
-	});
-}
-
-// Total number of collections. Negative test
-#[test]
-fn total_number_collections_bound_neg() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-
-		for i in 1..=COLLECTION_NUMBER_LIMIT {
-			create_test_collection(&CollectionMode::NFT, CollectionId(i));
-		}
-
-		let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
-		let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
-		let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
-
-		let data: CreateCollectionData<u64> = CreateCollectionData {
-			name: col_name1.try_into().unwrap(),
-			description: col_desc1.try_into().unwrap(),
-			token_prefix: token_prefix1.try_into().unwrap(),
-			mode: CollectionMode::NFT,
-			..Default::default()
-		};
-
-		// 11-th collection in chain. Expects error
-		assert_noop!(
-			TemplateModule::create_collection_ex(origin1, data),
-			CommonError::<Test>::TotalCollectionsLimitExceeded
-		);
-	});
-}
-
-// Owned tokens by a single address. Positive test
-#[test]
-fn owned_tokens_bound() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.clone().into());
-		create_test_item(collection_id, &data.into());
-	});
-}
-
-// Owned tokens by a single address. Negotive test
-#[test]
-fn owned_tokens_bound_neg() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		for _ in 1..=MAX_TOKEN_OWNERSHIP {
-			let data = default_nft_data();
-			create_test_item(collection_id, &data.clone().into());
-		}
-
-		let data = default_nft_data();
-		assert_noop!(
-			TemplateModule::create_item(origin1, CollectionId(1), account(1), data.into())
-				.map_err(|e| e.error),
-			CommonError::<Test>::AccountTokenLimitExceeded
-		);
-	});
-}
-
-// Number of collection admins. Positive test
-#[test]
-fn collection_admins_bound() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1.clone(),
-			collection_id,
-			account(2)
-		));
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin1,
-			collection_id,
-			account(3)
-		));
-	});
-}
-
-// Number of collection admins. Negotive test
-#[test]
-fn collection_admins_bound_neg() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		for i in 0..COLLECTION_ADMINS_LIMIT {
-			assert_ok!(TemplateModule::add_collection_admin(
-				origin1.clone(),
-				collection_id,
-				account((2 + i).into())
-			));
-		}
-		assert_noop!(
-			TemplateModule::add_collection_admin(
-				origin1,
-				collection_id,
-				account((3 + COLLECTION_ADMINS_LIMIT).into())
-			),
-			CommonError::<Test>::CollectionAdminCountExceeded
-		);
-	});
-}
-// #endregion
-
-#[test]
-fn set_const_on_chain_schema() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::set_const_on_chain_schema(
-			origin1,
-			collection_id,
-			b"test const on chain schema".to_vec().try_into().unwrap()
-		));
-
-		assert_eq!(
-			<pallet_common::CollectionById<Test>>::get(collection_id)
-				.unwrap()
-				.const_on_chain_schema,
-			b"test const on chain schema".to_vec()
-		);
-		assert_eq!(
-			<pallet_common::CollectionById<Test>>::get(collection_id)
-				.unwrap()
-				.variable_on_chain_schema,
-			b"".to_vec()
-		);
-	});
-}
-
-#[test]
-fn set_variable_on_chain_schema() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		assert_ok!(TemplateModule::set_variable_on_chain_schema(
-			origin1,
-			collection_id,
-			b"test variable on chain schema"
-				.to_vec()
-				.try_into()
-				.unwrap()
-		));
-
-		assert_eq!(
-			<pallet_common::CollectionById<Test>>::get(collection_id)
-				.unwrap()
-				.const_on_chain_schema,
-			b"".to_vec()
-		);
-		assert_eq!(
-			<pallet_common::CollectionById<Test>>::get(collection_id)
-				.unwrap()
-				.variable_on_chain_schema,
-			b"test variable on chain schema".to_vec()
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(CollectionId(1), &data.into());
-
-		let variable_data = b"test data".to_vec();
-		assert_ok!(TemplateModule::set_variable_meta_data(
-			origin1,
-			collection_id,
-			TokenId(1),
-			variable_data.clone().try_into().unwrap()
-		));
-
-		assert_eq!(
-			<pallet_nonfungible::TokenData<Test>>::get((collection_id, 1))
-				.unwrap()
-				.variable_data,
-			variable_data
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_re_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		let variable_data = b"test data".to_vec();
-		assert_ok!(TemplateModule::set_variable_meta_data(
-			origin1,
-			collection_id,
-			TokenId(1),
-			variable_data.clone().try_into().unwrap()
-		));
-
-		assert_eq!(
-			<pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1))).variable_data,
-			variable_data
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_fungible_token_fails() {
-	new_test_ext().execute_with(|| {
-		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_fungible_data();
-		create_test_item(collection_id, &data.into());
-
-		let variable_data = b"test data".to_vec();
-		assert_noop!(
-			TemplateModule::set_variable_meta_data(
-				origin1,
-				collection_id,
-				TokenId(0),
-				variable_data.try_into().unwrap()
-			)
-			.map_err(|e| e.error),
-			<pallet_fungible::Error<Test>>::FungibleItemsDontHaveData
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {
-	new_test_ext().execute_with(|| {
-		//default_limits();
-
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin1.clone(),
-			collection_id,
-			MetaUpdatePermission::ItemOwner,
-		));
-
-		let variable_data = b"ten chars.".to_vec();
-		assert_ok!(TemplateModule::set_variable_meta_data(
-			origin1,
-			collection_id,
-			TokenId(1),
-			variable_data.clone().try_into().unwrap()
-		));
-
-		assert_eq!(
-			<pallet_nonfungible::TokenData<Test>>::get((collection_id, TokenId(1)))
-				.unwrap()
-				.variable_data,
-			variable_data
-		);
-	});
-}
-
-#[test]
-fn collection_transfer_flag_works() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		assert_ok!(TemplateModule::set_transfers_enabled_flag(
-			origin1,
-			collection_id,
-			true
-		));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-
-		let origin1 = Origin::signed(1);
-
-		// default scenario
-		assert_ok!(TemplateModule::transfer(
-			origin1,
-			account(2),
-			collection_id,
-			TokenId(1),
-			1
-		));
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			false
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),
-			true
-		);
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			0
-		);
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),
-			1
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_admin_flag() {
-	new_test_ext().execute_with(|| {
-		// default_limits();
-
-		let collection_id =
-			create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin2.clone(),
-			collection_id,
-			true
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin2.clone(),
-			collection_id,
-			account(1)
-		));
-
-		assert_ok!(TemplateModule::add_collection_admin(
-			origin2.clone(),
-			collection_id,
-			account(1)
-		));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin2.clone(),
-			collection_id,
-			MetaUpdatePermission::Admin,
-		));
-
-		let variable_data = b"test.".to_vec();
-		assert_ok!(TemplateModule::set_variable_meta_data(
-			origin1,
-			collection_id,
-			TokenId(1),
-			variable_data.clone().try_into().unwrap()
-		));
-
-		assert_eq!(
-			<pallet_nonfungible::TokenData<Test>>::get((collection_id, 1))
-				.unwrap()
-				.variable_data,
-			variable_data
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_admin_flag_neg() {
-	new_test_ext().execute_with(|| {
-		// default_limits();
-
-		let collection_id =
-			create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));
-
-		let origin1 = Origin::signed(1);
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin2.clone(),
-			collection_id,
-			true
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin2.clone(),
-			collection_id,
-			account(1)
-		));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin2.clone(),
-			collection_id,
-			MetaUpdatePermission::Admin,
-		));
-
-		let variable_data = b"test.".to_vec();
-		assert_noop!(
-			TemplateModule::set_variable_meta_data(
-				origin1,
-				collection_id,
-				TokenId(1),
-				variable_data.try_into().unwrap()
-			)
-			.map_err(|e| e.error),
-			CommonError::<Test>::NoPermission
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_flag_after_freeze() {
-	new_test_ext().execute_with(|| {
-		// default_limits();
-
-		let collection_id =
-			create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));
-
-		let origin2 = Origin::signed(2);
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin2.clone(),
-			collection_id,
-			MetaUpdatePermission::None,
-		));
-		assert_noop!(
-			TemplateModule::set_meta_update_permission_flag(
-				origin2.clone(),
-				collection_id,
-				MetaUpdatePermission::Admin
-			),
-			CommonError::<Test>::MetadataFlagFrozen
-		);
-	});
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_none_flag_neg() {
-	new_test_ext().execute_with(|| {
-		// default_limits();
-
-		let collection_id =
-			create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));
-		let origin1 = Origin::signed(1);
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-
-		assert_ok!(TemplateModule::set_meta_update_permission_flag(
-			origin1.clone(),
-			collection_id,
-			MetaUpdatePermission::None,
-		));
-
-		let variable_data = b"test.".to_vec();
-		assert_noop!(
-			TemplateModule::set_variable_meta_data(
-				origin1.clone(),
-				collection_id,
-				TokenId(1),
-				variable_data.try_into().unwrap()
-			)
-			.map_err(|e| e.error),
-			CommonError::<Test>::NoPermission
-		);
-	});
-}
-
-#[test]
-fn collection_transfer_flag_works_neg() {
-	new_test_ext().execute_with(|| {
-		let origin1 = Origin::signed(1);
-
-		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-		assert_ok!(TemplateModule::set_transfers_enabled_flag(
-			origin1,
-			collection_id,
-			false
-		));
-
-		let data = default_nft_data();
-		create_test_item(collection_id, &data.into());
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-
-		let origin1 = Origin::signed(1);
-
-		// default scenario
-		assert_noop!(
-			TemplateModule::transfer(origin1, account(2), CollectionId(1), TokenId(1), 1)
-				.map_err(|e| e.error),
-			CommonError::<Test>::TransferNotAllowed
-		);
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),
-			1
-		);
-		assert_eq!(
-			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),
-			0
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),
-			true
-		);
-		assert_eq!(
-			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),
-			false
-		);
-	});
-}
-
-#[test]
-fn collection_sponsoring() {
-	new_test_ext().execute_with(|| {
-		// default_limits();
-		let user1 = 1_u64;
-		let user2 = 777_u64;
-		let origin1 = Origin::signed(user1);
-		let origin2 = Origin::signed(user2);
-		let account2 = account(user2);
-
-		let collection_id =
-			create_test_collection_for_owner(&CollectionMode::NFT, user1, CollectionId(1));
-		assert_ok!(TemplateModule::set_collection_sponsor(
-			origin1.clone(),
-			collection_id,
-			user1
-		));
-		assert_ok!(TemplateModule::confirm_sponsorship(
-			origin1.clone(),
-			collection_id
-		));
-
-		// Expect error while have no permissions
-		assert!(TemplateModule::create_item(
-			origin2.clone(),
-			collection_id,
-			account2.clone(),
-			default_nft_data().into()
-		)
-		.is_err());
-
-		assert_ok!(TemplateModule::set_public_access_mode(
-			origin1.clone(),
-			collection_id,
-			AccessMode::AllowList
-		));
-		assert_ok!(TemplateModule::add_to_allow_list(
-			origin1.clone(),
-			collection_id,
-			account2.clone()
-		));
-		assert_ok!(TemplateModule::set_mint_permission(
-			origin1.clone(),
-			collection_id,
-			true
-		));
-
-		assert_ok!(TemplateModule::create_item(
-			origin2,
-			collection_id,
-			account2,
-			default_nft_data().into()
-		));
-	});
-}
modifiedruntime/common/Cargo.tomldiffbeforeafterboth
--- a/runtime/common/Cargo.toml
+++ b/runtime/common/Cargo.toml
@@ -104,4 +104,6 @@
 branch = "unique-polkadot-v0.9.20"
 
 [dependencies]
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.18-2" }
+evm-coder = { default-features = false, path = '../../crates/evm-coder' }
+up-sponsorship = { default-features = false, git = "https://github.com/UniqueNetwork/pallet-sponsoring", branch = 'polkadot-v0.9.18' }
addedruntime/common/src/eth_sponsoring.rsdiffbeforeafterboth
--- /dev/null
+++ b/runtime/common/src/eth_sponsoring.rs
@@ -0,0 +1,107 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+//! Implements EVM sponsoring logic via TransactionValidityHack
+
+use evm_coder::{Call, abi::AbiReader};
+use pallet_common::{CollectionHandle, eth::map_eth_to_id};
+use sp_core::H160;
+use sp_std::prelude::*;
+use up_sponsorship::SponsorshipHandler;
+use core::marker::PhantomData;
+use core::convert::TryInto;
+use pallet_evm::account::CrossAccountId;
+use up_data_structs::{TokenId, CreateItemData, CreateNftData, CollectionMode};
+use pallet_unique::Config as UniqueConfig;
+
+use crate::sponsoring::*;
+
+use pallet_nonfungible::erc::{
+	UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call,
+};
+use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};
+use pallet_fungible::Config as FungibleConfig;
+use pallet_nonfungible::Config as NonfungibleConfig;
+use pallet_refungible::Config as RefungibleConfig;
+
+pub struct UniqueEthSponsorshipHandler<T: UniqueConfig>(PhantomData<*const T>);
+impl<T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>
+	SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)> for UniqueEthSponsorshipHandler<T>
+{
+	fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {
+		let collection_id = map_eth_to_id(&call.0)?;
+		let collection = <CollectionHandle<T>>::new(collection_id)?;
+		let sponsor = collection.sponsorship.sponsor()?.clone();
+		let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;
+		Some(T::CrossAccountId::from_sub(match &collection.mode {
+			CollectionMode::NFT => {
+				let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;
+				match call {
+					UniqueNFTCall::ERC721UniqueExtensions(
+						ERC721UniqueExtensionsCall::Transfer { token_id, .. },
+					) => {
+						let token_id: TokenId = token_id.try_into().ok()?;
+						withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)
+					}
+					UniqueNFTCall::ERC721Mintable(
+						ERC721MintableCall::Mint { token_id, .. }
+						| ERC721MintableCall::MintWithTokenUri { token_id, .. },
+					) => {
+						let _token_id: TokenId = token_id.try_into().ok()?;
+						withdraw_create_item::<T>(
+							&collection,
+							&who,
+							&CreateItemData::NFT(CreateNftData::default()),
+						)
+						.map(|()| sponsor)
+					}
+					UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {
+						let token_id: TokenId = token_id.try_into().ok()?;
+						let from = T::CrossAccountId::from_eth(from);
+						withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)
+					}
+					UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {
+						let token_id: TokenId = token_id.try_into().ok()?;
+						withdraw_approve::<T>(&collection, who.as_sub(), &token_id)
+							.map(|()| sponsor)
+					}
+					_ => None,
+				}
+			}
+			CollectionMode::Fungible(_) => {
+				let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;
+				#[allow(clippy::single_match)]
+				match call {
+					UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
+						withdraw_transfer::<T>(&collection, who, &TokenId::default())
+							.map(|()| sponsor)
+					}
+					UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {
+						let from = T::CrossAccountId::from_eth(from);
+						withdraw_transfer::<T>(&collection, &from, &TokenId::default())
+							.map(|()| sponsor)
+					}
+					UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {
+						withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())
+							.map(|()| sponsor)
+					}
+					_ => None,
+				}
+			}
+			_ => None,
+		}?))
+	}
+}
modifiedruntime/common/src/lib.rsdiffbeforeafterboth
--- a/runtime/common/src/lib.rs
+++ b/runtime/common/src/lib.rs
@@ -2,5 +2,8 @@
 
 pub mod constants;
 pub mod dispatch;
+pub mod eth_sponsoring;
 pub mod runtime_apis;
+pub mod sponsoring;
 pub mod types;
+pub mod weights;
addedruntime/common/src/sponsoring.rsdiffbeforeafterboth
--- /dev/null
+++ b/runtime/common/src/sponsoring.rs
@@ -0,0 +1,375 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+use core::marker::PhantomData;
+use up_sponsorship::SponsorshipHandler;
+use frame_support::{
+	traits::{IsSubType},
+	storage::{StorageMap, StorageDoubleMap, StorageNMap},
+};
+use up_data_structs::{
+	CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,
+	NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode,
+	CreateItemData,
+};
+use sp_runtime::traits::Saturating;
+use pallet_common::{CollectionHandle};
+use pallet_evm::account::CrossAccountId;
+use pallet_unique::{
+	Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,
+	NftApproveBasket, VariableMetaDataBasket, CreateItemBasket, ReFungibleTransferBasket,
+	FungibleTransferBasket, NftTransferBasket,
+};
+use pallet_fungible::Config as FungibleConfig;
+use pallet_nonfungible::Config as NonfungibleConfig;
+use pallet_refungible::Config as RefungibleConfig;
+
+pub fn withdraw_transfer<
+	T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+>(
+	collection: &CollectionHandle<T>,
+	who: &T::CrossAccountId,
+	item_id: &TokenId,
+) -> Option<()> {
+	// 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;
+			}
+		}
+	}
+
+	// sponsor timeout
+	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+	let limit = collection
+		.limits
+		.sponsor_transfer_timeout(match collection.mode {
+			CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
+			CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+			CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+		});
+
+	let last_tx_block = match collection.mode {
+		CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, item_id),
+		CollectionMode::Fungible(_) => {
+			<FungibleTransferBasket<T>>::get(collection.id, who.as_sub())
+		}
+		CollectionMode::ReFungible => {
+			<ReFungibleTransferBasket<T>>::get((collection.id, item_id, who.as_sub()))
+		}
+	};
+
+	if let Some(last_tx_block) = last_tx_block {
+		let timeout = last_tx_block + limit.into();
+		if block_number < timeout {
+			return None;
+		}
+	}
+
+	match collection.mode {
+		CollectionMode::NFT => <NftTransferBasket<T>>::insert(collection.id, item_id, block_number),
+		CollectionMode::Fungible(_) => {
+			<FungibleTransferBasket<T>>::insert(collection.id, who.as_sub(), block_number)
+		}
+		CollectionMode::ReFungible => <ReFungibleTransferBasket<T>>::insert(
+			(collection.id, item_id, who.as_sub()),
+			block_number,
+		),
+	};
+
+	Some(())
+}
+
+pub fn withdraw_create_item<
+	T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+>(
+	collection: &CollectionHandle<T>,
+	who: &T::CrossAccountId,
+	_properties: &CreateItemData,
+) -> Option<()> {
+	if _properties.data_size() as u32 > collection.limits.sponsored_data_size() {
+		return None;
+	}
+
+	// sponsor timeout
+	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+	let limit = collection
+		.limits
+		.sponsor_transfer_timeout(match _properties {
+			CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,
+			CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+			CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+		});
+
+	if let Some(last_tx_block) = <CreateItemBasket<T>>::get((collection.id, who.as_sub())) {
+		let timeout = last_tx_block + limit.into();
+		if block_number < timeout {
+			return None;
+		}
+	}
+
+	CreateItemBasket::<T>::insert((collection.id, who.as_sub()), block_number);
+
+	Some(())
+}
+
+pub fn withdraw_set_variable_meta_data<
+	T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+>(
+	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: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>(
+	collection: &CollectionHandle<T>,
+	who: &T::AccountId,
+	item_id: &TokenId,
+) -> Option<()> {
+	// sponsor timeout
+	let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+	let limit = collection.limits.sponsor_approve_timeout();
+
+	let last_tx_block = match collection.mode {
+		CollectionMode::NFT => <NftApproveBasket<T>>::get(collection.id, item_id),
+		CollectionMode::Fungible(_) => <FungibleApproveBasket<T>>::get(collection.id, who),
+		CollectionMode::ReFungible => {
+			<RefungibleApproveBasket<T>>::get((collection.id, item_id, who))
+		}
+	};
+
+	if let Some(last_tx_block) = last_tx_block {
+		let timeout = last_tx_block + limit.into();
+		if block_number < timeout {
+			return None;
+		}
+	}
+
+	match collection.mode {
+		CollectionMode::NFT => <NftApproveBasket<T>>::insert(collection.id, item_id, block_number),
+		CollectionMode::Fungible(_) => {
+			<FungibleApproveBasket<T>>::insert(collection.id, who, block_number)
+		}
+		CollectionMode::ReFungible => {
+			<RefungibleApproveBasket<T>>::insert((collection.id, item_id, who), block_number)
+		}
+	};
+
+	Some(())
+}
+
+fn load<T: UniqueConfig>(id: CollectionId) -> Option<(T::AccountId, CollectionHandle<T>)> {
+	let collection = CollectionHandle::new(id)?;
+	let sponsor = collection.sponsorship.sponsor().cloned()?;
+	Some((sponsor, collection))
+}
+
+pub struct UniqueSponsorshipHandler<T>(PhantomData<T>);
+impl<T, C> SponsorshipHandler<T::AccountId, C> for UniqueSponsorshipHandler<T>
+where
+	T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig,
+	C: IsSubType<UniqueCall<T>>,
+{
+	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {
+		match IsSubType::<UniqueCall<T>>::is_sub_type(call)? {
+			UniqueCall::create_item {
+				collection_id,
+				data,
+				..
+			} => {
+				let (sponsor, collection) = load(*collection_id)?;
+				withdraw_create_item::<T>(
+					&collection,
+					&T::CrossAccountId::from_sub(who.clone()),
+					data,
+				)
+				.map(|()| sponsor)
+			}
+			UniqueCall::transfer {
+				collection_id,
+				item_id,
+				..
+			} => {
+				let (sponsor, collection) = load(*collection_id)?;
+				withdraw_transfer::<T>(
+					&collection,
+					&T::CrossAccountId::from_sub(who.clone()),
+					item_id,
+				)
+				.map(|()| sponsor)
+			}
+			UniqueCall::transfer_from {
+				collection_id,
+				item_id,
+				from,
+				..
+			} => {
+				let (sponsor, collection) = load(*collection_id)?;
+				withdraw_transfer::<T>(&collection, from, item_id).map(|()| sponsor)
+			}
+			UniqueCall::approve {
+				collection_id,
+				item_id,
+				..
+			} => {
+				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,
+		}
+	}
+}
+
+use crate::SponsorshipPredict;
+pub struct UniqueSponsorshipPredict<T>(PhantomData<T>);
+
+impl<T> SponsorshipPredict<T> for UniqueSponsorshipPredict<T>
+where
+	T: Config,
+{
+	fn predict(collection_id: CollectionId, who: T::CrossAccountId, token: TokenId) -> Option<u64>
+	where
+		u64: From<<T as frame_system::Config>::BlockNumber>,
+	{
+		let collection = <CollectionHandle<T>>::try_get(collection_id).ok()?;
+		let _ = collection.sponsorship.sponsor()?;
+
+		// sponsor timeout
+		let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+		let limit = collection
+			.limits
+			.sponsor_transfer_timeout(match collection.mode {
+				CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
+				CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+				CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+			});
+
+		let last_tx_block = match collection.mode {
+			CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, token),
+			CollectionMode::Fungible(_) => {
+				<FungibleTransferBasket<T>>::get(collection.id, who.as_sub())
+			}
+			CollectionMode::ReFungible => {
+				<ReFungibleTransferBasket<T>>::get((collection.id, token, who.as_sub()))
+			}
+		};
+
+		if let Some(last_tx_block) = last_tx_block {
+			return Some(
+				last_tx_block
+					.saturating_add(limit.into())
+					.saturating_sub(block_number)
+					.into(),
+			);
+		}
+
+		let token_exists = match collection.mode {
+			CollectionMode::NFT => {
+				<pallet_nonfungible::TokenData<T>>::contains_key((collection.id, token))
+			}
+			CollectionMode::Fungible(_) => true,
+			CollectionMode::ReFungible => {
+				<pallet_refungible::TotalSupply<T>>::contains_key((collection.id, token))
+			}
+		};
+
+		if token_exists {
+			Some(0)
+		} else {
+			None
+		}
+	}
+}
addedruntime/common/src/weights.rsdiffbeforeafterboth
--- /dev/null
+++ b/runtime/common/src/weights.rs
@@ -0,0 +1,76 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+use core::marker::PhantomData;
+use frame_support::{weights::Weight};
+use pallet_common::{CommonWeightInfo, dispatch::dispatch_weight};
+
+use pallet_fungible::{Config as FungibleConfig, common::CommonWeights as FungibleWeights};
+use pallet_nonfungible::{Config as NonfungibleConfig, common::CommonWeights as NonfungibleWeights};
+use pallet_refungible::{Config as RefungibleConfig, common::CommonWeights as RefungibleWeights};
+use up_data_structs::CreateItemExData;
+
+macro_rules! max_weight_of {
+	($method:ident ( $($args:tt)* )) => {
+		<FungibleWeights<T>>::$method($($args)*)
+		.max(<NonfungibleWeights<T>>::$method($($args)*))
+		.max(<RefungibleWeights<T>>::$method($($args)*))
+	};
+}
+
+pub struct CommonWeights<T>(PhantomData<T>)
+where
+	T: FungibleConfig + NonfungibleConfig + RefungibleConfig;
+impl<T> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T>
+where
+	T: FungibleConfig + NonfungibleConfig + RefungibleConfig,
+{
+	fn create_item() -> Weight {
+		dispatch_weight::<T>() + max_weight_of!(create_item())
+	}
+
+	fn create_multiple_items(amount: u32) -> Weight {
+		dispatch_weight::<T>() + max_weight_of!(create_multiple_items(amount))
+	}
+
+	fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {
+		dispatch_weight::<T>() + max_weight_of!(create_multiple_items_ex(data))
+	}
+
+	fn burn_item() -> Weight {
+		dispatch_weight::<T>() + max_weight_of!(burn_item())
+	}
+
+	fn transfer() -> Weight {
+		dispatch_weight::<T>() + max_weight_of!(transfer())
+	}
+
+	fn approve() -> Weight {
+		dispatch_weight::<T>() + max_weight_of!(approve())
+	}
+
+	fn transfer_from() -> Weight {
+		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/opal/src/lib.rsdiffbeforeafterboth
--- a/runtime/opal/src/lib.rs
+++ b/runtime/opal/src/lib.rs
@@ -120,6 +120,9 @@
 	types::*,
 	constants::*,
 	dispatch::{CollectionDispatchT, CollectionDispatch},
+	sponsoring::UniqueSponsorshipHandler,
+	eth_sponsoring::UniqueEthSponsorshipHandler,
+	weights::CommonWeights,
 };
 
 pub const RUNTIME_NAME: &str = "opal";
@@ -902,6 +905,7 @@
 impl pallet_unique::Config for Runtime {
 	type Event = Event;
 	type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
+	type CommonWeightInfo = CommonWeights<Self>;
 }
 
 parameter_types! {
@@ -923,11 +927,11 @@
 // }
 
 type EvmSponsorshipHandler = (
-	pallet_unique::UniqueEthSponsorshipHandler<Runtime>,
+	UniqueEthSponsorshipHandler<Runtime>,
 	pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,
 );
 type SponsorshipHandler = (
-	pallet_unique::UniqueSponsorshipHandler<Runtime>,
+	UniqueSponsorshipHandler<Runtime>,
 	//pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,
 	pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,
 );
addedruntime/tests/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/runtime/tests/Cargo.toml
@@ -0,0 +1,37 @@
+[package]
+name = "tests"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+unique-runtime-common = { path = '../common' }
+up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
+
+sp-core = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.18' }
+sp-std = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.18' }
+sp-io = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.18' }
+sp-runtime = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.18' }
+
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.18-2" }
+
+frame-support = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.18' }
+frame-system = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.18' }
+
+pallet-balances = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.18' }
+pallet-transaction-payment = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.18' }
+pallet-timestamp = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.18' }
+
+pallet-evm = { default-features = false, git = 'https://github.com/uniquenetwork/frontier.git', branch = 'unique-polkadot-v0.9.18-2' }
+pallet-ethereum = { default-features = false, git = 'https://github.com/uniquenetwork/frontier.git', branch = 'unique-polkadot-v0.9.18-2' }
+
+pallet-common = { path = '../../pallets/common' }
+pallet-structure = { path = '../../pallets/structure' }
+pallet-fungible = { path = '../../pallets/fungible' }
+pallet-nonfungible = { path = '../../pallets/nonfungible' }
+pallet-refungible = { path = '../../pallets/refungible' }
+pallet-unique = { path = '../../pallets/unique' }
+
+pallet-evm-coder-substrate = { path = '../../pallets/evm-coder-substrate' }
+
+parity-scale-codec = "*"
+scale-info = "*"
addedruntime/tests/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/runtime/tests/src/lib.rs
@@ -0,0 +1,238 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+#![allow(clippy::from_over_into)]
+
+use sp_core::{H160, H256};
+use frame_support::{
+	parameter_types,
+	traits::{Everything, ConstU32},
+	weights::IdentityFee,
+};
+use sp_runtime::{
+	traits::{BlakeTwo256, IdentityLookup},
+	testing::Header,
+};
+use pallet_transaction_payment::{CurrencyAdapter};
+use frame_system as system;
+use pallet_evm::{AddressMapping, runner::stack::MaybeMirroredLog, account::CrossAccountId};
+use fp_evm_mapping::EvmBackwardsAddressMapping;
+use parity_scale_codec::{Encode, Decode, MaxEncodedLen};
+use scale_info::TypeInfo;
+
+use unique_runtime_common::{dispatch::CollectionDispatchT, weights::CommonWeights};
+use up_data_structs::mapping::{CrossTokenAddressMapping, EvmTokenAddressMapping};
+
+type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
+type Block = frame_system::mocking::MockBlock<Test>;
+
+#[cfg(test)]
+mod tests;
+
+// Configure a mock runtime to test the pallet.
+frame_support::construct_runtime!(
+	pub enum Test where
+		Block = Block,
+		NodeBlock = Block,
+		UncheckedExtrinsic = UncheckedExtrinsic,
+	{
+		System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
+		Unique: pallet_unique::{Pallet, Call, Storage},
+		Balances: pallet_balances::{Pallet, Call, Storage},
+		Common: pallet_common::{Pallet, Storage, Event<T>},
+		Fungible: pallet_fungible::{Pallet, Storage},
+		Refungible: pallet_refungible::{Pallet, Storage},
+		Nonfungible: pallet_nonfungible::{Pallet, Storage},
+	}
+);
+
+parameter_types! {
+	pub const BlockHashCount: u64 = 250;
+	pub const SS58Prefix: u8 = 42;
+}
+
+impl system::Config for Test {
+	type BaseCallFilter = Everything;
+	type BlockWeights = ();
+	type BlockLength = ();
+	type DbWeight = ();
+	type Origin = Origin;
+	type Call = Call;
+	type Index = u64;
+	type BlockNumber = u64;
+	type Hash = H256;
+	type Hashing = BlakeTwo256;
+	type AccountId = u64;
+	type Lookup = IdentityLookup<Self::AccountId>;
+	type Header = Header;
+	type Event = ();
+	type BlockHashCount = BlockHashCount;
+	type Version = ();
+	type PalletInfo = PalletInfo;
+	type AccountData = pallet_balances::AccountData<u64>;
+	type OnNewAccount = ();
+	type OnKilledAccount = ();
+	type SystemWeightInfo = ();
+	type SS58Prefix = SS58Prefix;
+	type OnSetCode = ();
+	type MaxConsumers = ConstU32<16>;
+}
+
+parameter_types! {
+	pub const ExistentialDeposit: u64 = 1;
+	pub const MaxLocks: u32 = 50;
+}
+//frame_system::Module<Test>;
+impl pallet_balances::Config for Test {
+	type AccountStore = System;
+	type Balance = u64;
+	type DustRemoval = ();
+	type Event = ();
+	type ExistentialDeposit = ExistentialDeposit;
+	type WeightInfo = ();
+	type MaxLocks = MaxLocks;
+	type MaxReserves = ();
+	type ReserveIdentifier = [u8; 8];
+}
+
+parameter_types! {
+	pub const OperationalFeeMultiplier: u8 = 5;
+}
+
+impl pallet_transaction_payment::Config for Test {
+	type OnChargeTransaction = CurrencyAdapter<pallet_balances::Pallet<Test>, ()>;
+	type LengthToFee = IdentityFee<u64>;
+	type WeightToFee = IdentityFee<u64>;
+	type FeeMultiplierUpdate = ();
+	type OperationalFeeMultiplier = OperationalFeeMultiplier;
+}
+
+parameter_types! {
+	pub const MinimumPeriod: u64 = 1;
+}
+impl pallet_timestamp::Config for Test {
+	type Moment = u64;
+	type OnTimestampSet = ();
+	type MinimumPeriod = MinimumPeriod;
+	type WeightInfo = ();
+}
+
+parameter_types! {
+	pub const CollectionCreationPrice: u32 = 100;
+	pub TreasuryAccountId: u64 = 1234;
+	pub EthereumChainId: u32 = 1111;
+}
+
+pub struct TestEvmAddressMapping;
+impl AddressMapping<u64> for TestEvmAddressMapping {
+	fn into_account_id(_addr: sp_core::H160) -> u64 {
+		unimplemented!()
+	}
+}
+
+pub struct TestEvmBackwardsAddressMapping;
+impl EvmBackwardsAddressMapping<u64> for TestEvmBackwardsAddressMapping {
+	fn from_account_id(_account_id: u64) -> sp_core::H160 {
+		unimplemented!()
+	}
+}
+
+#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, TypeInfo, MaxEncodedLen)]
+pub struct TestCrossAccountId(u64, sp_core::H160);
+impl CrossAccountId<u64> for TestCrossAccountId {
+	fn as_sub(&self) -> &u64 {
+		&self.0
+	}
+	fn as_eth(&self) -> &sp_core::H160 {
+		&self.1
+	}
+	fn from_sub(sub: u64) -> Self {
+		let mut eth = [0; 20];
+		eth[12..20].copy_from_slice(&sub.to_be_bytes());
+		Self(sub, sp_core::H160(eth))
+	}
+	fn from_eth(eth: sp_core::H160) -> Self {
+		let mut sub_raw = [0; 8];
+		sub_raw.copy_from_slice(&eth.0[0..8]);
+		let sub = u64::from_be_bytes(sub_raw);
+		Self(sub, eth)
+	}
+	fn conv_eq(&self, other: &Self) -> bool {
+		self.as_sub() == other.as_sub()
+	}
+}
+
+impl Default for TestCrossAccountId {
+	fn default() -> Self {
+		Self::from_sub(0)
+	}
+}
+
+pub struct TestEtheremTransactionSender;
+impl pallet_ethereum::EthereumTransactionSender for TestEtheremTransactionSender {
+	fn submit_logs_transaction(_source: H160, _logs: Vec<MaybeMirroredLog>) {}
+}
+
+impl pallet_evm_coder_substrate::Config for Test {
+	type EthereumTransactionSender = TestEtheremTransactionSender;
+	type GasWeightMapping = ();
+}
+
+impl pallet_common::Config for Test {
+	type Event = ();
+	type Currency = Balances;
+	type CollectionCreationPrice = CollectionCreationPrice;
+	type TreasuryAccountId = TreasuryAccountId;
+
+	type CollectionDispatch = CollectionDispatchT<Self>;
+	type EvmTokenAddressMapping = EvmTokenAddressMapping;
+	type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
+}
+
+impl pallet_evm::account::Config for Test {
+	type CrossAccountId = TestCrossAccountId;
+	type EvmAddressMapping = TestEvmAddressMapping;
+	type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;
+}
+
+impl pallet_structure::Config for Test {
+	type WeightInfo = ();
+	type Event = ();
+	type Call = Call;
+}
+impl pallet_fungible::Config for Test {
+	type WeightInfo = ();
+}
+impl pallet_refungible::Config for Test {
+	type WeightInfo = ();
+}
+impl pallet_nonfungible::Config for Test {
+	type WeightInfo = ();
+}
+
+impl pallet_unique::Config for Test {
+	type Event = ();
+	type WeightInfo = ();
+	type CommonWeightInfo = CommonWeights<Self>;
+}
+
+// Build genesis storage according to the mock runtime.
+pub fn new_test_ext() -> sp_io::TestExternalities {
+	system::GenesisConfig::default()
+		.build_storage::<Test>()
+		.unwrap()
+		.into()
+}
addedruntime/tests/src/tests.rsdiffbeforeafterboth
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		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		assert_eq!(2427			<pallet_common::CollectionData<Test>>::get((2428				collection_id,2429				CollectionField::VariableOnChainSchema2430			)),2431			b"".to_vec()2432		);2433	});2434}24352436#[test]2437fn set_variable_on_chain_schema() {2438	new_test_ext().execute_with(|| {2439		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24402441		let origin1 = Origin::signed(1);2442		assert_ok!(Unique::set_variable_on_chain_schema(2443			origin1,2444			collection_id,2445			b"test variable on chain schema"2446				.to_vec()2447				.try_into()2448				.unwrap()2449		));24502451		assert_eq!(2452			<pallet_common::CollectionData<Test>>::get((2453				collection_id,2454				CollectionField::ConstOnChainSchema2455			)),2456			b"".to_vec()2457		);2458		assert_eq!(2459			<pallet_common::CollectionData<Test>>::get((2460				collection_id,2461				CollectionField::VariableOnChainSchema2462			)),2463			b"test variable on chain schema".to_vec()2464		);2465	});2466}24672468#[test]2469fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {2470	new_test_ext().execute_with(|| {2471		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24722473		let origin1 = Origin::signed(1);24742475		let data = default_nft_data();2476		create_test_item(CollectionId(1), &data.into());24772478		let variable_data = b"test data".to_vec();2479		assert_ok!(Unique::set_variable_meta_data(2480			origin1,2481			collection_id,2482			TokenId(1),2483			variable_data.clone().try_into().unwrap()2484		));24852486		assert_eq!(2487			<pallet_nonfungible::TokenData<Test>>::get((collection_id, 1))2488				.unwrap()2489				.variable_data,2490			variable_data2491		);2492	});2493}24942495#[test]2496fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {2497	new_test_ext().execute_with(|| {2498		let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));24992500		let origin1 = Origin::signed(1);25012502		let data = default_re_fungible_data();2503		create_test_item(collection_id, &data.into());25042505		let variable_data = b"test data".to_vec();2506		assert_ok!(Unique::set_variable_meta_data(2507			origin1,2508			collection_id,2509			TokenId(1),2510			variable_data.clone().try_into().unwrap()2511		));25122513		assert_eq!(2514			<pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1))).variable_data,2515			variable_data2516		);2517	});2518}25192520#[test]2521fn set_variable_meta_data_on_fungible_token_fails() {2522	new_test_ext().execute_with(|| {2523		let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));25242525		let origin1 = Origin::signed(1);25262527		let data = default_fungible_data();2528		create_test_item(collection_id, &data.into());25292530		let variable_data = b"test data".to_vec();2531		assert_noop!(2532			Unique::set_variable_meta_data(2533				origin1,2534				collection_id,2535				TokenId(0),2536				variable_data.try_into().unwrap()2537			)2538			.map_err(|e| e.error),2539			<pallet_fungible::Error<Test>>::FungibleItemsDontHaveData2540		);2541	});2542}25432544#[test]2545fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {2546	new_test_ext().execute_with(|| {2547		//default_limits();25482549		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));25502551		let origin1 = Origin::signed(1);25522553		let data = default_nft_data();2554		create_test_item(collection_id, &data.into());25552556		assert_ok!(Unique::set_meta_update_permission_flag(2557			origin1.clone(),2558			collection_id,2559			MetaUpdatePermission::ItemOwner,2560		));25612562		let variable_data = b"ten chars.".to_vec();2563		assert_ok!(Unique::set_variable_meta_data(2564			origin1,2565			collection_id,2566			TokenId(1),2567			variable_data.clone().try_into().unwrap()2568		));25692570		assert_eq!(2571			<pallet_nonfungible::TokenData<Test>>::get((collection_id, TokenId(1)))2572				.unwrap()2573				.variable_data,2574			variable_data2575		);2576	});2577}25782579#[test]2580fn collection_transfer_flag_works() {2581	new_test_ext().execute_with(|| {2582		let origin1 = Origin::signed(1);25832584		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2585		assert_ok!(Unique::set_transfers_enabled_flag(2586			origin1,2587			collection_id,2588			true2589		));25902591		let data = default_nft_data();2592		create_test_item(collection_id, &data.into());2593		assert_eq!(2594			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2595			12596		);2597		assert_eq!(2598			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2599			true2600		);26012602		let origin1 = Origin::signed(1);26032604		// default scenario2605		assert_ok!(Unique::transfer(2606			origin1,2607			account(2),2608			collection_id,2609			TokenId(1),2610			12611		));2612		assert_eq!(2613			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2614			false2615		);2616		assert_eq!(2617			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2618			true2619		);2620		assert_eq!(2621			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2622			02623		);2624		assert_eq!(2625			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2626			12627		);2628	});2629}26302631#[test]2632fn set_variable_meta_data_on_nft_with_admin_flag() {2633	new_test_ext().execute_with(|| {2634		// default_limits();26352636		let collection_id =2637			create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));26382639		let origin1 = Origin::signed(1);2640		let origin2 = Origin::signed(2);26412642		assert_ok!(Unique::set_mint_permission(2643			origin2.clone(),2644			collection_id,2645			true2646		));2647		assert_ok!(Unique::add_to_allow_list(2648			origin2.clone(),2649			collection_id,2650			account(1)2651		));26522653		assert_ok!(Unique::add_collection_admin(2654			origin2.clone(),2655			collection_id,2656			account(1)2657		));26582659		let data = default_nft_data();2660		create_test_item(collection_id, &data.into());26612662		assert_ok!(Unique::set_meta_update_permission_flag(2663			origin2.clone(),2664			collection_id,2665			MetaUpdatePermission::Admin,2666		));26672668		let variable_data = b"test.".to_vec();2669		assert_ok!(Unique::set_variable_meta_data(2670			origin1,2671			collection_id,2672			TokenId(1),2673			variable_data.clone().try_into().unwrap()2674		));26752676		assert_eq!(2677			<pallet_nonfungible::TokenData<Test>>::get((collection_id, 1))2678				.unwrap()2679				.variable_data,2680			variable_data2681		);2682	});2683}26842685#[test]2686fn set_variable_meta_data_on_nft_with_admin_flag_neg() {2687	new_test_ext().execute_with(|| {2688		// default_limits();26892690		let collection_id =2691			create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));26922693		let origin1 = Origin::signed(1);2694		let origin2 = Origin::signed(2);26952696		assert_ok!(Unique::set_mint_permission(2697			origin2.clone(),2698			collection_id,2699			true2700		));2701		assert_ok!(Unique::add_to_allow_list(2702			origin2.clone(),2703			collection_id,2704			account(1)2705		));27062707		let data = default_nft_data();2708		create_test_item(collection_id, &data.into());27092710		assert_ok!(Unique::set_meta_update_permission_flag(2711			origin2.clone(),2712			collection_id,2713			MetaUpdatePermission::Admin,2714		));27152716		let variable_data = b"test.".to_vec();2717		assert_noop!(2718			Unique::set_variable_meta_data(2719				origin1,2720				collection_id,2721				TokenId(1),2722				variable_data.try_into().unwrap()2723			)2724			.map_err(|e| e.error),2725			CommonError::<Test>::NoPermission2726		);2727	});2728}27292730#[test]2731fn set_variable_meta_flag_after_freeze() {2732	new_test_ext().execute_with(|| {2733		// default_limits();27342735		let collection_id =2736			create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));27372738		let origin2 = Origin::signed(2);27392740		assert_ok!(Unique::set_meta_update_permission_flag(2741			origin2.clone(),2742			collection_id,2743			MetaUpdatePermission::None,2744		));2745		assert_noop!(2746			Unique::set_meta_update_permission_flag(2747				origin2.clone(),2748				collection_id,2749				MetaUpdatePermission::Admin2750			),2751			CommonError::<Test>::MetadataFlagFrozen2752		);2753	});2754}27552756#[test]2757fn set_variable_meta_data_on_nft_with_none_flag_neg() {2758	new_test_ext().execute_with(|| {2759		// default_limits();27602761		let collection_id =2762			create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));2763		let origin1 = Origin::signed(1);27642765		let data = default_nft_data();2766		create_test_item(collection_id, &data.into());27672768		assert_ok!(Unique::set_meta_update_permission_flag(2769			origin1.clone(),2770			collection_id,2771			MetaUpdatePermission::None,2772		));27732774		let variable_data = b"test.".to_vec();2775		assert_noop!(2776			Unique::set_variable_meta_data(2777				origin1.clone(),2778				collection_id,2779				TokenId(1),2780				variable_data.try_into().unwrap()2781			)2782			.map_err(|e| e.error),2783			CommonError::<Test>::NoPermission2784		);2785	});2786}27872788#[test]2789fn collection_transfer_flag_works_neg() {2790	new_test_ext().execute_with(|| {2791		let origin1 = Origin::signed(1);27922793		let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2794		assert_ok!(Unique::set_transfers_enabled_flag(2795			origin1,2796			collection_id,2797			false2798		));27992800		let data = default_nft_data();2801		create_test_item(collection_id, &data.into());2802		assert_eq!(2803			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2804			12805		);2806		assert_eq!(2807			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2808			true2809		);28102811		let origin1 = Origin::signed(1);28122813		// default scenario2814		assert_noop!(2815			Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 1)2816				.map_err(|e| e.error),2817			CommonError::<Test>::TransferNotAllowed2818		);2819		assert_eq!(2820			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2821			12822		);2823		assert_eq!(2824			<pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2825			02826		);2827		assert_eq!(2828			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2829			true2830		);2831		assert_eq!(2832			<pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2833			false2834		);2835	});2836}28372838#[test]2839fn collection_sponsoring() {2840	new_test_ext().execute_with(|| {2841		// default_limits();2842		let user1 = 1_u64;2843		let user2 = 777_u64;2844		let origin1 = Origin::signed(user1);2845		let origin2 = Origin::signed(user2);2846		let account2 = account(user2);28472848		let collection_id =2849			create_test_collection_for_owner(&CollectionMode::NFT, user1, CollectionId(1));2850		assert_ok!(Unique::set_collection_sponsor(2851			origin1.clone(),2852			collection_id,2853			user12854		));2855		assert_ok!(Unique::confirm_sponsorship(origin1.clone(), collection_id));28562857		// Expect error while have no permissions2858		assert!(Unique::create_item(2859			origin2.clone(),2860			collection_id,2861			account2.clone(),2862			default_nft_data().into()2863		)2864		.is_err());28652866		assert_ok!(Unique::set_public_access_mode(2867			origin1.clone(),2868			collection_id,2869			AccessMode::AllowList2870		));2871		assert_ok!(Unique::add_to_allow_list(2872			origin1.clone(),2873			collection_id,2874			account2.clone()2875		));2876		assert_ok!(Unique::set_mint_permission(2877			origin1.clone(),2878			collection_id,2879			true2880		));28812882		assert_ok!(Unique::create_item(2883			origin2,2884			collection_id,2885			account2,2886			default_nft_data().into()2887		));2888	});2889}