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
--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.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/>.
+
 #[macro_export]
 macro_rules! impl_common_runtime_apis {
     (
@@ -331,30 +347,30 @@
                         .iter()
                         .filter_map(|(res_id)| Some(RmrkResourceInfo {
                             id: res_id.0,
-                            pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).unwrap(),
-                            pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).unwrap(),
-                            resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).unwrap() {
+                            pending: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceAccept).ok()?,
+                            pending_removal: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::PendingResourceRemoval).ok()?,
+                            resource: match RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::ResourceType).ok()? {
                                 ResourceType::Basic => RmrkResourceTypes::Basic(RmrkBasicResource {
-                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
-                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
-                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
-                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
+                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?,
+                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?,
+                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?,
+                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?,
                                 }),
                                 ResourceType::Composable => RmrkResourceTypes::Composable(RmrkComposableResource {
-                                    parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).unwrap(),
-                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),
-                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
-                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
-                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
-                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
+                                    parts: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Parts).ok()?,
+                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).ok()?,
+                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?,
+                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?,
+                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?,
+                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?,
                                 }),
                                 ResourceType::Slot => RmrkResourceTypes::Slot(RmrkSlotResource {
-                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).unwrap(),
-                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).unwrap(),
-                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).unwrap(),
-                                    slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).unwrap(),
-                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).unwrap(),
-                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).unwrap(),
+                                    base: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Base).ok()?,
+                                    src: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Src).ok()?,
+                                    metadata: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Metadata).ok()?,
+                                    slot: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Slot).ok()?,
+                                    license: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::License).ok()?,
+                                    thumb: RmrkCore::get_nft_property_decoded(res_collection_id, *res_id, RmrkProperty::Thumb).ok()?,
                                 }),
                             },
                         }))
@@ -447,12 +463,10 @@
                     let theme_names = collection.collection_tokens()
                         .iter()
                         .filter_map(|token_id| {
-                            let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();
+                            let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).ok()?;
 
                             match nft_type {
-                                Theme => Some(
-                                    RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).unwrap()
-                                ),
+                                Theme => RmrkCore::get_nft_property_decoded(collection_id, *token_id, RmrkProperty::ThemeName).ok(),
                                 _ => None
                             }
                         })
@@ -829,6 +843,7 @@
                     list_benchmark!(list, extra, pallet_fungible, Fungible);
                     list_benchmark!(list, extra, pallet_refungible, Refungible);
                     list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);
+                    list_benchmark!(list, extra, pallet_proxy_rmrk_core, RmrkCore);
                     // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);
 
                     let storage_info = AllPalletsReversedWithSystemFirst::storage_info();
@@ -872,6 +887,7 @@
                     add_benchmark!(params, batches, pallet_fungible, Fungible);
                     add_benchmark!(params, batches, pallet_refungible, Refungible);
                     add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);
