git.delta.rocks / unique-network / refs/commits / 32d10d5b642a

difftreelog

Merge branch 'develop' into feature/CORE-386_1

bugrazoid2022-06-10parents: #db8b9ba #bb7c8cc.patch.diff
in: master

54 files changed

modifiedMakefilediffbeforeafterboth
--- a/Makefile
+++ b/Makefile
@@ -93,5 +93,9 @@
 bench-structure:
 	make _bench PALLET=structure
 
+.PHONY: bench-rmrk-core
+bench-rmrk-core:
+	make _bench PALLET=proxy-rmrk-core
+
 .PHONY: bench
-bench: bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible
+bench: bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-rmrk-core
modifiedpallets/common/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/common/src/benchmarking.rs
+++ b/pallets/common/src/benchmarking.rs
@@ -109,7 +109,7 @@
 	create_collection_raw(
 		owner,
 		CollectionMode::NFT,
-		|owner, data| <Pallet<T>>::init_collection(owner, data),
+		|owner, data| <Pallet<T>>::init_collection(owner, data, true),
 		|h| h,
 	)
 }
modifiedpallets/common/src/dispatch.rsdiffbeforeafterboth
--- a/pallets/common/src/dispatch.rs
+++ b/pallets/common/src/dispatch.rs
@@ -11,7 +11,7 @@
 use crate::{pallet::Config, CommonCollectionOperations, CollectionHandle};
 
 // TODO: move to benchmarking
-/// Price of [`dispatch_call`] call with noop `call` argument
+/// Price of [`dispatch_tx`] call with noop `call` argument
 pub fn dispatch_weight<T: Config>() -> Weight {
 	// Read collection
 	<T as frame_system::Config>::DbWeight::get().reads(1)
@@ -21,7 +21,7 @@
 }
 
 /// Helper function to implement substrate calls for common collection methods
-pub fn dispatch_call<
+pub fn dispatch_tx<
 	T: Config,
 	C: FnOnce(&dyn CommonCollectionOperations<T>) -> DispatchResultWithPostInfo,
 >(
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -427,7 +427,7 @@
 		/// Target collection doesn't supports this operation
 		UnsupportedOperation,
 
-		/// Not sufficient founds to perform action
+		/// Not sufficient funds to perform action
 		NotSufficientFounds,
 
 		/// Collection has nesting disabled
modifiedpallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -51,7 +51,7 @@
 	create_collection_raw(
 		owner,
 		CollectionMode::NFT,
-		<Pallet<T>>::init_collection,
+		|owner, data| <Pallet<T>>::init_collection(owner, data, true),
 		NonfungibleHandle::cast,
 	)
 }
@@ -99,7 +99,7 @@
 			sender: cross_from_sub(owner); burner: cross_sub;
 		};
 		let item = create_max_item(&collection, &sender, burner.clone())?;
-	}: {<Pallet<T>>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)}
+	}: {<Pallet<T>>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)?}
 
 	burn_recursively_breadth_plus_self_plus_self_per_each_raw {
 		let b in 0..200;
@@ -111,7 +111,7 @@
 		for i in 0..b {
 			create_max_item(&collection, &sender, T::CrossTokenAddressMapping::token_to_address(collection.id, item))?;
 		}
-	}: {<Pallet<T>>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)}
+	}: {<Pallet<T>>::burn_recursively(&collection, &burner, item, &Unlimited, &Unlimited)?}
 
 	transfer {
 		bench_init!{
@@ -183,7 +183,7 @@
 			value: property_value(),
 		}).collect::<Vec<_>>();
 		let item = create_max_item(&collection, &owner, owner.clone())?;
-	}: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props)?}
+	}: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props, false)?}
 
 	delete_token_properties {
 		let b in 0..MAX_PROPERTIES_PER_ITEM;
@@ -205,7 +205,7 @@
 			value: property_value(),
 		}).collect::<Vec<_>>();
 		let item = create_max_item(&collection, &owner, owner.clone())?;
-		<Pallet<T>>::set_token_properties(&collection, &owner, item, props)?;
+		<Pallet<T>>::set_token_properties(&collection, &owner, item, props, false)?;
 		let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();
 	}: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete)?}
 }
addedpallets/proxy-rmrk-core/src/benchmarking.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/proxy-rmrk-core/src/benchmarking.rs
@@ -0,0 +1,26 @@
+use sp_std::vec;
+
+use frame_benchmarking::{benchmarks, account};
+use frame_system::RawOrigin;
+use frame_support::{
+	traits::{Currency, Get},
+	BoundedVec,
+};
+
+use crate::{Config, Pallet, Call};
+
+const SEED: u32 = 1;
+
+fn create_data<S: Get<u32>>() -> BoundedVec<u8, S> {
+	vec![0; S::get() as usize].try_into().expect("size == S")
+}
+
+benchmarks! {
+	create_collection {
+		let caller = account("caller", 0, SEED);
+		<T as pallet_common::Config>::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get());
+		let metadata = create_data();
+		// TODO: Fix CollectionTokenPrefixLimitExceeded with create_data
+		let symbol = vec![].try_into().expect("0 <= x");
+	}: _(RawOrigin::Signed(caller), metadata, None, symbol)
+}
modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -31,9 +31,15 @@
 
 pub use pallet::*;
 
+#[cfg(feature = "runtime-benchmarks")]
+pub mod benchmarking;
 pub mod misc;
 pub mod property;
+pub mod weights;
+
+pub type SelfWeightOf<T> = <T as Config>::WeightInfo;
 
+use weights::WeightInfo;
 use misc::*;
 pub use property::*;
 
@@ -51,6 +57,7 @@
 		frame_system::Config + pallet_common::Config + pallet_nonfungible::Config + account::Config
 	{
 		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
+		type WeightInfo: WeightInfo;
 	}
 
 	#[pallet::storage]
@@ -169,8 +176,9 @@
 
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
-		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		/// Create a collection
 		#[transactional]
+		#[pallet::weight(<SelfWeightOf<T>>::create_collection())]
 		pub fn create_collection(
 			origin: OriginFor<T>,
 			metadata: RmrkString,
@@ -222,6 +230,7 @@
 			Ok(())
 		}
 
+		/// destroy collection
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn destroy_collection(
@@ -248,6 +257,12 @@
 			Ok(())
 		}
 
+		/// Change the issuer of a collection
+		///
+		/// Parameters:
+		/// - `origin`: sender of the transaction
+		/// - `collection_id`: collection id of the nft to change issuer of
+		/// - `new_issuer`: Collection's new issuer
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn change_collection_issuer(
@@ -278,6 +293,7 @@
 			Ok(())
 		}
 
+		/// lock collection
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn lock_collection(
@@ -309,6 +325,16 @@
 			Ok(())
 		}
 
+		/// Mints an NFT in the specified collection
+		/// Sets metadata and the royalty attribute
+		///
+		/// Parameters:
+		/// - `collection_id`: The class of the asset to be minted.
+		/// - `nft_id`: The nft value of the asset to be minted.
+		/// - `recipient`: Receiver of the royalty
+		/// - `royalty`: Permillage reward from each trade for the Recipient
+		/// - `metadata`: Arbitrary data about an nft, e.g. IPFS hash
+		/// - `transferable`: Ability to transfer this NFT
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn mint_nft(
@@ -378,6 +404,7 @@
 			Ok(())
 		}
 
+		/// burn nft
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn burn_nft(
@@ -409,6 +436,13 @@
 			Ok(())
 		}
 
+		/// Transfers a NFT from an Account or NFT A to another Account or NFT B
+		///
+		/// Parameters:
+		/// - `origin`: sender of the transaction
+		/// - `rmrk_collection_id`: collection id of the nft to be transferred
+		/// - `rmrk_nft_id`: nft id of the nft to be transferred
+		/// - `new_owner`: new owner of the nft which can be either an account or a NFT
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn send(
@@ -462,7 +496,7 @@
 
 					let target_nft_budget = budget::Value::new(NESTING_BUDGET);
 
-					let target_nft_owner = <PalletStructure<T>>::get_checked_indirect_owner(
+					let target_nft_owner = <PalletStructure<T>>::get_checked_topmost_owner(
 						target_collection_id,
 						target_nft_id.into(),
 						Some((collection_id, nft_id)),
@@ -513,6 +547,14 @@
 			Ok(())
 		}
 
+		/// Accepts an NFT sent from another account to self or owned NFT
+		///
+		/// Parameters:
+		/// - `origin`: sender of the transaction
+		/// - `rmrk_collection_id`: collection id of the nft to be accepted
+		/// - `rmrk_nft_id`: nft id of the nft to be accepted
+		/// - `new_owner`: either origin's account ID or origin-owned NFT, whichever the NFT was
+		///   sent to
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn accept_nft(
@@ -582,6 +624,12 @@
 			Ok(())
 		}
 
+		/// Rejects an NFT sent from another account to self or owned NFT
+		///
+		/// Parameters:
+		/// - `origin`: sender of the transaction
+		/// - `rmrk_collection_id`: collection id of the nft to be accepted
+		/// - `rmrk_nft_id`: nft id of the nft to be accepted
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn reject_nft(
@@ -618,6 +666,7 @@
 			Ok(())
 		}
 
+		/// accept the addition of a new resource to an existing NFT
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn accept_resource(
@@ -674,6 +723,7 @@
 			Ok(())
 		}
 
+		/// accept the removal of a resource of an existing NFT
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn accept_resource_removal(
@@ -731,6 +781,7 @@
 			Ok(())
 		}
 
+		/// set a custom value on an NFT
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn set_property(
@@ -790,6 +841,7 @@
 			Ok(())
 		}
 
+		/// set a different order of resource priority
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn set_priority(
@@ -828,6 +880,7 @@
 			Ok(())
 		}
 
+		/// Create basic resource
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn add_basic_resource(
@@ -865,6 +918,7 @@
 			Ok(())
 		}
 
+		/// Create composable resource
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn add_composable_resource(
@@ -905,6 +959,7 @@
 			Ok(())
 		}
 
+		/// Create slot resource
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn add_slot_resource(
@@ -944,6 +999,7 @@
 			Ok(())
 		}
 
+		/// remove resource
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn remove_resource(
modifiedpallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/src/misc.rs
+++ b/pallets/proxy-rmrk-core/src/misc.rs
@@ -1,3 +1,19 @@
+// 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 super::*;
 use codec::{Encode, Decode, Error};
 
modifiedpallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/src/property.rs
+++ b/pallets/proxy-rmrk-core/src/property.rs
@@ -1,3 +1,19 @@
+// 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 super::*;
 use core::convert::AsRef;
 
addedpallets/proxy-rmrk-core/src/weights.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/proxy-rmrk-core/src/weights.rs
@@ -0,0 +1,74 @@
+// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs
+
+//! Autogenerated weights for pallet_proxy_rmrk_core
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2022-06-09, STEPS: `50`, REPEAT: 200, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
+
+// Executed Command:
+// target/release/unique-collator
+// benchmark
+// pallet
+// --pallet
+// pallet-proxy-rmrk-core
+// --wasm-execution
+// compiled
+// --extrinsic
+// *
+// --template
+// .maintain/frame-weight-template.hbs
+// --steps=50
+// --repeat=200
+// --heap-pages=4096
+// --output=./pallets/proxy-rmrk-core/src/weights.rs
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for pallet_proxy_rmrk_core.
+pub trait WeightInfo {
+	fn create_collection() -> Weight;
+}
+
+/// Weights for pallet_proxy_rmrk_core using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+	// Storage: Common CreatedCollectionCount (r:1 w:1)
+	// Storage: Common DestroyedCollectionCount (r:1 w:0)
+	// Storage: System Account (r:2 w:2)
+	// Storage: RmrkCore CollectionIndex (r:1 w:1)
+	// Storage: Common CollectionPropertyPermissions (r:0 w:1)
+	// Storage: Common CollectionProperties (r:0 w:1)
+	// Storage: Common CollectionById (r:0 w:1)
+	// Storage: RmrkCore UniqueCollectionId (r:0 w:1)
+	// Storage: RmrkCore RmrkInernalCollectionId (r:0 w:1)
+	fn create_collection() -> Weight {
+		(76_647_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(5 as Weight))
+			.saturating_add(T::DbWeight::get().writes(9 as Weight))
+	}
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+	// Storage: Common CreatedCollectionCount (r:1 w:1)
+	// Storage: Common DestroyedCollectionCount (r:1 w:0)
+	// Storage: System Account (r:2 w:2)
+	// Storage: RmrkCore CollectionIndex (r:1 w:1)
+	// Storage: Common CollectionPropertyPermissions (r:0 w:1)
+	// Storage: Common CollectionProperties (r:0 w:1)
+	// Storage: Common CollectionById (r:0 w:1)
+	// Storage: RmrkCore UniqueCollectionId (r:0 w:1)
+	// Storage: RmrkCore RmrkInernalCollectionId (r:0 w:1)
+	fn create_collection() -> Weight {
+		(76_647_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(5 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(9 as Weight))
+	}
+}
modifiedpallets/proxy-rmrk-equip/src/lib.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-equip/src/lib.rs
+++ b/pallets/proxy-rmrk-equip/src/lib.rs
@@ -74,6 +74,15 @@
 
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
+		/// Creates a new Base.
+		/// Modeled after [base interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/base.md)
+		///
+		/// Parameters:
+		/// - origin: Caller, will be assigned as the issuer of the Base
+		/// - base_type: media type, e.g. "svg"
+		/// - symbol: arbitrary client-chosen symbol
+		/// - parts: array of Fixed and Slot parts composing the base, confined in length by
+		///   RmrkPartsLimit
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn create_base(
@@ -137,6 +146,19 @@
 			Ok(())
 		}
 
+		/// Adds a Theme to a Base.
+		/// Modeled after [themeadd interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/themeadd.md)
+		/// Themes are stored in the Themes storage
+		/// A Theme named "default" is required prior to adding other Themes.
+		///
+		/// Parameters:
+		/// - origin: The caller of the function, must be issuer of the base
+		/// - base_id: The Base containing the Theme to be updated
+		/// - theme: The Theme to add to the Base.  A Theme has a name and properties, which are an
+		///   array of [key, value, inherit].
+		///   - key: arbitrary BoundedString, defined by client
+		///   - value: arbitrary BoundedString, defined by client
+		///   - inherit: optional bool
 		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn theme_add(
modifiedpallets/structure/src/lib.rsdiffbeforeafterboth
--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -149,7 +149,7 @@
 		})
 	}
 
-	pub fn get_checked_indirect_owner(
+	pub fn get_checked_topmost_owner(
 		collection: CollectionId,
 		token: TokenId,
 		for_nest: Option<(CollectionId, TokenId)>,
@@ -203,7 +203,7 @@
 			None => user,
 		};
 
-		Self::get_checked_indirect_owner(collection, token, for_nest, budget)
+		Self::get_checked_topmost_owner(collection, token, for_nest, budget)
 			.map(|indirect_owner| indirect_owner == target_parent)
 	}
 
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -44,7 +44,7 @@
 };
 use pallet_evm::account::CrossAccountId;
 use pallet_common::{
-	CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_call,
+	CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_tx,
 	dispatch::CollectionDispatch,
 };
 pub mod eth;
