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
before · runtime/opal/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;93// use scale_info::TypeInfo;94use codec::{Encode, Decode};95use fp_rpc::TransactionStatus;96use sp_runtime::{97	traits::{98		Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,99		Saturating, CheckedConversion,100	},101	generic::Era,102	transaction_validity::TransactionValidityError,103	DispatchErrorWithPostInfo, SaturatedConversion,104};105106// pub use pallet_timestamp::Call as TimestampCall;107pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;108109// Polkadot imports110use pallet_xcm::XcmPassthrough;111use polkadot_parachain::primitives::Sibling;112use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};113use xcm_builder::{114	AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,115	EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,116	RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,117	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,118	ParentIsPreset,119};120use xcm_executor::{Config, XcmExecutor, Assets};121use sp_std::{cmp::Ordering, marker::PhantomData};122123use xcm::latest::{124	//	Xcm,125	AssetId::{Concrete},126	Fungibility::Fungible as XcmFungible,127	MultiAsset,128	Error as XcmError,129};130use xcm_executor::traits::{MatchesFungible, WeightTrader};131//use xcm_executor::traits::MatchesFungible;132133use unique_runtime_common::{134	impl_common_runtime_apis,135	types::*,136	constants::*,137	dispatch::{CollectionDispatchT, CollectionDispatch},138	sponsoring::UniqueSponsorshipHandler,139	eth_sponsoring::UniqueEthSponsorshipHandler,140	weights::CommonWeights,141};142143pub const RUNTIME_NAME: &str = "opal";144pub const TOKEN_SYMBOL: &str = "OPL";145146type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;147148impl RuntimeInstance for Runtime {149	type CrossAccountId = self::CrossAccountId;150	type TransactionConverter = self::TransactionConverter;151152	fn get_transaction_converter() -> TransactionConverter {153		TransactionConverter154	}155}156157/// The type for looking up accounts. We don't expect more than 4 billion of them, but you158/// never know...159pub type AccountIndex = u32;160161/// Balance of an account.162pub type Balance = u128;163164/// Index of a transaction in the chain.165pub type Index = u32;166167/// A hash of some data used by the chain.168pub type Hash = sp_core::H256;169170/// Digest item type.171pub type DigestItem = generic::DigestItem;172173/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know174/// the specifics of the runtime. They can then be made to be agnostic over specific formats175/// of data like extrinsics, allowing for them to continue syncing the network through upgrades176/// to even the core data structures.177pub mod opaque {178	use sp_std::prelude::*;179	use sp_runtime::impl_opaque_keys;180	use super::Aura;181182	pub use unique_runtime_common::types::*;183184	impl_opaque_keys! {185		pub struct SessionKeys {186			pub aura: Aura,187		}188	}189}190191/// This runtime version.192pub const VERSION: RuntimeVersion = RuntimeVersion {193	spec_name: create_runtime_str!(RUNTIME_NAME),194	impl_name: create_runtime_str!(RUNTIME_NAME),195	authoring_version: 1,196	spec_version: 922000,197	impl_version: 0,198	apis: RUNTIME_API_VERSIONS,199	transaction_version: 1,200	state_version: 0,201};202203#[derive(codec::Encode, codec::Decode)]204pub enum XCMPMessage<XAccountId, XBalance> {205	/// Transfer tokens to the given account from the Parachain account.206	TransferToken(XAccountId, XBalance),207}208209/// The version information used to identify this runtime when compiled natively.210#[cfg(feature = "std")]211pub fn native_version() -> NativeVersion {212	NativeVersion {213		runtime_version: VERSION,214		can_author_with: Default::default(),215	}216}217218type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;219220pub struct DealWithFees;221impl OnUnbalanced<NegativeImbalance> for DealWithFees {222	fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {223		if let Some(fees) = fees_then_tips.next() {224			// for fees, 100% to treasury225			let mut split = fees.ration(100, 0);226			if let Some(tips) = fees_then_tips.next() {227				// for tips, if any, 100% to treasury228				tips.ration_merge_into(100, 0, &mut split);229			}230			Treasury::on_unbalanced(split.0);231			// Author::on_unbalanced(split.1);232		}233	}234}235236parameter_types! {237	pub const BlockHashCount: BlockNumber = 2400;238	pub RuntimeBlockLength: BlockLength =239		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);240	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);241	pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;242	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()243		.base_block(BlockExecutionWeight::get())244		.for_class(DispatchClass::all(), |weights| {245			weights.base_extrinsic = ExtrinsicBaseWeight::get();246		})247		.for_class(DispatchClass::Normal, |weights| {248			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);249		})250		.for_class(DispatchClass::Operational, |weights| {251			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);252			// Operational transactions have some extra reserved space, so that they253			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.254			weights.reserved = Some(255				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT256			);257		})258		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)259		.build_or_panic();260	pub const Version: RuntimeVersion = VERSION;261	pub const SS58Prefix: u8 = 42;262}263264parameter_types! {265	pub const ChainId: u64 = 8882;266}267268pub struct FixedFee;269impl FeeCalculator for FixedFee {270	fn min_gas_price() -> (U256, u64) {271		(MIN_GAS_PRICE.into(), 0)272	}273}274275// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case276// (contract, which only writes a lot of data),277// approximating on top of our real store write weight278parameter_types! {279	pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;280	pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;281	pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();282}283284/// Limiting EVM execution to 50% of block for substrate users and management tasks285/// EVM transaction consumes more weight than substrate's, so we can't rely on them being286/// scheduled fairly287const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);288parameter_types! {289	pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());290}291292pub enum FixedGasWeightMapping {}293impl GasWeightMapping for FixedGasWeightMapping {294	fn gas_to_weight(gas: u64) -> Weight {295		gas.saturating_mul(WeightPerGas::get())296	}297	fn weight_to_gas(weight: Weight) -> u64 {298		weight / WeightPerGas::get()299	}300}301302impl pallet_evm::account::Config for Runtime {303	type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;304	type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;305	type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;306}307308impl pallet_evm::Config for Runtime {309	type BlockGasLimit = BlockGasLimit;310	type FeeCalculator = FixedFee;311	type GasWeightMapping = FixedGasWeightMapping;312	type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;313	type CallOrigin = EnsureAddressTruncated<Self>;314	type WithdrawOrigin = EnsureAddressTruncated<Self>;315	type AddressMapping = HashedAddressMapping<Self::Hashing>;316	type PrecompilesType = ();317	type PrecompilesValue = ();318	type Currency = Balances;319	type Event = Event;320	type OnMethodCall = (321		pallet_evm_migration::OnMethodCall<Self>,322		pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,323		CollectionDispatchT<Self>,324		pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,325	);326	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;327	type ChainId = ChainId;328	type Runner = pallet_evm::runner::stack::Runner<Self>;329	type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;330	type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;331	type FindAuthor = EthereumFindAuthor<Aura>;332}333334impl pallet_evm_migration::Config for Runtime {335	type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;336}337338pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);339impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {340	fn find_author<'a, I>(digests: I) -> Option<H160>341	where342		I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,343	{344		if let Some(author_index) = F::find_author(digests) {345			let authority_id = Aura::authorities()[author_index as usize].clone();346			return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));347		}348		None349	}350}351352impl pallet_ethereum::Config for Runtime {353	type Event = Event;354	type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;355}356357impl pallet_randomness_collective_flip::Config for Runtime {}358359impl frame_system::Config for Runtime {360	/// The data to be stored in an account.361	type AccountData = pallet_balances::AccountData<Balance>;362	/// The identifier used to distinguish between accounts.363	type AccountId = AccountId;364	/// The basic call filter to use in dispatchable.365	type BaseCallFilter = Everything;366	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).367	type BlockHashCount = BlockHashCount;368	/// The maximum length of a block (in bytes).369	type BlockLength = RuntimeBlockLength;370	/// The index type for blocks.371	type BlockNumber = BlockNumber;372	/// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.373	type BlockWeights = RuntimeBlockWeights;374	/// The aggregated dispatch type that is available for extrinsics.375	type Call = Call;376	/// The weight of database operations that the runtime can invoke.377	type DbWeight = RocksDbWeight;378	/// The ubiquitous event type.379	type Event = Event;380	/// The type for hashing blocks and tries.381	type Hash = Hash;382	/// The hashing algorithm used.383	type Hashing = BlakeTwo256;384	/// The header type.385	type Header = generic::Header<BlockNumber, BlakeTwo256>;386	/// The index type for storing how many extrinsics an account has signed.387	type Index = Index;388	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.389	type Lookup = AccountIdLookup<AccountId, ()>;390	/// What to do if an account is fully reaped from the system.391	type OnKilledAccount = ();392	/// What to do if a new account is created.393	type OnNewAccount = ();394	type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;395	/// The ubiquitous origin type.396	type Origin = Origin;397	/// This type is being generated by `construct_runtime!`.398	type PalletInfo = PalletInfo;399	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.400	type SS58Prefix = SS58Prefix;401	/// Weight information for the extrinsics of this pallet.402	type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;403	/// Version of the runtime.404	type Version = Version;405	type MaxConsumers = ConstU32<16>;406}407408parameter_types! {409	pub const MinimumPeriod: u64 = SLOT_DURATION / 2;410}411412impl pallet_timestamp::Config for Runtime {413	/// A timestamp: milliseconds since the unix epoch.414	type Moment = u64;415	type OnTimestampSet = ();416	type MinimumPeriod = MinimumPeriod;417	type WeightInfo = ();418}419420parameter_types! {421	// pub const ExistentialDeposit: u128 = 500;422	pub const ExistentialDeposit: u128 = 0;423	pub const MaxLocks: u32 = 50;424	pub const MaxReserves: u32 = 50;425}426427impl pallet_balances::Config for Runtime {428	type MaxLocks = MaxLocks;429	type MaxReserves = MaxReserves;430	type ReserveIdentifier = [u8; 16];431	/// The type for recording an account's balance.432	type Balance = Balance;433	/// The ubiquitous event type.434	type Event = Event;435	type DustRemoval = Treasury;436	type ExistentialDeposit = ExistentialDeposit;437	type AccountStore = System;438	type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;439}440441pub const fn deposit(items: u32, bytes: u32) -> Balance {442	items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE443}444445/*446parameter_types! {447	pub TombstoneDeposit: Balance = deposit(448		1,449		sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,450	);451	pub DepositPerContract: Balance = TombstoneDeposit::get();452	pub const DepositPerStorageByte: Balance = deposit(0, 1);453	pub const DepositPerStorageItem: Balance = deposit(1, 0);454	pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);455	pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;456	pub const SignedClaimHandicap: u32 = 2;457	pub const MaxDepth: u32 = 32;458	pub const MaxValueSize: u32 = 16 * 1024;459	pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb460	// The lazy deletion runs inside on_initialize.461	pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *462		RuntimeBlockWeights::get().max_block;463	// The weight needed for decoding the queue should be less or equal than a fifth464	// of the overall weight dedicated to the lazy deletion.465	pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (466			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -467			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)468		)) / 5) as u32;469	pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();470}471472impl pallet_contracts::Config for Runtime {473	type Time = Timestamp;474	type Randomness = RandomnessCollectiveFlip;475	type Currency = Balances;476	type Event = Event;477	type RentPayment = ();478	type SignedClaimHandicap = SignedClaimHandicap;479	type TombstoneDeposit = TombstoneDeposit;480	type DepositPerContract = DepositPerContract;481	type DepositPerStorageByte = DepositPerStorageByte;482	type DepositPerStorageItem = DepositPerStorageItem;483	type RentFraction = RentFraction;484	type SurchargeReward = SurchargeReward;485	type WeightPrice = pallet_transaction_payment::Pallet<Self>;486	type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;487	type ChainExtension = NFTExtension;488	type DeletionQueueDepth = DeletionQueueDepth;489	type DeletionWeightLimit = DeletionWeightLimit;490	type Schedule = Schedule;491	type CallStack = [pallet_contracts::Frame<Self>; 31];492}493*/494495parameter_types! {496	/// This value increases the priority of `Operational` transactions by adding497	/// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.498	pub const OperationalFeeMultiplier: u8 = 5;499}500501/// Linear implementor of `WeightToFeePolynomial`502pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);503504impl<T> WeightToFeePolynomial for LinearFee<T>505where506	T: BaseArithmetic + From<u32> + Copy + Unsigned,507{508	type Balance = T;509510	fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {511		smallvec!(WeightToFeeCoefficient {512			// Targeting 0.1 Unique per NFT transfer513			coeff_integer: WEIGHT_TO_FEE_COEFF.into(),514			coeff_frac: Perbill::zero(),515			negative: false,516			degree: 1,517		})518	}519}520521impl pallet_transaction_payment::Config for Runtime {522	type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;523	type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;524	type OperationalFeeMultiplier = OperationalFeeMultiplier;525	type WeightToFee = LinearFee<Balance>;526	type FeeMultiplierUpdate = ();527}528529parameter_types! {530	pub const ProposalBond: Permill = Permill::from_percent(5);531	pub const ProposalBondMinimum: Balance = 1 * UNIQUE;532	pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;533	pub const SpendPeriod: BlockNumber = 5 * MINUTES;534	pub const Burn: Permill = Permill::from_percent(0);535	pub const TipCountdown: BlockNumber = 1 * DAYS;536	pub const TipFindersFee: Percent = Percent::from_percent(20);537	pub const TipReportDepositBase: Balance = 1 * UNIQUE;538	pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;539	pub const BountyDepositBase: Balance = 1 * UNIQUE;540	pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;541	pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");542	pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;543	pub const MaximumReasonLength: u32 = 16384;544	pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);545	pub const BountyValueMinimum: Balance = 5 * UNIQUE;546	pub const MaxApprovals: u32 = 100;547}548549impl pallet_treasury::Config for Runtime {550	type PalletId = TreasuryModuleId;551	type Currency = Balances;552	type ApproveOrigin = EnsureRoot<AccountId>;553	type RejectOrigin = EnsureRoot<AccountId>;554	type Event = Event;555	type OnSlash = ();556	type ProposalBond = ProposalBond;557	type ProposalBondMinimum = ProposalBondMinimum;558	type ProposalBondMaximum = ProposalBondMaximum;559	type SpendPeriod = SpendPeriod;560	type Burn = Burn;561	type BurnDestination = ();562	type SpendFunds = ();563	type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;564	type MaxApprovals = MaxApprovals;565}566567impl pallet_sudo::Config for Runtime {568	type Event = Event;569	type Call = Call;570}571572pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);573574impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider575	for RelayChainBlockNumberProvider<T>576{577	type BlockNumber = BlockNumber;578579	fn current_block_number() -> Self::BlockNumber {580		cumulus_pallet_parachain_system::Pallet::<T>::validation_data()581			.map(|d| d.relay_parent_number)582			.unwrap_or_default()583	}584}585586parameter_types! {587	pub const MinVestedTransfer: Balance = 10 * UNIQUE;588	pub const MaxVestingSchedules: u32 = 28;589}590591impl orml_vesting::Config for Runtime {592	type Event = Event;593	type Currency = pallet_balances::Pallet<Runtime>;594	type MinVestedTransfer = MinVestedTransfer;595	type VestedTransferOrigin = EnsureSigned<AccountId>;596	type WeightInfo = ();597	type MaxVestingSchedules = MaxVestingSchedules;598	type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;599}600601parameter_types! {602	pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;603	pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;604}605606impl cumulus_pallet_parachain_system::Config for Runtime {607	type Event = Event;608	type SelfParaId = parachain_info::Pallet<Self>;609	type OnSystemEvent = ();610	// type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<611	// 	MaxDownwardMessageWeight,612	// 	XcmExecutor<XcmConfig>,613	// 	Call,614	// >;615	type OutboundXcmpMessageSource = XcmpQueue;616	type DmpMessageHandler = DmpQueue;617	type ReservedDmpWeight = ReservedDmpWeight;618	type ReservedXcmpWeight = ReservedXcmpWeight;619	type XcmpMessageHandler = XcmpQueue;620}621622impl parachain_info::Config for Runtime {}623624impl cumulus_pallet_aura_ext::Config for Runtime {}625626parameter_types! {627	pub const RelayLocation: MultiLocation = MultiLocation::parent();628	pub const RelayNetwork: NetworkId = NetworkId::Polkadot;629	pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();630	pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();631}632633/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used634/// when determining ownership of accounts for asset transacting and when attempting to use XCM635/// `Transact` in order to determine the dispatch Origin.636pub type LocationToAccountId = (637	// The parent (Relay-chain) origin converts to the default `AccountId`.638	ParentIsPreset<AccountId>,639	// Sibling parachain origins convert to AccountId via the `ParaId::into`.640	SiblingParachainConvertsVia<Sibling, AccountId>,641	// Straight up local `AccountId32` origins just alias directly to `AccountId`.642	AccountId32Aliases<RelayNetwork, AccountId>,643);644645pub struct OnlySelfCurrency;646impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {647	fn matches_fungible(a: &MultiAsset) -> Option<B> {648		match (&a.id, &a.fun) {649			(Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),650			_ => None,651		}652	}653}654655/// Means for transacting assets on this chain.656pub type LocalAssetTransactor = CurrencyAdapter<657	// Use this currency:658	Balances,659	// Use this currency when it is a fungible asset matching the given location or name:660	OnlySelfCurrency,661	// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:662	LocationToAccountId,663	// Our chain's account ID type (we can't get away without mentioning it explicitly):664	AccountId,665	// We don't track any teleports.666	(),667>;668669/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,670/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can671/// biases the kind of local `Origin` it will become.672pub type XcmOriginToTransactDispatchOrigin = (673	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location674	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for675	// foreign chains who want to have a local sovereign account on this chain which they control.676	SovereignSignedViaLocation<LocationToAccountId, Origin>,677	// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when678	// recognised.679	RelayChainAsNative<RelayOrigin, Origin>,680	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when681	// recognised.682	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,683	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a684	// transaction from the Root origin.685	ParentAsSuperuser<Origin>,686	// Native signed account converter; this just converts an `AccountId32` origin into a normal687	// `Origin::Signed` origin of the same 32-byte value.688	SignedAccountId32AsNative<RelayNetwork, Origin>,689	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.690	XcmPassthrough<Origin>,691);692693parameter_types! {694	// One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.695	pub UnitWeightCost: Weight = 1_000_000;696	// 1200 UNIQUEs buy 1 second of weight.697	pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);698	pub const MaxInstructions: u32 = 100;699	pub const MaxAuthorities: u32 = 100_000;700}701702match_types! {703	pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {704		MultiLocation { parents: 1, interior: Here } |705		MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }706	};707}708709pub type Barrier = (710	TakeWeightCredit,711	AllowTopLevelPaidExecutionFrom<Everything>,712	AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,713	// ^^^ Parent & its unit plurality gets free execution714);715716pub struct UsingOnlySelfCurrencyComponents<717	WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,718	AssetId: Get<MultiLocation>,719	AccountId,720	Currency: CurrencyT<AccountId>,721	OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,722>(723	Weight,724	Currency::Balance,725	PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,726);727impl<728		WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,729		AssetId: Get<MultiLocation>,730		AccountId,731		Currency: CurrencyT<AccountId>,732		OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,733	> WeightTrader734	for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>735{736	fn new() -> Self {737		Self(0, Zero::zero(), PhantomData)738	}739740	fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {741		let amount = WeightToFee::calc(&weight);742		let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;743744		// location to this parachain through relay chain745		let option1: xcm::v1::AssetId = Concrete(MultiLocation {746			parents: 1,747			interior: X1(Parachain(ParachainInfo::parachain_id().into())),748		});749		// direct location750		let option2: xcm::v1::AssetId = Concrete(MultiLocation {751			parents: 0,752			interior: Here,753		});754755		let required = if payment.fungible.contains_key(&option1) {756			(option1, u128_amount).into()757		} else if payment.fungible.contains_key(&option2) {758			(option2, u128_amount).into()759		} else {760			(Concrete(MultiLocation::default()), u128_amount).into()761		};762763		let unused = payment764			.checked_sub(required)765			.map_err(|_| XcmError::TooExpensive)?;766		self.0 = self.0.saturating_add(weight);767		self.1 = self.1.saturating_add(amount);768		Ok(unused)769	}770771	fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {772		let weight = weight.min(self.0);773		let amount = WeightToFee::calc(&weight);774		self.0 -= weight;775		self.1 = self.1.saturating_sub(amount);776		let amount: u128 = amount.saturated_into();777		if amount > 0 {778			Some((AssetId::get(), amount).into())779		} else {780			None781		}782	}783}784impl<785		WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,786		AssetId: Get<MultiLocation>,787		AccountId,788		Currency: CurrencyT<AccountId>,789		OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,790	> Drop791	for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>792{793	fn drop(&mut self) {794		OnUnbalanced::on_unbalanced(Currency::issue(self.1));795	}796}797798pub struct XcmConfig;799impl Config for XcmConfig {800	type Call = Call;801	type XcmSender = XcmRouter;802	// How to withdraw and deposit an asset.803	type AssetTransactor = LocalAssetTransactor;804	type OriginConverter = XcmOriginToTransactDispatchOrigin;805	type IsReserve = NativeAsset;806	type IsTeleporter = (); // Teleportation is disabled807	type LocationInverter = LocationInverter<Ancestry>;808	type Barrier = Barrier;809	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;810	type Trader = UsingOnlySelfCurrencyComponents<811		IdentityFee<Balance>,812		RelayLocation,813		AccountId,814		Balances,815		(),816	>;817	type ResponseHandler = (); // Don't handle responses for now.818	type SubscriptionService = PolkadotXcm;819820	type AssetTrap = PolkadotXcm;821	type AssetClaims = PolkadotXcm;822}823824// parameter_types! {825// 	pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;826// }827828/// No local origins on this chain are allowed to dispatch XCM sends/executions.829pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);830831/// The means for routing XCM messages which are not for local execution into the right message832/// queues.833pub type XcmRouter = (834	// Two routers - use UMP to communicate with the relay chain:835	cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,836	// ..and XCMP to communicate with the sibling chains.837	XcmpQueue,838);839840impl pallet_evm_coder_substrate::Config for Runtime {}841842impl pallet_xcm::Config for Runtime {843	type Event = Event;844	type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;845	type XcmRouter = XcmRouter;846	type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;847	type XcmExecuteFilter = Everything;848	type XcmExecutor = XcmExecutor<XcmConfig>;849	type XcmTeleportFilter = Everything;850	type XcmReserveTransferFilter = Everything;851	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;852	type LocationInverter = LocationInverter<Ancestry>;853	type Origin = Origin;854	type Call = Call;855	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;856	type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;857}858859impl cumulus_pallet_xcm::Config for Runtime {860	type Event = Event;861	type XcmExecutor = XcmExecutor<XcmConfig>;862}863864impl cumulus_pallet_xcmp_queue::Config for Runtime {865	type WeightInfo = ();866	type Event = Event;867	type XcmExecutor = XcmExecutor<XcmConfig>;868	type ChannelInfo = ParachainSystem;869	type VersionWrapper = ();870	type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;871	type ControllerOrigin = EnsureRoot<AccountId>;872	type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;873}874875impl cumulus_pallet_dmp_queue::Config for Runtime {876	type Event = Event;877	type XcmExecutor = XcmExecutor<XcmConfig>;878	type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;879}880881impl pallet_aura::Config for Runtime {882	type AuthorityId = AuraId;883	type DisabledValidators = ();884	type MaxAuthorities = MaxAuthorities;885}886887parameter_types! {888	pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();889	pub const CollectionCreationPrice: Balance = 2 * UNIQUE;890}891892impl pallet_common::Config for Runtime {893	type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;894	type Event = Event;895	type Currency = Balances;896	type CollectionCreationPrice = CollectionCreationPrice;897	type TreasuryAccountId = TreasuryAccountId;898	type CollectionDispatch = CollectionDispatchT<Self>;899900	type EvmTokenAddressMapping = EvmTokenAddressMapping;901	type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;902	type ContractAddress = EvmCollectionHelpersAddress;903}904905impl pallet_structure::Config for Runtime {906	type Event = Event;907	type Call = Call;908	type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;909}910911impl pallet_fungible::Config for Runtime {912	type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;913}914impl pallet_refungible::Config for Runtime {915	type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;916}917impl pallet_nonfungible::Config for Runtime {918	type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;919}920921impl pallet_proxy_rmrk_core::Config for Runtime {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,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,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);10911092type SponsorshipHandler = (1093	UniqueSponsorshipHandler<Runtime>,1094	//pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,1095	pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,1096);10971098impl pallet_evm_transaction_payment::Config for Runtime {1099	type EvmSponsorshipHandler = EvmSponsorshipHandler;1100	type Currency = Balances;1101}11021103impl pallet_charge_transaction::Config for Runtime {1104	type SponsorshipHandler = SponsorshipHandler;1105}11061107// impl pallet_contract_helpers::Config for Runtime {1108//	 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1109// }11101111parameter_types! {1112	// 0x842899ECF380553E8a4de75bF534cdf6fBF640491113	pub const HelpersContractAddress: H160 = H160([1114		0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,1115	]);11161117	// 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f1118	pub const EvmCollectionHelpersAddress: H160 = H160([1119		0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,1120	]);1121}11221123impl pallet_evm_contract_helpers::Config for Runtime {1124	type ContractAddress = HelpersContractAddress;1125	type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1126}11271128construct_runtime!(1129	pub enum Runtime where1130		Block = Block,1131		NodeBlock = opaque::Block,1132		UncheckedExtrinsic = UncheckedExtrinsic1133	{1134		ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,1135		ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,11361137		Aura: pallet_aura::{Pallet, Config<T>} = 22,1138		AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,11391140		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,1141		RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,1142		Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,1143		TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,1144		Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,1145		Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,1146		System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,1147		Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,1148		// Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,1149		// Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,11501151		// XCM helpers.1152		XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,1153		PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,1154		CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,1155		DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,11561157		// Unique Pallets1158		Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,1159		Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,1160		Scheduler: pallet_unq_scheduler::{Pallet, Call, Storage, Event<T>} = 62,1161		// free = 631162		Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,1163		// ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,1164		Common: pallet_common::{Pallet, Storage, Event<T>} = 66,1165		Fungible: pallet_fungible::{Pallet, Storage} = 67,1166		Refungible: pallet_refungible::{Pallet, Storage} = 68,1167		Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,1168		Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,1169		RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,1170		RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,11711172		// Frontier1173		EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,1174		Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,11751176		EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,1177		EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,1178		EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,1179		EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,1180	}1181);11821183pub struct TransactionConverter;11841185impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {1186	fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {1187		UncheckedExtrinsic::new_unsigned(1188			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1189		)1190	}1191}11921193impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {1194	fn convert_transaction(1195		&self,1196		transaction: pallet_ethereum::Transaction,1197	) -> opaque::UncheckedExtrinsic {1198		let extrinsic = UncheckedExtrinsic::new_unsigned(1199			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1200		);1201		let encoded = extrinsic.encode();1202		opaque::UncheckedExtrinsic::decode(&mut &encoded[..])1203			.expect("Encoded extrinsic is always valid")1204	}1205}12061207/// The address format for describing accounts.1208pub type Address = sp_runtime::MultiAddress<AccountId, ()>;1209/// Block header type as expected by this runtime.1210pub type Header = generic::Header<BlockNumber, BlakeTwo256>;1211/// Block type as expected by this runtime.1212pub type Block = generic::Block<Header, UncheckedExtrinsic>;1213/// A Block signed with a Justification1214pub type SignedBlock = generic::SignedBlock<Block>;1215/// BlockId type as expected by this runtime.1216pub type BlockId = generic::BlockId<Block>;1217/// The SignedExtension to the basic transaction logic.1218pub type SignedExtra = (1219	frame_system::CheckSpecVersion<Runtime>,1220	// system::CheckTxVersion<Runtime>,1221	frame_system::CheckGenesis<Runtime>,1222	frame_system::CheckEra<Runtime>,1223	frame_system::CheckNonce<Runtime>,1224	frame_system::CheckWeight<Runtime>,1225	ChargeTransactionPayment,1226	//pallet_contract_helpers::ContractHelpersExtension<Runtime>,1227	pallet_ethereum::FakeTransactionFinalizer<Runtime>,1228);1229pub 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);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/opal/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;93// use scale_info::TypeInfo;94use codec::{Encode, Decode};95use fp_rpc::TransactionStatus;96use sp_runtime::{97	traits::{98		Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,99		Saturating, CheckedConversion,100	},101	generic::Era,102	transaction_validity::TransactionValidityError,103	DispatchErrorWithPostInfo, SaturatedConversion,104};105106// pub use pallet_timestamp::Call as TimestampCall;107pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;108109// Polkadot imports110use pallet_xcm::XcmPassthrough;111use polkadot_parachain::primitives::Sibling;112use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};113use xcm_builder::{114	AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,115	EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,116	RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,117	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,118	ParentIsPreset,119};120use xcm_executor::{Config, XcmExecutor, Assets};121use sp_std::{cmp::Ordering, marker::PhantomData};122123use xcm::latest::{124	//	Xcm,125	AssetId::{Concrete},126	Fungibility::Fungible as XcmFungible,127	MultiAsset,128	Error as XcmError,129};130use xcm_executor::traits::{MatchesFungible, WeightTrader};131//use xcm_executor::traits::MatchesFungible;132133use unique_runtime_common::{134	impl_common_runtime_apis,135	types::*,136	constants::*,137	dispatch::{CollectionDispatchT, CollectionDispatch},138	sponsoring::UniqueSponsorshipHandler,139	eth_sponsoring::UniqueEthSponsorshipHandler,140	weights::CommonWeights,141};142143pub const RUNTIME_NAME: &str = "opal";144pub const TOKEN_SYMBOL: &str = "OPL";145146type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;147148impl RuntimeInstance for Runtime {149	type CrossAccountId = self::CrossAccountId;150	type TransactionConverter = self::TransactionConverter;151152	fn get_transaction_converter() -> TransactionConverter {153		TransactionConverter154	}155}156157/// The type for looking up accounts. We don't expect more than 4 billion of them, but you158/// never know...159pub type AccountIndex = u32;160161/// Balance of an account.162pub type Balance = u128;163164/// Index of a transaction in the chain.165pub type Index = u32;166167/// A hash of some data used by the chain.168pub type Hash = sp_core::H256;169170/// Digest item type.171pub type DigestItem = generic::DigestItem;172173/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know174/// the specifics of the runtime. They can then be made to be agnostic over specific formats175/// of data like extrinsics, allowing for them to continue syncing the network through upgrades176/// to even the core data structures.177pub mod opaque {178	use sp_std::prelude::*;179	use sp_runtime::impl_opaque_keys;180	use super::Aura;181182	pub use unique_runtime_common::types::*;183184	impl_opaque_keys! {185		pub struct SessionKeys {186			pub aura: Aura,187		}188	}189}190191/// This runtime version.192pub const VERSION: RuntimeVersion = RuntimeVersion {193	spec_name: create_runtime_str!(RUNTIME_NAME),194	impl_name: create_runtime_str!(RUNTIME_NAME),195	authoring_version: 1,196	spec_version: 922000,197	impl_version: 0,198	apis: RUNTIME_API_VERSIONS,199	transaction_version: 1,200	state_version: 0,201};202203#[derive(codec::Encode, codec::Decode)]204pub enum XCMPMessage<XAccountId, XBalance> {205	/// Transfer tokens to the given account from the Parachain account.206	TransferToken(XAccountId, XBalance),207}208209/// The version information used to identify this runtime when compiled natively.210#[cfg(feature = "std")]211pub fn native_version() -> NativeVersion {212	NativeVersion {213		runtime_version: VERSION,214		can_author_with: Default::default(),215	}216}217218type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;219220pub struct DealWithFees;221impl OnUnbalanced<NegativeImbalance> for DealWithFees {222	fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {223		if let Some(fees) = fees_then_tips.next() {224			// for fees, 100% to treasury225			let mut split = fees.ration(100, 0);226			if let Some(tips) = fees_then_tips.next() {227				// for tips, if any, 100% to treasury228				tips.ration_merge_into(100, 0, &mut split);229			}230			Treasury::on_unbalanced(split.0);231			// Author::on_unbalanced(split.1);232		}233	}234}235236parameter_types! {237	pub const BlockHashCount: BlockNumber = 2400;238	pub RuntimeBlockLength: BlockLength =239		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);240	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);241	pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;242	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()243		.base_block(BlockExecutionWeight::get())244		.for_class(DispatchClass::all(), |weights| {245			weights.base_extrinsic = ExtrinsicBaseWeight::get();246		})247		.for_class(DispatchClass::Normal, |weights| {248			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);249		})250		.for_class(DispatchClass::Operational, |weights| {251			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);252			// Operational transactions have some extra reserved space, so that they253			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.254			weights.reserved = Some(255				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT256			);257		})258		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)259		.build_or_panic();260	pub const Version: RuntimeVersion = VERSION;261	pub const SS58Prefix: u8 = 42;262}263264parameter_types! {265	pub const ChainId: u64 = 8882;266}267268pub struct FixedFee;269impl FeeCalculator for FixedFee {270	fn min_gas_price() -> (U256, u64) {271		(MIN_GAS_PRICE.into(), 0)272	}273}274275// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case276// (contract, which only writes a lot of data),277// approximating on top of our real store write weight278parameter_types! {279	pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;280	pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;281	pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();282}283284/// Limiting EVM execution to 50% of block for substrate users and management tasks285/// EVM transaction consumes more weight than substrate's, so we can't rely on them being286/// scheduled fairly287const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);288parameter_types! {289	pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());290}291292pub enum FixedGasWeightMapping {}293impl GasWeightMapping for FixedGasWeightMapping {294	fn gas_to_weight(gas: u64) -> Weight {295		gas.saturating_mul(WeightPerGas::get())296	}297	fn weight_to_gas(weight: Weight) -> u64 {298		weight / WeightPerGas::get()299	}300}301302impl pallet_evm::account::Config for Runtime {303	type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;304	type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;305	type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;306}307308impl pallet_evm::Config for Runtime {309	type BlockGasLimit = BlockGasLimit;310	type FeeCalculator = FixedFee;311	type GasWeightMapping = FixedGasWeightMapping;312	type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;313	type CallOrigin = EnsureAddressTruncated<Self>;314	type WithdrawOrigin = EnsureAddressTruncated<Self>;315	type AddressMapping = HashedAddressMapping<Self::Hashing>;316	type PrecompilesType = ();317	type PrecompilesValue = ();318	type Currency = Balances;319	type Event = Event;320	type OnMethodCall = (321		pallet_evm_migration::OnMethodCall<Self>,322		pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,323		CollectionDispatchT<Self>,324		pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,325	);326	type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;327	type ChainId = ChainId;328	type Runner = pallet_evm::runner::stack::Runner<Self>;329	type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;330	type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;331	type FindAuthor = EthereumFindAuthor<Aura>;332}333334impl pallet_evm_migration::Config for Runtime {335	type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;336}337338pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);339impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {340	fn find_author<'a, I>(digests: I) -> Option<H160>341	where342		I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,343	{344		if let Some(author_index) = F::find_author(digests) {345			let authority_id = Aura::authorities()[author_index as usize].clone();346			return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));347		}348		None349	}350}351352impl pallet_ethereum::Config for Runtime {353	type Event = Event;354	type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;355}356357impl pallet_randomness_collective_flip::Config for Runtime {}358359impl frame_system::Config for Runtime {360	/// The data to be stored in an account.361	type AccountData = pallet_balances::AccountData<Balance>;362	/// The identifier used to distinguish between accounts.363	type AccountId = AccountId;364	/// The basic call filter to use in dispatchable.365	type BaseCallFilter = Everything;366	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).367	type BlockHashCount = BlockHashCount;368	/// The maximum length of a block (in bytes).369	type BlockLength = RuntimeBlockLength;370	/// The index type for blocks.371	type BlockNumber = BlockNumber;372	/// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.373	type BlockWeights = RuntimeBlockWeights;374	/// The aggregated dispatch type that is available for extrinsics.375	type Call = Call;376	/// The weight of database operations that the runtime can invoke.377	type DbWeight = RocksDbWeight;378	/// The ubiquitous event type.379	type Event = Event;380	/// The type for hashing blocks and tries.381	type Hash = Hash;382	/// The hashing algorithm used.383	type Hashing = BlakeTwo256;384	/// The header type.385	type Header = generic::Header<BlockNumber, BlakeTwo256>;386	/// The index type for storing how many extrinsics an account has signed.387	type Index = Index;388	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.389	type Lookup = AccountIdLookup<AccountId, ()>;390	/// What to do if an account is fully reaped from the system.391	type OnKilledAccount = ();392	/// What to do if a new account is created.393	type OnNewAccount = ();394	type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;395	/// The ubiquitous origin type.396	type Origin = Origin;397	/// This type is being generated by `construct_runtime!`.398	type PalletInfo = PalletInfo;399	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.400	type SS58Prefix = SS58Prefix;401	/// Weight information for the extrinsics of this pallet.402	type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;403	/// Version of the runtime.404	type Version = Version;405	type MaxConsumers = ConstU32<16>;406}407408parameter_types! {409	pub const MinimumPeriod: u64 = SLOT_DURATION / 2;410}411412impl pallet_timestamp::Config for Runtime {413	/// A timestamp: milliseconds since the unix epoch.414	type Moment = u64;415	type OnTimestampSet = ();416	type MinimumPeriod = MinimumPeriod;417	type WeightInfo = ();418}419420parameter_types! {421	// pub const ExistentialDeposit: u128 = 500;422	pub const ExistentialDeposit: u128 = 0;423	pub const MaxLocks: u32 = 50;424	pub const MaxReserves: u32 = 50;425}426427impl pallet_balances::Config for Runtime {428	type MaxLocks = MaxLocks;429	type MaxReserves = MaxReserves;430	type ReserveIdentifier = [u8; 16];431	/// The type for recording an account's balance.432	type Balance = Balance;433	/// The ubiquitous event type.434	type Event = Event;435	type DustRemoval = Treasury;436	type ExistentialDeposit = ExistentialDeposit;437	type AccountStore = System;438	type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;439}440441pub const fn deposit(items: u32, bytes: u32) -> Balance {442	items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE443}444445/*446parameter_types! {447	pub TombstoneDeposit: Balance = deposit(448		1,449		sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,450	);451	pub DepositPerContract: Balance = TombstoneDeposit::get();452	pub const DepositPerStorageByte: Balance = deposit(0, 1);453	pub const DepositPerStorageItem: Balance = deposit(1, 0);454	pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);455	pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;456	pub const SignedClaimHandicap: u32 = 2;457	pub const MaxDepth: u32 = 32;458	pub const MaxValueSize: u32 = 16 * 1024;459	pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb460	// The lazy deletion runs inside on_initialize.461	pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *462		RuntimeBlockWeights::get().max_block;463	// The weight needed for decoding the queue should be less or equal than a fifth464	// of the overall weight dedicated to the lazy deletion.465	pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (466			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -467			<Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)468		)) / 5) as u32;469	pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();470}471472impl pallet_contracts::Config for Runtime {473	type Time = Timestamp;474	type Randomness = RandomnessCollectiveFlip;475	type Currency = Balances;476	type Event = Event;477	type RentPayment = ();478	type SignedClaimHandicap = SignedClaimHandicap;479	type TombstoneDeposit = TombstoneDeposit;480	type DepositPerContract = DepositPerContract;481	type DepositPerStorageByte = DepositPerStorageByte;482	type DepositPerStorageItem = DepositPerStorageItem;483	type RentFraction = RentFraction;484	type SurchargeReward = SurchargeReward;485	type WeightPrice = pallet_transaction_payment::Pallet<Self>;486	type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;487	type ChainExtension = NFTExtension;488	type DeletionQueueDepth = DeletionQueueDepth;489	type DeletionWeightLimit = DeletionWeightLimit;490	type Schedule = Schedule;491	type CallStack = [pallet_contracts::Frame<Self>; 31];492}493*/494495parameter_types! {496	/// This value increases the priority of `Operational` transactions by adding497	/// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.498	pub const OperationalFeeMultiplier: u8 = 5;499}500501/// Linear implementor of `WeightToFeePolynomial`502pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);503504impl<T> WeightToFeePolynomial for LinearFee<T>505where506	T: BaseArithmetic + From<u32> + Copy + Unsigned,507{508	type Balance = T;509510	fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {511		smallvec!(WeightToFeeCoefficient {512			// Targeting 0.1 Unique per NFT transfer513			coeff_integer: WEIGHT_TO_FEE_COEFF.into(),514			coeff_frac: Perbill::zero(),515			negative: false,516			degree: 1,517		})518	}519}520521impl pallet_transaction_payment::Config for Runtime {522	type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;523	type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;524	type OperationalFeeMultiplier = OperationalFeeMultiplier;525	type WeightToFee = LinearFee<Balance>;526	type FeeMultiplierUpdate = ();527}528529parameter_types! {530	pub const ProposalBond: Permill = Permill::from_percent(5);531	pub const ProposalBondMinimum: Balance = 1 * UNIQUE;532	pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;533	pub const SpendPeriod: BlockNumber = 5 * MINUTES;534	pub const Burn: Permill = Permill::from_percent(0);535	pub const TipCountdown: BlockNumber = 1 * DAYS;536	pub const TipFindersFee: Percent = Percent::from_percent(20);537	pub const TipReportDepositBase: Balance = 1 * UNIQUE;538	pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;539	pub const BountyDepositBase: Balance = 1 * UNIQUE;540	pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;541	pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");542	pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;543	pub const MaximumReasonLength: u32 = 16384;544	pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);545	pub const BountyValueMinimum: Balance = 5 * UNIQUE;546	pub const MaxApprovals: u32 = 100;547}548549impl pallet_treasury::Config for Runtime {550	type PalletId = TreasuryModuleId;551	type Currency = Balances;552	type ApproveOrigin = EnsureRoot<AccountId>;553	type RejectOrigin = EnsureRoot<AccountId>;554	type Event = Event;555	type OnSlash = ();556	type ProposalBond = ProposalBond;557	type ProposalBondMinimum = ProposalBondMinimum;558	type ProposalBondMaximum = ProposalBondMaximum;559	type SpendPeriod = SpendPeriod;560	type Burn = Burn;561	type BurnDestination = ();562	type SpendFunds = ();563	type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;564	type MaxApprovals = MaxApprovals;565}566567impl pallet_sudo::Config for Runtime {568	type Event = Event;569	type Call = Call;570}571572pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);573574impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider575	for RelayChainBlockNumberProvider<T>576{577	type BlockNumber = BlockNumber;578579	fn current_block_number() -> Self::BlockNumber {580		cumulus_pallet_parachain_system::Pallet::<T>::validation_data()581			.map(|d| d.relay_parent_number)582			.unwrap_or_default()583	}584}585586parameter_types! {587	pub const MinVestedTransfer: Balance = 10 * UNIQUE;588	pub const MaxVestingSchedules: u32 = 28;589}590591impl orml_vesting::Config for Runtime {592	type Event = Event;593	type Currency = pallet_balances::Pallet<Runtime>;594	type MinVestedTransfer = MinVestedTransfer;595	type VestedTransferOrigin = EnsureSigned<AccountId>;596	type WeightInfo = ();597	type MaxVestingSchedules = MaxVestingSchedules;598	type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;599}600601parameter_types! {602	pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;603	pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;604}605606impl cumulus_pallet_parachain_system::Config for Runtime {607	type Event = Event;608	type SelfParaId = parachain_info::Pallet<Self>;609	type OnSystemEvent = ();610	// type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<611	// 	MaxDownwardMessageWeight,612	// 	XcmExecutor<XcmConfig>,613	// 	Call,614	// >;615	type OutboundXcmpMessageSource = XcmpQueue;616	type DmpMessageHandler = DmpQueue;617	type ReservedDmpWeight = ReservedDmpWeight;618	type ReservedXcmpWeight = ReservedXcmpWeight;619	type XcmpMessageHandler = XcmpQueue;620}621622impl parachain_info::Config for Runtime {}623624impl cumulus_pallet_aura_ext::Config for Runtime {}625626parameter_types! {627	pub const RelayLocation: MultiLocation = MultiLocation::parent();628	pub const RelayNetwork: NetworkId = NetworkId::Polkadot;629	pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();630	pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();631}632633/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used634/// when determining ownership of accounts for asset transacting and when attempting to use XCM635/// `Transact` in order to determine the dispatch Origin.636pub type LocationToAccountId = (637	// The parent (Relay-chain) origin converts to the default `AccountId`.638	ParentIsPreset<AccountId>,639	// Sibling parachain origins convert to AccountId via the `ParaId::into`.640	SiblingParachainConvertsVia<Sibling, AccountId>,641	// Straight up local `AccountId32` origins just alias directly to `AccountId`.642	AccountId32Aliases<RelayNetwork, AccountId>,643);644645pub struct OnlySelfCurrency;646impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {647	fn matches_fungible(a: &MultiAsset) -> Option<B> {648		match (&a.id, &a.fun) {649			(Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),650			_ => None,651		}652	}653}654655/// Means for transacting assets on this chain.656pub type LocalAssetTransactor = CurrencyAdapter<657	// Use this currency:658	Balances,659	// Use this currency when it is a fungible asset matching the given location or name:660	OnlySelfCurrency,661	// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:662	LocationToAccountId,663	// Our chain's account ID type (we can't get away without mentioning it explicitly):664	AccountId,665	// We don't track any teleports.666	(),667>;668669/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,670/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can671/// biases the kind of local `Origin` it will become.672pub type XcmOriginToTransactDispatchOrigin = (673	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location674	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for675	// foreign chains who want to have a local sovereign account on this chain which they control.676	SovereignSignedViaLocation<LocationToAccountId, Origin>,677	// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when678	// recognised.679	RelayChainAsNative<RelayOrigin, Origin>,680	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when681	// recognised.682	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,683	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a684	// transaction from the Root origin.685	ParentAsSuperuser<Origin>,686	// Native signed account converter; this just converts an `AccountId32` origin into a normal687	// `Origin::Signed` origin of the same 32-byte value.688	SignedAccountId32AsNative<RelayNetwork, Origin>,689	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.690	XcmPassthrough<Origin>,691);692693parameter_types! {694	// One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.695	pub UnitWeightCost: Weight = 1_000_000;696	// 1200 UNIQUEs buy 1 second of weight.697	pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);698	pub const MaxInstructions: u32 = 100;699	pub const MaxAuthorities: u32 = 100_000;700}701702match_types! {703	pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {704		MultiLocation { parents: 1, interior: Here } |705		MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }706	};707}708709pub type Barrier = (710	TakeWeightCredit,711	AllowTopLevelPaidExecutionFrom<Everything>,712	AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,713	// ^^^ Parent & its unit plurality gets free execution714);715716pub struct UsingOnlySelfCurrencyComponents<717	WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,718	AssetId: Get<MultiLocation>,719	AccountId,720	Currency: CurrencyT<AccountId>,721	OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,722>(723	Weight,724	Currency::Balance,725	PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,726);727impl<728		WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,729		AssetId: Get<MultiLocation>,730		AccountId,731		Currency: CurrencyT<AccountId>,732		OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,733	> WeightTrader734	for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>735{736	fn new() -> Self {737		Self(0, Zero::zero(), PhantomData)738	}739740	fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {741		let amount = WeightToFee::calc(&weight);742		let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;743744		// location to this parachain through relay chain745		let option1: xcm::v1::AssetId = Concrete(MultiLocation {746			parents: 1,747			interior: X1(Parachain(ParachainInfo::parachain_id().into())),748		});749		// direct location750		let option2: xcm::v1::AssetId = Concrete(MultiLocation {751			parents: 0,752			interior: Here,753		});754755		let required = if payment.fungible.contains_key(&option1) {756			(option1, u128_amount).into()757		} else if payment.fungible.contains_key(&option2) {758			(option2, u128_amount).into()759		} else {760			(Concrete(MultiLocation::default()), u128_amount).into()761		};762763		let unused = payment764			.checked_sub(required)765			.map_err(|_| XcmError::TooExpensive)?;766		self.0 = self.0.saturating_add(weight);767		self.1 = self.1.saturating_add(amount);768		Ok(unused)769	}770771	fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {772		let weight = weight.min(self.0);773		let amount = WeightToFee::calc(&weight);774		self.0 -= weight;775		self.1 = self.1.saturating_sub(amount);776		let amount: u128 = amount.saturated_into();777		if amount > 0 {778			Some((AssetId::get(), amount).into())779		} else {780			None781		}782	}783}784impl<785		WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,786		AssetId: Get<MultiLocation>,787		AccountId,788		Currency: CurrencyT<AccountId>,789		OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,790	> Drop791	for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>792{793	fn drop(&mut self) {794		OnUnbalanced::on_unbalanced(Currency::issue(self.1));795	}796}797798pub struct XcmConfig;799impl Config for XcmConfig {800	type Call = Call;801	type XcmSender = XcmRouter;802	// How to withdraw and deposit an asset.803	type AssetTransactor = LocalAssetTransactor;804	type OriginConverter = XcmOriginToTransactDispatchOrigin;805	type IsReserve = NativeAsset;806	type IsTeleporter = (); // Teleportation is disabled807	type LocationInverter = LocationInverter<Ancestry>;808	type Barrier = Barrier;809	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;810	type Trader = UsingOnlySelfCurrencyComponents<811		IdentityFee<Balance>,812		RelayLocation,813		AccountId,814		Balances,815		(),816	>;817	type ResponseHandler = (); // Don't handle responses for now.818	type SubscriptionService = PolkadotXcm;819820	type AssetTrap = PolkadotXcm;821	type AssetClaims = PolkadotXcm;822}823824// parameter_types! {825// 	pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;826// }827828/// No local origins on this chain are allowed to dispatch XCM sends/executions.829pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);830831/// The means for routing XCM messages which are not for local execution into the right message832/// queues.833pub type XcmRouter = (834	// Two routers - use UMP to communicate with the relay chain:835	cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,836	// ..and XCMP to communicate with the sibling chains.837	XcmpQueue,838);839840impl pallet_evm_coder_substrate::Config for Runtime {}841842impl pallet_xcm::Config for Runtime {843	type Event = Event;844	type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;845	type XcmRouter = XcmRouter;846	type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;847	type XcmExecuteFilter = Everything;848	type XcmExecutor = XcmExecutor<XcmConfig>;849	type XcmTeleportFilter = Everything;850	type XcmReserveTransferFilter = Everything;851	type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;852	type LocationInverter = LocationInverter<Ancestry>;853	type Origin = Origin;854	type Call = Call;855	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;856	type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;857}858859impl cumulus_pallet_xcm::Config for Runtime {860	type Event = Event;861	type XcmExecutor = XcmExecutor<XcmConfig>;862}863864impl cumulus_pallet_xcmp_queue::Config for Runtime {865	type WeightInfo = ();866	type Event = Event;867	type XcmExecutor = XcmExecutor<XcmConfig>;868	type ChannelInfo = ParachainSystem;869	type VersionWrapper = ();870	type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;871	type ControllerOrigin = EnsureRoot<AccountId>;872	type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;873}874875impl cumulus_pallet_dmp_queue::Config for Runtime {876	type Event = Event;877	type XcmExecutor = XcmExecutor<XcmConfig>;878	type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;879}880881impl pallet_aura::Config for Runtime {882	type AuthorityId = AuraId;883	type DisabledValidators = ();884	type MaxAuthorities = MaxAuthorities;885}886887parameter_types! {888	pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();889	pub const CollectionCreationPrice: Balance = 2 * UNIQUE;890}891892impl pallet_common::Config for Runtime {893	type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;894	type Event = Event;895	type Currency = Balances;896	type CollectionCreationPrice = CollectionCreationPrice;897	type TreasuryAccountId = TreasuryAccountId;898	type CollectionDispatch = CollectionDispatchT<Self>;899900	type EvmTokenAddressMapping = EvmTokenAddressMapping;901	type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;902	type ContractAddress = EvmCollectionHelpersAddress;903}904905impl pallet_structure::Config for Runtime {906	type Event = Event;907	type Call = Call;908	type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;909}910911impl pallet_fungible::Config for Runtime {912	type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;913}914impl pallet_refungible::Config for Runtime {915	type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;916}917impl pallet_nonfungible::Config for Runtime {918	type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;919}920921impl pallet_proxy_rmrk_core::Config for Runtime {922	type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;923	type Event = Event;924}925926impl pallet_proxy_rmrk_equip::Config for Runtime {927	type Event = Event;928}929930impl pallet_unique::Config for Runtime {931	type Event = Event;932	type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;933	type CommonWeightInfo = CommonWeights<Self>;934}935936parameter_types! {937	pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied938}939940/// Used for the pallet inflation941impl pallet_inflation::Config for Runtime {942	type Currency = Balances;943	type TreasuryAccountId = TreasuryAccountId;944	type InflationBlockInterval = InflationBlockInterval;945	type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;946}947948parameter_types! {949	pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *950		RuntimeBlockWeights::get().max_block;951	pub const MaxScheduledPerBlock: u32 = 50;952}953954type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;955use frame_support::traits::NamedReservableCurrency;956957fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {958	(959		frame_system::CheckSpecVersion::<Runtime>::new(),960		frame_system::CheckGenesis::<Runtime>::new(),961		frame_system::CheckEra::<Runtime>::from(Era::Immortal),962		frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(963			from,964		)),965		frame_system::CheckWeight::<Runtime>::new(),966		// sponsoring transaction logic967		// pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),968	)969}970971pub struct SchedulerPaymentExecutor;972impl<T: frame_system::Config + pallet_unq_scheduler::Config, SelfContainedSignedInfo>973	DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor974where975	<T as frame_system::Config>::Call: Member976		+ Dispatchable<Origin = Origin, Info = DispatchInfo>977		+ SelfContainedCall<SignedInfo = SelfContainedSignedInfo>978		+ GetDispatchInfo979		+ From<frame_system::Call<Runtime>>,980	SelfContainedSignedInfo: Send + Sync + 'static,981	Call: From<<T as frame_system::Config>::Call>982		+ From<<T as pallet_unq_scheduler::Config>::Call>983		+ SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,984	sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,985{986	fn dispatch_call(987		signer: <T as frame_system::Config>::AccountId,988		call: <T as pallet_unq_scheduler::Config>::Call,989	) -> Result<990		Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,991		TransactionValidityError,992	> {993		let dispatch_info = call.get_dispatch_info();994		let extrinsic = fp_self_contained::CheckedExtrinsic::<995			AccountId,996			Call,997			SignedExtraScheduler,998			SelfContainedSignedInfo,999		> {1000			signed:1001				CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(1002					signer.clone().into(),1003					get_signed_extras(signer.into()),1004				),1005			function: call.into(),1006		};10071008		extrinsic.apply::<Runtime>(&dispatch_info, 0)1009	}10101011	fn reserve_balance(1012		id: [u8; 16],1013		sponsor: <T as frame_system::Config>::AccountId,1014		call: <T as pallet_unq_scheduler::Config>::Call,1015		count: u32,1016	) -> Result<(), DispatchError> {1017		let dispatch_info = call.get_dispatch_info();1018		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)1019			.saturating_mul(count.into());10201021		<Balances as NamedReservableCurrency<AccountId>>::reserve_named(1022			&id,1023			&(sponsor.into()),1024			weight,1025		)1026	}10271028	fn pay_for_call(1029		id: [u8; 16],1030		sponsor: <T as frame_system::Config>::AccountId,1031		call: <T as pallet_unq_scheduler::Config>::Call,1032	) -> Result<u128, DispatchError> {1033		let dispatch_info = call.get_dispatch_info();1034		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);1035		Ok(1036			<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1037				&id,1038				&(sponsor.into()),1039				weight,1040			),1041		)1042	}10431044	fn cancel_reserve(1045		id: [u8; 16],1046		sponsor: <T as frame_system::Config>::AccountId,1047	) -> Result<u128, DispatchError> {1048		Ok(1049			<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(1050				&id,1051				&(sponsor.into()),1052				u128::MAX,1053			),1054		)1055	}1056}10571058parameter_types! {1059	pub const NoPreimagePostponement: Option<u32> = Some(10);1060	pub const Preimage: Option<u32> = Some(10);1061}10621063/// Used the compare the privilege of an origin inside the scheduler.1064pub struct OriginPrivilegeCmp;10651066impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {1067	fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {1068		Some(Ordering::Equal)1069	}1070}10711072impl pallet_unq_scheduler::Config for Runtime {1073	type Event = Event;1074	type Origin = Origin;1075	type Currency = Balances;1076	type PalletsOrigin = OriginCaller;1077	type Call = Call;1078	type MaximumWeight = MaximumSchedulerWeight;1079	type ScheduleOrigin = EnsureSigned<AccountId>;1080	type MaxScheduledPerBlock = MaxScheduledPerBlock;1081	type WeightInfo = ();1082	type CallExecutor = SchedulerPaymentExecutor;1083	type OriginPrivilegeCmp = OriginPrivilegeCmp;1084	type PreimageProvider = ();1085	type NoPreimagePostponement = NoPreimagePostponement;1086}10871088type EvmSponsorshipHandler = (1089	UniqueEthSponsorshipHandler<Runtime>,1090	pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,1091);10921093type SponsorshipHandler = (1094	UniqueSponsorshipHandler<Runtime>,1095	//pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,1096	pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,1097);10981099impl pallet_evm_transaction_payment::Config for Runtime {1100	type EvmSponsorshipHandler = EvmSponsorshipHandler;1101	type Currency = Balances;1102}11031104impl pallet_charge_transaction::Config for Runtime {1105	type SponsorshipHandler = SponsorshipHandler;1106}11071108// impl pallet_contract_helpers::Config for Runtime {1109//	 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1110// }11111112parameter_types! {1113	// 0x842899ECF380553E8a4de75bF534cdf6fBF640491114	pub const HelpersContractAddress: H160 = H160([1115		0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,1116	]);11171118	// 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f1119	pub const EvmCollectionHelpersAddress: H160 = H160([1120		0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,1121	]);1122}11231124impl pallet_evm_contract_helpers::Config for Runtime {1125	type ContractAddress = HelpersContractAddress;1126	type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;1127}11281129construct_runtime!(1130	pub enum Runtime where1131		Block = Block,1132		NodeBlock = opaque::Block,1133		UncheckedExtrinsic = UncheckedExtrinsic1134	{1135		ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,1136		ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,11371138		Aura: pallet_aura::{Pallet, Config<T>} = 22,1139		AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,11401141		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,1142		RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,1143		Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,1144		TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,1145		Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,1146		Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,1147		System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,1148		Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,1149		// Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,1150		// Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,11511152		// XCM helpers.1153		XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,1154		PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,1155		CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,1156		DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,11571158		// Unique Pallets1159		Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,1160		Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,1161		Scheduler: pallet_unq_scheduler::{Pallet, Call, Storage, Event<T>} = 62,1162		// free = 631163		Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,1164		// ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,1165		Common: pallet_common::{Pallet, Storage, Event<T>} = 66,1166		Fungible: pallet_fungible::{Pallet, Storage} = 67,1167		Refungible: pallet_refungible::{Pallet, Storage} = 68,1168		Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,1169		Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,1170		RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,1171		RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,11721173		// Frontier1174		EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,1175		Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,11761177		EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,1178		EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,1179		EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,1180		EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,1181	}1182);11831184pub struct TransactionConverter;11851186impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {1187	fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {1188		UncheckedExtrinsic::new_unsigned(1189			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1190		)1191	}1192}11931194impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {1195	fn convert_transaction(1196		&self,1197		transaction: pallet_ethereum::Transaction,1198	) -> opaque::UncheckedExtrinsic {1199		let extrinsic = UncheckedExtrinsic::new_unsigned(1200			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),1201		);1202		let encoded = extrinsic.encode();1203		opaque::UncheckedExtrinsic::decode(&mut &encoded[..])1204			.expect("Encoded extrinsic is always valid")1205	}1206}12071208/// The address format for describing accounts.1209pub type Address = sp_runtime::MultiAddress<AccountId, ()>;1210/// Block header type as expected by this runtime.1211pub type Header = generic::Header<BlockNumber, BlakeTwo256>;1212/// Block type as expected by this runtime.1213pub type Block = generic::Block<Header, UncheckedExtrinsic>;1214/// A Block signed with a Justification1215pub type SignedBlock = generic::SignedBlock<Block>;1216/// BlockId type as expected by this runtime.1217pub type BlockId = generic::BlockId<Block>;1218/// The SignedExtension to the basic transaction logic.1219pub type SignedExtra = (1220	frame_system::CheckSpecVersion<Runtime>,1221	// system::CheckTxVersion<Runtime>,1222	frame_system::CheckGenesis<Runtime>,1223	frame_system::CheckEra<Runtime>,1224	frame_system::CheckNonce<Runtime>,1225	frame_system::CheckWeight<Runtime>,1226	ChargeTransactionPayment,1227	//pallet_contract_helpers::ContractHelpersExtension<Runtime>,1228	pallet_ethereum::FakeTransactionFinalizer<Runtime>,1229);1230pub type SignedExtraScheduler = (1231	frame_system::CheckSpecVersion<Runtime>,1232	frame_system::CheckGenesis<Runtime>,1233	frame_system::CheckEra<Runtime>,1234	frame_system::CheckNonce<Runtime>,1235	frame_system::CheckWeight<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/quartz/src/lib.rsdiffbeforeafterboth
--- a/runtime/quartz/src/lib.rs
+++ b/runtime/quartz/src/lib.rs
@@ -918,6 +918,7 @@
 }
 
 impl pallet_proxy_rmrk_core::Config for Runtime {
+	type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
 	type Event = Event;
 }
 