+                    add_benchmark!(params, batches, pallet_proxy_rmrk_core, RmrkCore);
                     // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);
 
                     if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
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
before · runtime/quartz/src/lib.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//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.1819#![cfg_attr(not(feature = "std"), no_std)]20// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.21#![recursion_limit = "1024"]22#![allow(clippy::from_over_into, clippy::identity_op)]23#![allow(clippy::fn_to_numeric_cast_with_truncation)]24// Make the WASM binary available.25#[cfg(feature = "std")]26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));2728use sp_api::impl_runtime_apis;29use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};30use sp_runtime::DispatchError;31use fp_self_contained::*;32// #[cfg(any(feature = "std", test))]33// pub use sp_runtime::BuildStorage;3435use sp_runtime::{36	Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,37	traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},38	transaction_validity::{TransactionSource, TransactionValidity},39	ApplyExtrinsicResult, RuntimeAppPublic,40};4142use sp_std::prelude::*;4344#[cfg(feature = "std")]45use sp_version::NativeVersion;46use sp_version::RuntimeVersion;47pub use pallet_transaction_payment::{48	Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,49};50// A few exports that help ease life for downstream crates.51pub use pallet_balances::Call as BalancesCall;52pub use pallet_evm::{53	EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,54	OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,55};56pub use frame_support::{57	construct_runtime, match_types,58	dispatch::DispatchResult,59	PalletId, parameter_types, StorageValue, ConsensusEngineId,60	traits::{61		tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,62		Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,63		OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,64	},65	weights::{66		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},67		DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,68		WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,69	},70};71use pallet_unq_scheduler::DispatchCall;72use up_data_structs::{73	CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,74	CollectionStats, RpcCollection,75	mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},76	TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,77	RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkThemeProperty, RmrkCollectionId,78	RmrkNftId, RmrkAccountIdOrCollectionNftTuple, RmrkNftChild, RmrkPropertyKey, RmrkResourceTypes,79	RmrkBasicResource, RmrkComposableResource, RmrkSlotResource, RmrkResourceId, RmrkBaseId,80	RmrkFixedPart, RmrkSlotPart, RmrkString,81};8283// use pallet_contracts::weights::WeightInfo;84// #[cfg(any(feature = "std", test))]85use frame_system::{86	self as frame_system, EnsureRoot, EnsureSigned,87	limits::{BlockWeights, BlockLength},88};89use sp_arithmetic::{90	traits::{BaseArithmetic, Unsigned},91};92use smallvec::smallvec;93use codec::{Encode, Decode};94use fp_rpc::TransactionStatus;95use sp_runtime::{96	traits::{97		Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,98		Saturating, CheckedConversion,99	},100	generic::Era,101	transaction_validity::TransactionValidityError,102	DispatchErrorWithPostInfo, SaturatedConversion,103};104105// pub use pallet_timestamp::Call as TimestampCall;106pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;107108// Polkadot imports109use pallet_xcm::XcmPassthrough;110use polkadot_parachain::primitives::Sibling;111use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};112use xcm_builder::{113	AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,114	EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,115	RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,116	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,117	ParentIsPreset,118};119use xcm_executor::{Config, XcmExecutor, Assets};120use sp_std::{cmp::Ordering, marker::PhantomData};121122use xcm::latest::{123	//	Xcm,124	AssetId::{Concrete},125	Fungibility::Fungible as XcmFungible,126	MultiAsset,127	Error as XcmError,128};129use xcm_executor::traits::{MatchesFungible, WeightTrader};130131use unique_runtime_common::{132	impl_common_runtime_apis,133	types::*,134	constants::*,135	dispatch::{CollectionDispatchT, CollectionDispatch},136	sponsoring::UniqueSponsorshipHandler,137	eth_sponsoring::UniqueEthSponsorshipHandler,138	weights::CommonWeights,139};140141pub const RUNTIME_NAME: &str = "quartz";142pub const TOKEN_SYMBOL: &str = "QTZ";143144type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;145146impl RuntimeInstance for Runtime {147	type CrossAccountId = self::CrossAccountId;148149	type TransactionConverter = self::TransactionConverter;150151	fn get_transaction_converter() -> TransactionConverter {152		TransactionConverter153	}154}155156/// The type for looking up accounts. We don't expect more than 4 billion of them, but you157/// never know...158pub type AccountIndex = u32;159160/// Balance of an account.161pub type Balance = u128;162163/// Index of a transaction in the chain.164pub type Index = u32;165166/// A hash of some data used by the chain.167pub type Hash = sp_core::H256;168169/// Digest item type.170pub type DigestItem = generic::DigestItem;171172/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know173/// the specifics of the runtime. They can then be made to be agnostic over specific formats174/// of data like extrinsics, allowing for them to continue syncing the network through upgrades175/// to even the core data structures.176pub mod opaque {177	use sp_std::prelude::*;178	use sp_runtime::impl_opaque_keys;179	use super::Aura;180181	pub use unique_runtime_common::types::*;182183	impl_opaque_keys! {184		pub struct SessionKeys {185			pub aura: Aura,186		}187	}188}189190/// This runtime version.191pub const VERSION: RuntimeVersion = RuntimeVersion {192	spec_name: create_runtime_str!(RUNTIME_NAME),193	impl_name: create_runtime_str!(RUNTIME_NAME),194	authoring_version: 1,195	spec_version: 922000,196	impl_version: 0,197	apis: RUNTIME_API_VERSIONS,198	transaction_version: 1,199	state_version: 0,200};201202#[derive(codec::Encode, codec::Decode)]203pub enum XCMPMessage<XAccountId, XBalance> {204	/// Transfer tokens to the given account from the Parachain account.205	TransferToken(XAccountId, XBalance),206}207208/// The version information used to identify this runtime when compiled natively.209#[cfg(feature = "std")]210pub fn native_version() -> NativeVersion {211	NativeVersion {212		runtime_version: VERSION,213		can_author_with: Default::default(),214	}215}216217type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;218219pub struct DealWithFees;220impl OnUnbalanced<NegativeImbalance> for DealWithFees {221	fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {222		if let Some(fees) = fees_then_tips.next() {223			// for fees, 100% to treasury224			let mut split = fees.ration(100, 0);225			if let Some(tips) = fees_then_tips.next() {226				// for tips, if any, 100% to treasury227				tips.ration_merge_into(100, 0, &mut split);228			}229			Treasury::on_unbalanced(split.0);230			// Author::on_unbalanced(split.1);231		}232	}233}234235parameter_types! {236	pub const BlockHashCount: BlockNumber = 2400;237	pub RuntimeBlockLength: BlockLength =238		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);239	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);240	pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;241	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()242		.base_block(BlockExecutionWeight::get())243		.for_class(DispatchClass::all(), |weights| {244			weights.base_extrinsic = ExtrinsicBaseWeight::get();245		})246		.for_class(DispatchClass::Normal, |weights| {247			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);248		})249		.for_class(DispatchClass::Operational, |weights| {250			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);251			// Operational transactions have some extra reserved space, so that they252			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.253			weights.reserved = Some(254				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT255			);256		})257		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)258		.build_or_panic();259	pub const Version: RuntimeVersion = VERSION;260	pub const SS58Prefix: u8 = 255;261}262263parameter_types! {264	pub const ChainId: u64 = 8881;265}266267pub struct FixedFee;268impl FeeCalculator for FixedFee {269	fn min_gas_price() -> (U256, u64) {270		(MIN_GAS_PRICE.into(), 0)271	}272}273274// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case275// (contract, which only writes a lot of data),276// approximating on top of our real store write weight277parameter_types! {278	pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;279	pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;280	pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();281}282283/// Limiting EVM execution to 50% of block for substrate users and management tasks284/// EVM transaction consumes more weight than substrate's, so we can't rely on them being285/// scheduled fairly286const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);287parameter_types! {288	pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());289}290291pub enum FixedGasWeightMapping {}292impl GasWeightMapping for FixedGasWeightMapping {293	fn gas_to_weight(gas: u64) -> Weight {294		gas.saturating_mul(WeightPerGas::get())295	}296	fn weight_to_gas(weight: Weight) -> u64 {297		weight / WeightPerGas::get()298	}299}300301impl pallet_evm::account::Config for Runtime {302	type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;303	type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;304	type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;305}306307impl pallet_evm::Config for Runtime {308	type BlockGasLimit = BlockGasLimit;309	type FeeCalculator = FixedFee;310	type GasWeightMapping = FixedGasWeightMapping;311	type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;312	type CallOrigin = EnsureAddressTruncated<Self>;313	type WithdrawOrigin = EnsureAddressTruncated<Self>;314	type AddressMapping = HashedAddressMapping<Self::Hashing>;315	type PrecompilesType = ();316	type PrecompilesValue = ();317	type Currency = Balances;318	type Event = Event;319	type OnMethodCall = (320		pallet_evm_migration::OnMethodCall<Self>,321		pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,322		CollectionDispatchT<Self>,323		pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,324	);325	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;326	type ChainId = ChainId;327	type Runner = pallet_evm::runner::stack::Runner<Self>;328	type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;329	type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;330	type FindAuthor = EthereumFindAuthor<Aura>;331}332333impl pallet_evm_migration::Config for Runtime {334	type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;335}336337pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);338impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {339	fn find_author<'a, I>(digests: I) -> Option<H160>340	where341		I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,342	{343		if let Some(author_index) = F::find_author(digests) {344			let authority_id = Aura::authorities()[author_index as usize].clone();345			return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));346		}347		None348	}349}350351impl pallet_ethereum::Config for Runtime {352	type Event = Event;353	type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;354}355356impl pallet_randomness_collective_flip::Config for Runtime {}357358impl frame_system::Config for Runtime {359	/// The data to be stored in an account.360	type AccountData = pallet_balances::AccountData<Balance>;361	/// The identifier used to distinguish between accounts.362	type AccountId = AccountId;363	/// The basic call filter to use in dispatchable.364	type BaseCallFilter = Everything;365	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).366	type BlockHashCount = BlockHashCount;367	/// The maximum length of a block (in bytes).368	type BlockLength = RuntimeBlockLength;369	/// The index type for blocks.370	type BlockNumber = BlockNumber;371	/// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.372	type BlockWeights = RuntimeBlockWeights;373	/// The aggregated dispatch type that is available for extrinsics.374	type Call = Call;375	/// The weight of database operations that the runtime can invoke.376	type DbWeight = RocksDbWeight;377	/// The ubiquitous event type.378	type Event = Event;379	/// The type for hashing blocks and tries.380	type Hash = Hash;381	/// The hashing algorithm used.382	type Hashing = BlakeTwo256;383	/// The header type.384	type Header = generic::Header<BlockNumber, BlakeTwo256>;385	/// The index type for storing how many extrinsics an account has signed.386	type Index = Index;387	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.388	type Lookup = AccountIdLookup<AccountId, ()>;389	/// What to do if an account is fully reaped from the system.390	type OnKilledAccount = ();391	/// What to do if a new account is created.392	type OnNewAccount = ();393	type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;394	/// The ubiquitous origin type.395	type Origin = Origin;396	/// This type is being generated by `construct_runtime!`.397	type PalletInfo = PalletInfo;398	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.399	type SS58Prefix = SS58Prefix;400	/// Weight information for the extrinsics of this pallet.401	type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;402	/// Version of the runtime.403	type Version = Version;404	type MaxConsumers = ConstU32<16>;405}406407parameter_types! {408	pub const MinimumPeriod: u64 = SLOT_DURATION / 2;409}410411impl pallet_timestamp::Config for Runtime {412	/// A timestamp: milliseconds since the unix epoch.413	type Moment = u64;414	type OnTimestampSet = ();415	type MinimumPeriod = MinimumPeriod;416	type WeightInfo = ();417}418419parameter_types! {420	// pub const ExistentialDeposit: u128 = 500;421	pub const ExistentialDeposit: u128 = 0;422	pub const MaxLocks: u32 = 50;423	pub const MaxReserves: u32 = 50;424}425426impl pallet_balances::Config for Runtime {427	type MaxLocks = MaxLocks;428	type MaxReserves = MaxReserves;429	type ReserveIdentifier = [u8; 16];430	/// The type for recording an account's balance.431	type Balance = Balance;432	/// The ubiquitous event type.433	type Event = Event;434	type DustRemoval = Treasury;435	type ExistentialDeposit = ExistentialDeposit;436	type AccountStore = System;437	type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;438}439440pub const fn deposit(items: u32, bytes: u32) -> Balance {441	items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE442}443444/*445parameter_types! {446	pub TombstoneDeposit: Balance = deposit(447		1,448		sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,449	);450	pub DepositPerContract: Balance = TombstoneDeposit::get();451	pub const DepositPerStorageByte: Balance = deposit(0, 1);452	pub const DepositPerStorageItem: Balance = deposit(1, 0);453	pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);454	pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;455	pub const SignedClaimHandicap: u32 = 2;456	pub const MaxDepth: u32 = 32;457	pub const MaxValueSize: u32 = 16 * 1024;458	pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb459	// The lazy deletion runs inside on_initialize.460	pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *461		RuntimeBlockWeights::get().max_block;462	// The weight needed for decoding the queue should be less or equal than a fifth463	// of the overall weight dedicated to the lazy deletion.464	pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (465			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -466			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)467		)) / 5) as u32;468	pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();469}470471impl pallet_contracts::Config for Runtime {472	type Time = Timestamp;473	type Randomness = RandomnessCollectiveFlip;474	type Currency = Balances;475	type Event = Event;476	type RentPayment = ();477	type SignedClaimHandicap = SignedClaimHandicap;478	type TombstoneDeposit = TombstoneDeposit;479	type DepositPerContract = DepositPerContract;480	type DepositPerStorageByte = DepositPerStorageByte;481	type DepositPerStorageItem = DepositPerStorageItem;482	type RentFraction = RentFraction;483	type SurchargeReward = SurchargeReward;484	type WeightPrice = pallet_transaction_payment::Pallet<Self>;485	type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;486	type ChainExtension = NFTExtension;487	type DeletionQueueDepth = DeletionQueueDepth;488	type DeletionWeightLimit = DeletionWeightLimit;489	type Schedule = Schedule;490	type CallStack = [pallet_contracts::Frame<Self>; 31];491}492*/493494parameter_types! {495	/// This value increases the priority of `Operational` transactions by adding496	/// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.497	pub const OperationalFeeMultiplier: u8 = 5;498}499500/// Linear implementor of `WeightToFeePolynomial`501pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);502503impl<T> WeightToFeePolynomial for LinearFee<T>504where505	T: BaseArithmetic + From<u32> + Copy + Unsigned,506{507	type Balance = T;508509	fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {510		smallvec!(WeightToFeeCoefficient {511			// Targeting 0.1 Unique per NFT transfer512			coeff_integer: WEIGHT_TO_FEE_COEFF.into(),513			coeff_frac: Perbill::zero(),514			negative: false,515			degree: 1,516		})517	}518}519520impl pallet_transaction_payment::Config for Runtime {521	type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;522	type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;523	type OperationalFeeMultiplier = OperationalFeeMultiplier;524	type WeightToFee = LinearFee<Balance>;525	type FeeMultiplierUpdate = ();526}527528parameter_types! {529	pub const ProposalBond: Permill = Permill::from_percent(5);530	pub const ProposalBondMinimum: Balance = 1 * UNIQUE;531	pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;532	pub const SpendPeriod: BlockNumber = 5 * MINUTES;533	pub const Burn: Permill = Permill::from_percent(0);534	pub const TipCountdown: BlockNumber = 1 * DAYS;535	pub const TipFindersFee: Percent = Percent::from_percent(20);536	pub const TipReportDepositBase: Balance = 1 * UNIQUE;537	pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;538	pub const BountyDepositBase: Balance = 1 * UNIQUE;539	pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;540	pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");541	pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;542	pub const MaximumReasonLength: u32 = 16384;543	pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);544	pub const BountyValueMinimum: Balance = 5 * UNIQUE;545	pub const MaxApprovals: u32 = 100;546}547548impl pallet_treasury::Config for Runtime {549	type PalletId = TreasuryModuleId;550	type Currency = Balances;551	type ApproveOrigin = EnsureRoot<AccountId>;552	type RejectOrigin = EnsureRoot<AccountId>;553	type Event = Event;554	type OnSlash = ();555	type ProposalBond = ProposalBond;556	type ProposalBondMinimum = ProposalBondMinimum;557	type ProposalBondMaximum = ProposalBondMaximum;558	type SpendPeriod = SpendPeriod;559	type Burn = Burn;560	type BurnDestination = ();561	type SpendFunds = ();562	type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;563	type MaxApprovals = MaxApprovals;564}565566impl pallet_sudo::Config for Runtime {567	type Event = Event;568	type Call = Call;569}570571pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);572573impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider574	for RelayChainBlockNumberProvider<T>575{576	type BlockNumber = BlockNumber;577578	fn current_block_number() -> Self::BlockNumber {579		cumulus_pallet_parachain_system::Pallet::<T>::validation_data()580			.map(|d| d.relay_parent_number)581			.unwrap_or_default()582	}583}584585parameter_types! {586	pub const MinVestedTransfer: Balance = 10 * UNIQUE;587	pub const MaxVestingSchedules: u32 = 28;588}589590impl orml_vesting::Config for Runtime {591	type Event = Event;592	type Currency = pallet_balances::Pallet<Runtime>;593	type MinVestedTransfer = MinVestedTransfer;594	type VestedTransferOrigin = EnsureSigned<AccountId>;595	type WeightInfo = ();596	type MaxVestingSchedules = MaxVestingSchedules;597	type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;598}599600parameter_types! {601	pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;602	pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;603}604605impl cumulus_pallet_parachain_system::Config for Runtime {606	type Event = Event;607	type SelfParaId = parachain_info::Pallet<Self>;608	type OnSystemEvent = ();609	// type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<610	// 	MaxDownwardMessageWeight,611	// 	XcmExecutor<XcmConfig>,612	// 	Call,613	// >;614	type OutboundXcmpMessageSource = XcmpQueue;615	type DmpMessageHandler = DmpQueue;616	type ReservedDmpWeight = ReservedDmpWeight;617	type ReservedXcmpWeight = ReservedXcmpWeight;618	type XcmpMessageHandler = XcmpQueue;619}620621impl parachain_info::Config for Runtime {}622623impl cumulus_pallet_aura_ext::Config for Runtime {}624625parameter_types! {626	pub const RelayLocation: MultiLocation = MultiLocation::parent();627	pub const RelayNetwork: NetworkId = NetworkId::Polkadot;628	pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();629	pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();630}631632/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used633/// when determining ownership of accounts for asset transacting and when attempting to use XCM634/// `Transact` in order to determine the dispatch Origin.635pub type LocationToAccountId = (636	// The parent (Relay-chain) origin converts to the default `AccountId`.637	ParentIsPreset<AccountId>,638	// Sibling parachain origins convert to AccountId via the `ParaId::into`.639	SiblingParachainConvertsVia<Sibling, AccountId>,640	// Straight up local `AccountId32` origins just alias directly to `AccountId`.641	AccountId32Aliases<RelayNetwork, AccountId>,642);643644pub struct OnlySelfCurrency;645impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {646	fn matches_fungible(a: &MultiAsset) -> Option<B> {647		match (&a.id, &a.fun) {648			(Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),649			_ => None,650		}651	}652}653654/// Means for transacting assets on this chain.655pub type LocalAssetTransactor = CurrencyAdapter<656	// Use this currency:657	Balances,658	// Use this currency when it is a fungible asset matching the given location or name:659	OnlySelfCurrency,660	// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:661	LocationToAccountId,662	// Our chain's account ID type (we can't get away without mentioning it explicitly):663	AccountId,664	// We don't track any teleports.665	(),666>;667668/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,669/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can670/// biases the kind of local `Origin` it will become.671pub type XcmOriginToTransactDispatchOrigin = (672	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location673	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for674	// foreign chains who want to have a local sovereign account on this chain which they control.675	SovereignSignedViaLocation<LocationToAccountId, Origin>,676	// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when677	// recognised.678	RelayChainAsNative<RelayOrigin, Origin>,679	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when680	// recognised.681	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,682	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a683	// transaction from the Root origin.684	ParentAsSuperuser<Origin>,685	// Native signed account converter; this just converts an `AccountId32` origin into a normal686	// `Origin::Signed` origin of the same 32-byte value.687	SignedAccountId32AsNative<RelayNetwork, Origin>,688	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.689	XcmPassthrough<Origin>,690);691692parameter_types! {693	// One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.694	pub UnitWeightCost: Weight = 1_000_000;695	// 1200 UNIQUEs buy 1 second of weight.696	pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);697	pub const MaxInstructions: u32 = 100;698	pub const MaxAuthorities: u32 = 100_000;699}700701match_types! {702	pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {703		MultiLocation { parents: 1, interior: Here } |704		MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }705	};706}707708pub type Barrier = (709	TakeWeightCredit,710	AllowTopLevelPaidExecutionFrom<Everything>,711	AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,712	// ^^^ Parent & its unit plurality gets free execution713);714715pub struct UsingOnlySelfCurrencyComponents<716	WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,717	AssetId: Get<MultiLocation>,718	AccountId,719	Currency: CurrencyT<AccountId>,720	OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,721>(722	Weight,723	Currency::Balance,724	PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,725);726impl<727		WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,728		AssetId: Get<MultiLocation>,729		AccountId,730		Currency: CurrencyT<AccountId>,731		OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,732	> WeightTrader733	for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>734{735	fn new() -> Self {736		Self(0, Zero::zero(), PhantomData)737	}738739	fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {740		let amount = WeightToFee::calc(&weight);741		let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;742743		// location to this parachain through relay chain744		let option1: xcm::v1::AssetId = Concrete(MultiLocation {745			parents: 1,746			interior: X1(Parachain(ParachainInfo::parachain_id().into())),747		});748		// direct location749		let option2: xcm::v1::AssetId = Concrete(MultiLocation {750			parents: 0,751			interior: Here,752		});753754		let required = if payment.fungible.contains_key(&option1) {755			(option1, u128_amount).into()756		} else if payment.fungible.contains_key(&option2) {757			(option2, u128_amount).into()758		} else {759			(Concrete(MultiLocation::default()), u128_amount).into()760		};761762		let unused = payment763			.checked_sub(required)764			.map_err(|_| XcmError::TooExpensive)?;765		self.0 = self.0.saturating_add(weight);766		self.1 = self.1.saturating_add(amount);767		Ok(unused)768	}769770	fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {771		let weight = weight.min(self.0);772		let amount = WeightToFee::calc(&weight);773		self.0 -= weight;774		self.1 = self.1.saturating_sub(amount);775		let amount: u128 = amount.saturated_into();776		if amount > 0 {777			Some((AssetId::get(), amount).into())778		} else {779			None780		}781	}782}783impl<784		WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,785		AssetId: Get<MultiLocation>,786		AccountId,787		Currency: CurrencyT<AccountId>,788		OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,789	> Drop790	for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>791{792	fn drop(&mut self) {793		OnUnbalanced::on_unbalanced(Currency::issue(self.1));794	}795}796797pub struct XcmConfig;798impl Config for XcmConfig {799	type Call = Call;800	type XcmSender = XcmRouter;801	// How to withdraw and deposit an asset.802	type AssetTransactor = LocalAssetTransactor;803	type OriginConverter = XcmOriginToTransactDispatchOrigin;804	type IsReserve = NativeAsset;805	type IsTeleporter = (); // Teleportation is disabled806	type LocationInverter = LocationInverter<Ancestry>;807	type Barrier = Barrier;808	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;809	type Trader = UsingOnlySelfCurrencyComponents<810		IdentityFee<Balance>,811		RelayLocation,812		AccountId,813		Balances,814		(),815	>;816	type ResponseHandler = (); // Don't handle responses for now.817	type SubscriptionService = PolkadotXcm;818819	type AssetTrap = PolkadotXcm;820	type AssetClaims = PolkadotXcm;821}822823// parameter_types! {824// 	pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;825// }826827/// No local origins on this chain are allowed to dispatch XCM sends/executions.828pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);829830/// The means for routing XCM messages which are not for local execution into the right message831/// queues.832pub type XcmRouter = (833	// Two routers - use UMP to communicate with the relay chain:834	cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,835	// ..and XCMP to communicate with the sibling chains.836	XcmpQueue,837);838839impl pallet_evm_coder_substrate::Config for Runtime {}840841impl pallet_xcm::Config for Runtime {842	type Event = Event;843	type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;844	type XcmRouter = XcmRouter;845	type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;846	type XcmExecuteFilter = Everything;847	type XcmExecutor = XcmExecutor<XcmConfig>;848	type XcmTeleportFilter = Everything;849	type XcmReserveTransferFilter = Everything;850	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;851	type LocationInverter = LocationInverter<Ancestry>;852	type Origin = Origin;853	type Call = Call;854	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;855	type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;856}857858impl cumulus_pallet_xcm::Config for Runtime {859	type Event = Event;860	type XcmExecutor = XcmExecutor<XcmConfig>;861}862863impl cumulus_pallet_xcmp_queue::Config for Runtime {864	type WeightInfo = ();865	type Event = Event;866	type XcmExecutor = XcmExecutor<XcmConfig>;867	type ChannelInfo = ParachainSystem;868	type VersionWrapper = ();869	type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;870	type ControllerOrigin = EnsureRoot<AccountId>;871	type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;872}873874impl cumulus_pallet_dmp_queue::Config for Runtime {875	type Event = Event;876	type XcmExecutor = XcmExecutor<XcmConfig>;877	type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;878}879880impl pallet_aura::Config for Runtime {881	type AuthorityId = AuraId;882	type DisabledValidators = ();883	type MaxAuthorities = MaxAuthorities;884}885886parameter_types! {887	pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();888	pub const CollectionCreationPrice: Balance = 2 * UNIQUE;889}890891impl pallet_common::Config for Runtime {892	type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;893	type Event = Event;894	type Currency = Balances;895	type CollectionCreationPrice = CollectionCreationPrice;896	type TreasuryAccountId = TreasuryAccountId;897	type CollectionDispatch = CollectionDispatchT<Self>;898899	type EvmTokenAddressMapping = EvmTokenAddressMapping;900	type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;901	type ContractAddress = EvmCollectionHelpersAddress;902}903904impl pallet_structure::Config for Runtime {905	type Event = Event;906	type Call = Call;907	type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;908}909910impl pallet_fungible::Config for Runtime {911	type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;912}913impl pallet_refungible::Config for Runtime {914	type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;915}916impl pallet_nonfungible::Config for Runtime {917	type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;918}919920impl pallet_proxy_rmrk_core::Config for Runtime {921	type Event = Event;922}923924impl pallet_proxy_rmrk_equip::Config for Runtime {925	type Event = Event;926}927928impl pallet_unique::Config for Runtime {929	type Event = Event;930	type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;931	type CommonWeightInfo = CommonWeights<Self>;932}933934parameter_types! {935	pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied936}937938/// Used for the pallet inflation939impl pallet_inflation::Config for Runtime {940	type Currency = Balances;941	type TreasuryAccountId = TreasuryAccountId;942	type InflationBlockInterval = InflationBlockInterval;943	type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;944}945946parameter_types! {947	pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *948		RuntimeBlockWeights::get().max_block;949	pub const MaxScheduledPerBlock: u32 = 50;950}951952type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;953use frame_support::traits::NamedReservableCurrency;954955fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {956	(957		frame_system::CheckSpecVersion::<Runtime>::new(),958		frame_system::CheckGenesis::<Runtime>::new(),959		frame_system::CheckEra::<Runtime>::from(Era::Immortal),960		frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(961			from,962		)),963		frame_system::CheckWeight::<Runtime>::new(),964		// sponsoring transaction logic965		// pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),966	)967}968969pub struct SchedulerPaymentExecutor;970impl<T: frame_system::Config + pallet_unq_scheduler::Config, SelfContainedSignedInfo>971	DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor972where973	<T as frame_system::Config>::Call: Member974		+ Dispatchable<Origin = Origin, Info = DispatchInfo>975		+ SelfContainedCall<SignedInfo = SelfContainedSignedInfo>976		+ GetDispatchInfo977		+ From<frame_system::Call<Runtime>>,978	SelfContainedSignedInfo: Send + Sync + 'static,979	Call: From<<T as frame_system::Config>::Call>980		+ From<<T as pallet_unq_scheduler::Config>::Call>981		+ SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,982	sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,983{984	fn dispatch_call(985		signer: <T as frame_system::Config>::AccountId,986		call: <T as pallet_unq_scheduler::Config>::Call,987	) -> Result<988		Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,989		TransactionValidityError,990	> {991		let dispatch_info = call.get_dispatch_info();992		let extrinsic = fp_self_contained::CheckedExtrinsic::<993			AccountId,994			Call,995			SignedExtraScheduler,996			SelfContainedSignedInfo,997		> {998			signed:999				CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(1000					signer.clone().into(),1001					get_signed_extras(signer.into()),1002				),1003			function: call.into(),1004		};10051006		extrinsic.apply::<Runtime>(&dispatch_info, 0)1007	}10081009	fn reserve_balance(1010		id: [u8; 16],1011		sponsor: <T as frame_system::Config>::AccountId,1012		call: <T as pallet_unq_scheduler::Config>::Call,1013		count: u32,1014	) -> Result<(), DispatchError> {1015		let dispatch_info = call.get_dispatch_info();1016		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)1017			.saturating_mul(count.into());10181019		<Balances as NamedReservableCurrency<AccountId>>::reserve_named(1020			&id,1021			&(sponsor.into()),1022			weight.into(),1023		)1024	}10251026	fn pay_for_call(1027		id: [u8; 16],1028		sponsor: <T as frame_system::Config>::AccountId,1029		call: <T as pallet_unq_scheduler::Config>::Call,1030	) -> Result<u128, DispatchError> {1031		let dispatch_info = call.get_dispatch_info();1032		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);1033		Ok(1034			<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1035				&id,1036				&(sponsor.into()),1037				weight.into(),1038			),1039		)1040	}10411042	fn cancel_reserve(1043		id: [u8; 16],1044		sponsor: <T as frame_system::Config>::AccountId,1045	) -> Result<u128, DispatchError> {1046		Ok(1047			<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1048				&id,1049				&(sponsor.into()),1050				u128::MAX,1051			),1052		)1053	}1054}10551056parameter_types! {1057	pub const NoPreimagePostponement: Option<u32> = Some(10);1058	pub const Preimage: Option<u32> = Some(10);1059}10601061/// Used the compare the privilege of an origin inside the scheduler.1062pub struct OriginPrivilegeCmp;10631064impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {1065	fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {1066		Some(Ordering::Equal)1067	}1068}10691070impl pallet_unq_scheduler::Config for Runtime {1071	type Event = Event;1072	type Origin = Origin;1073	type Currency = Balances;1074	type PalletsOrigin = OriginCaller;1075	type Call = Call;1076	type MaximumWeight = MaximumSchedulerWeight;1077	type ScheduleOrigin = EnsureSigned<AccountId>;1078	type MaxScheduledPerBlock = MaxScheduledPerBlock;1079	type WeightInfo = ();1080	type CallExecutor = SchedulerPaymentExecutor;1081	type OriginPrivilegeCmp = OriginPrivilegeCmp;1082	type PreimageProvider = ();1083	type NoPreimagePostponement = NoPreimagePostponement;1084}10851086type EvmSponsorshipHandler = (1087	UniqueEthSponsorshipHandler<Runtime>,1088	pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,1089);1090type SponsorshipHandler = (1091	UniqueSponsorshipHandler<Runtime>,1092	//pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,1093	pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,1094);10951096impl pallet_evm_transaction_payment::Config for Runtime {1097	type EvmSponsorshipHandler = EvmSponsorshipHandler;1098	type Currency = Balances;1099}11001101impl pallet_charge_transaction::Config for Runtime {1102	type SponsorshipHandler = SponsorshipHandler;1103}11041105// impl pallet_contract_helpers::Config for Runtime {1106//	 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1107// }11081109parameter_types! {1110	// 0x842899ECF380553E8a4de75bF534cdf6fBF640491111	pub const HelpersContractAddress: H160 = H160([1112		0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,1113	]);11141115	// 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f1116	pub const EvmCollectionHelpersAddress: H160 = H160([1117		0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,1118	]);1119}11201121impl pallet_evm_contract_helpers::Config for Runtime {1122	type ContractAddress = HelpersContractAddress;1123	type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1124}11251126construct_runtime!(1127	pub enum Runtime where1128		Block = Block,1129		NodeBlock = opaque::Block,1130		UncheckedExtrinsic = UncheckedExtrinsic1131	{1132		ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,1133		ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,11341135		Aura: pallet_aura::{Pallet, Config<T>} = 22,1136		AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,11371138		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,1139		RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,1140		Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,1141		TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,1142		Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,1143		Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,1144		System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,1145		Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,1146		// Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,1147		// Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,11481149		// XCM helpers.1150		XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,1151		PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,1152		CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,1153		DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,11541155		// Unique Pallets1156		Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,1157		Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,1158		Scheduler: pallet_unq_scheduler::{Pallet, Call, Storage, Event<T>} = 62,1159		// free = 631160		Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,1161		// ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,1162		Common: pallet_common::{Pallet, Storage, Event<T>} = 66,1163		Fungible: pallet_fungible::{Pallet, Storage} = 67,1164		Refungible: pallet_refungible::{Pallet, Storage} = 68,1165		Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,1166		Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,1167		RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,1168		RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,11691170		// Frontier1171		EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,1172		Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,11731174		EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,1175		EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,1176		EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,1177		EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,1178	}1179);11801181pub struct TransactionConverter;11821183impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {1184	fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {1185		UncheckedExtrinsic::new_unsigned(1186			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1187		)1188	}1189}11901191impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {1192	fn convert_transaction(1193		&self,1194		transaction: pallet_ethereum::Transaction,1195	) -> opaque::UncheckedExtrinsic {1196		let extrinsic = UncheckedExtrinsic::new_unsigned(1197			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1198		);1199		let encoded = extrinsic.encode();1200		opaque::UncheckedExtrinsic::decode(&mut &encoded[..])1201			.expect("Encoded extrinsic is always valid")1202	}1203}12041205/// The address format for describing accounts.1206pub type Address = sp_runtime::MultiAddress<AccountId, ()>;1207/// Block header type as expected by this runtime.1208pub type Header = generic::Header<BlockNumber, BlakeTwo256>;1209/// Block type as expected by this runtime.1210pub type Block = generic::Block<Header, UncheckedExtrinsic>;1211/// A Block signed with a Justification1212pub type SignedBlock = generic::SignedBlock<Block>;1213/// BlockId type as expected by this runtime.1214pub type BlockId = generic::BlockId<Block>;1215/// The SignedExtension to the basic transaction logic.1216pub type SignedExtra = (1217	frame_system::CheckSpecVersion<Runtime>,1218	// system::CheckTxVersion<Runtime>,1219	frame_system::CheckGenesis<Runtime>,1220	frame_system::CheckEra<Runtime>,1221	frame_system::CheckNonce<Runtime>,1222	frame_system::CheckWeight<Runtime>,1223	ChargeTransactionPayment,1224	//pallet_contract_helpers::ContractHelpersExtension<Runtime>,1225	pallet_ethereum::FakeTransactionFinalizer<Runtime>,1226);12271228pub type SignedExtraScheduler = (1229	frame_system::CheckSpecVersion<Runtime>,1230	frame_system::CheckGenesis<Runtime>,1231	frame_system::CheckEra<Runtime>,1232	frame_system::CheckNonce<Runtime>,1233	frame_system::CheckWeight<Runtime>,1234	// pallet_charge_transaction::ChargeTransactionPayment<Runtime>,1235);1236/// Unchecked extrinsic type as expected by this runtime.1237pub type UncheckedExtrinsic =1238	fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;1239/// Extrinsic type that has already been checked.1240pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;1241/// Executive: handles dispatch to the various modules.1242pub type Executive = frame_executive::Executive<1243	Runtime,1244	Block,1245	frame_system::ChainContext<Runtime>,1246	Runtime,1247	AllPalletsReversedWithSystemFirst,1248>;12491250impl_opaque_keys! {1251	pub struct SessionKeys {1252		pub aura: Aura,1253	}1254}12551256impl fp_self_contained::SelfContainedCall for Call {1257	type SignedInfo = H160;12581259	fn is_self_contained(&self) -> bool {1260		match self {1261			Call::Ethereum(call) => call.is_self_contained(),1262			_ => false,1263		}1264	}12651266	fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {1267		match self {1268			Call::Ethereum(call) => call.check_self_contained(),1269			_ => None,1270		}1271	}12721273	fn validate_self_contained(1274		&self,1275		info: &Self::SignedInfo,1276		dispatch_info: &DispatchInfoOf<Call>,1277		len: usize,1278	) -> Option<TransactionValidity> {1279		match self {1280			Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),1281			_ => None,1282		}1283	}12841285	fn pre_dispatch_self_contained(1286		&self,1287		info: &Self::SignedInfo,1288	) -> Option<Result<(), TransactionValidityError>> {1289		match self {1290			Call::Ethereum(call) => call.pre_dispatch_self_contained(info),1291			_ => None,1292		}1293	}12941295	fn apply_self_contained(1296		self,1297		info: Self::SignedInfo,1298	) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {1299		match self {1300			call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(1301				Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),1302			)),1303			_ => None,1304		}1305	}1306}13071308macro_rules! dispatch_unique_runtime {1309	($collection:ident.$method:ident($($name:ident),*)) => {{1310		let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);1311		let dispatch = collection.as_dyn();13121313		Ok::<_, DispatchError>(dispatch.$method($($name),*))1314	}};1315}13161317impl_common_runtime_apis!();13181319struct CheckInherents;13201321impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {1322	fn check_inherents(1323		block: &Block,1324		relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,1325	) -> sp_inherents::CheckInherentsResult {1326		let relay_chain_slot = relay_state_proof1327			.read_slot()1328			.expect("Could not read the relay chain slot from the proof");13291330		let inherent_data =1331			cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(1332				relay_chain_slot,1333				sp_std::time::Duration::from_secs(6),1334			)1335			.create_inherent_data()1336			.expect("Could not create the timestamp inherent data");13371338		inherent_data.check_extrinsics(block)1339	}1340}13411342cumulus_pallet_parachain_system::register_validate_block!(1343	Runtime = Runtime,1344	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,1345	CheckInherents = CheckInherents,1346);
after · runtime/quartz/src/lib.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//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.1819#![cfg_attr(not(feature = "std"), no_std)]20// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.21#![recursion_limit = "1024"]22#![allow(clippy::from_over_into, clippy::identity_op)]23#![allow(clippy::fn_to_numeric_cast_with_truncation)]24// Make the WASM binary available.25#[cfg(feature = "std")]26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));2728use sp_api::impl_runtime_apis;29use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};30use sp_runtime::DispatchError;31use fp_self_contained::*;32// #[cfg(any(feature = "std", test))]33// pub use sp_runtime::BuildStorage;3435use sp_runtime::{36	Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,37	traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},38	transaction_validity::{TransactionSource, TransactionValidity},39	ApplyExtrinsicResult, RuntimeAppPublic,40};4142use sp_std::prelude::*;4344#[cfg(feature = "std")]45use sp_version::NativeVersion;46use sp_version::RuntimeVersion;47pub use pallet_transaction_payment::{48	Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,49};50// A few exports that help ease life for downstream crates.51pub use pallet_balances::Call as BalancesCall;52pub use pallet_evm::{53	EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,54	OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,55};56pub use frame_support::{57	construct_runtime, match_types,58	dispatch::DispatchResult,59	PalletId, parameter_types, StorageValue, ConsensusEngineId,60	traits::{61		tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,62		Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,63		OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,64	},65	weights::{66		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},67		DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,68		WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,69	},70};71use pallet_unq_scheduler::DispatchCall;72use up_data_structs::{73	CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,74	CollectionStats, RpcCollection,75	mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},76	TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,77	RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkThemeProperty, RmrkCollectionId,78	RmrkNftId, RmrkAccountIdOrCollectionNftTuple, RmrkNftChild, RmrkPropertyKey, RmrkResourceTypes,79	RmrkBasicResource, RmrkComposableResource, RmrkSlotResource, RmrkResourceId, RmrkBaseId,80	RmrkFixedPart, RmrkSlotPart, RmrkString,81};8283// use pallet_contracts::weights::WeightInfo;84// #[cfg(any(feature = "std", test))]85use frame_system::{86	self as frame_system, EnsureRoot, EnsureSigned,87	limits::{BlockWeights, BlockLength},88};89use sp_arithmetic::{90	traits::{BaseArithmetic, Unsigned},91};92use smallvec::smallvec;93use codec::{Encode, Decode};94use fp_rpc::TransactionStatus;95use sp_runtime::{96	traits::{97		Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,98		Saturating, CheckedConversion,99	},100	generic::Era,101	transaction_validity::TransactionValidityError,102	DispatchErrorWithPostInfo, SaturatedConversion,103};104105// pub use pallet_timestamp::Call as TimestampCall;106pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;107108// Polkadot imports109use pallet_xcm::XcmPassthrough;110use polkadot_parachain::primitives::Sibling;111use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};112use xcm_builder::{113	AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,114	EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,115	RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,116	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,117	ParentIsPreset,118};119use xcm_executor::{Config, XcmExecutor, Assets};120use sp_std::{cmp::Ordering, marker::PhantomData};121122use xcm::latest::{123	//	Xcm,124	AssetId::{Concrete},125	Fungibility::Fungible as XcmFungible,126	MultiAsset,127	Error as XcmError,128};129use xcm_executor::traits::{MatchesFungible, WeightTrader};130131use unique_runtime_common::{132	impl_common_runtime_apis,133	types::*,134	constants::*,135	dispatch::{CollectionDispatchT, CollectionDispatch},136	sponsoring::UniqueSponsorshipHandler,137	eth_sponsoring::UniqueEthSponsorshipHandler,138	weights::CommonWeights,139};140141pub const RUNTIME_NAME: &str = "quartz";142pub const TOKEN_SYMBOL: &str = "QTZ";143144type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;145146impl RuntimeInstance for Runtime {147	type CrossAccountId = self::CrossAccountId;148149	type TransactionConverter = self::TransactionConverter;150151	fn get_transaction_converter() -> TransactionConverter {152		TransactionConverter153	}154}155156/// The type for looking up accounts. We don't expect more than 4 billion of them, but you157/// never know...158pub type AccountIndex = u32;159160/// Balance of an account.161pub type Balance = u128;162163/// Index of a transaction in the chain.164pub type Index = u32;165166/// A hash of some data used by the chain.167pub type Hash = sp_core::H256;168169/// Digest item type.170pub type DigestItem = generic::DigestItem;171172/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know173/// the specifics of the runtime. They can then be made to be agnostic over specific formats174/// of data like extrinsics, allowing for them to continue syncing the network through upgrades175/// to even the core data structures.176pub mod opaque {177	use sp_std::prelude::*;178	use sp_runtime::impl_opaque_keys;179	use super::Aura;180181	pub use unique_runtime_common::types::*;182183	impl_opaque_keys! {184		pub struct SessionKeys {185			pub aura: Aura,186		}187	}188}189190/// This runtime version.191pub const VERSION: RuntimeVersion = RuntimeVersion {192	spec_name: create_runtime_str!(RUNTIME_NAME),193	impl_name: create_runtime_str!(RUNTIME_NAME),194	authoring_version: 1,195	spec_version: 922000,196	impl_version: 0,197	apis: RUNTIME_API_VERSIONS,198	transaction_version: 1,199	state_version: 0,200};201202#[derive(codec::Encode, codec::Decode)]203pub enum XCMPMessage<XAccountId, XBalance> {204	/// Transfer tokens to the given account from the Parachain account.205	TransferToken(XAccountId, XBalance),206}207208/// The version information used to identify this runtime when compiled natively.209#[cfg(feature = "std")]210pub fn native_version() -> NativeVersion {211	NativeVersion {212		runtime_version: VERSION,213		can_author_with: Default::default(),214	}215}216217type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;218219pub struct DealWithFees;220impl OnUnbalanced<NegativeImbalance> for DealWithFees {221	fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {222		if let Some(fees) = fees_then_tips.next() {223			// for fees, 100% to treasury224			let mut split = fees.ration(100, 0);225			if let Some(tips) = fees_then_tips.next() {226				// for tips, if any, 100% to treasury227				tips.ration_merge_into(100, 0, &mut split);228			}229			Treasury::on_unbalanced(split.0);230			// Author::on_unbalanced(split.1);231		}232	}233}234235parameter_types! {236	pub const BlockHashCount: BlockNumber = 2400;237	pub RuntimeBlockLength: BlockLength =238		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);239	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);240	pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;241	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()242		.base_block(BlockExecutionWeight::get())243		.for_class(DispatchClass::all(), |weights| {244			weights.base_extrinsic = ExtrinsicBaseWeight::get();245		})246		.for_class(DispatchClass::Normal, |weights| {247			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);248		})249		.for_class(DispatchClass::Operational, |weights| {250			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);251			// Operational transactions have some extra reserved space, so that they252			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.253			weights.reserved = Some(254				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT255			);256		})257		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)258		.build_or_panic();259	pub const Version: RuntimeVersion = VERSION;260	pub const SS58Prefix: u8 = 255;261}262263parameter_types! {264	pub const ChainId: u64 = 8881;265}266267pub struct FixedFee;268impl FeeCalculator for FixedFee {269	fn min_gas_price() -> (U256, u64) {270		(MIN_GAS_PRICE.into(), 0)271	}272}273274// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case275// (contract, which only writes a lot of data),276// approximating on top of our real store write weight277parameter_types! {278	pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;279	pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;280	pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();281}282283/// Limiting EVM execution to 50% of block for substrate users and management tasks284/// EVM transaction consumes more weight than substrate's, so we can't rely on them being285/// scheduled fairly286const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);287parameter_types! {288	pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());289}290291pub enum FixedGasWeightMapping {}292impl GasWeightMapping for FixedGasWeightMapping {293	fn gas_to_weight(gas: u64) -> Weight {294		gas.saturating_mul(WeightPerGas::get())295	}296	fn weight_to_gas(weight: Weight) -> u64 {297		weight / WeightPerGas::get()298	}299}300301impl pallet_evm::account::Config for Runtime {302	type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;303	type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;304	type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;305}306307impl pallet_evm::Config for Runtime {308	type BlockGasLimit = BlockGasLimit;309	type FeeCalculator = FixedFee;310	type GasWeightMapping = FixedGasWeightMapping;311	type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;312	type CallOrigin = EnsureAddressTruncated<Self>;313	type WithdrawOrigin = EnsureAddressTruncated<Self>;314	type AddressMapping = HashedAddressMapping<Self::Hashing>;315	type PrecompilesType = ();316	type PrecompilesValue = ();317	type Currency = Balances;318	type Event = Event;319	type OnMethodCall = (320		pallet_evm_migration::OnMethodCall<Self>,321		pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,322		CollectionDispatchT<Self>,323		pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,324	);325	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;326	type ChainId = ChainId;327	type Runner = pallet_evm::runner::stack::Runner<Self>;328	type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;329	type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;330	type FindAuthor = EthereumFindAuthor<Aura>;331}332333impl pallet_evm_migration::Config for Runtime {334	type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;335}336337pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);338impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {339	fn find_author<'a, I>(digests: I) -> Option<H160>340	where341		I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,342	{343		if let Some(author_index) = F::find_author(digests) {344			let authority_id = Aura::authorities()[author_index as usize].clone();345			return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));346		}347		None348	}349}350351impl pallet_ethereum::Config for Runtime {352	type Event = Event;353	type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;354}355356impl pallet_randomness_collective_flip::Config for Runtime {}357358impl frame_system::Config for Runtime {359	/// The data to be stored in an account.360	type AccountData = pallet_balances::AccountData<Balance>;361	/// The identifier used to distinguish between accounts.362	type AccountId = AccountId;363	/// The basic call filter to use in dispatchable.364	type BaseCallFilter = Everything;365	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).366	type BlockHashCount = BlockHashCount;367	/// The maximum length of a block (in bytes).368	type BlockLength = RuntimeBlockLength;369	/// The index type for blocks.370	type BlockNumber = BlockNumber;371	/// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.372	type BlockWeights = RuntimeBlockWeights;373	/// The aggregated dispatch type that is available for extrinsics.374	type Call = Call;375	/// The weight of database operations that the runtime can invoke.376	type DbWeight = RocksDbWeight;377	/// The ubiquitous event type.378	type Event = Event;379	/// The type for hashing blocks and tries.380	type Hash = Hash;381	/// The hashing algorithm used.382	type Hashing = BlakeTwo256;383	/// The header type.384	type Header = generic::Header<BlockNumber, BlakeTwo256>;385	/// The index type for storing how many extrinsics an account has signed.386	type Index = Index;387	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.388	type Lookup = AccountIdLookup<AccountId, ()>;389	/// What to do if an account is fully reaped from the system.390	type OnKilledAccount = ();391	/// What to do if a new account is created.392	type OnNewAccount = ();393	type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;394	/// The ubiquitous origin type.395	type Origin = Origin;396	/// This type is being generated by `construct_runtime!`.397	type PalletInfo = PalletInfo;398	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.399	type SS58Prefix = SS58Prefix;400	/// Weight information for the extrinsics of this pallet.401	type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;402	/// Version of the runtime.403	type Version = Version;404	type MaxConsumers = ConstU32<16>;405}406407parameter_types! {408	pub const MinimumPeriod: u64 = SLOT_DURATION / 2;409}410411impl pallet_timestamp::Config for Runtime {412	/// A timestamp: milliseconds since the unix epoch.413	type Moment = u64;414	type OnTimestampSet = ();415	type MinimumPeriod = MinimumPeriod;416	type WeightInfo = ();417}418419parameter_types! {420	// pub const ExistentialDeposit: u128 = 500;421	pub const ExistentialDeposit: u128 = 0;422	pub const MaxLocks: u32 = 50;423	pub const MaxReserves: u32 = 50;424}425426impl pallet_balances::Config for Runtime {427	type MaxLocks = MaxLocks;428	type MaxReserves = MaxReserves;429	type ReserveIdentifier = [u8; 16];430	/// The type for recording an account's balance.431	type Balance = Balance;432	/// The ubiquitous event type.433	type Event = Event;434	type DustRemoval = Treasury;435	type ExistentialDeposit = ExistentialDeposit;436	type AccountStore = System;437	type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;438}439440pub const fn deposit(items: u32, bytes: u32) -> Balance {441	items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE442}443444/*445parameter_types! {446	pub TombstoneDeposit: Balance = deposit(447		1,448		sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,449	);450	pub DepositPerContract: Balance = TombstoneDeposit::get();451	pub const DepositPerStorageByte: Balance = deposit(0, 1);452	pub const DepositPerStorageItem: Balance = deposit(1, 0);453	pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);454	pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;455	pub const SignedClaimHandicap: u32 = 2;456	pub const MaxDepth: u32 = 32;457	pub const MaxValueSize: u32 = 16 * 1024;458	pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb459	// The lazy deletion runs inside on_initialize.460	pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *461		RuntimeBlockWeights::get().max_block;462	// The weight needed for decoding the queue should be less or equal than a fifth463	// of the overall weight dedicated to the lazy deletion.464	pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (465			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -466			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)467		)) / 5) as u32;468	pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();469}470471impl pallet_contracts::Config for Runtime {472	type Time = Timestamp;473	type Randomness = RandomnessCollectiveFlip;474	type Currency = Balances;475	type Event = Event;476	type RentPayment = ();477	type SignedClaimHandicap = SignedClaimHandicap;478	type TombstoneDeposit = TombstoneDeposit;479	type DepositPerContract = DepositPerContract;480	type DepositPerStorageByte = DepositPerStorageByte;481	type DepositPerStorageItem = DepositPerStorageItem;482	type RentFraction = RentFraction;483	type SurchargeReward = SurchargeReward;484	type WeightPrice = pallet_transaction_payment::Pallet<Self>;485	type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;486	type ChainExtension = NFTExtension;487	type DeletionQueueDepth = DeletionQueueDepth;488	type DeletionWeightLimit = DeletionWeightLimit;489	type Schedule = Schedule;490	type CallStack = [pallet_contracts::Frame<Self>; 31];491}492*/493494parameter_types! {495	/// This value increases the priority of `Operational` transactions by adding496	/// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.497	pub const OperationalFeeMultiplier: u8 = 5;498}499500/// Linear implementor of `WeightToFeePolynomial`501pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);502503impl<T> WeightToFeePolynomial for LinearFee<T>504where505	T: BaseArithmetic + From<u32> + Copy + Unsigned,506{507	type Balance = T;508509	fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {510		smallvec!(WeightToFeeCoefficient {511			// Targeting 0.1 Unique per NFT transfer512			coeff_integer: WEIGHT_TO_FEE_COEFF.into(),513			coeff_frac: Perbill::zero(),514			negative: false,515			degree: 1,516		})517	}518}519520impl pallet_transaction_payment::Config for Runtime {521	type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;522	type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;523	type OperationalFeeMultiplier = OperationalFeeMultiplier;524	type WeightToFee = LinearFee<Balance>;525	type FeeMultiplierUpdate = ();526}527528parameter_types! {529	pub const ProposalBond: Permill = Permill::from_percent(5);530	pub const ProposalBondMinimum: Balance = 1 * UNIQUE;531	pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;532	pub const SpendPeriod: BlockNumber = 5 * MINUTES;533	pub const Burn: Permill = Permill::from_percent(0);534	pub const TipCountdown: BlockNumber = 1 * DAYS;535	pub const TipFindersFee: Percent = Percent::from_percent(20);536	pub const TipReportDepositBase: Balance = 1 * UNIQUE;537	pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;538	pub const BountyDepositBase: Balance = 1 * UNIQUE;539	pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;540	pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");541	pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;542	pub const MaximumReasonLength: u32 = 16384;543	pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);544	pub const BountyValueMinimum: Balance = 5 * UNIQUE;545	pub const MaxApprovals: u32 = 100;546}547548impl pallet_treasury::Config for Runtime {549	type PalletId = TreasuryModuleId;550	type Currency = Balances;551	type ApproveOrigin = EnsureRoot<AccountId>;552	type RejectOrigin = EnsureRoot<AccountId>;553	type Event = Event;554	type OnSlash = ();555	type ProposalBond = ProposalBond;556	type ProposalBondMinimum = ProposalBondMinimum;557	type ProposalBondMaximum = ProposalBondMaximum;558	type SpendPeriod = SpendPeriod;559	type Burn = Burn;560	type BurnDestination = ();561	type SpendFunds = ();562	type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;563	type MaxApprovals = MaxApprovals;564}565566impl pallet_sudo::Config for Runtime {567	type Event = Event;568	type Call = Call;569}570571pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);572573impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider574	for RelayChainBlockNumberProvider<T>575{576	type BlockNumber = BlockNumber;577578	fn current_block_number() -> Self::BlockNumber {579		cumulus_pallet_parachain_system::Pallet::<T>::validation_data()580			.map(|d| d.relay_parent_number)581			.unwrap_or_default()582	}583}584585parameter_types! {586	pub const MinVestedTransfer: Balance = 10 * UNIQUE;587	pub const MaxVestingSchedules: u32 = 28;588}589590impl orml_vesting::Config for Runtime {591	type Event = Event;592	type Currency = pallet_balances::Pallet<Runtime>;593	type MinVestedTransfer = MinVestedTransfer;594	type VestedTransferOrigin = EnsureSigned<AccountId>;595	type WeightInfo = ();596	type MaxVestingSchedules = MaxVestingSchedules;597	type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;598}599600parameter_types! {601	pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;602	pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;603}604605impl cumulus_pallet_parachain_system::Config for Runtime {606	type Event = Event;607	type SelfParaId = parachain_info::Pallet<Self>;608	type OnSystemEvent = ();609	// type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<610	// 	MaxDownwardMessageWeight,611	// 	XcmExecutor<XcmConfig>,612	// 	Call,613	// >;614	type OutboundXcmpMessageSource = XcmpQueue;615	type DmpMessageHandler = DmpQueue;616	type ReservedDmpWeight = ReservedDmpWeight;617	type ReservedXcmpWeight = ReservedXcmpWeight;618	type XcmpMessageHandler = XcmpQueue;619}620621impl parachain_info::Config for Runtime {}622623impl cumulus_pallet_aura_ext::Config for Runtime {}624625parameter_types! {626	pub const RelayLocation: MultiLocation = MultiLocation::parent();627	pub const RelayNetwork: NetworkId = NetworkId::Polkadot;628	pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();629	pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();630}631632/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used633/// when determining ownership of accounts for asset transacting and when attempting to use XCM634/// `Transact` in order to determine the dispatch Origin.635pub type LocationToAccountId = (636	// The parent (Relay-chain) origin converts to the default `AccountId`.637	ParentIsPreset<AccountId>,638	// Sibling parachain origins convert to AccountId via the `ParaId::into`.639	SiblingParachainConvertsVia<Sibling, AccountId>,640	// Straight up local `AccountId32` origins just alias directly to `AccountId`.641	AccountId32Aliases<RelayNetwork, AccountId>,642);643644pub struct OnlySelfCurrency;645impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {646	fn matches_fungible(a: &MultiAsset) -> Option<B> {647		match (&a.id, &a.fun) {648			(Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),649			_ => None,650		}651	}652}653654/// Means for transacting assets on this chain.655pub type LocalAssetTransactor = CurrencyAdapter<656	// Use this currency:657	Balances,658	// Use this currency when it is a fungible asset matching the given location or name:659	OnlySelfCurrency,660	// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:661	LocationToAccountId,662	// Our chain's account ID type (we can't get away without mentioning it explicitly):663	AccountId,664	// We don't track any teleports.665	(),666>;667668/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,669/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can670/// biases the kind of local `Origin` it will become.671pub type XcmOriginToTransactDispatchOrigin = (672	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location673	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for674	// foreign chains who want to have a local sovereign account on this chain which they control.675	SovereignSignedViaLocation<LocationToAccountId, Origin>,676	// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when677	// recognised.678	RelayChainAsNative<RelayOrigin, Origin>,679	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when680	// recognised.681	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,682	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a683	// transaction from the Root origin.684	ParentAsSuperuser<Origin>,685	// Native signed account converter; this just converts an `AccountId32` origin into a normal686	// `Origin::Signed` origin of the same 32-byte value.687	SignedAccountId32AsNative<RelayNetwork, Origin>,688	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.689	XcmPassthrough<Origin>,690);691692parameter_types! {693	// One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.694	pub UnitWeightCost: Weight = 1_000_000;695	// 1200 UNIQUEs buy 1 second of weight.696	pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);697	pub const MaxInstructions: u32 = 100;698	pub const MaxAuthorities: u32 = 100_000;699}700701match_types! {702	pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {703		MultiLocation { parents: 1, interior: Here } |704		MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }705	};706}707708pub type Barrier = (709	TakeWeightCredit,710	AllowTopLevelPaidExecutionFrom<Everything>,711	AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,712	// ^^^ Parent & its unit plurality gets free execution713);714715pub struct UsingOnlySelfCurrencyComponents<716	WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,717	AssetId: Get<MultiLocation>,718	AccountId,719	Currency: CurrencyT<AccountId>,720	OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,721>(722	Weight,723	Currency::Balance,724	PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,725);726impl<727		WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,728		AssetId: Get<MultiLocation>,729		AccountId,730		Currency: CurrencyT<AccountId>,731		OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,732	> WeightTrader733	for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>734{735	fn new() -> Self {736		Self(0, Zero::zero(), PhantomData)737	}738739	fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {740		let amount = WeightToFee::calc(&weight);741		let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;742743		// location to this parachain through relay chain744		let option1: xcm::v1::AssetId = Concrete(MultiLocation {745			parents: 1,746			interior: X1(Parachain(ParachainInfo::parachain_id().into())),747		});748		// direct location749		let option2: xcm::v1::AssetId = Concrete(MultiLocation {750			parents: 0,751			interior: Here,752		});753754		let required = if payment.fungible.contains_key(&option1) {755			(option1, u128_amount).into()756		} else if payment.fungible.contains_key(&option2) {757			(option2, u128_amount).into()758		} else {759			(Concrete(MultiLocation::default()), u128_amount).into()760		};761762		let unused = payment763			.checked_sub(required)764			.map_err(|_| XcmError::TooExpensive)?;765		self.0 = self.0.saturating_add(weight);766		self.1 = self.1.saturating_add(amount);767		Ok(unused)768	}769770	fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {771		let weight = weight.min(self.0);772		let amount = WeightToFee::calc(&weight);773		self.0 -= weight;774		self.1 = self.1.saturating_sub(amount);775		let amount: u128 = amount.saturated_into();776		if amount > 0 {777			Some((AssetId::get(), amount).into())778		} else {779			None780		}781	}782}783impl<784		WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,785		AssetId: Get<MultiLocation>,786		AccountId,787		Currency: CurrencyT<AccountId>,788		OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,789	> Drop790	for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>791{792	fn drop(&mut self) {793		OnUnbalanced::on_unbalanced(Currency::issue(self.1));794	}795}796797pub struct XcmConfig;798impl Config for XcmConfig {799	type Call = Call;800	type XcmSender = XcmRouter;801	// How to withdraw and deposit an asset.802	type AssetTransactor = LocalAssetTransactor;803	type OriginConverter = XcmOriginToTransactDispatchOrigin;804	type IsReserve = NativeAsset;805	type IsTeleporter = (); // Teleportation is disabled806	type LocationInverter = LocationInverter<Ancestry>;807	type Barrier = Barrier;808	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;809	type Trader = UsingOnlySelfCurrencyComponents<810		IdentityFee<Balance>,811		RelayLocation,812		AccountId,813		Balances,814		(),815	>;816	type ResponseHandler = (); // Don't handle responses for now.817	type SubscriptionService = PolkadotXcm;818819	type AssetTrap = PolkadotXcm;820	type AssetClaims = PolkadotXcm;821}822823// parameter_types! {824// 	pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;825// }826827/// No local origins on this chain are allowed to dispatch XCM sends/executions.828pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);829830/// The means for routing XCM messages which are not for local execution into the right message831/// queues.832pub type XcmRouter = (833	// Two routers - use UMP to communicate with the relay chain:834	cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,835	// ..and XCMP to communicate with the sibling chains.836	XcmpQueue,837);838839impl pallet_evm_coder_substrate::Config for Runtime {}840841impl pallet_xcm::Config for Runtime {842	type Event = Event;843	type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;844	type XcmRouter = XcmRouter;845	type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;846	type XcmExecuteFilter = Everything;847	type XcmExecutor = XcmExecutor<XcmConfig>;848	type XcmTeleportFilter = Everything;849	type XcmReserveTransferFilter = Everything;850	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;851	type LocationInverter = LocationInverter<Ancestry>;852	type Origin = Origin;853	type Call = Call;854	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;855	type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;856}857858impl cumulus_pallet_xcm::Config for Runtime {859	type Event = Event;860	type XcmExecutor = XcmExecutor<XcmConfig>;861}862863impl cumulus_pallet_xcmp_queue::Config for Runtime {864	type WeightInfo = ();865	type Event = Event;866	type XcmExecutor = XcmExecutor<XcmConfig>;867	type ChannelInfo = ParachainSystem;868	type VersionWrapper = ();869	type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;870	type ControllerOrigin = EnsureRoot<AccountId>;871	type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;872}873874impl cumulus_pallet_dmp_queue::Config for Runtime {875	type Event = Event;876	type XcmExecutor = XcmExecutor<XcmConfig>;877	type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;878}879880impl pallet_aura::Config for Runtime {881	type AuthorityId = AuraId;882	type DisabledValidators = ();883	type MaxAuthorities = MaxAuthorities;884}885886parameter_types! {887	pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();888	pub const CollectionCreationPrice: Balance = 2 * UNIQUE;889}890891impl pallet_common::Config for Runtime {892	type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;893	type Event = Event;894	type Currency = Balances;895	type CollectionCreationPrice = CollectionCreationPrice;896	type TreasuryAccountId = TreasuryAccountId;897	type CollectionDispatch = CollectionDispatchT<Self>;898899	type EvmTokenAddressMapping = EvmTokenAddressMapping;900	type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;901	type ContractAddress = EvmCollectionHelpersAddress;902}903904impl pallet_structure::Config for Runtime {905	type Event = Event;906	type Call = Call;907	type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;908}909910impl pallet_fungible::Config for Runtime {911	type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;912}913impl pallet_refungible::Config for Runtime {914	type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;915}916impl pallet_nonfungible::Config for Runtime {917	type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;918}919920impl pallet_proxy_rmrk_core::Config for Runtime {921	type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;922	type Event = Event;923}924925impl pallet_proxy_rmrk_equip::Config for Runtime {926	type Event = Event;927}928929impl pallet_unique::Config for Runtime {930	type Event = Event;931	type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;932	type CommonWeightInfo = CommonWeights<Self>;933}934935parameter_types! {936	pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied937}938939/// Used for the pallet inflation940impl pallet_inflation::Config for Runtime {941	type Currency = Balances;942	type TreasuryAccountId = TreasuryAccountId;943	type InflationBlockInterval = InflationBlockInterval;944	type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;945}946947parameter_types! {948	pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *949		RuntimeBlockWeights::get().max_block;950	pub const MaxScheduledPerBlock: u32 = 50;951}952953type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;954use frame_support::traits::NamedReservableCurrency;955956fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {957	(958		frame_system::CheckSpecVersion::<Runtime>::new(),959		frame_system::CheckGenesis::<Runtime>::new(),960		frame_system::CheckEra::<Runtime>::from(Era::Immortal),961		frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(962			from,963		)),964		frame_system::CheckWeight::<Runtime>::new(),965		// sponsoring transaction logic966		// pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),967	)968}969970pub struct SchedulerPaymentExecutor;971impl<T: frame_system::Config + pallet_unq_scheduler::Config, SelfContainedSignedInfo>972	DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor973where974	<T as frame_system::Config>::Call: Member975		+ Dispatchable<Origin = Origin, Info = DispatchInfo>976		+ SelfContainedCall<SignedInfo = SelfContainedSignedInfo>977		+ GetDispatchInfo978		+ From<frame_system::Call<Runtime>>,979	SelfContainedSignedInfo: Send + Sync + 'static,980	Call: From<<T as frame_system::Config>::Call>981		+ From<<T as pallet_unq_scheduler::Config>::Call>982		+ SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,983	sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,984{985	fn dispatch_call(986		signer: <T as frame_system::Config>::AccountId,987		call: <T as pallet_unq_scheduler::Config>::Call,988	) -> Result<989		Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,990		TransactionValidityError,991	> {992		let dispatch_info = call.get_dispatch_info();993		let extrinsic = fp_self_contained::CheckedExtrinsic::<994			AccountId,995			Call,996			SignedExtraScheduler,997			SelfContainedSignedInfo,998		> {999			signed:1000				CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(1001					signer.clone().into(),1002					get_signed_extras(signer.into()),1003				),1004			function: call.into(),1005		};10061007		extrinsic.apply::<Runtime>(&dispatch_info, 0)1008	}10091010	fn reserve_balance(1011		id: [u8; 16],1012		sponsor: <T as frame_system::Config>::AccountId,1013		call: <T as pallet_unq_scheduler::Config>::Call,1014		count: u32,1015	) -> Result<(), DispatchError> {1016		let dispatch_info = call.get_dispatch_info();1017		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)1018			.saturating_mul(count.into());10191020		<Balances as NamedReservableCurrency<AccountId>>::reserve_named(1021			&id,1022			&(sponsor.into()),1023			weight.into(),1024		)1025	}10261027	fn pay_for_call(1028		id: [u8; 16],1029		sponsor: <T as frame_system::Config>::AccountId,1030		call: <T as pallet_unq_scheduler::Config>::Call,1031	) -> Result<u128, DispatchError> {1032		let dispatch_info = call.get_dispatch_info();1033		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);1034		Ok(1035			<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1036				&id,1037				&(sponsor.into()),1038				weight.into(),1039			),1040		)1041	}10421043	fn cancel_reserve(1044		id: [u8; 16],1045		sponsor: <T as frame_system::Config>::AccountId,1046	) -> Result<u128, DispatchError> {1047		Ok(1048			<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1049				&id,1050				&(sponsor.into()),1051				u128::MAX,1052			),1053		)1054	}1055}10561057parameter_types! {1058	pub const NoPreimagePostponement: Option<u32> = Some(10);1059	pub const Preimage: Option<u32> = Some(10);1060}10611062/// Used the compare the privilege of an origin inside the scheduler.1063pub struct OriginPrivilegeCmp;10641065impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {1066	fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {1067		Some(Ordering::Equal)1068	}1069}10701071impl pallet_unq_scheduler::Config for Runtime {1072	type Event = Event;1073	type Origin = Origin;1074	type Currency = Balances;1075	type PalletsOrigin = OriginCaller;1076	type Call = Call;1077	type MaximumWeight = MaximumSchedulerWeight;1078	type ScheduleOrigin = EnsureSigned<AccountId>;1079	type MaxScheduledPerBlock = MaxScheduledPerBlock;1080	type WeightInfo = ();1081	type CallExecutor = SchedulerPaymentExecutor;1082	type OriginPrivilegeCmp = OriginPrivilegeCmp;1083	type PreimageProvider = ();1084	type NoPreimagePostponement = NoPreimagePostponement;1085}10861087type EvmSponsorshipHandler = (1088	UniqueEthSponsorshipHandler<Runtime>,1089	pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,1090);1091type SponsorshipHandler = (1092	UniqueSponsorshipHandler<Runtime>,1093	//pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,1094	pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,1095);10961097impl pallet_evm_transaction_payment::Config for Runtime {1098	type EvmSponsorshipHandler = EvmSponsorshipHandler;1099	type Currency = Balances;1100}11011102impl pallet_charge_transaction::Config for Runtime {1103	type SponsorshipHandler = SponsorshipHandler;1104}11051106// impl pallet_contract_helpers::Config for Runtime {1107//	 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1108// }11091110parameter_types! {1111	// 0x842899ECF380553E8a4de75bF534cdf6fBF640491112	pub const HelpersContractAddress: H160 = H160([1113		0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,1114	]);11151116	// 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f1117	pub const EvmCollectionHelpersAddress: H160 = H160([1118		0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,1119	]);1120}11211122impl pallet_evm_contract_helpers::Config for Runtime {1123	type ContractAddress = HelpersContractAddress;1124	type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1125}11261127construct_runtime!(1128	pub enum Runtime where1129		Block = Block,1130		NodeBlock = opaque::Block,1131		UncheckedExtrinsic = UncheckedExtrinsic1132	{1133		ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,1134		ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,11351136		Aura: pallet_aura::{Pallet, Config<T>} = 22,1137		AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,11381139		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,1140		RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,1141		Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,1142		TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,1143		Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,1144		Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,1145		System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,1146		Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,1147		// Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,1148		// Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,11491150		// XCM helpers.1151		XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,1152		PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,1153		CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,1154		DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,11551156		// Unique Pallets1157		Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,1158		Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,1159		Scheduler: pallet_unq_scheduler::{Pallet, Call, Storage, Event<T>} = 62,1160		// free = 631161		Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,1162		// ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,1163		Common: pallet_common::{Pallet, Storage, Event<T>} = 66,1164		Fungible: pallet_fungible::{Pallet, Storage} = 67,1165		Refungible: pallet_refungible::{Pallet, Storage} = 68,1166		Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,1167		Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,1168		RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,1169		RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,11701171		// Frontier1172		EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,1173		Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,11741175		EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,1176		EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,1177		EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,1178		EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,1179	}1180);11811182pub struct TransactionConverter;11831184impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {1185	fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {1186		UncheckedExtrinsic::new_unsigned(1187			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1188		)1189	}1190}11911192impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {1193	fn convert_transaction(1194		&self,1195		transaction: pallet_ethereum::Transaction,1196	) -> opaque::UncheckedExtrinsic {1197		let extrinsic = UncheckedExtrinsic::new_unsigned(1198			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1199		);1200		let encoded = extrinsic.encode();1201		opaque::UncheckedExtrinsic::decode(&mut &encoded[..])1202			.expect("Encoded extrinsic is always valid")1203	}1204}12051206/// The address format for describing accounts.1207pub type Address = sp_runtime::MultiAddress<AccountId, ()>;1208/// Block header type as expected by this runtime.1209pub type Header = generic::Header<BlockNumber, BlakeTwo256>;1210/// Block type as expected by this runtime.1211pub type Block = generic::Block<Header, UncheckedExtrinsic>;1212/// A Block signed with a Justification1213pub type SignedBlock = generic::SignedBlock<Block>;1214/// BlockId type as expected by this runtime.1215pub type BlockId = generic::BlockId<Block>;1216/// The SignedExtension to the basic transaction logic.1217pub type SignedExtra = (1218	frame_system::CheckSpecVersion<Runtime>,1219	// system::CheckTxVersion<Runtime>,1220	frame_system::CheckGenesis<Runtime>,1221	frame_system::CheckEra<Runtime>,1222	frame_system::CheckNonce<Runtime>,1223	frame_system::CheckWeight<Runtime>,1224	ChargeTransactionPayment,1225	//pallet_contract_helpers::ContractHelpersExtension<Runtime>,1226	pallet_ethereum::FakeTransactionFinalizer<Runtime>,1227);12281229pub type SignedExtraScheduler = (1230	frame_system::CheckSpecVersion<Runtime>,1231	frame_system::CheckGenesis<Runtime>,1232	frame_system::CheckEra<Runtime>,1233	frame_system::CheckNonce<Runtime>,1234	frame_system::CheckWeight<Runtime>,1235	// pallet_charge_transaction::ChargeTransactionPayment<Runtime>,1236);1237/// Unchecked extrinsic type as expected by this runtime.1238pub type UncheckedExtrinsic =1239	fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;1240/// Extrinsic type that has already been checked.1241pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;1242/// Executive: handles dispatch to the various modules.1243pub type Executive = frame_executive::Executive<1244	Runtime,1245	Block,1246	frame_system::ChainContext<Runtime>,1247	Runtime,1248	AllPalletsReversedWithSystemFirst,1249>;12501251impl_opaque_keys! {1252	pub struct SessionKeys {1253		pub aura: Aura,1254	}1255}12561257impl fp_self_contained::SelfContainedCall for Call {1258	type SignedInfo = H160;12591260	fn is_self_contained(&self) -> bool {1261		match self {1262			Call::Ethereum(call) => call.is_self_contained(),1263			_ => false,1264		}1265	}12661267	fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {1268		match self {1269			Call::Ethereum(call) => call.check_self_contained(),1270			_ => None,1271		}1272	}12731274	fn validate_self_contained(1275		&self,1276		info: &Self::SignedInfo,1277		dispatch_info: &DispatchInfoOf<Call>,1278		len: usize,1279	) -> Option<TransactionValidity> {1280		match self {1281			Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),1282			_ => None,1283		}1284	}12851286	fn pre_dispatch_self_contained(1287		&self,1288		info: &Self::SignedInfo,1289	) -> Option<Result<(), TransactionValidityError>> {1290		match self {1291			Call::Ethereum(call) => call.pre_dispatch_self_contained(info),1292			_ => None,1293		}1294	}12951296	fn apply_self_contained(1297		self,1298		info: Self::SignedInfo,1299	) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {1300		match self {1301			call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(1302				Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),1303			)),1304			_ => None,1305		}1306	}1307}13081309macro_rules! dispatch_unique_runtime {1310	($collection:ident.$method:ident($($name:ident),*)) => {{1311		let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);1312		let dispatch = collection.as_dyn();13131314		Ok::<_, DispatchError>(dispatch.$method($($name),*))1315	}};1316}13171318impl_common_runtime_apis!();13191320struct CheckInherents;13211322impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {1323	fn check_inherents(1324		block: &Block,1325		relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,1326	) -> sp_inherents::CheckInherentsResult {1327		let relay_chain_slot = relay_state_proof1328			.read_slot()1329			.expect("Could not read the relay chain slot from the proof");13301331		let inherent_data =1332			cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(1333				relay_chain_slot,1334				sp_std::time::Duration::from_secs(6),1335			)1336			.create_inherent_data()1337			.expect("Could not create the timestamp inherent data");13381339		inherent_data.check_extrinsics(block)1340	}1341}13421343cumulus_pallet_parachain_system::register_validate_block!(1344	Runtime = Runtime,1345	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,1346	CheckInherents = CheckInherents,1347);
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);