@@ -581,7 +581,7 @@
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 			let budget = budget::Value::new(NESTING_BUDGET);
 
-			dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))
+			dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))
 		}
 
 		/// This method creates multiple items in a collection created with CreateCollection method.
@@ -609,7 +609,7 @@
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 			let budget = budget::Value::new(NESTING_BUDGET);
 
-			dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))
+			dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))
 		}
 
 		#[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]
@@ -623,7 +623,7 @@
 
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 
-			dispatch_call::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))
+			dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))
 		}
 
 		#[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]
@@ -637,7 +637,7 @@
 
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 
-			dispatch_call::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))
+			dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))
 		}
 
 		#[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]
@@ -652,7 +652,7 @@
 
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 
-			dispatch_call::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties))
+			dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties))
 		}
 
 		#[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]
@@ -667,7 +667,7 @@
 
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 
-			dispatch_call::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys))
+			dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys))
 		}
 
 		#[weight = T::CommonWeightInfo::set_property_permissions(property_permissions.len() as u32)]
@@ -681,7 +681,7 @@
 
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 
-			dispatch_call::<T, _>(collection_id, |d| d.set_property_permissions(&sender, property_permissions))
+			dispatch_tx::<T, _>(collection_id, |d| d.set_property_permissions(&sender, property_permissions))
 		}
 
 		#[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]
@@ -690,7 +690,7 @@
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 			let budget = budget::Value::new(NESTING_BUDGET);
 
-			dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))
+			dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))
 		}
 
 		// TODO! transaction weight
@@ -738,7 +738,7 @@
 		pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 
-			let post_info = dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;
+			let post_info = dispatch_tx::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;
 			if value == 1 {
 				<NftTransferBasket<T>>::remove(collection_id, item_id);
 				<NftApproveBasket<T>>::remove(collection_id, item_id);
@@ -771,7 +771,7 @@
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 			let budget = budget::Value::new(NESTING_BUDGET);
 
-			dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))
+			dispatch_tx::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))
 		}
 
 		/// Change ownership of the token.
@@ -803,7 +803,7 @@
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 			let budget = budget::Value::new(NESTING_BUDGET);
 
-			dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))
+			dispatch_tx::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))
 		}
 
 		/// Set, change, or remove approved address to transfer the ownership of the NFT.
@@ -826,7 +826,7 @@
 		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)?);
 
-			dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
+			dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
 		}
 
 		/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
@@ -854,7 +854,7 @@
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 			let budget = budget::Value::new(NESTING_BUDGET);
 
-			dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))
+			dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))
 		}
 
 		#[weight = <SelfWeightOf<T>>::set_collection_limits()]
modifiedprimitives/rmrk-rpc/src/lib.rsdiffbeforeafterboth
--- a/primitives/rmrk-rpc/src/lib.rs
+++ b/primitives/rmrk-rpc/src/lib.rs
@@ -1,3 +1,19 @@
+// 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/>.
+
 #![cfg_attr(not(feature = "std"), no_std)]
 
 use sp_api::{Encode, Decode};