modifiedruntime/unique/src/lib.rsdiffbeforeafterboth
--- a/runtime/unique/src/lib.rs
+++ b/runtime/unique/src/lib.rs
@@ -917,6 +917,7 @@
 }
 
 impl pallet_proxy_rmrk_core::Config for Runtime {
+	type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
 	type Event = Event;
 }
 
modifiedtests/src/addCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/addCollectionAdmin.test.ts
+++ b/tests/src/addCollectionAdmin.test.ts
@@ -40,8 +40,10 @@
       expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
     });
   });
+});
 
-  it('Add admin using added collection admin.', async () => {
+describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
+  it("Not owner can't add collection admin.", async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       const collectionId = await createCollectionExpectSuccess();
       const alice = privateKeyWrapper('//Alice');
@@ -51,38 +53,43 @@
       const collection = await queryCollectionExpectSuccess(api, collectionId);
       expect(collection.owner.toString()).to.be.equal(alice.address);
 
-      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
-      await submitTransactionAsync(alice, changeAdminTx);
-
       const adminListAfterAddAdmin = await getAdminList(api, collectionId);
-      expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+      expect(adminListAfterAddAdmin).to.be.not.deep.contains(normalizeAccountId(bob.address));
 
       const changeAdminTxCharlie = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
-      await submitTransactionAsync(bob, changeAdminTxCharlie);
+      await expect(submitTransactionAsync(bob, changeAdminTxCharlie)).to.be.rejected;
+     
       const adminListAfterAddNewAdmin = await getAdminList(api, collectionId);
-      expect(adminListAfterAddNewAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
-      expect(adminListAfterAddNewAdmin).to.be.deep.contains(normalizeAccountId(charlie.address));
+      expect(adminListAfterAddNewAdmin).to.be.not.deep.contains(normalizeAccountId(bob.address));
+      expect(adminListAfterAddNewAdmin).to.be.not.deep.contains(normalizeAccountId(charlie.address));
     });
   });