modifiedprimitives/rmrk-traits/src/base.rsdiffbeforeafterboth
--- a/primitives/rmrk-traits/src/base.rs
+++ b/primitives/rmrk-traits/src/base.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
 use codec::{Decode, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 
modifiedprimitives/rmrk-traits/src/collection.rsdiffbeforeafterboth
--- a/primitives/rmrk-traits/src/collection.rs
+++ b/primitives/rmrk-traits/src/collection.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
 use codec::{Decode, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 
modifiedprimitives/rmrk-traits/src/lib.rsdiffbeforeafterboth
--- a/primitives/rmrk-traits/src/lib.rs
+++ b/primitives/rmrk-traits/src/lib.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
 #![cfg_attr(not(feature = "std"), no_std)]
 
 pub mod base;
modifiedprimitives/rmrk-traits/src/nft.rsdiffbeforeafterboth
--- a/primitives/rmrk-traits/src/nft.rs
+++ b/primitives/rmrk-traits/src/nft.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
 use codec::{Decode, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 
modifiedprimitives/rmrk-traits/src/part.rsdiffbeforeafterboth
--- a/primitives/rmrk-traits/src/part.rs
+++ b/primitives/rmrk-traits/src/part.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
 use codec::{Decode, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 
modifiedprimitives/rmrk-traits/src/property.rsdiffbeforeafterboth
--- a/primitives/rmrk-traits/src/property.rs
+++ b/primitives/rmrk-traits/src/property.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
 use codec::{Decode, Encode};
 use scale_info::TypeInfo;
 
modifiedprimitives/rmrk-traits/src/resource.rsdiffbeforeafterboth
--- a/primitives/rmrk-traits/src/resource.rs
+++ b/primitives/rmrk-traits/src/resource.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
 use codec::{Decode, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
 
modifiedprimitives/rmrk-traits/src/serialize.rsdiffbeforeafterboth
--- a/primitives/rmrk-traits/src/serialize.rs
+++ b/primitives/rmrk-traits/src/serialize.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
 use core::convert::AsRef;
 use serde::ser::{self, Serialize};
 
modifiedprimitives/rmrk-traits/src/theme.rsdiffbeforeafterboth
--- a/primitives/rmrk-traits/src/theme.rs
+++ b/primitives/rmrk-traits/src/theme.rs
@@ -1,3 +1,7 @@
+// Copyright (C) 2021-2022 RMRK
+// This file is part of rmrk-substrate.
+// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
+
 use codec::{Decode, Encode};
 use scale_info::TypeInfo;
 
modifiedruntime/common/src/constants.rsdiffbeforeafterboth
--- a/runtime/common/src/constants.rs
+++ b/runtime/common/src/constants.rs
@@ -1,3 +1,19 @@
+// 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 sp_runtime::Perbill;
 use frame_support::{
 	parameter_types,
modifiedruntime/common/src/dispatch.rsdiffbeforeafterboth
--- a/runtime/common/src/dispatch.rs
+++ b/runtime/common/src/dispatch.rs
@@ -1,3 +1,19 @@
+// 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 frame_support::{dispatch::DispatchResult, ensure};
 use pallet_evm::{PrecompileHandle, PrecompileResult};
 use sp_core::H160;
modifiedruntime/common/src/lib.rsdiffbeforeafterboth
--- a/runtime/common/src/lib.rs
+++ b/runtime/common/src/lib.rs
@@ -1,3 +1,19 @@
+// 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/>.
+
 #![cfg_attr(not(feature = "std"), no_std)]
 
 pub mod constants;
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
before · runtime/common/src/runtime_apis.rs
1#[macro_export]2macro_rules! impl_common_runtime_apis {3    (4        $(5            #![custom_apis]67            $($custom_apis:tt)+8        )?9    ) => {10        impl_runtime_apis! {11            $($($custom_apis)+)?1213            impl up_rpc::UniqueApi<Block, CrossAccountId, AccountId> for Runtime {14                fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>, DispatchError> {15                    dispatch_unique_runtime!(collection.account_tokens(account))16                }17                fn collection_tokens(collection: CollectionId) -> Result<Vec<TokenId>, DispatchError> {18                    dispatch_unique_runtime!(collection.collection_tokens())19                }20                fn token_exists(collection: CollectionId, token: TokenId) -> Result<bool, DispatchError> {21                    dispatch_unique_runtime!(collection.token_exists(token))22                }2324                fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {25                    dispatch_unique_runtime!(collection.token_owner(token))26                }27                fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {28                    let budget = up_data_structs::budget::Value::new(10);2930                    Ok(Some(<pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)?))31                }32                fn token_children(collection: CollectionId, token: TokenId) -> Result<Vec<TokenChild>, DispatchError> {33                    Ok(<pallet_nonfungible::Pallet<Runtime>>::token_children_ids(collection, token))34                }35                fn collection_properties(36                    collection: CollectionId,37                    keys: Option<Vec<Vec<u8>>>38                ) -> Result<Vec<Property>, DispatchError> {39                    let keys = keys.map(40                        |keys| Common::bytes_keys_to_property_keys(keys)41                    ).transpose()?;4243                    Common::filter_collection_properties(collection, keys)44                }4546                fn token_properties(47                    collection: CollectionId,48                    token_id: TokenId,49                    keys: Option<Vec<Vec<u8>>>50                ) -> Result<Vec<Property>, DispatchError> {51                    let keys = keys.map(52                        |keys| Common::bytes_keys_to_property_keys(keys)53                    ).transpose()?;5455                    dispatch_unique_runtime!(collection.token_properties(token_id, keys))56                }5758                fn property_permissions(59                    collection: CollectionId,60                    keys: Option<Vec<Vec<u8>>>61                ) -> Result<Vec<PropertyKeyPermission>, DispatchError> {62                    let keys = keys.map(63                        |keys| Common::bytes_keys_to_property_keys(keys)64                    ).transpose()?;6566                    Common::filter_property_permissions(collection, keys)67                }6869                fn token_data(70                    collection: CollectionId,71                    token_id: TokenId,72                    keys: Option<Vec<Vec<u8>>>73                ) -> Result<TokenData<CrossAccountId>, DispatchError> {74                    let token_data = TokenData {75                        properties: Self::token_properties(collection, token_id, keys)?,76                        owner: Self::token_owner(collection, token_id)?77                    };7879                    Ok(token_data)80                }8182                fn total_supply(collection: CollectionId) -> Result<u32, DispatchError> {83                    dispatch_unique_runtime!(collection.total_supply())84                }85                fn account_balance(collection: CollectionId, account: CrossAccountId) -> Result<u32, DispatchError> {86                    dispatch_unique_runtime!(collection.account_balance(account))87                }88                fn balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<u128, DispatchError> {89                    dispatch_unique_runtime!(collection.balance(account, token))90                }91                fn allowance(92                    collection: CollectionId,93                    sender: CrossAccountId,94                    spender: CrossAccountId,95                    token: TokenId,96                ) -> Result<u128, DispatchError> {97                    dispatch_unique_runtime!(collection.allowance(sender, spender, token))98                }99100                fn adminlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {101                    Ok(<pallet_common::Pallet<Runtime>>::adminlist(collection))102                }103                fn allowlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {104                    Ok(<pallet_common::Pallet<Runtime>>::allowlist(collection))105                }106                fn allowed(collection: CollectionId, user: CrossAccountId) -> Result<bool, DispatchError> {107                    Ok(<pallet_common::Pallet<Runtime>>::allowed(collection, user))108                }109                fn last_token_id(collection: CollectionId) -> Result<TokenId, DispatchError> {110                    dispatch_unique_runtime!(collection.last_token_id())111                }112                fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>, DispatchError> {113                    Ok(<pallet_common::Pallet<Runtime>>::rpc_collection(collection))114                }115                fn collection_stats() -> Result<CollectionStats, DispatchError> {116                    Ok(<pallet_common::Pallet<Runtime>>::collection_stats())117                }118                fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>, DispatchError> {119                    Ok(<$crate::sponsoring::UniqueSponsorshipPredict<Runtime> as120                            $crate::sponsoring::SponsorshipPredict<Runtime>>::predict(121                        collection,122                        account,123                        token))124                }125126                fn effective_collection_limits(collection: CollectionId) -> Result<Option<CollectionLimits>, DispatchError> {127                    Ok(<pallet_common::Pallet<Runtime>>::effective_collection_limits(collection))128                }129            }130131            impl rmrk_rpc::RmrkApi<132                Block,133                AccountId,134                RmrkCollectionInfo<AccountId>,135                RmrkInstanceInfo<AccountId>,136                RmrkResourceInfo,137                RmrkPropertyInfo,138                RmrkBaseInfo<AccountId>,139                RmrkPartType,140                RmrkTheme141            > for Runtime {142                fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {143                    Ok(RmrkCore::last_collection_idx())144                }145146                fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {147                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};148                    use pallet_common::CommonCollectionOperations;149150                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) {151                        Ok(c) => c,152                        Err(_) => return Ok(None),153                    };154155                    let nfts_count = collection.total_supply();156157                    Ok(Some(RmrkCollectionInfo {158                        issuer: collection.owner.clone(),159                        metadata: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::Metadata)?,160                        max: collection.limits.token_limit,161                        symbol: RmrkCore::rebind(&collection.token_prefix)?,162                        nfts_count163                    }))164                }165166                fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {167                    use up_data_structs::mapping::TokenAddressMapping;168                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};169                    use pallet_common::CommonCollectionOperations;170171                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) {172                        Ok(c) => c,173                        Err(_) => return Ok(None),174                    };175176                    let nft_id = TokenId(nft_by_id);177                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); }178179                    let owner = match collection.token_owner(nft_id) {180                        Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {181                            Some((col, tok)) => {182                                let rmrk_collection = RmrkCore::rmrk_collection_id(col)?;183184                                RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0)185                            }186                            None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())187                        },188                        None => return Ok(None)189                    };190191                    Ok(Some(RmrkInstanceInfo {192                        owner: owner,193                        royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,194                        metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,195                        equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,196                        pending: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::PendingNftAccept)?,197                    }))198                }199200                fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {201                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};202                    use pallet_common::CommonCollectionOperations;203204                    let cross_account_id = CrossAccountId::from_sub(account_id);205206                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) {207                        Ok(c) => c,208                        Err(_) => return Ok(Vec::new()),209                    };210211                    let tokens = collection.account_tokens(cross_account_id)212                        .into_iter()213                        .filter(|token| {214                            let is_pending = RmrkCore::get_nft_property_decoded(215                                collection_id,216                                *token,217                                RmrkProperty::PendingNftAccept218                            ).unwrap_or(true);219220                            !is_pending221                        })222                        .map(|token| token.0)223                        .collect();224225                    Ok(tokens)226                }227228                fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {229                    use pallet_proxy_rmrk_core::RmrkProperty;230231                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {232                        Ok(id) => id,233                        Err(_) => return Ok(Vec::new())234                    };235                    let nft_id = TokenId(nft_id);236                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); }237238                    Ok(239                        pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))240                            .filter_map(|((child_collection, child_token), _)| {241                                let is_pending = RmrkCore::get_nft_property_decoded(242                                    child_collection,243                                    child_token,244                                    RmrkProperty::PendingNftAccept245                                ).ok()?;246247                                if is_pending {248                                    return None;249                                }250251                                let rmrk_child_collection = RmrkCore::rmrk_collection_id(252                                    child_collection253                                ).ok()?;254255                                Some(RmrkNftChild {256                                    collection_id: rmrk_child_collection,257                                    nft_id: child_token.0,258                                })259                            }).collect()260                    )261                }262263                fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {264                    use pallet_proxy_rmrk_core::misc::CollectionType;265266                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {267                        Ok(id) => id,268                        Err(_) => return Ok(Vec::new())269                    };270                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {271                        return Ok(Vec::new());272                    }273274                    let properties = RmrkCore::filter_user_properties(275                        collection_id,276                        /* token_id = */ None,277                        filter_keys,278                        |key, value| RmrkPropertyInfo {279                            key,280                            value281                        }282                    )?;283284                    Ok(properties)285                }286287                fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {288                    use pallet_proxy_rmrk_core::misc::NftType;289290                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {291                        Ok(id) => id,292                        Err(_) => return Ok(Vec::new())293                    };294                    let token_id = TokenId(nft_id);295296                    if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {297                        return Ok(Vec::new());298                    }299300		            let properties = RmrkCore::filter_user_properties(301                        collection_id,302                        Some(token_id),303                        filter_keys,304                        |key, value| RmrkPropertyInfo {305                            key,306                            value307                        }308                    )?;309310                    Ok(properties)311                }312313                fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {314                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};315                    use pallet_common::CommonCollectionOperations;316317                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {318                        Ok(id) => id,319                        Err(_) => return Ok(Vec::new())320                    };321                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }322323                    let nft_id = TokenId(nft_id);324                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }325326                    let res_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?;327                    let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?;328329                    let resources = resource_collection330                        .collection_tokens()331                        .iter()332                        .filter_map(|(res_id)| Some(RmrkResourceInfo {333                            id: res_id.0,334                            pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap(),335                            pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap(),336                            resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap() {337                                ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {338                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),339                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),340                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),341                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),342                                }),343                                ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {344                                    parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).unwrap(),345                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),346                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),347                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),348                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),349                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),350                                }),351                                ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {352                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),353                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),354                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),355                                    slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).unwrap(),356                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),357                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),358                                }),359                            },360                        }))361                        .collect();362363                    Ok(resources)364                }365366                fn nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {367                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};368369                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {370                        Ok(id) => id,371                        Err(_) => return Ok(None)372                    };373                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(None); }374375                    let nft_id = TokenId(nft_id);376                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(None); }377378                    let priorities: Vec<_> = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourcePriorities)?;379                    Ok(380                        priorities.into_iter()381                            .enumerate()382                            .find(|(_, id)| *id == resource_id)383                            .map(|(priority, _): (usize, RmrkResourceId)| priority as u32)384                    )385                }386387                fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {388                    use pallet_proxy_rmrk_core::{389                        RmrkProperty, misc::{CollectionType},390                    };391392                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) {393                        Ok(c) => c,394                        Err(_) => return Ok(None),395                    };396397                    Ok(Some(RmrkBaseInfo {398                        issuer: collection.owner.clone(),399                        base_type: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::BaseType)?,400                        symbol: RmrkCore::rebind(&collection.token_prefix)?,401                    }))402                }403404                fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {405                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};406                    use pallet_common::CommonCollectionOperations;407408                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) {409                        Ok(c) => c,410                        Err(_) => return Ok(Vec::new()),411                    };412413                    let parts = collection.collection_tokens()414                        .into_iter()415                        .filter_map(|token_id| {416                            let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?;417418                            match nft_type {419                                NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart {420                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,421                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,422                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,423                                })),424                                NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart {425                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,426                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,427                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,428                                    equippable: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::EquippableList).ok()?,429                                })),430                                _ => None431                            }432                        })433                        .collect();434435                    Ok(parts)436                }437438                fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {439                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};440                    use pallet_common::CommonCollectionOperations;441442                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) {443                        Ok(c) => c,444                        Err(_) => return Ok(Vec::new()),445                    };446447                    let theme_names = collection.collection_tokens()448                        .iter()449                        .filter_map(|token_id| {450                            let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();451452                            match nft_type {453                                Theme => Some(454                                    RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).unwrap()455                                ),456                                _ => None457                            }458                        })459                        .collect();460461                    Ok(theme_names)462                }463464                fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {465                    use pallet_proxy_rmrk_core::{466                        RmrkProperty,467                        misc::{CollectionType, NftType}468                    };469                    use pallet_common::CommonCollectionOperations;470471                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) {472                        Ok(c) => c,473                        Err(_) => return Ok(None),474                    };475476                    let theme_info = collection.collection_tokens()477                        .into_iter()478                        .find_map(|token_id| {479                            RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;480481                            let name: RmrkString = RmrkCore::get_nft_property_decoded(482                                collection_id, token_id, RmrkProperty::ThemeName483                            ).ok()?;484485                            if name == theme_name {486                                Some((name, token_id))487                            } else {488                                None489                            }490                        });491492                    let (name, theme_id) = match theme_info {493                        Some((name, theme_id)) => (name, theme_id),494                        None => return Ok(None)495                    };496497                    let properties = RmrkCore::filter_user_properties(498                        collection_id,499                        Some(theme_id),500                        filter_keys,501                        |key, value| RmrkThemeProperty {502                            key,503                            value504                        }505                    )?;506507                    let inherit = RmrkCore::get_nft_property_decoded(508                        collection_id,509                        theme_id,510                        RmrkProperty::ThemeInherit511                    )?;512513                    let theme = RmrkTheme {514                        name,515                        properties,516                        inherit,517                    };518519                    Ok(Some(theme))520                }521            }522523            impl sp_api::Core<Block> for Runtime {524                fn version() -> RuntimeVersion {525                    VERSION526                }527528                fn execute_block(block: Block) {529                    Executive::execute_block(block)530                }531532                fn initialize_block(header: &<Block as BlockT>::Header) {533                    Executive::initialize_block(header)534                }535            }536537            impl sp_api::Metadata<Block> for Runtime {538                fn metadata() -> OpaqueMetadata {539                    OpaqueMetadata::new(Runtime::metadata().into())540                }541            }542543            impl sp_block_builder::BlockBuilder<Block> for Runtime {544                fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {545                    Executive::apply_extrinsic(extrinsic)546                }547548                fn finalize_block() -> <Block as BlockT>::Header {549                    Executive::finalize_block()550                }551552                fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {553                    data.create_extrinsics()554                }555556                fn check_inherents(557                    block: Block,558                    data: sp_inherents::InherentData,559                ) -> sp_inherents::CheckInherentsResult {560                    data.check_extrinsics(&block)561                }562563                // fn random_seed() -> <Block as BlockT>::Hash {564                //     RandomnessCollectiveFlip::random_seed().0565                // }566            }567568            impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {569                fn validate_transaction(570                    source: TransactionSource,571                    tx: <Block as BlockT>::Extrinsic,572                    hash: <Block as BlockT>::Hash,573                ) -> TransactionValidity {574                    Executive::validate_transaction(source, tx, hash)575                }576            }577578            impl sp_offchain::OffchainWorkerApi<Block> for Runtime {579                fn offchain_worker(header: &<Block as BlockT>::Header) {580                    Executive::offchain_worker(header)581                }582            }583584            impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {585                fn chain_id() -> u64 {586                    <Runtime as pallet_evm::Config>::ChainId::get()587                }588589                fn account_basic(address: H160) -> EVMAccount {590                    let (account, _) = EVM::account_basic(&address);591                    account592                }593594                fn gas_price() -> U256 {595                    let (price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();596                    price597                }598599                fn account_code_at(address: H160) -> Vec<u8> {600                    EVM::account_codes(address)601                }602603                fn author() -> H160 {604                    <pallet_evm::Pallet<Runtime>>::find_author()605                }606607                fn storage_at(address: H160, index: U256) -> H256 {608                    let mut tmp = [0u8; 32];609                    index.to_big_endian(&mut tmp);610                    EVM::account_storages(address, H256::from_slice(&tmp[..]))611                }612613                #[allow(clippy::redundant_closure)]614                fn call(615                    from: H160,616                    to: H160,617                    data: Vec<u8>,618                    value: U256,619                    gas_limit: U256,620                    max_fee_per_gas: Option<U256>,621                    max_priority_fee_per_gas: Option<U256>,622                    nonce: Option<U256>,623                    estimate: bool,624                    access_list: Option<Vec<(H160, Vec<H256>)>>,625                ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {626                    let config = if estimate {627                        let mut config = <Runtime as pallet_evm::Config>::config().clone();628                        config.estimate = true;629                        Some(config)630                    } else {631                        None632                    };633634                    let is_transactional = false;635                    <Runtime as pallet_evm::Config>::Runner::call(636                        CrossAccountId::from_eth(from),637                        to,638                        data,639                        value,640                        gas_limit.low_u64(),641                        max_fee_per_gas,642                        max_priority_fee_per_gas,643                        nonce,644                        access_list.unwrap_or_default(),645                        is_transactional,646                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),647                    ).map_err(|err| err.error.into())648                }649650                #[allow(clippy::redundant_closure)]651                fn create(652                    from: H160,653                    data: Vec<u8>,654                    value: U256,655                    gas_limit: U256,656                    max_fee_per_gas: Option<U256>,657                    max_priority_fee_per_gas: Option<U256>,658                    nonce: Option<U256>,659                    estimate: bool,660                    access_list: Option<Vec<(H160, Vec<H256>)>>,661                ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {662                    let config = if estimate {663                        let mut config = <Runtime as pallet_evm::Config>::config().clone();664                        config.estimate = true;665                        Some(config)666                    } else {667                        None668                    };669670                    let is_transactional = false;671                    <Runtime as pallet_evm::Config>::Runner::create(672                        CrossAccountId::from_eth(from),673                        data,674                        value,675                        gas_limit.low_u64(),676                        max_fee_per_gas,677                        max_priority_fee_per_gas,678                        nonce,679                        access_list.unwrap_or_default(),680                        is_transactional,681                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),682                    ).map_err(|err| err.error.into())683                }684685                fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {686                    Ethereum::current_transaction_statuses()687                }688689                fn current_block() -> Option<pallet_ethereum::Block> {690                    Ethereum::current_block()691                }692693                fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {694                    Ethereum::current_receipts()695                }696697                fn current_all() -> (698                    Option<pallet_ethereum::Block>,699                    Option<Vec<pallet_ethereum::Receipt>>,700                    Option<Vec<TransactionStatus>>701                ) {702                    (703                        Ethereum::current_block(),704                        Ethereum::current_receipts(),705                        Ethereum::current_transaction_statuses()706                    )707                }708709                fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {710                    xts.into_iter().filter_map(|xt| match xt.0.function {711                        Call::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),712                        _ => None713                    }).collect()714                }715716                fn elasticity() -> Option<Permill> {717                    None718                }719            }720721            impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {722                fn convert_transaction(transaction: pallet_ethereum::Transaction) -> <Block as BlockT>::Extrinsic  {723                    UncheckedExtrinsic::new_unsigned(724                        pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),725                    )726                }727            }728729            impl sp_session::SessionKeys<Block> for Runtime {730                fn decode_session_keys(731                    encoded: Vec<u8>,732                ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {733                    SessionKeys::decode_into_raw_public_keys(&encoded)734                }735736                fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {737                    SessionKeys::generate(seed)738                }739            }740741            impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {742                fn slot_duration() -> sp_consensus_aura::SlotDuration {743                    sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())744                }745746                fn authorities() -> Vec<AuraId> {747                    Aura::authorities().to_vec()748                }749            }750751            impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {752                fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {753                    ParachainSystem::collect_collation_info(header)754                }755            }756757            impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {758                fn account_nonce(account: AccountId) -> Index {759                    System::account_nonce(account)760                }761            }762763            impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {764                fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {765                    TransactionPayment::query_info(uxt, len)766                }767                fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {768                    TransactionPayment::query_fee_details(uxt, len)769                }770            }771772            /*773            impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>774                for Runtime775            {776                fn call(777                    origin: AccountId,778                    dest: AccountId,779                    value: Balance,780                    gas_limit: u64,781                    input_data: Vec<u8>,782                ) -> pallet_contracts_primitives::ContractExecResult {783                    Contracts::bare_call(origin, dest, value, gas_limit, input_data, false)784                }785786                fn instantiate(787                    origin: AccountId,788                    endowment: Balance,789                    gas_limit: u64,790                    code: pallet_contracts_primitives::Code<Hash>,791                    data: Vec<u8>,792                    salt: Vec<u8>,793                ) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber>794                {795                    Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true, false)796                }797798                fn get_storage(799                    address: AccountId,800                    key: [u8; 32],801                ) -> pallet_contracts_primitives::GetStorageResult {802                    Contracts::get_storage(address, key)803                }804805                fn rent_projection(806                    address: AccountId,807                ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {808                    Contracts::rent_projection(address)809                }810            }811            */812813            #[cfg(feature = "runtime-benchmarks")]814            impl frame_benchmarking::Benchmark<Block> for Runtime {815                fn benchmark_metadata(extra: bool) -> (816                    Vec<frame_benchmarking::BenchmarkList>,817                    Vec<frame_support::traits::StorageInfo>,818                ) {819                    use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};820                    use frame_support::traits::StorageInfoTrait;821822                    let mut list = Vec::<BenchmarkList>::new();823824                    list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);825                    list_benchmark!(list, extra, pallet_common, Common);826                    list_benchmark!(list, extra, pallet_unique, Unique);827                    list_benchmark!(list, extra, pallet_structure, Structure);828                    list_benchmark!(list, extra, pallet_inflation, Inflation);829                    list_benchmark!(list, extra, pallet_fungible, Fungible);830                    list_benchmark!(list, extra, pallet_refungible, Refungible);831                    list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);832                    // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);833834                    let storage_info = AllPalletsReversedWithSystemFirst::storage_info();835836                    return (list, storage_info)837                }838839                fn dispatch_benchmark(840                    config: frame_benchmarking::BenchmarkConfig841                ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {842                    use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};843844                    let allowlist: Vec<TrackedStorageKey> = vec![845                        // Total Issuance846                        hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),847848                        // Block Number849                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),850                        // Execution Phase851                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),852                        // Event Count853                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),854                        // System Events855                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),856857                        // Evm CurrentLogs858                        hex_literal::hex!("1da53b775b270400e7e61ed5cbc5a146547f210cec367e9af919603343b9cb56").to_vec().into(),859860                        // Transactional depth861                        hex_literal::hex!("3a7472616e73616374696f6e5f6c6576656c3a").to_vec().into(),862                    ];863864                    let mut batches = Vec::<BenchmarkBatch>::new();865                    let params = (&config, &allowlist);866867                    add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);868                    add_benchmark!(params, batches, pallet_common, Common);869                    add_benchmark!(params, batches, pallet_unique, Unique);870                    add_benchmark!(params, batches, pallet_structure, Structure);871                    add_benchmark!(params, batches, pallet_inflation, Inflation);872                    add_benchmark!(params, batches, pallet_fungible, Fungible);873                    add_benchmark!(params, batches, pallet_refungible, Refungible);874                    add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);875                    // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);876877                    if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }878                    Ok(batches)879                }880            }881882            #[cfg(feature = "try-runtime")]883            impl frame_try_runtime::TryRuntime<Block> for Runtime {884                fn on_runtime_upgrade() -> (Weight, Weight) {885                    log::info!("try-runtime::on_runtime_upgrade unique-chain.");886                    let weight = Executive::try_runtime_upgrade().unwrap();887                    (weight, RuntimeBlockWeights::get().max_block)888                }889890                fn execute_block_no_check(block: Block) -> Weight {891                    Executive::execute_block_no_check(block)892                }893            }894        }895    }896}
after · runtime/common/src/runtime_apis.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#[macro_export]18macro_rules! impl_common_runtime_apis {19    (20        $(21            #![custom_apis]2223            $($custom_apis:tt)+24        )?25    ) => {26        impl_runtime_apis! {27            $($($custom_apis)+)?2829            impl up_rpc::UniqueApi<Block, CrossAccountId, AccountId> for Runtime {30                fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>, DispatchError> {31                    dispatch_unique_runtime!(collection.account_tokens(account))32                }33                fn collection_tokens(collection: CollectionId) -> Result<Vec<TokenId>, DispatchError> {34                    dispatch_unique_runtime!(collection.collection_tokens())35                }36                fn token_exists(collection: CollectionId, token: TokenId) -> Result<bool, DispatchError> {37                    dispatch_unique_runtime!(collection.token_exists(token))38                }3940                fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {41                    dispatch_unique_runtime!(collection.token_owner(token))42                }43                fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {44                    let budget = up_data_structs::budget::Value::new(10);4546                    Ok(Some(<pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)?))47                }48                fn token_children(collection: CollectionId, token: TokenId) -> Result<Vec<TokenChild>, DispatchError> {49                    Ok(<pallet_nonfungible::Pallet<Runtime>>::token_children_ids(collection, token))50                }51                fn collection_properties(52                    collection: CollectionId,53                    keys: Option<Vec<Vec<u8>>>54                ) -> Result<Vec<Property>, DispatchError> {55                    let keys = keys.map(56                        |keys| Common::bytes_keys_to_property_keys(keys)57                    ).transpose()?;5859                    Common::filter_collection_properties(collection, keys)60                }6162                fn token_properties(63                    collection: CollectionId,64                    token_id: TokenId,65                    keys: Option<Vec<Vec<u8>>>66                ) -> Result<Vec<Property>, DispatchError> {67                    let keys = keys.map(68                        |keys| Common::bytes_keys_to_property_keys(keys)69                    ).transpose()?;7071                    dispatch_unique_runtime!(collection.token_properties(token_id, keys))72                }7374                fn property_permissions(75                    collection: CollectionId,76                    keys: Option<Vec<Vec<u8>>>77                ) -> Result<Vec<PropertyKeyPermission>, DispatchError> {78                    let keys = keys.map(79                        |keys| Common::bytes_keys_to_property_keys(keys)80                    ).transpose()?;8182                    Common::filter_property_permissions(collection, keys)83                }8485                fn token_data(86                    collection: CollectionId,87                    token_id: TokenId,88                    keys: Option<Vec<Vec<u8>>>89                ) -> Result<TokenData<CrossAccountId>, DispatchError> {90                    let token_data = TokenData {91                        properties: Self::token_properties(collection, token_id, keys)?,92                        owner: Self::token_owner(collection, token_id)?93                    };9495                    Ok(token_data)96                }9798                fn total_supply(collection: CollectionId) -> Result<u32, DispatchError> {99                    dispatch_unique_runtime!(collection.total_supply())100                }101                fn account_balance(collection: CollectionId, account: CrossAccountId) -> Result<u32, DispatchError> {102                    dispatch_unique_runtime!(collection.account_balance(account))103                }104                fn balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<u128, DispatchError> {105                    dispatch_unique_runtime!(collection.balance(account, token))106                }107                fn allowance(108                    collection: CollectionId,109                    sender: CrossAccountId,110                    spender: CrossAccountId,111                    token: TokenId,112                ) -> Result<u128, DispatchError> {113                    dispatch_unique_runtime!(collection.allowance(sender, spender, token))114                }115116                fn adminlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {117                    Ok(<pallet_common::Pallet<Runtime>>::adminlist(collection))118                }119                fn allowlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {120                    Ok(<pallet_common::Pallet<Runtime>>::allowlist(collection))121                }122                fn allowed(collection: CollectionId, user: CrossAccountId) -> Result<bool, DispatchError> {123                    Ok(<pallet_common::Pallet<Runtime>>::allowed(collection, user))124                }125                fn last_token_id(collection: CollectionId) -> Result<TokenId, DispatchError> {126                    dispatch_unique_runtime!(collection.last_token_id())127                }128                fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>, DispatchError> {129                    Ok(<pallet_common::Pallet<Runtime>>::rpc_collection(collection))130                }131                fn collection_stats() -> Result<CollectionStats, DispatchError> {132                    Ok(<pallet_common::Pallet<Runtime>>::collection_stats())133                }134                fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>, DispatchError> {135                    Ok(<$crate::sponsoring::UniqueSponsorshipPredict<Runtime> as136                            $crate::sponsoring::SponsorshipPredict<Runtime>>::predict(137                        collection,138                        account,139                        token))140                }141142                fn effective_collection_limits(collection: CollectionId) -> Result<Option<CollectionLimits>, DispatchError> {143                    Ok(<pallet_common::Pallet<Runtime>>::effective_collection_limits(collection))144                }145            }146147            impl rmrk_rpc::RmrkApi<148                Block,149                AccountId,150                RmrkCollectionInfo<AccountId>,151                RmrkInstanceInfo<AccountId>,152                RmrkResourceInfo,153                RmrkPropertyInfo,154                RmrkBaseInfo<AccountId>,155                RmrkPartType,156                RmrkTheme157            > for Runtime {158                fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {159                    Ok(RmrkCore::last_collection_idx())160                }161162                fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {163                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};164                    use pallet_common::CommonCollectionOperations;165166                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) {167                        Ok(c) => c,168                        Err(_) => return Ok(None),169                    };170171                    let nfts_count = collection.total_supply();172173                    Ok(Some(RmrkCollectionInfo {174                        issuer: collection.owner.clone(),175                        metadata: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::Metadata)?,176                        max: collection.limits.token_limit,177                        symbol: RmrkCore::rebind(&collection.token_prefix)?,178                        nfts_count179                    }))180                }181182                fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {183                    use up_data_structs::mapping::TokenAddressMapping;184                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};185                    use pallet_common::CommonCollectionOperations;186187                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) {188                        Ok(c) => c,189                        Err(_) => return Ok(None),190                    };191192                    let nft_id = TokenId(nft_by_id);193                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); }194195                    let owner = match collection.token_owner(nft_id) {196                        Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {197                            Some((col, tok)) => {198                                let rmrk_collection = RmrkCore::rmrk_collection_id(col)?;199200                                RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0)201                            }202                            None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())203                        },204                        None => return Ok(None)205                    };206207                    Ok(Some(RmrkInstanceInfo {208                        owner: owner,209                        royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,210                        metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,211                        equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,212                        pending: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::PendingNftAccept)?,213                    }))214                }215216                fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {217                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};218                    use pallet_common::CommonCollectionOperations;219220                    let cross_account_id = CrossAccountId::from_sub(account_id);221222                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(collection_id, CollectionType::Regular) {223                        Ok(c) => c,224                        Err(_) => return Ok(Vec::new()),225                    };226227                    let tokens = collection.account_tokens(cross_account_id)228                        .into_iter()229                        .filter(|token| {230                            let is_pending = RmrkCore::get_nft_property_decoded(231                                collection_id,232                                *token,233                                RmrkProperty::PendingNftAccept234                            ).unwrap_or(true);235236                            !is_pending237                        })238                        .map(|token| token.0)239                        .collect();240241                    Ok(tokens)242                }243244                fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {245                    use pallet_proxy_rmrk_core::RmrkProperty;246247                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {248                        Ok(id) => id,249                        Err(_) => return Ok(Vec::new())250                    };251                    let nft_id = TokenId(nft_id);252                    if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); }253254                    Ok(255                        pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))256                            .filter_map(|((child_collection, child_token), _)| {257                                let is_pending = RmrkCore::get_nft_property_decoded(258                                    child_collection,259                                    child_token,260                                    RmrkProperty::PendingNftAccept261                                ).ok()?;262263                                if is_pending {264                                    return None;265                                }266267                                let rmrk_child_collection = RmrkCore::rmrk_collection_id(268                                    child_collection269                                ).ok()?;270271                                Some(RmrkNftChild {272                                    collection_id: rmrk_child_collection,273                                    nft_id: child_token.0,274                                })275                            }).collect()276                    )277                }278279                fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {280                    use pallet_proxy_rmrk_core::misc::CollectionType;281282                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {283                        Ok(id) => id,284                        Err(_) => return Ok(Vec::new())285                    };286                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {287                        return Ok(Vec::new());288                    }289290                    let properties = RmrkCore::filter_user_properties(291                        collection_id,292                        /* token_id = */ None,293                        filter_keys,294                        |key, value| RmrkPropertyInfo {295                            key,296                            value297                        }298                    )?;299300                    Ok(properties)301                }302303                fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {304                    use pallet_proxy_rmrk_core::misc::NftType;305306                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {307                        Ok(id) => id,308                        Err(_) => return Ok(Vec::new())309                    };310                    let token_id = TokenId(nft_id);311312                    if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {313                        return Ok(Vec::new());314                    }315316		            let properties = RmrkCore::filter_user_properties(317                        collection_id,318                        Some(token_id),319                        filter_keys,320                        |key, value| RmrkPropertyInfo {321                            key,322                            value323                        }324                    )?;325326                    Ok(properties)327                }328329                fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {330                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};331                    use pallet_common::CommonCollectionOperations;332333                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {334                        Ok(id) => id,335                        Err(_) => return Ok(Vec::new())336                    };337                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }338339                    let nft_id = TokenId(nft_id);340                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(Vec::new()); }341342                    let res_collection_id: CollectionId = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourceCollection)?;343                    let resource_collection = RmrkCore::get_typed_nft_collection(res_collection_id, CollectionType::Resource)?;344345                    let resources = resource_collection346                        .collection_tokens()347                        .iter()348                        .filter_map(|(res_id)| Some(RmrkResourceInfo {349                            id: res_id.0,350                            pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).ok()?,351                            pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).ok()?,352                            resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).ok()? {353                                ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {354                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?,355                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?,356                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?,357                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?,358                                }),359                                ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {360                                    parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).ok()?,361                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).ok()?,362                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?,363                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?,364                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?,365                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?,366                                }),367                                ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {368                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).ok()?,369                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?,370                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?,371                                    slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).ok()?,372                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?,373                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?,374                                }),375                            },376                        }))377                        .collect();378379                    Ok(resources)380                }381382                fn nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {383                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};384385                    let collection_id = match RmrkCore::unique_collection_id(collection_id) {386                        Ok(id) => id,387                        Err(_) => return Ok(None)388                    };389                    if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(None); }390391                    let nft_id = TokenId(nft_id);392                    if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() { return Ok(None); }393394                    let priorities: Vec<_> = RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::ResourcePriorities)?;395                    Ok(396                        priorities.into_iter()397                            .enumerate()398                            .find(|(_, id)| *id == resource_id)399                            .map(|(priority, _): (usize, RmrkResourceId)| priority as u32)400                    )401                }402403                fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {404                    use pallet_proxy_rmrk_core::{405                        RmrkProperty, misc::{CollectionType},406                    };407408                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) {409                        Ok(c) => c,410                        Err(_) => return Ok(None),411                    };412413                    Ok(Some(RmrkBaseInfo {414                        issuer: collection.owner.clone(),415                        base_type: RmrkCore::get_collection_property_decoded(collection_id, RmrkProperty::BaseType)?,416                        symbol: RmrkCore::rebind(&collection.token_prefix)?,417                    }))418                }419420                fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {421                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};422                    use pallet_common::CommonCollectionOperations;423424                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) {425                        Ok(c) => c,426                        Err(_) => return Ok(Vec::new()),427                    };428429                    let parts = collection.collection_tokens()430                        .into_iter()431                        .filter_map(|token_id| {432                            let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?;433434                            match nft_type {435                                NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart {436                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,437                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,438                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,439                                })),440                                NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart {441                                    id: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?,442                                    src: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::Src).ok()?,443                                    z: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::ZIndex).ok()?,444                                    equippable: RmrkCore::get_nft_property_decoded(collection_id, token_id, RmrkProperty::EquippableList).ok()?,445                                })),446                                _ => None447                            }448                        })449                        .collect();450451                    Ok(parts)452                }453454                fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {455                    use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};456                    use pallet_common::CommonCollectionOperations;457458                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) {459                        Ok(c) => c,460                        Err(_) => return Ok(Vec::new()),461                    };462463                    let theme_names = collection.collection_tokens()464                        .iter()465                        .filter_map(|token_id| {466                            let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).ok()?;467468                            match nft_type {469                                Theme => RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).ok(),470                                _ => None471                            }472                        })473                        .collect();474475                    Ok(theme_names)476                }477478                fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {479                    use pallet_proxy_rmrk_core::{480                        RmrkProperty,481                        misc::{CollectionType, NftType}482                    };483                    use pallet_common::CommonCollectionOperations;484485                    let (collection, collection_id) = match RmrkCore::get_typed_nft_collection_mapped(base_id, CollectionType::Base) {486                        Ok(c) => c,487                        Err(_) => return Ok(None),488                    };489490                    let theme_info = collection.collection_tokens()491                        .into_iter()492                        .find_map(|token_id| {493                            RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;494495                            let name: RmrkString = RmrkCore::get_nft_property_decoded(496                                collection_id, token_id, RmrkProperty::ThemeName497                            ).ok()?;498499                            if name == theme_name {500                                Some((name, token_id))501                            } else {502                                None503                            }504                        });505506                    let (name, theme_id) = match theme_info {507                        Some((name, theme_id)) => (name, theme_id),508                        None => return Ok(None)509                    };510511                    let properties = RmrkCore::filter_user_properties(512                        collection_id,513                        Some(theme_id),514                        filter_keys,515                        |key, value| RmrkThemeProperty {516                            key,517                            value518                        }519                    )?;520521                    let inherit = RmrkCore::get_nft_property_decoded(522                        collection_id,523                        theme_id,524                        RmrkProperty::ThemeInherit525                    )?;526527                    let theme = RmrkTheme {528                        name,529                        properties,530                        inherit,531                    };532533                    Ok(Some(theme))534                }535            }536537            impl sp_api::Core<Block> for Runtime {538                fn version() -> RuntimeVersion {539                    VERSION540                }541542                fn execute_block(block: Block) {543                    Executive::execute_block(block)544                }545546                fn initialize_block(header: &<Block as BlockT>::Header) {547                    Executive::initialize_block(header)548                }549            }550551            impl sp_api::Metadata<Block> for Runtime {552                fn metadata() -> OpaqueMetadata {553                    OpaqueMetadata::new(Runtime::metadata().into())554                }555            }556557            impl sp_block_builder::BlockBuilder<Block> for Runtime {558                fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {559                    Executive::apply_extrinsic(extrinsic)560                }561562                fn finalize_block() -> <Block as BlockT>::Header {563                    Executive::finalize_block()564                }565566                fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {567                    data.create_extrinsics()568                }569570                fn check_inherents(571                    block: Block,572                    data: sp_inherents::InherentData,573                ) -> sp_inherents::CheckInherentsResult {574                    data.check_extrinsics(&block)575                }576577                // fn random_seed() -> <Block as BlockT>::Hash {578                //     RandomnessCollectiveFlip::random_seed().0579                // }580            }581582            impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {583                fn validate_transaction(584                    source: TransactionSource,585                    tx: <Block as BlockT>::Extrinsic,586                    hash: <Block as BlockT>::Hash,587                ) -> TransactionValidity {588                    Executive::validate_transaction(source, tx, hash)589                }590            }591592            impl sp_offchain::OffchainWorkerApi<Block> for Runtime {593                fn offchain_worker(header: &<Block as BlockT>::Header) {594                    Executive::offchain_worker(header)595                }596            }597598            impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {599                fn chain_id() -> u64 {600                    <Runtime as pallet_evm::Config>::ChainId::get()601                }602603                fn account_basic(address: H160) -> EVMAccount {604                    let (account, _) = EVM::account_basic(&address);605                    account606                }607608                fn gas_price() -> U256 {609                    let (price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();610                    price611                }612613                fn account_code_at(address: H160) -> Vec<u8> {614                    EVM::account_codes(address)615                }616617                fn author() -> H160 {618                    <pallet_evm::Pallet<Runtime>>::find_author()619                }620621                fn storage_at(address: H160, index: U256) -> H256 {622                    let mut tmp = [0u8; 32];623                    index.to_big_endian(&mut tmp);624                    EVM::account_storages(address, H256::from_slice(&tmp[..]))625                }626627                #[allow(clippy::redundant_closure)]628                fn call(629                    from: H160,630                    to: H160,631                    data: Vec<u8>,632                    value: U256,633                    gas_limit: U256,634                    max_fee_per_gas: Option<U256>,635                    max_priority_fee_per_gas: Option<U256>,636                    nonce: Option<U256>,637                    estimate: bool,638                    access_list: Option<Vec<(H160, Vec<H256>)>>,639                ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {640                    let config = if estimate {641                        let mut config = <Runtime as pallet_evm::Config>::config().clone();642                        config.estimate = true;643                        Some(config)644                    } else {645                        None646                    };647648                    let is_transactional = false;649                    <Runtime as pallet_evm::Config>::Runner::call(650                        CrossAccountId::from_eth(from),651                        to,652                        data,653                        value,654                        gas_limit.low_u64(),655                        max_fee_per_gas,656                        max_priority_fee_per_gas,657                        nonce,658                        access_list.unwrap_or_default(),659                        is_transactional,660                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),661                    ).map_err(|err| err.error.into())662                }663664                #[allow(clippy::redundant_closure)]665                fn create(666                    from: H160,667                    data: Vec<u8>,668                    value: U256,669                    gas_limit: U256,670                    max_fee_per_gas: Option<U256>,671                    max_priority_fee_per_gas: Option<U256>,672                    nonce: Option<U256>,673                    estimate: bool,674                    access_list: Option<Vec<(H160, Vec<H256>)>>,675                ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {676                    let config = if estimate {677                        let mut config = <Runtime as pallet_evm::Config>::config().clone();678                        config.estimate = true;679                        Some(config)680                    } else {681                        None682                    };683684                    let is_transactional = false;685                    <Runtime as pallet_evm::Config>::Runner::create(686                        CrossAccountId::from_eth(from),687                        data,688                        value,689                        gas_limit.low_u64(),690                        max_fee_per_gas,691                        max_priority_fee_per_gas,692                        nonce,693                        access_list.unwrap_or_default(),694                        is_transactional,695                        config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),696                    ).map_err(|err| err.error.into())697                }698699                fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {700                    Ethereum::current_transaction_statuses()701                }702703                fn current_block() -> Option<pallet_ethereum::Block> {704                    Ethereum::current_block()705                }706707                fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {708                    Ethereum::current_receipts()709                }710711                fn current_all() -> (712                    Option<pallet_ethereum::Block>,713                    Option<Vec<pallet_ethereum::Receipt>>,714                    Option<Vec<TransactionStatus>>715                ) {716                    (717                        Ethereum::current_block(),718                        Ethereum::current_receipts(),719                        Ethereum::current_transaction_statuses()720                    )721                }722723                fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {724                    xts.into_iter().filter_map(|xt| match xt.0.function {725                        Call::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),726                        _ => None727                    }).collect()728                }729730                fn elasticity() -> Option<Permill> {731                    None732                }733            }734735            impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {736                fn convert_transaction(transaction: pallet_ethereum::Transaction) -> <Block as BlockT>::Extrinsic  {737                    UncheckedExtrinsic::new_unsigned(738                        pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),739                    )740                }741            }742743            impl sp_session::SessionKeys<Block> for Runtime {744                fn decode_session_keys(745                    encoded: Vec<u8>,746                ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {747                    SessionKeys::decode_into_raw_public_keys(&encoded)748                }749750                fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {751                    SessionKeys::generate(seed)752                }753            }754755            impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {756                fn slot_duration() -> sp_consensus_aura::SlotDuration {757                    sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())758                }759760                fn authorities() -> Vec<AuraId> {761                    Aura::authorities().to_vec()762                }763            }764765            impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {766                fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {767                    ParachainSystem::collect_collation_info(header)768                }769            }770771            impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {772                fn account_nonce(account: AccountId) -> Index {773                    System::account_nonce(account)774                }775            }776777            impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {778                fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {779                    TransactionPayment::query_info(uxt, len)780                }781                fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {782                    TransactionPayment::query_fee_details(uxt, len)783                }784            }785786            /*787            impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>788                for Runtime789            {790                fn call(791                    origin: AccountId,792                    dest: AccountId,793                    value: Balance,794                    gas_limit: u64,795                    input_data: Vec<u8>,796                ) -> pallet_contracts_primitives::ContractExecResult {797                    Contracts::bare_call(origin, dest, value, gas_limit, input_data, false)798                }799800                fn instantiate(801                    origin: AccountId,802                    endowment: Balance,803                    gas_limit: u64,804                    code: pallet_contracts_primitives::Code<Hash>,805                    data: Vec<u8>,806                    salt: Vec<u8>,807                ) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber>808                {809                    Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true, false)810                }811812                fn get_storage(813                    address: AccountId,814                    key: [u8; 32],815                ) -> pallet_contracts_primitives::GetStorageResult {816                    Contracts::get_storage(address, key)817                }818819                fn rent_projection(820                    address: AccountId,821                ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {822                    Contracts::rent_projection(address)823                }824            }825            */826827            #[cfg(feature = "runtime-benchmarks")]828            impl frame_benchmarking::Benchmark<Block> for Runtime {829                fn benchmark_metadata(extra: bool) -> (830                    Vec<frame_benchmarking::BenchmarkList>,831                    Vec<frame_support::traits::StorageInfo>,832                ) {833                    use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};834                    use frame_support::traits::StorageInfoTrait;835836                    let mut list = Vec::<BenchmarkList>::new();837838                    list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);839                    list_benchmark!(list, extra, pallet_common, Common);840                    list_benchmark!(list, extra, pallet_unique, Unique);841                    list_benchmark!(list, extra, pallet_structure, Structure);842                    list_benchmark!(list, extra, pallet_inflation, Inflation);843                    list_benchmark!(list, extra, pallet_fungible, Fungible);844                    list_benchmark!(list, extra, pallet_refungible, Refungible);845                    list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);846                    list_benchmark!(list, extra, pallet_proxy_rmrk_core, RmrkCore);847                    // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);848849                    let storage_info = AllPalletsReversedWithSystemFirst::storage_info();850851                    return (list, storage_info)852                }853854                fn dispatch_benchmark(855                    config: frame_benchmarking::BenchmarkConfig856                ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {857                    use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};858859                    let allowlist: Vec<TrackedStorageKey> = vec![860                        // Total Issuance861                        hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),862863                        // Block Number864                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),865                        // Execution Phase866                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),867                        // Event Count868                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),869                        // System Events870                        hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),871872                        // Evm CurrentLogs873                        hex_literal::hex!("1da53b775b270400e7e61ed5cbc5a146547f210cec367e9af919603343b9cb56").to_vec().into(),874875                        // Transactional depth876                        hex_literal::hex!("3a7472616e73616374696f6e5f6c6576656c3a").to_vec().into(),877                    ];878879                    let mut batches = Vec::<BenchmarkBatch>::new();880                    let params = (&config, &allowlist);881882                    add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);883                    add_benchmark!(params, batches, pallet_common, Common);884                    add_benchmark!(params, batches, pallet_unique, Unique);885                    add_benchmark!(params, batches, pallet_structure, Structure);886                    add_benchmark!(params, batches, pallet_inflation, Inflation);887                    add_benchmark!(params, batches, pallet_fungible, Fungible);888                    add_benchmark!(params, batches, pallet_refungible, Refungible);889                    add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);890                    add_benchmark!(params, batches, pallet_proxy_rmrk_core, RmrkCore);891                    // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);892893                    if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }894                    Ok(batches)895                }896            }897898            #[cfg(feature = "try-runtime")]899            impl frame_try_runtime::TryRuntime<Block> for Runtime {900                fn on_runtime_upgrade() -> (Weight, Weight) {901                    log::info!("try-runtime::on_runtime_upgrade unique-chain.");902                    let weight = Executive::try_runtime_upgrade().unwrap();903                    (weight, RuntimeBlockWeights::get().max_block)904                }905906                fn execute_block_no_check(block: Block) -> Weight {907                    Executive::execute_block_no_check(block)908                }909            }910        }911    }912}
modifiedruntime/common/src/types.rsdiffbeforeafterboth
--- a/runtime/common/src/types.rs
+++ b/runtime/common/src/types.rs
@@ -1,3 +1,19 @@
+// 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 sp_runtime::{
 	traits::{Verify, IdentifyAccount, BlakeTwo256},
 	generic, MultiSignature,
modifiedruntime/opal/src/lib.rsdiffbeforeafterboth
--- a/runtime/opal/src/lib.rs
+++ b/runtime/opal/src/lib.rs
@@ -919,6 +919,7 @@
 }
 
 impl pallet_proxy_rmrk_core::Config for Runtime {
+	type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
 	type Event = Event;
 }
 
modifiedruntime/quartz/src/lib.rsdiffbeforeafterboth
--- a/runtime/quartz/src/lib.rs
+++ b/runtime/quartz/src/lib.rs
@@ -918,6 +918,7 @@
 }
 
 impl pallet_proxy_rmrk_core::Config for Runtime {
+	type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
 	type Event = Event;
 }
 
modifiedruntime/unique/src/lib.rsdiffbeforeafterboth
--- a/runtime/unique/src/lib.rs
+++ b/runtime/unique/src/lib.rs
@@ -917,6 +917,7 @@
 }
 
 impl pallet_proxy_rmrk_core::Config for Runtime {
+	type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
 	type Event = Event;
 }
 
modifiedtests/src/addCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/addCollectionAdmin.test.ts
+++ b/tests/src/addCollectionAdmin.test.ts
@@ -40,8 +40,10 @@
       expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
     });
   });
+});
 
-  it('Add admin using added collection admin.', async () => {
+describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
+  it("Not owner can't add collection admin.", async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       const collectionId = await createCollectionExpectSuccess();
       const alice = privateKeyWrapper('//Alice');
@@ -51,38 +53,43 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.equal(alice.address);
 
-      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
-      await submitTransactionAsync(alice, changeAdminTx);
-
       const adminListAfterAddAdmin = await getAdminList(api, collectionId);
-      expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+      expect(adminListAfterAddAdmin).to.be.not.deep.contains(normalizeAccountId(bob.address));
 
       const changeAdminTxCharlie = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
-      await submitTransactionAsync(bob, changeAdminTxCharlie);
+      await expect(submitTransactionAsync(bob, changeAdminTxCharlie)).to.be.rejected;
+     
       const adminListAfterAddNewAdmin = await getAdminList(api, collectionId);
-      expect(adminListAfterAddNewAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
-      expect(adminListAfterAddNewAdmin).to.be.deep.contains(normalizeAccountId(charlie.address));
+      expect(adminListAfterAddNewAdmin).to.be.not.deep.contains(normalizeAccountId(bob.address));
+      expect(adminListAfterAddNewAdmin).to.be.not.deep.contains(normalizeAccountId(charlie.address));
     });
   });