-});
 
-describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
-  it("Not owner can't add collection admin.", async () => {
+  it("Admin can't add collection admin.", async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       const collectionId = await createCollectionExpectSuccess();
       const alice = privateKeyWrapper('//Alice');
-      const nonOwner = privateKeyWrapper('//Bob_stash');
+      const bob = privateKeyWrapper('//Bob');
+      const charlie = privateKeyWrapper('//CHARLIE');
+
+      const collection = await queryCollectionExpectSuccess(api, collectionId);
+      expect(collection.owner.toString()).to.be.equal(alice.address);
 
-      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(alice.address));
-      await expect(submitTransactionExpectFailAsync(nonOwner, changeAdminTx)).to.be.rejected;
+      const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      await submitTransactionAsync(alice, changeAdminTx);
 
       const adminListAfterAddAdmin = await getAdminList(api, collectionId);
-      expect(adminListAfterAddAdmin).not.to.be.deep.contains(normalizeAccountId(alice.address));
+      expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
 
-      // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
-      await createCollectionExpectSuccess();
+      const changeAdminTxCharlie = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
+      await expect(submitTransactionAsync(bob, changeAdminTxCharlie)).to.be.rejected;
+     
+      const adminListAfterAddNewAdmin = await getAdminList(api, collectionId);
+      expect(adminListAfterAddNewAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+      expect(adminListAfterAddNewAdmin).to.be.not.deep.contains(normalizeAccountId(charlie.address));
     });
   });