-});
 
-describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
-  it("Not owner can't add collection admin.", async () => {
+  it("Admin can't add collection admin.", async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       const collectionId = await createCollectionExpectSuccess();
       const alice = privateKeyWrapper('//Alice');
-      const nonOwner = privateKeyWrapper('//Bob_stash');
+      const bob = privateKeyWrapper('//Bob');
+      const charlie = privateKeyWrapper('//CHARLIE');
+
+      const collection = await queryCollectionExpectSuccess(api, collectionId);
+      expect(collection.owner.toString()).to.be.equal(alice.address);
 
-      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(alice.address));
-      await expect(submitTransactionExpectFailAsync(nonOwner, changeAdminTx)).to.be.rejected;
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      await submitTransactionAsync(alice, changeAdminTx);
 
       const adminListAfterAddAdmin = await getAdminList(api, collectionId);
-      expect(adminListAfterAddAdmin).not.to.be.deep.contains(normalizeAccountId(alice.address));
+      expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
 
-      // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
-      await createCollectionExpectSuccess();
+      const changeAdminTxCharlie = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
+      await expect(submitTransactionAsync(bob, changeAdminTxCharlie)).to.be.rejected;
+     
+      const adminListAfterAddNewAdmin = await getAdminList(api, collectionId);
+      expect(adminListAfterAddNewAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+      expect(adminListAfterAddNewAdmin).to.be.not.deep.contains(normalizeAccountId(charlie.address));
     });
   });
+
   it("Can't add collection admin of not existing collection.", async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       // tslint:disable-next-line: no-bitwise
modifiedtests/src/eth/allowlist.test.tsdiffbeforeafterboth
--- a/tests/src/eth/allowlist.test.ts
+++ b/tests/src/eth/allowlist.test.ts
@@ -18,8 +18,8 @@
 import {contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3} from './util/helpers';
 
 describe('EVM allowlist', () => {
-  itWeb3('Contract allowlist can be toggled', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Contract allowlist can be toggled', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
 
     const helpers = contractHelpers(web3, owner);
@@ -36,10 +36,10 @@
     expect(await helpers.methods.allowlistEnabled(flipper.options.address).call()).to.be.false;
   });
 
-  itWeb3('Non-allowlisted user can\'t call contract with allowlist enabled', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Non-allowlisted user can\'t call contract with allowlist enabled', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const helpers = contractHelpers(web3, owner);
 
modifiedtests/src/eth/base.test.tsdiffbeforeafterboth
--- a/tests/src/eth/base.test.ts
+++ b/tests/src/eth/base.test.ts
@@ -32,16 +32,16 @@
 import Web3 from 'web3';
 
 describe('Contract calls', () => {
-  itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({web3, api}) => {
-    const deployer = await createEthAccountWithBalance(api, web3);
+  itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({web3, api, privateKeyWrapper}) => {
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, deployer);
 
     const cost = await recordEthFee(api, deployer, () => flipper.methods.flip().send({from: deployer}));
     expect(cost < BigInt(0.2 * Number(UNIQUE))).to.be.true;
   });
 
-  itWeb3('Balance transfer fee is less than 0.2 UNQ', async ({web3, api}) => {
-    const userA = await createEthAccountWithBalance(api, web3);
+  itWeb3('Balance transfer fee is less than 0.2 UNQ', async ({web3, api, privateKeyWrapper}) => {
+    const userA = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const userB = createEthAccount(web3);
 
     const cost = await recordEthFee(api, userA, () => web3.eth.sendTransaction({from: userA, to: userB, value: '1000000', ...GAS_ARGS}));
@@ -50,7 +50,7 @@
   });
 
   itWeb3('NFT transfer is close to 0.15 UNQ', async ({web3, api, privateKeyWrapper}) => {
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
 
     const alice = privateKeyWrapper('//Alice');
modifiedtests/src/eth/collectionProperties.test.tsdiffbeforeafterboth
--- a/tests/src/eth/collectionProperties.test.ts
+++ b/tests/src/eth/collectionProperties.test.ts
@@ -7,7 +7,7 @@
 describe('EVM collection properties', () => {
   itWeb3('Can be set', async({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
 
     await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
@@ -22,7 +22,7 @@
   });
   itWeb3('Can be deleted', async({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
 
     await executeTransaction(api, alice, api.tx.unique.setCollectionProperties(collection, [{key: 'testKey', value: 'testValue'}]));
modifiedtests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/contractSponsoring.test.ts
+++ b/tests/src/eth/contractSponsoring.test.ts
@@ -44,8 +44,8 @@
 import {evmToAddress} from '@polkadot/util-crypto';
 
 describe('Sponsoring EVM contracts', () => {
-  itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
     const helpers = contractHelpers(web3, owner);
     expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
@@ -53,9 +53,9 @@
     expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
   });
 
-  itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
-    const notOwner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
     const helpers = contractHelpers(web3, owner);
     expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
@@ -66,8 +66,8 @@
   itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const flipper = await deployFlipper(web3, owner);
 
@@ -94,7 +94,7 @@
   itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should decrease (allowlisted)', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const caller = createEthAccount(web3);
 
     const flipper = await deployFlipper(web3, owner);
@@ -124,7 +124,7 @@
   itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should not decrease (non-allowlisted)', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const caller = createEthAccount(web3);
 
     const flipper = await deployFlipper(web3, owner);
@@ -152,8 +152,8 @@
   itWeb3('Sponsoring is set, an address that has UNQ can send a transaction and it works. User balance should not change', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const originalCallerBalance = await web3.eth.getBalance(caller);
 
     const flipper = await deployFlipper(web3, owner);
@@ -181,8 +181,8 @@
   itWeb3('Sponsoring is limited, with setContractRateLimit. The limitation is working if transactions are sent more often, the sender pays the commission.', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const originalCallerBalance = await web3.eth.getBalance(caller);
 
     const flipper = await deployFlipper(web3, owner);
@@ -214,30 +214,31 @@
   });
 
   // TODO: Find a way to calculate default rate limit
-  itWeb3('Default rate limit equals 7200', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Default rate limit equals 7200', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
     const helpers = contractHelpers(web3, owner);
     expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');
   });
 
-  itWeb3('Sponsoring collection from evm address via access list', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Sponsoring collection from evm address via access list', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
-    const sponsor = await createEthAccountWithBalance(api, web3);
+    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
     result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});
     let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
+    const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
     expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
     await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
 
     await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
     collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
     expect(collectionSub.sponsorship.isConfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
 
     const user = createEthAccount(web3);
     const nextTokenId = await collectionEvm.methods.nextTokenId().call();
@@ -289,23 +290,24 @@
     }
   });
 
-  itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
-    const sponsor = await createEthAccountWithBalance(api, web3);
+    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
     result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();
     let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
+    const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
     expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
     await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
     const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
     collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
     expect(collectionSub.sponsorship.isConfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
 
     const user = createEthAccount(web3);
     await collectionEvm.methods.addCollectionAdmin(user).send();
modifiedtests/src/eth/createCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createCollection.test.ts
+++ b/tests/src/eth/createCollection.test.ts
@@ -28,67 +28,68 @@
 } from './util/helpers';
 
 describe('Create collection from EVM', () => {
-  itWeb3('Create collection', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
-    const collectionHelper = evmCollectionHelpers(web3, owner);
-    const collectionName = 'CollectionEVM';
-    const description = 'Some description';
-    const tokenPrefix = 'token prefix';
+  // itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {
+  //   const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+  //   const collectionHelper = evmCollectionHelpers(web3, owner);
+  //   const collectionName = 'CollectionEVM';
+  //   const description = 'Some description';
+  //   const tokenPrefix = 'token prefix';
   
-    const collectionCountBefore = await getCreatedCollectionCount(api);
-    const result = await collectionHelper.methods
-      .createNonfungibleCollection(collectionName, description, tokenPrefix)
-      .send();
-    const collectionCountAfter = await getCreatedCollectionCount(api);
+  //   const collectionCountBefore = await getCreatedCollectionCount(api);
+  //   const result = await collectionHelper.methods
+  //     .createNonfungibleCollection(collectionName, description, tokenPrefix)
+  //     .send();
+  //   const collectionCountAfter = await getCreatedCollectionCount(api);
   
-    const {collectionId, collection} = await getCollectionAddressFromResult(api, result);
-    expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);
-    expect(collectionId).to.be.eq(collectionCountAfter);
-    expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);
-    expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);
-    expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);
-  });
+  //   const {collectionId, collection} = await getCollectionAddressFromResult(api, result);
+  //   expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);
+  //   expect(collectionId).to.be.eq(collectionCountAfter);
+  //   expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);
+  //   expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);
+  //   expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);
+  // });
 
-  itWeb3('Check collection address exist', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
-    const collectionHelpers = evmCollectionHelpers(web3, owner);
+  // itWeb3('Check collection address exist', async ({api, web3, privateKeyWrapper}) => {
+  //   const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+  //   const collectionHelpers = evmCollectionHelpers(web3, owner);
   
-    const expectedCollectionId = await getCreatedCollectionCount(api) + 1;
-    const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId);
-    expect(await collectionHelpers.methods
-      .isCollectionExist(expectedCollectionAddress)
-      .call()).to.be.false;
+  //   const expectedCollectionId = await getCreatedCollectionCount(api) + 1;
+  //   const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId);
+  //   expect(await collectionHelpers.methods
+  //     .isCollectionExist(expectedCollectionAddress)
+  //     .call()).to.be.false;
 
-    await collectionHelpers.methods
-      .createNonfungibleCollection('A', 'A', 'A')
-      .send();
+  //   await collectionHelpers.methods
+  //     .createNonfungibleCollection('A', 'A', 'A')
+  //     .send();
     
-    expect(await collectionHelpers.methods
-      .isCollectionExist(expectedCollectionAddress)
-      .call()).to.be.true;
-  });
+  //   expect(await collectionHelpers.methods
+  //     .isCollectionExist(expectedCollectionAddress)
+  //     .call()).to.be.true;
+  // });
   
-  itWeb3('Set sponsorship', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Set sponsorship', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
-    const sponsor = await createEthAccountWithBalance(api, web3);
+    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
     result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();
     let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
     expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
+    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
     await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
     const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
     collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
     expect(collectionSub.sponsorship.isConfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
   });
 
-  itWeb3('Set limits', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Set limits', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     const result = await collectionHelpers.methods.createNonfungibleCollection('Const collection', '5', '5').send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
@@ -127,8 +128,8 @@
     expect(collectionSub.limits.transfersEnabled.toHuman()).to.be.eq(limits.transfersEnabled);
   });
 
-  itWeb3('Collection address exist', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Collection address exist', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     expect(await collectionHelpers.methods
@@ -144,8 +145,8 @@
 });
 
 describe('(!negative tests!) Create collection from EVM', () => {
-  itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const helper = evmCollectionHelpers(web3, owner);
     {
       const MAX_NAME_LENGHT = 64;
@@ -190,8 +191,8 @@
       .call()).to.be.rejectedWith('NotSufficientFounds');
   });
 
-  itWeb3('(!negative test!) Check owner', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('(!negative test!) Check owner', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const notOwner = await createEthAccount(web3);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     const result = await collectionHelpers.methods.createNonfungibleCollection('A', 'A', 'A').send();
@@ -199,7 +200,7 @@
     const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress);
     const EXPECTED_ERROR = 'NoPermission';
     {
-      const sponsor = await createEthAccountWithBalance(api, web3);
+      const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
       await expect(contractEvmFromNotOwner.methods
         .setCollectionSponsor(sponsor)
         .call()).to.be.rejectedWith(EXPECTED_ERROR);
@@ -216,8 +217,8 @@
     }
   });
 
-  itWeb3('(!negative test!) Set limits', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('(!negative test!) Set limits', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     const result = await collectionHelpers.methods.createNonfungibleCollection('Schema collection', 'A', 'A').send();
     const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
modifiedtests/src/eth/crossTransfer.test.tsdiffbeforeafterboth
--- a/tests/src/eth/crossTransfer.test.ts
+++ b/tests/src/eth/crossTransfer.test.ts
@@ -48,8 +48,8 @@
     });
     const alice = privateKeyWrapper('//Alice');
     const bob = privateKeyWrapper('//Bob');
-    const bobProxy = await createEthAccountWithBalance(api, web3);
-    const aliceProxy = await createEthAccountWithBalance(api, web3);
+    const bobProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const aliceProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, alice.address);
     await transferExpectSuccess(collection, 0, alice, {Ethereum: aliceProxy} , 200, 'Fungible');
@@ -85,8 +85,8 @@
     const alice = privateKeyWrapper('//Alice');
     const bob = privateKeyWrapper('//Bob');
     const charlie = privateKeyWrapper('//Charlie');
-    const bobProxy = await createEthAccountWithBalance(api, web3);
-    const aliceProxy = await createEthAccountWithBalance(api, web3);
+    const bobProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const aliceProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
     await transferExpectSuccess(collection, tokenId, alice, {Ethereum: aliceProxy} , 1, 'NFT');
     const address = collectionIdToAddress(collection);
modifiedtests/src/eth/fungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/fungible.test.ts
+++ b/tests/src/eth/fungible.test.ts
@@ -27,7 +27,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address});
 