+
   it("Can't add collection admin of not existing collection.", async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       // tslint:disable-next-line: no-bitwise
modifiedtests/src/eth/allowlist.test.tsdiffbeforeafterboth
--- a/tests/src/eth/allowlist.test.ts
+++ b/tests/src/eth/allowlist.test.ts
@@ -18,8 +18,8 @@
 import {contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3} from './util/helpers';
 
 describe('EVM allowlist', () => {
-  itWeb3('Contract allowlist can be toggled', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Contract allowlist can be toggled', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
 
     const helpers = contractHelpers(web3, owner);
@@ -36,10 +36,10 @@
     expect(await helpers.methods.allowlistEnabled(flipper.options.address).call()).to.be.false;
   });
 
-  itWeb3('Non-allowlisted user can\'t call contract with allowlist enabled', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Non-allowlisted user can\'t call contract with allowlist enabled', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const helpers = contractHelpers(web3, owner);
 
modifiedtests/src/eth/base.test.tsdiffbeforeafterboth
--- a/tests/src/eth/base.test.ts
+++ b/tests/src/eth/base.test.ts
@@ -32,16 +32,16 @@
 import Web3 from 'web3';
 
 describe('Contract calls', () => {
-  itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({web3, api}) => {
-    const deployer = await createEthAccountWithBalance(api, web3);
+  itWeb3('Call of simple contract fee is less than 0.2 UNQ', async ({web3, api, privateKeyWrapper}) => {
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, deployer);
 
     const cost = await recordEthFee(api, deployer, () => flipper.methods.flip().send({from: deployer}));
     expect(cost < BigInt(0.2 * Number(UNIQUE))).to.be.true;
   });
 
-  itWeb3('Balance transfer fee is less than 0.2 UNQ', async ({web3, api}) => {
-    const userA = await createEthAccountWithBalance(api, web3);
+  itWeb3('Balance transfer fee is less than 0.2 UNQ', async ({web3, api, privateKeyWrapper}) => {
+    const userA = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const userB = createEthAccount(web3);
 
     const cost = await recordEthFee(api, userA, () => web3.eth.sendTransaction({from: userA, to: userB, value: '1000000', ...GAS_ARGS}));
@@ -50,7 +50,7 @@
   });
 
   itWeb3('NFT transfer is close to 0.15 UNQ', async ({web3, api, privateKeyWrapper}) => {
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
 
     const alice = privateKeyWrapper('//Alice');
modifiedtests/src/eth/collectionProperties.test.tsdiffbeforeafterboth
--- a/tests/src/eth/collectionProperties.test.ts
+++ b/tests/src/eth/collectionProperties.test.ts
@@ -7,7 +7,7 @@
 describe('EVM collection properties', () => {
   itWeb3('Can be set', async({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
 
     await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
@@ -22,7 +22,7 @@
   });
   itWeb3('Can be deleted', async({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
 
     await executeTransaction(api, alice, api.tx.unique.setCollectionProperties(collection, [{key: 'testKey', value: 'testValue'}]));
modifiedtests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/contractSponsoring.test.ts
+++ b/tests/src/eth/contractSponsoring.test.ts
@@ -44,8 +44,8 @@
 import {evmToAddress} from '@polkadot/util-crypto';
 
 describe('Sponsoring EVM contracts', () => {
-  itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
     const helpers = contractHelpers(web3, owner);
     expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
@@ -53,9 +53,9 @@
     expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
   });
 
-  itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
-    const notOwner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
     const helpers = contractHelpers(web3, owner);
     expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
@@ -66,8 +66,8 @@
   itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const flipper = await deployFlipper(web3, owner);
 
@@ -94,7 +94,7 @@
   itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should decrease (allowlisted)', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const caller = createEthAccount(web3);
 
     const flipper = await deployFlipper(web3, owner);
@@ -124,7 +124,7 @@
   itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should not decrease (non-allowlisted)', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const caller = createEthAccount(web3);
 
     const flipper = await deployFlipper(web3, owner);
@@ -152,8 +152,8 @@
   itWeb3('Sponsoring is set, an address that has UNQ can send a transaction and it works. User balance should not change', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const originalCallerBalance = await web3.eth.getBalance(caller);
 
     const flipper = await deployFlipper(web3, owner);
@@ -181,8 +181,8 @@
   itWeb3('Sponsoring is limited, with setContractRateLimit. The limitation is working if transactions are sent more often, the sender pays the commission.', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const originalCallerBalance = await web3.eth.getBalance(caller);
 
     const flipper = await deployFlipper(web3, owner);
@@ -214,30 +214,31 @@
   });
 
   // TODO: Find a way to calculate default rate limit
-  itWeb3('Default rate limit equals 7200', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Default rate limit equals 7200', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
     const helpers = contractHelpers(web3, owner);
     expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');
   });
 
-  itWeb3('Sponsoring collection from evm address via access list', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Sponsoring collection from evm address via access list', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
-    const sponsor = await createEthAccountWithBalance(api, web3);
+    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
     result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});
     let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
+    const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
     expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
     await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
 
     await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
     collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
     expect(collectionSub.sponsorship.isConfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
 
     const user = createEthAccount(web3);
     const nextTokenId = await collectionEvm.methods.nextTokenId().call();
@@ -289,23 +290,24 @@
     }
   });
 
-  itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
-    const sponsor = await createEthAccountWithBalance(api, web3);
+    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
     result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();
     let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
+    const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
     expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
     await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
     const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
     collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
     expect(collectionSub.sponsorship.isConfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
 
     const user = createEthAccount(web3);
     await collectionEvm.methods.addCollectionAdmin(user).send();
modifiedtests/src/eth/createCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createCollection.test.ts
+++ b/tests/src/eth/createCollection.test.ts
@@ -28,67 +28,68 @@
 } from './util/helpers';
 
 describe('Create collection from EVM', () => {
-  itWeb3('Create collection', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
-    const collectionHelper = evmCollectionHelpers(web3, owner);
-    const collectionName = 'CollectionEVM';
-    const description = 'Some description';
-    const tokenPrefix = 'token prefix';
+  // itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {
+  //   const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+  //   const collectionHelper = evmCollectionHelpers(web3, owner);
+  //   const collectionName = 'CollectionEVM';
+  //   const description = 'Some description';
+  //   const tokenPrefix = 'token prefix';
   
-    const collectionCountBefore = await getCreatedCollectionCount(api);
-    const result = await collectionHelper.methods
-      .createNonfungibleCollection(collectionName, description, tokenPrefix)
-      .send();
-    const collectionCountAfter = await getCreatedCollectionCount(api);
+  //   const collectionCountBefore = await getCreatedCollectionCount(api);
+  //   const result = await collectionHelper.methods
+  //     .createNonfungibleCollection(collectionName, description, tokenPrefix)
+  //     .send();
+  //   const collectionCountAfter = await getCreatedCollectionCount(api);
   
-    const {collectionId, collection} = await getCollectionAddressFromResult(api, result);
-    expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);
-    expect(collectionId).to.be.eq(collectionCountAfter);
-    expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);
-    expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);
-    expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);
-  });
+  //   const {collectionId, collection} = await getCollectionAddressFromResult(api, result);
+  //   expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);
+  //   expect(collectionId).to.be.eq(collectionCountAfter);
+  //   expect(collection.name.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(collectionName);
+  //   expect(collection.description.map(v => String.fromCharCode(v.toNumber())).join('')).to.be.eq(description);
+  //   expect(collection.tokenPrefix.toHuman()).to.be.eq(tokenPrefix);
+  // });
 
-  itWeb3('Check collection address exist', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
-    const collectionHelpers = evmCollectionHelpers(web3, owner);
+  // itWeb3('Check collection address exist', async ({api, web3, privateKeyWrapper}) => {
+  //   const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+  //   const collectionHelpers = evmCollectionHelpers(web3, owner);
   
-    const expectedCollectionId = await getCreatedCollectionCount(api) + 1;
-    const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId);
-    expect(await collectionHelpers.methods
-      .isCollectionExist(expectedCollectionAddress)
-      .call()).to.be.false;
+  //   const expectedCollectionId = await getCreatedCollectionCount(api) + 1;
+  //   const expectedCollectionAddress = collectionIdToAddress(expectedCollectionId);
+  //   expect(await collectionHelpers.methods
+  //     .isCollectionExist(expectedCollectionAddress)
+  //     .call()).to.be.false;
 
-    await collectionHelpers.methods
-      .createNonfungibleCollection('A', 'A', 'A')
-      .send();
+  //   await collectionHelpers.methods
+  //     .createNonfungibleCollection('A', 'A', 'A')
+  //     .send();
     
-    expect(await collectionHelpers.methods
-      .isCollectionExist(expectedCollectionAddress)
-      .call()).to.be.true;
-  });
+  //   expect(await collectionHelpers.methods
+  //     .isCollectionExist(expectedCollectionAddress)
+  //     .call()).to.be.true;
+  // });
   
-  itWeb3('Set sponsorship', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Set sponsorship', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
-    const sponsor = await createEthAccountWithBalance(api, web3);
+    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
     result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();
     let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
     expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
+    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
     await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
     const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
     collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
     expect(collectionSub.sponsorship.isConfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor));
+    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
   });
 
-  itWeb3('Set limits', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Set limits', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     const result = await collectionHelpers.methods.createNonfungibleCollection('Const collection', '5', '5').send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
@@ -127,8 +128,8 @@
     expect(collectionSub.limits.transfersEnabled.toHuman()).to.be.eq(limits.transfersEnabled);
   });
 
-  itWeb3('Collection address exist', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Collection address exist', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     expect(await collectionHelpers.methods
@@ -144,8 +145,8 @@
 });
 
 describe('(!negative tests!) Create collection from EVM', () => {
-  itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const helper = evmCollectionHelpers(web3, owner);
     {
       const MAX_NAME_LENGHT = 64;
@@ -190,8 +191,8 @@
       .call()).to.be.rejectedWith('NotSufficientFounds');
   });
 
-  itWeb3('(!negative test!) Check owner', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('(!negative test!) Check owner', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const notOwner = await createEthAccount(web3);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     const result = await collectionHelpers.methods.createNonfungibleCollection('A', 'A', 'A').send();
@@ -199,7 +200,7 @@
     const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress);
     const EXPECTED_ERROR = 'NoPermission';
     {
-      const sponsor = await createEthAccountWithBalance(api, web3);
+      const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
       await expect(contractEvmFromNotOwner.methods
         .setCollectionSponsor(sponsor)
         .call()).to.be.rejectedWith(EXPECTED_ERROR);
@@ -216,8 +217,8 @@
     }
   });
 
-  itWeb3('(!negative test!) Set limits', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('(!negative test!) Set limits', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     const result = await collectionHelpers.methods.createNonfungibleCollection('Schema collection', 'A', 'A').send();
     const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
modifiedtests/src/eth/crossTransfer.test.tsdiffbeforeafterboth
--- a/tests/src/eth/crossTransfer.test.ts
+++ b/tests/src/eth/crossTransfer.test.ts
@@ -48,8 +48,8 @@
     });
     const alice = privateKeyWrapper('//Alice');
     const bob = privateKeyWrapper('//Bob');
-    const bobProxy = await createEthAccountWithBalance(api, web3);
-    const aliceProxy = await createEthAccountWithBalance(api, web3);
+    const bobProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const aliceProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, alice.address);
     await transferExpectSuccess(collection, 0, alice, {Ethereum: aliceProxy} , 200, 'Fungible');