@@ -45,7 +45,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: caller});
 
@@ -65,7 +65,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
 
@@ -208,7 +208,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const spender = createEthAccount(web3);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
@@ -226,8 +226,8 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const spender = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
 
@@ -246,7 +246,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
modifiedtests/src/eth/helpersSmoke.test.tsdiffbeforeafterboth
--- a/tests/src/eth/helpersSmoke.test.ts
+++ b/tests/src/eth/helpersSmoke.test.ts
@@ -18,16 +18,16 @@
 import {createEthAccountWithBalance, deployFlipper, itWeb3, contractHelpers} from './util/helpers';
 
 describe('Helpers sanity check', () => {
-  itWeb3('Contract owner is recorded', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Contract owner is recorded', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const flipper = await deployFlipper(web3, owner);
 
     expect(await contractHelpers(web3, owner).methods.contractOwner(flipper.options.address).call()).to.be.equal(owner);
   });
 
-  itWeb3('Flipper is working', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Flipper is working', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
 
     expect(await flipper.methods.getValue().call()).to.be.false;
modifiedtests/src/eth/marketplace/marketplace.test.tsdiffbeforeafterboth
--- a/tests/src/eth/marketplace/marketplace.test.ts
+++ b/tests/src/eth/marketplace/marketplace.test.ts
@@ -39,7 +39,7 @@
 describe('Matcher contract usage', () => {
   itWeb3('With UNQ', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const matcherOwner = await createEthAccountWithBalance(api, web3);
+    const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
       from: matcherOwner,
       ...GAS_ARGS,
@@ -100,8 +100,8 @@
 
   itWeb3('With escrow', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const matcherOwner = await createEthAccountWithBalance(api, web3);
-    const escrow = await createEthAccountWithBalance(api, web3);
+    const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const escrow = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
       from: matcherOwner,
       ...GAS_ARGS,
@@ -171,7 +171,7 @@
 
   itWeb3('Sell tokens from substrate user via EVM contract', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const matcherOwner = await createEthAccountWithBalance(api, web3);
+    const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
       from: matcherOwner,
       ...GAS_ARGS,
modifiedtests/src/eth/migration.test.tsdiffbeforeafterboth
--- a/tests/src/eth/migration.test.ts
+++ b/tests/src/eth/migration.test.ts
@@ -54,7 +54,7 @@
     ];
 
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.begin(ADDRESS) as any));
     await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.setData(ADDRESS, DATA as any) as any));
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -26,7 +26,7 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
 
@@ -43,7 +43,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum:caller});
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
@@ -61,7 +61,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
 
     const address = collectionIdToAddress(collection);