@@ -85,8 +85,8 @@
     const alice = privateKeyWrapper('//Alice');
     const bob = privateKeyWrapper('//Bob');
     const charlie = privateKeyWrapper('//Charlie');
-    const bobProxy = await createEthAccountWithBalance(api, web3);
-    const aliceProxy = await createEthAccountWithBalance(api, web3);
+    const bobProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const aliceProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
     await transferExpectSuccess(collection, tokenId, alice, {Ethereum: aliceProxy} , 1, 'NFT');
     const address = collectionIdToAddress(collection);
modifiedtests/src/eth/fungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/fungible.test.ts
+++ b/tests/src/eth/fungible.test.ts
@@ -27,7 +27,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address});
 
@@ -45,7 +45,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: caller});
 
@@ -65,7 +65,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
 
@@ -208,7 +208,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const spender = createEthAccount(web3);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
@@ -226,8 +226,8 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const spender = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
 
@@ -246,7 +246,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
modifiedtests/src/eth/helpersSmoke.test.tsdiffbeforeafterboth
--- a/tests/src/eth/helpersSmoke.test.ts
+++ b/tests/src/eth/helpersSmoke.test.ts
@@ -18,16 +18,16 @@
 import {createEthAccountWithBalance, deployFlipper, itWeb3, contractHelpers} from './util/helpers';
 
 describe('Helpers sanity check', () => {
-  itWeb3('Contract owner is recorded', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Contract owner is recorded', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const flipper = await deployFlipper(web3, owner);
 
     expect(await contractHelpers(web3, owner).methods.contractOwner(flipper.options.address).call()).to.be.equal(owner);
   });
 
-  itWeb3('Flipper is working', async ({api, web3}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Flipper is working', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, owner);
 
     expect(await flipper.methods.getValue().call()).to.be.false;
modifiedtests/src/eth/marketplace/marketplace.test.tsdiffbeforeafterboth
--- a/tests/src/eth/marketplace/marketplace.test.ts
+++ b/tests/src/eth/marketplace/marketplace.test.ts
@@ -39,7 +39,7 @@
 describe('Matcher contract usage', () => {
   itWeb3('With UNQ', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const matcherOwner = await createEthAccountWithBalance(api, web3);
+    const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
       from: matcherOwner,
       ...GAS_ARGS,
@@ -100,8 +100,8 @@
 
   itWeb3('With escrow', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const matcherOwner = await createEthAccountWithBalance(api, web3);
-    const escrow = await createEthAccountWithBalance(api, web3);
+    const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const escrow = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
       from: matcherOwner,
       ...GAS_ARGS,
@@ -171,7 +171,7 @@
 
   itWeb3('Sell tokens from substrate user via EVM contract', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const matcherOwner = await createEthAccountWithBalance(api, web3);
+    const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {
       from: matcherOwner,
       ...GAS_ARGS,
modifiedtests/src/eth/migration.test.tsdiffbeforeafterboth
--- a/tests/src/eth/migration.test.ts
+++ b/tests/src/eth/migration.test.ts
@@ -54,7 +54,7 @@
     ];
 
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.begin(ADDRESS) as any));
     await submitTransactionAsync(alice, api.tx.sudo.sudo(api.tx.evmMigration.setData(ADDRESS, DATA as any) as any));
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nonFungible.test.ts
+++ b/tests/src/eth/nonFungible.test.ts
@@ -26,7 +26,7 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
 
@@ -43,7 +43,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum:caller});
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
@@ -61,7 +61,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
 
     const address = collectionIdToAddress(collection);
@@ -73,8 +73,8 @@
 });
 
 describe('NFT: Plain calls', () => {
-  itWeb3('Can perform mint()', async ({web3, api}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const helper = evmCollectionHelpers(web3, owner);
     let result = await helper.methods.createNonfungibleCollection('Mint collection', '6', '6').send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
@@ -119,7 +119,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: caller});
     await submitTransactionAsync(alice, changeAdminTx);
     const receiver = createEthAccount(web3);
@@ -182,7 +182,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
 
@@ -341,7 +341,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const spender = createEthAccount(web3);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
@@ -359,8 +359,8 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const spender = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
 
@@ -379,7 +379,7 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
 
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
@@ -541,12 +541,12 @@
 });
 
 describe('Common metadata', () => {
-  itWeb3('Returns collection name', async ({api, web3}) => {
+  itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {
     const collection = await createCollectionExpectSuccess({
       name: 'token name',
       mode: {type: 'NFT'},
     });
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const address = collectionIdToAddress(collection);
     const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
@@ -555,12 +555,12 @@
     expect(name).to.equal('token name');
   });
 
-  itWeb3('Returns symbol name', async ({api, web3}) => {
+  itWeb3('Returns symbol name', async ({api, web3, privateKeyWrapper}) => {
     const collection = await createCollectionExpectSuccess({
       tokenPrefix: 'TOK',
       mode: {type: 'NFT'},
     });
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const address = collectionIdToAddress(collection);
     const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
modifiedtests/src/eth/payable.test.tsdiffbeforeafterboth
--- a/tests/src/eth/payable.test.ts
+++ b/tests/src/eth/payable.test.ts
@@ -22,8 +22,8 @@
 import {getBalanceSingle, transferBalanceExpectSuccess} from '../substrate/get-balance';
 
 describe('EVM payable contracts', () => {
-  itWeb3('Evm contract can receive wei from eth account', async ({api, web3}) => {
-    const deployer = await createEthAccountWithBalance(api, web3);
+  itWeb3('Evm contract can receive wei from eth account', async ({api, web3, privateKeyWrapper}) => {
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const contract = await deployCollector(web3, deployer);
 
     await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: '10000', ...GAS_ARGS});
@@ -32,7 +32,7 @@
   });
 
   itWeb3('Evm contract can receive wei from substrate account', async ({api, web3, privateKeyWrapper}) => {
-    const deployer = await createEthAccountWithBalance(api, web3);
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const contract = await deployCollector(web3, deployer);
     const alice = privateKeyWrapper('//Alice');
 
@@ -62,7 +62,7 @@
 
   // We can't handle sending balance to backing storage of evm balance, because evmToAddress operation is irreversible
   itWeb3('Wei sent directly to backing storage of evm contract balance is unaccounted', async({api, web3, privateKeyWrapper}) => {
-    const deployer = await createEthAccountWithBalance(api, web3);
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const contract = await deployCollector(web3, deployer);
     const alice = privateKeyWrapper('//Alice');
 
@@ -75,7 +75,7 @@
     const FEE_BALANCE = 1000n * UNIQUE;
     const CONTRACT_BALANCE = 1n * UNIQUE;
 
-    const deployer = await createEthAccountWithBalance(api, web3);
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const contract = await deployCollector(web3, deployer);
     const alice = privateKeyWrapper('//Alice');
 
modifiedtests/src/eth/proxy/fungibleProxy.test.tsdiffbeforeafterboth
--- a/tests/src/eth/proxy/fungibleProxy.test.ts
+++ b/tests/src/eth/proxy/fungibleProxy.test.ts
@@ -21,10 +21,11 @@
 import {ApiPromise} from '@polkadot/api';
 import Web3 from 'web3';
 import {readFile} from 'fs/promises';
+import {IKeyringPair} from '@polkadot/types/types';
 
-async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {
+async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any, privateKeyWrapper: (account: string) => IKeyringPair) {
   // Proxy owner has no special privilegies, we don't need to reuse them
-  const owner = await createEthAccountWithBalance(api, web3);
+  const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
   const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueFungibleProxy.abi`)).toString()), undefined, {
     from: owner,
     ...GAS_ARGS,
@@ -40,12 +41,12 @@
       mode: {type: 'Fungible', decimalPoints: 0},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address});
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const totalSupply = await contract.methods.totalSupply().call();
 
     expect(totalSupply).to.equal('200');
@@ -57,12 +58,12 @@
       mode: {type: 'Fungible', decimalPoints: 0},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: caller});
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const balance = await contract.methods.balanceOf(caller).call();
 
     expect(balance).to.equal('200');
@@ -76,11 +77,11 @@
       mode: {type: 'Fungible', decimalPoints: 0},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const spender = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: contract.options.address});
 
     {
@@ -112,8 +113,8 @@
       mode: {type: 'Fungible', decimalPoints: 0},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
-    const owner = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: owner});
 
@@ -121,7 +122,7 @@
 
     const address = collectionIdToAddress(collection);
     const evmCollection = new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS});
-    const contract = await proxyWrap(api, web3, evmCollection);
+    const contract = await proxyWrap(api, web3, evmCollection, privateKeyWrapper);
 
     await evmCollection.methods.approve(contract.options.address, 100).send({from: owner});
 
@@ -167,11 +168,11 @@
       mode: {type: 'Fungible', decimalPoints: 0},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
-    const receiver = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(fungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Ethereum: contract.options.address});
 
     {
modifiedtests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth
--- a/tests/src/eth/proxy/nonFungibleProxy.test.ts
+++ b/tests/src/eth/proxy/nonFungibleProxy.test.ts
@@ -22,10 +22,11 @@
 import Web3 from 'web3';
 import {readFile} from 'fs/promises';
 import {ApiPromise} from '@polkadot/api';
+import {IKeyringPair} from '@polkadot/types/types';
 
-async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any) {
+async function proxyWrap(api: ApiPromise, web3: Web3, wrapped: any, privateKeyWrapper: (account: string) => IKeyringPair) {
   // Proxy owner has no special privilegies, we don't need to reuse them
-  const owner = await createEthAccountWithBalance(api, web3);
+  const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
   const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {
     from: owner,
     ...GAS_ARGS,
@@ -40,12 +41,12 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const totalSupply = await contract.methods.totalSupply().call();
 
     expect(totalSupply).to.equal('1');
@@ -57,13 +58,13 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
     await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const balance = await contract.methods.balanceOf(caller).call();
 
     expect(balance).to.equal('3');
@@ -75,11 +76,11 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: caller});
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const owner = await contract.methods.ownerOf(tokenId).call();
 
     expect(owner).to.equal(caller);
@@ -87,18 +88,18 @@
 });
 
 describe('NFT (Via EVM proxy): Plain calls', () => {
-  itWeb3('Can perform mint()', async ({web3, api}) => {
-    const owner = await createEthAccountWithBalance(api, web3);
+  itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionHelper = evmCollectionHelpers(web3, owner);
     const result = await collectionHelper.methods
       .createNonfungibleCollection('A', 'A', 'A')
       .send();
     const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
     const collectionEvmOwned = evmCollection(web3, owner, collectionIdAddress);
     const collectionEvm = evmCollection(web3, caller, collectionIdAddress);
-    const contract = await proxyWrap(api, web3, collectionEvm);
+    const contract = await proxyWrap(api, web3, collectionEvm, privateKeyWrapper);
     await collectionEvmOwned.methods.addCollectionAdmin(contract.options.address).send();
 
     {
@@ -135,11 +136,11 @@
     });
     const alice = privateKeyWrapper('//Alice');
 
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});
     await submitTransactionAsync(alice, changeAdminTx);
 
@@ -197,10 +198,10 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
 
     const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});
@@ -229,11 +230,11 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const spender = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address), privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
 
     {
@@ -259,14 +260,14 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
-    const owner = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
 
     const receiver = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
     const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
-    const contract = await proxyWrap(api, web3, evmCollection);
+    const contract = await proxyWrap(api, web3, evmCollection, privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: owner});
 
     await evmCollection.methods.approve(contract.options.address, tokenId).send({from: owner});
@@ -303,11 +304,11 @@
       mode: {type: 'NFT'},
     });
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const receiver = createEthAccount(web3);
 
     const address = collectionIdToAddress(collection);
-    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}));
+    const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);
     const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: contract.options.address});
 
     {
modifiedtests/src/eth/scheduling.test.tsdiffbeforeafterboth
--- a/tests/src/eth/scheduling.test.ts
+++ b/tests/src/eth/scheduling.test.ts
@@ -17,14 +17,13 @@
 import {expect} from 'chai';
 import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';
 import {scheduleExpectSuccess, waitNewBlocks} from '../util/helpers';
-import privateKey from '../substrate/privateKey';
 
 describe('Scheduing EVM smart contracts', () => {
-  itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3}) => {
-    const deployer = await createEthAccountWithBalance(api, web3);
+  itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3, privateKeyWrapper}) => {
+    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const flipper = await deployFlipper(web3, deployer);
     const initialValue = await flipper.methods.getValue().call();
-    const alice = privateKey('//Alice');
+    const alice = privateKeyWrapper('//Alice');
     await transferBalanceToEth(api, alice, subToEth(alice.address));
 
     {
modifiedtests/src/eth/sponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/sponsoring.test.ts
+++ b/tests/src/eth/sponsoring.test.ts
@@ -21,7 +21,7 @@
   itWeb3('Fee is deducted from contract if sponsoring is enabled', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const caller = createEthAccount(web3);
     const originalCallerBalance = await web3.eth.getBalance(caller);
     expect(originalCallerBalance).to.be.equal('0');
@@ -52,8 +52,8 @@
   itWeb3('...but this doesn\'t applies to payable value', async ({api, web3, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
 
-    const owner = await createEthAccountWithBalance(api, web3);
-    const caller = await createEthAccountWithBalance(api, web3);
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const originalCallerBalance = await web3.eth.getBalance(caller);
     expect(originalCallerBalance).to.be.not.equal('0');
 
modifiedtests/src/eth/tokenProperties.test.tsdiffbeforeafterboth
--- a/tests/src/eth/tokenProperties.test.ts
+++ b/tests/src/eth/tokenProperties.test.ts
@@ -7,7 +7,7 @@
 describe('EVM token properties', () => {
   itWeb3('Can be reconfigured', async({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
       await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
@@ -25,7 +25,7 @@
   });
   itWeb3('Can be set', async({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
     const token = await createItemExpectSuccess(alice, collection, 'NFT');
 
@@ -48,7 +48,7 @@
   });
   itWeb3('Can be deleted', async({web3, api, privateKeyWrapper}) => {
     const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3);
+    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
     const token = await createItemExpectSuccess(alice, collection, 'NFT');
 
modifiedtests/src/eth/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/eth/util/helpers.ts
+++ b/tests/src/eth/util/helpers.ts
@@ -112,8 +112,8 @@
   return account.address;
 }
 
-export async function createEthAccountWithBalance(api: ApiPromise, web3: Web3) {
-  const alice = privateKey('//Alice');
+export async function createEthAccountWithBalance(api: ApiPromise, web3: Web3, privateKeyWrapper: (account: string) => IKeyringPair) {
+  const alice = privateKeyWrapper('//Alice');
   const account = createEthAccount(web3);
   await transferBalanceToEth(api, alice, account);
 
modifiedtests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -46,33 +46,6 @@
     });
   });
 
-  it('Remove collection admin by admin.', async () => {
-    await usingApi(async (api, privateKeyWrapper) => {
-      const collectionId = await createCollectionExpectSuccess();
-      const alice = privateKeyWrapper('//Alice');
-      const bob = privateKeyWrapper('//Bob');
-      const charlie = privateKeyWrapper('//Charlie');
-      const collection = await queryCollectionExpectSuccess(api, collectionId);
-      expect(collection.owner.toString()).to.be.eq(alice.address);
-      // first - add collection admin Bob
-      const addAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
-      await submitTransactionAsync(alice, addAdminTx);
-
-      const addAdminTx2 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
-      await submitTransactionAsync(alice, addAdminTx2);
-
-      const adminListAfterAddAdmin = await getAdminList(api, collectionId);
-      expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
-
-      // then remove bob from admins of collection
-      const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
-      await submitTransactionAsync(charlie, removeAdminTx);
-
-      const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
-      expect(adminListAfterRemoveAdmin).not.to.be.deep.contains(normalizeAccountId(bob.address));
-    });
-  });
-
   it('Remove admin from collection that has no admins', async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       const alice = privateKeyWrapper('//Alice');
@@ -120,7 +93,7 @@
     });
   });
 
-  it('Regular user Can\'t remove collection admin', async () => {
+  it('Regular user can\'t remove collection admin', async () => {
     await usingApi(async (api, privateKeyWrapper) => {
       const collectionId = await createCollectionExpectSuccess();
       const alice = privateKeyWrapper('//Alice');
@@ -137,4 +110,23 @@
       await createCollectionExpectSuccess();
     });
   });
+
+  it('Admin can\'t remove collection admin.', async () => {
+    await usingApi(async (api, privateKeyWrapper) => {
+      const collectionId = await createCollectionExpectSuccess();
+      const alice = privateKeyWrapper('//Alice');
+      const bob = privateKeyWrapper('//Bob');
+      const charlie = privateKeyWrapper('//Charlie');
+
+      const adminListAfterAddAdmin = await getAdminList(api, collectionId);
+      expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+
+      const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+      await expect(submitTransactionAsync(charlie, removeAdminTx)).to.be.rejected;
+
+      const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
+      expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+      expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(charlie.address));
+    });
+  });
 });
modifiedtests/src/rmrk/rmrk.test.tsdiffbeforeafterboth
--- a/tests/src/rmrk/rmrk.test.ts
+++ b/tests/src/rmrk/rmrk.test.ts
@@ -49,8 +49,8 @@
 
 describe('RMRK External Integration Test', () => {
   before(async () => {
-    await usingApi(async () => {
-      alice = privateKey('//Alice');
+    await usingApi(async (api, privateKeyWrapper) => {
+      alice = privateKeyWrapper('//Alice');
     });
   });
 
@@ -75,9 +75,9 @@
   let rmrkNftId: number;
 
   before(async () => {
-    await usingApi(async api => {
-      alice = privateKey('//Alice');
-      bob = privateKey('//Bob');
+    await usingApi(async (api, privateKeyWrapper) => {
+      alice = privateKeyWrapper('//Alice');
+      bob = privateKeyWrapper('//Bob');
 
       const collectionIds = await createRmrkCollection(api, alice);
       uniqueCollectionId = collectionIds.uniqueId;
@@ -210,9 +210,9 @@
   let nftId: number;
 
   before(async () => {
-    await usingApi(async () => {
-      alice = privateKey('//Alice');
-      bob = privateKey('//Bob');
+    await usingApi(async (api, privateKeyWrapper) => {
+      alice = privateKeyWrapper('//Alice');
+      bob = privateKeyWrapper('//Bob');
 
       collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
       nftId = await createItemExpectSuccess(alice, collectionId, 'NFT');
modifiedtests/src/rpc.load.tsdiffbeforeafterboth
--- a/tests/src/rpc.load.ts
+++ b/tests/src/rpc.load.ts
@@ -59,8 +59,7 @@
   const deployer = await findUnusedAddress(api, privateKeyWrapper);
 
   // Transfer balance to it
-  const keyring = new Keyring({type: 'sr25519'});
-  const alice = keyring.addFromUri('//Alice');
+  const alice = privateKeyWrapper('//Alice');
   const amount = BigInt(endowment) + 10n**15n;
   const tx = api.tx.balances.transfer(deployer.address, amount);
   await submitTransactionAsync(alice, tx);
modifiedtests/src/scheduler.test.tsdiffbeforeafterboth
--- a/tests/src/scheduler.test.ts
+++ b/tests/src/scheduler.test.ts
@@ -16,7 +16,6 @@
 
 import chai, {expect} from 'chai';
 import chaiAsPromised from 'chai-as-promised';
-import privateKey from './substrate/privateKey';
 import {
   default as usingApi, 
   submitTransactionAsync,
@@ -52,9 +51,9 @@
   let scheduledIdSlider: number;
 
   before(async() => {
-    await usingApi(async () => {
-      alice = privateKey('//Alice');
-      bob = privateKey('//Bob');
+    await usingApi(async (api, privateKeyWrapper) => {
+      alice = privateKeyWrapper('//Alice');
+      bob = privateKeyWrapper('//Bob');
     });
 
     scheduledIdBase = '0x' + '0'.repeat(31);