@@ -73,8 +73,8 @@
 });
 
 describe('NFT: Plain calls', () => {
-  itWeb3('Can perform mint()', async ({web3, api}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const helper = evmCollectionHelpers(web3, owner);
     let result = await helper.methods.createNonfungibleCollection('Mint collection', '6', '6').send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
@@ -119,7 +119,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: caller});
     await submitTransactionAsync(alice, changeAdminTx);
     const receiver = createEthAccount(web3);
@@ -182,7 +182,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
 
@@ -341,7 +341,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const spender = createEthAccount(web3);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
@@ -359,8 +359,8 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const spender = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
 
@@ -379,7 +379,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
@@ -541,12 +541,12 @@
 });
 
 describe('Common metadata', () => {
-  itWeb3('Returns collection name', async ({api, web3}) => {
+  itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {
     const collection = await createCollectionExpectSuccess({
       name: 'token name',
       mode: {type: 'NFT'},
     });
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const address = collectionIdToAddress(collection);
     const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
@@ -555,12 +555,12 @@
     expect(name).to.equal('token name');
   });
 
-  itWeb3('Returns symbol name', async ({api, web3}) => {
+  itWeb3('Returns symbol name', async ({api, web3, privateKeyWrapper}) => {
     const collection = await createCollectionExpectSuccess({
       tokenPrefix: 'TOK',
       mode: {type: 'NFT'},
     });
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const address = collectionIdToAddress(collection);
     const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
modifiedtests/src/eth/payable.test.tsdiffbeforeafterboth
--- a/tests/src/eth/payable.test.ts
+++ b/tests/src/eth/payable.test.ts
@@ -22,8 +22,8 @@
 import {getBalanceSingle, transferBalanceExpectSuccess} from '../substrate/get-balance';
 
 describe('EVM payable contracts', () => {
-  itWeb3('Evm contract can receive wei from eth account', async ({api, web3}) => {
-    const deployer = await createEthAccountWithBalance(api, web3);
+  itWeb3('Evm contract can receive wei from eth account', async ({api, web3, privateKeyWrapper}) => {
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const contract = await deployCollector(web3, deployer);
 
     await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: '10000', ...GAS_ARGS});
@@ -32,7 +32,7 @@
   });
 
   itWeb3('Evm contract can receive wei from substrate account', async ({api, web3, privateKeyWrapper}) => {
-    const deployer = await createEthAccountWithBalance(api, web3);
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const contract = await deployCollector(web3, deployer);
     const alice = privateKeyWrapper('//Alice');
 
@@ -62,7 +62,7 @@
 
   // We can't handle sending balance to backing storage of evm balance, because evmToAddress operation is irreversible
   itWeb3('Wei sent directly to backing storage of evm contract balance is unaccounted', async({api, web3, privateKeyWrapper}) => {
-    const deployer = await createEthAccountWithBalance(api, web3);
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const contract = await deployCollector(web3, deployer);
     const alice = privateKeyWrapper('//Alice');
 
@@ -75,7 +75,7 @@
     const FEE_BALANCE = 1000n * UNIQUE;
     const CONTRACT_BALANCE = 1n * UNIQUE;
 
-    const deployer = await createEthAccountWithBalance(api, web3);
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const contract = await deployCollector(web3, deployer);
     const alice = privateKeyWrapper('//Alice');
 
modifiedtests/src/eth/proxy/fungibleProxy.test.tsdiffbeforeafterboth
--- a/tests/src/eth/proxy/fungibleProxy.test.ts
+++ b/tests/src/eth/proxy/fungibleProxy.test.ts
@@ -21,10 +21,11 @@
 import {ApiPromise} from '@polkadot/api';
 import Web3 from 'web3';
 import {readFile} from 'fs/promises';
+import {IKeyringPair} from '@polkadot/types/types';
 
-async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {
+async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any, privateKeyWrapper: (account: string) => IKeyringPair) {
   // Proxy owner has no special privilegies, we don't need to reuse them
-  const owner = await createEthAccountWithBalance(api, web3);
+  const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
   const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueFungibleProxy.abi`)).toString()), undefined, {
     from: owner,
     ...GAS_ARGS,
@@ -40,12 +41,12 @@
       mode: {type: 'Fungible', decimalPoints: 0},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address});
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const totalSupply = await contract.methods.totalSupply().call();
 
     expect(totalSupply).to.equal('200');
@@ -57,12 +58,12 @@
       mode: {type: 'Fungible', decimalPoints: 0},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: caller});
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const balance = await contract.methods.balanceOf(caller).call();
 
     expect(balance).to.equal('200');
@@ -76,11 +77,11 @@
       mode: {type: 'Fungible', decimalPoints: 0},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const spender = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: contract.options.address});
 
     {
@@ -112,8 +113,8 @@
       mode: {type: 'Fungible', decimalPoints: 0},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
-    const owner = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
 
@@ -121,7 +122,7 @@
 
     const address = collectionIdToAddress(collection);
     const evmCollection = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS});
-    const contract = await proxyWrap(api, web3, evmCollection);
+    const contract = await proxyWrap(api, web3, evmCollection, privateKeyWrapper);
 
     await evmCollection.methods.approve(contract.options.address, 100).send({from: owner});
 
@@ -167,11 +168,11 @@
       mode: {type: 'Fungible', decimalPoints: 0},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
-    const receiver = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: contract.options.address});
 
     {
modifiedtests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth
--- a/tests/src/eth/proxy/nonFungibleProxy.test.ts
+++ b/tests/src/eth/proxy/nonFungibleProxy.test.ts
@@ -22,10 +22,11 @@
 import Web3 from 'web3';
 import {readFile} from 'fs/promises';
 import {ApiPromise} from '@polkadot/api';
+import {IKeyringPair} from '@polkadot/types/types';
 
-async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {
+async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any, privateKeyWrapper: (account: string) => IKeyringPair) {
   // Proxy owner has no special privilegies, we don't need to reuse them
-  const owner = await createEthAccountWithBalance(api, web3);
+  const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
   const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {
     from: owner,
     ...GAS_ARGS,
@@ -40,12 +41,12 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const totalSupply = await contract.methods.totalSupply().call();
 
     expect(totalSupply).to.equal('1');
@@ -57,13 +58,13 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const balance = await contract.methods.balanceOf(caller).call();
 
     expect(balance).to.equal('3');
@@ -75,11 +76,11 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const owner = await contract.methods.ownerOf(tokenId).call();
 
     expect(owner).to.equal(caller);
@@ -87,18 +88,18 @@
 });
 
 describe('NFT (Via EVM proxy): Plain calls', () => {
-  itWeb3('Can perform mint()', async ({web3, api}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelper = evmCollectionHelpers(web3, owner);
     const result = await collectionHelper.methods
       .createNonfungibleCollection('A', 'A', 'A')
       .send();
     const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
     const collectionEvmOwned = evmCollection(web3, owner, collectionIdAddress);
     const collectionEvm = evmCollection(web3, caller, collectionIdAddress);
-    const contract = await proxyWrap(api, web3, collectionEvm);
+    const contract = await proxyWrap(api, web3, collectionEvm, privateKeyWrapper);
     await collectionEvmOwned.methods.addCollectionAdmin(contract.options.address).send();
 
     {
@@ -135,11 +136,11 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});
     await submitTransactionAsync(alice, changeAdminTx);
 
@@ -197,10 +198,10 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
 
     const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});
@@ -229,11 +230,11 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const spender = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address), privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
 
     {
@@ -259,14 +260,14 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
-    const owner = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const receiver = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
     const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
-    const contract = await proxyWrap(api, web3, evmCollection);
+    const contract = await proxyWrap(api, web3, evmCollection, privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
 
     await evmCollection.methods.approve(contract.options.address, tokenId).send({from: owner});
@@ -303,11 +304,11 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
 
     {
modifiedtests/src/eth/scheduling.test.tsdiffbeforeafterboth
--- a/tests/src/eth/scheduling.test.ts
+++ b/tests/src/eth/scheduling.test.ts
@@ -17,14 +17,13 @@
 import {expect} from 'chai';
 import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';
 import {scheduleExpectSuccess, waitNewBlocks} from '../util/helpers';
-import privateKey from '../substrate/privateKey';
 
 describe('Scheduing EVM smart contracts', () => {
-  itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3}) => {
-    const deployer = await createEthAccountWithBalance(api, web3);
+  itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3, privateKeyWrapper}) => {
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, deployer);
     const initialValue = await flipper.methods.getValue().call();
-    const alice = privateKey('//Alice');
+    const alice = privateKeyWrapper('//Alice');
     await transferBalanceToEth(api, alice, subToEth(alice.address));
 
     {
modifiedtests/src/eth/sponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/sponsoring.test.ts
+++ b/tests/src/eth/sponsoring.test.ts
@@ -21,7 +21,7 @@
   itWeb3('Fee is deducted from contract if sponsoring is enabled', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const caller = createEthAccount(web3);
     const originalCallerBalance = await web3.eth.getBalance(caller);
     expect(originalCallerBalance).to.be.equal('0');
@@ -52,8 +52,8 @@
   itWeb3('...but this doesn\'t applies to payable value', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const originalCallerBalance = await web3.eth.getBalance(caller);
     expect(originalCallerBalance).to.be.not.equal('0');
 
modifiedtests/src/eth/tokenProperties.test.tsdiffbeforeafterboth
--- a/tests/src/eth/tokenProperties.test.ts
+++ b/tests/src/eth/tokenProperties.test.ts
@@ -7,7 +7,7 @@
 describe('EVM token properties', () => {
   itWeb3('Can be reconfigured', async({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
       await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
@@ -25,7 +25,7 @@
   });
   itWeb3('Can be set', async({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
     const token = await createItemExpectSuccess(alice, collection, 'NFT');
 
@@ -48,7 +48,7 @@
   });
   itWeb3('Can be deleted', async({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
     const token = await createItemExpectSuccess(alice, collection, 'NFT');
 
modifiedtests/src/eth/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/eth/util/helpers.ts
+++ b/tests/src/eth/util/helpers.ts
@@ -112,8 +112,8 @@
   return account.address;
 }
 
-export async function createEthAccountWithBalance(api: ApiPromise, web3: Web3) {
-  const alice = privateKey('//Alice');
+export async function createEthAccountWithBalance(api: ApiPromise, web3: Web3, privateKeyWrapper: (account: string) => IKeyringPair) {
+  const alice = privateKeyWrapper('//Alice');
   const account = createEthAccount(web3);
   await transferBalanceToEth(api, alice, account);
 
modifiedtests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -46,33 +46,6 @@
     });
   });
 
-  it('Remove collection admin by admin.', async () => {
-    await usingApi(async (api, privateKeyWrapper) => {
-      const collectionId = await createCollectionExpectSuccess();
-      const alice = privateKeyWrapper('//Alice');
-      const bob = privateKeyWrapper('//Bob');
-      const charlie = privateKeyWrapper('//Charlie');
-      const collection = await queryCollectionExpectSuccess(api, collectionId);
-      expect(collection.owner.toString()).to.be.eq(alice.address);
-      // first - add collection admin Bob
-      const addAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
-      await submitTransactionAsync(alice, addAdminTx);
-
-      const addAdminTx2 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
-      await submitTransactionAsync(alice, addAdminTx2);
-
-      const adminListAfterAddAdmin = await getAdminList(api, collectionId);
-      expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
-
-      // then remove bob from admins of collection
-      const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
-      await submitTransactionAsync(charlie, removeAdminTx);
-
-      const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
-      expect(adminListAfterRemoveAdmin).not.to.be.deep.contains(normalizeAccountId(bob.address));
-    });
-  });
-
   it('Remove admin from collection that has no admins', async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       const alice = privateKeyWrapper('//Alice');
@@ -120,7 +93,7 @@
     });
   });
 
-  it('Regular user Can\'t remove collection admin', async () => {
+  it('Regular user can\'t remove collection admin', async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       const collectionId = await createCollectionExpectSuccess();
       const alice = privateKeyWrapper('//Alice');
@@ -137,4 +110,23 @@
       await createCollectionExpectSuccess();
     });
   });
+
+  it('Admin can\'t remove collection admin.', async () => {
+    await usingApi(async (api, privateKeyWrapper) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const alice = privateKeyWrapper('//Alice');
+      const bob = privateKeyWrapper('//Bob');
+      const charlie = privateKeyWrapper('//Charlie');
+
+      const adminListAfterAddAdmin = await getAdminList(api, collectionId);
+      expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+
+      const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      await expect(submitTransactionAsync(charlie, removeAdminTx)).to.be.rejected;
+
+      const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
+      expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+      expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(charlie.address));
+    });
+  });
 });
modifiedtests/src/rmrk/rmrk.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/rmrk.test.ts
+++ b/tests/src/rmrk/rmrk.test.ts
@@ -49,8 +49,8 @@
 
 describe('RMRK External Integration Test', () => {
   before(async () => {
-    await usingApi(async () => {
-      alice = privateKey('//Alice');
+    await usingApi(async (api, privateKeyWrapper) => {
+      alice = privateKeyWrapper('//Alice');
     });
   });
 
@@ -75,9 +75,9 @@
   let rmrkNftId: number;
 
   before(async () => {
-    await usingApi(async api => {
-      alice = privateKey('//Alice');
-      bob = privateKey('//Bob');
+    await usingApi(async (api, privateKeyWrapper) => {
+      alice = privateKeyWrapper('//Alice');
+      bob = privateKeyWrapper('//Bob');
 
       const collectionIds = await createRmrkCollection(api, alice);
       uniqueCollectionId = collectionIds.uniqueId;
@@ -210,9 +210,9 @@
   let nftId: number;
 
   before(async () => {
-    await usingApi(async () => {
-      alice = privateKey('//Alice');
-      bob = privateKey('//Bob');
+    await usingApi(async (api, privateKeyWrapper) => {
+      alice = privateKeyWrapper('//Alice');
+      bob = privateKeyWrapper('//Bob');
 
       collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
       nftId = await createItemExpectSuccess(alice, collectionId, 'NFT');
modifiedtests/src/rpc.load.tsdiffbeforeafterboth
--- a/tests/src/rpc.load.ts
+++ b/tests/src/rpc.load.ts
@@ -59,8 +59,7 @@
   const deployer = await findUnusedAddress(api, privateKeyWrapper);
 
   // Transfer balance to it
-  const keyring = new Keyring({type: 'sr25519'});
-  const alice = keyring.addFromUri('//Alice');
+  const alice = privateKeyWrapper('//Alice');
   const amount = BigInt(endowment) + 10n**15n;
   const tx = api.tx.balances.transfer(deployer.address, amount);
   await submitTransactionAsync(alice, tx);
modifiedtests/src/scheduler.test.tsdiffbeforeafterboth
--- a/tests/src/scheduler.test.ts
+++ b/tests/src/scheduler.test.ts
@@ -16,7 +16,6 @@
 
 import chai, {expect} from 'chai';
 import chaiAsPromised from 'chai-as-promised';
-import privateKey from './substrate/privateKey';
 import {
   default as usingApi, 
   submitTransactionAsync,
@@ -52,9 +51,9 @@
   let scheduledIdSlider: number;
 
   before(async() => {
-    await usingApi(async () => {
-      alice = privateKey('//Alice');
-      bob = privateKey('//Bob');
+    await usingApi(async (api, privateKeyWrapper) => {
+      alice = privateKeyWrapper('//Alice');
+      bob = privateKeyWrapper('//Bob');
     });
 
     scheduledIdBase = '0x' + '0'.repeat(31);