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

difftreelog

merge develop into test/playground-migration

rkv2022-09-09parents: #16ab55f #4f3f998.patch.diff
in: master

79 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -113,6 +113,20 @@
 checksum = "508b352bb5c066aac251f6daf6b36eccd03e8a88e8081cd44959ea277a3af9a8"
 
 [[package]]
+name = "app-promotion-rpc"
+version = "0.1.0"
+dependencies = [
+ "pallet-common",
+ "pallet-evm",
+ "parity-scale-codec 3.1.5",
+ "sp-api",
+ "sp-core",
+ "sp-runtime",
+ "sp-std",
+ "up-data-structs",
+]
+
+[[package]]
 name = "approx"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5127,6 +5141,7 @@
 name = "opal-runtime"
 version = "0.9.27"
 dependencies = [
+ "app-promotion-rpc",
  "cumulus-pallet-aura-ext",
  "cumulus-pallet-dmp-queue",
  "cumulus-pallet-parachain-system",
@@ -5150,6 +5165,7 @@
  "hex-literal",
  "log",
  "orml-vesting",
+ "pallet-app-promotion",
  "pallet-aura",
  "pallet-balances",
  "pallet-base-fee",
@@ -5296,6 +5312,31 @@
 ]
 
 [[package]]
+name = "pallet-app-promotion"
+version = "0.1.0"
+dependencies = [
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "pallet-balances",
+ "pallet-common",
+ "pallet-evm",
+ "pallet-evm-contract-helpers",
+ "pallet-evm-migration",
+ "pallet-randomness-collective-flip",
+ "pallet-timestamp",
+ "pallet-unique",
+ "parity-scale-codec 3.1.5",
+ "scale-info",
+ "serde",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+ "up-data-structs",
+]
+
+[[package]]
 name = "pallet-aura"
 version = "4.0.0-dev"
 source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#8eff668a42325aeb4433eace1604f4d286a6ec05"
@@ -5694,6 +5735,7 @@
 name = "pallet-evm-contract-helpers"
 version = "0.2.0"
 dependencies = [
+ "ethereum",
  "evm-coder",
  "fp-evm-mapping",
  "frame-support",
@@ -6432,7 +6474,7 @@
 
 [[package]]
 name = "pallet-unique"
-version = "0.1.3"
+version = "0.1.4"
 dependencies = [
  "ethereum",
  "evm-coder",
@@ -8332,6 +8374,7 @@
 name = "quartz-runtime"
 version = "0.9.27"
 dependencies = [
+ "app-promotion-rpc",
  "cumulus-pallet-aura-ext",
  "cumulus-pallet-dmp-queue",
  "cumulus-pallet-parachain-system",
@@ -8355,6 +8398,7 @@
  "hex-literal",
  "log",
  "orml-vesting",
+ "pallet-app-promotion",
  "pallet-aura",
  "pallet-balances",
  "pallet-base-fee",
@@ -12103,9 +12147,10 @@
 
 [[package]]
 name = "uc-rpc"
-version = "0.1.3"
+version = "0.1.4"
 dependencies = [
  "anyhow",
+ "app-promotion-rpc",
  "jsonrpsee",
  "pallet-common",
  "pallet-evm",
@@ -12184,6 +12229,7 @@
 name = "unique-node"
 version = "0.9.27"
 dependencies = [
+ "app-promotion-rpc",
  "clap",
  "cumulus-client-cli",
  "cumulus-client-collator",
@@ -12272,6 +12318,7 @@
 name = "unique-rpc"
 version = "0.1.1"
 dependencies = [
+ "app-promotion-rpc",
  "fc-db",
  "fc-mapping-sync",
  "fc-rpc",
@@ -12321,6 +12368,7 @@
 name = "unique-runtime"
 version = "0.9.27"
 dependencies = [
+ "app-promotion-rpc",
  "cumulus-pallet-aura-ext",
  "cumulus-pallet-dmp-queue",
  "cumulus-pallet-parachain-system",
@@ -12344,6 +12392,7 @@
  "hex-literal",
  "log",
  "orml-vesting",
+ "pallet-app-promotion",
  "pallet-aura",
  "pallet-balances",
  "pallet-base-fee",
modifiedMakefilediffbeforeafterboth
--- a/Makefile
+++ b/Makefile
@@ -128,5 +128,9 @@
 bench-rmrk-equip:
 	make _bench PALLET=proxy-rmrk-equip
 
+.PHONY: bench-app-promotion
+bench-app-promotion:
+	make _bench PALLET=app-promotion PALLET_DIR=app-promotion
+	
 .PHONY: bench
 bench: bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-scheduler bench-rmrk-core bench-rmrk-equip
modifiedclient/rpc/CHANGELOG.mddiffbeforeafterboth
--- a/client/rpc/CHANGELOG.md
+++ b/client/rpc/CHANGELOG.md
@@ -3,15 +3,21 @@
 All notable changes to this project will be documented in this file.
 
 <!-- bureaucrate goes here -->
+
+## [v0.1.4] 2022-09-08
+
+### Added
+-  Support RPC for `AppPromotion` pallet. 
+
 ## [v0.1.3] 2022-08-16
 
 ### Other changes
 
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
+-   build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
 
-- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
+-   build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
 
-- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
+-   build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
 
 ## [0.1.2] - 2022-08-12
 
modifiedclient/rpc/Cargo.tomldiffbeforeafterboth
--- a/client/rpc/Cargo.toml
+++ b/client/rpc/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "uc-rpc"
-version = "0.1.3"
+version = "0.1.4"
 license = "GPLv3"
 edition = "2021"
 
@@ -8,6 +8,7 @@
 pallet-common = { default-features = false, path = '../../pallets/common' }
 up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
 up-rpc = { path = "../../primitives/rpc" }
+app-promotion-rpc = { path = "../../primitives/app_promotion_rpc"}
 rmrk-rpc = { path = "../../primitives/rmrk-rpc" }
 codec = { package = "parity-scale-codec", version = "3.1.2" }
 jsonrpsee = { version = "0.14.0", features = ["server", "macros"] }
modifiedclient/rpc/src/lib.rsdiffbeforeafterboth
--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -23,6 +23,7 @@
 	proc_macros::rpc,
 };
 use anyhow::anyhow;
+use sp_runtime::traits::{AtLeast32BitUnsigned, Member};
 use up_data_structs::{
 	RpcCollection, CollectionId, CollectionStats, CollectionLimits, TokenId, Property,
 	PropertyKeyPermission, TokenData, TokenChild,
@@ -30,6 +31,7 @@
 use sp_api::{BlockId, BlockT, ProvideRuntimeApi, ApiExt};
 use sp_blockchain::HeaderBackend;
 use up_rpc::UniqueApi as UniqueRuntimeApi;
+use app_promotion_rpc::AppPromotionApi as AppPromotionRuntimeApi;
 
 // RMRK
 use rmrk_rpc::RmrkApi as RmrkRuntimeApi;
@@ -37,6 +39,7 @@
 	RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName, RmrkResourceId,
 };
 
+pub use app_promotion_unique_rpc::AppPromotionApiServer;
 pub use rmrk_unique_rpc::RmrkApiServer;
 
 #[rpc(server)]
@@ -245,6 +248,46 @@
 	) -> Result<Option<String>>;
 }
 
+mod app_promotion_unique_rpc {
+	use super::*;
+
+	#[rpc(server)]
+	#[async_trait]
+	pub trait AppPromotionApi<BlockHash, BlockNumber, CrossAccountId, AccountId> {
+		/// Returns the total amount of staked tokens.
+		#[method(name = "appPromotion_totalStaked")]
+		fn total_staked(
+			&self,
+			staker: Option<CrossAccountId>,
+			at: Option<BlockHash>,
+		) -> Result<String>;
+
+		///Returns the total amount of staked tokens per block when staked.
+		#[method(name = "appPromotion_totalStakedPerBlock")]
+		fn total_staked_per_block(
+			&self,
+			staker: CrossAccountId,
+			at: Option<BlockHash>,
+		) -> Result<Vec<(BlockNumber, String)>>;
+
+		/// Returns the total amount of tokens pending withdrawal from staking.
+		#[method(name = "appPromotion_pendingUnstake")]
+		fn pending_unstake(
+			&self,
+			staker: Option<CrossAccountId>,
+			at: Option<BlockHash>,
+		) -> Result<String>;
+
+		/// Returns the total amount of tokens pending withdrawal from staking per block.
+		#[method(name = "appPromotion_pendingUnstakePerBlock")]
+		fn pending_unstake_per_block(
+			&self,
+			staker: CrossAccountId,
+			at: Option<BlockHash>,
+		) -> Result<Vec<(BlockNumber, String)>>;
+	}
+}
+
 mod rmrk_unique_rpc {
 	use super::*;
 
@@ -367,34 +410,28 @@
 	}
 }
 
-pub struct Unique<C, P> {
-	client: Arc<C>,
-	_marker: std::marker::PhantomData<P>,
-}
+macro_rules! define_struct_for_server_api {
+	($name:ident) => {
+		pub struct $name<C, P> {
+			client: Arc<C>,
+			_marker: std::marker::PhantomData<P>,
+		}
 
-impl<C, P> Unique<C, P> {
-	pub fn new(client: Arc<C>) -> Self {
-		Self {
-			client,
-			_marker: Default::default(),
+		impl<C, P> $name<C, P> {
+			pub fn new(client: Arc<C>) -> Self {
+				Self {
+					client,
+					_marker: Default::default(),
+				}
+			}
 		}
-	}
+	};
 }
 
-pub struct Rmrk<C, P> {
-	client: Arc<C>,
-	_marker: std::marker::PhantomData<P>,
-}
+define_struct_for_server_api!(Unique);
+define_struct_for_server_api!(AppPromotion);
+define_struct_for_server_api!(Rmrk);
 
-impl<C, P> Rmrk<C, P> {
-	pub fn new(client: Arc<C>) -> Self {
-		Self {
-			client,
-			_marker: Default::default(),
-		}
-	}
-}
-
 macro_rules! pass_method {
 	(
 		$method_name:ident(
@@ -440,6 +477,12 @@
 	};
 }
 
+macro_rules! app_promotion_api {
+	() => {
+		dyn AppPromotionRuntimeApi<Block, BlockNumber, CrossAccountId, AccountId>
+	};
+}
+
 macro_rules! rmrk_api {
 	() => {
 		dyn RmrkRuntimeApi<Block, AccountId, CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme>
@@ -522,6 +565,35 @@
 	pass_method!(token_owners(collection: CollectionId, token: TokenId) -> Vec<CrossAccountId>, unique_api);
 }
 
+impl<C, Block, BlockNumber, CrossAccountId, AccountId>
+	app_promotion_unique_rpc::AppPromotionApiServer<
+		<Block as BlockT>::Hash,
+		BlockNumber,
+		CrossAccountId,
+		AccountId,
+	> for AppPromotion<C, Block>
+where
+	Block: BlockT,
+	BlockNumber: Decode + Member + AtLeast32BitUnsigned,
+	AccountId: Decode,
+	C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
+	C::Api: AppPromotionRuntimeApi<Block, BlockNumber, CrossAccountId, AccountId>,
+	CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,
+{
+	pass_method!(total_staked(staker: Option<CrossAccountId>) -> String => |v| v.to_string(), app_promotion_api);
+	pass_method!(total_staked_per_block(staker: CrossAccountId) -> Vec<(BlockNumber, String)> =>
+		|v| v
+		.into_iter()
+		.map(|(b, a)| (b, a.to_string()))
+		.collect::<Vec<_>>(), app_promotion_api);
+	pass_method!(pending_unstake(staker: Option<CrossAccountId>) -> String => |v| v.to_string(), app_promotion_api);
+	pass_method!(pending_unstake_per_block(staker: CrossAccountId) -> Vec<(BlockNumber, String)> =>
+		|v| v
+		.into_iter()
+		.map(|(b, a)| (b, a.to_string()))
+		.collect::<Vec<_>>(), app_promotion_api);
+}
+
 #[allow(deprecated)]
 impl<
 		C,
addeddoc/separate_rpc.mddiffbeforeafterboth
--- /dev/null
+++ b/doc/separate_rpc.md
@@ -0,0 +1,123 @@
+1. Create, in the `primitives` folder, a crate with a trait for RPC generation.
+    ```rust
+    sp_api::decl_runtime_apis! {
+        #[api_version(2)]
+        pub trait ModuleNameApi<CrossAccountId> 
+        where
+            CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,
+        {
+            fn method_name(user: Option<CrossAccountId>) -> Result<u128, DispatchError>;
+        }
+    }
+    ```
+
+2. client/rpc/src/lib.rs
+    * Add a trait with the required methods. Mark it with `#[rpc(server)]` and `#[async_trait]` directives.
+        ```rust
+        #[rpc(server)]
+        #[async_trait]
+        pub trait ModuleNameApi<BlockHash, CrossAccountId> {
+            #[method(name = "moduleName_methodName")]
+            fn method_name(&self, user: Option<CrossAccountId>, at: Option<BlockHash>)
+                -> Result<String>;
+        }
+        ```
+    * Don't forget to write the correct method identifier in the form `moduleName_methodName`.
+    * Add a structure for which the server API interface will be implemented.
+        ```rust
+        define_struct_for_server_api!(ModuleName);
+        ```
+    * Define a macro to be used in the implementation of the server API interface.
+        ```rust
+        macro_rules! module_api {
+            () => {
+                dyn ModuleNameRuntimeApi<BlockHash, CrossAccountId>
+            };
+        }
+        ```
+    * Implement a server API interface.
+        ```rust
+        impl<C, Block, CrossAccountId> 
+        ModuleNameApiServer<<Block as BlockT>::Hash, CrossAccountId> for ModuleName<C, Block>
+        where
+            Block: BlockT,
+            C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
+            C::Api: AppPromotionRuntimeApi<Block, BlockNumber, CrossAccountId, AccountId>,
+            CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,
+        {
+            pass_method!(method_name(user: Option<CrossAccountId>) -> String => |v| v.to_string(), app_promotion_api);
+        }
+        ```
+
+3. runtime/common/runtime_apis.rs
+    * Implement the `ModuleNameApi` interface for `Runtime`. Optionally, you can mark a feature flag to disable the functionality.
+        ```rust
+        impl MethodApi<Block, BlockNumber, CrossAccountId, AccountId> for Runtime {
+                fn method_name(user: Option<CrossAccountId>) -> Result<u128, DispatchError> {
+                    #[cfg(not(feature = "module"))]
+                    return unsupported!();
+
+                    #[cfg(feature = "module")]
+                    return Ok(0);
+                }
+            }
+        ```
+
+4. node/cli/src/service.rs
+    * Set the `MethodApi<Block, Runtime::CrossAccountId>` bound in the `start_node_impl`, `start_node`, `start_dev_node` methods.
+
+5. node/rpc/src/lib.rs
+    * Add `MethodApi<Block, Runtime::CrossAccountId>` bound to `create_full` method.
+    * Enable RPC in the `create_full` method by adding `io.merge(ModuleName::new(client.clone()).into_rpc())?;`
+
+6. Add a new crate (see point 1) into dependencies.
+    * client/rpc/Cargo.toml
+    * node/rpc/Cargo.toml
+    * runtime/opal/Cargo.toml
+    * runtime/quartz/Cargo.toml
+    * runtime/unique/Cargo.toml
+
+7. Create tests/src/interfaces/ModuleName/definitions.ts and describe the necessary methods in it.
+    ```ts
+    type RpcParam = {
+        name: string;
+        type: string;
+        isOptional?: true;
+        };
+
+        const CROSS_ACCOUNT_ID_TYPE = 'PalletEvmAccountBasicCrossAccountIdRepr';
+
+        const fun = (description: string, params: RpcParam[], type: string) => ({
+        description,
+        params: [...params, atParam],
+        type,
+        });
+
+        export default {
+            types: {},
+            rpc: {
+                methodName: fun(
+                'Documentation for method',
+                [{name: 'user', type: CROSS_ACCOUNT_ID_TYPE, isOptional: true}],
+                'u128',
+                ),
+            },
+        };
+    ```
+
+8. Describe definitions from paragraph 7 in tests/src/interfaces/definitions.ts.
+    ```ts
+    export {default as ModuleName} from './module/definitions';
+    ```
+
+9. tests/src/substrate/substrate-api.ts
+    * Set the RPC interface in the `defaultApiOptions` function, add an entry in the `rpc` parameter
+        ```ts
+        module: defs.module.rpc,
+        ```
+
+10. tests/src/util/playgrounds/unique.dev.ts
+    * Specify RPC interface in `connect` function, add entry in `rpc` parameter
+        ```ts
+        module: defs.module.rpc,
+        ```
\ No newline at end of file
modifiednode/cli/Cargo.tomldiffbeforeafterboth
--- a/node/cli/Cargo.toml
+++ b/node/cli/Cargo.toml
@@ -318,6 +318,7 @@
 pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
 
 unique-rpc = { default-features = false, path = "../rpc" }
+app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}
 rmrk-rpc = { path = "../../primitives/rmrk-rpc" }
 
 [features]
modifiednode/cli/src/service.rsdiffbeforeafterboth
--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -63,7 +63,9 @@
 use fc_rpc_core::types::FilterPool;
 use fc_mapping_sync::{MappingSyncWorker, SyncStrategy};
 
-use up_common::types::opaque::{AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block};
+use up_common::types::opaque::{
+	AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block, BlockNumber,
+};
 
 // RMRK
 use up_data_structs::{
@@ -362,6 +364,7 @@
 		+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
 		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>
 		+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>
+		+ app_promotion_rpc::AppPromotionApi<Block, BlockNumber, Runtime::CrossAccountId, AccountId>
 		+ rmrk_rpc::RmrkApi<
 			Block,
 			AccountId,
@@ -663,6 +666,7 @@
 		+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
 		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>
 		+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>
+		+ app_promotion_rpc::AppPromotionApi<Block, BlockNumber, Runtime::CrossAccountId, AccountId>
 		+ rmrk_rpc::RmrkApi<
 			Block,
 			AccountId,
@@ -807,6 +811,7 @@
 		+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
 		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>
 		+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>
+		+ app_promotion_rpc::AppPromotionApi<Block, BlockNumber, Runtime::CrossAccountId, AccountId>
 		+ rmrk_rpc::RmrkApi<
 			Block,
 			AccountId,
modifiednode/rpc/Cargo.tomldiffbeforeafterboth
--- a/node/rpc/Cargo.toml
+++ b/node/rpc/Cargo.toml
@@ -53,6 +53,7 @@
 pallet-unique = { path = "../../pallets/unique" }
 uc-rpc = { path = "../../client/rpc" }
 up-rpc = { path = "../../primitives/rpc" }
+app-promotion-rpc = { path = "../../primitives/app_promotion_rpc"}
 rmrk-rpc = { path = "../../primitives/rmrk-rpc" }
 up-data-structs = { default-features = false, path = "../../primitives/data-structs" }
 
modifiednode/rpc/src/lib.rsdiffbeforeafterboth
--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -145,6 +145,12 @@
 	C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,
 	C::Api: fp_rpc::ConvertTransactionRuntimeApi<Block>,
 	C::Api: up_rpc::UniqueApi<Block, <R as RuntimeInstance>::CrossAccountId, AccountId>,
+	C::Api: app_promotion_rpc::AppPromotionApi<
+		Block,
+		BlockNumber,
+		<R as RuntimeInstance>::CrossAccountId,
+		AccountId,
+	>,
 	C::Api: rmrk_rpc::RmrkApi<
 		Block,
 		AccountId,
@@ -169,6 +175,7 @@
 		EthPubSubApiServer, EthSigner, Net, NetApiServer, Web3, Web3ApiServer,
 	};
 	use uc_rpc::{UniqueApiServer, Unique};
+	use uc_rpc::{AppPromotionApiServer, AppPromotion};
 
 	#[cfg(not(feature = "unique-runtime"))]
 	use uc_rpc::{RmrkApiServer, Rmrk};
@@ -227,6 +234,9 @@
 
 	io.merge(Unique::new(client.clone()).into_rpc())?;
 
+	#[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))]
+	io.merge(AppPromotion::new(client.clone()).into_rpc())?;
+
 	#[cfg(not(feature = "unique-runtime"))]
 	io.merge(Rmrk::new(client.clone()).into_rpc())?;
 
addedpallets/app-promotion/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/app-promotion/Cargo.toml
@@ -0,0 +1,73 @@
+################################################################################
+# Package
+
+[package]
+authors = ['Unique Network <support@uniquenetwork.io>']
+description = 'Unique App Promotion Pallet'
+edition = '2021'
+homepage = 'https://unique.network'
+license = 'GPLv3'
+name = 'pallet-app-promotion'
+repository = 'https://github.com/UniqueNetwork/unique-chain'
+version = '0.1.0'
+
+[package.metadata.docs.rs]
+targets = ['x86_64-unknown-linux-gnu']
+
+[features]
+default = ['std']
+runtime-benchmarks = [
+    'frame-benchmarking',
+    'frame-support/runtime-benchmarks',
+    'frame-system/runtime-benchmarks',
+    # 'pallet-unique/runtime-benchmarks',
+]
+std = [
+    'codec/std',
+    'frame-benchmarking/std',
+    'frame-support/std',
+    'frame-system/std',
+    'pallet-balances/std',
+    'pallet-timestamp/std',
+    'pallet-randomness-collective-flip/std',
+    'pallet-evm/std',
+    'sp-io/std',
+    'sp-std/std',
+    'sp-runtime/std',
+    'sp-core/std',
+    'serde/std',
+
+]
+[dependencies]
+scale-info = { version = "2.0.1", default-features = false, features = [
+    "derive",
+] }
+################################################################################
+# Substrate Dependencies
+
+codec = { default-features = false, features = ['derive'], package = 'parity-scale-codec', version = '3.1.2' }
+frame-benchmarking = {default-features = false, optional = true,  git = "https://github.com/paritytech/substrate",  branch = "polkadot-v0.9.27" }
+frame-support = { default-features = false,  git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+frame-system ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+pallet-balances ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+pallet-timestamp ={ default-features = false,  git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+pallet-randomness-collective-flip ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+pallet-evm ={ default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+sp-std ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+sp-io ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+serde = { default-features = false, features = ['derive'], version = '1.0.130' }
+
+################################################################################
+# local dependencies
+
+up-data-structs ={ default-features = false, path = "../../primitives/data-structs" }
+pallet-common ={ default-features = false, path = "../common" }
+pallet-unique ={ default-features = false, path = "../unique" }
+pallet-evm-contract-helpers ={ default-features = false, path = "../evm-contract-helpers" }
+
+[dev-dependencies]
+pallet-evm-migration ={ default-features = false, path = "../evm-migration" }
+
+################################################################################
addedpallets/app-promotion/src/benchmarking.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/app-promotion/src/benchmarking.rs
@@ -0,0 +1,162 @@
+// 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(feature = "runtime-benchmarks")]
+
+use super::*;
+use crate::Pallet as PromototionPallet;
+
+use sp_runtime::traits::Bounded;
+use sp_std::vec;
+
+use frame_benchmarking::{benchmarks, account};
+use frame_support::traits::OnInitialize;
+use frame_system::{Origin, RawOrigin};
+use pallet_unique::benchmarking::create_nft_collection;
+use pallet_evm_migration::Pallet as EvmMigrationPallet;
+
+const SEED: u32 = 0;
+
+fn set_admin<T>() -> Result<T::AccountId, sp_runtime::DispatchError>
+where
+	T: Config + pallet_unique::Config + pallet_evm_migration::Config,
+	T::BlockNumber: From<u32> + Into<u32>,
+	<<T as Config>::Currency as Currency<T::AccountId>>::Balance: Sum + From<u128>,
+{
+	let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+
+	<T as Config>::Currency::make_free_balance_be(
+		&pallet_admin,
+		Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value(),
+	);
+
+	PromototionPallet::<T>::set_admin_address(
+		RawOrigin::Root.into(),
+		T::CrossAccountId::from_sub(pallet_admin.clone()),
+	)?;
+
+	Ok(pallet_admin)
+}
+
+benchmarks! {
+	where_clause{
+		where T:  Config + pallet_unique::Config + pallet_evm_migration::Config ,
+		T::BlockNumber: From<u32> + Into<u32>,
+		<<T as Config>::Currency as Currency<T::AccountId>>::Balance: Sum + From<u128>
+	}
+
+	on_initialize {
+		let b in 0..PENDING_LIMIT_PER_BLOCK;
+		set_admin::<T>()?;
+
+		(0..b).try_for_each(|index| {
+			let staker = account::<T::AccountId>("staker", index, SEED);
+			<T as Config>::Currency::make_free_balance_be(&staker,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+			PromototionPallet::<T>::stake(RawOrigin::Signed(staker.clone()).into(), Into::<BalanceOf<T>>::into(100u128) * T::Nominal::get())?;
+			PromototionPallet::<T>::unstake(RawOrigin::Signed(staker.clone()).into()).map_err(|e| e.error)?;
+			Result::<(), sp_runtime::DispatchError>::Ok(())
+		})?;
+		let block_number = <frame_system::Pallet<T>>::current_block_number() + T::PendingInterval::get();
+	}: {PromototionPallet::<T>::on_initialize(block_number)}
+
+	set_admin_address {
+		let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+		let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+	} : _(RawOrigin::Root, T::CrossAccountId::from_sub(pallet_admin))
+
+	payout_stakers{
+		let b in 1..101;
+
+		let pallet_admin = account::<T::AccountId>("admin", 1, SEED);
+		let share = Perbill::from_rational(1u32, 20);
+		PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?;
+		<T as Config>::Currency::make_free_balance_be(&pallet_admin,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+
+		let staker: T::AccountId = account("caller", 0, SEED);
+		<T as Config>::Currency::make_free_balance_be(&staker,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+		let stakers: Vec<T::AccountId> = (0..b).map(|index| account("staker", index, SEED)).collect();
+		stakers.iter().for_each(|staker| {
+			<T as Config>::Currency::make_free_balance_be(&staker,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+		});
+		(0..10).try_for_each(|_| {
+			stakers.iter()
+				.map(|staker| {
+					PromototionPallet::<T>::stake(RawOrigin::Signed(staker.clone()).into(), Into::<BalanceOf<T>>::into(100u128) * T::Nominal::get())
+				}).collect::<Result<Vec<_>, _>>()?;
+			<frame_system::Pallet<T>>::finalize();
+			Result::<(), sp_runtime::DispatchError>::Ok(())
+		})?;
+	} : _(RawOrigin::Signed(pallet_admin.clone()), Some(b as u8))
+
+	stake {
+		let caller = account::<T::AccountId>("caller", 0, SEED);
+		let share = Perbill::from_rational(1u32, 10);
+		let _ = <T as Config>::Currency::make_free_balance_be(&caller,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+	} : _(RawOrigin::Signed(caller.clone()), share * <T as Config>::Currency::total_balance(&caller))
+
+	unstake {
+		let caller = account::<T::AccountId>("caller", 0, SEED);
+		let share = Perbill::from_rational(1u32, 20);
+		let _ = <T as Config>::Currency::make_free_balance_be(&caller,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+		(0..10).map(|_| {
+			<frame_system::Pallet<T>>::finalize();
+			PromototionPallet::<T>::stake(RawOrigin::Signed(caller.clone()).into(), share * <T as Config>::Currency::total_balance(&caller))
+		}).collect::<Result<Vec<_>, _>>()?;
+
+	} : _(RawOrigin::Signed(caller.clone()))
+
+	sponsor_collection {
+		let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+		PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?;
+		let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let _ = <T as Config>::Currency::make_free_balance_be(&caller,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	} : _(RawOrigin::Signed(pallet_admin.clone()), collection)
+
+	stop_sponsoring_collection {
+		let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+		PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?;
+		let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let _ = <T as Config>::Currency::make_free_balance_be(&caller,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+		let collection = create_nft_collection::<T>(caller.clone())?;
+		PromototionPallet::<T>::sponsor_collection(RawOrigin::Signed(pallet_admin.clone()).into(), collection)?;
+	} : _(RawOrigin::Signed(pallet_admin.clone()), collection)
+
+	sponsor_contract {
+		let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+		PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?;
+
+		let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+		let address = H160::from_low_u64_be(SEED as u64);
+		let data: Vec<u8> = (0..20 as u8).collect();
+		<EvmMigrationPallet<T>>::begin(RawOrigin::Root.into(), address)?;
+		<EvmMigrationPallet<T>>::finish(RawOrigin::Root.into(), address, data)?;
+	} : _(RawOrigin::Signed(pallet_admin.clone()), address)
+
+	stop_sponsoring_contract {
+		let pallet_admin = account::<T::AccountId>("admin", 0, SEED);
+		PromototionPallet::<T>::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?;
+
+		let _ = <T as Config>::Currency::make_free_balance_be(&pallet_admin,  Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
+		let address = H160::from_low_u64_be(SEED as u64);
+		let data: Vec<u8> = (0..20 as u8).collect();
+		<EvmMigrationPallet<T>>::begin(RawOrigin::Root.into(), address)?;
+		<EvmMigrationPallet<T>>::finish(RawOrigin::Root.into(), address, data)?;
+		PromototionPallet::<T>::sponsor_contract(RawOrigin::Signed(pallet_admin.clone()).into(), address)?;
+	} : _(RawOrigin::Signed(pallet_admin.clone()), address)
+}
addedpallets/app-promotion/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/app-promotion/src/lib.rs
@@ -0,0 +1,758 @@
+// 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/>.
+
+//! # App promotion
+//!
+//! The app promotion pallet is designed to ... .
+//!
+//! ## Interface
+//!
+//! ### Dispatchable Functions
+//!
+
+// #![recursion_limit = "1024"]
+#![cfg_attr(not(feature = "std"), no_std)]
+
+#[cfg(feature = "runtime-benchmarks")]
+mod benchmarking;
+
+pub mod types;
+pub mod weights;
+
+use sp_std::{
+	vec::{Vec},
+	vec,
+	iter::Sum,
+	borrow::ToOwned,
+	cell::RefCell,
+};
+use sp_core::H160;
+use codec::EncodeLike;
+use pallet_balances::BalanceLock;
+pub use types::*;
+
+use up_data_structs::CollectionId;
+
+use frame_support::{
+	dispatch::{DispatchResult},
+	traits::{
+		Currency, Get, LockableCurrency, WithdrawReasons, tokens::Balance, ExistenceRequirement,
+	},
+	ensure,
+};
+
+use weights::WeightInfo;
+
+pub use pallet::*;
+use pallet_evm::account::CrossAccountId;
+use sp_runtime::{
+	Perbill,
+	traits::{BlockNumberProvider, CheckedAdd, CheckedSub, AccountIdConversion, Zero},
+	ArithmeticError,
+};
+
+pub const LOCK_IDENTIFIER: [u8; 8] = *b"appstake";
+
+const PENDING_LIMIT_PER_BLOCK: u32 = 3;
+
+type BalanceOf<T> =
+	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
+
+#[frame_support::pallet]
+pub mod pallet {
+	use super::*;
+	use frame_support::{
+		Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key, PalletId,
+		traits::ReservableCurrency,
+	};
+	use frame_system::pallet_prelude::*;
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config + pallet_evm::account::Config {
+		/// Type to interact with the native token
+		type Currency: ExtendedLockableCurrency<Self::AccountId>
+			+ ReservableCurrency<Self::AccountId>;
+
+		/// Type for interacting with collections
+		type CollectionHandler: CollectionHandler<
+			AccountId = Self::AccountId,
+			CollectionId = CollectionId,
+		>;
+
+		/// Type for interacting with conrtacts
+		type ContractHandler: ContractHandler<AccountId = Self::CrossAccountId, ContractId = H160>;
+
+		/// ID for treasury
+		type TreasuryAccountId: Get<Self::AccountId>;
+
+		/// The app's pallet id, used for deriving its sovereign account ID.
+		#[pallet::constant]
+		type PalletId: Get<PalletId>;
+
+		/// In relay blocks.
+		#[pallet::constant]
+		type RecalculationInterval: Get<Self::BlockNumber>;
+
+		/// In parachain blocks.
+		#[pallet::constant]
+		type PendingInterval: Get<Self::BlockNumber>;
+
+		/// Rate of return for interval in blocks defined in `RecalculationInterval`.
+		#[pallet::constant]
+		type IntervalIncome: Get<Perbill>;
+
+		/// Decimals for the `Currency`.
+		#[pallet::constant]
+		type Nominal: Get<BalanceOf<Self>>;
+
+		/// Weight information for extrinsics in this pallet.
+		type WeightInfo: WeightInfo;
+
+		// The relay block number provider
+		type RelayBlockNumberProvider: BlockNumberProvider<BlockNumber = Self::BlockNumber>;
+
+		/// Events compatible with [`frame_system::Config::Event`].
+		type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;
+	}
+
+	#[pallet::pallet]
+	#[pallet::generate_store(pub(super) trait Store)]
+	pub struct Pallet<T>(_);
+
+	#[pallet::event]
+	#[pallet::generate_deposit(fn deposit_event)]
+	pub enum Event<T: Config> {
+		/// Staking recalculation was performed
+		///
+		/// # Arguments
+		/// * AccountId: ID of the staker.
+		/// * Balance : recalculation base
+		/// * Balance : total income
+		StakingRecalculation(
+			/// An recalculated staker
+			T::AccountId,
+			/// Base on which interest is calculated
+			BalanceOf<T>,
+			/// Amount of accrued interest
+			BalanceOf<T>,
+		),
+
+		/// Staking was performed
+		///
+		/// # Arguments
+		/// * AccountId: ID of the staker
+		/// * Balance : staking amount
+		Stake(T::AccountId, BalanceOf<T>),
+
+		/// Unstaking was performed
+		///
+		/// # Arguments
+		/// * AccountId: ID of the staker
+		/// * Balance : unstaking amount
+		Unstake(T::AccountId, BalanceOf<T>),
+
+		/// The admin was set
+		///
+		/// # Arguments
+		/// * AccountId: ID of the admin
+		SetAdmin(T::AccountId),
+	}
+
+	#[pallet::error]
+	pub enum Error<T> {
+		/// Error due to action requiring admin to be set.
+		AdminNotSet,
+		/// No permission to perform an action.
+		NoPermission,
+		/// Insufficient funds to perform an action.
+		NotSufficientFunds,
+		/// Occurs when a pending unstake cannot be added in this block. PENDING_LIMIT_PER_BLOCK` limits exceeded.
+		PendingForBlockOverflow,
+		/// The error is due to the fact that the collection/contract must already be sponsored in order to perform the action.
+		SponsorNotSet,
+		/// Errors caused by incorrect actions with a locked balance.
+		IncorrectLockedBalanceOperation,
+	}
+
+	#[pallet::storage]
+	pub type TotalStaked<T: Config> = StorageValue<Value = BalanceOf<T>, QueryKind = ValueQuery>;
+
+	#[pallet::storage]
+	pub type Admin<T: Config> = StorageValue<Value = T::AccountId, QueryKind = OptionQuery>;
+
+	/// Amount of tokens staked by account in the blocknumber.
+	#[pallet::storage]
+	pub type Staked<T: Config> = StorageNMap<
+		Key = (
+			Key<Blake2_128Concat, T::AccountId>,
+			Key<Twox64Concat, T::BlockNumber>,
+		),
+		Value = (BalanceOf<T>, T::BlockNumber),
+		QueryKind = ValueQuery,
+	>;
+	/// Amount of stakes for an Account
+	#[pallet::storage]
+	pub type StakesPerAccount<T: Config> =
+		StorageMap<_, Blake2_128Concat, T::AccountId, u8, ValueQuery>;
+
+	#[pallet::storage]
+	pub type PendingUnstake<T: Config> = StorageMap<
+		_,
+		Twox64Concat,
+		T::BlockNumber,
+		BoundedVec<(T::AccountId, BalanceOf<T>), ConstU32<PENDING_LIMIT_PER_BLOCK>>,
+		ValueQuery,
+	>;
+
+	/// Stores a key for record for which the next revenue recalculation would be performed.
+	/// If `None`, then recalculation has not yet been performed or calculations have been completed for all stakers.
+	#[pallet::storage]
+	#[pallet::getter(fn get_next_calculated_record)]
+	pub type NextCalculatedRecord<T: Config> =
+		StorageValue<Value = (T::AccountId, T::BlockNumber), QueryKind = OptionQuery>;
+
+	#[pallet::hooks]
+	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
+		/// Block overflow is impossible due to the fact that the unstake algorithm in on_initialize
+		/// implies the execution of a strictly limited number of relatively lightweight operations.
+		/// A separate benchmark has been implemented to scale the weight depending on the number of pendings.
+		fn on_initialize(current_block_number: T::BlockNumber) -> Weight
+		where
+			<T as frame_system::Config>::BlockNumber: From<u32>,
+		{
+			let block_pending = PendingUnstake::<T>::take(current_block_number);
+			let counter = block_pending.len() as u32;
+
+			if !block_pending.is_empty() {
+				block_pending.into_iter().for_each(|(staker, amount)| {
+					<T::Currency as ReservableCurrency<T::AccountId>>::unreserve(&staker, amount);
+				});
+			}
+
+			T::WeightInfo::on_initialize(counter)
+		}
+	}
+
+	#[pallet::call]
+	impl<T: Config> Pallet<T>
+	where
+		T::BlockNumber: From<u32> + Into<u32>,
+		<<T as Config>::Currency as Currency<T::AccountId>>::Balance: Sum + From<u128>,
+	{
+		#[pallet::weight(T::WeightInfo::set_admin_address())]
+		pub fn set_admin_address(origin: OriginFor<T>, admin: T::CrossAccountId) -> DispatchResult {
+			ensure_root(origin)?;
+
+			<Admin<T>>::set(Some(admin.as_sub().to_owned()));
+
+			Self::deposit_event(Event::SetAdmin(admin.as_sub().to_owned()));
+
+			Ok(())
+		}
+
+		#[pallet::weight(T::WeightInfo::stake())]
+		pub fn stake(staker: OriginFor<T>, amount: BalanceOf<T>) -> DispatchResult {
+			let staker_id = ensure_signed(staker)?;
+
+			ensure!(
+				StakesPerAccount::<T>::get(&staker_id) < 10,
+				Error::<T>::NoPermission
+			);
+
+			ensure!(
+				amount >= <BalanceOf<T>>::from(100u128) * T::Nominal::get(),
+				ArithmeticError::Underflow
+			);
+
+			let balance =
+				<<T as Config>::Currency as Currency<T::AccountId>>::free_balance(&staker_id);
+
+			<<T as Config>::Currency as Currency<T::AccountId>>::ensure_can_withdraw(
+				&staker_id,
+				amount,
+				WithdrawReasons::all(),
+				balance
+					.checked_sub(&amount)
+					.ok_or(ArithmeticError::Underflow)?,
+			)?;
+
+			Self::add_lock_balance(&staker_id, amount)?;
+
+			let block_number = T::RelayBlockNumberProvider::current_block_number();
+
+			let recalculate_after_interval: T::BlockNumber =
+				if block_number % T::RecalculationInterval::get() == 0u32.into() {
+					1u32.into()
+				} else {
+					2u32.into()
+				};
+
+			let recalc_block = (block_number / T::RecalculationInterval::get()
+				+ recalculate_after_interval)
+				* T::RecalculationInterval::get();
+
+			<Staked<T>>::insert((&staker_id, block_number), {
+				let mut balance_and_recalc_block = <Staked<T>>::get((&staker_id, block_number));
+				balance_and_recalc_block.0 = balance_and_recalc_block
+					.0
+					.checked_add(&amount)
+					.ok_or(ArithmeticError::Overflow)?;
+				balance_and_recalc_block.1 = recalc_block;
+				balance_and_recalc_block
+			});
+
+			<TotalStaked<T>>::set(
+				<TotalStaked<T>>::get()
+					.checked_add(&amount)
+					.ok_or(ArithmeticError::Overflow)?,
+			);
+
+			StakesPerAccount::<T>::mutate(&staker_id, |stakes| *stakes += 1);
+
+			Self::deposit_event(Event::Stake(staker_id, amount));
+
+			Ok(())
+		}
+
+		#[pallet::weight(T::WeightInfo::unstake())]
+		pub fn unstake(staker: OriginFor<T>) -> DispatchResultWithPostInfo {
+			let staker_id = ensure_signed(staker)?;
+			let block = <frame_system::Pallet<T>>::block_number() + T::PendingInterval::get();
+			let mut pendings = <PendingUnstake<T>>::get(block);
+
+			ensure!(!pendings.is_full(), Error::<T>::PendingForBlockOverflow);
+
+			let mut total_stakes = 0u64;
+
+			let total_staked: BalanceOf<T> = Staked::<T>::drain_prefix((&staker_id,))
+				.map(|(_, (amount, _))| {
+					total_stakes += 1;
+					amount
+				})
+				.sum();
+
+			if total_staked.is_zero() {
+				return Ok(None.into()); // TO-DO
+			}
+
+			pendings
+				.try_push((staker_id.clone(), total_staked))
+				.map_err(|_| Error::<T>::PendingForBlockOverflow)?;
+
+			<PendingUnstake<T>>::insert(block, pendings);
+
+			Self::unlock_balance(&staker_id, total_staked)?;
+
+			<T::Currency as ReservableCurrency<T::AccountId>>::reserve(&staker_id, total_staked)?;
+
+			TotalStaked::<T>::set(
+				TotalStaked::<T>::get()
+					.checked_sub(&total_staked)
+					.ok_or(ArithmeticError::Underflow)?,
+			);
+
+			StakesPerAccount::<T>::remove(&staker_id);
+
+			Self::deposit_event(Event::Unstake(staker_id, total_staked));
+
+			Ok(None.into())
+		}
+
+		#[pallet::weight(T::WeightInfo::sponsor_collection())]
+		pub fn sponsor_collection(
+			admin: OriginFor<T>,
+			collection_id: CollectionId,
+		) -> DispatchResult {
+			let admin_id = ensure_signed(admin)?;
+			ensure!(
+				admin_id == Admin::<T>::get().ok_or(Error::<T>::AdminNotSet)?,
+				Error::<T>::NoPermission
+			);
+
+			T::CollectionHandler::set_sponsor(Self::account_id(), collection_id)
+		}
+		#[pallet::weight(T::WeightInfo::stop_sponsoring_collection())]
+		pub fn stop_sponsoring_collection(
+			admin: OriginFor<T>,
+			collection_id: CollectionId,
+		) -> DispatchResult {
+			let admin_id = ensure_signed(admin)?;
+
+			ensure!(
+				admin_id == Admin::<T>::get().ok_or(Error::<T>::AdminNotSet)?,
+				Error::<T>::NoPermission
+			);
+
+			ensure!(
+				T::CollectionHandler::sponsor(collection_id)?.ok_or(<Error<T>>::SponsorNotSet)?
+					== Self::account_id(),
+				<Error<T>>::NoPermission
+			);
+			T::CollectionHandler::remove_collection_sponsor(collection_id)
+		}
+
+		#[pallet::weight(T::WeightInfo::sponsor_contract())]
+		pub fn sponsor_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {
+			let admin_id = ensure_signed(admin)?;
+
+			ensure!(
+				admin_id == Admin::<T>::get().ok_or(Error::<T>::AdminNotSet)?,
+				Error::<T>::NoPermission
+			);
+
+			T::ContractHandler::set_sponsor(
+				T::CrossAccountId::from_sub(Self::account_id()),
+				contract_id,
+			)
+		}
+
+		#[pallet::weight(T::WeightInfo::stop_sponsoring_contract())]
+		pub fn stop_sponsoring_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {
+			let admin_id = ensure_signed(admin)?;
+
+			ensure!(
+				admin_id == Admin::<T>::get().ok_or(Error::<T>::AdminNotSet)?,
+				Error::<T>::NoPermission
+			);
+
+			ensure!(
+				T::ContractHandler::sponsor(contract_id)?
+					.ok_or(<Error<T>>::SponsorNotSet)?
+					.as_sub() == &Self::account_id(),
+				<Error<T>>::NoPermission
+			);
+			T::ContractHandler::remove_contract_sponsor(contract_id)
+		}
+
+		#[pallet::weight(T::WeightInfo::payout_stakers(stakers_number.unwrap_or(20) as u32))]
+		pub fn payout_stakers(admin: OriginFor<T>, stakers_number: Option<u8>) -> DispatchResult {
+			let admin_id = ensure_signed(admin)?;
+
+			ensure!(
+				admin_id == Admin::<T>::get().ok_or(Error::<T>::AdminNotSet)?,
+				Error::<T>::NoPermission
+			);
+
+			let current_recalc_block =
+				Self::get_current_recalc_block(T::RelayBlockNumberProvider::current_block_number());
+			let next_recalc_block = current_recalc_block + T::RecalculationInterval::get();
+
+			let mut storage_iterator = Self::get_next_calculated_key()
+				.map_or(Staked::<T>::iter(), |key| Staked::<T>::iter_from(key));
+
+			NextCalculatedRecord::<T>::set(None);
+
+			// {
+			// 	let mut stakers_number = stakers_number.unwrap_or(20);
+			// 	let mut last_id = admin_id;
+			// 	let mut income_acc = BalanceOf::<T>::default();
+			// 	let mut amount_acc = BalanceOf::<T>::default();
+
+			// 	while let Some((
+			// 		(current_id, staked_block),
+			// 		(amount, next_recalc_block_for_stake),
+			// 	)) = storage_iterator.next()
+			// 	{
+			// 		if last_id != current_id {
+			// 			if income_acc != BalanceOf::<T>::default() {
+			// 				<T::Currency as Currency<T::AccountId>>::transfer(
+			// 					&T::TreasuryAccountId::get(),
+			// 					&last_id,
+			// 					income_acc,
+			// 					ExistenceRequirement::KeepAlive,
+			// 				)
+			// 				.and_then(|_| Self::add_lock_balance(&last_id, income_acc))?;
+
+			// 				Self::deposit_event(Event::StakingRecalculation(
+			// 					last_id, amount, income_acc,
+			// 				));
+			// 			}
+
+			// 			if stakers_number == 0 {
+			// 				NextCalculatedRecord::<T>::set(Some((current_id, staked_block)));
+			// 				break;
+			// 			}
+			// 			stakers_number -= 1;
+			// 			income_acc = BalanceOf::<T>::default();
+			// 			last_id = current_id;
+			// 		};
+			// 		if current_recalc_block >= next_recalc_block_for_stake {
+			// 			Self::recalculate_and_insert_stake(
+			// 				&last_id,
+			// 				staked_block,
+			// 				next_recalc_block,
+			// 				amount,
+			// 				((current_recalc_block - next_recalc_block_for_stake)
+			// 					/ T::RecalculationInterval::get())
+			// 				.into() + 1,
+			// 				&mut income_acc,
+			// 			);
+			// 		}
+			// 	}
+			// }
+
+			{
+				let mut stakers_number = stakers_number.unwrap_or(20);
+				let last_id = RefCell::new(None);
+				let income_acc = RefCell::new(BalanceOf::<T>::default());
+				let amount_acc = RefCell::new(BalanceOf::<T>::default());
+
+				let flush_stake = || -> DispatchResult {
+					if let Some(last_id) = &*last_id.borrow() {
+						if !income_acc.borrow().is_zero() {
+							<T::Currency as Currency<T::AccountId>>::transfer(
+								&T::TreasuryAccountId::get(),
+								last_id,
+								*income_acc.borrow(),
+								ExistenceRequirement::KeepAlive,
+							)
+							.and_then(|_| {
+								Self::add_lock_balance(last_id, *income_acc.borrow())?;
+								<TotalStaked<T>>::try_mutate(|staked| {
+									staked
+										.checked_add(&*income_acc.borrow())
+										.ok_or(ArithmeticError::Overflow.into())
+								})
+							})?;
+
+							Self::deposit_event(Event::StakingRecalculation(
+								last_id.clone(),
+								*amount_acc.borrow(),
+								*income_acc.borrow(),
+							));
+						}
+
+						*income_acc.borrow_mut() = BalanceOf::<T>::default();
+						*amount_acc.borrow_mut() = BalanceOf::<T>::default();
+					}
+					Ok(())
+				};
+
+				while let Some((
+					(current_id, staked_block),
+					(amount, next_recalc_block_for_stake),
+				)) = storage_iterator.next()
+				{
+					if stakers_number == 0 {
+						NextCalculatedRecord::<T>::set(Some((current_id, staked_block)));
+						break;
+					}
+					if last_id.borrow().as_ref() != Some(&current_id) {
+						flush_stake()?;
+						*last_id.borrow_mut() = Some(current_id.clone());
+						stakers_number -= 1;
+					};
+					if current_recalc_block >= next_recalc_block_for_stake {
+						*amount_acc.borrow_mut() += amount;
+						Self::recalculate_and_insert_stake(
+							&current_id,
+							staked_block,
+							next_recalc_block,
+							amount,
+							((current_recalc_block - next_recalc_block_for_stake)
+								/ T::RecalculationInterval::get())
+							.into() + 1,
+							&mut *income_acc.borrow_mut(),
+						);
+					}
+				}
+				flush_stake()?;
+			}
+
+			Ok(())
+		}
+	}
+}
+
+impl<T: Config> Pallet<T> {
+	pub fn account_id() -> T::AccountId {
+		T::PalletId::get().into_account_truncating()
+	}
+
+	fn unlock_balance(staker: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {
+		let locked_balance = Self::get_locked_balance(staker)
+			.map(|l| l.amount)
+			.ok_or(<Error<T>>::IncorrectLockedBalanceOperation)?;
+
+		// It is understood that we cannot unlock more funds than were locked by staking.
+		// Therefore, if implemented correctly, this error should not occur.
+		Self::set_lock_unchecked(
+			staker,
+			locked_balance
+				.checked_sub(&amount)
+				.ok_or(ArithmeticError::Underflow)?,
+		);
+		Ok(())
+	}
+
+	fn add_lock_balance(staker: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {
+		Self::get_locked_balance(staker)
+			.map_or(<BalanceOf<T>>::default(), |l| l.amount)
+			.checked_add(&amount)
+			.map(|new_lock| Self::set_lock_unchecked(staker, new_lock))
+			.ok_or(ArithmeticError::Overflow.into())
+	}
+
+	fn set_lock_unchecked(staker: &T::AccountId, amount: BalanceOf<T>) {
+		if amount.is_zero() {
+			<T::Currency as LockableCurrency<T::AccountId>>::remove_lock(LOCK_IDENTIFIER, &staker);
+		} else {
+			<T::Currency as LockableCurrency<T::AccountId>>::set_lock(
+				LOCK_IDENTIFIER,
+				staker,
+				amount,
+				WithdrawReasons::all(),
+			)
+		}
+	}
+
+	pub fn get_locked_balance(
+		staker: impl EncodeLike<T::AccountId>,
+	) -> Option<BalanceLock<BalanceOf<T>>> {
+		<T::Currency as ExtendedLockableCurrency<T::AccountId>>::locks(staker)
+			.into_iter()
+			.find(|l| l.id == LOCK_IDENTIFIER)
+	}
+
+	pub fn total_staked_by_id(staker: impl EncodeLike<T::AccountId>) -> Option<BalanceOf<T>> {
+		let staked = Staked::<T>::iter_prefix((staker,))
+			.into_iter()
+			.fold(<BalanceOf<T>>::default(), |acc, (_, (amount, _))| {
+				acc + amount
+			});
+		if staked != <BalanceOf<T>>::default() {
+			Some(staked)
+		} else {
+			None
+		}
+	}
+
+	pub fn total_staked_by_id_per_block(
+		staker: impl EncodeLike<T::AccountId>,
+	) -> Option<Vec<(T::BlockNumber, BalanceOf<T>)>> {
+		let mut staked = Staked::<T>::iter_prefix((staker,))
+			.into_iter()
+			.map(|(block, (amount, _))| (block, amount))
+			.collect::<Vec<_>>();
+		staked.sort_by_key(|(block, _)| *block);
+		if !staked.is_empty() {
+			Some(staked)
+		} else {
+			None
+		}
+	}
+
+	pub fn cross_id_total_staked(staker: Option<T::CrossAccountId>) -> Option<BalanceOf<T>> {
+		staker.map_or(Some(<TotalStaked<T>>::get()), |s| {
+			Self::total_staked_by_id(s.as_sub())
+		})
+	}
+
+	// pub fn cross_id_locked_balance(staker: T::CrossAccountId) -> BalanceOf<T> {
+	// 	Self::get_locked_balance(staker.as_sub())
+	// 		.map(|l| l.amount)
+	// 		.unwrap_or_default()
+	// }
+
+	pub fn cross_id_total_staked_per_block(
+		staker: T::CrossAccountId,
+	) -> Vec<(T::BlockNumber, BalanceOf<T>)> {
+		Self::total_staked_by_id_per_block(staker.as_sub()).unwrap_or_default()
+	}
+
+	fn recalculate_and_insert_stake(
+		staker: &T::AccountId,
+		staked_block: T::BlockNumber,
+		next_recalc_block: T::BlockNumber,
+		base: BalanceOf<T>,
+		iters: u32,
+		income_acc: &mut BalanceOf<T>,
+	) {
+		let income = Self::calculate_income(base, iters);
+
+		base.checked_add(&income).map(|res| {
+			<Staked<T>>::insert((staker, staked_block), (res, next_recalc_block));
+			*income_acc += income;
+		});
+	}
+
+	fn calculate_income<I>(base: I, iters: u32) -> I
+	where
+		I: EncodeLike<BalanceOf<T>> + Balance,
+	{
+		let mut income = base;
+
+		(0..iters).for_each(|_| income += T::IntervalIncome::get() * income);
+
+		income - base
+	}
+
+	fn get_current_recalc_block(current_relay_block: T::BlockNumber) -> T::BlockNumber {
+		(current_relay_block / T::RecalculationInterval::get()) * T::RecalculationInterval::get()
+	}
+
+	// fn get_next_recalc_block(current_relay_block: T::BlockNumber) -> T::BlockNumber {
+	// 	Self::get_current_recalc_block(current_relay_block) + T::RecalculationInterval::get()
+	// }
+
+	fn get_next_calculated_key() -> Option<Vec<u8>> {
+		Self::get_next_calculated_record().map(|key| Staked::<T>::hashed_key_for(key))
+	}
+}
+
+impl<T: Config> Pallet<T>
+where
+	<<T as Config>::Currency as Currency<T::AccountId>>::Balance: Sum,
+{
+	/// Since user funds are not transferred anywhere by staking, overflow protection is provided
+	/// at the level of the associated type `Balance` of `Currency` trait. In order to overflow,
+	/// the staker must have more funds on his account than the maximum set for `Balance` type.
+	pub fn cross_id_pending_unstake(staker: Option<T::CrossAccountId>) -> BalanceOf<T> {
+		staker.map_or(
+			PendingUnstake::<T>::iter_values()
+				.flat_map(|pendings| pendings.into_iter().map(|(_, amount)| amount))
+				.sum(),
+			|s| {
+				PendingUnstake::<T>::iter_values()
+					.flatten()
+					.filter_map(|(id, amount)| {
+						if id == *s.as_sub() {
+							Some(amount)
+						} else {
+							None
+						}
+					})
+					.sum()
+			},
+		)
+	}
+
+	pub fn cross_id_pending_unstake_per_block(
+		staker: T::CrossAccountId,
+	) -> Vec<(T::BlockNumber, BalanceOf<T>)> {
+		let mut unsorted_res = vec![];
+		PendingUnstake::<T>::iter().for_each(|(block, pendings)| {
+			pendings.into_iter().for_each(|(id, amount)| {
+				if id == *staker.as_sub() {
+					unsorted_res.push((block, amount));
+				};
+			})
+		});
+
+		unsorted_res.sort_by_key(|(block, _)| *block);
+		unsorted_res
+	}
+}
addedpallets/app-promotion/src/types.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/app-promotion/src/types.rs
@@ -0,0 +1,107 @@
+use codec::EncodeLike;
+use frame_support::{traits::LockableCurrency, WeakBoundedVec, Parameter, dispatch::DispatchResult};
+
+use pallet_balances::{BalanceLock, Config as BalancesConfig, Pallet as PalletBalances};
+use pallet_common::CollectionHandle;
+
+use sp_runtime::DispatchError;
+use up_data_structs::{CollectionId};
+use sp_std::borrow::ToOwned;
+use pallet_evm_contract_helpers::{Pallet as EvmHelpersPallet, Config as EvmHelpersConfig};
+
+pub trait ExtendedLockableCurrency<AccountId: Parameter>: LockableCurrency<AccountId> {
+	fn locks<KArg>(who: KArg) -> WeakBoundedVec<BalanceLock<Self::Balance>, Self::MaxLocks>
+	where
+		KArg: EncodeLike<AccountId>;
+}
+
+impl<T: BalancesConfig<I>, I: 'static> ExtendedLockableCurrency<T::AccountId>
+	for PalletBalances<T, I>
+{
+	fn locks<KArg>(who: KArg) -> WeakBoundedVec<BalanceLock<Self::Balance>, Self::MaxLocks>
+	where
+		KArg: EncodeLike<T::AccountId>,
+	{
+		Self::locks(who)
+	}
+}
+
+pub trait CollectionHandler {
+	type CollectionId;
+	type AccountId;
+
+	fn set_sponsor(
+		sponsor_id: Self::AccountId,
+		collection_id: Self::CollectionId,
+	) -> DispatchResult;
+
+	fn remove_collection_sponsor(collection_id: Self::CollectionId) -> DispatchResult;
+
+	fn sponsor(collection_id: Self::CollectionId)
+		-> Result<Option<Self::AccountId>, DispatchError>;
+}
+
+impl<T: pallet_unique::Config> CollectionHandler for pallet_unique::Pallet<T> {
+	type CollectionId = CollectionId;
+
+	type AccountId = T::AccountId;
+
+	fn set_sponsor(
+		sponsor_id: Self::AccountId,
+		collection_id: Self::CollectionId,
+	) -> DispatchResult {
+		Self::force_set_sponsor(sponsor_id, collection_id)
+	}
+
+	fn remove_collection_sponsor(collection_id: Self::CollectionId) -> DispatchResult {
+		Self::force_remove_collection_sponsor(collection_id)
+	}
+
+	fn sponsor(
+		collection_id: Self::CollectionId,
+	) -> Result<Option<Self::AccountId>, DispatchError> {
+		Ok(<CollectionHandle<T>>::try_get(collection_id)?
+			.sponsorship
+			.sponsor()
+			.map(|acc| acc.to_owned()))
+	}
+}
+
+pub trait ContractHandler {
+	type ContractId;
+	type AccountId;
+
+	fn set_sponsor(
+		sponsor_id: Self::AccountId,
+		contract_address: Self::ContractId,
+	) -> DispatchResult;
+
+	fn remove_contract_sponsor(contract_address: Self::ContractId) -> DispatchResult;
+
+	fn sponsor(
+		contract_address: Self::ContractId,
+	) -> Result<Option<Self::AccountId>, DispatchError>;
+}
+
+impl<T: EvmHelpersConfig> ContractHandler for EvmHelpersPallet<T> {
+	type ContractId = sp_core::H160;
+
+	type AccountId = T::CrossAccountId;
+
+	fn set_sponsor(
+		sponsor_id: Self::AccountId,
+		contract_address: Self::ContractId,
+	) -> DispatchResult {
+		Self::force_set_sponsor(contract_address, &sponsor_id)
+	}
+
+	fn remove_contract_sponsor(contract_address: Self::ContractId) -> DispatchResult {
+		Self::force_remove_sponsor(contract_address)
+	}
+
+	fn sponsor(
+		contract_address: Self::ContractId,
+	) -> Result<Option<Self::AccountId>, DispatchError> {
+		Ok(Self::get_sponsor(contract_address))
+	}
+}
addedpallets/app-promotion/src/weights.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/app-promotion/src/weights.rs
@@ -0,0 +1,209 @@
+// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs
+
+//! Autogenerated weights for pallet_app_promotion
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2022-09-07, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
+
+// Executed Command:
+// target/release/unique-collator
+// benchmark
+// pallet
+// --pallet
+// pallet-app-promotion
+// --wasm-execution
+// compiled
+// --extrinsic
+// *
+// --template
+// .maintain/frame-weight-template.hbs
+// --steps=50
+// --repeat=80
+// --heap-pages=4096
+// --output=./pallets/app-promotion/src/weights.rs
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+#![allow(clippy::unnecessary_cast)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use sp_std::marker::PhantomData;
+
+/// Weight functions needed for pallet_app_promotion.
+pub trait WeightInfo {
+	fn on_initialize(b: u32, ) -> Weight;
+	fn set_admin_address() -> Weight;
+	fn payout_stakers(b: u32, ) -> Weight;
+	fn stake() -> Weight;
+	fn unstake() -> Weight;
+	fn sponsor_collection() -> Weight;
+	fn stop_sponsoring_collection() -> Weight;
+	fn sponsor_contract() -> Weight;
+	fn stop_sponsoring_contract() -> Weight;
+}
+
+/// Weights for pallet_app_promotion using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+	// Storage: AppPromotion PendingUnstake (r:1 w:0)
+	// Storage: System Account (r:1 w:1)
+	fn on_initialize(b: u32, ) -> Weight {
+		(2_651_000 as Weight)
+			// Standard Error: 103_000
+			.saturating_add((6_024_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
+			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
+	}
+	// Storage: AppPromotion Admin (r:0 w:1)
+	fn set_admin_address() -> Weight {
+		(7_117_000 as Weight)
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: AppPromotion Admin (r:1 w:0)
+	// Storage: ParachainSystem ValidationData (r:1 w:0)
+	// Storage: AppPromotion NextCalculatedRecord (r:1 w:1)
+	// Storage: AppPromotion Staked (r:2 w:0)
+	fn payout_stakers(b: u32, ) -> Weight {
+		(9_958_000 as Weight)
+			// Standard Error: 8_000
+			.saturating_add((4_406_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(T::DbWeight::get().reads(4 as Weight))
+			.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: AppPromotion StakesPerAccount (r:1 w:1)
+	// Storage: System Account (r:1 w:1)
+	// Storage: Balances Locks (r:1 w:1)
+	// Storage: ParachainSystem ValidationData (r:1 w:0)
+	// Storage: AppPromotion Staked (r:1 w:1)
+	// Storage: AppPromotion TotalStaked (r:1 w:1)
+	fn stake() -> Weight {
+		(20_574_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(6 as Weight))
+			.saturating_add(T::DbWeight::get().writes(5 as Weight))
+	}
+	// Storage: AppPromotion PendingUnstake (r:1 w:1)
+	// Storage: AppPromotion Staked (r:2 w:1)
+	// Storage: Balances Locks (r:1 w:1)
+	// Storage: System Account (r:1 w:1)
+	// Storage: AppPromotion TotalStaked (r:1 w:1)
+	// Storage: AppPromotion StakesPerAccount (r:0 w:1)
+	fn unstake() -> Weight {
+		(31_703_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(6 as Weight))
+			.saturating_add(T::DbWeight::get().writes(6 as Weight))
+	}
+	// Storage: AppPromotion Admin (r:1 w:0)
+	// Storage: Common CollectionById (r:1 w:1)
+	fn sponsor_collection() -> Weight {
+		(12_932_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: AppPromotion Admin (r:1 w:0)
+	// Storage: Common CollectionById (r:1 w:1)
+	fn stop_sponsoring_collection() -> Weight {
+		(12_453_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: AppPromotion Admin (r:1 w:0)
+	// Storage: EvmContractHelpers Sponsoring (r:0 w:1)
+	fn sponsor_contract() -> Weight {
+		(11_952_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+	// Storage: AppPromotion Admin (r:1 w:0)
+	// Storage: EvmContractHelpers Sponsoring (r:1 w:1)
+	fn stop_sponsoring_contract() -> Weight {
+		(12_538_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+			.saturating_add(T::DbWeight::get().writes(1 as Weight))
+	}
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+	// Storage: AppPromotion PendingUnstake (r:1 w:0)
+	// Storage: System Account (r:1 w:1)
+	fn on_initialize(b: u32, ) -> Weight {
+		(2_651_000 as Weight)
+			// Standard Error: 103_000
+			.saturating_add((6_024_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
+			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
+	}
+	// Storage: AppPromotion Admin (r:0 w:1)
+	fn set_admin_address() -> Weight {
+		(7_117_000 as Weight)
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: AppPromotion Admin (r:1 w:0)
+	// Storage: ParachainSystem ValidationData (r:1 w:0)
+	// Storage: AppPromotion NextCalculatedRecord (r:1 w:1)
+	// Storage: AppPromotion Staked (r:2 w:0)
+	fn payout_stakers(b: u32, ) -> Weight {
+		(9_958_000 as Weight)
+			// Standard Error: 8_000
+			.saturating_add((4_406_000 as Weight).saturating_mul(b as Weight))
+			.saturating_add(RocksDbWeight::get().reads(4 as Weight))
+			.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: AppPromotion StakesPerAccount (r:1 w:1)
+	// Storage: System Account (r:1 w:1)
+	// Storage: Balances Locks (r:1 w:1)
+	// Storage: ParachainSystem ValidationData (r:1 w:0)
+	// Storage: AppPromotion Staked (r:1 w:1)
+	// Storage: AppPromotion TotalStaked (r:1 w:1)
+	fn stake() -> Weight {
+		(20_574_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(5 as Weight))
+	}
+	// Storage: AppPromotion PendingUnstake (r:1 w:1)
+	// Storage: AppPromotion Staked (r:2 w:1)
+	// Storage: Balances Locks (r:1 w:1)
+	// Storage: System Account (r:1 w:1)
+	// Storage: AppPromotion TotalStaked (r:1 w:1)
+	// Storage: AppPromotion StakesPerAccount (r:0 w:1)
+	fn unstake() -> Weight {
+		(31_703_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(6 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(6 as Weight))
+	}
+	// Storage: AppPromotion Admin (r:1 w:0)
+	// Storage: Common CollectionById (r:1 w:1)
+	fn sponsor_collection() -> Weight {
+		(12_932_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: AppPromotion Admin (r:1 w:0)
+	// Storage: Common CollectionById (r:1 w:1)
+	fn stop_sponsoring_collection() -> Weight {
+		(12_453_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: AppPromotion Admin (r:1 w:0)
+	// Storage: EvmContractHelpers Sponsoring (r:0 w:1)
+	fn sponsor_contract() -> Weight {
+		(11_952_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+	// Storage: AppPromotion Admin (r:1 w:0)
+	// Storage: EvmContractHelpers Sponsoring (r:1 w:1)
+	fn stop_sponsoring_contract() -> Weight {
+		(12_538_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
+	}
+}
modifiedpallets/common/Cargo.tomldiffbeforeafterboth
--- a/pallets/common/Cargo.toml
+++ b/pallets/common/Cargo.toml
@@ -40,4 +40,7 @@
     "up-data-structs/std",
     "pallet-evm/std",
 ]
-runtime-benchmarks = ["frame-benchmarking"]
+runtime-benchmarks = [
+    "frame-benchmarking/runtime-benchmarks",
+    "up-data-structs/runtime-benchmarks",
+]
modifiedpallets/evm-contract-helpers/Cargo.tomldiffbeforeafterboth
--- a/pallets/evm-contract-helpers/Cargo.toml
+++ b/pallets/evm-contract-helpers/Cargo.toml
@@ -9,6 +9,7 @@
     "derive",
 ] }
 log = { default-features = false, version = "0.4.14" }
+ethereum = { version = "0.12.0", default-features = false }
 
 # Substrate
 frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
modifiedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -17,7 +17,9 @@
 //! Implementation of magic contract
 
 use core::marker::PhantomData;
-use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};
+use evm_coder::{
+	abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*, ToLog,
+};
 use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};
 use pallet_evm::{
 	ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle,
@@ -33,6 +35,35 @@
 use up_sponsorship::SponsorshipHandler;
 use sp_std::vec::Vec;
 
+/// Pallet events.
+#[derive(ToLog)]
+pub enum ContractHelpersEvents {
+	/// Contract sponsor was set.
+	ContractSponsorSet {
+		/// Contract address of the affected collection.
+		#[indexed]
+		contract_address: address,
+		/// New sponsor address.
+		sponsor: address,
+	},
+
+	/// New sponsor was confirm.
+	ContractSponsorshipConfirmed {
+		/// Contract address of the affected collection.
+		#[indexed]
+		contract_address: address,
+		/// New sponsor address.
+		sponsor: address,
+	},
+
+	/// Collection sponsor was removed.
+	ContractSponsorRemoved {
+		/// Contract address of the affected collection.
+		#[indexed]
+		contract_address: address,
+	},
+}
+
 /// See [`ContractHelpersCall`]
 pub struct ContractHelpers<T: Config>(SubstrateRecorder<T>);
 impl<T: Config> WithRecorder<T> for ContractHelpers<T> {
@@ -46,7 +77,7 @@
 }
 
 /// @title Magic contract, which allows users to reconfigure other contracts
-#[solidity_interface(name = ContractHelpers)]
+#[solidity_interface(name = ContractHelpers, events(ContractHelpersEvents))]
 impl<T: Config> ContractHelpers<T>
 where
 	T::AccountId: AsRef<[u8; 32]>,
@@ -91,9 +122,17 @@
 		self.recorder().consume_sload()?;
 		self.recorder().consume_sstore()?;
 
-		Pallet::<T>::self_sponsored_enable(&T::CrossAccountId::from_eth(caller), contract_address)
+		let caller = T::CrossAccountId::from_eth(caller);
+
+		Pallet::<T>::ensure_owner(contract_address, *caller.as_eth())
 			.map_err(dispatch_to_evm::<T>)?;
 
+		Pallet::<T>::force_set_sponsor(
+			contract_address,
+			&T::CrossAccountId::from_eth(contract_address),
+		)
+		.map_err(dispatch_to_evm::<T>)?;
+
 		Ok(())
 	}
 
modifiedpallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/lib.rs
+++ b/pallets/evm-contract-helpers/src/lib.rs
@@ -16,7 +16,7 @@
 
 #![doc = include_str!("../README.md")]
 #![cfg_attr(not(feature = "std"), no_std)]
-#![deny(missing_docs)]
+#![warn(missing_docs)]
 
 use codec::{Decode, Encode, MaxEncodedLen};
 pub use pallet::*;
@@ -27,18 +27,24 @@
 #[frame_support::pallet]
 pub mod pallet {
 	pub use super::*;
+	use crate::eth::ContractHelpersEvents;
 	use frame_support::pallet_prelude::*;
 	use pallet_evm_coder_substrate::DispatchResult;
 	use sp_core::H160;
-	use pallet_evm::account::CrossAccountId;
+	use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
 	use up_data_structs::SponsorshipState;
+	use evm_coder::ToLog;
 
 	#[pallet::config]
 	pub trait Config:
 		frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config
 	{
+		/// Overarching event type.
+		type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;
+
 		/// Address, under which magic contract will be available
 		type ContractAddress: Get<H160>;
+
 		/// In case of enabled sponsoring, but no sponsoring rate limit set,
 		/// this value will be used implicitly
 		type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;
@@ -150,6 +156,32 @@
 		QueryKind = ValueQuery,
 	>;
 
+	#[pallet::event]
+	#[pallet::generate_deposit(pub fn deposit_event)]
+	pub enum Event<T: Config> {
+		/// Contract sponsor was set.
+		ContractSponsorSet(
+			/// Contract address of the affected collection.
+			H160,
+			/// New sponsor address.
+			T::AccountId,
+		),
+
+		/// New sponsor was confirm.
+		ContractSponsorshipConfirmed(
+			/// Contract address of the affected collection.
+			H160,
+			/// New sponsor address.
+			T::AccountId,
+		),
+
+		/// Collection sponsor was removed.
+		ContractSponsorRemoved(
+			/// Contract address of the affected collection.
+			H160,
+		),
+	}
+
 	impl<T: Config> Pallet<T> {
 		/// Get contract owner.
 		pub fn contract_owner(contract: H160) -> H160 {
@@ -169,43 +201,118 @@
 				contract,
 				SponsorshipState::<T::CrossAccountId>::Unconfirmed(sponsor.clone()),
 			);
+
+			<Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(
+				contract,
+				sponsor.as_sub().clone(),
+			));
+			<PalletEvm<T>>::deposit_log(
+				ContractHelpersEvents::ContractSponsorSet {
+					contract_address: contract,
+					sponsor: *sponsor.as_eth(),
+				}
+				.to_log(contract),
+			);
 			Ok(())
 		}
 
-		/// Set `contract` as self sponsored.
+		/// TO-DO
 		///
-		/// `sender` must be owner of contract.
-		pub fn self_sponsored_enable(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {
-			Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;
+		///
+		pub fn force_set_sponsor(
+			contract_address: H160,
+			sponsor: &T::CrossAccountId,
+		) -> DispatchResult {
 			Sponsoring::<T>::insert(
-				contract,
-				SponsorshipState::<T::CrossAccountId>::Confirmed(T::CrossAccountId::from_eth(
-					contract,
-				)),
+				contract_address,
+				SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor.clone()),
 			);
+
+			let eth_sponsor = *sponsor.as_eth();
+			let sub_sponsor = sponsor.as_sub().clone();
+
+			<Pallet<T>>::deposit_event(Event::<T>::ContractSponsorSet(
+				contract_address,
+				sub_sponsor.clone(),
+			));
+			<PalletEvm<T>>::deposit_log(
+				ContractHelpersEvents::ContractSponsorSet {
+					contract_address,
+					sponsor: eth_sponsor,
+				}
+				.to_log(contract_address),
+			);
+
+			<Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(
+				contract_address,
+				sub_sponsor,
+			));
+			<PalletEvm<T>>::deposit_log(
+				ContractHelpersEvents::ContractSponsorshipConfirmed {
+					contract_address,
+					sponsor: eth_sponsor,
+				}
+				.to_log(contract_address),
+			);
+
 			Ok(())
 		}
 
 		/// Remove sponsor for `contract`.
 		///
 		/// `sender` must be owner of contract.
-		pub fn remove_sponsor(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {
-			Pallet::<T>::ensure_owner(contract, *sender.as_eth())?;
-			Sponsoring::<T>::remove(contract);
+		pub fn remove_sponsor(
+			sender: &T::CrossAccountId,
+			contract_address: H160,
+		) -> DispatchResult {
+			Self::ensure_owner(contract_address, *sender.as_eth())?;
+			Self::force_remove_sponsor(contract_address)
+		}
+
+		/// TO-DO
+		///
+		///
+		pub fn force_remove_sponsor(contract_address: H160) -> DispatchResult {
+			Sponsoring::<T>::remove(contract_address);
+
+			Self::deposit_event(Event::<T>::ContractSponsorRemoved(contract_address));
+			<PalletEvm<T>>::deposit_log(
+				ContractHelpersEvents::ContractSponsorRemoved { contract_address }
+					.to_log(contract_address),
+			);
+
 			Ok(())
 		}
 
 		/// Confirm sponsorship.
 		///
 		/// `sender` must be same that set via [`set_sponsor`].
-		pub fn confirm_sponsorship(sender: &T::CrossAccountId, contract: H160) -> DispatchResult {
-			match Sponsoring::<T>::get(contract) {
+		pub fn confirm_sponsorship(
+			sender: &T::CrossAccountId,
+			contract_address: H160,
+		) -> DispatchResult {
+			match Sponsoring::<T>::get(contract_address) {
 				SponsorshipState::Unconfirmed(sponsor) => {
 					ensure!(sponsor == *sender, Error::<T>::NoPermission);
+					let eth_sponsor = *sponsor.as_eth();
+					let sub_sponsor = sponsor.as_sub().clone();
 					Sponsoring::<T>::insert(
-						contract,
+						contract_address,
 						SponsorshipState::<T::CrossAccountId>::Confirmed(sponsor),
 					);
+
+					<Pallet<T>>::deposit_event(Event::<T>::ContractSponsorshipConfirmed(
+						contract_address,
+						sub_sponsor,
+					));
+					<PalletEvm<T>>::deposit_log(
+						ContractHelpersEvents::ContractSponsorshipConfirmed {
+							contract_address,
+							sponsor: eth_sponsor,
+						}
+						.to_log(contract_address),
+					);
+
 					Ok(())
 				}
 				SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => {
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
+++ b/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
@@ -21,9 +21,19 @@
 	}
 }
 
+/// @dev inlined interface
+contract ContractHelpersEvents {
+	event ContractSponsorSet(address indexed contractAddress, address sponsor);
+	event ContractSponsorshipConfirmed(
+		address indexed contractAddress,
+		address sponsor
+	);
+	event ContractSponsorRemoved(address indexed contractAddress);
+}
+
 /// @title Magic contract, which allows users to reconfigure other contracts
 /// @dev the ERC-165 identifier for this interface is 0xd77fab70
-contract ContractHelpers is Dummy, ERC165 {
+contract ContractHelpers is Dummy, ERC165, ContractHelpersEvents {
 	/// Get user, which deployed specified contract
 	/// @dev May return zero address in case if contract is deployed
 	///  using uniquenetwork evm-migration pallet, or using other terms not
modifiedpallets/unique/CHANGELOG.mddiffbeforeafterboth
--- a/pallets/unique/CHANGELOG.md
+++ b/pallets/unique/CHANGELOG.md
@@ -3,22 +3,29 @@
 All notable changes to this project will be documented in this file.
 
 <!-- bureaucrate goes here -->
+
+## [v0.1.4] 2022-09-5
+
+### Added
+
+-   Methods `force_set_sponsor` , `force_remove_collection_sponsor` to be able to administer sponsorships with other pallets. Added to implement `AppPromotion` pallet logic.
+
 ## [v0.1.3] 2022-08-16
 
 ### Other changes
 
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
+-   build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
 
-- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
+-   build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
 
-- refactor: Remove `#[transactional]` from extrinsics 7fd36cea2f6e00c02c67ccc1de9649ae404efd31
+-   refactor: Remove `#[transactional]` from extrinsics 7fd36cea2f6e00c02c67ccc1de9649ae404efd31
 
 Every extrinsic now runs in transaction implicitly, and
 `#[transactional]` on pallet dispatchable is now meaningless
 
 Upstream-Change: https://github.com/paritytech/substrate/issues/10806
 
-- refactor: Switch to new prefix removal methods 26734e9567589d75cdd99e404eabf11d5a97d975
+-   refactor: Switch to new prefix removal methods 26734e9567589d75cdd99e404eabf11d5a97d975
 
 New methods allows to call `remove_prefix` with limit multiple times
 in the same block
@@ -27,10 +34,12 @@
 
 Upstream-Change: https://github.com/paritytech/substrate/pull/11490
 
-- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
+-   build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
 
 ## [v0.1.1] - 2022-07-25
+
 ### Added
-- Method for creating `ERC721Metadata` compatible NFT collection.
-- Method for creating `ERC721Metadata` compatible ReFungible collection.
-- Method for creating ReFungible collection.
+
+-   Method for creating `ERC721Metadata` compatible NFT collection.
+-   Method for creating `ERC721Metadata` compatible ReFungible collection.
+-   Method for creating ReFungible collection.
modifiedpallets/unique/Cargo.tomldiffbeforeafterboth
--- a/pallets/unique/Cargo.toml
+++ b/pallets/unique/Cargo.toml
@@ -9,7 +9,7 @@
 license = 'GPLv3'
 name = 'pallet-unique'
 repository = 'https://github.com/UniqueNetwork/unique-chain'
-version = "0.1.3"
+version = "0.1.4"
 
 [package.metadata.docs.rs]
 targets = ['x86_64-unknown-linux-gnu']
modifiedpallets/unique/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/unique/src/benchmarking.rs
+++ b/pallets/unique/src/benchmarking.rs
@@ -46,7 +46,9 @@
 	)?;
 	Ok(<pallet_common::CreatedCollectionCount<T>>::get())
 }
-fn create_nft_collection<T: Config>(owner: T::AccountId) -> Result<CollectionId, DispatchError> {
+pub fn create_nft_collection<T: Config>(
+	owner: T::AccountId,
+) -> Result<CollectionId, DispatchError> {
 	create_collection_helper::<T>(owner, CollectionMode::NFT)
 }
 
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -98,7 +98,7 @@
 pub mod eth;
 
 #[cfg(feature = "runtime-benchmarks")]
-mod benchmarking;
+pub mod benchmarking;
 pub mod weights;
 use weights::WeightInfo;
 
@@ -277,7 +277,7 @@
 	{
 		type Error = Error<T>;
 
-		fn deposit_event() = default;
+		pub fn deposit_event() = default;
 
 		fn on_initialize(_now: T::BlockNumber) -> Weight {
 			0
@@ -1103,3 +1103,35 @@
 		}
 	}
 }
+
+impl<T: Config> Pallet<T> {
+	pub fn force_set_sponsor(sponsor: T::AccountId, collection_id: CollectionId) -> DispatchResult {
+		let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+		target_collection.check_is_internal()?;
+		target_collection.set_sponsor(sponsor.clone())?;
+
+		Self::deposit_event(Event::<T>::CollectionSponsorSet(
+			collection_id,
+			sponsor.clone(),
+		));
+
+		ensure!(
+			target_collection.confirm_sponsorship(&sponsor)?,
+			Error::<T>::ConfirmUnsetSponsorFail
+		);
+
+		Self::deposit_event(Event::<T>::SponsorshipConfirmed(collection_id, sponsor));
+
+		target_collection.save()
+	}
+
+	pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {
+		let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
+		target_collection.check_is_internal()?;
+		target_collection.sponsorship = SponsorshipState::Disabled;
+
+		Self::deposit_event(Event::<T>::CollectionSponsorRemoved(collection_id));
+
+		target_collection.save()
+	}
+}
addedprimitives/app_promotion_rpc/CHANGELOG.mddiffbeforeafterboth
--- /dev/null
+++ b/primitives/app_promotion_rpc/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+
+<!-- bureaucrate goes here -->
addedprimitives/app_promotion_rpc/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/primitives/app_promotion_rpc/Cargo.toml
@@ -0,0 +1,29 @@
+[package]
+name = "app-promotion-rpc"
+version = "0.1.0"
+license = "GPLv3"
+edition = "2021"
+
+[dependencies]
+pallet-common = { default-features = false, path = '../../pallets/common' }
+up-data-structs = { default-features = false, path = '../data-structs' }
+codec = { package = "parity-scale-codec", version = "3.1.2", default-features = false, features = [
+	"derive",
+] }
+sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+
+[features]
+default = ["std"]
+std = [
+	"codec/std",
+	"sp-core/std",
+	"sp-std/std",
+	"sp-api/std",
+	"sp-runtime/std",
+	"pallet-common/std",
+	"up-data-structs/std",
+]
addedprimitives/app_promotion_rpc/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/primitives/app_promotion_rpc/src/lib.rs
@@ -0,0 +1,41 @@
+// 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_std::vec::Vec;
+use codec::Decode;
+use sp_runtime::{
+	DispatchError,
+	traits::{AtLeast32BitUnsigned, Member},
+};
+
+type Result<T> = core::result::Result<T, DispatchError>;
+
+sp_api::decl_runtime_apis! {
+	#[api_version(2)]
+	/// Trait for generate rpc.
+	pub trait AppPromotionApi<BlockNumber ,CrossAccountId, AccountId> where
+		BlockNumber: Decode + Member + AtLeast32BitUnsigned,
+		AccountId: Decode,
+		CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,
+	{
+		fn total_staked(staker: Option<CrossAccountId>) -> Result<u128>;
+		fn total_staked_per_block(staker: CrossAccountId) -> Result<Vec<(BlockNumber, u128)>>;
+		fn pending_unstake(staker: Option<CrossAccountId>) -> Result<u128>;
+		fn pending_unstake_per_block(staker: CrossAccountId) -> Result<Vec<(BlockNumber, u128)>>;
+	}
+}
modifiedprimitives/common/src/constants.rsdiffbeforeafterboth
--- a/primitives/common/src/constants.rs
+++ b/primitives/common/src/constants.rs
@@ -22,6 +22,7 @@
 use crate::types::{BlockNumber, Balance};
 
 pub const MILLISECS_PER_BLOCK: u64 = 12000;
+pub const MILLISECS_PER_RELAY_BLOCK: u64 = 6000;
 
 pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
 
@@ -30,6 +31,11 @@
 pub const HOURS: BlockNumber = MINUTES * 60;
 pub const DAYS: BlockNumber = HOURS * 24;
 
+// These time units are defined in number of relay blocks.
+pub const RELAY_MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_RELAY_BLOCK as BlockNumber);
+pub const RELAY_HOURS: BlockNumber = RELAY_MINUTES * 60;
+pub const RELAY_DAYS: BlockNumber = RELAY_HOURS * 24;
+
 pub const MICROUNIQUE: Balance = 1_000_000_000_000;
 pub const MILLIUNIQUE: Balance = 1_000 * MICROUNIQUE;
 pub const CENTIUNIQUE: Balance = 10 * MILLIUNIQUE;
modifiedprimitives/rpc/src/lib.rsdiffbeforeafterboth
--- a/primitives/rpc/src/lib.rs
+++ b/primitives/rpc/src/lib.rs
@@ -20,9 +20,13 @@
 	CollectionId, TokenId, RpcCollection, CollectionStats, CollectionLimits, Property,
 	PropertyKeyPermission, TokenData, TokenChild,
 };
+
 use sp_std::vec::Vec;
 use codec::Decode;
-use sp_runtime::DispatchError;
+use sp_runtime::{
+	DispatchError,
+	traits::{AtLeast32BitUnsigned, Member},
+};
 
 type Result<T> = core::result::Result<T, DispatchError>;
 
@@ -120,6 +124,7 @@
 
 		/// Get total pieces of token.
 		fn total_pieces(collection_id: CollectionId, token_id: TokenId) -> Result<Option<u128>>;
+
 		fn token_owners(collection: CollectionId, token: TokenId) -> Result<Vec<CrossAccountId>>;
 	}
 }
modifiedruntime/common/config/ethereum.rsdiffbeforeafterboth
--- a/runtime/common/config/ethereum.rs
+++ b/runtime/common/config/ethereum.rs
@@ -112,6 +112,7 @@
 }
 
 impl pallet_evm_contract_helpers::Config for Runtime {
+	type Event = Event;
 	type ContractAddress = HelpersContractAddress;
 	type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
 }
addedruntime/common/config/pallets/app_promotion.rsdiffbeforeafterboth
--- /dev/null
+++ b/runtime/common/config/pallets/app_promotion.rs
@@ -0,0 +1,63 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+use crate::{
+	runtime_common::config::pallets::{TreasuryAccountId, RelayChainBlockNumberProvider},
+	Runtime, Balances, BlockNumber, Unique, Event, EvmContractHelpers,
+};
+
+use frame_support::{parameter_types, PalletId};
+use sp_arithmetic::Perbill;
+use up_common::{
+	constants::{UNIQUE, RELAY_DAYS},
+	types::Balance,
+};
+
+#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))]
+parameter_types! {
+	pub const AppPromotionId: PalletId = PalletId(*b"appstake");
+	pub const RecalculationInterval: BlockNumber = 20;
+	pub const PendingInterval: BlockNumber = 10;
+	pub const Nominal: Balance = UNIQUE;
+	// pub const Day: BlockNumber = DAYS;
+	pub IntervalIncome: Perbill = Perbill::from_rational(RecalculationInterval::get(), RELAY_DAYS) * Perbill::from_rational(5u32, 10_000);
+}
+
+#[cfg(any(feature = "unique-runtime", feature = "quartz-runtime"))]
+parameter_types! {
+	pub const AppPromotionId: PalletId = PalletId(*b"appstake");
+	pub const RecalculationInterval: BlockNumber = RELAY_DAYS;
+	pub const PendingInterval: BlockNumber = 7 * RELAY_DAYS;
+	pub const Nominal: Balance = UNIQUE;
+	// pub const Day: BlockNumber = RELAY_DAYS;
+	pub IntervalIncome: Perbill = Perbill::from_rational(5u32, 10_000);
+}
+
+impl pallet_app_promotion::Config for Runtime {
+	type PalletId = AppPromotionId;
+	type CollectionHandler = Unique;
+	type ContractHandler = EvmContractHelpers;
+	type Currency = Balances;
+	type WeightInfo = pallet_app_promotion::weights::SubstrateWeight<Self>;
+	type TreasuryAccountId = TreasuryAccountId;
+	type RelayBlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
+	type RecalculationInterval = RecalculationInterval;
+	type PendingInterval = PendingInterval;
+	// type Day = Day;
+	type Nominal = Nominal;
+	type IntervalIncome = IntervalIncome;
+	type Event = Event;
+}
modifiedruntime/common/config/pallets/mod.rsdiffbeforeafterboth
--- a/runtime/common/config/pallets/mod.rs
+++ b/runtime/common/config/pallets/mod.rs
@@ -40,6 +40,9 @@
 #[cfg(feature = "scheduler")]
 pub mod scheduler;
 
+#[cfg(feature = "app-promotion")]
+pub mod app_promotion;
+
 parameter_types! {
 	pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();
 	pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
modifiedruntime/common/construct_runtime/mod.rsdiffbeforeafterboth
--- a/runtime/common/construct_runtime/mod.rs
+++ b/runtime/common/construct_runtime/mod.rs
@@ -77,12 +77,15 @@
                 #[runtimes(opal)]
                 RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,
 
+                #[runtimes(opal)]
+                AppPromotion: pallet_app_promotion::{Pallet, Call, Storage, Event<T>} = 73,
+
                 // Frontier
                 EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,
                 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,
 
                 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,
-                EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,
+                EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage, Event<T>} = 151,
                 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,
                 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,
             }
modifiedruntime/common/runtime_apis.rsdiffbeforeafterboth
--- a/runtime/common/runtime_apis.rs
+++ b/runtime/common/runtime_apis.rs
@@ -189,6 +189,40 @@
                 }
             }
 
+            impl app_promotion_rpc::AppPromotionApi<Block, BlockNumber, CrossAccountId, AccountId> for Runtime {
+                fn total_staked(staker: Option<CrossAccountId>) -> Result<u128, DispatchError> {
+                    #[cfg(not(feature = "app-promotion"))]
+                    return unsupported!();
+
+                    #[cfg(feature = "app-promotion")]
+                    return Ok(<pallet_app_promotion::Pallet<Runtime>>::cross_id_total_staked(staker).unwrap_or_default());
+                }
+
+                fn total_staked_per_block(staker: CrossAccountId) -> Result<Vec<(BlockNumber, u128)>, DispatchError> {
+                    #[cfg(not(feature = "app-promotion"))]
+                    return unsupported!();
+
+                    #[cfg(feature = "app-promotion")]
+                    return Ok(<pallet_app_promotion::Pallet<Runtime>>::cross_id_total_staked_per_block(staker));
+                }
+
+                fn pending_unstake(staker: Option<CrossAccountId>) -> Result<u128, DispatchError> {
+                    #[cfg(not(feature = "app-promotion"))]
+                    return unsupported!();
+
+                    #[cfg(feature = "app-promotion")]
+                    return Ok(<pallet_app_promotion::Pallet<Runtime>>::cross_id_pending_unstake(staker));
+                }
+
+                fn pending_unstake_per_block(staker: CrossAccountId) -> Result<Vec<(BlockNumber, u128)>, DispatchError> {
+                    #[cfg(not(feature = "app-promotion"))]
+                    return unsupported!();
+
+                    #[cfg(feature = "app-promotion")]
+                    return Ok(<pallet_app_promotion::Pallet<Runtime>>::cross_id_pending_unstake_per_block(staker))
+                }
+            }
+
             impl rmrk_rpc::RmrkApi<
                 Block,
                 AccountId,
@@ -638,6 +672,7 @@
                     list_benchmark!(list, extra, pallet_unique, Unique);
                     list_benchmark!(list, extra, pallet_structure, Structure);
                     list_benchmark!(list, extra, pallet_inflation, Inflation);
+                    list_benchmark!(list, extra, pallet_app_promotion, AppPromotion);
                     list_benchmark!(list, extra, pallet_fungible, Fungible);
                     list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);
 
@@ -693,6 +728,7 @@
                     add_benchmark!(params, batches, pallet_unique, Unique);
                     add_benchmark!(params, batches, pallet_structure, Structure);
                     add_benchmark!(params, batches, pallet_inflation, Inflation);
+                    add_benchmark!(params, batches, pallet_app_promotion, AppPromotion);
                     add_benchmark!(params, batches, pallet_fungible, Fungible);
                     add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);
 
modifiedruntime/opal/Cargo.tomldiffbeforeafterboth
--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -37,6 +37,7 @@
     'pallet-proxy-rmrk-equip/runtime-benchmarks',
     'pallet-unique/runtime-benchmarks',
     'pallet-inflation/runtime-benchmarks',
+    'pallet-app-promotion/runtime-benchmarks',
     'pallet-unique-scheduler/runtime-benchmarks',
     'pallet-xcm/runtime-benchmarks',
     'sp-runtime/runtime-benchmarks',
@@ -82,12 +83,14 @@
     'pallet-base-fee/std',
     'fp-rpc/std',
     'up-rpc/std',
+    'app-promotion-rpc/std',
     'fp-evm-mapping/std',
     'fp-self-contained/std',
     'parachain-info/std',
     'serde',
     'pallet-inflation/std',
     'pallet-configuration/std',
+    'pallet-app-promotion/std',
     'pallet-common/std',
     'pallet-structure/std',
     'pallet-fungible/std',
@@ -122,11 +125,12 @@
     "orml-vesting/std",
 ]
 limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
-opal-runtime = ['refungible', 'scheduler', 'rmrk']
+opal-runtime = ['refungible', 'scheduler', 'rmrk', 'app-promotion']
 
 refungible = []
 scheduler = []
 rmrk = []
+app-promotion = []
 
 ################################################################################
 # Substrate Dependencies
@@ -411,9 +415,11 @@
 derivative = "2.2.0"
 pallet-unique = { path = '../../pallets/unique', default-features = false }
 up-rpc = { path = "../../primitives/rpc", default-features = false }
+app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}
 rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }
 fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
 pallet-inflation = { path = '../../pallets/inflation', default-features = false }
+pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
 up-data-structs = { path = '../../primitives/data-structs', default-features = false }
 pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
 pallet-common = { default-features = false, path = "../../pallets/common" }
modifiedruntime/quartz/Cargo.tomldiffbeforeafterboth
--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -82,6 +82,7 @@
     'pallet-base-fee/std',
     'fp-rpc/std',
     'up-rpc/std',
+    'app-promotion-rpc/std',
     'fp-evm-mapping/std',
     'fp-self-contained/std',
     'parachain-info/std',
@@ -416,8 +417,10 @@
 derivative = "2.2.0"
 pallet-unique = { path = '../../pallets/unique', default-features = false }
 up-rpc = { path = "../../primitives/rpc", default-features = false }
+app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}
 fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
 pallet-inflation = { path = '../../pallets/inflation', default-features = false }
+pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
 up-data-structs = { path = '../../primitives/data-structs', default-features = false }
 pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
 pallet-common = { default-features = false, path = "../../pallets/common" }
modifiedruntime/unique/Cargo.tomldiffbeforeafterboth
--- a/runtime/unique/Cargo.toml
+++ b/runtime/unique/Cargo.toml
@@ -83,6 +83,7 @@
     'pallet-base-fee/std',
     'fp-rpc/std',
     'up-rpc/std',
+    'app-promotion-rpc/std',
     'fp-evm-mapping/std',
     'fp-self-contained/std',
     'parachain-info/std',
@@ -409,8 +410,10 @@
 derivative = "2.2.0"
 pallet-unique = { path = '../../pallets/unique', default-features = false }
 up-rpc = { path = "../../primitives/rpc", default-features = false }
+app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}
 rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }
 pallet-inflation = { path = '../../pallets/inflation', default-features = false }
+pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
 up-data-structs = { path = '../../primitives/data-structs', default-features = false }
 pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
 pallet-common = { default-features = false, path = "../../pallets/common" }
modifiedtests/package.jsondiffbeforeafterboth
--- a/tests/package.json
+++ b/tests/package.json
@@ -30,6 +30,7 @@
     "testEth": "mocha --timeout 9999999 -r ts-node/register './**/eth/**/*.test.ts'",
     "testEthMarketplace": "mocha --timeout 9999999 -r ts-node/register './**/eth/marketplace/**/*.test.ts'",
     "testEthNesting": "mocha --timeout 9999999 -r ts-node/register './**/eth/nesting/**/*.test.ts'",
+    "testEthPayable": "mocha --timeout 9999999 -r ts-node/register './**/eth/payable.test.ts'",
     "load": "mocha --timeout 9999999 -r ts-node/register './**/*.load.ts'",
     "loadTransfer": "ts-node src/transfer.nload.ts",
     "testCollision": "mocha --timeout 9999999 -r ts-node/register ./src/collision-tests/*.test.ts",
@@ -64,6 +65,7 @@
     "testBurnItem": "mocha --timeout 9999999 -r ts-node/register ./**/burnItem.test.ts",
     "testAdminTransferAndBurn": "mocha --timeout 9999999 -r ts-node/register ./**/adminTransferAndBurn.test.ts",
     "testSetMintPermission": "mocha --timeout 9999999 -r ts-node/register ./**/setMintPermission.test.ts",
+    "testSetPublicAccessMode": "mocha --timeout 9999999 -r ts-node/register ./**/setPublicAccessMode.test.ts",
     "testCreditFeesToTreasury": "mocha --timeout 9999999 -r ts-node/register ./**/creditFeesToTreasury.test.ts",
     "testContractSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/contractSponsoring.test.ts",
     "testEnableContractSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/enableContractSponsoring.test.ts",
@@ -71,7 +73,6 @@
     "testSetContractSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setContractSponsoringRateLimit.test.ts",
     "testSetOffchainSchema": "mocha --timeout 9999999 -r ts-node/register ./**/setOffchainSchema.test.ts",
     "testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts",
-    "testSetVariableMetadataSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetadataSponsoringRateLimit.test.ts",
     "testInflation": "mocha --timeout 9999999 -r ts-node/register ./**/inflation.test.ts",
     "testScheduler": "mocha --timeout 9999999 -r ts-node/register ./**/scheduler.test.ts",
     "testSchedulingEVM": "mocha --timeout 9999999 -r ts-node/register ./**/eth/scheduling.test.ts",
@@ -80,10 +81,12 @@
     "testBlockProduction": "mocha --timeout 9999999 -r ts-node/register ./**/block-production.test.ts",
     "testEnableDisableTransfers": "mocha --timeout 9999999 -r ts-node/register ./**/enableDisableTransfer.test.ts",
     "testLimits": "mocha --timeout 9999999 -r ts-node/register ./**/limits.test.ts",
-    "testEthCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createCollection.test.ts",
+    "testEthCreateNFTCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createNFTCollection.test.ts",
+    "testEthCreateRFTCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createRFTCollection.test.ts",
     "testRFT": "mocha --timeout 9999999 -r ts-node/register ./**/refungible.test.ts",
     "testFT": "mocha --timeout 9999999 -r ts-node/register ./**/fungible.test.ts",
     "testRPC": "mocha --timeout 9999999 -r ts-node/register ./**/rpc.test.ts",
+    "testPromotion": "mocha --timeout 9999999 -r ts-node/register ./**/app-promotion.test.ts",
     "polkadot-types-fetch-metadata": "curl -H 'Content-Type: application/json' -d '{\"id\":\"1\", \"jsonrpc\":\"2.0\", \"method\": \"state_getMetadata\", \"params\":[]}' http://localhost:9933 > src/interfaces/metadata.json",
     "polkadot-types-from-defs": "ts-node ./node_modules/.bin/polkadot-types-from-defs --endpoint src/interfaces/metadata.json --input src/interfaces/ --package .",
     "polkadot-types-from-chain": "ts-node ./node_modules/.bin/polkadot-types-from-chain --endpoint src/interfaces/metadata.json --output src/interfaces/ --package .",
addedtests/src/app-promotion.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/app-promotion.test.ts
@@ -0,0 +1,800 @@
+// 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/>.
+
+import {IKeyringPair} from '@polkadot/types/types';
+import {
+  normalizeAccountId,
+  getModuleNames,
+  Pallets,
+} from './util/helpers';
+
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import {usingPlaygrounds} from './util/playgrounds';
+
+import {encodeAddress} from '@polkadot/util-crypto';
+import {stringToU8a} from '@polkadot/util';
+import {SponsoringMode, contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3, transferBalanceToEth} from './eth/util/helpers';
+import {DevUniqueHelper} from './util/playgrounds/unique.dev';
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+let alice: IKeyringPair;
+let palletAdmin: IKeyringPair;
+let nominal: bigint;
+const palletAddress = calculatePalleteAddress('appstake');
+let accounts: IKeyringPair[] = [];
+const LOCKING_PERIOD = 20n; // 20 blocks of relay
+const UNLOCKING_PERIOD = 10n; // 20 blocks of parachain
+const rewardAvailableInBlock = (stakedInBlock: bigint) => (stakedInBlock - stakedInBlock % LOCKING_PERIOD) + (LOCKING_PERIOD * 2n);
+
+const beforeEach = async (context: Mocha.Context) => {
+  await usingPlaygrounds(async (helper, privateKey) => {
+    if (!getModuleNames(helper.api!).includes(Pallets.AppPromotion)) context.skip();
+    alice = privateKey('//Alice');
+    palletAdmin = privateKey('//Charlie'); // TODO use custom address
+    await helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})));
+    nominal = helper.balance.getOneTokenNominal();
+    await helper.balance.transferToSubstrate(alice, palletAdmin.address, 1000n * nominal);
+    await helper.balance.transferToSubstrate(alice, palletAddress, 1000n * nominal);
+    accounts = await helper.arrange.createCrowd(100, 1000n, alice); // create accounts-pool to speed up tests
+  });
+};
+
+describe('app-promotions.stake extrinsic', () => {
+  before(async function () {
+    await beforeEach(this);
+  });
+
+  it('should "lock" staking balance, add it to "staked" map, and increase "totalStaked" amount', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const [staker, recepient] = [accounts.pop()!, accounts.pop()!];
+      const totalStakedBefore = await helper.staking.getTotalStaked();
+
+      // Minimum stake amount is 100:
+      await expect(helper.staking.stake(staker, 100n * nominal - 1n)).to.be.eventually.rejected;
+      await helper.staking.stake(staker, 100n * nominal);
+
+      // Staker balance is: miscFrozen: 100, feeFrozen: 100, reserved: 0n...
+      // ...so he can not transfer 900
+      expect (await helper.balance.getSubstrateFull(staker.address)).to.contain({miscFrozen: 100n * nominal, feeFrozen: 100n * nominal, reserved: 0n});
+      await expect(helper.balance.transferToSubstrate(staker, recepient.address, 900n * nominal)).to.be.rejected;
+      
+      expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(100n * nominal);
+      expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);
+      // it is potentially flaky test. Promotion can credited some tokens. Maybe we need to use closeTo? 
+      expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore + 100n * nominal); // total tokens amount staked in app-promotion increased 
+
+      
+      await helper.staking.stake(staker, 200n * nominal);
+      expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(300n * nominal);
+      expect((await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map((x) => x[1])).to.be.deep.equal([100n * nominal, 200n * nominal]);
+    });
+  });
+
+  it('should allow to create maximum 10 stakes for account', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const [staker] = await helper.arrange.createAccounts([2000n], alice);
+      for (let i = 0; i < 10; i++) {
+        await helper.staking.stake(staker, 100n * nominal);
+      }
+
+      // can have 10 stakes
+      expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(1000n * nominal);
+      expect(await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).to.have.length(10);
+
+      await expect(helper.staking.stake(staker, 100n * nominal)).to.be.rejected;
+
+      // After unstake can stake again
+      await helper.staking.unstake(staker);
+      await helper.staking.stake(staker, 100n * nominal);
+      expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.equal(100n * nominal);
+    });
+  });
+  
+  it('should reject transaction if stake amount is more than total free balance minus frozen', async () => {
+    await usingPlaygrounds(async helper => { 
+      const staker = accounts.pop()!;
+
+      // Can't stake full balance because Alice needs to pay some fee
+      await expect(helper.staking.stake(staker, 1000n * nominal)).to.be.eventually.rejected;
+      await helper.staking.stake(staker, 500n * nominal);
+
+      // Can't stake 500 tkn because Alice has Less than 500 transferable;
+      await expect(helper.staking.stake(staker, 500n * nominal)).to.be.eventually.rejected; 
+      expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(500n * nominal);
+    });
+  });
+  
+  it('for different accounts in one block is possible', async () => {
+    await usingPlaygrounds(async helper => {
+      const crowd = [accounts.pop()!, accounts.pop()!, accounts.pop()!, accounts.pop()!];
+      
+      const crowdStartsToStake = crowd.map(user => helper.staking.stake(user, 100n * nominal));
+      await expect(Promise.all(crowdStartsToStake)).to.be.eventually.fulfilled;
+
+      const crowdStakes = await Promise.all(crowd.map(address => helper.staking.getTotalStaked({Substrate: address.address})));
+      expect(crowdStakes).to.deep.equal([100n * nominal, 100n * nominal, 100n * nominal, 100n * nominal]);
+    });
+  });
+});
+
+describe('unstake balance extrinsic', () => {  
+  before(async function () {
+    await beforeEach(this);
+  });
+
+  it('should change balance state from "frozen" to "reserved", add it to "pendingUnstake" map, and subtract it from totalStaked', async () => {
+    await usingPlaygrounds(async helper => {
+      const [staker, recepient] = [accounts.pop()!, accounts.pop()!];
+      const totalStakedBefore = await helper.staking.getTotalStaked();
+      await helper.staking.stake(staker, 900n * nominal);
+      await helper.staking.unstake(staker);
+
+      // Right after unstake balance is reserved
+      // Staker can not transfer 
+      expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 900n * nominal, miscFrozen: 0n, feeFrozen: 0n});
+      await expect(helper.balance.transferToSubstrate(staker, recepient.address, 100n * nominal)).to.be.rejected;
+      expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(900n * nominal);
+      expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n);
+      expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore);
+    });
+  });
+
+  it('should unlock balance after unlocking period ends and remove it from "pendingUnstake"', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const staker = accounts.pop()!;
+      await helper.staking.stake(staker, 100n * nominal);
+      await helper.staking.unstake(staker);
+      const unstakedInBlock = (await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address}))[0][0];
+
+      // Wait for unstaking period. Balance now free ~1000; reserved, frozen, miscFrozeb: 0n
+      await helper.wait.forParachainBlockNumber(unstakedInBlock);
+      expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, miscFrozen: 0n, feeFrozen: 0n});
+      expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);
+
+      // staker can transfer:
+      await helper.balance.transferToSubstrate(staker, alice.address, 998n * nominal);
+      expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(1n);
+    });
+  });
+
+  it('should successfully unstake multiple stakes', async () => {
+    await usingPlaygrounds(async helper => {
+      const staker = accounts.pop()!;
+      await helper.staking.stake(staker, 100n * nominal);
+      await helper.staking.stake(staker, 200n * nominal);
+      await helper.staking.stake(staker, 300n * nominal);
+
+      // staked: [100, 200, 300]; unstaked: 0
+      let pendingUnstake = await helper.staking.getPendingUnstake({Substrate: staker.address});
+      let unstakedPerBlock = (await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address})).map(stake => stake[1]);
+      let stakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(stake => stake[1]);
+      expect(pendingUnstake).to.be.deep.equal(0n);
+      expect(unstakedPerBlock).to.be.deep.equal([]);
+      expect(stakedPerBlock).to.be.deep.equal([100n * nominal, 200n * nominal, 300n * nominal]);
+     
+      // Can unstake multiple stakes
+      await helper.staking.unstake(staker);
+      const unstakingBlock = (await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address}))[0][0];
+      pendingUnstake = await helper.staking.getPendingUnstake({Substrate: staker.address});
+      unstakedPerBlock = (await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address})).map(stake => stake[1]);
+      stakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(stake => stake[1]);
+      expect(pendingUnstake).to.be.equal(600n * nominal);
+      expect(stakedPerBlock).to.be.deep.equal([]);
+      expect(unstakedPerBlock).to.be.deep.equal([600n * nominal]);
+
+      expect (await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 600n * nominal, feeFrozen: 0n, miscFrozen: 0n});
+      await helper.wait.forParachainBlockNumber(unstakingBlock);
+      expect (await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, feeFrozen: 0n, miscFrozen: 0n});
+      expect (await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);
+    });
+  });
+
+  it('should not have any effects if no active stakes', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const staker = accounts.pop()!;
+      
+      // unstake has no effect if no stakes at all
+      await helper.staking.unstake(staker);
+      expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(0n);
+      expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n); // TODO bigint closeTo helper
+
+      // TODO stake() unstake() waitUnstaked() unstake();
+
+      // can't unstake if there are only pendingUnstakes
+      await helper.staking.stake(staker, 100n * nominal);
+      await helper.staking.unstake(staker);
+      await helper.staking.unstake(staker);
+
+      expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(100n * nominal);
+      expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n);
+    });
+  });
+
+  it('should keep different unlocking block for each unlocking stake', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const staker = accounts.pop()!;
+      await helper.staking.stake(staker, 100n * nominal);
+      await helper.staking.unstake(staker);
+      await helper.staking.stake(staker, 120n * nominal);
+      await helper.staking.unstake(staker);
+
+      const unstakingPerBlock = await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address});
+      expect(unstakingPerBlock).has.length(2);
+      expect(unstakingPerBlock[0][1]).to.equal(100n * nominal);
+      expect(unstakingPerBlock[1][1]).to.equal(120n * nominal);
+    });
+  });
+
+  it('should be possible for different accounts in one block', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const stakers = [accounts.pop()!, accounts.pop()!, accounts.pop()!];
+
+      await Promise.all(stakers.map(staker => helper.staking.stake(staker, 100n * nominal)));
+      await Promise.all(stakers.map(staker => helper.staking.unstake(staker)));
+
+      await Promise.all(stakers.map(async (staker) => {
+        expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(100n * nominal);
+        expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n);
+      }));
+    });
+  });
+});
+
+describe('Admin adress', () => {
+  before(async function () {
+    await beforeEach(this);
+  });
+
+  it('can be set by sudo only', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const nonAdmin = accounts.pop()!;
+      // nonAdmin can not set admin not from himself nor as a sudo
+      await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address}))).to.be.eventually.rejected;
+      await expect(helper.signTransaction(nonAdmin, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address})))).to.be.eventually.rejected;
+
+      // Alice can
+      await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})))).to.be.eventually.fulfilled;
+    });
+  });
+  
+  it('can be any valid CrossAccountId', async () => {
+    // We are not going to set an eth address as a sponsor,
+    // but we do want to check, it doesn't break anything;
+    await usingPlaygrounds(async (helper) => {
+      const account = accounts.pop()!;
+      const ethAccount = helper.address.substrateToEth(account.address); 
+      // Alice sets Ethereum address as a sudo. Then Substrate address back...
+      await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Ethereum: ethAccount})))).to.be.eventually.fulfilled;
+      await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})))).to.be.eventually.fulfilled;
+      
+      // ...It doesn't break anything;
+      const collection = await helper.nft.mintCollection(account, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
+      await expect(helper.signTransaction(account, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.rejected;
+    });
+  });
+
+  it('can be reassigned', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const [oldAdmin, newAdmin, collectionOwner] = [accounts.pop()!, accounts.pop()!, accounts.pop()!];
+      const collection  = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
+      
+      await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress(normalizeAccountId(oldAdmin))))).to.be.eventually.fulfilled;
+      await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress(normalizeAccountId(newAdmin))))).to.be.eventually.fulfilled;
+      await expect(helper.signTransaction(oldAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.rejected;
+      
+      await expect(helper.signTransaction(newAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.fulfilled;
+    });
+  });
+});
+
+describe('App-promotion collection sponsoring', () => {
+  before(async function () {
+    await beforeEach(this);
+    await usingPlaygrounds(async (helper) => {
+      const tx = helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address}));
+      await helper.signTransaction(alice, tx);
+    });
+  });
+
+  it('should actually sponsor transactions', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const [collectionOwner, tokenSender, receiver] = [accounts.pop()!, accounts.pop()!, accounts.pop()!];
+      const collection = await helper.nft.mintCollection(collectionOwner, {name: 'Name', description: 'Description', tokenPrefix: 'Prefix', limits: {sponsorTransferTimeout: 0}});
+      const token = await collection.mintToken(collectionOwner, {Substrate: tokenSender.address});
+      await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId));
+      const palletBalanceBefore = await helper.balance.getSubstrate(palletAddress);
+
+      await token.transfer(tokenSender, {Substrate: receiver.address});
+      expect (await token.getOwner()).to.be.deep.equal({Substrate: receiver.address});
+      const palletBalanceAfter = await helper.balance.getSubstrate(palletAddress);
+
+      // senders balance the same, transaction has sponsored
+      expect (await helper.balance.getSubstrate(tokenSender.address)).to.be.equal(1000n * nominal);
+      expect (palletBalanceBefore > palletBalanceAfter).to.be.true;
+    });
+  });
+
+  it('can not be set by non admin', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!];
+
+      const collection  = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
+      
+      await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.rejected;
+      expect((await collection.getData())?.raw.sponsorship).to.equal('Disabled');
+    });
+  });
+
+  it('should set pallet address as confirmed admin', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const [collectionOwner, oldSponsor] = [accounts.pop()!, accounts.pop()!];
+      
+      // Can set sponsoring for collection without sponsor
+      const collectionWithoutSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'No-sponsor', description: 'New Collection', tokenPrefix: 'Promotion'});
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithoutSponsor.collectionId))).to.be.eventually.fulfilled;
+      expect((await collectionWithoutSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});
+
+      // Can set sponsoring for collection with unconfirmed sponsor
+      const collectionWithUnconfirmedSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'Unconfirmed', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: oldSponsor.address});
+      expect((await collectionWithUnconfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Unconfirmed: oldSponsor.address});
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithUnconfirmedSponsor.collectionId))).to.be.eventually.fulfilled;
+      expect((await collectionWithUnconfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});
+
+      // Can set sponsoring for collection with confirmed sponsor
+      const collectionWithConfirmedSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'Confirmed', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: oldSponsor.address});
+      await collectionWithConfirmedSponsor.confirmSponsorship(oldSponsor);
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithConfirmedSponsor.collectionId))).to.be.eventually.fulfilled;
+      expect((await collectionWithConfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});
+    });
+  });
+
+  it('can be overwritten by collection owner', async () => {    
+    await usingPlaygrounds(async (helper) => {
+      const [collectionOwner, newSponsor] = [accounts.pop()!, accounts.pop()!];
+      const collection  = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
+      const collectionId = collection.collectionId;
+      
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionId))).to.be.eventually.fulfilled;
+      
+      // Collection limits still can be changed by the owner
+      expect(await collection.setLimits(collectionOwner, {sponsorTransferTimeout: 0})).to.be.true;
+      expect((await collection.getData())?.raw.limits.sponsorTransferTimeout).to.be.equal(0);
+      expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});
+
+      // Collection sponsor can be changed too
+      expect((await collection.setSponsor(collectionOwner, newSponsor.address))).to.be.true;
+      expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Unconfirmed: newSponsor.address});
+    });
+  });
+  
+  it('should not overwrite collection limits set by the owner earlier', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const limits = {ownerCanDestroy: true, ownerCanTransfer: true, sponsorTransferTimeout: 0};
+      const collectionWithLimits = await helper.nft.mintCollection(alice, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits});
+
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithLimits.collectionId))).to.be.eventually.fulfilled;
+      expect((await collectionWithLimits.getData())?.raw.limits).to.be.deep.contain(limits);
+    });
+  });
+  
+  it('should reject transaction if collection doesn\'t exist', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const collectionOwner = accounts.pop()!;
+      
+      // collection has never existed
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(999999999))).to.be.eventually.rejected;
+      // collection has been burned
+      const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
+      await collection.burn(collectionOwner);
+
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.rejected;
+    });
+  });
+});
+
+describe('app-promotion stopSponsoringCollection', () => {
+  before(async function () {
+    await beforeEach(this);
+  });
+
+  it('can not be called by non-admin', async () => {    
+    await usingPlaygrounds(async (helper) => {
+      const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!];
+      const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
+      
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.fulfilled;
+      
+      await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.eventually.rejected;
+      expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});
+    });
+  });
+
+  it('should set sponsoring as disabled', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const [collectionOwner, recepient] = [accounts.pop()!, accounts.pop()!];
+      const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits: {sponsorTransferTimeout: 0}});
+      const token = await collection.mintToken(collectionOwner, {Substrate: collectionOwner.address});
+      
+      await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId));
+      await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId));
+      
+      expect((await collection.getData())?.raw.sponsorship).to.be.equal('Disabled');
+
+      // Transactions are not sponsored anymore:
+      const ownerBalanceBefore = await helper.balance.getSubstrate(collectionOwner.address);
+      await token.transfer(collectionOwner, {Substrate: recepient.address});
+      const ownerBalanceAfter = await helper.balance.getSubstrate(collectionOwner.address);
+      expect(ownerBalanceAfter < ownerBalanceBefore).to.be.equal(true);
+    });
+  });
+
+  it('should not affect collection which is not sponsored by pallete', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const collectionOwner = accounts.pop()!;
+      const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: collectionOwner.address});
+      await collection.confirmSponsorship(collectionOwner);
+      
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.eventually.rejected;
+      
+      expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: collectionOwner.address});
+    });
+  });
+
+  it('should reject transaction if collection does not exist', async () => {    
+    await usingPlaygrounds(async (helper) => {
+      const collectionOwner = accounts.pop()!;
+      const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
+      
+      await collection.burn(collectionOwner);
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.eventually.rejected;
+      await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(999999999))).to.be.eventually.rejected;
+    });
+  });
+});
+
+describe('app-promotion contract sponsoring', () => {
+  before(async function () {
+    await beforeEach(this);
+  });
+
+  itWeb3('should set palletes address as a sponsor', async ({api, web3, privateKeyWrapper}) => {
+    await usingPlaygrounds(async (helper) => {
+      const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+      const flipper = await deployFlipper(web3, contractOwner);
+      const contractMethods = contractHelpers(web3, contractOwner);
+
+      await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address));
+      
+      expect(await contractMethods.methods.hasSponsor(flipper.options.address).call()).to.be.true;  
+      expect((await api.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner);  
+      expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({
+        confirmed: {
+          substrate: palletAddress,
+        },
+      });
+    });
+  });
+
+  itWeb3('should overwrite sponsoring mode and existed sponsor', async ({api, web3, privateKeyWrapper}) => {
+    await usingPlaygrounds(async (helper) => {
+      const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+      const flipper = await deployFlipper(web3, contractOwner);
+      const contractMethods = contractHelpers(web3, contractOwner);
+
+      await expect(contractMethods.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;
+
+      // Contract is self sponsored
+      expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.be.deep.equal({
+        confirmed: {
+          ethereum: flipper.options.address.toLowerCase(),
+        },
+      });
+
+      // set promotion sponsoring
+      await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address));
+
+      // new sponsor is pallet address
+      expect(await contractMethods.methods.hasSponsor(flipper.options.address).call()).to.be.true;  
+      expect((await api.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner);  
+      expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({
+        confirmed: {
+          substrate: palletAddress,
+        },
+      });
+    });
+  });
+
+  itWeb3('can be overwritten by contract owner', async ({api, web3, privateKeyWrapper}) => {
+    await usingPlaygrounds(async (helper) => {      
+      const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+      const flipper = await deployFlipper(web3, contractOwner);
+      const contractMethods = contractHelpers(web3, contractOwner);
+
+      // contract sponsored by pallet
+      await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address));
+
+      // owner sets self sponsoring
+      await expect(contractMethods.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;
+
+      expect(await contractMethods.methods.hasSponsor(flipper.options.address).call()).to.be.true;  
+      expect((await api.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner);  
+      expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({
+        confirmed: {
+          ethereum: flipper.options.address.toLowerCase(),
+        },
+      });
+    });
+  });
+
+  itWeb3('can not be set by non admin', async ({api, web3, privateKeyWrapper}) => {
+    await usingPlaygrounds(async (helper) => {      
+      const nonAdmin = accounts.pop()!;
+      const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+      const flipper = await deployFlipper(web3, contractOwner);
+      const contractMethods = contractHelpers(web3, contractOwner);
+
+      await expect(contractMethods.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;
+
+      // nonAdmin calls sponsorContract
+      await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address))).to.be.rejected;
+
+      // contract still self-sponsored 
+      expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({
+        confirmed: {
+          ethereum: flipper.options.address.toLowerCase(),
+        },
+      });
+    });
+
+    itWeb3('should be rejected for non-contract address', async ({api, web3, privateKeyWrapper}) => {
+      await usingPlaygrounds(async (helper) => {
+
+      });
+    });
+  });
+
+  itWeb3('should actually sponsor transactions', async ({api, web3, privateKeyWrapper}) => {
+    await usingPlaygrounds(async (helper) => {      
+      const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+      const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+      const flipper = await deployFlipper(web3, contractOwner);
+      const contractHelper = contractHelpers(web3, contractOwner);
+      await contractHelper.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: contractOwner});
+      await contractHelper.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: contractOwner});
+      await transferBalanceToEth(api, alice, flipper.options.address, 1000n);
+
+      await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address));
+      await flipper.methods.flip().send({from: caller});
+      expect(await flipper.methods.getValue().call()).to.be.true;
+
+      const callerBalance = await helper.balance.getEthereum(caller);
+      const contractBalanceAfter = await helper.balance.getEthereum(flipper.options.address);
+
+      expect(callerBalance).to.be.equal(1000n * nominal);
+      expect(1000n * nominal > contractBalanceAfter).to.be.true;
+    });
+  });
+});
+
+describe('app-promotion stopSponsoringContract', () => {  
+  before(async function () {
+    await beforeEach(this);
+  });
+
+  itWeb3('should remove pallet address from contract sponsors', async ({api, web3, privateKeyWrapper}) => {
+    await usingPlaygrounds(async (helper) => {      
+      const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+      const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+      const flipper = await deployFlipper(web3, contractOwner);
+      await transferBalanceToEth(api, alice, flipper.options.address);
+      const contractHelper = contractHelpers(web3, contractOwner);
+      await contractHelper.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: contractOwner});
+      await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address));
+      await helper.signTransaction(palletAdmin, api.tx.appPromotion.stopSponsoringContract(flipper.options.address));
+
+      expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.false;  
+      expect((await api.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner);  
+      expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({
+        disabled: null,
+      });
+
+      await flipper.methods.flip().send({from: caller});
+      expect(await flipper.methods.getValue().call()).to.be.true;
+
+      const callerBalance = await helper.balance.getEthereum(caller);
+      const contractBalanceAfter = await helper.balance.getEthereum(flipper.options.address);
+
+      // caller payed for call
+      expect(1000n * nominal > callerBalance).to.be.true;
+      expect(contractBalanceAfter).to.be.equal(1000n * nominal);
+    });
+  });
+
+  itWeb3('can not be called by non-admin', async ({api, web3, privateKeyWrapper}) => {
+    await usingPlaygrounds(async (helper) => {      
+      const nonAdmin = accounts.pop()!;
+      const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+      const flipper = await deployFlipper(web3, contractOwner);
+
+      await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address));
+      await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.stopSponsoringContract(flipper.options.address))).to.be.rejected;
+    });
+  });
+
+  itWeb3('should not affect a contract which is not sponsored by pallete', async ({api, web3, privateKeyWrapper}) => {
+    await usingPlaygrounds(async (helper) => {      
+      const nonAdmin = accounts.pop()!;
+      const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+      const flipper = await deployFlipper(web3, contractOwner);
+      const contractHelper = contractHelpers(web3, contractOwner);
+      await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;
+
+      await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.stopSponsoringContract(flipper.options.address))).to.be.rejected;
+    });
+  });
+});
+
+describe('app-promotion rewards', () => {
+  before(async function () {
+    await beforeEach(this);
+  });
+
+  it('can not be called by non admin', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const nonAdmin = accounts.pop()!;
+      await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.payoutStakers(100))).to.be.rejected;
+    });
+  });
+
+  it('should credit 0.05% for staking period', async () => {    
+    await usingPlaygrounds(async helper => {
+      const staker = accounts.pop()!;
+
+      await waitPromotionPeriodDoesntEnd(helper);
+      
+      await helper.staking.stake(staker, 100n * nominal);
+      await helper.staking.stake(staker, 200n * nominal);
+
+      // wait rewards are available:
+      const stakedInBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}))[1][0];
+      await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock));
+
+      await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100));
+
+      const totalStakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(s => s[1]);
+      expect(totalStakedPerBlock).to.be.deep.equal([calculateIncome(100n * nominal, 10n), calculateIncome(200n * nominal, 10n)]);
+    });
+  });
+
+  it('shoud be paid for more than one period if payments was missed', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const staker = accounts.pop()!;
+
+      await helper.staking.stake(staker, 100n * nominal);
+      // wait for two rewards are available:
+      const stakedInBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}))[0][0];
+      await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock) + LOCKING_PERIOD);
+
+      await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100));
+      const stakedPerBlock = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address});
+      const frozenBalanceShouldBe = calculateIncome(100n * nominal, 10n, 2);
+      expect(stakedPerBlock[0][1]).to.be.equal(frozenBalanceShouldBe);
+
+      const stakerFullBalance = await helper.balance.getSubstrateFull(staker.address);
+
+      expect(stakerFullBalance).to.contain({reserved: 0n, feeFrozen: frozenBalanceShouldBe, miscFrozen: frozenBalanceShouldBe});
+    });
+  });
+  
+  it('should not be credited for unstaked (reserved) balance', async () => {
+    await usingPlaygrounds(async helper => {
+      // staker unstakes before rewards has been payed
+      const staker = accounts.pop()!;
+      await helper.staking.stake(staker, 100n * nominal);
+      const stakedInBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}))[0][0];
+      await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock) + LOCKING_PERIOD);
+      await helper.staking.unstake(staker);
+      
+      // so he did not receive any rewards
+      const totalBalanceBefore = await helper.balance.getSubstrate(staker.address);
+      await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100));
+      const totalBalanceAfter = await helper.balance.getSubstrate(staker.address);
+
+      expect(totalBalanceBefore).to.be.equal(totalBalanceAfter);
+    });
+  });
+  
+  it('should bring compound interest', async () => {
+    await usingPlaygrounds(async helper => {
+      const staker = accounts.pop()!;
+            
+      await helper.staking.stake(staker, 100n * nominal);
+
+      const stakedInBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}))[0][0];
+      await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock));
+      
+      await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100));
+      let totalStakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(s => s[1]);
+      expect(totalStakedPerBlock).to.deep.equal([calculateIncome(100n * nominal, 10n)]);
+      
+      await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock) + LOCKING_PERIOD);
+      await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100));
+      totalStakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(s => s[1]);
+      expect(totalStakedPerBlock).to.deep.equal([calculateIncome(100n * nominal, 10n, 2)]);      
+    });
+  });
+
+  it.skip('can be paid 1000 rewards in a time', async () => {
+    // all other stakes should be unstaked
+    await usingPlaygrounds(async (helper) => {
+      const oneHundredStakers = await helper.arrange.createCrowd(100, 1050n, alice);
+
+      // stakers stakes 10 times each
+      for (let i = 0; i < 10; i++) {
+        await Promise.all(oneHundredStakers.map(staker => helper.staking.stake(staker, 100n * nominal)));
+      }
+      await helper.wait.newBlocks(40);
+      const result = await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100));
+    });
+  });
+
+  it.skip('can handle 40.000 rewards', async () => {
+    await usingPlaygrounds(async (helper) => {
+      const [donor] = await helper.arrange.createAccounts([7_000_000n], alice);
+      const crowdStakes = async () => {
+        // each account in the crowd stakes 2 times
+        const crowd = await helper.arrange.createCrowd(500, 300n, donor);
+        await Promise.all(crowd.map(account => helper.staking.stake(account, 100n * nominal)));
+        await Promise.all(crowd.map(account => helper.staking.stake(account, 100n * nominal)));
+        // 
+      };
+
+      for (let i = 0; i < 40; i++) {
+        await crowdStakes();
+      }
+
+      // TODO pay rewards for some period
+    });
+  });
+});
+
+function calculatePalleteAddress(palletId: any) {
+  const address = stringToU8a(('modl' + palletId).padEnd(32, '\0'));
+  return encodeAddress(address);
+}
+
+function calculateIncome(base: bigint, calcPeriod: bigint, iter = 0): bigint {
+  const DAY = 7200n;
+  const ACCURACY = 1_000_000_000n;
+  const income = base + base * (ACCURACY * (calcPeriod * 5n) / (10_000n * DAY)) / ACCURACY ;
+  
+  if (iter > 1) {
+    return calculateIncome(income, calcPeriod, iter - 1);
+  } else return income;
+}
+
+// Wait while promotion period less than specified block, to avoid boundary cases
+// 0 if this should be the beginning of the period.
+async function waitPromotionPeriodDoesntEnd(helper: DevUniqueHelper, waitBlockLessThan = LOCKING_PERIOD / 3n) {
+  const relayBlockNumber = (await helper.api!.query.parachainSystem.validationData()).value.relayParentNumber.toNumber(); // await helper.chain.getLatestBlockNumber();
+  const currentPeriodBlock = BigInt(relayBlockNumber) % LOCKING_PERIOD;
+
+  if (currentPeriodBlock > waitBlockLessThan) {
+    await helper.wait.forRelayBlockNumber(BigInt(relayBlockNumber) + LOCKING_PERIOD - currentPeriodBlock);
+  }
+}
modifiedtests/src/approve.test.tsdiffbeforeafterboth
--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -79,11 +79,12 @@
 
   it('[nft] Remove approval by using 0 amount', async () => {
     await usingPlaygrounds(async (helper) => {
-      const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+      const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+      const collectionId = collection.collectionId;
       const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
       await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
       expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
-      await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);
+      await helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0).signAndSend(alice);
       expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;
     });
   });
@@ -97,7 +98,7 @@
       const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
       expect(amountBefore).to.be.equal(BigInt(1));
 
-      await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);
+      await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
       const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
       expect(amountAfter).to.be.equal(BigInt(0));
     });
@@ -111,7 +112,7 @@
       const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
       expect(amountBefore).to.be.equal(BigInt(100));
 
-      await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);
+      await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
       const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
       expect(amountAfter).to.be.equal(BigInt(0));
     });
@@ -289,7 +290,7 @@
       const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
       await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);
       const tokenId = await helper.ft.getLastTokenId(collectionId);
-      await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 10n);
+      await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);
 
       const charlieBefore = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});
       await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: charlie.address}, 2n);
@@ -321,7 +322,7 @@
       const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
       await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
       expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
-      await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);
+      await helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0).signAndSend(alice);
       expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;
       const transferTokenFromTx = async () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});
       await expect(transferTokenFromTx()).to.be.rejected;
@@ -337,7 +338,7 @@
       const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
       expect(amountBefore).to.be.equal(BigInt(1));
 
-      await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);
+      await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
       const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
       expect(amountAfter).to.be.equal(BigInt(0));
 
@@ -354,7 +355,7 @@
       const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
       expect(amountBefore).to.be.equal(BigInt(100));
 
-      await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 0n);
+      await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
       const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
       expect(amountAfter).to.be.equal(BigInt(0));
 
@@ -379,8 +380,7 @@
     await usingPlaygrounds(async (helper) => {
       const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
       const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
-      const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, undefined, 2n);
-      await expect(approveTx()).to.be.rejected;
+      await helper.api?.tx.unique.approve({Substrate: charlie.address}, collectionId, tokenId, 2).signAndSend(bob);
       expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;
     });
   });
@@ -390,7 +390,7 @@
       const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
       await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);
       const tokenId = await helper.ft.getLastTokenId(collectionId);
-      const approveTx = async () => helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 11n);
+      const approveTx = async () => helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 11n);
       await expect(approveTx()).to.be.rejected;
     });
   });
@@ -399,7 +399,7 @@
     await usingPlaygrounds(async (helper) => {
       const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
       const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
-      const approveTx = async () => helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, undefined, 101n);
+      const approveTx = async () => helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 101n);
       await expect(approveTx()).to.be.rejected;
     });
   });
@@ -658,9 +658,9 @@
       const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
       const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
       await helper.rft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 100n);
-      await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, undefined, 100n);
+      await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 100n);
 
-      const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, undefined, 101n);
+      const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 101n);
       await expect(approveTx()).to.be.rejected;
     });
   });
@@ -672,8 +672,8 @@
       const tokenId = await helper.ft.getLastTokenId(collectionId);
 
       await helper.ft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);
-      await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, undefined, 10n);
-      const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, undefined, 11n);
+      await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 10n);
+      const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 11n);
       await expect(approveTx()).to.be.rejected;
     });
   });
modifiedtests/src/eth/api/ContractHelpers.soldiffbeforeafterboth
--- a/tests/src/eth/api/ContractHelpers.sol
+++ b/tests/src/eth/api/ContractHelpers.sol
@@ -12,9 +12,19 @@
 	function supportsInterface(bytes4 interfaceID) external view returns (bool);
 }
 
+/// @dev inlined interface
+interface ContractHelpersEvents {
+	event ContractSponsorSet(address indexed contractAddress, address sponsor);
+	event ContractSponsorshipConfirmed(
+		address indexed contractAddress,
+		address sponsor
+	);
+	event ContractSponsorRemoved(address indexed contractAddress);
+}
+
 /// @title Magic contract, which allows users to reconfigure other contracts
 /// @dev the ERC-165 identifier for this interface is 0xd77fab70
-interface ContractHelpers is Dummy, ERC165 {
+interface ContractHelpers is Dummy, ERC165, ContractHelpersEvents {
 	/// Get user, which deployed specified contract
 	/// @dev May return zero address in case if contract is deployed
 	///  using uniquenetwork evm-migration pallet, or using other terms not
modifiedtests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/eth/collectionAdmin.test.ts
+++ b/tests/src/eth/collectionAdmin.test.ts
@@ -15,7 +15,7 @@
 
 import {expect} from 'chai';
 import privateKey from '../substrate/privateKey';
-import { UNIQUE } from '../util/helpers';
+import {UNIQUE} from '../util/helpers';
 import {
   createEthAccount,
   createEthAccountWithBalance, 
@@ -24,7 +24,6 @@
   getCollectionAddressFromResult, 
   itWeb3,
   recordEthFee,
-  subToEth,
 } from './util/helpers';
 
 describe('Add collection admins', () => {
@@ -37,7 +36,7 @@
       .send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
 
-    const newAdmin = await createEthAccount(web3);
+    const newAdmin = createEthAccount(web3);
     const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
     await collectionEvm.methods.addCollectionAdmin(newAdmin).send();
     const adminList = await api.rpc.unique.adminlist(collectionId);
@@ -92,7 +91,7 @@
     const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
     await collectionEvm.methods.addCollectionAdmin(admin).send();
     
-    const user = await createEthAccount(web3);
+    const user = createEthAccount(web3);
     await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: admin}))
       .to.be.rejectedWith('NoPermission');
 
@@ -114,7 +113,7 @@
     const notAdmin = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
     
-    const user = await createEthAccount(web3);
+    const user = createEthAccount(web3);
     await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: notAdmin}))
       .to.be.rejectedWith('NoPermission');
 
@@ -175,7 +174,7 @@
       .send();
     const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
 
-    const newAdmin = await createEthAccount(web3);
+    const newAdmin = createEthAccount(web3);
     const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
     await collectionEvm.methods.addCollectionAdmin(newAdmin).send();
     {
@@ -226,7 +225,7 @@
 
     const admin0 = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     await collectionEvm.methods.addCollectionAdmin(admin0).send();
-    const admin1 = await createEthAccount(web3);
+    const admin1 = createEthAccount(web3);
     await collectionEvm.methods.addCollectionAdmin(admin1).send();
 
     await expect(collectionEvm.methods.removeCollectionAdmin(admin1).call({from: admin0}))
@@ -253,7 +252,7 @@
 
     const admin = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     await collectionEvm.methods.addCollectionAdmin(admin).send();
-    const notAdmin = await createEthAccount(web3);
+    const notAdmin = createEthAccount(web3);
 
     await expect(collectionEvm.methods.removeCollectionAdmin(admin).call({from: notAdmin}))
       .to.be.rejectedWith('NoPermission');
modifiedtests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/collectionSponsoring.test.ts
+++ b/tests/src/eth/collectionSponsoring.test.ts
@@ -1,5 +1,5 @@
 import {addToAllowListExpectSuccess, bigIntToSub, confirmSponsorshipExpectSuccess, createCollectionExpectSuccess, enablePublicMintingExpectSuccess, getDetailedCollectionInfo, setCollectionSponsorExpectSuccess} from '../util/helpers';
-import {itWeb3, createEthAccount, collectionIdToAddress, GAS_ARGS, normalizeEvents, createEthAccountWithBalance, evmCollectionHelpers, getCollectionAddressFromResult, evmCollection, ethBalanceViaSub, subToEth} from './util/helpers';
+import {itWeb3, createEthAccount, collectionIdToAddress, GAS_ARGS, normalizeEvents, createEthAccountWithBalance, evmCollectionHelpers, getCollectionAddressFromResult, evmCollection, ethBalanceViaSub} from './util/helpers';
 import nonFungibleAbi from './nonFungibleAbi.json';
 import {expect} from 'chai';
 import {evmToAddress} from '@polkadot/util-crypto';
modifiedtests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/contractSponsoring.test.ts
+++ b/tests/src/eth/contractSponsoring.test.ts
@@ -15,6 +15,7 @@
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
 import {expect} from 'chai';
+import { expectSubstrateEventsAtBlock } from '../util/helpers';
 import {
   contractHelpers,
   createEthAccountWithBalance,
@@ -24,6 +25,7 @@
   SponsoringMode,
   createEthAccount,
   ethBalanceViaSub,
+  normalizeEvents,
 } from './util/helpers';
 
 describe('Sponsoring EVM contracts', () => {
@@ -36,6 +38,41 @@
     expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;
   });
 
+  itWeb3('Set self sponsored events', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const flipper = await deployFlipper(web3, owner);
+    const helpers = contractHelpers(web3, owner);
+    
+    const result = await helpers.methods.selfSponsoredEnable(flipper.options.address).send();
+    // console.log(result);
+    const ethEvents = normalizeEvents(result.events);
+    expect(ethEvents).to.be.deep.equal([
+      {
+        address: flipper.options.address,
+        event: 'ContractSponsorSet',
+        args: {
+          contractAddress: flipper.options.address,
+          sponsor: flipper.options.address,
+        },
+      },
+      {
+        address: flipper.options.address,
+        event: 'ContractSponsorshipConfirmed',
+        args: {
+          contractAddress: flipper.options.address,
+          sponsor: flipper.options.address,
+        },
+      },
+    ]);
+
+    await expectSubstrateEventsAtBlock(
+      api, 
+      result.blockNumber,
+      'evmContractHelpers',
+      ['ContractSponsorSet','ContractSponsorshipConfirmed'],
+    );
+  });
+
   itWeb3('Self sponsored can not 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);
@@ -75,6 +112,33 @@
     expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;
   });
   
+  itWeb3('Set sponsor event', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const flipper = await deployFlipper(web3, owner);
+    const helpers = contractHelpers(web3, owner);
+    
+    const result = await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
+    const events = normalizeEvents(result.events);
+    expect(events).to.be.deep.equal([
+      {
+        address: flipper.options.address,
+        event: 'ContractSponsorSet',
+        args: {
+          contractAddress: flipper.options.address,
+          sponsor: sponsor,
+        },
+      },
+    ]);
+
+    await expectSubstrateEventsAtBlock(
+      api, 
+      result.blockNumber,
+      'evmContractHelpers',
+      ['ContractSponsorSet'],
+    );
+  });
+  
   itWeb3('Sponsor can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {
     const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
@@ -97,6 +161,33 @@
     expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;
   });
 
+  itWeb3('Confirm sponsorship event', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const flipper = await deployFlipper(web3, owner);
+    const helpers = contractHelpers(web3, owner);
+    await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;
+    const result = await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});
+    const events = normalizeEvents(result.events);
+    expect(events).to.be.deep.equal([
+      {
+        address: flipper.options.address,
+        event: 'ContractSponsorshipConfirmed',
+        args: {
+          contractAddress: flipper.options.address,
+          sponsor: sponsor,
+        },
+      },
+    ]);
+
+    await expectSubstrateEventsAtBlock(
+      api, 
+      result.blockNumber,
+      'evmContractHelpers',
+      ['ContractSponsorshipConfirmed'],
+    );
+  });
+
   itWeb3('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({api, web3, privateKeyWrapper}) => {
     const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
     const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
@@ -160,6 +251,35 @@
     expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
   });
 
+  itWeb3('Remove sponsor event', async ({api, web3, privateKeyWrapper}) => {
+    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+    const flipper = await deployFlipper(web3, owner);
+    const helpers = contractHelpers(web3, owner);
+
+    await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
+    await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});
+    
+    const result = await helpers.methods.removeSponsor(flipper.options.address).send();
+    const events = normalizeEvents(result.events);
+    expect(events).to.be.deep.equal([
+      {
+        address: flipper.options.address,
+        event: 'ContractSponsorRemoved',
+        args: {
+          contractAddress: flipper.options.address,
+        },
+      },
+    ]);
+
+    await expectSubstrateEventsAtBlock(
+      api, 
+      result.blockNumber,
+      'evmContractHelpers',
+      ['ContractSponsorRemoved'],
+    );
+  });
+
   itWeb3('Sponsor can not be removed 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);
modifiedtests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createNFTCollection.test.ts
+++ b/tests/src/eth/createNFTCollection.test.ts
@@ -181,7 +181,7 @@
   });
   
   itWeb3('(!negative test!) Create collection (no funds)', async ({web3}) => {
-    const owner = await createEthAccount(web3);
+    const owner = createEthAccount(web3);
     const helper = evmCollectionHelpers(web3, owner);
     const collectionName = 'A';
     const description = 'A';
@@ -194,7 +194,7 @@
 
   itWeb3('(!negative test!) Check owner', async ({api, web3, privateKeyWrapper}) => {
     const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const notOwner = await createEthAccount(web3);
+    const notOwner = createEthAccount(web3);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     const result = await collectionHelpers.methods.createNonfungibleCollection('A', 'A', 'A').send();
     const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
modifiedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -189,7 +189,7 @@
   });
   
   itWeb3('(!negative test!) Create collection (no funds)', async ({web3}) => {
-    const owner = await createEthAccount(web3);
+    const owner = createEthAccount(web3);
     const helper = evmCollectionHelpers(web3, owner);
     const collectionName = 'A';
     const description = 'A';
@@ -202,7 +202,7 @@
 
   itWeb3('(!negative test!) Check owner', async ({api, web3, privateKeyWrapper}) => {
     const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const notOwner = await createEthAccount(web3);
+    const notOwner = createEthAccount(web3);
     const collectionHelpers = evmCollectionHelpers(web3, owner);
     const result = await collectionHelpers.methods.createRefungibleCollection('A', 'A', 'A').send();
     const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
modifiedtests/src/eth/nesting/nest.test.tsdiffbeforeafterboth
--- a/tests/src/eth/nesting/nest.test.ts
+++ b/tests/src/eth/nesting/nest.test.ts
@@ -1,217 +1,220 @@
-import {ApiPromise} from '@polkadot/api';
+import {IKeyringPair} from '@polkadot/types/types';
 import {Contract} from 'web3-eth-contract';
-import {expect} from 'chai';
-import Web3 from 'web3';
-import {createEthAccountWithBalance, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, tokenIdToAddress} from '../../eth/util/helpers';
-import nonFungibleAbi from '../nonFungibleAbi.json';
 
+import {itEth, EthUniqueHelper, usingEthPlaygrounds, expect} from '../util/playgrounds';
+
 const createNestingCollection = async (
-  api: ApiPromise,
-  web3: Web3,
+  helper: EthUniqueHelper,
   owner: string,
 ): Promise<{ collectionId: number, collectionAddress: string, contract: Contract }> => {
-  const collectionHelper = evmCollectionHelpers(web3, owner);
-        
-  const result = await collectionHelper.methods
-    .createNonfungibleCollection('A', 'B', 'C')
-    .send();
-  const {collectionIdAddress: collectionAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+  const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
 
-  const contract = new web3.eth.Contract(nonFungibleAbi as any, collectionAddress, {from: owner, ...GAS_ARGS});
+  const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
   await contract.methods.setCollectionNesting(true).send({from: owner});
 
   return {collectionId, collectionAddress, contract};
 };
 
-describe('Integration Test: EVM Nesting', () => {
-  itWeb3('NFT: allows an Owner to nest/unnest their token', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const {collectionId, contract} = await createNestingCollection(api, web3, owner);
 
-    // Create a token to be nested
-    const targetNFTTokenId = await contract.methods.nextTokenId().call();
-    await contract.methods.mint(
-      owner,
-      targetNFTTokenId,
-    ).send({from: owner});
-
-    const targetNftTokenAddress = tokenIdToAddress(collectionId, targetNFTTokenId);
-
-    // Create a nested token
-    const firstTokenId = await contract.methods.nextTokenId().call();
-    await contract.methods.mint(
-      targetNftTokenAddress,
-      firstTokenId,
-    ).send({from: owner});
+describe('EVM nesting tests group', () => {
+  let donor: IKeyringPair;
 
-    expect(await contract.methods.ownerOf(firstTokenId).call()).to.be.equal(targetNftTokenAddress);
-
-    // Create a token to be nested and nest
-    const secondTokenId = await contract.methods.nextTokenId().call();
-    await contract.methods.mint(
-      owner,
-      secondTokenId,
-    ).send({from: owner});
-
-    await contract.methods.transfer(targetNftTokenAddress, secondTokenId).send({from: owner});
-
-    expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(targetNftTokenAddress);
-
-    // Unnest token back
-    await contract.methods.transferFrom(targetNftTokenAddress, owner, secondTokenId).send({from: owner});
-    expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(owner);
+  before(async function() {
+    await usingEthPlaygrounds(async (helper, privateKey) => {
+      donor = privateKey('//Alice');
+    });
   });
 
-  itWeb3('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
-    const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(api, web3, owner);
-    const {collectionAddress: collectionAddressB, contract: contractB} = await createNestingCollection(api, web3, owner);
-    await contractA.methods.setCollectionNesting(true, [collectionAddressA, collectionAddressB]).send({from: owner});
-
-    // Create a token to nest into
-    const targetNftTokenId = await contractA.methods.nextTokenId().call();
-    await contractA.methods.mint(
-      owner,
-      targetNftTokenId,
-    ).send({from: owner});
-    const nftTokenAddressA1 = tokenIdToAddress(collectionIdA, targetNftTokenId);
-
-    // Create a token for nesting in the same collection as the target
-    const nftTokenIdA = await contractA.methods.nextTokenId().call();
-    await contractA.methods.mint(
-      owner,
-      nftTokenIdA,
-    ).send({from: owner});
-
-    // Create a token for nesting in a different collection
-    const nftTokenIdB = await contractB.methods.nextTokenId().call();
-    await contractB.methods.mint(
-      owner,
-      nftTokenIdB,
-    ).send({from: owner});
-
-    // Nest
-    await contractA.methods.transfer(nftTokenAddressA1, nftTokenIdA).send({from: owner});
-    expect(await contractA.methods.ownerOf(nftTokenIdA).call()).to.be.equal(nftTokenAddressA1);
-
-    await contractB.methods.transfer(nftTokenAddressA1, nftTokenIdB).send({from: owner});
-    expect(await contractB.methods.ownerOf(nftTokenIdB).call()).to.be.equal(nftTokenAddressA1);
-  });
-});
-
-describe('Negative Test: EVM Nesting', async() => {
-  itWeb3('NFT: disallows to nest token if nesting is disabled', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
-    const {collectionId, contract} = await createNestingCollection(api, web3, owner);
-    await contract.methods.setCollectionNesting(false).send({from: owner});
-
-    // Create a token to nest into
-    const targetNftTokenId = await contract.methods.nextTokenId().call();
-    await contract.methods.mint(
-      owner,
-      targetNftTokenId,
-    ).send({from: owner});
-
-    const targetNftTokenAddress = tokenIdToAddress(collectionId, targetNftTokenId);
-
-    // Create a token to nest
-    const nftTokenId = await contract.methods.nextTokenId().call();
-    await contract.methods.mint(
-      owner,
-      nftTokenId,
-    ).send({from: owner});
-
-    // Try to nest
-    await expect(contract.methods
-      .transfer(targetNftTokenAddress, nftTokenId)
-      .call({from: owner})).to.be.rejectedWith('UserIsNotAllowedToNest');
-  });
-
-  itWeb3('NFT: disallows a non-Owner to nest someone else\'s token', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const malignant = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
-    const {collectionId, contract} = await createNestingCollection(api, web3, owner);
-
-    // Mint a token
-    const targetTokenId = await contract.methods.nextTokenId().call();
-    await contract.methods.mint(
-      owner,
-      targetTokenId,
-    ).send({from: owner});
-    const targetTokenAddress = tokenIdToAddress(collectionId, targetTokenId);
-
-    // Mint a token belonging to a different account
-    const tokenId = await contract.methods.nextTokenId().call();
-    await contract.methods.mint(
-      malignant,
-      tokenId,
-    ).send({from: owner});
-
-    // Try to nest one token in another as a non-owner account
-    await expect(contract.methods
-      .transfer(targetTokenAddress, tokenId)
-      .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');
-  });
-
-  itWeb3('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const malignant = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
-    const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(api, web3, owner);
-    const {collectionAddress: collectionAddressB, contract: contractB} = await createNestingCollection(api, web3, owner);
-
-    await contractA.methods.setCollectionNesting(true, [collectionAddressA, collectionAddressB]).send({from: owner});
-
-    // Create a token in one collection
-    const nftTokenIdA = await contractA.methods.nextTokenId().call();
-    await contractA.methods.mint(
-      owner,
-      nftTokenIdA,
-    ).send({from: owner});
-    const nftTokenAddressA = tokenIdToAddress(collectionIdA, nftTokenIdA);
-
-    // Create a token in another collection belonging to someone else
-    const nftTokenIdB = await contractB.methods.nextTokenId().call();
-    await contractB.methods.mint(
-      malignant,
-      nftTokenIdB,
-    ).send({from: owner});
-
-    // Try to drag someone else's token into the other collection and nest
-    await expect(contractB.methods
-      .transfer(nftTokenAddressA, nftTokenIdB)
-      .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');
+  describe('Integration Test: EVM Nesting', () => {
+    itEth('NFT: allows an Owner to nest/unnest their token', async ({helper}) => {
+      const owner = await helper.eth.createAccountWithBalance(donor);
+      const {collectionId, contract} = await createNestingCollection(helper, owner);
+  
+      // Create a token to be nested
+      const targetNFTTokenId = await contract.methods.nextTokenId().call();
+      await contract.methods.mint(
+        owner,
+        targetNFTTokenId,
+      ).send({from: owner});
+  
+      const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetNFTTokenId);
+  
+      // Create a nested token
+      const firstTokenId = await contract.methods.nextTokenId().call();
+      await contract.methods.mint(
+        targetNftTokenAddress,
+        firstTokenId,
+      ).send({from: owner});
+  
+      expect(await contract.methods.ownerOf(firstTokenId).call()).to.be.equal(targetNftTokenAddress);
+  
+      // Create a token to be nested and nest
+      const secondTokenId = await contract.methods.nextTokenId().call();
+      await contract.methods.mint(
+        owner,
+        secondTokenId,
+      ).send({from: owner});
+  
+      await contract.methods.transfer(targetNftTokenAddress, secondTokenId).send({from: owner});
+  
+      expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(targetNftTokenAddress);
+  
+      // Unnest token back
+      await contract.methods.transferFrom(targetNftTokenAddress, owner, secondTokenId).send({from: owner});
+      expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(owner);
+    });
+  
+    itEth('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {
+      const owner = await helper.eth.createAccountWithBalance(donor);
+  
+      const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);
+      const {collectionAddress: collectionAddressB, contract: contractB} = await createNestingCollection(helper, owner);
+      await contractA.methods.setCollectionNesting(true, [collectionAddressA, collectionAddressB]).send({from: owner});
+  
+      // Create a token to nest into
+      const targetNftTokenId = await contractA.methods.nextTokenId().call();
+      await contractA.methods.mint(
+        owner,
+        targetNftTokenId,
+      ).send({from: owner});
+      const nftTokenAddressA1 = helper.ethAddress.fromTokenId(collectionIdA, targetNftTokenId);
+  
+      // Create a token for nesting in the same collection as the target
+      const nftTokenIdA = await contractA.methods.nextTokenId().call();
+      await contractA.methods.mint(
+        owner,
+        nftTokenIdA,
+      ).send({from: owner});
+  
+      // Create a token for nesting in a different collection
+      const nftTokenIdB = await contractB.methods.nextTokenId().call();
+      await contractB.methods.mint(
+        owner,
+        nftTokenIdB,
+      ).send({from: owner});
+  
+      // Nest
+      await contractA.methods.transfer(nftTokenAddressA1, nftTokenIdA).send({from: owner});
+      expect(await contractA.methods.ownerOf(nftTokenIdA).call()).to.be.equal(nftTokenAddressA1);
+  
+      await contractB.methods.transfer(nftTokenAddressA1, nftTokenIdB).send({from: owner});
+      expect(await contractB.methods.ownerOf(nftTokenIdB).call()).to.be.equal(nftTokenAddressA1);
+    });
   });
 
-  itWeb3('NFT: disallows to nest token in an unlisted collection', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-
-    const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(api, web3, owner);
-    const {contract: contractB} = await createNestingCollection(api, web3, owner);
-
-    await contractA.methods.setCollectionNesting(true, [collectionAddressA]).send({from: owner});
-
-    // Create a token in one collection
-    const nftTokenIdA = await contractA.methods.nextTokenId().call();
-    await contractA.methods.mint(
-      owner,
-      nftTokenIdA,
-    ).send({from: owner});
-    const nftTokenAddressA = tokenIdToAddress(collectionIdA, nftTokenIdA);
-
-    // Create a token in another collection
-    const nftTokenIdB = await contractB.methods.nextTokenId().call();
-    await contractB.methods.mint(
-      owner,
-      nftTokenIdB,
-    ).send({from: owner});
-
-    // Try to nest into a token in the other collection, disallowed in the first
-    await expect(contractB.methods
-      .transfer(nftTokenAddressA, nftTokenIdB)
-      .call()).to.be.rejectedWith('SourceCollectionIsNotAllowedToNest');
+  describe('Negative Test: EVM Nesting', async() => {
+    itEth('NFT: disallows to nest token if nesting is disabled', async ({helper}) => {
+      const owner = await helper.eth.createAccountWithBalance(donor);
+  
+      const {collectionId, contract} = await createNestingCollection(helper, owner);
+      await contract.methods.setCollectionNesting(false).send({from: owner});
+  
+      // Create a token to nest into
+      const targetNftTokenId = await contract.methods.nextTokenId().call();
+      await contract.methods.mint(
+        owner,
+        targetNftTokenId,
+      ).send({from: owner});
+  
+      const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetNftTokenId);
+  
+      // Create a token to nest
+      const nftTokenId = await contract.methods.nextTokenId().call();
+      await contract.methods.mint(
+        owner,
+        nftTokenId,
+      ).send({from: owner});
+  
+      // Try to nest
+      await expect(contract.methods
+        .transfer(targetNftTokenAddress, nftTokenId)
+        .call({from: owner})).to.be.rejectedWith('UserIsNotAllowedToNest');
+    });
+  
+    itEth('NFT: disallows a non-Owner to nest someone else\'s token', async ({helper}) => {
+      const owner = await helper.eth.createAccountWithBalance(donor);
+      const malignant = await helper.eth.createAccountWithBalance(donor);
+  
+      const {collectionId, contract} = await createNestingCollection(helper, owner);
+  
+      // Mint a token
+      const targetTokenId = await contract.methods.nextTokenId().call();
+      await contract.methods.mint(
+        owner,
+        targetTokenId,
+      ).send({from: owner});
+      const targetTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetTokenId);
+  
+      // Mint a token belonging to a different account
+      const tokenId = await contract.methods.nextTokenId().call();
+      await contract.methods.mint(
+        malignant,
+        tokenId,
+      ).send({from: owner});
+  
+      // Try to nest one token in another as a non-owner account
+      await expect(contract.methods
+        .transfer(targetTokenAddress, tokenId)
+        .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');
+    });
+  
+    itEth('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async ({helper}) => {
+      const owner = await helper.eth.createAccountWithBalance(donor);
+      const malignant = await helper.eth.createAccountWithBalance(donor);
+  
+      const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);
+      const {collectionAddress: collectionAddressB, contract: contractB} = await createNestingCollection(helper, owner);
+  
+      await contractA.methods.setCollectionNesting(true, [collectionAddressA, collectionAddressB]).send({from: owner});
+  
+      // Create a token in one collection
+      const nftTokenIdA = await contractA.methods.nextTokenId().call();
+      await contractA.methods.mint(
+        owner,
+        nftTokenIdA,
+      ).send({from: owner});
+      const nftTokenAddressA = helper.ethAddress.fromTokenId(collectionIdA, nftTokenIdA);
+  
+      // Create a token in another collection belonging to someone else
+      const nftTokenIdB = await contractB.methods.nextTokenId().call();
+      await contractB.methods.mint(
+        malignant,
+        nftTokenIdB,
+      ).send({from: owner});
+  
+      // Try to drag someone else's token into the other collection and nest
+      await expect(contractB.methods
+        .transfer(nftTokenAddressA, nftTokenIdB)
+        .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');
+    });
+  
+    itEth('NFT: disallows to nest token in an unlisted collection', async ({helper}) => {
+      const owner = await helper.eth.createAccountWithBalance(donor);
+  
+      const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);
+      const {contract: contractB} = await createNestingCollection(helper, owner);
+  
+      await contractA.methods.setCollectionNesting(true, [collectionAddressA]).send({from: owner});
+  
+      // Create a token in one collection
+      const nftTokenIdA = await contractA.methods.nextTokenId().call();
+      await contractA.methods.mint(
+        owner,
+        nftTokenIdA,
+      ).send({from: owner});
+      const nftTokenAddressA = helper.ethAddress.fromTokenId(collectionIdA, nftTokenIdA);
+  
+      // Create a token in another collection
+      const nftTokenIdB = await contractB.methods.nextTokenId().call();
+      await contractB.methods.mint(
+        owner,
+        nftTokenIdB,
+      ).send({from: owner});
+  
+      // Try to nest into a token in the other collection, disallowed in the first
+      await expect(contractB.methods
+        .transfer(nftTokenAddressA, nftTokenIdB)
+        .call()).to.be.rejectedWith('SourceCollectionIsNotAllowedToNest');
+    });
   });
 });
modifiedtests/src/eth/payable.test.tsdiffbeforeafterboth
--- a/tests/src/eth/payable.test.ts
+++ b/tests/src/eth/payable.test.ts
@@ -14,97 +14,91 @@
 // You should have received a copy of the GNU General Public License
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
-import {expect} from 'chai';
-import {submitTransactionAsync} from '../substrate/substrate-api';
-import {createEthAccountWithBalance, deployCollector, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';
-import {evmToAddress} from '@polkadot/util-crypto';
-import {getGenericResult, UNIQUE} from '../util/helpers';
-import {getBalanceSingle, transferBalanceExpectSuccess} from '../substrate/get-balance';
+import {IKeyringPair} from '@polkadot/types/types';
+
+import {itEth, expect, usingEthPlaygrounds} from './util/playgrounds';
 
 describe('EVM payable contracts', () => {
-  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);
+  let donor: IKeyringPair;
 
-    await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: '10000', ...GAS_ARGS});
+  before(async function() {
+    await usingEthPlaygrounds(async (helper, privateKey) => {
+      donor = privateKey('//Alice');
+    });
+  });
+
+  itEth('Evm contract can receive wei from eth account', async ({helper}) => {
+    const deployer = await helper.eth.createAccountWithBalance(donor);
+    const contract = await helper.eth.deployCollectorContract(deployer);
+
+    const web3 = helper.getWeb3();
+
+    await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: '10000', gas: helper.eth.DEFAULT_GAS});
 
     expect(await contract.methods.getCollected().call()).to.be.equal('10000');
   });
 
-  itWeb3('Evm contract can receive wei from substrate account', async ({api, web3, privateKeyWrapper}) => {
-    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const contract = await deployCollector(web3, deployer);
-    const alice = privateKeyWrapper('//Alice');
+  itEth('Evm contract can receive wei from substrate account', async ({helper}) => {
+    const deployer = await helper.eth.createAccountWithBalance(donor);
+    const contract = await helper.eth.deployCollectorContract(deployer);
+    const [alice] = await helper.arrange.createAccounts([10n], donor);
+
+    const weiCount = '10000';
 
     // Transaction fee/value will be payed from subToEth(sender) evm balance,
     // which is backed by evmToAddress(subToEth(sender)) substrate balance
-    await transferBalanceToEth(api, alice, subToEth(alice.address));
+    await helper.eth.transferBalanceFromSubstrate(alice, helper.address.substrateToEth(alice.address), 5n);
+
 
-    {
-      const tx = api.tx.evm.call(
-        subToEth(alice.address),
-        contract.options.address,
-        contract.methods.giveMoney().encodeABI(),
-        '10000',
-        GAS_ARGS.gas,
-        await web3.eth.getGasPrice(),
-        null,
-        null,
-        [],
-      );
-      const events = await submitTransactionAsync(alice, tx);
-      const result = getGenericResult(events);
-      expect(result.success).to.be.true;
-    }
+    await helper.eth.callEVM(alice, contract.options.address, contract.methods.giveMoney().encodeABI(), weiCount);
 
-    expect(await contract.methods.getCollected().call()).to.be.equal('10000');
+    expect(await contract.methods.getCollected().call()).to.be.equal(weiCount);
   });
 
   // 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, privateKeyWrapper);
-    const contract = await deployCollector(web3, deployer);
-    const alice = privateKeyWrapper('//Alice');
+  itEth('Wei sent directly to backing storage of evm contract balance is unaccounted', async({helper}) => {
+    const deployer = await helper.eth.createAccountWithBalance(donor);
+    const contract = await helper.eth.deployCollectorContract(deployer);
+    const [alice] = await helper.arrange.createAccounts([10n], donor);
+
+    const weiCount = 10_000n;
 
-    await transferBalanceExpectSuccess(api, alice, evmToAddress(contract.options.address), '10000');
+    await helper.eth.transferBalanceFromSubstrate(alice, contract.options.address, weiCount, false);
 
-    expect(await contract.methods.getUnaccounted().call()).to.be.equal('10000');
+    expect(await contract.methods.getUnaccounted().call()).to.be.equal(weiCount.toString());
   });
 
-  itWeb3('Balance can be retrieved from evm contract', async({api, web3, privateKeyWrapper}) => {
-    const FEE_BALANCE = 1000n * UNIQUE;
-    const CONTRACT_BALANCE = 1n * UNIQUE;
+  itEth('Balance can be retrieved from evm contract', async({helper, privateKey}) => {
+    const FEE_BALANCE = 10n * helper.balance.getOneTokenNominal();
+    const CONTRACT_BALANCE = 1n * helper.balance.getOneTokenNominal();
+
+    const deployer = await helper.eth.createAccountWithBalance(donor);
+    const contract = await helper.eth.deployCollectorContract(deployer);
+    const [alice] = await helper.arrange.createAccounts([20n], donor);
 
-    const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const contract = await deployCollector(web3, deployer);
-    const alice = privateKeyWrapper('//Alice');
+    const web3 = helper.getWeb3();
 
-    await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: CONTRACT_BALANCE.toString(), ...GAS_ARGS});
+    await web3.eth.sendTransaction({from: deployer, to: contract.options.address, value: CONTRACT_BALANCE.toString(), gas: helper.eth.DEFAULT_GAS});
 
-    const receiver = privateKeyWrapper(`//Receiver${Date.now()}`);
+    const receiver = privateKey(`//Receiver${Date.now()}`);
 
     // First receive balance on eth balance of bob
     {
-      const ethReceiver = subToEth(receiver.address);
+      const ethReceiver = helper.address.substrateToEth(receiver.address);
       expect(await web3.eth.getBalance(ethReceiver)).to.be.equal('0');
       await contract.methods.withdraw(ethReceiver).send({from: deployer});
       expect(await web3.eth.getBalance(ethReceiver)).to.be.equal(CONTRACT_BALANCE.toString());
     }
 
     // Some balance is required to pay fee for evm.withdraw call
-    await transferBalanceExpectSuccess(api, alice, receiver.address, FEE_BALANCE.toString());
+    await helper.balance.transferToSubstrate(alice, receiver.address, FEE_BALANCE);
+    // await transferBalanceExpectSuccess(api, alice, receiver.address, FEE_BALANCE.toString());
 
     // Withdraw balance from eth to substrate
     {
-      const initialReceiverBalance = await getBalanceSingle(api, receiver.address);
-      const tx = api.tx.evm.withdraw(
-        subToEth(receiver.address),
-        CONTRACT_BALANCE.toString(),
-      );
-      const events = await submitTransactionAsync(receiver, tx);
-      const result = getGenericResult(events);
-      expect(result.success).to.be.true;
-      const finalReceiverBalance = await getBalanceSingle(api, receiver.address);
+      const initialReceiverBalance = await helper.balance.getSubstrate(receiver.address);
+      await helper.executeExtrinsic(receiver, 'api.tx.evm.withdraw', [helper.address.substrateToEth(receiver.address), CONTRACT_BALANCE.toString()], true);
+      const finalReceiverBalance = await helper.balance.getSubstrate(receiver.address);
 
       expect(finalReceiverBalance > initialReceiverBalance).to.be.true;
     }
modifiedtests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth
--- a/tests/src/eth/reFungibleToken.test.ts
+++ b/tests/src/eth/reFungibleToken.test.ts
@@ -15,7 +15,7 @@
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
 import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers';
-import {collectionIdFromAddress, collectionIdToAddress, createEthAccount, createEthAccountWithBalance, createNonfungibleCollection, createRefungibleCollection, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth, uniqueNFT, uniqueRefungible, uniqueRefungibleToken} from './util/helpers';
+import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, createRefungibleCollection, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth, uniqueRefungible, uniqueRefungibleToken} from './util/helpers';
 
 import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
modifiedtests/src/eth/util/contractHelpersAbi.jsondiffbeforeafterboth
--- a/tests/src/eth/util/contractHelpersAbi.json
+++ b/tests/src/eth/util/contractHelpersAbi.json
@@ -1,5 +1,56 @@
 [
   {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "contractAddress",
+        "type": "address"
+      }
+    ],
+    "name": "ContractSponsorRemoved",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "contractAddress",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "address",
+        "name": "sponsor",
+        "type": "address"
+      }
+    ],
+    "name": "ContractSponsorSet",
+    "type": "event"
+  },
+  {
+    "anonymous": false,
+    "inputs": [
+      {
+        "indexed": true,
+        "internalType": "address",
+        "name": "contractAddress",
+        "type": "address"
+      },
+      {
+        "indexed": false,
+        "internalType": "address",
+        "name": "sponsor",
+        "type": "address"
+      }
+    ],
+    "name": "ContractSponsorshipConfirmed",
+    "type": "event"
+  },
+  {
     "inputs": [
       {
         "internalType": "address",
addedtests/src/eth/util/playgrounds/index.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/util/playgrounds/index.ts
@@ -0,0 +1,49 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+import {IKeyringPair} from '@polkadot/types/types';
+
+import config from '../../../config';
+
+import {EthUniqueHelper} from './unique.dev';
+import {SilentLogger, SilentConsole} from '../../../util/playgrounds/unique.dev';
+
+export {EthUniqueHelper} from './unique.dev';
+
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+chai.use(chaiAsPromised);
+export const expect = chai.expect;
+
+export const usingEthPlaygrounds = async (code: (helper: EthUniqueHelper, privateKey: (seed: string) => IKeyringPair) => Promise<void>) => {
+  const silentConsole = new SilentConsole();
+  silentConsole.enable();
+
+  const helper = new EthUniqueHelper(new SilentLogger());
+
+  try {
+    await helper.connect(config.substrateUrl);
+    await helper.connectWeb3(config.substrateUrl);
+    const ss58Format = helper.chain.getChainProperties().ss58Format;
+    const privateKey = (seed: string) => helper.util.fromSeed(seed, ss58Format);
+    await code(helper, privateKey);
+  }
+  finally {
+    await helper.disconnect();
+    await helper.disconnectWeb3();
+    silentConsole.disable();
+  }
+};
+  
+export async function itEth(name: string, cb: (apis: { helper: EthUniqueHelper, privateKey: (seed: string) => IKeyringPair }) => any, opts: { only?: boolean, skip?: boolean } = {}) {
+  let i: any = it;
+  if (opts.only) i = i.only;
+  else if (opts.skip) i = i.skip;
+  i(name, async () => {
+    await usingEthPlaygrounds(async (helper, privateKey) => {
+      await cb({helper, privateKey});
+    });
+  });
+}
+itEth.only = (name: string, cb: (apis: { helper: EthUniqueHelper, privateKey: (seed: string) => IKeyringPair }) => any) => itEth(name, cb, {only: true});
+itEth.skip = (name: string, cb: (apis: { helper: EthUniqueHelper, privateKey: (seed: string) => IKeyringPair }) => any) => itEth(name, cb, {skip: true});
\ No newline at end of file
addedtests/src/eth/util/playgrounds/types.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/util/playgrounds/types.ts
@@ -0,0 +1,9 @@
+export interface ContractImports {
+  solPath: string;
+  fsPath: string;
+}
+
+export interface CompiledContract {
+  abi: any;
+  object: string;
+}
\ No newline at end of file
addedtests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/util/playgrounds/unique.dev.ts
@@ -0,0 +1,268 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+/* eslint-disable function-call-argument-newline */
+
+import {readFile} from 'fs/promises';
+
+import Web3 from 'web3';
+import {WebsocketProvider} from 'web3-core';
+import {Contract} from 'web3-eth-contract';
+
+import * as solc from 'solc';
+
+import {evmToAddress} from '@polkadot/util-crypto';
+import {IKeyringPair} from '@polkadot/types/types';
+
+import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';
+
+import {ContractImports, CompiledContract} from './types';
+
+// Native contracts ABI
+import collectionHelpersAbi from '../../collectionHelpersAbi.json';
+import fungibleAbi from '../../fungibleAbi.json';
+import nonFungibleAbi from '../../nonFungibleAbi.json';
+import refungibleAbi from '../../reFungibleAbi.json';
+import refungibleTokenAbi from '../../reFungibleTokenAbi.json';
+import contractHelpersAbi from './../contractHelpersAbi.json';
+
+class EthGroupBase {
+  helper: EthUniqueHelper;
+
+  constructor(helper: EthUniqueHelper) {
+    this.helper = helper;
+  }
+}
+
+
+class ContractGroup extends EthGroupBase {
+  async findImports(imports?: ContractImports[]){
+    if(!imports) return function(path: string) {
+      return {error: `File not found: ${path}`};
+    };
+  
+    const knownImports = {} as any;
+    for(const imp of imports) {
+      knownImports[imp.solPath] = (await readFile(imp.fsPath)).toString();
+    }
+  
+    return function(path: string) {
+      if(knownImports.hasOwnPropertyDescriptor(path)) return {contents: knownImports[path]};
+      return {error: `File not found: ${path}`};
+    };
+  }
+
+  async compile(name: string, src: string, imports?: ContractImports[]): Promise<CompiledContract> {
+    const out = JSON.parse(solc.compile(JSON.stringify({
+      language: 'Solidity',
+      sources: {
+        [`${name}.sol`]: {
+          content: src,
+        },
+      },
+      settings: {
+        outputSelection: {
+          '*': {
+            '*': ['*'],
+          },
+        },
+      },
+    }), {import: await this.findImports(imports)})).contracts[`${name}.sol`][name];
+  
+    return {
+      abi: out.abi,
+      object: '0x' + out.evm.bytecode.object,
+    };
+  }
+
+  async deployByCode(signer: string, name: string, src: string, imports?: ContractImports[]): Promise<Contract> {
+    const compiledContract = await this.compile(name, src, imports);
+    return this.deployByAbi(signer, compiledContract.abi, compiledContract.object);
+  }
+
+  async deployByAbi(signer: string, abi: any, object: string): Promise<Contract> {
+    const web3 = this.helper.getWeb3();
+    const contract = new web3.eth.Contract(abi, undefined, {
+      data: object,
+      from: signer,
+      gas: this.helper.eth.DEFAULT_GAS,
+    });
+    return await contract.deploy({data: object}).send({from: signer});
+  }
+
+}
+  
+class NativeContractGroup extends EthGroupBase {
+
+  contractHelpers(caller: string): Contract {
+    const web3 = this.helper.getWeb3();
+    return new web3.eth.Contract(contractHelpersAbi as any, '0x842899ECF380553E8a4de75bF534cdf6fBF64049', {from: caller, gas: this.helper.eth.DEFAULT_GAS});
+  }
+
+  collectionHelpers(caller: string) {
+    const web3 = this.helper.getWeb3();
+    return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, gas: this.helper.eth.DEFAULT_GAS});
+  }
+
+  collection(address: string, mode: 'nft' | 'rft' | 'ft', caller?: string): Contract {
+    const abi = {
+      'nft': nonFungibleAbi,
+      'rft': refungibleAbi,
+      'ft': fungibleAbi,
+    }[mode];
+    const web3 = this.helper.getWeb3();
+    return new web3.eth.Contract(abi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})});
+  }
+
+  rftTokenByAddress(address: string, caller?: string): Contract {
+    const web3 = this.helper.getWeb3();
+    return new web3.eth.Contract(refungibleTokenAbi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})});
+  }
+
+  rftToken(collectionId: number, tokenId: number, caller?: string): Contract {
+    return this.rftTokenByAddress(this.helper.ethAddress.fromTokenId(collectionId, tokenId), caller);
+  }
+}
+
+  
+class EthGroup extends EthGroupBase {
+  DEFAULT_GAS = 2_500_000;
+
+  createAccount() {
+    const web3 = this.helper.getWeb3();
+    const account = web3.eth.accounts.create();
+    web3.eth.accounts.wallet.add(account.privateKey);
+    return account.address;
+  }
+
+  async createAccountWithBalance(donor: IKeyringPair, amount=1000n) {
+    const account = this.createAccount();
+    await this.transferBalanceFromSubstrate(donor, account, amount);
+  
+    return account;
+  }
+
+  async transferBalanceFromSubstrate(donor: IKeyringPair, recepient: string, amount=1000n, inTokens=true) {
+    return await this.helper.balance.transferToSubstrate(donor, evmToAddress(recepient), amount * (inTokens ? this.helper.balance.getOneTokenNominal() : 1n));
+  }
+
+  async callEVM(signer: IKeyringPair, contractAddress: string, abi: any, value: string, gasLimit?: number) {
+    if(!gasLimit) gasLimit = this.DEFAULT_GAS;
+    const web3 = this.helper.getWeb3();
+    const gasPrice = await web3.eth.getGasPrice();
+    // TODO: check execution status
+    await this.helper.executeExtrinsic(
+      signer,
+      'api.tx.evm.call', [this.helper.address.substrateToEth(signer.address), contractAddress, abi, value, gasLimit, gasPrice, null, null, []],
+      true,
+    );
+  }
+
+  async createNonfungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {
+    const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);
+        
+    const result = await collectionHelper.methods.createNonfungibleCollection(name, description, tokenPrefix).send();
+
+    const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
+    const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);
+
+    return {collectionId, collectionAddress};
+  }
+
+  async deployCollectorContract(signer: string): Promise<Contract> {
+    return await this.helper.ethContract.deployByCode(signer, 'Collector', `
+    // SPDX-License-Identifier: UNLICENSED
+    pragma solidity ^0.8.6;
+
+    contract Collector {
+      uint256 collected;
+      fallback() external payable {
+        giveMoney();
+      }
+      function giveMoney() public payable {
+        collected += msg.value;
+      }
+      function getCollected() public view returns (uint256) {
+        return collected;
+      }
+      function getUnaccounted() public view returns (uint256) {
+        return address(this).balance - collected;
+      }
+
+      function withdraw(address payable target) public {
+        target.transfer(collected);
+        collected = 0;
+      }
+    }
+  `);
+  }
+}
+  
+  
+class EthAddressGroup extends EthGroupBase {
+  extractCollectionId(address: string): number {
+    if (!(address.length === 42 || address.length === 40)) throw new Error('address wrong format');
+    return parseInt(address.substr(address.length - 8), 16);
+  }
+
+  fromCollectionId(collectionId: number): string {
+    if (collectionId >= 0xffffffff || collectionId < 0) throw new Error('collectionId overflow');
+    return Web3.utils.toChecksumAddress(`0x17c4e6453cc49aaaaeaca894e6d9683e${collectionId.toString(16).padStart(8, '0')}`);
+  }
+
+  extractTokenId(address: string): {collectionId: number, tokenId: number} {
+    if (!address.startsWith('0x'))
+      throw 'address not starts with "0x"';
+    if (address.length > 42)
+      throw 'address length is more than 20 bytes';
+    return {
+      collectionId: Number('0x' + address.substring(address.length - 16, address.length - 8)),
+      tokenId: Number('0x' + address.substring(address.length - 8)),
+    };
+  }
+
+  fromTokenId(collectionId: number, tokenId: number): string  {
+    return this.helper.util.getNestingTokenAddress(collectionId, tokenId);
+  }
+
+  normalizeAddress(address: string): string {
+    return '0x' + address.substring(address.length - 40);
+  }
+}  
+ 
+
+export class EthUniqueHelper extends DevUniqueHelper {
+  web3: Web3 | null = null;
+  web3Provider: WebsocketProvider | null = null;
+
+  eth: EthGroup;
+  ethAddress: EthAddressGroup;
+  ethNativeContract: NativeContractGroup;
+  ethContract: ContractGroup;
+
+  constructor(logger: { log: (msg: any, level: any) => void, level: any }) {
+    super(logger);
+    this.eth = new EthGroup(this);
+    this.ethAddress = new EthAddressGroup(this);
+    this.ethNativeContract = new NativeContractGroup(this);
+    this.ethContract = new ContractGroup(this);
+  }
+
+  getWeb3(): Web3 {
+    if(this.web3 === null) throw Error('Web3 not connected');
+    return this.web3;
+  }
+
+  async connectWeb3(wsEndpoint: string) {
+    if(this.web3 !== null) return;
+    this.web3Provider = new Web3.providers.WebsocketProvider(wsEndpoint);
+    this.web3 = new Web3(this.web3Provider);
+  }
+
+  async disconnectWeb3() {
+    if(this.web3 === null) return;
+    this.web3Provider?.connection.close();
+    this.web3 = null;
+  }
+}
+  
\ No newline at end of file
addedtests/src/interfaces/appPromotion/definitions.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/interfaces/appPromotion/definitions.ts
@@ -0,0 +1,58 @@
+// 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/>.
+
+type RpcParam = {
+  name: string;
+  type: string;
+  isOptional?: true;
+};
+
+const CROSS_ACCOUNT_ID_TYPE = 'PalletEvmAccountBasicCrossAccountIdRepr';
+
+const crossAccountParam = (name = 'account') => ({name, type: CROSS_ACCOUNT_ID_TYPE});
+const atParam = {name: 'at', type: 'Hash', isOptional: true};
+
+const fun = (description: string, params: RpcParam[], type: string) => ({
+  description,
+  params: [...params, atParam],
+  type,
+});
+
+export default {
+  types: {},
+  rpc: {
+    totalStaked: fun(
+      'Returns the total amount of staked tokens',
+      [{name: 'staker', type: CROSS_ACCOUNT_ID_TYPE, isOptional: true}],
+      'u128',
+    ),
+    totalStakedPerBlock: fun(
+      'Returns the total amount of staked tokens per block when staked',
+      [crossAccountParam('staker')],
+      'Vec<(u32, u128)>',
+    ),
+    pendingUnstake: fun(
+      'Returns the total amount of unstaked tokens',
+      [{name: 'staker', type: CROSS_ACCOUNT_ID_TYPE, isOptional: true}],
+      'u128',
+    ),
+    pendingUnstakePerBlock: fun(
+      'Returns the total amount of unstaked tokens per block',
+      [crossAccountParam('staker')],
+      'Vec<(u32, u128)>',
+    ),
+  },
+};
addedtests/src/interfaces/appPromotion/index.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/interfaces/appPromotion/index.ts
@@ -0,0 +1,4 @@
+// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
+/* eslint-disable */
+
+export * from './types';
addedtests/src/interfaces/appPromotion/types.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/interfaces/appPromotion/types.ts
@@ -0,0 +1,4 @@
+// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
+/* eslint-disable */
+
+export type PHANTOM_APPPROMOTION = 'appPromotion';
modifiedtests/src/interfaces/augment-api-consts.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-consts.ts
+++ b/tests/src/interfaces/augment-api-consts.ts
@@ -8,13 +8,39 @@
 import type { ApiTypes, AugmentedConst } from '@polkadot/api-base/types';
 import type { Option, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';
 import type { Codec } from '@polkadot/types-codec/types';
-import type { Permill } from '@polkadot/types/interfaces/runtime';
+import type { Perbill, Permill } from '@polkadot/types/interfaces/runtime';
 import type { FrameSupportPalletId, FrameSupportWeightsRuntimeDbWeight, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpVersionRuntimeVersion } from '@polkadot/types/lookup';
 
 export type __AugmentedConst<ApiType extends ApiTypes> = AugmentedConst<ApiType>;
 
 declare module '@polkadot/api-base/types/consts' {
   interface AugmentedConsts<ApiType extends ApiTypes> {
+    appPromotion: {
+      /**
+       * Rate of return for interval in blocks defined in `RecalculationInterval`.
+       **/
+      intervalIncome: Perbill & AugmentedConst<ApiType>;
+      /**
+       * Decimals for the `Currency`.
+       **/
+      nominal: u128 & AugmentedConst<ApiType>;
+      /**
+       * The app's pallet id, used for deriving its sovereign account ID.
+       **/
+      palletId: FrameSupportPalletId & AugmentedConst<ApiType>;
+      /**
+       * In parachain blocks.
+       **/
+      pendingInterval: u32 & AugmentedConst<ApiType>;
+      /**
+       * In relay blocks.
+       **/
+      recalculationInterval: u32 & AugmentedConst<ApiType>;
+      /**
+       * Generic const
+       **/
+      [key: string]: Codec;
+    };
     balances: {
       /**
        * The minimum amount required to keep an account open.
modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-errors.ts
+++ b/tests/src/interfaces/augment-api-errors.ts
@@ -11,6 +11,36 @@
 
 declare module '@polkadot/api-base/types/errors' {
   interface AugmentedErrors<ApiType extends ApiTypes> {
+    appPromotion: {
+      /**
+       * Error due to action requiring admin to be set.
+       **/
+      AdminNotSet: AugmentedError<ApiType>;
+      /**
+       * Errors caused by incorrect actions with a locked balance.
+       **/
+      IncorrectLockedBalanceOperation: AugmentedError<ApiType>;
+      /**
+       * No permission to perform an action.
+       **/
+      NoPermission: AugmentedError<ApiType>;
+      /**
+       * Insufficient funds to perform an action.
+       **/
+      NotSufficientFunds: AugmentedError<ApiType>;
+      /**
+       * Occurs when a pending unstake cannot be added in this block. PENDING_LIMIT_PER_BLOCK` limits exceeded.
+       **/
+      PendingForBlockOverflow: AugmentedError<ApiType>;
+      /**
+       * The error is due to the fact that the collection/contract must already be sponsored in order to perform the action.
+       **/
+      SponsorNotSet: AugmentedError<ApiType>;
+      /**
+       * Generic error
+       **/
+      [key: string]: AugmentedError<ApiType>;
+    };
     balances: {
       /**
        * Beneficiary account must pre-exist
@@ -265,8 +295,12 @@
     };
     evmContractHelpers: {
       /**
-       * This method is only executable by owner
+       * No pending sponsor for contract.
        **/
+      NoPendingSponsor: AugmentedError<ApiType>;
+      /**
+       * This method is only executable by contract owner
+       **/
       NoPermission: AugmentedError<ApiType>;
       /**
        * Generic error
@@ -274,7 +308,13 @@
       [key: string]: AugmentedError<ApiType>;
     };
     evmMigration: {
+      /**
+       * Migration of this account is not yet started, or already finished.
+       **/
       AccountIsNotMigrating: AugmentedError<ApiType>;
+      /**
+       * Can only migrate to empty address.
+       **/
       AccountNotEmpty: AugmentedError<ApiType>;
       /**
        * Generic error
modifiedtests/src/interfaces/augment-api-events.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-events.ts
+++ b/tests/src/interfaces/augment-api-events.ts
@@ -15,6 +15,44 @@
 
 declare module '@polkadot/api-base/types/events' {
   interface AugmentedEvents<ApiType extends ApiTypes> {
+    appPromotion: {
+      /**
+       * The admin was set
+       * 
+       * # Arguments
+       * * AccountId: ID of the admin
+       **/
+      SetAdmin: AugmentedEvent<ApiType, [AccountId32]>;
+      /**
+       * Staking was performed
+       * 
+       * # Arguments
+       * * AccountId: ID of the staker
+       * * Balance : staking amount
+       **/
+      Stake: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      /**
+       * Staking recalculation was performed
+       * 
+       * # Arguments
+       * * AccountId: ID of the staker.
+       * * Balance : recalculation base
+       * * Balance : total income
+       **/
+      StakingRecalculation: AugmentedEvent<ApiType, [AccountId32, u128, u128]>;
+      /**
+       * Unstaking was performed
+       * 
+       * # Arguments
+       * * AccountId: ID of the staker
+       * * Balance : unstaking amount
+       **/
+      Unstake: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      /**
+       * Generic event
+       **/
+      [key: string]: AugmentedEvent<ApiType>;
+    };
     balances: {
       /**
        * A balance was set by root.
@@ -208,6 +246,24 @@
        **/
       [key: string]: AugmentedEvent<ApiType>;
     };
+    evmContractHelpers: {
+      /**
+       * Collection sponsor was removed.
+       **/
+      ContractSponsorRemoved: AugmentedEvent<ApiType, [H160]>;
+      /**
+       * Contract sponsor was set.
+       **/
+      ContractSponsorSet: AugmentedEvent<ApiType, [H160, AccountId32]>;
+      /**
+       * New sponsor was confirm.
+       **/
+      ContractSponsorshipConfirmed: AugmentedEvent<ApiType, [H160, AccountId32]>;
+      /**
+       * Generic event
+       **/
+      [key: string]: AugmentedEvent<ApiType>;
+    };
     parachainSystem: {
       /**
        * Downward messages were processed using the given weight.
modifiedtests/src/interfaces/augment-api-query.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-query.ts
+++ b/tests/src/interfaces/augment-api-query.ts
@@ -6,10 +6,10 @@
 import '@polkadot/api-base/types/storage';
 
 import type { ApiTypes, AugmentedQuery, QueryableStorageEntry } from '@polkadot/api-base/types';
-import type { BTreeMap, Bytes, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types-codec';
+import type { BTreeMap, Bytes, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';
 import type { AnyNumber, ITuple } from '@polkadot/types-codec/types';
 import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime';
-import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsTokenChild } from '@polkadot/types/lookup';
+import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild } from '@polkadot/types/lookup';
 import type { Observable } from '@polkadot/types/types';
 
 export type __AugmentedQuery<ApiType extends ApiTypes> = AugmentedQuery<ApiType, () => unknown>;
@@ -17,6 +17,28 @@
 
 declare module '@polkadot/api-base/types/storage' {
   interface AugmentedQueries<ApiType extends ApiTypes> {
+    appPromotion: {
+      admin: AugmentedQuery<ApiType, () => Observable<Option<AccountId32>>, []> & QueryableStorageEntry<ApiType, []>;
+      /**
+       * Stores a key for record for which the next revenue recalculation would be performed.
+       * If `None`, then recalculation has not yet been performed or calculations have been completed for all stakers.
+       **/
+      nextCalculatedRecord: AugmentedQuery<ApiType, () => Observable<Option<ITuple<[AccountId32, u32]>>>, []> & QueryableStorageEntry<ApiType, []>;
+      pendingUnstake: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Vec<ITuple<[AccountId32, u128]>>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
+      /**
+       * Amount of tokens staked by account in the blocknumber.
+       **/
+      staked: AugmentedQuery<ApiType, (arg1: AccountId32 | string | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<ITuple<[u128, u32]>>, [AccountId32, u32]> & QueryableStorageEntry<ApiType, [AccountId32, u32]>;
+      /**
+       * Amount of stakes for an Account
+       **/
+      stakesPerAccount: AugmentedQuery<ApiType, (arg: AccountId32 | string | Uint8Array) => Observable<u8>, [AccountId32]> & QueryableStorageEntry<ApiType, [AccountId32]>;
+      totalStaked: AugmentedQuery<ApiType, () => Observable<u128>, []> & QueryableStorageEntry<ApiType, []>;
+      /**
+       * Generic query
+       **/
+      [key: string]: QueryableStorageEntry<ApiType>;
+    };
     balances: {
       /**
        * The Balances pallet example of storing the balance of an account.
@@ -194,12 +216,66 @@
       [key: string]: QueryableStorageEntry<ApiType>;
     };
     evmContractHelpers: {
+      /**
+       * Storage for users that allowed for sponsorship.
+       * 
+       * ### Usage
+       * Prefer to delete record from storage if user no more allowed for sponsorship.
+       * 
+       * * **Key1** - contract address.
+       * * **Key2** - user that allowed for sponsorship.
+       * * **Value** - allowance for sponsorship.
+       **/
       allowlist: AugmentedQuery<ApiType, (arg1: H160 | string | Uint8Array, arg2: H160 | string | Uint8Array) => Observable<bool>, [H160, H160]> & QueryableStorageEntry<ApiType, [H160, H160]>;
+      /**
+       * Storege for contracts with [`Allowlisted`](SponsoringModeT::Allowlisted) sponsoring mode.
+       * 
+       * ### Usage
+       * Prefer to delete collection from storage if mode chaged to non `Allowlisted`, than set **Value** to **false**.
+       * 
+       * * **Key** - contract address.
+       * * **Value** - is contract in [`Allowlisted`](SponsoringModeT::Allowlisted) mode.
+       **/
       allowlistEnabled: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<bool>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;
+      /**
+       * Store owner for contract.
+       * 
+       * * **Key** - contract address.
+       * * **Value** - owner for contract.
+       **/
       owner: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<H160>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;
       selfSponsoring: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<bool>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;
+      /**
+       * Storage for last sponsored block.
+       * 
+       * * **Key1** - contract address.
+       * * **Key2** - sponsored user address.
+       * * **Value** - last sponsored block number.
+       **/
       sponsorBasket: AugmentedQuery<ApiType, (arg1: H160 | string | Uint8Array, arg2: H160 | string | Uint8Array) => Observable<Option<u32>>, [H160, H160]> & QueryableStorageEntry<ApiType, [H160, H160]>;
+      /**
+       * Store for contract sponsorship state.
+       * 
+       * * **Key** - contract address.
+       * * **Value** - sponsorship state.
+       **/
+      sponsoring: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<UpDataStructsSponsorshipStateBasicCrossAccountIdRepr>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;
+      /**
+       * Store for sponsoring mode.
+       * 
+       * ### Usage
+       * Prefer to delete collection from storage if mode chaged to [`Disabled`](SponsoringModeT::Disabled).
+       * 
+       * * **Key** - contract address.
+       * * **Value** - [`sponsoring mode`](SponsoringModeT).
+       **/
       sponsoringMode: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<Option<PalletEvmContractHelpersSponsoringModeT>>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;
+      /**
+       * Storage for sponsoring rate limit in blocks.
+       * 
+       * * **Key** - contract address.
+       * * **Value** - amount of sponsored blocks.
+       **/
       sponsoringRateLimit: AugmentedQuery<ApiType, (arg: H160 | string | Uint8Array) => Observable<u32>, [H160]> & QueryableStorageEntry<ApiType, [H160]>;
       /**
        * Generic query
@@ -281,7 +357,7 @@
        * 
        * Currently used to store RMRK data.
        **/
-      tokenAuxProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: UpDataStructsPropertyScope | 'None' | 'Rmrk' | 'Eth' | number | Uint8Array, arg4: Bytes | string | Uint8Array) => Observable<Option<Bytes>>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry<ApiType, [u32, u32, UpDataStructsPropertyScope, Bytes]>;
+      tokenAuxProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: UpDataStructsPropertyScope | 'None' | 'Rmrk' | number | Uint8Array, arg4: Bytes | string | Uint8Array) => Observable<Option<Bytes>>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry<ApiType, [u32, u32, UpDataStructsPropertyScope, Bytes]>;
       /**
        * Used to enumerate token's children.
        **/
modifiedtests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-rpc.ts
+++ b/tests/src/interfaces/augment-api-rpc.ts
@@ -9,7 +9,7 @@
 import type { AugmentedRpc } from '@polkadot/rpc-core/types';
 import type { Metadata, StorageKey } from '@polkadot/types';
 import type { Bytes, HashMap, Json, Null, Option, Text, U256, U64, Vec, bool, f64, u128, u32, u64 } from '@polkadot/types-codec';
-import type { AnyNumber, Codec } from '@polkadot/types-codec/types';
+import type { AnyNumber, Codec, ITuple } from '@polkadot/types-codec/types';
 import type { ExtrinsicOrHash, ExtrinsicStatus } from '@polkadot/types/interfaces/author';
 import type { EpochAuthorship } from '@polkadot/types/interfaces/babe';
 import type { BeefySignedCommitment } from '@polkadot/types/interfaces/beefy';
@@ -35,6 +35,24 @@
 
 declare module '@polkadot/rpc-core/types/jsonrpc' {
   interface RpcInterface {
+    appPromotion: {
+      /**
+       * Returns the total amount of unstaked tokens
+       **/
+      pendingUnstake: AugmentedRpc<(staker?: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u128>>;
+      /**
+       * Returns the total amount of unstaked tokens per block
+       **/
+      pendingUnstakePerBlock: AugmentedRpc<(staker: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<ITuple<[u32, u128]>>>>;
+      /**
+       * Returns the total amount of staked tokens
+       **/
+      totalStaked: AugmentedRpc<(staker?: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u128>>;
+      /**
+       * Returns the total amount of staked tokens per block when staked
+       **/
+      totalStakedPerBlock: AugmentedRpc<(staker: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<ITuple<[u32, u128]>>>>;
+    };
     author: {
       /**
        * Returns true if the keystore has private keys for the given public key and key type.
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -17,6 +17,20 @@
 
 declare module '@polkadot/api-base/types/submittable' {
   interface AugmentedSubmittables<ApiType extends ApiTypes> {
+    appPromotion: {
+      payoutStakers: AugmentedSubmittable<(stakersNumber: Option<u8> | null | Uint8Array | u8 | AnyNumber) => SubmittableExtrinsic<ApiType>, [Option<u8>]>;
+      setAdminAddress: AugmentedSubmittable<(admin: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletEvmAccountBasicCrossAccountIdRepr]>;
+      sponsorCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
+      sponsorContract: AugmentedSubmittable<(contractId: H160 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H160]>;
+      stake: AugmentedSubmittable<(amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u128]>;
+      stopSponsoringCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
+      stopSponsoringContract: AugmentedSubmittable<(contractId: H160 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H160]>;
+      unstake: AugmentedSubmittable<() => SubmittableExtrinsic<ApiType>, []>;
+      /**
+       * Generic tx
+       **/
+      [key: string]: SubmittableExtrinsicFunction<ApiType>;
+    };
     balances: {
       /**
        * Exactly as `transfer`, except the origin must be root and the source account may be
@@ -181,8 +195,21 @@
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
     evmMigration: {
+      /**
+       * Start contract migration, inserts contract stub at target address,
+       * and marks account as pending, allowing to insert storage
+       **/
       begin: AugmentedSubmittable<(address: H160 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H160]>;
+      /**
+       * Finish contract migration, allows it to be called.
+       * It is not possible to alter contract storage via [`Self::set_data`]
+       * after this call.
+       **/
       finish: AugmentedSubmittable<(address: H160 | string | Uint8Array, code: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [H160, Bytes]>;
+      /**
+       * Insert items into contract storage, this method can be called
+       * multiple times
+       **/
       setData: AugmentedSubmittable<(address: H160 | string | Uint8Array, data: Vec<ITuple<[H256, H256]>> | ([H256 | string | Uint8Array, H256 | string | Uint8Array])[]) => SubmittableExtrinsic<ApiType>, [H160, Vec<ITuple<[H256, H256]>>]>;
       /**
        * Generic tx
modifiedtests/src/interfaces/augment-types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-types.ts
+++ b/tests/src/interfaces/augment-types.ts
@@ -5,7 +5,7 @@
 // this is required to allow for ambient/previous definitions
 import '@polkadot/types/types/registry';
 
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
 import type { Data, StorageKey } from '@polkadot/types';
 import type { BitVec, Bool, Bytes, F32, F64, I128, I16, I256, I32, I64, I8, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, f32, f64, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec';
 import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';
@@ -804,6 +804,9 @@
     Owner: Owner;
     PageCounter: PageCounter;
     PageIndexData: PageIndexData;
+    PalletAppPromotionCall: PalletAppPromotionCall;
+    PalletAppPromotionError: PalletAppPromotionError;
+    PalletAppPromotionEvent: PalletAppPromotionEvent;
     PalletBalancesAccountData: PalletBalancesAccountData;
     PalletBalancesBalanceLock: PalletBalancesBalanceLock;
     PalletBalancesCall: PalletBalancesCall;
@@ -832,6 +835,7 @@
     PalletEvmCall: PalletEvmCall;
     PalletEvmCoderSubstrateError: PalletEvmCoderSubstrateError;
     PalletEvmContractHelpersError: PalletEvmContractHelpersError;
+    PalletEvmContractHelpersEvent: PalletEvmContractHelpersEvent;
     PalletEvmContractHelpersSponsoringModeT: PalletEvmContractHelpersSponsoringModeT;
     PalletEvmError: PalletEvmError;
     PalletEvmEvent: PalletEvmEvent;
@@ -1295,7 +1299,8 @@
     UpDataStructsPropertyScope: UpDataStructsPropertyScope;
     UpDataStructsRpcCollection: UpDataStructsRpcCollection;
     UpDataStructsSponsoringRateLimit: UpDataStructsSponsoringRateLimit;
-    UpDataStructsSponsorshipState: UpDataStructsSponsorshipState;
+    UpDataStructsSponsorshipStateAccountId32: UpDataStructsSponsorshipStateAccountId32;
+    UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: UpDataStructsSponsorshipStateBasicCrossAccountIdRepr;
     UpDataStructsTokenChild: UpDataStructsTokenChild;
     UpDataStructsTokenData: UpDataStructsTokenData;
     UpgradeGoAhead: UpgradeGoAhead;
modifiedtests/src/interfaces/default/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -806,6 +806,64 @@
   readonly perPeriod: Compact<u128>;
 }
 
+/** @name PalletAppPromotionCall */
+export interface PalletAppPromotionCall extends Enum {
+  readonly isSetAdminAddress: boolean;
+  readonly asSetAdminAddress: {
+    readonly admin: PalletEvmAccountBasicCrossAccountIdRepr;
+  } & Struct;
+  readonly isStake: boolean;
+  readonly asStake: {
+    readonly amount: u128;
+  } & Struct;
+  readonly isUnstake: boolean;
+  readonly isSponsorCollection: boolean;
+  readonly asSponsorCollection: {
+    readonly collectionId: u32;
+  } & Struct;
+  readonly isStopSponsoringCollection: boolean;
+  readonly asStopSponsoringCollection: {
+    readonly collectionId: u32;
+  } & Struct;
+  readonly isSponsorContract: boolean;
+  readonly asSponsorContract: {
+    readonly contractId: H160;
+  } & Struct;
+  readonly isStopSponsoringContract: boolean;
+  readonly asStopSponsoringContract: {
+    readonly contractId: H160;
+  } & Struct;
+  readonly isPayoutStakers: boolean;
+  readonly asPayoutStakers: {
+    readonly stakersNumber: Option<u8>;
+  } & Struct;
+  readonly type: 'SetAdminAddress' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers';
+}
+
+/** @name PalletAppPromotionError */
+export interface PalletAppPromotionError extends Enum {
+  readonly isAdminNotSet: boolean;
+  readonly isNoPermission: boolean;
+  readonly isNotSufficientFunds: boolean;
+  readonly isPendingForBlockOverflow: boolean;
+  readonly isSponsorNotSet: boolean;
+  readonly isIncorrectLockedBalanceOperation: boolean;
+  readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation';
+}
+
+/** @name PalletAppPromotionEvent */
+export interface PalletAppPromotionEvent extends Enum {
+  readonly isStakingRecalculation: boolean;
+  readonly asStakingRecalculation: ITuple<[AccountId32, u128, u128]>;
+  readonly isStake: boolean;
+  readonly asStake: ITuple<[AccountId32, u128]>;
+  readonly isUnstake: boolean;
+  readonly asUnstake: ITuple<[AccountId32, u128]>;
+  readonly isSetAdmin: boolean;
+  readonly asSetAdmin: AccountId32;
+  readonly type: 'StakingRecalculation' | 'Stake' | 'Unstake' | 'SetAdmin';
+}
+
 /** @name PalletBalancesAccountData */
 export interface PalletBalancesAccountData extends Struct {
   readonly free: u128;
@@ -1127,7 +1185,19 @@
 /** @name PalletEvmContractHelpersError */
 export interface PalletEvmContractHelpersError extends Enum {
   readonly isNoPermission: boolean;
-  readonly type: 'NoPermission';
+  readonly isNoPendingSponsor: boolean;
+  readonly type: 'NoPermission' | 'NoPendingSponsor';
+}
+
+/** @name PalletEvmContractHelpersEvent */
+export interface PalletEvmContractHelpersEvent extends Enum {
+  readonly isContractSponsorSet: boolean;
+  readonly asContractSponsorSet: ITuple<[H160, AccountId32]>;
+  readonly isContractSponsorshipConfirmed: boolean;
+  readonly asContractSponsorshipConfirmed: ITuple<[H160, AccountId32]>;
+  readonly isContractSponsorRemoved: boolean;
+  readonly asContractSponsorRemoved: H160;
+  readonly type: 'ContractSponsorSet' | 'ContractSponsorshipConfirmed' | 'ContractSponsorRemoved';
 }
 
 /** @name PalletEvmContractHelpersSponsoringModeT */
@@ -2419,7 +2489,7 @@
   readonly name: Vec<u16>;
   readonly description: Vec<u16>;
   readonly tokenPrefix: Bytes;
-  readonly sponsorship: UpDataStructsSponsorshipState;
+  readonly sponsorship: UpDataStructsSponsorshipStateAccountId32;
   readonly limits: UpDataStructsCollectionLimits;
   readonly permissions: UpDataStructsCollectionPermissions;
   readonly externalCollection: bool;
@@ -2580,8 +2650,7 @@
 export interface UpDataStructsPropertyScope extends Enum {
   readonly isNone: boolean;
   readonly isRmrk: boolean;
-  readonly isEth: boolean;
-  readonly type: 'None' | 'Rmrk' | 'Eth';
+  readonly type: 'None' | 'Rmrk';
 }
 
 /** @name UpDataStructsRpcCollection */
@@ -2591,7 +2660,7 @@
   readonly name: Vec<u16>;
   readonly description: Vec<u16>;
   readonly tokenPrefix: Bytes;
-  readonly sponsorship: UpDataStructsSponsorshipState;
+  readonly sponsorship: UpDataStructsSponsorshipStateAccountId32;
   readonly limits: UpDataStructsCollectionLimits;
   readonly permissions: UpDataStructsCollectionPermissions;
   readonly tokenPropertyPermissions: Vec<UpDataStructsPropertyKeyPermission>;
@@ -2607,8 +2676,8 @@
   readonly type: 'SponsoringDisabled' | 'Blocks';
 }
 
-/** @name UpDataStructsSponsorshipState */
-export interface UpDataStructsSponsorshipState extends Enum {
+/** @name UpDataStructsSponsorshipStateAccountId32 */
+export interface UpDataStructsSponsorshipStateAccountId32 extends Enum {
   readonly isDisabled: boolean;
   readonly isUnconfirmed: boolean;
   readonly asUnconfirmed: AccountId32;
@@ -2617,6 +2686,16 @@
   readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
 }
 
+/** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr */
+export interface UpDataStructsSponsorshipStateBasicCrossAccountIdRepr extends Enum {
+  readonly isDisabled: boolean;
+  readonly isUnconfirmed: boolean;
+  readonly asUnconfirmed: PalletEvmAccountBasicCrossAccountIdRepr;
+  readonly isConfirmed: boolean;
+  readonly asConfirmed: PalletEvmAccountBasicCrossAccountIdRepr;
+  readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
+}
+
 /** @name UpDataStructsTokenChild */
 export interface UpDataStructsTokenChild extends Struct {
   readonly token: u32;
modifiedtests/src/interfaces/definitions.tsdiffbeforeafterboth
--- a/tests/src/interfaces/definitions.ts
+++ b/tests/src/interfaces/definitions.ts
@@ -15,5 +15,6 @@
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
 export {default as unique} from './unique/definitions';
+export {default as appPromotion} from './appPromotion/definitions';
 export {default as rmrk} from './rmrk/definitions';
 export {default as default} from './default/definitions';
\ No newline at end of file
modifiedtests/src/interfaces/lookup.tsdiffbeforeafterboth
before · tests/src/interfaces/lookup.ts
1// Auto-generated via `yarn polkadot-types-from-defs`, do not edit2/* eslint-disable */34/* eslint-disable sort-keys */56export default {7  /**8   * Lookup3: frame_system::AccountInfo<Index, pallet_balances::AccountData<Balance>>9   **/10  FrameSystemAccountInfo: {11    nonce: 'u32',12    consumers: 'u32',13    providers: 'u32',14    sufficients: 'u32',15    data: 'PalletBalancesAccountData'16  },17  /**18   * Lookup5: pallet_balances::AccountData<Balance>19   **/20  PalletBalancesAccountData: {21    free: 'u128',22    reserved: 'u128',23    miscFrozen: 'u128',24    feeFrozen: 'u128'25  },26  /**27   * Lookup7: frame_support::weights::PerDispatchClass<T>28   **/29  FrameSupportWeightsPerDispatchClassU64: {30    normal: 'u64',31    operational: 'u64',32    mandatory: 'u64'33  },34  /**35   * Lookup11: sp_runtime::generic::digest::Digest36   **/37  SpRuntimeDigest: {38    logs: 'Vec<SpRuntimeDigestDigestItem>'39  },40  /**41   * Lookup13: sp_runtime::generic::digest::DigestItem42   **/43  SpRuntimeDigestDigestItem: {44    _enum: {45      Other: 'Bytes',46      __Unused1: 'Null',47      __Unused2: 'Null',48      __Unused3: 'Null',49      Consensus: '([u8;4],Bytes)',50      Seal: '([u8;4],Bytes)',51      PreRuntime: '([u8;4],Bytes)',52      __Unused7: 'Null',53      RuntimeEnvironmentUpdated: 'Null'54    }55  },56  /**57   * Lookup16: frame_system::EventRecord<opal_runtime::Event, primitive_types::H256>58   **/59  FrameSystemEventRecord: {60    phase: 'FrameSystemPhase',61    event: 'Event',62    topics: 'Vec<H256>'63  },64  /**65   * Lookup18: frame_system::pallet::Event<T>66   **/67  FrameSystemEvent: {68    _enum: {69      ExtrinsicSuccess: {70        dispatchInfo: 'FrameSupportWeightsDispatchInfo',71      },72      ExtrinsicFailed: {73        dispatchError: 'SpRuntimeDispatchError',74        dispatchInfo: 'FrameSupportWeightsDispatchInfo',75      },76      CodeUpdated: 'Null',77      NewAccount: {78        account: 'AccountId32',79      },80      KilledAccount: {81        account: 'AccountId32',82      },83      Remarked: {84        _alias: {85          hash_: 'hash',86        },87        sender: 'AccountId32',88        hash_: 'H256'89      }90    }91  },92  /**93   * Lookup19: frame_support::weights::DispatchInfo94   **/95  FrameSupportWeightsDispatchInfo: {96    weight: 'u64',97    class: 'FrameSupportWeightsDispatchClass',98    paysFee: 'FrameSupportWeightsPays'99  },100  /**101   * Lookup20: frame_support::weights::DispatchClass102   **/103  FrameSupportWeightsDispatchClass: {104    _enum: ['Normal', 'Operational', 'Mandatory']105  },106  /**107   * Lookup21: frame_support::weights::Pays108   **/109  FrameSupportWeightsPays: {110    _enum: ['Yes', 'No']111  },112  /**113   * Lookup22: sp_runtime::DispatchError114   **/115  SpRuntimeDispatchError: {116    _enum: {117      Other: 'Null',118      CannotLookup: 'Null',119      BadOrigin: 'Null',120      Module: 'SpRuntimeModuleError',121      ConsumerRemaining: 'Null',122      NoProviders: 'Null',123      TooManyConsumers: 'Null',124      Token: 'SpRuntimeTokenError',125      Arithmetic: 'SpRuntimeArithmeticError',126      Transactional: 'SpRuntimeTransactionalError'127    }128  },129  /**130   * Lookup23: sp_runtime::ModuleError131   **/132  SpRuntimeModuleError: {133    index: 'u8',134    error: '[u8;4]'135  },136  /**137   * Lookup24: sp_runtime::TokenError138   **/139  SpRuntimeTokenError: {140    _enum: ['NoFunds', 'WouldDie', 'BelowMinimum', 'CannotCreate', 'UnknownAsset', 'Frozen', 'Unsupported']141  },142  /**143   * Lookup25: sp_runtime::ArithmeticError144   **/145  SpRuntimeArithmeticError: {146    _enum: ['Underflow', 'Overflow', 'DivisionByZero']147  },148  /**149   * Lookup26: sp_runtime::TransactionalError150   **/151  SpRuntimeTransactionalError: {152    _enum: ['LimitReached', 'NoLayer']153  },154  /**155   * Lookup27: cumulus_pallet_parachain_system::pallet::Event<T>156   **/157  CumulusPalletParachainSystemEvent: {158    _enum: {159      ValidationFunctionStored: 'Null',160      ValidationFunctionApplied: {161        relayChainBlockNum: 'u32',162      },163      ValidationFunctionDiscarded: 'Null',164      UpgradeAuthorized: {165        codeHash: 'H256',166      },167      DownwardMessagesReceived: {168        count: 'u32',169      },170      DownwardMessagesProcessed: {171        weightUsed: 'u64',172        dmqHead: 'H256'173      }174    }175  },176  /**177   * Lookup28: pallet_balances::pallet::Event<T, I>178   **/179  PalletBalancesEvent: {180    _enum: {181      Endowed: {182        account: 'AccountId32',183        freeBalance: 'u128',184      },185      DustLost: {186        account: 'AccountId32',187        amount: 'u128',188      },189      Transfer: {190        from: 'AccountId32',191        to: 'AccountId32',192        amount: 'u128',193      },194      BalanceSet: {195        who: 'AccountId32',196        free: 'u128',197        reserved: 'u128',198      },199      Reserved: {200        who: 'AccountId32',201        amount: 'u128',202      },203      Unreserved: {204        who: 'AccountId32',205        amount: 'u128',206      },207      ReserveRepatriated: {208        from: 'AccountId32',209        to: 'AccountId32',210        amount: 'u128',211        destinationStatus: 'FrameSupportTokensMiscBalanceStatus',212      },213      Deposit: {214        who: 'AccountId32',215        amount: 'u128',216      },217      Withdraw: {218        who: 'AccountId32',219        amount: 'u128',220      },221      Slashed: {222        who: 'AccountId32',223        amount: 'u128'224      }225    }226  },227  /**228   * Lookup29: frame_support::traits::tokens::misc::BalanceStatus229   **/230  FrameSupportTokensMiscBalanceStatus: {231    _enum: ['Free', 'Reserved']232  },233  /**234   * Lookup30: pallet_transaction_payment::pallet::Event<T>235   **/236  PalletTransactionPaymentEvent: {237    _enum: {238      TransactionFeePaid: {239        who: 'AccountId32',240        actualFee: 'u128',241        tip: 'u128'242      }243    }244  },245  /**246   * Lookup31: pallet_treasury::pallet::Event<T, I>247   **/248  PalletTreasuryEvent: {249    _enum: {250      Proposed: {251        proposalIndex: 'u32',252      },253      Spending: {254        budgetRemaining: 'u128',255      },256      Awarded: {257        proposalIndex: 'u32',258        award: 'u128',259        account: 'AccountId32',260      },261      Rejected: {262        proposalIndex: 'u32',263        slashed: 'u128',264      },265      Burnt: {266        burntFunds: 'u128',267      },268      Rollover: {269        rolloverBalance: 'u128',270      },271      Deposit: {272        value: 'u128',273      },274      SpendApproved: {275        proposalIndex: 'u32',276        amount: 'u128',277        beneficiary: 'AccountId32'278      }279    }280  },281  /**282   * Lookup32: pallet_sudo::pallet::Event<T>283   **/284  PalletSudoEvent: {285    _enum: {286      Sudid: {287        sudoResult: 'Result<Null, SpRuntimeDispatchError>',288      },289      KeyChanged: {290        oldSudoer: 'Option<AccountId32>',291      },292      SudoAsDone: {293        sudoResult: 'Result<Null, SpRuntimeDispatchError>'294      }295    }296  },297  /**298   * Lookup36: orml_vesting::module::Event<T>299   **/300  OrmlVestingModuleEvent: {301    _enum: {302      VestingScheduleAdded: {303        from: 'AccountId32',304        to: 'AccountId32',305        vestingSchedule: 'OrmlVestingVestingSchedule',306      },307      Claimed: {308        who: 'AccountId32',309        amount: 'u128',310      },311      VestingSchedulesUpdated: {312        who: 'AccountId32'313      }314    }315  },316  /**317   * Lookup37: orml_vesting::VestingSchedule<BlockNumber, Balance>318   **/319  OrmlVestingVestingSchedule: {320    start: 'u32',321    period: 'u32',322    periodCount: 'u32',323    perPeriod: 'Compact<u128>'324  },325  /**326   * Lookup39: cumulus_pallet_xcmp_queue::pallet::Event<T>327   **/328  CumulusPalletXcmpQueueEvent: {329    _enum: {330      Success: {331        messageHash: 'Option<H256>',332        weight: 'u64',333      },334      Fail: {335        messageHash: 'Option<H256>',336        error: 'XcmV2TraitsError',337        weight: 'u64',338      },339      BadVersion: {340        messageHash: 'Option<H256>',341      },342      BadFormat: {343        messageHash: 'Option<H256>',344      },345      UpwardMessageSent: {346        messageHash: 'Option<H256>',347      },348      XcmpMessageSent: {349        messageHash: 'Option<H256>',350      },351      OverweightEnqueued: {352        sender: 'u32',353        sentAt: 'u32',354        index: 'u64',355        required: 'u64',356      },357      OverweightServiced: {358        index: 'u64',359        used: 'u64'360      }361    }362  },363  /**364   * Lookup41: xcm::v2::traits::Error365   **/366  XcmV2TraitsError: {367    _enum: {368      Overflow: 'Null',369      Unimplemented: 'Null',370      UntrustedReserveLocation: 'Null',371      UntrustedTeleportLocation: 'Null',372      MultiLocationFull: 'Null',373      MultiLocationNotInvertible: 'Null',374      BadOrigin: 'Null',375      InvalidLocation: 'Null',376      AssetNotFound: 'Null',377      FailedToTransactAsset: 'Null',378      NotWithdrawable: 'Null',379      LocationCannotHold: 'Null',380      ExceedsMaxMessageSize: 'Null',381      DestinationUnsupported: 'Null',382      Transport: 'Null',383      Unroutable: 'Null',384      UnknownClaim: 'Null',385      FailedToDecode: 'Null',386      MaxWeightInvalid: 'Null',387      NotHoldingFees: 'Null',388      TooExpensive: 'Null',389      Trap: 'u64',390      UnhandledXcmVersion: 'Null',391      WeightLimitReached: 'u64',392      Barrier: 'Null',393      WeightNotComputable: 'Null'394    }395  },396  /**397   * Lookup43: pallet_xcm::pallet::Event<T>398   **/399  PalletXcmEvent: {400    _enum: {401      Attempted: 'XcmV2TraitsOutcome',402      Sent: '(XcmV1MultiLocation,XcmV1MultiLocation,XcmV2Xcm)',403      UnexpectedResponse: '(XcmV1MultiLocation,u64)',404      ResponseReady: '(u64,XcmV2Response)',405      Notified: '(u64,u8,u8)',406      NotifyOverweight: '(u64,u8,u8,u64,u64)',407      NotifyDispatchError: '(u64,u8,u8)',408      NotifyDecodeFailed: '(u64,u8,u8)',409      InvalidResponder: '(XcmV1MultiLocation,u64,Option<XcmV1MultiLocation>)',410      InvalidResponderVersion: '(XcmV1MultiLocation,u64)',411      ResponseTaken: 'u64',412      AssetsTrapped: '(H256,XcmV1MultiLocation,XcmVersionedMultiAssets)',413      VersionChangeNotified: '(XcmV1MultiLocation,u32)',414      SupportedVersionChanged: '(XcmV1MultiLocation,u32)',415      NotifyTargetSendFail: '(XcmV1MultiLocation,u64,XcmV2TraitsError)',416      NotifyTargetMigrationFail: '(XcmVersionedMultiLocation,u64)'417    }418  },419  /**420   * Lookup44: xcm::v2::traits::Outcome421   **/422  XcmV2TraitsOutcome: {423    _enum: {424      Complete: 'u64',425      Incomplete: '(u64,XcmV2TraitsError)',426      Error: 'XcmV2TraitsError'427    }428  },429  /**430   * Lookup45: xcm::v1::multilocation::MultiLocation431   **/432  XcmV1MultiLocation: {433    parents: 'u8',434    interior: 'XcmV1MultilocationJunctions'435  },436  /**437   * Lookup46: xcm::v1::multilocation::Junctions438   **/439  XcmV1MultilocationJunctions: {440    _enum: {441      Here: 'Null',442      X1: 'XcmV1Junction',443      X2: '(XcmV1Junction,XcmV1Junction)',444      X3: '(XcmV1Junction,XcmV1Junction,XcmV1Junction)',445      X4: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',446      X5: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',447      X6: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',448      X7: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',449      X8: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)'450    }451  },452  /**453   * Lookup47: xcm::v1::junction::Junction454   **/455  XcmV1Junction: {456    _enum: {457      Parachain: 'Compact<u32>',458      AccountId32: {459        network: 'XcmV0JunctionNetworkId',460        id: '[u8;32]',461      },462      AccountIndex64: {463        network: 'XcmV0JunctionNetworkId',464        index: 'Compact<u64>',465      },466      AccountKey20: {467        network: 'XcmV0JunctionNetworkId',468        key: '[u8;20]',469      },470      PalletInstance: 'u8',471      GeneralIndex: 'Compact<u128>',472      GeneralKey: 'Bytes',473      OnlyChild: 'Null',474      Plurality: {475        id: 'XcmV0JunctionBodyId',476        part: 'XcmV0JunctionBodyPart'477      }478    }479  },480  /**481   * Lookup49: xcm::v0::junction::NetworkId482   **/483  XcmV0JunctionNetworkId: {484    _enum: {485      Any: 'Null',486      Named: 'Bytes',487      Polkadot: 'Null',488      Kusama: 'Null'489    }490  },491  /**492   * Lookup53: xcm::v0::junction::BodyId493   **/494  XcmV0JunctionBodyId: {495    _enum: {496      Unit: 'Null',497      Named: 'Bytes',498      Index: 'Compact<u32>',499      Executive: 'Null',500      Technical: 'Null',501      Legislative: 'Null',502      Judicial: 'Null'503    }504  },505  /**506   * Lookup54: xcm::v0::junction::BodyPart507   **/508  XcmV0JunctionBodyPart: {509    _enum: {510      Voice: 'Null',511      Members: {512        count: 'Compact<u32>',513      },514      Fraction: {515        nom: 'Compact<u32>',516        denom: 'Compact<u32>',517      },518      AtLeastProportion: {519        nom: 'Compact<u32>',520        denom: 'Compact<u32>',521      },522      MoreThanProportion: {523        nom: 'Compact<u32>',524        denom: 'Compact<u32>'525      }526    }527  },528  /**529   * Lookup55: xcm::v2::Xcm<Call>530   **/531  XcmV2Xcm: 'Vec<XcmV2Instruction>',532  /**533   * Lookup57: xcm::v2::Instruction<Call>534   **/535  XcmV2Instruction: {536    _enum: {537      WithdrawAsset: 'XcmV1MultiassetMultiAssets',538      ReserveAssetDeposited: 'XcmV1MultiassetMultiAssets',539      ReceiveTeleportedAsset: 'XcmV1MultiassetMultiAssets',540      QueryResponse: {541        queryId: 'Compact<u64>',542        response: 'XcmV2Response',543        maxWeight: 'Compact<u64>',544      },545      TransferAsset: {546        assets: 'XcmV1MultiassetMultiAssets',547        beneficiary: 'XcmV1MultiLocation',548      },549      TransferReserveAsset: {550        assets: 'XcmV1MultiassetMultiAssets',551        dest: 'XcmV1MultiLocation',552        xcm: 'XcmV2Xcm',553      },554      Transact: {555        originType: 'XcmV0OriginKind',556        requireWeightAtMost: 'Compact<u64>',557        call: 'XcmDoubleEncoded',558      },559      HrmpNewChannelOpenRequest: {560        sender: 'Compact<u32>',561        maxMessageSize: 'Compact<u32>',562        maxCapacity: 'Compact<u32>',563      },564      HrmpChannelAccepted: {565        recipient: 'Compact<u32>',566      },567      HrmpChannelClosing: {568        initiator: 'Compact<u32>',569        sender: 'Compact<u32>',570        recipient: 'Compact<u32>',571      },572      ClearOrigin: 'Null',573      DescendOrigin: 'XcmV1MultilocationJunctions',574      ReportError: {575        queryId: 'Compact<u64>',576        dest: 'XcmV1MultiLocation',577        maxResponseWeight: 'Compact<u64>',578      },579      DepositAsset: {580        assets: 'XcmV1MultiassetMultiAssetFilter',581        maxAssets: 'Compact<u32>',582        beneficiary: 'XcmV1MultiLocation',583      },584      DepositReserveAsset: {585        assets: 'XcmV1MultiassetMultiAssetFilter',586        maxAssets: 'Compact<u32>',587        dest: 'XcmV1MultiLocation',588        xcm: 'XcmV2Xcm',589      },590      ExchangeAsset: {591        give: 'XcmV1MultiassetMultiAssetFilter',592        receive: 'XcmV1MultiassetMultiAssets',593      },594      InitiateReserveWithdraw: {595        assets: 'XcmV1MultiassetMultiAssetFilter',596        reserve: 'XcmV1MultiLocation',597        xcm: 'XcmV2Xcm',598      },599      InitiateTeleport: {600        assets: 'XcmV1MultiassetMultiAssetFilter',601        dest: 'XcmV1MultiLocation',602        xcm: 'XcmV2Xcm',603      },604      QueryHolding: {605        queryId: 'Compact<u64>',606        dest: 'XcmV1MultiLocation',607        assets: 'XcmV1MultiassetMultiAssetFilter',608        maxResponseWeight: 'Compact<u64>',609      },610      BuyExecution: {611        fees: 'XcmV1MultiAsset',612        weightLimit: 'XcmV2WeightLimit',613      },614      RefundSurplus: 'Null',615      SetErrorHandler: 'XcmV2Xcm',616      SetAppendix: 'XcmV2Xcm',617      ClearError: 'Null',618      ClaimAsset: {619        assets: 'XcmV1MultiassetMultiAssets',620        ticket: 'XcmV1MultiLocation',621      },622      Trap: 'Compact<u64>',623      SubscribeVersion: {624        queryId: 'Compact<u64>',625        maxResponseWeight: 'Compact<u64>',626      },627      UnsubscribeVersion: 'Null'628    }629  },630  /**631   * Lookup58: xcm::v1::multiasset::MultiAssets632   **/633  XcmV1MultiassetMultiAssets: 'Vec<XcmV1MultiAsset>',634  /**635   * Lookup60: xcm::v1::multiasset::MultiAsset636   **/637  XcmV1MultiAsset: {638    id: 'XcmV1MultiassetAssetId',639    fun: 'XcmV1MultiassetFungibility'640  },641  /**642   * Lookup61: xcm::v1::multiasset::AssetId643   **/644  XcmV1MultiassetAssetId: {645    _enum: {646      Concrete: 'XcmV1MultiLocation',647      Abstract: 'Bytes'648    }649  },650  /**651   * Lookup62: xcm::v1::multiasset::Fungibility652   **/653  XcmV1MultiassetFungibility: {654    _enum: {655      Fungible: 'Compact<u128>',656      NonFungible: 'XcmV1MultiassetAssetInstance'657    }658  },659  /**660   * Lookup63: xcm::v1::multiasset::AssetInstance661   **/662  XcmV1MultiassetAssetInstance: {663    _enum: {664      Undefined: 'Null',665      Index: 'Compact<u128>',666      Array4: '[u8;4]',667      Array8: '[u8;8]',668      Array16: '[u8;16]',669      Array32: '[u8;32]',670      Blob: 'Bytes'671    }672  },673  /**674   * Lookup66: xcm::v2::Response675   **/676  XcmV2Response: {677    _enum: {678      Null: 'Null',679      Assets: 'XcmV1MultiassetMultiAssets',680      ExecutionResult: 'Option<(u32,XcmV2TraitsError)>',681      Version: 'u32'682    }683  },684  /**685   * Lookup69: xcm::v0::OriginKind686   **/687  XcmV0OriginKind: {688    _enum: ['Native', 'SovereignAccount', 'Superuser', 'Xcm']689  },690  /**691   * Lookup70: xcm::double_encoded::DoubleEncoded<T>692   **/693  XcmDoubleEncoded: {694    encoded: 'Bytes'695  },696  /**697   * Lookup71: xcm::v1::multiasset::MultiAssetFilter698   **/699  XcmV1MultiassetMultiAssetFilter: {700    _enum: {701      Definite: 'XcmV1MultiassetMultiAssets',702      Wild: 'XcmV1MultiassetWildMultiAsset'703    }704  },705  /**706   * Lookup72: xcm::v1::multiasset::WildMultiAsset707   **/708  XcmV1MultiassetWildMultiAsset: {709    _enum: {710      All: 'Null',711      AllOf: {712        id: 'XcmV1MultiassetAssetId',713        fun: 'XcmV1MultiassetWildFungibility'714      }715    }716  },717  /**718   * Lookup73: xcm::v1::multiasset::WildFungibility719   **/720  XcmV1MultiassetWildFungibility: {721    _enum: ['Fungible', 'NonFungible']722  },723  /**724   * Lookup74: xcm::v2::WeightLimit725   **/726  XcmV2WeightLimit: {727    _enum: {728      Unlimited: 'Null',729      Limited: 'Compact<u64>'730    }731  },732  /**733   * Lookup76: xcm::VersionedMultiAssets734   **/735  XcmVersionedMultiAssets: {736    _enum: {737      V0: 'Vec<XcmV0MultiAsset>',738      V1: 'XcmV1MultiassetMultiAssets'739    }740  },741  /**742   * Lookup78: xcm::v0::multi_asset::MultiAsset743   **/744  XcmV0MultiAsset: {745    _enum: {746      None: 'Null',747      All: 'Null',748      AllFungible: 'Null',749      AllNonFungible: 'Null',750      AllAbstractFungible: {751        id: 'Bytes',752      },753      AllAbstractNonFungible: {754        class: 'Bytes',755      },756      AllConcreteFungible: {757        id: 'XcmV0MultiLocation',758      },759      AllConcreteNonFungible: {760        class: 'XcmV0MultiLocation',761      },762      AbstractFungible: {763        id: 'Bytes',764        amount: 'Compact<u128>',765      },766      AbstractNonFungible: {767        class: 'Bytes',768        instance: 'XcmV1MultiassetAssetInstance',769      },770      ConcreteFungible: {771        id: 'XcmV0MultiLocation',772        amount: 'Compact<u128>',773      },774      ConcreteNonFungible: {775        class: 'XcmV0MultiLocation',776        instance: 'XcmV1MultiassetAssetInstance'777      }778    }779  },780  /**781   * Lookup79: xcm::v0::multi_location::MultiLocation782   **/783  XcmV0MultiLocation: {784    _enum: {785      Null: 'Null',786      X1: 'XcmV0Junction',787      X2: '(XcmV0Junction,XcmV0Junction)',788      X3: '(XcmV0Junction,XcmV0Junction,XcmV0Junction)',789      X4: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',790      X5: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',791      X6: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',792      X7: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',793      X8: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)'794    }795  },796  /**797   * Lookup80: xcm::v0::junction::Junction798   **/799  XcmV0Junction: {800    _enum: {801      Parent: 'Null',802      Parachain: 'Compact<u32>',803      AccountId32: {804        network: 'XcmV0JunctionNetworkId',805        id: '[u8;32]',806      },807      AccountIndex64: {808        network: 'XcmV0JunctionNetworkId',809        index: 'Compact<u64>',810      },811      AccountKey20: {812        network: 'XcmV0JunctionNetworkId',813        key: '[u8;20]',814      },815      PalletInstance: 'u8',816      GeneralIndex: 'Compact<u128>',817      GeneralKey: 'Bytes',818      OnlyChild: 'Null',819      Plurality: {820        id: 'XcmV0JunctionBodyId',821        part: 'XcmV0JunctionBodyPart'822      }823    }824  },825  /**826   * Lookup81: xcm::VersionedMultiLocation827   **/828  XcmVersionedMultiLocation: {829    _enum: {830      V0: 'XcmV0MultiLocation',831      V1: 'XcmV1MultiLocation'832    }833  },834  /**835   * Lookup82: cumulus_pallet_xcm::pallet::Event<T>836   **/837  CumulusPalletXcmEvent: {838    _enum: {839      InvalidFormat: '[u8;8]',840      UnsupportedVersion: '[u8;8]',841      ExecutedDownward: '([u8;8],XcmV2TraitsOutcome)'842    }843  },844  /**845   * Lookup83: cumulus_pallet_dmp_queue::pallet::Event<T>846   **/847  CumulusPalletDmpQueueEvent: {848    _enum: {849      InvalidFormat: {850        messageId: '[u8;32]',851      },852      UnsupportedVersion: {853        messageId: '[u8;32]',854      },855      ExecutedDownward: {856        messageId: '[u8;32]',857        outcome: 'XcmV2TraitsOutcome',858      },859      WeightExhausted: {860        messageId: '[u8;32]',861        remainingWeight: 'u64',862        requiredWeight: 'u64',863      },864      OverweightEnqueued: {865        messageId: '[u8;32]',866        overweightIndex: 'u64',867        requiredWeight: 'u64',868      },869      OverweightServiced: {870        overweightIndex: 'u64',871        weightUsed: 'u64'872      }873    }874  },875  /**876   * Lookup84: pallet_unique::RawEvent<sp_core::crypto::AccountId32, pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>877   **/878  PalletUniqueRawEvent: {879    _enum: {880      CollectionSponsorRemoved: 'u32',881      CollectionAdminAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',882      CollectionOwnedChanged: '(u32,AccountId32)',883      CollectionSponsorSet: '(u32,AccountId32)',884      SponsorshipConfirmed: '(u32,AccountId32)',885      CollectionAdminRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',886      AllowListAddressRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',887      AllowListAddressAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',888      CollectionLimitSet: 'u32',889      CollectionPermissionSet: 'u32'890    }891  },892  /**893   * Lookup85: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>894   **/895  PalletEvmAccountBasicCrossAccountIdRepr: {896    _enum: {897      Substrate: 'AccountId32',898      Ethereum: 'H160'899    }900  },901  /**902   * Lookup88: pallet_unique_scheduler::pallet::Event<T>903   **/904  PalletUniqueSchedulerEvent: {905    _enum: {906      Scheduled: {907        when: 'u32',908        index: 'u32',909      },910      Canceled: {911        when: 'u32',912        index: 'u32',913      },914      Dispatched: {915        task: '(u32,u32)',916        id: 'Option<[u8;16]>',917        result: 'Result<Null, SpRuntimeDispatchError>',918      },919      CallLookupFailed: {920        task: '(u32,u32)',921        id: 'Option<[u8;16]>',922        error: 'FrameSupportScheduleLookupError'923      }924    }925  },926  /**927   * Lookup91: frame_support::traits::schedule::LookupError928   **/929  FrameSupportScheduleLookupError: {930    _enum: ['Unknown', 'BadFormat']931  },932  /**933   * Lookup92: pallet_common::pallet::Event<T>934   **/935  PalletCommonEvent: {936    _enum: {937      CollectionCreated: '(u32,u8,AccountId32)',938      CollectionDestroyed: 'u32',939      ItemCreated: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',940      ItemDestroyed: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',941      Transfer: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',942      Approved: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',943      CollectionPropertySet: '(u32,Bytes)',944      CollectionPropertyDeleted: '(u32,Bytes)',945      TokenPropertySet: '(u32,u32,Bytes)',946      TokenPropertyDeleted: '(u32,u32,Bytes)',947      PropertyPermissionSet: '(u32,Bytes)'948    }949  },950  /**951   * Lookup95: pallet_structure::pallet::Event<T>952   **/953  PalletStructureEvent: {954    _enum: {955      Executed: 'Result<Null, SpRuntimeDispatchError>'956    }957  },958  /**959   * Lookup96: pallet_rmrk_core::pallet::Event<T>960   **/961  PalletRmrkCoreEvent: {962    _enum: {963      CollectionCreated: {964        issuer: 'AccountId32',965        collectionId: 'u32',966      },967      CollectionDestroyed: {968        issuer: 'AccountId32',969        collectionId: 'u32',970      },971      IssuerChanged: {972        oldIssuer: 'AccountId32',973        newIssuer: 'AccountId32',974        collectionId: 'u32',975      },976      CollectionLocked: {977        issuer: 'AccountId32',978        collectionId: 'u32',979      },980      NftMinted: {981        owner: 'AccountId32',982        collectionId: 'u32',983        nftId: 'u32',984      },985      NFTBurned: {986        owner: 'AccountId32',987        nftId: 'u32',988      },989      NFTSent: {990        sender: 'AccountId32',991        recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',992        collectionId: 'u32',993        nftId: 'u32',994        approvalRequired: 'bool',995      },996      NFTAccepted: {997        sender: 'AccountId32',998        recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',999        collectionId: 'u32',1000        nftId: 'u32',1001      },1002      NFTRejected: {1003        sender: 'AccountId32',1004        collectionId: 'u32',1005        nftId: 'u32',1006      },1007      PropertySet: {1008        collectionId: 'u32',1009        maybeNftId: 'Option<u32>',1010        key: 'Bytes',1011        value: 'Bytes',1012      },1013      ResourceAdded: {1014        nftId: 'u32',1015        resourceId: 'u32',1016      },1017      ResourceRemoval: {1018        nftId: 'u32',1019        resourceId: 'u32',1020      },1021      ResourceAccepted: {1022        nftId: 'u32',1023        resourceId: 'u32',1024      },1025      ResourceRemovalAccepted: {1026        nftId: 'u32',1027        resourceId: 'u32',1028      },1029      PrioritySet: {1030        collectionId: 'u32',1031        nftId: 'u32'1032      }1033    }1034  },1035  /**1036   * Lookup97: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>1037   **/1038  RmrkTraitsNftAccountIdOrCollectionNftTuple: {1039    _enum: {1040      AccountId: 'AccountId32',1041      CollectionAndNftTuple: '(u32,u32)'1042    }1043  },1044  /**1045   * Lookup102: pallet_rmrk_equip::pallet::Event<T>1046   **/1047  PalletRmrkEquipEvent: {1048    _enum: {1049      BaseCreated: {1050        issuer: 'AccountId32',1051        baseId: 'u32',1052      },1053      EquippablesUpdated: {1054        baseId: 'u32',1055        slotId: 'u32'1056      }1057    }1058  },1059  /**1060   * Lookup103: pallet_evm::pallet::Event<T>1061   **/1062  PalletEvmEvent: {1063    _enum: {1064      Log: 'EthereumLog',1065      Created: 'H160',1066      CreatedFailed: 'H160',1067      Executed: 'H160',1068      ExecutedFailed: 'H160',1069      BalanceDeposit: '(AccountId32,H160,U256)',1070      BalanceWithdraw: '(AccountId32,H160,U256)'1071    }1072  },1073  /**1074   * Lookup104: ethereum::log::Log1075   **/1076  EthereumLog: {1077    address: 'H160',1078    topics: 'Vec<H256>',1079    data: 'Bytes'1080  },1081  /**1082   * Lookup108: pallet_ethereum::pallet::Event1083   **/1084  PalletEthereumEvent: {1085    _enum: {1086      Executed: '(H160,H160,H256,EvmCoreErrorExitReason)'1087    }1088  },1089  /**1090   * Lookup109: evm_core::error::ExitReason1091   **/1092  EvmCoreErrorExitReason: {1093    _enum: {1094      Succeed: 'EvmCoreErrorExitSucceed',1095      Error: 'EvmCoreErrorExitError',1096      Revert: 'EvmCoreErrorExitRevert',1097      Fatal: 'EvmCoreErrorExitFatal'1098    }1099  },1100  /**1101   * Lookup110: evm_core::error::ExitSucceed1102   **/1103  EvmCoreErrorExitSucceed: {1104    _enum: ['Stopped', 'Returned', 'Suicided']1105  },1106  /**1107   * Lookup111: evm_core::error::ExitError1108   **/1109  EvmCoreErrorExitError: {1110    _enum: {1111      StackUnderflow: 'Null',1112      StackOverflow: 'Null',1113      InvalidJump: 'Null',1114      InvalidRange: 'Null',1115      DesignatedInvalid: 'Null',1116      CallTooDeep: 'Null',1117      CreateCollision: 'Null',1118      CreateContractLimit: 'Null',1119      OutOfOffset: 'Null',1120      OutOfGas: 'Null',1121      OutOfFund: 'Null',1122      PCUnderflow: 'Null',1123      CreateEmpty: 'Null',1124      Other: 'Text',1125      InvalidCode: 'Null'1126    }1127  },1128  /**1129   * Lookup114: evm_core::error::ExitRevert1130   **/1131  EvmCoreErrorExitRevert: {1132    _enum: ['Reverted']1133  },1134  /**1135   * Lookup115: evm_core::error::ExitFatal1136   **/1137  EvmCoreErrorExitFatal: {1138    _enum: {1139      NotSupported: 'Null',1140      UnhandledInterrupt: 'Null',1141      CallErrorAsFatal: 'EvmCoreErrorExitError',1142      Other: 'Text'1143    }1144  },1145  /**1146   * Lookup116: frame_system::Phase1147   **/1148  FrameSystemPhase: {1149    _enum: {1150      ApplyExtrinsic: 'u32',1151      Finalization: 'Null',1152      Initialization: 'Null'1153    }1154  },1155  /**1156   * Lookup118: frame_system::LastRuntimeUpgradeInfo1157   **/1158  FrameSystemLastRuntimeUpgradeInfo: {1159    specVersion: 'Compact<u32>',1160    specName: 'Text'1161  },1162  /**1163   * Lookup119: frame_system::pallet::Call<T>1164   **/1165  FrameSystemCall: {1166    _enum: {1167      fill_block: {1168        ratio: 'Perbill',1169      },1170      remark: {1171        remark: 'Bytes',1172      },1173      set_heap_pages: {1174        pages: 'u64',1175      },1176      set_code: {1177        code: 'Bytes',1178      },1179      set_code_without_checks: {1180        code: 'Bytes',1181      },1182      set_storage: {1183        items: 'Vec<(Bytes,Bytes)>',1184      },1185      kill_storage: {1186        _alias: {1187          keys_: 'keys',1188        },1189        keys_: 'Vec<Bytes>',1190      },1191      kill_prefix: {1192        prefix: 'Bytes',1193        subkeys: 'u32',1194      },1195      remark_with_event: {1196        remark: 'Bytes'1197      }1198    }1199  },1200  /**1201   * Lookup124: frame_system::limits::BlockWeights1202   **/1203  FrameSystemLimitsBlockWeights: {1204    baseBlock: 'u64',1205    maxBlock: 'u64',1206    perClass: 'FrameSupportWeightsPerDispatchClassWeightsPerClass'1207  },1208  /**1209   * Lookup125: frame_support::weights::PerDispatchClass<frame_system::limits::WeightsPerClass>1210   **/1211  FrameSupportWeightsPerDispatchClassWeightsPerClass: {1212    normal: 'FrameSystemLimitsWeightsPerClass',1213    operational: 'FrameSystemLimitsWeightsPerClass',1214    mandatory: 'FrameSystemLimitsWeightsPerClass'1215  },1216  /**1217   * Lookup126: frame_system::limits::WeightsPerClass1218   **/1219  FrameSystemLimitsWeightsPerClass: {1220    baseExtrinsic: 'u64',1221    maxExtrinsic: 'Option<u64>',1222    maxTotal: 'Option<u64>',1223    reserved: 'Option<u64>'1224  },1225  /**1226   * Lookup128: frame_system::limits::BlockLength1227   **/1228  FrameSystemLimitsBlockLength: {1229    max: 'FrameSupportWeightsPerDispatchClassU32'1230  },1231  /**1232   * Lookup129: frame_support::weights::PerDispatchClass<T>1233   **/1234  FrameSupportWeightsPerDispatchClassU32: {1235    normal: 'u32',1236    operational: 'u32',1237    mandatory: 'u32'1238  },1239  /**1240   * Lookup130: frame_support::weights::RuntimeDbWeight1241   **/1242  FrameSupportWeightsRuntimeDbWeight: {1243    read: 'u64',1244    write: 'u64'1245  },1246  /**1247   * Lookup131: sp_version::RuntimeVersion1248   **/1249  SpVersionRuntimeVersion: {1250    specName: 'Text',1251    implName: 'Text',1252    authoringVersion: 'u32',1253    specVersion: 'u32',1254    implVersion: 'u32',1255    apis: 'Vec<([u8;8],u32)>',1256    transactionVersion: 'u32',1257    stateVersion: 'u8'1258  },1259  /**1260   * Lookup136: frame_system::pallet::Error<T>1261   **/1262  FrameSystemError: {1263    _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered']1264  },1265  /**1266   * Lookup137: polkadot_primitives::v2::PersistedValidationData<primitive_types::H256, N>1267   **/1268  PolkadotPrimitivesV2PersistedValidationData: {1269    parentHead: 'Bytes',1270    relayParentNumber: 'u32',1271    relayParentStorageRoot: 'H256',1272    maxPovSize: 'u32'1273  },1274  /**1275   * Lookup140: polkadot_primitives::v2::UpgradeRestriction1276   **/1277  PolkadotPrimitivesV2UpgradeRestriction: {1278    _enum: ['Present']1279  },1280  /**1281   * Lookup141: sp_trie::storage_proof::StorageProof1282   **/1283  SpTrieStorageProof: {1284    trieNodes: 'BTreeSet<Bytes>'1285  },1286  /**1287   * Lookup143: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot1288   **/1289  CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: {1290    dmqMqcHead: 'H256',1291    relayDispatchQueueSize: '(u32,u32)',1292    ingressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>',1293    egressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>'1294  },1295  /**1296   * Lookup146: polkadot_primitives::v2::AbridgedHrmpChannel1297   **/1298  PolkadotPrimitivesV2AbridgedHrmpChannel: {1299    maxCapacity: 'u32',1300    maxTotalSize: 'u32',1301    maxMessageSize: 'u32',1302    msgCount: 'u32',1303    totalSize: 'u32',1304    mqcHead: 'Option<H256>'1305  },1306  /**1307   * Lookup147: polkadot_primitives::v2::AbridgedHostConfiguration1308   **/1309  PolkadotPrimitivesV2AbridgedHostConfiguration: {1310    maxCodeSize: 'u32',1311    maxHeadDataSize: 'u32',1312    maxUpwardQueueCount: 'u32',1313    maxUpwardQueueSize: 'u32',1314    maxUpwardMessageSize: 'u32',1315    maxUpwardMessageNumPerCandidate: 'u32',1316    hrmpMaxMessageNumPerCandidate: 'u32',1317    validationUpgradeCooldown: 'u32',1318    validationUpgradeDelay: 'u32'1319  },1320  /**1321   * Lookup153: polkadot_core_primitives::OutboundHrmpMessage<polkadot_parachain::primitives::Id>1322   **/1323  PolkadotCorePrimitivesOutboundHrmpMessage: {1324    recipient: 'u32',1325    data: 'Bytes'1326  },1327  /**1328   * Lookup154: cumulus_pallet_parachain_system::pallet::Call<T>1329   **/1330  CumulusPalletParachainSystemCall: {1331    _enum: {1332      set_validation_data: {1333        data: 'CumulusPrimitivesParachainInherentParachainInherentData',1334      },1335      sudo_send_upward_message: {1336        message: 'Bytes',1337      },1338      authorize_upgrade: {1339        codeHash: 'H256',1340      },1341      enact_authorized_upgrade: {1342        code: 'Bytes'1343      }1344    }1345  },1346  /**1347   * Lookup155: cumulus_primitives_parachain_inherent::ParachainInherentData1348   **/1349  CumulusPrimitivesParachainInherentParachainInherentData: {1350    validationData: 'PolkadotPrimitivesV2PersistedValidationData',1351    relayChainState: 'SpTrieStorageProof',1352    downwardMessages: 'Vec<PolkadotCorePrimitivesInboundDownwardMessage>',1353    horizontalMessages: 'BTreeMap<u32, Vec<PolkadotCorePrimitivesInboundHrmpMessage>>'1354  },1355  /**1356   * Lookup157: polkadot_core_primitives::InboundDownwardMessage<BlockNumber>1357   **/1358  PolkadotCorePrimitivesInboundDownwardMessage: {1359    sentAt: 'u32',1360    msg: 'Bytes'1361  },1362  /**1363   * Lookup160: polkadot_core_primitives::InboundHrmpMessage<BlockNumber>1364   **/1365  PolkadotCorePrimitivesInboundHrmpMessage: {1366    sentAt: 'u32',1367    data: 'Bytes'1368  },1369  /**1370   * Lookup163: cumulus_pallet_parachain_system::pallet::Error<T>1371   **/1372  CumulusPalletParachainSystemError: {1373    _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized']1374  },1375  /**1376   * Lookup165: pallet_balances::BalanceLock<Balance>1377   **/1378  PalletBalancesBalanceLock: {1379    id: '[u8;8]',1380    amount: 'u128',1381    reasons: 'PalletBalancesReasons'1382  },1383  /**1384   * Lookup166: pallet_balances::Reasons1385   **/1386  PalletBalancesReasons: {1387    _enum: ['Fee', 'Misc', 'All']1388  },1389  /**1390   * Lookup169: pallet_balances::ReserveData<ReserveIdentifier, Balance>1391   **/1392  PalletBalancesReserveData: {1393    id: '[u8;16]',1394    amount: 'u128'1395  },1396  /**1397   * Lookup171: pallet_balances::Releases1398   **/1399  PalletBalancesReleases: {1400    _enum: ['V1_0_0', 'V2_0_0']1401  },1402  /**1403   * Lookup172: pallet_balances::pallet::Call<T, I>1404   **/1405  PalletBalancesCall: {1406    _enum: {1407      transfer: {1408        dest: 'MultiAddress',1409        value: 'Compact<u128>',1410      },1411      set_balance: {1412        who: 'MultiAddress',1413        newFree: 'Compact<u128>',1414        newReserved: 'Compact<u128>',1415      },1416      force_transfer: {1417        source: 'MultiAddress',1418        dest: 'MultiAddress',1419        value: 'Compact<u128>',1420      },1421      transfer_keep_alive: {1422        dest: 'MultiAddress',1423        value: 'Compact<u128>',1424      },1425      transfer_all: {1426        dest: 'MultiAddress',1427        keepAlive: 'bool',1428      },1429      force_unreserve: {1430        who: 'MultiAddress',1431        amount: 'u128'1432      }1433    }1434  },1435  /**1436   * Lookup175: pallet_balances::pallet::Error<T, I>1437   **/1438  PalletBalancesError: {1439    _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves']1440  },1441  /**1442   * Lookup177: pallet_timestamp::pallet::Call<T>1443   **/1444  PalletTimestampCall: {1445    _enum: {1446      set: {1447        now: 'Compact<u64>'1448      }1449    }1450  },1451  /**1452   * Lookup179: pallet_transaction_payment::Releases1453   **/1454  PalletTransactionPaymentReleases: {1455    _enum: ['V1Ancient', 'V2']1456  },1457  /**1458   * Lookup180: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>1459   **/1460  PalletTreasuryProposal: {1461    proposer: 'AccountId32',1462    value: 'u128',1463    beneficiary: 'AccountId32',1464    bond: 'u128'1465  },1466  /**1467   * Lookup183: pallet_treasury::pallet::Call<T, I>1468   **/1469  PalletTreasuryCall: {1470    _enum: {1471      propose_spend: {1472        value: 'Compact<u128>',1473        beneficiary: 'MultiAddress',1474      },1475      reject_proposal: {1476        proposalId: 'Compact<u32>',1477      },1478      approve_proposal: {1479        proposalId: 'Compact<u32>',1480      },1481      spend: {1482        amount: 'Compact<u128>',1483        beneficiary: 'MultiAddress',1484      },1485      remove_approval: {1486        proposalId: 'Compact<u32>'1487      }1488    }1489  },1490  /**1491   * Lookup186: frame_support::PalletId1492   **/1493  FrameSupportPalletId: '[u8;8]',1494  /**1495   * Lookup187: pallet_treasury::pallet::Error<T, I>1496   **/1497  PalletTreasuryError: {1498    _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'InsufficientPermission', 'ProposalNotApproved']1499  },1500  /**1501   * Lookup188: pallet_sudo::pallet::Call<T>1502   **/1503  PalletSudoCall: {1504    _enum: {1505      sudo: {1506        call: 'Call',1507      },1508      sudo_unchecked_weight: {1509        call: 'Call',1510        weight: 'u64',1511      },1512      set_key: {1513        _alias: {1514          new_: 'new',1515        },1516        new_: 'MultiAddress',1517      },1518      sudo_as: {1519        who: 'MultiAddress',1520        call: 'Call'1521      }1522    }1523  },1524  /**1525   * Lookup190: orml_vesting::module::Call<T>1526   **/1527  OrmlVestingModuleCall: {1528    _enum: {1529      claim: 'Null',1530      vested_transfer: {1531        dest: 'MultiAddress',1532        schedule: 'OrmlVestingVestingSchedule',1533      },1534      update_vesting_schedules: {1535        who: 'MultiAddress',1536        vestingSchedules: 'Vec<OrmlVestingVestingSchedule>',1537      },1538      claim_for: {1539        dest: 'MultiAddress'1540      }1541    }1542  },1543  /**1544   * Lookup192: cumulus_pallet_xcmp_queue::pallet::Call<T>1545   **/1546  CumulusPalletXcmpQueueCall: {1547    _enum: {1548      service_overweight: {1549        index: 'u64',1550        weightLimit: 'u64',1551      },1552      suspend_xcm_execution: 'Null',1553      resume_xcm_execution: 'Null',1554      update_suspend_threshold: {1555        _alias: {1556          new_: 'new',1557        },1558        new_: 'u32',1559      },1560      update_drop_threshold: {1561        _alias: {1562          new_: 'new',1563        },1564        new_: 'u32',1565      },1566      update_resume_threshold: {1567        _alias: {1568          new_: 'new',1569        },1570        new_: 'u32',1571      },1572      update_threshold_weight: {1573        _alias: {1574          new_: 'new',1575        },1576        new_: 'u64',1577      },1578      update_weight_restrict_decay: {1579        _alias: {1580          new_: 'new',1581        },1582        new_: 'u64',1583      },1584      update_xcmp_max_individual_weight: {1585        _alias: {1586          new_: 'new',1587        },1588        new_: 'u64'1589      }1590    }1591  },1592  /**1593   * Lookup193: pallet_xcm::pallet::Call<T>1594   **/1595  PalletXcmCall: {1596    _enum: {1597      send: {1598        dest: 'XcmVersionedMultiLocation',1599        message: 'XcmVersionedXcm',1600      },1601      teleport_assets: {1602        dest: 'XcmVersionedMultiLocation',1603        beneficiary: 'XcmVersionedMultiLocation',1604        assets: 'XcmVersionedMultiAssets',1605        feeAssetItem: 'u32',1606      },1607      reserve_transfer_assets: {1608        dest: 'XcmVersionedMultiLocation',1609        beneficiary: 'XcmVersionedMultiLocation',1610        assets: 'XcmVersionedMultiAssets',1611        feeAssetItem: 'u32',1612      },1613      execute: {1614        message: 'XcmVersionedXcm',1615        maxWeight: 'u64',1616      },1617      force_xcm_version: {1618        location: 'XcmV1MultiLocation',1619        xcmVersion: 'u32',1620      },1621      force_default_xcm_version: {1622        maybeXcmVersion: 'Option<u32>',1623      },1624      force_subscribe_version_notify: {1625        location: 'XcmVersionedMultiLocation',1626      },1627      force_unsubscribe_version_notify: {1628        location: 'XcmVersionedMultiLocation',1629      },1630      limited_reserve_transfer_assets: {1631        dest: 'XcmVersionedMultiLocation',1632        beneficiary: 'XcmVersionedMultiLocation',1633        assets: 'XcmVersionedMultiAssets',1634        feeAssetItem: 'u32',1635        weightLimit: 'XcmV2WeightLimit',1636      },1637      limited_teleport_assets: {1638        dest: 'XcmVersionedMultiLocation',1639        beneficiary: 'XcmVersionedMultiLocation',1640        assets: 'XcmVersionedMultiAssets',1641        feeAssetItem: 'u32',1642        weightLimit: 'XcmV2WeightLimit'1643      }1644    }1645  },1646  /**1647   * Lookup194: xcm::VersionedXcm<Call>1648   **/1649  XcmVersionedXcm: {1650    _enum: {1651      V0: 'XcmV0Xcm',1652      V1: 'XcmV1Xcm',1653      V2: 'XcmV2Xcm'1654    }1655  },1656  /**1657   * Lookup195: xcm::v0::Xcm<Call>1658   **/1659  XcmV0Xcm: {1660    _enum: {1661      WithdrawAsset: {1662        assets: 'Vec<XcmV0MultiAsset>',1663        effects: 'Vec<XcmV0Order>',1664      },1665      ReserveAssetDeposit: {1666        assets: 'Vec<XcmV0MultiAsset>',1667        effects: 'Vec<XcmV0Order>',1668      },1669      TeleportAsset: {1670        assets: 'Vec<XcmV0MultiAsset>',1671        effects: 'Vec<XcmV0Order>',1672      },1673      QueryResponse: {1674        queryId: 'Compact<u64>',1675        response: 'XcmV0Response',1676      },1677      TransferAsset: {1678        assets: 'Vec<XcmV0MultiAsset>',1679        dest: 'XcmV0MultiLocation',1680      },1681      TransferReserveAsset: {1682        assets: 'Vec<XcmV0MultiAsset>',1683        dest: 'XcmV0MultiLocation',1684        effects: 'Vec<XcmV0Order>',1685      },1686      Transact: {1687        originType: 'XcmV0OriginKind',1688        requireWeightAtMost: 'u64',1689        call: 'XcmDoubleEncoded',1690      },1691      HrmpNewChannelOpenRequest: {1692        sender: 'Compact<u32>',1693        maxMessageSize: 'Compact<u32>',1694        maxCapacity: 'Compact<u32>',1695      },1696      HrmpChannelAccepted: {1697        recipient: 'Compact<u32>',1698      },1699      HrmpChannelClosing: {1700        initiator: 'Compact<u32>',1701        sender: 'Compact<u32>',1702        recipient: 'Compact<u32>',1703      },1704      RelayedFrom: {1705        who: 'XcmV0MultiLocation',1706        message: 'XcmV0Xcm'1707      }1708    }1709  },1710  /**1711   * Lookup197: xcm::v0::order::Order<Call>1712   **/1713  XcmV0Order: {1714    _enum: {1715      Null: 'Null',1716      DepositAsset: {1717        assets: 'Vec<XcmV0MultiAsset>',1718        dest: 'XcmV0MultiLocation',1719      },1720      DepositReserveAsset: {1721        assets: 'Vec<XcmV0MultiAsset>',1722        dest: 'XcmV0MultiLocation',1723        effects: 'Vec<XcmV0Order>',1724      },1725      ExchangeAsset: {1726        give: 'Vec<XcmV0MultiAsset>',1727        receive: 'Vec<XcmV0MultiAsset>',1728      },1729      InitiateReserveWithdraw: {1730        assets: 'Vec<XcmV0MultiAsset>',1731        reserve: 'XcmV0MultiLocation',1732        effects: 'Vec<XcmV0Order>',1733      },1734      InitiateTeleport: {1735        assets: 'Vec<XcmV0MultiAsset>',1736        dest: 'XcmV0MultiLocation',1737        effects: 'Vec<XcmV0Order>',1738      },1739      QueryHolding: {1740        queryId: 'Compact<u64>',1741        dest: 'XcmV0MultiLocation',1742        assets: 'Vec<XcmV0MultiAsset>',1743      },1744      BuyExecution: {1745        fees: 'XcmV0MultiAsset',1746        weight: 'u64',1747        debt: 'u64',1748        haltOnError: 'bool',1749        xcm: 'Vec<XcmV0Xcm>'1750      }1751    }1752  },1753  /**1754   * Lookup199: xcm::v0::Response1755   **/1756  XcmV0Response: {1757    _enum: {1758      Assets: 'Vec<XcmV0MultiAsset>'1759    }1760  },1761  /**1762   * Lookup200: xcm::v1::Xcm<Call>1763   **/1764  XcmV1Xcm: {1765    _enum: {1766      WithdrawAsset: {1767        assets: 'XcmV1MultiassetMultiAssets',1768        effects: 'Vec<XcmV1Order>',1769      },1770      ReserveAssetDeposited: {1771        assets: 'XcmV1MultiassetMultiAssets',1772        effects: 'Vec<XcmV1Order>',1773      },1774      ReceiveTeleportedAsset: {1775        assets: 'XcmV1MultiassetMultiAssets',1776        effects: 'Vec<XcmV1Order>',1777      },1778      QueryResponse: {1779        queryId: 'Compact<u64>',1780        response: 'XcmV1Response',1781      },1782      TransferAsset: {1783        assets: 'XcmV1MultiassetMultiAssets',1784        beneficiary: 'XcmV1MultiLocation',1785      },1786      TransferReserveAsset: {1787        assets: 'XcmV1MultiassetMultiAssets',1788        dest: 'XcmV1MultiLocation',1789        effects: 'Vec<XcmV1Order>',1790      },1791      Transact: {1792        originType: 'XcmV0OriginKind',1793        requireWeightAtMost: 'u64',1794        call: 'XcmDoubleEncoded',1795      },1796      HrmpNewChannelOpenRequest: {1797        sender: 'Compact<u32>',1798        maxMessageSize: 'Compact<u32>',1799        maxCapacity: 'Compact<u32>',1800      },1801      HrmpChannelAccepted: {1802        recipient: 'Compact<u32>',1803      },1804      HrmpChannelClosing: {1805        initiator: 'Compact<u32>',1806        sender: 'Compact<u32>',1807        recipient: 'Compact<u32>',1808      },1809      RelayedFrom: {1810        who: 'XcmV1MultilocationJunctions',1811        message: 'XcmV1Xcm',1812      },1813      SubscribeVersion: {1814        queryId: 'Compact<u64>',1815        maxResponseWeight: 'Compact<u64>',1816      },1817      UnsubscribeVersion: 'Null'1818    }1819  },1820  /**1821   * Lookup202: xcm::v1::order::Order<Call>1822   **/1823  XcmV1Order: {1824    _enum: {1825      Noop: 'Null',1826      DepositAsset: {1827        assets: 'XcmV1MultiassetMultiAssetFilter',1828        maxAssets: 'u32',1829        beneficiary: 'XcmV1MultiLocation',1830      },1831      DepositReserveAsset: {1832        assets: 'XcmV1MultiassetMultiAssetFilter',1833        maxAssets: 'u32',1834        dest: 'XcmV1MultiLocation',1835        effects: 'Vec<XcmV1Order>',1836      },1837      ExchangeAsset: {1838        give: 'XcmV1MultiassetMultiAssetFilter',1839        receive: 'XcmV1MultiassetMultiAssets',1840      },1841      InitiateReserveWithdraw: {1842        assets: 'XcmV1MultiassetMultiAssetFilter',1843        reserve: 'XcmV1MultiLocation',1844        effects: 'Vec<XcmV1Order>',1845      },1846      InitiateTeleport: {1847        assets: 'XcmV1MultiassetMultiAssetFilter',1848        dest: 'XcmV1MultiLocation',1849        effects: 'Vec<XcmV1Order>',1850      },1851      QueryHolding: {1852        queryId: 'Compact<u64>',1853        dest: 'XcmV1MultiLocation',1854        assets: 'XcmV1MultiassetMultiAssetFilter',1855      },1856      BuyExecution: {1857        fees: 'XcmV1MultiAsset',1858        weight: 'u64',1859        debt: 'u64',1860        haltOnError: 'bool',1861        instructions: 'Vec<XcmV1Xcm>'1862      }1863    }1864  },1865  /**1866   * Lookup204: xcm::v1::Response1867   **/1868  XcmV1Response: {1869    _enum: {1870      Assets: 'XcmV1MultiassetMultiAssets',1871      Version: 'u32'1872    }1873  },1874  /**1875   * Lookup218: cumulus_pallet_xcm::pallet::Call<T>1876   **/1877  CumulusPalletXcmCall: 'Null',1878  /**1879   * Lookup219: cumulus_pallet_dmp_queue::pallet::Call<T>1880   **/1881  CumulusPalletDmpQueueCall: {1882    _enum: {1883      service_overweight: {1884        index: 'u64',1885        weightLimit: 'u64'1886      }1887    }1888  },1889  /**1890   * Lookup220: pallet_inflation::pallet::Call<T>1891   **/1892  PalletInflationCall: {1893    _enum: {1894      start_inflation: {1895        inflationStartRelayBlock: 'u32'1896      }1897    }1898  },1899  /**1900   * Lookup221: pallet_unique::Call<T>1901   **/1902  PalletUniqueCall: {1903    _enum: {1904      create_collection: {1905        collectionName: 'Vec<u16>',1906        collectionDescription: 'Vec<u16>',1907        tokenPrefix: 'Bytes',1908        mode: 'UpDataStructsCollectionMode',1909      },1910      create_collection_ex: {1911        data: 'UpDataStructsCreateCollectionData',1912      },1913      destroy_collection: {1914        collectionId: 'u32',1915      },1916      add_to_allow_list: {1917        collectionId: 'u32',1918        address: 'PalletEvmAccountBasicCrossAccountIdRepr',1919      },1920      remove_from_allow_list: {1921        collectionId: 'u32',1922        address: 'PalletEvmAccountBasicCrossAccountIdRepr',1923      },1924      change_collection_owner: {1925        collectionId: 'u32',1926        newOwner: 'AccountId32',1927      },1928      add_collection_admin: {1929        collectionId: 'u32',1930        newAdminId: 'PalletEvmAccountBasicCrossAccountIdRepr',1931      },1932      remove_collection_admin: {1933        collectionId: 'u32',1934        accountId: 'PalletEvmAccountBasicCrossAccountIdRepr',1935      },1936      set_collection_sponsor: {1937        collectionId: 'u32',1938        newSponsor: 'AccountId32',1939      },1940      confirm_sponsorship: {1941        collectionId: 'u32',1942      },1943      remove_collection_sponsor: {1944        collectionId: 'u32',1945      },1946      create_item: {1947        collectionId: 'u32',1948        owner: 'PalletEvmAccountBasicCrossAccountIdRepr',1949        data: 'UpDataStructsCreateItemData',1950      },1951      create_multiple_items: {1952        collectionId: 'u32',1953        owner: 'PalletEvmAccountBasicCrossAccountIdRepr',1954        itemsData: 'Vec<UpDataStructsCreateItemData>',1955      },1956      set_collection_properties: {1957        collectionId: 'u32',1958        properties: 'Vec<UpDataStructsProperty>',1959      },1960      delete_collection_properties: {1961        collectionId: 'u32',1962        propertyKeys: 'Vec<Bytes>',1963      },1964      set_token_properties: {1965        collectionId: 'u32',1966        tokenId: 'u32',1967        properties: 'Vec<UpDataStructsProperty>',1968      },1969      delete_token_properties: {1970        collectionId: 'u32',1971        tokenId: 'u32',1972        propertyKeys: 'Vec<Bytes>',1973      },1974      set_token_property_permissions: {1975        collectionId: 'u32',1976        propertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',1977      },1978      create_multiple_items_ex: {1979        collectionId: 'u32',1980        data: 'UpDataStructsCreateItemExData',1981      },1982      set_transfers_enabled_flag: {1983        collectionId: 'u32',1984        value: 'bool',1985      },1986      burn_item: {1987        collectionId: 'u32',1988        itemId: 'u32',1989        value: 'u128',1990      },1991      burn_from: {1992        collectionId: 'u32',1993        from: 'PalletEvmAccountBasicCrossAccountIdRepr',1994        itemId: 'u32',1995        value: 'u128',1996      },1997      transfer: {1998        recipient: 'PalletEvmAccountBasicCrossAccountIdRepr',1999        collectionId: 'u32',2000        itemId: 'u32',2001        value: 'u128',2002      },2003      approve: {2004        spender: 'PalletEvmAccountBasicCrossAccountIdRepr',2005        collectionId: 'u32',2006        itemId: 'u32',2007        amount: 'u128',2008      },2009      transfer_from: {2010        from: 'PalletEvmAccountBasicCrossAccountIdRepr',2011        recipient: 'PalletEvmAccountBasicCrossAccountIdRepr',2012        collectionId: 'u32',2013        itemId: 'u32',2014        value: 'u128',2015      },2016      set_collection_limits: {2017        collectionId: 'u32',2018        newLimit: 'UpDataStructsCollectionLimits',2019      },2020      set_collection_permissions: {2021        collectionId: 'u32',2022        newPermission: 'UpDataStructsCollectionPermissions',2023      },2024      repartition: {2025        collectionId: 'u32',2026        tokenId: 'u32',2027        amount: 'u128'2028      }2029    }2030  },2031  /**2032   * Lookup226: up_data_structs::CollectionMode2033   **/2034  UpDataStructsCollectionMode: {2035    _enum: {2036      NFT: 'Null',2037      Fungible: 'u8',2038      ReFungible: 'Null'2039    }2040  },2041  /**2042   * Lookup227: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>2043   **/2044  UpDataStructsCreateCollectionData: {2045    mode: 'UpDataStructsCollectionMode',2046    access: 'Option<UpDataStructsAccessMode>',2047    name: 'Vec<u16>',2048    description: 'Vec<u16>',2049    tokenPrefix: 'Bytes',2050    pendingSponsor: 'Option<AccountId32>',2051    limits: 'Option<UpDataStructsCollectionLimits>',2052    permissions: 'Option<UpDataStructsCollectionPermissions>',2053    tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',2054    properties: 'Vec<UpDataStructsProperty>'2055  },2056  /**2057   * Lookup229: up_data_structs::AccessMode2058   **/2059  UpDataStructsAccessMode: {2060    _enum: ['Normal', 'AllowList']2061  },2062  /**2063   * Lookup231: up_data_structs::CollectionLimits2064   **/2065  UpDataStructsCollectionLimits: {2066    accountTokenOwnershipLimit: 'Option<u32>',2067    sponsoredDataSize: 'Option<u32>',2068    sponsoredDataRateLimit: 'Option<UpDataStructsSponsoringRateLimit>',2069    tokenLimit: 'Option<u32>',2070    sponsorTransferTimeout: 'Option<u32>',2071    sponsorApproveTimeout: 'Option<u32>',2072    ownerCanTransfer: 'Option<bool>',2073    ownerCanDestroy: 'Option<bool>',2074    transfersEnabled: 'Option<bool>'2075  },2076  /**2077   * Lookup233: up_data_structs::SponsoringRateLimit2078   **/2079  UpDataStructsSponsoringRateLimit: {2080    _enum: {2081      SponsoringDisabled: 'Null',2082      Blocks: 'u32'2083    }2084  },2085  /**2086   * Lookup236: up_data_structs::CollectionPermissions2087   **/2088  UpDataStructsCollectionPermissions: {2089    access: 'Option<UpDataStructsAccessMode>',2090    mintMode: 'Option<bool>',2091    nesting: 'Option<UpDataStructsNestingPermissions>'2092  },2093  /**2094   * Lookup238: up_data_structs::NestingPermissions2095   **/2096  UpDataStructsNestingPermissions: {2097    tokenOwner: 'bool',2098    collectionAdmin: 'bool',2099    restricted: 'Option<UpDataStructsOwnerRestrictedSet>'2100  },2101  /**2102   * Lookup240: up_data_structs::OwnerRestrictedSet2103   **/2104  UpDataStructsOwnerRestrictedSet: 'BTreeSet<u32>',2105  /**2106   * Lookup245: up_data_structs::PropertyKeyPermission2107   **/2108  UpDataStructsPropertyKeyPermission: {2109    key: 'Bytes',2110    permission: 'UpDataStructsPropertyPermission'2111  },2112  /**2113   * Lookup246: up_data_structs::PropertyPermission2114   **/2115  UpDataStructsPropertyPermission: {2116    mutable: 'bool',2117    collectionAdmin: 'bool',2118    tokenOwner: 'bool'2119  },2120  /**2121   * Lookup249: up_data_structs::Property2122   **/2123  UpDataStructsProperty: {2124    key: 'Bytes',2125    value: 'Bytes'2126  },2127  /**2128   * Lookup252: up_data_structs::CreateItemData2129   **/2130  UpDataStructsCreateItemData: {2131    _enum: {2132      NFT: 'UpDataStructsCreateNftData',2133      Fungible: 'UpDataStructsCreateFungibleData',2134      ReFungible: 'UpDataStructsCreateReFungibleData'2135    }2136  },2137  /**2138   * Lookup253: up_data_structs::CreateNftData2139   **/2140  UpDataStructsCreateNftData: {2141    properties: 'Vec<UpDataStructsProperty>'2142  },2143  /**2144   * Lookup254: up_data_structs::CreateFungibleData2145   **/2146  UpDataStructsCreateFungibleData: {2147    value: 'u128'2148  },2149  /**2150   * Lookup255: up_data_structs::CreateReFungibleData2151   **/2152  UpDataStructsCreateReFungibleData: {2153    pieces: 'u128',2154    properties: 'Vec<UpDataStructsProperty>'2155  },2156  /**2157   * Lookup258: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2158   **/2159  UpDataStructsCreateItemExData: {2160    _enum: {2161      NFT: 'Vec<UpDataStructsCreateNftExData>',2162      Fungible: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',2163      RefungibleMultipleItems: 'Vec<UpDataStructsCreateRefungibleExSingleOwner>',2164      RefungibleMultipleOwners: 'UpDataStructsCreateRefungibleExMultipleOwners'2165    }2166  },2167  /**2168   * Lookup260: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2169   **/2170  UpDataStructsCreateNftExData: {2171    properties: 'Vec<UpDataStructsProperty>',2172    owner: 'PalletEvmAccountBasicCrossAccountIdRepr'2173  },2174  /**2175   * Lookup267: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2176   **/2177  UpDataStructsCreateRefungibleExSingleOwner: {2178    user: 'PalletEvmAccountBasicCrossAccountIdRepr',2179    pieces: 'u128',2180    properties: 'Vec<UpDataStructsProperty>'2181  },2182  /**2183   * Lookup269: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2184   **/2185  UpDataStructsCreateRefungibleExMultipleOwners: {2186    users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',2187    properties: 'Vec<UpDataStructsProperty>'2188  },2189  /**2190   * Lookup270: pallet_unique_scheduler::pallet::Call<T>2191   **/2192  PalletUniqueSchedulerCall: {2193    _enum: {2194      schedule_named: {2195        id: '[u8;16]',2196        when: 'u32',2197        maybePeriodic: 'Option<(u32,u32)>',2198        priority: 'u8',2199        call: 'FrameSupportScheduleMaybeHashed',2200      },2201      cancel_named: {2202        id: '[u8;16]',2203      },2204      schedule_named_after: {2205        id: '[u8;16]',2206        after: 'u32',2207        maybePeriodic: 'Option<(u32,u32)>',2208        priority: 'u8',2209        call: 'FrameSupportScheduleMaybeHashed'2210      }2211    }2212  },2213  /**2214   * Lookup272: frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>2215   **/2216  FrameSupportScheduleMaybeHashed: {2217    _enum: {2218      Value: 'Call',2219      Hash: 'H256'2220    }2221  },2222  /**2223   * Lookup273: pallet_configuration::pallet::Call<T>2224   **/2225  PalletConfigurationCall: {2226    _enum: {2227      set_weight_to_fee_coefficient_override: {2228        coeff: 'Option<u32>',2229      },2230      set_min_gas_price_override: {2231        coeff: 'Option<u64>'2232      }2233    }2234  },2235  /**2236   * Lookup274: pallet_template_transaction_payment::Call<T>2237   **/2238  PalletTemplateTransactionPaymentCall: 'Null',2239  /**2240   * Lookup275: pallet_structure::pallet::Call<T>2241   **/2242  PalletStructureCall: 'Null',2243  /**2244   * Lookup276: pallet_rmrk_core::pallet::Call<T>2245   **/2246  PalletRmrkCoreCall: {2247    _enum: {2248      create_collection: {2249        metadata: 'Bytes',2250        max: 'Option<u32>',2251        symbol: 'Bytes',2252      },2253      destroy_collection: {2254        collectionId: 'u32',2255      },2256      change_collection_issuer: {2257        collectionId: 'u32',2258        newIssuer: 'MultiAddress',2259      },2260      lock_collection: {2261        collectionId: 'u32',2262      },2263      mint_nft: {2264        owner: 'Option<AccountId32>',2265        collectionId: 'u32',2266        recipient: 'Option<AccountId32>',2267        royaltyAmount: 'Option<Permill>',2268        metadata: 'Bytes',2269        transferable: 'bool',2270        resources: 'Option<Vec<RmrkTraitsResourceResourceTypes>>',2271      },2272      burn_nft: {2273        collectionId: 'u32',2274        nftId: 'u32',2275        maxBurns: 'u32',2276      },2277      send: {2278        rmrkCollectionId: 'u32',2279        rmrkNftId: 'u32',2280        newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2281      },2282      accept_nft: {2283        rmrkCollectionId: 'u32',2284        rmrkNftId: 'u32',2285        newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2286      },2287      reject_nft: {2288        rmrkCollectionId: 'u32',2289        rmrkNftId: 'u32',2290      },2291      accept_resource: {2292        rmrkCollectionId: 'u32',2293        rmrkNftId: 'u32',2294        resourceId: 'u32',2295      },2296      accept_resource_removal: {2297        rmrkCollectionId: 'u32',2298        rmrkNftId: 'u32',2299        resourceId: 'u32',2300      },2301      set_property: {2302        rmrkCollectionId: 'Compact<u32>',2303        maybeNftId: 'Option<u32>',2304        key: 'Bytes',2305        value: 'Bytes',2306      },2307      set_priority: {2308        rmrkCollectionId: 'u32',2309        rmrkNftId: 'u32',2310        priorities: 'Vec<u32>',2311      },2312      add_basic_resource: {2313        rmrkCollectionId: 'u32',2314        nftId: 'u32',2315        resource: 'RmrkTraitsResourceBasicResource',2316      },2317      add_composable_resource: {2318        rmrkCollectionId: 'u32',2319        nftId: 'u32',2320        resource: 'RmrkTraitsResourceComposableResource',2321      },2322      add_slot_resource: {2323        rmrkCollectionId: 'u32',2324        nftId: 'u32',2325        resource: 'RmrkTraitsResourceSlotResource',2326      },2327      remove_resource: {2328        rmrkCollectionId: 'u32',2329        nftId: 'u32',2330        resourceId: 'u32'2331      }2332    }2333  },2334  /**2335   * Lookup282: rmrk_traits::resource::ResourceTypes<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2336   **/2337  RmrkTraitsResourceResourceTypes: {2338    _enum: {2339      Basic: 'RmrkTraitsResourceBasicResource',2340      Composable: 'RmrkTraitsResourceComposableResource',2341      Slot: 'RmrkTraitsResourceSlotResource'2342    }2343  },2344  /**2345   * Lookup284: rmrk_traits::resource::BasicResource<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2346   **/2347  RmrkTraitsResourceBasicResource: {2348    src: 'Option<Bytes>',2349    metadata: 'Option<Bytes>',2350    license: 'Option<Bytes>',2351    thumb: 'Option<Bytes>'2352  },2353  /**2354   * Lookup286: rmrk_traits::resource::ComposableResource<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2355   **/2356  RmrkTraitsResourceComposableResource: {2357    parts: 'Vec<u32>',2358    base: 'u32',2359    src: 'Option<Bytes>',2360    metadata: 'Option<Bytes>',2361    license: 'Option<Bytes>',2362    thumb: 'Option<Bytes>'2363  },2364  /**2365   * Lookup287: rmrk_traits::resource::SlotResource<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2366   **/2367  RmrkTraitsResourceSlotResource: {2368    base: 'u32',2369    src: 'Option<Bytes>',2370    metadata: 'Option<Bytes>',2371    slot: 'u32',2372    license: 'Option<Bytes>',2373    thumb: 'Option<Bytes>'2374  },2375  /**2376   * Lookup290: pallet_rmrk_equip::pallet::Call<T>2377   **/2378  PalletRmrkEquipCall: {2379    _enum: {2380      create_base: {2381        baseType: 'Bytes',2382        symbol: 'Bytes',2383        parts: 'Vec<RmrkTraitsPartPartType>',2384      },2385      theme_add: {2386        baseId: 'u32',2387        theme: 'RmrkTraitsTheme',2388      },2389      equippable: {2390        baseId: 'u32',2391        slotId: 'u32',2392        equippables: 'RmrkTraitsPartEquippableList'2393      }2394    }2395  },2396  /**2397   * Lookup293: rmrk_traits::part::PartType<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2398   **/2399  RmrkTraitsPartPartType: {2400    _enum: {2401      FixedPart: 'RmrkTraitsPartFixedPart',2402      SlotPart: 'RmrkTraitsPartSlotPart'2403    }2404  },2405  /**2406   * Lookup295: rmrk_traits::part::FixedPart<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2407   **/2408  RmrkTraitsPartFixedPart: {2409    id: 'u32',2410    z: 'u32',2411    src: 'Bytes'2412  },2413  /**2414   * Lookup296: rmrk_traits::part::SlotPart<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2415   **/2416  RmrkTraitsPartSlotPart: {2417    id: 'u32',2418    equippable: 'RmrkTraitsPartEquippableList',2419    src: 'Bytes',2420    z: 'u32'2421  },2422  /**2423   * Lookup297: rmrk_traits::part::EquippableList<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2424   **/2425  RmrkTraitsPartEquippableList: {2426    _enum: {2427      All: 'Null',2428      Empty: 'Null',2429      Custom: 'Vec<u32>'2430    }2431  },2432  /**2433   * Lookup299: rmrk_traits::theme::Theme<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<rmrk_traits::theme::ThemeProperty<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>, S>>2434   **/2435  RmrkTraitsTheme: {2436    name: 'Bytes',2437    properties: 'Vec<RmrkTraitsThemeThemeProperty>',2438    inherit: 'bool'2439  },2440  /**2441   * Lookup301: rmrk_traits::theme::ThemeProperty<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2442   **/2443  RmrkTraitsThemeThemeProperty: {2444    key: 'Bytes',2445    value: 'Bytes'2446  },2447  /**2448   * Lookup303: pallet_evm::pallet::Call<T>2449   **/2450  PalletEvmCall: {2451    _enum: {2452      withdraw: {2453        address: 'H160',2454        value: 'u128',2455      },2456      call: {2457        source: 'H160',2458        target: 'H160',2459        input: 'Bytes',2460        value: 'U256',2461        gasLimit: 'u64',2462        maxFeePerGas: 'U256',2463        maxPriorityFeePerGas: 'Option<U256>',2464        nonce: 'Option<U256>',2465        accessList: 'Vec<(H160,Vec<H256>)>',2466      },2467      create: {2468        source: 'H160',2469        init: 'Bytes',2470        value: 'U256',2471        gasLimit: 'u64',2472        maxFeePerGas: 'U256',2473        maxPriorityFeePerGas: 'Option<U256>',2474        nonce: 'Option<U256>',2475        accessList: 'Vec<(H160,Vec<H256>)>',2476      },2477      create2: {2478        source: 'H160',2479        init: 'Bytes',2480        salt: 'H256',2481        value: 'U256',2482        gasLimit: 'u64',2483        maxFeePerGas: 'U256',2484        maxPriorityFeePerGas: 'Option<U256>',2485        nonce: 'Option<U256>',2486        accessList: 'Vec<(H160,Vec<H256>)>'2487      }2488    }2489  },2490  /**2491   * Lookup307: pallet_ethereum::pallet::Call<T>2492   **/2493  PalletEthereumCall: {2494    _enum: {2495      transact: {2496        transaction: 'EthereumTransactionTransactionV2'2497      }2498    }2499  },2500  /**2501   * Lookup308: ethereum::transaction::TransactionV22502   **/2503  EthereumTransactionTransactionV2: {2504    _enum: {2505      Legacy: 'EthereumTransactionLegacyTransaction',2506      EIP2930: 'EthereumTransactionEip2930Transaction',2507      EIP1559: 'EthereumTransactionEip1559Transaction'2508    }2509  },2510  /**2511   * Lookup309: ethereum::transaction::LegacyTransaction2512   **/2513  EthereumTransactionLegacyTransaction: {2514    nonce: 'U256',2515    gasPrice: 'U256',2516    gasLimit: 'U256',2517    action: 'EthereumTransactionTransactionAction',2518    value: 'U256',2519    input: 'Bytes',2520    signature: 'EthereumTransactionTransactionSignature'2521  },2522  /**2523   * Lookup310: ethereum::transaction::TransactionAction2524   **/2525  EthereumTransactionTransactionAction: {2526    _enum: {2527      Call: 'H160',2528      Create: 'Null'2529    }2530  },2531  /**2532   * Lookup311: ethereum::transaction::TransactionSignature2533   **/2534  EthereumTransactionTransactionSignature: {2535    v: 'u64',2536    r: 'H256',2537    s: 'H256'2538  },2539  /**2540   * Lookup313: ethereum::transaction::EIP2930Transaction2541   **/2542  EthereumTransactionEip2930Transaction: {2543    chainId: 'u64',2544    nonce: 'U256',2545    gasPrice: 'U256',2546    gasLimit: 'U256',2547    action: 'EthereumTransactionTransactionAction',2548    value: 'U256',2549    input: 'Bytes',2550    accessList: 'Vec<EthereumTransactionAccessListItem>',2551    oddYParity: 'bool',2552    r: 'H256',2553    s: 'H256'2554  },2555  /**2556   * Lookup315: ethereum::transaction::AccessListItem2557   **/2558  EthereumTransactionAccessListItem: {2559    address: 'H160',2560    storageKeys: 'Vec<H256>'2561  },2562  /**2563   * Lookup316: ethereum::transaction::EIP1559Transaction2564   **/2565  EthereumTransactionEip1559Transaction: {2566    chainId: 'u64',2567    nonce: 'U256',2568    maxPriorityFeePerGas: 'U256',2569    maxFeePerGas: 'U256',2570    gasLimit: 'U256',2571    action: 'EthereumTransactionTransactionAction',2572    value: 'U256',2573    input: 'Bytes',2574    accessList: 'Vec<EthereumTransactionAccessListItem>',2575    oddYParity: 'bool',2576    r: 'H256',2577    s: 'H256'2578  },2579  /**2580   * Lookup317: pallet_evm_migration::pallet::Call<T>2581   **/2582  PalletEvmMigrationCall: {2583    _enum: {2584      begin: {2585        address: 'H160',2586      },2587      set_data: {2588        address: 'H160',2589        data: 'Vec<(H256,H256)>',2590      },2591      finish: {2592        address: 'H160',2593        code: 'Bytes'2594      }2595    }2596  },2597  /**2598   * Lookup320: pallet_sudo::pallet::Error<T>2599   **/2600  PalletSudoError: {2601    _enum: ['RequireSudo']2602  },2603  /**2604   * Lookup322: orml_vesting::module::Error<T>2605   **/2606  OrmlVestingModuleError: {2607    _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded']2608  },2609  /**2610   * Lookup324: cumulus_pallet_xcmp_queue::InboundChannelDetails2611   **/2612  CumulusPalletXcmpQueueInboundChannelDetails: {2613    sender: 'u32',2614    state: 'CumulusPalletXcmpQueueInboundState',2615    messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>'2616  },2617  /**2618   * Lookup325: cumulus_pallet_xcmp_queue::InboundState2619   **/2620  CumulusPalletXcmpQueueInboundState: {2621    _enum: ['Ok', 'Suspended']2622  },2623  /**2624   * Lookup328: polkadot_parachain::primitives::XcmpMessageFormat2625   **/2626  PolkadotParachainPrimitivesXcmpMessageFormat: {2627    _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals']2628  },2629  /**2630   * Lookup331: cumulus_pallet_xcmp_queue::OutboundChannelDetails2631   **/2632  CumulusPalletXcmpQueueOutboundChannelDetails: {2633    recipient: 'u32',2634    state: 'CumulusPalletXcmpQueueOutboundState',2635    signalsExist: 'bool',2636    firstIndex: 'u16',2637    lastIndex: 'u16'2638  },2639  /**2640   * Lookup332: cumulus_pallet_xcmp_queue::OutboundState2641   **/2642  CumulusPalletXcmpQueueOutboundState: {2643    _enum: ['Ok', 'Suspended']2644  },2645  /**2646   * Lookup334: cumulus_pallet_xcmp_queue::QueueConfigData2647   **/2648  CumulusPalletXcmpQueueQueueConfigData: {2649    suspendThreshold: 'u32',2650    dropThreshold: 'u32',2651    resumeThreshold: 'u32',2652    thresholdWeight: 'u64',2653    weightRestrictDecay: 'u64',2654    xcmpMaxIndividualWeight: 'u64'2655  },2656  /**2657   * Lookup336: cumulus_pallet_xcmp_queue::pallet::Error<T>2658   **/2659  CumulusPalletXcmpQueueError: {2660    _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit']2661  },2662  /**2663   * Lookup337: pallet_xcm::pallet::Error<T>2664   **/2665  PalletXcmError: {2666    _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed']2667  },2668  /**2669   * Lookup338: cumulus_pallet_xcm::pallet::Error<T>2670   **/2671  CumulusPalletXcmError: 'Null',2672  /**2673   * Lookup339: cumulus_pallet_dmp_queue::ConfigData2674   **/2675  CumulusPalletDmpQueueConfigData: {2676    maxIndividual: 'u64'2677  },2678  /**2679   * Lookup340: cumulus_pallet_dmp_queue::PageIndexData2680   **/2681  CumulusPalletDmpQueuePageIndexData: {2682    beginUsed: 'u32',2683    endUsed: 'u32',2684    overweightCount: 'u64'2685  },2686  /**2687   * Lookup343: cumulus_pallet_dmp_queue::pallet::Error<T>2688   **/2689  CumulusPalletDmpQueueError: {2690    _enum: ['Unknown', 'OverLimit']2691  },2692  /**2693   * Lookup347: pallet_unique::Error<T>2694   **/2695  PalletUniqueError: {2696    _enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection']2697  },2698  /**2699   * Lookup350: pallet_unique_scheduler::ScheduledV3<frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>2700   **/2701  PalletUniqueSchedulerScheduledV3: {2702    maybeId: 'Option<[u8;16]>',2703    priority: 'u8',2704    call: 'FrameSupportScheduleMaybeHashed',2705    maybePeriodic: 'Option<(u32,u32)>',2706    origin: 'OpalRuntimeOriginCaller'2707  },2708  /**2709   * Lookup351: opal_runtime::OriginCaller2710   **/2711  OpalRuntimeOriginCaller: {2712    _enum: {2713      system: 'FrameSupportDispatchRawOrigin',2714      __Unused1: 'Null',2715      __Unused2: 'Null',2716      __Unused3: 'Null',2717      Void: 'SpCoreVoid',2718      __Unused5: 'Null',2719      __Unused6: 'Null',2720      __Unused7: 'Null',2721      __Unused8: 'Null',2722      __Unused9: 'Null',2723      __Unused10: 'Null',2724      __Unused11: 'Null',2725      __Unused12: 'Null',2726      __Unused13: 'Null',2727      __Unused14: 'Null',2728      __Unused15: 'Null',2729      __Unused16: 'Null',2730      __Unused17: 'Null',2731      __Unused18: 'Null',2732      __Unused19: 'Null',2733      __Unused20: 'Null',2734      __Unused21: 'Null',2735      __Unused22: 'Null',2736      __Unused23: 'Null',2737      __Unused24: 'Null',2738      __Unused25: 'Null',2739      __Unused26: 'Null',2740      __Unused27: 'Null',2741      __Unused28: 'Null',2742      __Unused29: 'Null',2743      __Unused30: 'Null',2744      __Unused31: 'Null',2745      __Unused32: 'Null',2746      __Unused33: 'Null',2747      __Unused34: 'Null',2748      __Unused35: 'Null',2749      __Unused36: 'Null',2750      __Unused37: 'Null',2751      __Unused38: 'Null',2752      __Unused39: 'Null',2753      __Unused40: 'Null',2754      __Unused41: 'Null',2755      __Unused42: 'Null',2756      __Unused43: 'Null',2757      __Unused44: 'Null',2758      __Unused45: 'Null',2759      __Unused46: 'Null',2760      __Unused47: 'Null',2761      __Unused48: 'Null',2762      __Unused49: 'Null',2763      __Unused50: 'Null',2764      PolkadotXcm: 'PalletXcmOrigin',2765      CumulusXcm: 'CumulusPalletXcmOrigin',2766      __Unused53: 'Null',2767      __Unused54: 'Null',2768      __Unused55: 'Null',2769      __Unused56: 'Null',2770      __Unused57: 'Null',2771      __Unused58: 'Null',2772      __Unused59: 'Null',2773      __Unused60: 'Null',2774      __Unused61: 'Null',2775      __Unused62: 'Null',2776      __Unused63: 'Null',2777      __Unused64: 'Null',2778      __Unused65: 'Null',2779      __Unused66: 'Null',2780      __Unused67: 'Null',2781      __Unused68: 'Null',2782      __Unused69: 'Null',2783      __Unused70: 'Null',2784      __Unused71: 'Null',2785      __Unused72: 'Null',2786      __Unused73: 'Null',2787      __Unused74: 'Null',2788      __Unused75: 'Null',2789      __Unused76: 'Null',2790      __Unused77: 'Null',2791      __Unused78: 'Null',2792      __Unused79: 'Null',2793      __Unused80: 'Null',2794      __Unused81: 'Null',2795      __Unused82: 'Null',2796      __Unused83: 'Null',2797      __Unused84: 'Null',2798      __Unused85: 'Null',2799      __Unused86: 'Null',2800      __Unused87: 'Null',2801      __Unused88: 'Null',2802      __Unused89: 'Null',2803      __Unused90: 'Null',2804      __Unused91: 'Null',2805      __Unused92: 'Null',2806      __Unused93: 'Null',2807      __Unused94: 'Null',2808      __Unused95: 'Null',2809      __Unused96: 'Null',2810      __Unused97: 'Null',2811      __Unused98: 'Null',2812      __Unused99: 'Null',2813      __Unused100: 'Null',2814      Ethereum: 'PalletEthereumRawOrigin'2815    }2816  },2817  /**2818   * Lookup352: frame_support::dispatch::RawOrigin<sp_core::crypto::AccountId32>2819   **/2820  FrameSupportDispatchRawOrigin: {2821    _enum: {2822      Root: 'Null',2823      Signed: 'AccountId32',2824      None: 'Null'2825    }2826  },2827  /**2828   * Lookup353: pallet_xcm::pallet::Origin2829   **/2830  PalletXcmOrigin: {2831    _enum: {2832      Xcm: 'XcmV1MultiLocation',2833      Response: 'XcmV1MultiLocation'2834    }2835  },2836  /**2837   * Lookup354: cumulus_pallet_xcm::pallet::Origin2838   **/2839  CumulusPalletXcmOrigin: {2840    _enum: {2841      Relay: 'Null',2842      SiblingParachain: 'u32'2843    }2844  },2845  /**2846   * Lookup355: pallet_ethereum::RawOrigin2847   **/2848  PalletEthereumRawOrigin: {2849    _enum: {2850      EthereumTransaction: 'H160'2851    }2852  },2853  /**2854   * Lookup356: sp_core::Void2855   **/2856  SpCoreVoid: 'Null',2857  /**2858   * Lookup357: pallet_unique_scheduler::pallet::Error<T>2859   **/2860  PalletUniqueSchedulerError: {2861    _enum: ['FailedToSchedule', 'NotFound', 'TargetBlockNumberInPast', 'RescheduleNoChange']2862  },2863  /**2864   * Lookup358: up_data_structs::Collection<sp_core::crypto::AccountId32>2865   **/2866  UpDataStructsCollection: {2867    owner: 'AccountId32',2868    mode: 'UpDataStructsCollectionMode',2869    name: 'Vec<u16>',2870    description: 'Vec<u16>',2871    tokenPrefix: 'Bytes',2872    sponsorship: 'UpDataStructsSponsorshipState',2873    limits: 'UpDataStructsCollectionLimits',2874    permissions: 'UpDataStructsCollectionPermissions',2875    externalCollection: 'bool'2876  },2877  /**2878   * Lookup359: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>2879   **/2880  UpDataStructsSponsorshipState: {2881    _enum: {2882      Disabled: 'Null',2883      Unconfirmed: 'AccountId32',2884      Confirmed: 'AccountId32'2885    }2886  },2887  /**2888   * Lookup360: up_data_structs::Properties2889   **/2890  UpDataStructsProperties: {2891    map: 'UpDataStructsPropertiesMapBoundedVec',2892    consumedSpace: 'u32',2893    spaceLimit: 'u32'2894  },2895  /**2896   * Lookup361: up_data_structs::PropertiesMap<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2897   **/2898  UpDataStructsPropertiesMapBoundedVec: 'BTreeMap<Bytes, Bytes>',2899  /**2900   * Lookup366: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>2901   **/2902  UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap<Bytes, UpDataStructsPropertyPermission>',2903  /**2904   * Lookup373: up_data_structs::CollectionStats2905   **/2906  UpDataStructsCollectionStats: {2907    created: 'u32',2908    destroyed: 'u32',2909    alive: 'u32'2910  },2911  /**2912   * Lookup374: up_data_structs::TokenChild2913   **/2914  UpDataStructsTokenChild: {2915    token: 'u32',2916    collection: 'u32'2917  },2918  /**2919   * Lookup375: PhantomType::up_data_structs<T>2920   **/2921  PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild);0]',2922  /**2923   * Lookup377: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2924   **/2925  UpDataStructsTokenData: {2926    properties: 'Vec<UpDataStructsProperty>',2927    owner: 'Option<PalletEvmAccountBasicCrossAccountIdRepr>',2928    pieces: 'u128'2929  },2930  /**2931   * Lookup379: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>2932   **/2933  UpDataStructsRpcCollection: {2934    owner: 'AccountId32',2935    mode: 'UpDataStructsCollectionMode',2936    name: 'Vec<u16>',2937    description: 'Vec<u16>',2938    tokenPrefix: 'Bytes',2939    sponsorship: 'UpDataStructsSponsorshipState',2940    limits: 'UpDataStructsCollectionLimits',2941    permissions: 'UpDataStructsCollectionPermissions',2942    tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',2943    properties: 'Vec<UpDataStructsProperty>',2944    readOnly: 'bool'2945  },2946  /**2947   * Lookup380: rmrk_traits::collection::CollectionInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>2948   **/2949  RmrkTraitsCollectionCollectionInfo: {2950    issuer: 'AccountId32',2951    metadata: 'Bytes',2952    max: 'Option<u32>',2953    symbol: 'Bytes',2954    nftsCount: 'u32'2955  },2956  /**2957   * Lookup381: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2958   **/2959  RmrkTraitsNftNftInfo: {2960    owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2961    royalty: 'Option<RmrkTraitsNftRoyaltyInfo>',2962    metadata: 'Bytes',2963    equipped: 'bool',2964    pending: 'bool'2965  },2966  /**2967   * Lookup383: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>2968   **/2969  RmrkTraitsNftRoyaltyInfo: {2970    recipient: 'AccountId32',2971    amount: 'Permill'2972  },2973  /**2974   * Lookup384: rmrk_traits::resource::ResourceInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2975   **/2976  RmrkTraitsResourceResourceInfo: {2977    id: 'u32',2978    resource: 'RmrkTraitsResourceResourceTypes',2979    pending: 'bool',2980    pendingRemoval: 'bool'2981  },2982  /**2983   * Lookup385: rmrk_traits::property::PropertyInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2984   **/2985  RmrkTraitsPropertyPropertyInfo: {2986    key: 'Bytes',2987    value: 'Bytes'2988  },2989  /**2990   * Lookup386: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2991   **/2992  RmrkTraitsBaseBaseInfo: {2993    issuer: 'AccountId32',2994    baseType: 'Bytes',2995    symbol: 'Bytes'2996  },2997  /**2998   * Lookup387: rmrk_traits::nft::NftChild2999   **/3000  RmrkTraitsNftNftChild: {3001    collectionId: 'u32',3002    nftId: 'u32'3003  },3004  /**3005   * Lookup389: pallet_common::pallet::Error<T>3006   **/3007  PalletCommonError: {3008    _enum: ['CollectionNotFound', 'MustBeTokenOwner', 'NoPermission', 'CantDestroyNotEmptyCollection', 'PublicMintingNotAllowed', 'AddressNotInAllowlist', 'CollectionNameLimitExceeded', 'CollectionDescriptionLimitExceeded', 'CollectionTokenPrefixLimitExceeded', 'TotalCollectionsLimitExceeded', 'CollectionAdminCountExceeded', 'CollectionLimitBoundsExceeded', 'OwnerPermissionsCantBeReverted', 'TransferNotAllowed', 'AccountTokenLimitExceeded', 'CollectionTokenLimitExceeded', 'MetadataFlagFrozen', 'TokenNotFound', 'TokenValueTooLow', 'ApprovedValueTooLow', 'CantApproveMoreThanOwned', 'AddressIsZero', 'UnsupportedOperation', 'NotSufficientFounds', 'UserIsNotAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'PropertyKeyIsTooLong', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey', 'CollectionIsExternal', 'CollectionIsInternal']3009  },3010  /**3011   * Lookup391: pallet_fungible::pallet::Error<T>3012   **/3013  PalletFungibleError: {3014    _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed']3015  },3016  /**3017   * Lookup392: pallet_refungible::ItemData3018   **/3019  PalletRefungibleItemData: {3020    constData: 'Bytes'3021  },3022  /**3023   * Lookup397: pallet_refungible::pallet::Error<T>3024   **/3025  PalletRefungibleError: {3026    _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed']3027  },3028  /**3029   * Lookup398: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>3030   **/3031  PalletNonfungibleItemData: {3032    owner: 'PalletEvmAccountBasicCrossAccountIdRepr'3033  },3034  /**3035   * Lookup400: up_data_structs::PropertyScope3036   **/3037  UpDataStructsPropertyScope: {3038    _enum: ['None', 'Rmrk', 'Eth']3039  },3040  /**3041   * Lookup402: pallet_nonfungible::pallet::Error<T>3042   **/3043  PalletNonfungibleError: {3044    _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren']3045  },3046  /**3047   * Lookup403: pallet_structure::pallet::Error<T>3048   **/3049  PalletStructureError: {3050    _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound']3051  },3052  /**3053   * Lookup404: pallet_rmrk_core::pallet::Error<T>3054   **/3055  PalletRmrkCoreError: {3056    _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId']3057  },3058  /**3059   * Lookup406: pallet_rmrk_equip::pallet::Error<T>3060   **/3061  PalletRmrkEquipError: {3062    _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart']3063  },3064  /**3065   * Lookup409: pallet_evm::pallet::Error<T>3066   **/3067  PalletEvmError: {3068    _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce']3069  },3070  /**3071   * Lookup412: fp_rpc::TransactionStatus3072   **/3073  FpRpcTransactionStatus: {3074    transactionHash: 'H256',3075    transactionIndex: 'u32',3076    from: 'H160',3077    to: 'Option<H160>',3078    contractAddress: 'Option<H160>',3079    logs: 'Vec<EthereumLog>',3080    logsBloom: 'EthbloomBloom'3081  },3082  /**3083   * Lookup414: ethbloom::Bloom3084   **/3085  EthbloomBloom: '[u8;256]',3086  /**3087   * Lookup416: ethereum::receipt::ReceiptV33088   **/3089  EthereumReceiptReceiptV3: {3090    _enum: {3091      Legacy: 'EthereumReceiptEip658ReceiptData',3092      EIP2930: 'EthereumReceiptEip658ReceiptData',3093      EIP1559: 'EthereumReceiptEip658ReceiptData'3094    }3095  },3096  /**3097   * Lookup417: ethereum::receipt::EIP658ReceiptData3098   **/3099  EthereumReceiptEip658ReceiptData: {3100    statusCode: 'u8',3101    usedGas: 'U256',3102    logsBloom: 'EthbloomBloom',3103    logs: 'Vec<EthereumLog>'3104  },3105  /**3106   * Lookup418: ethereum::block::Block<ethereum::transaction::TransactionV2>3107   **/3108  EthereumBlock: {3109    header: 'EthereumHeader',3110    transactions: 'Vec<EthereumTransactionTransactionV2>',3111    ommers: 'Vec<EthereumHeader>'3112  },3113  /**3114   * Lookup419: ethereum::header::Header3115   **/3116  EthereumHeader: {3117    parentHash: 'H256',3118    ommersHash: 'H256',3119    beneficiary: 'H160',3120    stateRoot: 'H256',3121    transactionsRoot: 'H256',3122    receiptsRoot: 'H256',3123    logsBloom: 'EthbloomBloom',3124    difficulty: 'U256',3125    number: 'U256',3126    gasLimit: 'U256',3127    gasUsed: 'U256',3128    timestamp: 'u64',3129    extraData: 'Bytes',3130    mixHash: 'H256',3131    nonce: 'EthereumTypesHashH64'3132  },3133  /**3134   * Lookup420: ethereum_types::hash::H643135   **/3136  EthereumTypesHashH64: '[u8;8]',3137  /**3138   * Lookup425: pallet_ethereum::pallet::Error<T>3139   **/3140  PalletEthereumError: {3141    _enum: ['InvalidSignature', 'PreLogExists']3142  },3143  /**3144   * Lookup426: pallet_evm_coder_substrate::pallet::Error<T>3145   **/3146  PalletEvmCoderSubstrateError: {3147    _enum: ['OutOfGas', 'OutOfFund']3148  },3149  /**3150   * Lookup427: pallet_evm_contract_helpers::SponsoringModeT3151   **/3152  PalletEvmContractHelpersSponsoringModeT: {3153    _enum: ['Disabled', 'Allowlisted', 'Generous']3154  },3155  /**3156   * Lookup429: pallet_evm_contract_helpers::pallet::Error<T>3157   **/3158  PalletEvmContractHelpersError: {3159    _enum: ['NoPermission']3160  },3161  /**3162   * Lookup430: pallet_evm_migration::pallet::Error<T>3163   **/3164  PalletEvmMigrationError: {3165    _enum: ['AccountNotEmpty', 'AccountIsNotMigrating']3166  },3167  /**3168   * Lookup432: sp_runtime::MultiSignature3169   **/3170  SpRuntimeMultiSignature: {3171    _enum: {3172      Ed25519: 'SpCoreEd25519Signature',3173      Sr25519: 'SpCoreSr25519Signature',3174      Ecdsa: 'SpCoreEcdsaSignature'3175    }3176  },3177  /**3178   * Lookup433: sp_core::ed25519::Signature3179   **/3180  SpCoreEd25519Signature: '[u8;64]',3181  /**3182   * Lookup435: sp_core::sr25519::Signature3183   **/3184  SpCoreSr25519Signature: '[u8;64]',3185  /**3186   * Lookup436: sp_core::ecdsa::Signature3187   **/3188  SpCoreEcdsaSignature: '[u8;65]',3189  /**3190   * Lookup439: frame_system::extensions::check_spec_version::CheckSpecVersion<T>3191   **/3192  FrameSystemExtensionsCheckSpecVersion: 'Null',3193  /**3194   * Lookup440: frame_system::extensions::check_genesis::CheckGenesis<T>3195   **/3196  FrameSystemExtensionsCheckGenesis: 'Null',3197  /**3198   * Lookup443: frame_system::extensions::check_nonce::CheckNonce<T>3199   **/3200  FrameSystemExtensionsCheckNonce: 'Compact<u32>',3201  /**3202   * Lookup444: frame_system::extensions::check_weight::CheckWeight<T>3203   **/3204  FrameSystemExtensionsCheckWeight: 'Null',3205  /**3206   * Lookup445: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>3207   **/3208  PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact<u128>',3209  /**3210   * Lookup446: opal_runtime::Runtime3211   **/3212  OpalRuntimeRuntime: 'Null',3213  /**3214   * Lookup447: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>3215   **/3216  PalletEthereumFakeTransactionFinalizer: 'Null'3217};
after · tests/src/interfaces/lookup.ts
1// Auto-generated via `yarn polkadot-types-from-defs`, do not edit2/* eslint-disable */34/* eslint-disable sort-keys */56export default {7  /**8   * Lookup3: frame_system::AccountInfo<Index, pallet_balances::AccountData<Balance>>9   **/10  FrameSystemAccountInfo: {11    nonce: 'u32',12    consumers: 'u32',13    providers: 'u32',14    sufficients: 'u32',15    data: 'PalletBalancesAccountData'16  },17  /**18   * Lookup5: pallet_balances::AccountData<Balance>19   **/20  PalletBalancesAccountData: {21    free: 'u128',22    reserved: 'u128',23    miscFrozen: 'u128',24    feeFrozen: 'u128'25  },26  /**27   * Lookup7: frame_support::weights::PerDispatchClass<T>28   **/29  FrameSupportWeightsPerDispatchClassU64: {30    normal: 'u64',31    operational: 'u64',32    mandatory: 'u64'33  },34  /**35   * Lookup11: sp_runtime::generic::digest::Digest36   **/37  SpRuntimeDigest: {38    logs: 'Vec<SpRuntimeDigestDigestItem>'39  },40  /**41   * Lookup13: sp_runtime::generic::digest::DigestItem42   **/43  SpRuntimeDigestDigestItem: {44    _enum: {45      Other: 'Bytes',46      __Unused1: 'Null',47      __Unused2: 'Null',48      __Unused3: 'Null',49      Consensus: '([u8;4],Bytes)',50      Seal: '([u8;4],Bytes)',51      PreRuntime: '([u8;4],Bytes)',52      __Unused7: 'Null',53      RuntimeEnvironmentUpdated: 'Null'54    }55  },56  /**57   * Lookup16: frame_system::EventRecord<opal_runtime::Event, primitive_types::H256>58   **/59  FrameSystemEventRecord: {60    phase: 'FrameSystemPhase',61    event: 'Event',62    topics: 'Vec<H256>'63  },64  /**65   * Lookup18: frame_system::pallet::Event<T>66   **/67  FrameSystemEvent: {68    _enum: {69      ExtrinsicSuccess: {70        dispatchInfo: 'FrameSupportWeightsDispatchInfo',71      },72      ExtrinsicFailed: {73        dispatchError: 'SpRuntimeDispatchError',74        dispatchInfo: 'FrameSupportWeightsDispatchInfo',75      },76      CodeUpdated: 'Null',77      NewAccount: {78        account: 'AccountId32',79      },80      KilledAccount: {81        account: 'AccountId32',82      },83      Remarked: {84        _alias: {85          hash_: 'hash',86        },87        sender: 'AccountId32',88        hash_: 'H256'89      }90    }91  },92  /**93   * Lookup19: frame_support::weights::DispatchInfo94   **/95  FrameSupportWeightsDispatchInfo: {96    weight: 'u64',97    class: 'FrameSupportWeightsDispatchClass',98    paysFee: 'FrameSupportWeightsPays'99  },100  /**101   * Lookup20: frame_support::weights::DispatchClass102   **/103  FrameSupportWeightsDispatchClass: {104    _enum: ['Normal', 'Operational', 'Mandatory']105  },106  /**107   * Lookup21: frame_support::weights::Pays108   **/109  FrameSupportWeightsPays: {110    _enum: ['Yes', 'No']111  },112  /**113   * Lookup22: sp_runtime::DispatchError114   **/115  SpRuntimeDispatchError: {116    _enum: {117      Other: 'Null',118      CannotLookup: 'Null',119      BadOrigin: 'Null',120      Module: 'SpRuntimeModuleError',121      ConsumerRemaining: 'Null',122      NoProviders: 'Null',123      TooManyConsumers: 'Null',124      Token: 'SpRuntimeTokenError',125      Arithmetic: 'SpRuntimeArithmeticError',126      Transactional: 'SpRuntimeTransactionalError'127    }128  },129  /**130   * Lookup23: sp_runtime::ModuleError131   **/132  SpRuntimeModuleError: {133    index: 'u8',134    error: '[u8;4]'135  },136  /**137   * Lookup24: sp_runtime::TokenError138   **/139  SpRuntimeTokenError: {140    _enum: ['NoFunds', 'WouldDie', 'BelowMinimum', 'CannotCreate', 'UnknownAsset', 'Frozen', 'Unsupported']141  },142  /**143   * Lookup25: sp_runtime::ArithmeticError144   **/145  SpRuntimeArithmeticError: {146    _enum: ['Underflow', 'Overflow', 'DivisionByZero']147  },148  /**149   * Lookup26: sp_runtime::TransactionalError150   **/151  SpRuntimeTransactionalError: {152    _enum: ['LimitReached', 'NoLayer']153  },154  /**155   * Lookup27: cumulus_pallet_parachain_system::pallet::Event<T>156   **/157  CumulusPalletParachainSystemEvent: {158    _enum: {159      ValidationFunctionStored: 'Null',160      ValidationFunctionApplied: {161        relayChainBlockNum: 'u32',162      },163      ValidationFunctionDiscarded: 'Null',164      UpgradeAuthorized: {165        codeHash: 'H256',166      },167      DownwardMessagesReceived: {168        count: 'u32',169      },170      DownwardMessagesProcessed: {171        weightUsed: 'u64',172        dmqHead: 'H256'173      }174    }175  },176  /**177   * Lookup28: pallet_balances::pallet::Event<T, I>178   **/179  PalletBalancesEvent: {180    _enum: {181      Endowed: {182        account: 'AccountId32',183        freeBalance: 'u128',184      },185      DustLost: {186        account: 'AccountId32',187        amount: 'u128',188      },189      Transfer: {190        from: 'AccountId32',191        to: 'AccountId32',192        amount: 'u128',193      },194      BalanceSet: {195        who: 'AccountId32',196        free: 'u128',197        reserved: 'u128',198      },199      Reserved: {200        who: 'AccountId32',201        amount: 'u128',202      },203      Unreserved: {204        who: 'AccountId32',205        amount: 'u128',206      },207      ReserveRepatriated: {208        from: 'AccountId32',209        to: 'AccountId32',210        amount: 'u128',211        destinationStatus: 'FrameSupportTokensMiscBalanceStatus',212      },213      Deposit: {214        who: 'AccountId32',215        amount: 'u128',216      },217      Withdraw: {218        who: 'AccountId32',219        amount: 'u128',220      },221      Slashed: {222        who: 'AccountId32',223        amount: 'u128'224      }225    }226  },227  /**228   * Lookup29: frame_support::traits::tokens::misc::BalanceStatus229   **/230  FrameSupportTokensMiscBalanceStatus: {231    _enum: ['Free', 'Reserved']232  },233  /**234   * Lookup30: pallet_transaction_payment::pallet::Event<T>235   **/236  PalletTransactionPaymentEvent: {237    _enum: {238      TransactionFeePaid: {239        who: 'AccountId32',240        actualFee: 'u128',241        tip: 'u128'242      }243    }244  },245  /**246   * Lookup31: pallet_treasury::pallet::Event<T, I>247   **/248  PalletTreasuryEvent: {249    _enum: {250      Proposed: {251        proposalIndex: 'u32',252      },253      Spending: {254        budgetRemaining: 'u128',255      },256      Awarded: {257        proposalIndex: 'u32',258        award: 'u128',259        account: 'AccountId32',260      },261      Rejected: {262        proposalIndex: 'u32',263        slashed: 'u128',264      },265      Burnt: {266        burntFunds: 'u128',267      },268      Rollover: {269        rolloverBalance: 'u128',270      },271      Deposit: {272        value: 'u128',273      },274      SpendApproved: {275        proposalIndex: 'u32',276        amount: 'u128',277        beneficiary: 'AccountId32'278      }279    }280  },281  /**282   * Lookup32: pallet_sudo::pallet::Event<T>283   **/284  PalletSudoEvent: {285    _enum: {286      Sudid: {287        sudoResult: 'Result<Null, SpRuntimeDispatchError>',288      },289      KeyChanged: {290        oldSudoer: 'Option<AccountId32>',291      },292      SudoAsDone: {293        sudoResult: 'Result<Null, SpRuntimeDispatchError>'294      }295    }296  },297  /**298   * Lookup36: orml_vesting::module::Event<T>299   **/300  OrmlVestingModuleEvent: {301    _enum: {302      VestingScheduleAdded: {303        from: 'AccountId32',304        to: 'AccountId32',305        vestingSchedule: 'OrmlVestingVestingSchedule',306      },307      Claimed: {308        who: 'AccountId32',309        amount: 'u128',310      },311      VestingSchedulesUpdated: {312        who: 'AccountId32'313      }314    }315  },316  /**317   * Lookup37: orml_vesting::VestingSchedule<BlockNumber, Balance>318   **/319  OrmlVestingVestingSchedule: {320    start: 'u32',321    period: 'u32',322    periodCount: 'u32',323    perPeriod: 'Compact<u128>'324  },325  /**326   * Lookup39: cumulus_pallet_xcmp_queue::pallet::Event<T>327   **/328  CumulusPalletXcmpQueueEvent: {329    _enum: {330      Success: {331        messageHash: 'Option<H256>',332        weight: 'u64',333      },334      Fail: {335        messageHash: 'Option<H256>',336        error: 'XcmV2TraitsError',337        weight: 'u64',338      },339      BadVersion: {340        messageHash: 'Option<H256>',341      },342      BadFormat: {343        messageHash: 'Option<H256>',344      },345      UpwardMessageSent: {346        messageHash: 'Option<H256>',347      },348      XcmpMessageSent: {349        messageHash: 'Option<H256>',350      },351      OverweightEnqueued: {352        sender: 'u32',353        sentAt: 'u32',354        index: 'u64',355        required: 'u64',356      },357      OverweightServiced: {358        index: 'u64',359        used: 'u64'360      }361    }362  },363  /**364   * Lookup41: xcm::v2::traits::Error365   **/366  XcmV2TraitsError: {367    _enum: {368      Overflow: 'Null',369      Unimplemented: 'Null',370      UntrustedReserveLocation: 'Null',371      UntrustedTeleportLocation: 'Null',372      MultiLocationFull: 'Null',373      MultiLocationNotInvertible: 'Null',374      BadOrigin: 'Null',375      InvalidLocation: 'Null',376      AssetNotFound: 'Null',377      FailedToTransactAsset: 'Null',378      NotWithdrawable: 'Null',379      LocationCannotHold: 'Null',380      ExceedsMaxMessageSize: 'Null',381      DestinationUnsupported: 'Null',382      Transport: 'Null',383      Unroutable: 'Null',384      UnknownClaim: 'Null',385      FailedToDecode: 'Null',386      MaxWeightInvalid: 'Null',387      NotHoldingFees: 'Null',388      TooExpensive: 'Null',389      Trap: 'u64',390      UnhandledXcmVersion: 'Null',391      WeightLimitReached: 'u64',392      Barrier: 'Null',393      WeightNotComputable: 'Null'394    }395  },396  /**397   * Lookup43: pallet_xcm::pallet::Event<T>398   **/399  PalletXcmEvent: {400    _enum: {401      Attempted: 'XcmV2TraitsOutcome',402      Sent: '(XcmV1MultiLocation,XcmV1MultiLocation,XcmV2Xcm)',403      UnexpectedResponse: '(XcmV1MultiLocation,u64)',404      ResponseReady: '(u64,XcmV2Response)',405      Notified: '(u64,u8,u8)',406      NotifyOverweight: '(u64,u8,u8,u64,u64)',407      NotifyDispatchError: '(u64,u8,u8)',408      NotifyDecodeFailed: '(u64,u8,u8)',409      InvalidResponder: '(XcmV1MultiLocation,u64,Option<XcmV1MultiLocation>)',410      InvalidResponderVersion: '(XcmV1MultiLocation,u64)',411      ResponseTaken: 'u64',412      AssetsTrapped: '(H256,XcmV1MultiLocation,XcmVersionedMultiAssets)',413      VersionChangeNotified: '(XcmV1MultiLocation,u32)',414      SupportedVersionChanged: '(XcmV1MultiLocation,u32)',415      NotifyTargetSendFail: '(XcmV1MultiLocation,u64,XcmV2TraitsError)',416      NotifyTargetMigrationFail: '(XcmVersionedMultiLocation,u64)'417    }418  },419  /**420   * Lookup44: xcm::v2::traits::Outcome421   **/422  XcmV2TraitsOutcome: {423    _enum: {424      Complete: 'u64',425      Incomplete: '(u64,XcmV2TraitsError)',426      Error: 'XcmV2TraitsError'427    }428  },429  /**430   * Lookup45: xcm::v1::multilocation::MultiLocation431   **/432  XcmV1MultiLocation: {433    parents: 'u8',434    interior: 'XcmV1MultilocationJunctions'435  },436  /**437   * Lookup46: xcm::v1::multilocation::Junctions438   **/439  XcmV1MultilocationJunctions: {440    _enum: {441      Here: 'Null',442      X1: 'XcmV1Junction',443      X2: '(XcmV1Junction,XcmV1Junction)',444      X3: '(XcmV1Junction,XcmV1Junction,XcmV1Junction)',445      X4: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',446      X5: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',447      X6: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',448      X7: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',449      X8: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)'450    }451  },452  /**453   * Lookup47: xcm::v1::junction::Junction454   **/455  XcmV1Junction: {456    _enum: {457      Parachain: 'Compact<u32>',458      AccountId32: {459        network: 'XcmV0JunctionNetworkId',460        id: '[u8;32]',461      },462      AccountIndex64: {463        network: 'XcmV0JunctionNetworkId',464        index: 'Compact<u64>',465      },466      AccountKey20: {467        network: 'XcmV0JunctionNetworkId',468        key: '[u8;20]',469      },470      PalletInstance: 'u8',471      GeneralIndex: 'Compact<u128>',472      GeneralKey: 'Bytes',473      OnlyChild: 'Null',474      Plurality: {475        id: 'XcmV0JunctionBodyId',476        part: 'XcmV0JunctionBodyPart'477      }478    }479  },480  /**481   * Lookup49: xcm::v0::junction::NetworkId482   **/483  XcmV0JunctionNetworkId: {484    _enum: {485      Any: 'Null',486      Named: 'Bytes',487      Polkadot: 'Null',488      Kusama: 'Null'489    }490  },491  /**492   * Lookup53: xcm::v0::junction::BodyId493   **/494  XcmV0JunctionBodyId: {495    _enum: {496      Unit: 'Null',497      Named: 'Bytes',498      Index: 'Compact<u32>',499      Executive: 'Null',500      Technical: 'Null',501      Legislative: 'Null',502      Judicial: 'Null'503    }504  },505  /**506   * Lookup54: xcm::v0::junction::BodyPart507   **/508  XcmV0JunctionBodyPart: {509    _enum: {510      Voice: 'Null',511      Members: {512        count: 'Compact<u32>',513      },514      Fraction: {515        nom: 'Compact<u32>',516        denom: 'Compact<u32>',517      },518      AtLeastProportion: {519        nom: 'Compact<u32>',520        denom: 'Compact<u32>',521      },522      MoreThanProportion: {523        nom: 'Compact<u32>',524        denom: 'Compact<u32>'525      }526    }527  },528  /**529   * Lookup55: xcm::v2::Xcm<Call>530   **/531  XcmV2Xcm: 'Vec<XcmV2Instruction>',532  /**533   * Lookup57: xcm::v2::Instruction<Call>534   **/535  XcmV2Instruction: {536    _enum: {537      WithdrawAsset: 'XcmV1MultiassetMultiAssets',538      ReserveAssetDeposited: 'XcmV1MultiassetMultiAssets',539      ReceiveTeleportedAsset: 'XcmV1MultiassetMultiAssets',540      QueryResponse: {541        queryId: 'Compact<u64>',542        response: 'XcmV2Response',543        maxWeight: 'Compact<u64>',544      },545      TransferAsset: {546        assets: 'XcmV1MultiassetMultiAssets',547        beneficiary: 'XcmV1MultiLocation',548      },549      TransferReserveAsset: {550        assets: 'XcmV1MultiassetMultiAssets',551        dest: 'XcmV1MultiLocation',552        xcm: 'XcmV2Xcm',553      },554      Transact: {555        originType: 'XcmV0OriginKind',556        requireWeightAtMost: 'Compact<u64>',557        call: 'XcmDoubleEncoded',558      },559      HrmpNewChannelOpenRequest: {560        sender: 'Compact<u32>',561        maxMessageSize: 'Compact<u32>',562        maxCapacity: 'Compact<u32>',563      },564      HrmpChannelAccepted: {565        recipient: 'Compact<u32>',566      },567      HrmpChannelClosing: {568        initiator: 'Compact<u32>',569        sender: 'Compact<u32>',570        recipient: 'Compact<u32>',571      },572      ClearOrigin: 'Null',573      DescendOrigin: 'XcmV1MultilocationJunctions',574      ReportError: {575        queryId: 'Compact<u64>',576        dest: 'XcmV1MultiLocation',577        maxResponseWeight: 'Compact<u64>',578      },579      DepositAsset: {580        assets: 'XcmV1MultiassetMultiAssetFilter',581        maxAssets: 'Compact<u32>',582        beneficiary: 'XcmV1MultiLocation',583      },584      DepositReserveAsset: {585        assets: 'XcmV1MultiassetMultiAssetFilter',586        maxAssets: 'Compact<u32>',587        dest: 'XcmV1MultiLocation',588        xcm: 'XcmV2Xcm',589      },590      ExchangeAsset: {591        give: 'XcmV1MultiassetMultiAssetFilter',592        receive: 'XcmV1MultiassetMultiAssets',593      },594      InitiateReserveWithdraw: {595        assets: 'XcmV1MultiassetMultiAssetFilter',596        reserve: 'XcmV1MultiLocation',597        xcm: 'XcmV2Xcm',598      },599      InitiateTeleport: {600        assets: 'XcmV1MultiassetMultiAssetFilter',601        dest: 'XcmV1MultiLocation',602        xcm: 'XcmV2Xcm',603      },604      QueryHolding: {605        queryId: 'Compact<u64>',606        dest: 'XcmV1MultiLocation',607        assets: 'XcmV1MultiassetMultiAssetFilter',608        maxResponseWeight: 'Compact<u64>',609      },610      BuyExecution: {611        fees: 'XcmV1MultiAsset',612        weightLimit: 'XcmV2WeightLimit',613      },614      RefundSurplus: 'Null',615      SetErrorHandler: 'XcmV2Xcm',616      SetAppendix: 'XcmV2Xcm',617      ClearError: 'Null',618      ClaimAsset: {619        assets: 'XcmV1MultiassetMultiAssets',620        ticket: 'XcmV1MultiLocation',621      },622      Trap: 'Compact<u64>',623      SubscribeVersion: {624        queryId: 'Compact<u64>',625        maxResponseWeight: 'Compact<u64>',626      },627      UnsubscribeVersion: 'Null'628    }629  },630  /**631   * Lookup58: xcm::v1::multiasset::MultiAssets632   **/633  XcmV1MultiassetMultiAssets: 'Vec<XcmV1MultiAsset>',634  /**635   * Lookup60: xcm::v1::multiasset::MultiAsset636   **/637  XcmV1MultiAsset: {638    id: 'XcmV1MultiassetAssetId',639    fun: 'XcmV1MultiassetFungibility'640  },641  /**642   * Lookup61: xcm::v1::multiasset::AssetId643   **/644  XcmV1MultiassetAssetId: {645    _enum: {646      Concrete: 'XcmV1MultiLocation',647      Abstract: 'Bytes'648    }649  },650  /**651   * Lookup62: xcm::v1::multiasset::Fungibility652   **/653  XcmV1MultiassetFungibility: {654    _enum: {655      Fungible: 'Compact<u128>',656      NonFungible: 'XcmV1MultiassetAssetInstance'657    }658  },659  /**660   * Lookup63: xcm::v1::multiasset::AssetInstance661   **/662  XcmV1MultiassetAssetInstance: {663    _enum: {664      Undefined: 'Null',665      Index: 'Compact<u128>',666      Array4: '[u8;4]',667      Array8: '[u8;8]',668      Array16: '[u8;16]',669      Array32: '[u8;32]',670      Blob: 'Bytes'671    }672  },673  /**674   * Lookup66: xcm::v2::Response675   **/676  XcmV2Response: {677    _enum: {678      Null: 'Null',679      Assets: 'XcmV1MultiassetMultiAssets',680      ExecutionResult: 'Option<(u32,XcmV2TraitsError)>',681      Version: 'u32'682    }683  },684  /**685   * Lookup69: xcm::v0::OriginKind686   **/687  XcmV0OriginKind: {688    _enum: ['Native', 'SovereignAccount', 'Superuser', 'Xcm']689  },690  /**691   * Lookup70: xcm::double_encoded::DoubleEncoded<T>692   **/693  XcmDoubleEncoded: {694    encoded: 'Bytes'695  },696  /**697   * Lookup71: xcm::v1::multiasset::MultiAssetFilter698   **/699  XcmV1MultiassetMultiAssetFilter: {700    _enum: {701      Definite: 'XcmV1MultiassetMultiAssets',702      Wild: 'XcmV1MultiassetWildMultiAsset'703    }704  },705  /**706   * Lookup72: xcm::v1::multiasset::WildMultiAsset707   **/708  XcmV1MultiassetWildMultiAsset: {709    _enum: {710      All: 'Null',711      AllOf: {712        id: 'XcmV1MultiassetAssetId',713        fun: 'XcmV1MultiassetWildFungibility'714      }715    }716  },717  /**718   * Lookup73: xcm::v1::multiasset::WildFungibility719   **/720  XcmV1MultiassetWildFungibility: {721    _enum: ['Fungible', 'NonFungible']722  },723  /**724   * Lookup74: xcm::v2::WeightLimit725   **/726  XcmV2WeightLimit: {727    _enum: {728      Unlimited: 'Null',729      Limited: 'Compact<u64>'730    }731  },732  /**733   * Lookup76: xcm::VersionedMultiAssets734   **/735  XcmVersionedMultiAssets: {736    _enum: {737      V0: 'Vec<XcmV0MultiAsset>',738      V1: 'XcmV1MultiassetMultiAssets'739    }740  },741  /**742   * Lookup78: xcm::v0::multi_asset::MultiAsset743   **/744  XcmV0MultiAsset: {745    _enum: {746      None: 'Null',747      All: 'Null',748      AllFungible: 'Null',749      AllNonFungible: 'Null',750      AllAbstractFungible: {751        id: 'Bytes',752      },753      AllAbstractNonFungible: {754        class: 'Bytes',755      },756      AllConcreteFungible: {757        id: 'XcmV0MultiLocation',758      },759      AllConcreteNonFungible: {760        class: 'XcmV0MultiLocation',761      },762      AbstractFungible: {763        id: 'Bytes',764        amount: 'Compact<u128>',765      },766      AbstractNonFungible: {767        class: 'Bytes',768        instance: 'XcmV1MultiassetAssetInstance',769      },770      ConcreteFungible: {771        id: 'XcmV0MultiLocation',772        amount: 'Compact<u128>',773      },774      ConcreteNonFungible: {775        class: 'XcmV0MultiLocation',776        instance: 'XcmV1MultiassetAssetInstance'777      }778    }779  },780  /**781   * Lookup79: xcm::v0::multi_location::MultiLocation782   **/783  XcmV0MultiLocation: {784    _enum: {785      Null: 'Null',786      X1: 'XcmV0Junction',787      X2: '(XcmV0Junction,XcmV0Junction)',788      X3: '(XcmV0Junction,XcmV0Junction,XcmV0Junction)',789      X4: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',790      X5: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',791      X6: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',792      X7: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',793      X8: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)'794    }795  },796  /**797   * Lookup80: xcm::v0::junction::Junction798   **/799  XcmV0Junction: {800    _enum: {801      Parent: 'Null',802      Parachain: 'Compact<u32>',803      AccountId32: {804        network: 'XcmV0JunctionNetworkId',805        id: '[u8;32]',806      },807      AccountIndex64: {808        network: 'XcmV0JunctionNetworkId',809        index: 'Compact<u64>',810      },811      AccountKey20: {812        network: 'XcmV0JunctionNetworkId',813        key: '[u8;20]',814      },815      PalletInstance: 'u8',816      GeneralIndex: 'Compact<u128>',817      GeneralKey: 'Bytes',818      OnlyChild: 'Null',819      Plurality: {820        id: 'XcmV0JunctionBodyId',821        part: 'XcmV0JunctionBodyPart'822      }823    }824  },825  /**826   * Lookup81: xcm::VersionedMultiLocation827   **/828  XcmVersionedMultiLocation: {829    _enum: {830      V0: 'XcmV0MultiLocation',831      V1: 'XcmV1MultiLocation'832    }833  },834  /**835   * Lookup82: cumulus_pallet_xcm::pallet::Event<T>836   **/837  CumulusPalletXcmEvent: {838    _enum: {839      InvalidFormat: '[u8;8]',840      UnsupportedVersion: '[u8;8]',841      ExecutedDownward: '([u8;8],XcmV2TraitsOutcome)'842    }843  },844  /**845   * Lookup83: cumulus_pallet_dmp_queue::pallet::Event<T>846   **/847  CumulusPalletDmpQueueEvent: {848    _enum: {849      InvalidFormat: {850        messageId: '[u8;32]',851      },852      UnsupportedVersion: {853        messageId: '[u8;32]',854      },855      ExecutedDownward: {856        messageId: '[u8;32]',857        outcome: 'XcmV2TraitsOutcome',858      },859      WeightExhausted: {860        messageId: '[u8;32]',861        remainingWeight: 'u64',862        requiredWeight: 'u64',863      },864      OverweightEnqueued: {865        messageId: '[u8;32]',866        overweightIndex: 'u64',867        requiredWeight: 'u64',868      },869      OverweightServiced: {870        overweightIndex: 'u64',871        weightUsed: 'u64'872      }873    }874  },875  /**876   * Lookup84: pallet_unique::RawEvent<sp_core::crypto::AccountId32, pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>877   **/878  PalletUniqueRawEvent: {879    _enum: {880      CollectionSponsorRemoved: 'u32',881      CollectionAdminAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',882      CollectionOwnedChanged: '(u32,AccountId32)',883      CollectionSponsorSet: '(u32,AccountId32)',884      SponsorshipConfirmed: '(u32,AccountId32)',885      CollectionAdminRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',886      AllowListAddressRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',887      AllowListAddressAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',888      CollectionLimitSet: 'u32',889      CollectionPermissionSet: 'u32'890    }891  },892  /**893   * Lookup85: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>894   **/895  PalletEvmAccountBasicCrossAccountIdRepr: {896    _enum: {897      Substrate: 'AccountId32',898      Ethereum: 'H160'899    }900  },901  /**902   * Lookup88: pallet_unique_scheduler::pallet::Event<T>903   **/904  PalletUniqueSchedulerEvent: {905    _enum: {906      Scheduled: {907        when: 'u32',908        index: 'u32',909      },910      Canceled: {911        when: 'u32',912        index: 'u32',913      },914      Dispatched: {915        task: '(u32,u32)',916        id: 'Option<[u8;16]>',917        result: 'Result<Null, SpRuntimeDispatchError>',918      },919      CallLookupFailed: {920        task: '(u32,u32)',921        id: 'Option<[u8;16]>',922        error: 'FrameSupportScheduleLookupError'923      }924    }925  },926  /**927   * Lookup91: frame_support::traits::schedule::LookupError928   **/929  FrameSupportScheduleLookupError: {930    _enum: ['Unknown', 'BadFormat']931  },932  /**933   * Lookup92: pallet_common::pallet::Event<T>934   **/935  PalletCommonEvent: {936    _enum: {937      CollectionCreated: '(u32,u8,AccountId32)',938      CollectionDestroyed: 'u32',939      ItemCreated: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',940      ItemDestroyed: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',941      Transfer: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',942      Approved: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',943      CollectionPropertySet: '(u32,Bytes)',944      CollectionPropertyDeleted: '(u32,Bytes)',945      TokenPropertySet: '(u32,u32,Bytes)',946      TokenPropertyDeleted: '(u32,u32,Bytes)',947      PropertyPermissionSet: '(u32,Bytes)'948    }949  },950  /**951   * Lookup95: pallet_structure::pallet::Event<T>952   **/953  PalletStructureEvent: {954    _enum: {955      Executed: 'Result<Null, SpRuntimeDispatchError>'956    }957  },958  /**959   * Lookup96: pallet_rmrk_core::pallet::Event<T>960   **/961  PalletRmrkCoreEvent: {962    _enum: {963      CollectionCreated: {964        issuer: 'AccountId32',965        collectionId: 'u32',966      },967      CollectionDestroyed: {968        issuer: 'AccountId32',969        collectionId: 'u32',970      },971      IssuerChanged: {972        oldIssuer: 'AccountId32',973        newIssuer: 'AccountId32',974        collectionId: 'u32',975      },976      CollectionLocked: {977        issuer: 'AccountId32',978        collectionId: 'u32',979      },980      NftMinted: {981        owner: 'AccountId32',982        collectionId: 'u32',983        nftId: 'u32',984      },985      NFTBurned: {986        owner: 'AccountId32',987        nftId: 'u32',988      },989      NFTSent: {990        sender: 'AccountId32',991        recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',992        collectionId: 'u32',993        nftId: 'u32',994        approvalRequired: 'bool',995      },996      NFTAccepted: {997        sender: 'AccountId32',998        recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',999        collectionId: 'u32',1000        nftId: 'u32',1001      },1002      NFTRejected: {1003        sender: 'AccountId32',1004        collectionId: 'u32',1005        nftId: 'u32',1006      },1007      PropertySet: {1008        collectionId: 'u32',1009        maybeNftId: 'Option<u32>',1010        key: 'Bytes',1011        value: 'Bytes',1012      },1013      ResourceAdded: {1014        nftId: 'u32',1015        resourceId: 'u32',1016      },1017      ResourceRemoval: {1018        nftId: 'u32',1019        resourceId: 'u32',1020      },1021      ResourceAccepted: {1022        nftId: 'u32',1023        resourceId: 'u32',1024      },1025      ResourceRemovalAccepted: {1026        nftId: 'u32',1027        resourceId: 'u32',1028      },1029      PrioritySet: {1030        collectionId: 'u32',1031        nftId: 'u32'1032      }1033    }1034  },1035  /**1036   * Lookup97: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>1037   **/1038  RmrkTraitsNftAccountIdOrCollectionNftTuple: {1039    _enum: {1040      AccountId: 'AccountId32',1041      CollectionAndNftTuple: '(u32,u32)'1042    }1043  },1044  /**1045   * Lookup102: pallet_rmrk_equip::pallet::Event<T>1046   **/1047  PalletRmrkEquipEvent: {1048    _enum: {1049      BaseCreated: {1050        issuer: 'AccountId32',1051        baseId: 'u32',1052      },1053      EquippablesUpdated: {1054        baseId: 'u32',1055        slotId: 'u32'1056      }1057    }1058  },1059  /**1060   * Lookup103: pallet_app_promotion::pallet::Event<T>1061   **/1062  PalletAppPromotionEvent: {1063    _enum: {1064      StakingRecalculation: '(AccountId32,u128,u128)',1065      Stake: '(AccountId32,u128)',1066      Unstake: '(AccountId32,u128)',1067      SetAdmin: 'AccountId32'1068    }1069  },1070  /**1071   * Lookup104: pallet_evm::pallet::Event<T>1072   **/1073  PalletEvmEvent: {1074    _enum: {1075      Log: 'EthereumLog',1076      Created: 'H160',1077      CreatedFailed: 'H160',1078      Executed: 'H160',1079      ExecutedFailed: 'H160',1080      BalanceDeposit: '(AccountId32,H160,U256)',1081      BalanceWithdraw: '(AccountId32,H160,U256)'1082    }1083  },1084  /**1085   * Lookup105: ethereum::log::Log1086   **/1087  EthereumLog: {1088    address: 'H160',1089    topics: 'Vec<H256>',1090    data: 'Bytes'1091  },1092  /**1093   * Lookup109: pallet_ethereum::pallet::Event1094   **/1095  PalletEthereumEvent: {1096    _enum: {1097      Executed: '(H160,H160,H256,EvmCoreErrorExitReason)'1098    }1099  },1100  /**1101   * Lookup110: evm_core::error::ExitReason1102   **/1103  EvmCoreErrorExitReason: {1104    _enum: {1105      Succeed: 'EvmCoreErrorExitSucceed',1106      Error: 'EvmCoreErrorExitError',1107      Revert: 'EvmCoreErrorExitRevert',1108      Fatal: 'EvmCoreErrorExitFatal'1109    }1110  },1111  /**1112   * Lookup111: evm_core::error::ExitSucceed1113   **/1114  EvmCoreErrorExitSucceed: {1115    _enum: ['Stopped', 'Returned', 'Suicided']1116  },1117  /**1118   * Lookup112: evm_core::error::ExitError1119   **/1120  EvmCoreErrorExitError: {1121    _enum: {1122      StackUnderflow: 'Null',1123      StackOverflow: 'Null',1124      InvalidJump: 'Null',1125      InvalidRange: 'Null',1126      DesignatedInvalid: 'Null',1127      CallTooDeep: 'Null',1128      CreateCollision: 'Null',1129      CreateContractLimit: 'Null',1130      OutOfOffset: 'Null',1131      OutOfGas: 'Null',1132      OutOfFund: 'Null',1133      PCUnderflow: 'Null',1134      CreateEmpty: 'Null',1135      Other: 'Text',1136      InvalidCode: 'Null'1137    }1138  },1139  /**1140   * Lookup115: evm_core::error::ExitRevert1141   **/1142  EvmCoreErrorExitRevert: {1143    _enum: ['Reverted']1144  },1145  /**1146   * Lookup116: evm_core::error::ExitFatal1147   **/1148  EvmCoreErrorExitFatal: {1149    _enum: {1150      NotSupported: 'Null',1151      UnhandledInterrupt: 'Null',1152      CallErrorAsFatal: 'EvmCoreErrorExitError',1153      Other: 'Text'1154    }1155  },1156  /**1157   * Lookup117: pallet_evm_contract_helpers::pallet::Event<T>1158   **/1159  PalletEvmContractHelpersEvent: {1160    _enum: {1161      ContractSponsorSet: '(H160,AccountId32)',1162      ContractSponsorshipConfirmed: '(H160,AccountId32)',1163      ContractSponsorRemoved: 'H160'1164    }1165  },1166  /**1167   * Lookup118: frame_system::Phase1168   **/1169  FrameSystemPhase: {1170    _enum: {1171      ApplyExtrinsic: 'u32',1172      Finalization: 'Null',1173      Initialization: 'Null'1174    }1175  },1176  /**1177   * Lookup120: frame_system::LastRuntimeUpgradeInfo1178   **/1179  FrameSystemLastRuntimeUpgradeInfo: {1180    specVersion: 'Compact<u32>',1181    specName: 'Text'1182  },1183  /**1184   * Lookup121: frame_system::pallet::Call<T>1185   **/1186  FrameSystemCall: {1187    _enum: {1188      fill_block: {1189        ratio: 'Perbill',1190      },1191      remark: {1192        remark: 'Bytes',1193      },1194      set_heap_pages: {1195        pages: 'u64',1196      },1197      set_code: {1198        code: 'Bytes',1199      },1200      set_code_without_checks: {1201        code: 'Bytes',1202      },1203      set_storage: {1204        items: 'Vec<(Bytes,Bytes)>',1205      },1206      kill_storage: {1207        _alias: {1208          keys_: 'keys',1209        },1210        keys_: 'Vec<Bytes>',1211      },1212      kill_prefix: {1213        prefix: 'Bytes',1214        subkeys: 'u32',1215      },1216      remark_with_event: {1217        remark: 'Bytes'1218      }1219    }1220  },1221  /**1222   * Lookup126: frame_system::limits::BlockWeights1223   **/1224  FrameSystemLimitsBlockWeights: {1225    baseBlock: 'u64',1226    maxBlock: 'u64',1227    perClass: 'FrameSupportWeightsPerDispatchClassWeightsPerClass'1228  },1229  /**1230   * Lookup127: frame_support::weights::PerDispatchClass<frame_system::limits::WeightsPerClass>1231   **/1232  FrameSupportWeightsPerDispatchClassWeightsPerClass: {1233    normal: 'FrameSystemLimitsWeightsPerClass',1234    operational: 'FrameSystemLimitsWeightsPerClass',1235    mandatory: 'FrameSystemLimitsWeightsPerClass'1236  },1237  /**1238   * Lookup128: frame_system::limits::WeightsPerClass1239   **/1240  FrameSystemLimitsWeightsPerClass: {1241    baseExtrinsic: 'u64',1242    maxExtrinsic: 'Option<u64>',1243    maxTotal: 'Option<u64>',1244    reserved: 'Option<u64>'1245  },1246  /**1247   * Lookup130: frame_system::limits::BlockLength1248   **/1249  FrameSystemLimitsBlockLength: {1250    max: 'FrameSupportWeightsPerDispatchClassU32'1251  },1252  /**1253   * Lookup131: frame_support::weights::PerDispatchClass<T>1254   **/1255  FrameSupportWeightsPerDispatchClassU32: {1256    normal: 'u32',1257    operational: 'u32',1258    mandatory: 'u32'1259  },1260  /**1261   * Lookup132: frame_support::weights::RuntimeDbWeight1262   **/1263  FrameSupportWeightsRuntimeDbWeight: {1264    read: 'u64',1265    write: 'u64'1266  },1267  /**1268   * Lookup133: sp_version::RuntimeVersion1269   **/1270  SpVersionRuntimeVersion: {1271    specName: 'Text',1272    implName: 'Text',1273    authoringVersion: 'u32',1274    specVersion: 'u32',1275    implVersion: 'u32',1276    apis: 'Vec<([u8;8],u32)>',1277    transactionVersion: 'u32',1278    stateVersion: 'u8'1279  },1280  /**1281   * Lookup138: frame_system::pallet::Error<T>1282   **/1283  FrameSystemError: {1284    _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered']1285  },1286  /**1287   * Lookup139: polkadot_primitives::v2::PersistedValidationData<primitive_types::H256, N>1288   **/1289  PolkadotPrimitivesV2PersistedValidationData: {1290    parentHead: 'Bytes',1291    relayParentNumber: 'u32',1292    relayParentStorageRoot: 'H256',1293    maxPovSize: 'u32'1294  },1295  /**1296   * Lookup142: polkadot_primitives::v2::UpgradeRestriction1297   **/1298  PolkadotPrimitivesV2UpgradeRestriction: {1299    _enum: ['Present']1300  },1301  /**1302   * Lookup143: sp_trie::storage_proof::StorageProof1303   **/1304  SpTrieStorageProof: {1305    trieNodes: 'BTreeSet<Bytes>'1306  },1307  /**1308   * Lookup145: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot1309   **/1310  CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: {1311    dmqMqcHead: 'H256',1312    relayDispatchQueueSize: '(u32,u32)',1313    ingressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>',1314    egressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>'1315  },1316  /**1317   * Lookup148: polkadot_primitives::v2::AbridgedHrmpChannel1318   **/1319  PolkadotPrimitivesV2AbridgedHrmpChannel: {1320    maxCapacity: 'u32',1321    maxTotalSize: 'u32',1322    maxMessageSize: 'u32',1323    msgCount: 'u32',1324    totalSize: 'u32',1325    mqcHead: 'Option<H256>'1326  },1327  /**1328   * Lookup149: polkadot_primitives::v2::AbridgedHostConfiguration1329   **/1330  PolkadotPrimitivesV2AbridgedHostConfiguration: {1331    maxCodeSize: 'u32',1332    maxHeadDataSize: 'u32',1333    maxUpwardQueueCount: 'u32',1334    maxUpwardQueueSize: 'u32',1335    maxUpwardMessageSize: 'u32',1336    maxUpwardMessageNumPerCandidate: 'u32',1337    hrmpMaxMessageNumPerCandidate: 'u32',1338    validationUpgradeCooldown: 'u32',1339    validationUpgradeDelay: 'u32'1340  },1341  /**1342   * Lookup155: polkadot_core_primitives::OutboundHrmpMessage<polkadot_parachain::primitives::Id>1343   **/1344  PolkadotCorePrimitivesOutboundHrmpMessage: {1345    recipient: 'u32',1346    data: 'Bytes'1347  },1348  /**1349   * Lookup156: cumulus_pallet_parachain_system::pallet::Call<T>1350   **/1351  CumulusPalletParachainSystemCall: {1352    _enum: {1353      set_validation_data: {1354        data: 'CumulusPrimitivesParachainInherentParachainInherentData',1355      },1356      sudo_send_upward_message: {1357        message: 'Bytes',1358      },1359      authorize_upgrade: {1360        codeHash: 'H256',1361      },1362      enact_authorized_upgrade: {1363        code: 'Bytes'1364      }1365    }1366  },1367  /**1368   * Lookup157: cumulus_primitives_parachain_inherent::ParachainInherentData1369   **/1370  CumulusPrimitivesParachainInherentParachainInherentData: {1371    validationData: 'PolkadotPrimitivesV2PersistedValidationData',1372    relayChainState: 'SpTrieStorageProof',1373    downwardMessages: 'Vec<PolkadotCorePrimitivesInboundDownwardMessage>',1374    horizontalMessages: 'BTreeMap<u32, Vec<PolkadotCorePrimitivesInboundHrmpMessage>>'1375  },1376  /**1377   * Lookup159: polkadot_core_primitives::InboundDownwardMessage<BlockNumber>1378   **/1379  PolkadotCorePrimitivesInboundDownwardMessage: {1380    sentAt: 'u32',1381    msg: 'Bytes'1382  },1383  /**1384   * Lookup162: polkadot_core_primitives::InboundHrmpMessage<BlockNumber>1385   **/1386  PolkadotCorePrimitivesInboundHrmpMessage: {1387    sentAt: 'u32',1388    data: 'Bytes'1389  },1390  /**1391   * Lookup165: cumulus_pallet_parachain_system::pallet::Error<T>1392   **/1393  CumulusPalletParachainSystemError: {1394    _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized']1395  },1396  /**1397   * Lookup167: pallet_balances::BalanceLock<Balance>1398   **/1399  PalletBalancesBalanceLock: {1400    id: '[u8;8]',1401    amount: 'u128',1402    reasons: 'PalletBalancesReasons'1403  },1404  /**1405   * Lookup168: pallet_balances::Reasons1406   **/1407  PalletBalancesReasons: {1408    _enum: ['Fee', 'Misc', 'All']1409  },1410  /**1411   * Lookup171: pallet_balances::ReserveData<ReserveIdentifier, Balance>1412   **/1413  PalletBalancesReserveData: {1414    id: '[u8;16]',1415    amount: 'u128'1416  },1417  /**1418   * Lookup173: pallet_balances::Releases1419   **/1420  PalletBalancesReleases: {1421    _enum: ['V1_0_0', 'V2_0_0']1422  },1423  /**1424   * Lookup174: pallet_balances::pallet::Call<T, I>1425   **/1426  PalletBalancesCall: {1427    _enum: {1428      transfer: {1429        dest: 'MultiAddress',1430        value: 'Compact<u128>',1431      },1432      set_balance: {1433        who: 'MultiAddress',1434        newFree: 'Compact<u128>',1435        newReserved: 'Compact<u128>',1436      },1437      force_transfer: {1438        source: 'MultiAddress',1439        dest: 'MultiAddress',1440        value: 'Compact<u128>',1441      },1442      transfer_keep_alive: {1443        dest: 'MultiAddress',1444        value: 'Compact<u128>',1445      },1446      transfer_all: {1447        dest: 'MultiAddress',1448        keepAlive: 'bool',1449      },1450      force_unreserve: {1451        who: 'MultiAddress',1452        amount: 'u128'1453      }1454    }1455  },1456  /**1457   * Lookup177: pallet_balances::pallet::Error<T, I>1458   **/1459  PalletBalancesError: {1460    _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves']1461  },1462  /**1463   * Lookup179: pallet_timestamp::pallet::Call<T>1464   **/1465  PalletTimestampCall: {1466    _enum: {1467      set: {1468        now: 'Compact<u64>'1469      }1470    }1471  },1472  /**1473   * Lookup181: pallet_transaction_payment::Releases1474   **/1475  PalletTransactionPaymentReleases: {1476    _enum: ['V1Ancient', 'V2']1477  },1478  /**1479   * Lookup182: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>1480   **/1481  PalletTreasuryProposal: {1482    proposer: 'AccountId32',1483    value: 'u128',1484    beneficiary: 'AccountId32',1485    bond: 'u128'1486  },1487  /**1488   * Lookup185: pallet_treasury::pallet::Call<T, I>1489   **/1490  PalletTreasuryCall: {1491    _enum: {1492      propose_spend: {1493        value: 'Compact<u128>',1494        beneficiary: 'MultiAddress',1495      },1496      reject_proposal: {1497        proposalId: 'Compact<u32>',1498      },1499      approve_proposal: {1500        proposalId: 'Compact<u32>',1501      },1502      spend: {1503        amount: 'Compact<u128>',1504        beneficiary: 'MultiAddress',1505      },1506      remove_approval: {1507        proposalId: 'Compact<u32>'1508      }1509    }1510  },1511  /**1512   * Lookup188: frame_support::PalletId1513   **/1514  FrameSupportPalletId: '[u8;8]',1515  /**1516   * Lookup189: pallet_treasury::pallet::Error<T, I>1517   **/1518  PalletTreasuryError: {1519    _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'InsufficientPermission', 'ProposalNotApproved']1520  },1521  /**1522   * Lookup190: pallet_sudo::pallet::Call<T>1523   **/1524  PalletSudoCall: {1525    _enum: {1526      sudo: {1527        call: 'Call',1528      },1529      sudo_unchecked_weight: {1530        call: 'Call',1531        weight: 'u64',1532      },1533      set_key: {1534        _alias: {1535          new_: 'new',1536        },1537        new_: 'MultiAddress',1538      },1539      sudo_as: {1540        who: 'MultiAddress',1541        call: 'Call'1542      }1543    }1544  },1545  /**1546   * Lookup192: orml_vesting::module::Call<T>1547   **/1548  OrmlVestingModuleCall: {1549    _enum: {1550      claim: 'Null',1551      vested_transfer: {1552        dest: 'MultiAddress',1553        schedule: 'OrmlVestingVestingSchedule',1554      },1555      update_vesting_schedules: {1556        who: 'MultiAddress',1557        vestingSchedules: 'Vec<OrmlVestingVestingSchedule>',1558      },1559      claim_for: {1560        dest: 'MultiAddress'1561      }1562    }1563  },1564  /**1565   * Lookup194: cumulus_pallet_xcmp_queue::pallet::Call<T>1566   **/1567  CumulusPalletXcmpQueueCall: {1568    _enum: {1569      service_overweight: {1570        index: 'u64',1571        weightLimit: 'u64',1572      },1573      suspend_xcm_execution: 'Null',1574      resume_xcm_execution: 'Null',1575      update_suspend_threshold: {1576        _alias: {1577          new_: 'new',1578        },1579        new_: 'u32',1580      },1581      update_drop_threshold: {1582        _alias: {1583          new_: 'new',1584        },1585        new_: 'u32',1586      },1587      update_resume_threshold: {1588        _alias: {1589          new_: 'new',1590        },1591        new_: 'u32',1592      },1593      update_threshold_weight: {1594        _alias: {1595          new_: 'new',1596        },1597        new_: 'u64',1598      },1599      update_weight_restrict_decay: {1600        _alias: {1601          new_: 'new',1602        },1603        new_: 'u64',1604      },1605      update_xcmp_max_individual_weight: {1606        _alias: {1607          new_: 'new',1608        },1609        new_: 'u64'1610      }1611    }1612  },1613  /**1614   * Lookup195: pallet_xcm::pallet::Call<T>1615   **/1616  PalletXcmCall: {1617    _enum: {1618      send: {1619        dest: 'XcmVersionedMultiLocation',1620        message: 'XcmVersionedXcm',1621      },1622      teleport_assets: {1623        dest: 'XcmVersionedMultiLocation',1624        beneficiary: 'XcmVersionedMultiLocation',1625        assets: 'XcmVersionedMultiAssets',1626        feeAssetItem: 'u32',1627      },1628      reserve_transfer_assets: {1629        dest: 'XcmVersionedMultiLocation',1630        beneficiary: 'XcmVersionedMultiLocation',1631        assets: 'XcmVersionedMultiAssets',1632        feeAssetItem: 'u32',1633      },1634      execute: {1635        message: 'XcmVersionedXcm',1636        maxWeight: 'u64',1637      },1638      force_xcm_version: {1639        location: 'XcmV1MultiLocation',1640        xcmVersion: 'u32',1641      },1642      force_default_xcm_version: {1643        maybeXcmVersion: 'Option<u32>',1644      },1645      force_subscribe_version_notify: {1646        location: 'XcmVersionedMultiLocation',1647      },1648      force_unsubscribe_version_notify: {1649        location: 'XcmVersionedMultiLocation',1650      },1651      limited_reserve_transfer_assets: {1652        dest: 'XcmVersionedMultiLocation',1653        beneficiary: 'XcmVersionedMultiLocation',1654        assets: 'XcmVersionedMultiAssets',1655        feeAssetItem: 'u32',1656        weightLimit: 'XcmV2WeightLimit',1657      },1658      limited_teleport_assets: {1659        dest: 'XcmVersionedMultiLocation',1660        beneficiary: 'XcmVersionedMultiLocation',1661        assets: 'XcmVersionedMultiAssets',1662        feeAssetItem: 'u32',1663        weightLimit: 'XcmV2WeightLimit'1664      }1665    }1666  },1667  /**1668   * Lookup196: xcm::VersionedXcm<Call>1669   **/1670  XcmVersionedXcm: {1671    _enum: {1672      V0: 'XcmV0Xcm',1673      V1: 'XcmV1Xcm',1674      V2: 'XcmV2Xcm'1675    }1676  },1677  /**1678   * Lookup197: xcm::v0::Xcm<Call>1679   **/1680  XcmV0Xcm: {1681    _enum: {1682      WithdrawAsset: {1683        assets: 'Vec<XcmV0MultiAsset>',1684        effects: 'Vec<XcmV0Order>',1685      },1686      ReserveAssetDeposit: {1687        assets: 'Vec<XcmV0MultiAsset>',1688        effects: 'Vec<XcmV0Order>',1689      },1690      TeleportAsset: {1691        assets: 'Vec<XcmV0MultiAsset>',1692        effects: 'Vec<XcmV0Order>',1693      },1694      QueryResponse: {1695        queryId: 'Compact<u64>',1696        response: 'XcmV0Response',1697      },1698      TransferAsset: {1699        assets: 'Vec<XcmV0MultiAsset>',1700        dest: 'XcmV0MultiLocation',1701      },1702      TransferReserveAsset: {1703        assets: 'Vec<XcmV0MultiAsset>',1704        dest: 'XcmV0MultiLocation',1705        effects: 'Vec<XcmV0Order>',1706      },1707      Transact: {1708        originType: 'XcmV0OriginKind',1709        requireWeightAtMost: 'u64',1710        call: 'XcmDoubleEncoded',1711      },1712      HrmpNewChannelOpenRequest: {1713        sender: 'Compact<u32>',1714        maxMessageSize: 'Compact<u32>',1715        maxCapacity: 'Compact<u32>',1716      },1717      HrmpChannelAccepted: {1718        recipient: 'Compact<u32>',1719      },1720      HrmpChannelClosing: {1721        initiator: 'Compact<u32>',1722        sender: 'Compact<u32>',1723        recipient: 'Compact<u32>',1724      },1725      RelayedFrom: {1726        who: 'XcmV0MultiLocation',1727        message: 'XcmV0Xcm'1728      }1729    }1730  },1731  /**1732   * Lookup199: xcm::v0::order::Order<Call>1733   **/1734  XcmV0Order: {1735    _enum: {1736      Null: 'Null',1737      DepositAsset: {1738        assets: 'Vec<XcmV0MultiAsset>',1739        dest: 'XcmV0MultiLocation',1740      },1741      DepositReserveAsset: {1742        assets: 'Vec<XcmV0MultiAsset>',1743        dest: 'XcmV0MultiLocation',1744        effects: 'Vec<XcmV0Order>',1745      },1746      ExchangeAsset: {1747        give: 'Vec<XcmV0MultiAsset>',1748        receive: 'Vec<XcmV0MultiAsset>',1749      },1750      InitiateReserveWithdraw: {1751        assets: 'Vec<XcmV0MultiAsset>',1752        reserve: 'XcmV0MultiLocation',1753        effects: 'Vec<XcmV0Order>',1754      },1755      InitiateTeleport: {1756        assets: 'Vec<XcmV0MultiAsset>',1757        dest: 'XcmV0MultiLocation',1758        effects: 'Vec<XcmV0Order>',1759      },1760      QueryHolding: {1761        queryId: 'Compact<u64>',1762        dest: 'XcmV0MultiLocation',1763        assets: 'Vec<XcmV0MultiAsset>',1764      },1765      BuyExecution: {1766        fees: 'XcmV0MultiAsset',1767        weight: 'u64',1768        debt: 'u64',1769        haltOnError: 'bool',1770        xcm: 'Vec<XcmV0Xcm>'1771      }1772    }1773  },1774  /**1775   * Lookup201: xcm::v0::Response1776   **/1777  XcmV0Response: {1778    _enum: {1779      Assets: 'Vec<XcmV0MultiAsset>'1780    }1781  },1782  /**1783   * Lookup202: xcm::v1::Xcm<Call>1784   **/1785  XcmV1Xcm: {1786    _enum: {1787      WithdrawAsset: {1788        assets: 'XcmV1MultiassetMultiAssets',1789        effects: 'Vec<XcmV1Order>',1790      },1791      ReserveAssetDeposited: {1792        assets: 'XcmV1MultiassetMultiAssets',1793        effects: 'Vec<XcmV1Order>',1794      },1795      ReceiveTeleportedAsset: {1796        assets: 'XcmV1MultiassetMultiAssets',1797        effects: 'Vec<XcmV1Order>',1798      },1799      QueryResponse: {1800        queryId: 'Compact<u64>',1801        response: 'XcmV1Response',1802      },1803      TransferAsset: {1804        assets: 'XcmV1MultiassetMultiAssets',1805        beneficiary: 'XcmV1MultiLocation',1806      },1807      TransferReserveAsset: {1808        assets: 'XcmV1MultiassetMultiAssets',1809        dest: 'XcmV1MultiLocation',1810        effects: 'Vec<XcmV1Order>',1811      },1812      Transact: {1813        originType: 'XcmV0OriginKind',1814        requireWeightAtMost: 'u64',1815        call: 'XcmDoubleEncoded',1816      },1817      HrmpNewChannelOpenRequest: {1818        sender: 'Compact<u32>',1819        maxMessageSize: 'Compact<u32>',1820        maxCapacity: 'Compact<u32>',1821      },1822      HrmpChannelAccepted: {1823        recipient: 'Compact<u32>',1824      },1825      HrmpChannelClosing: {1826        initiator: 'Compact<u32>',1827        sender: 'Compact<u32>',1828        recipient: 'Compact<u32>',1829      },1830      RelayedFrom: {1831        who: 'XcmV1MultilocationJunctions',1832        message: 'XcmV1Xcm',1833      },1834      SubscribeVersion: {1835        queryId: 'Compact<u64>',1836        maxResponseWeight: 'Compact<u64>',1837      },1838      UnsubscribeVersion: 'Null'1839    }1840  },1841  /**1842   * Lookup204: xcm::v1::order::Order<Call>1843   **/1844  XcmV1Order: {1845    _enum: {1846      Noop: 'Null',1847      DepositAsset: {1848        assets: 'XcmV1MultiassetMultiAssetFilter',1849        maxAssets: 'u32',1850        beneficiary: 'XcmV1MultiLocation',1851      },1852      DepositReserveAsset: {1853        assets: 'XcmV1MultiassetMultiAssetFilter',1854        maxAssets: 'u32',1855        dest: 'XcmV1MultiLocation',1856        effects: 'Vec<XcmV1Order>',1857      },1858      ExchangeAsset: {1859        give: 'XcmV1MultiassetMultiAssetFilter',1860        receive: 'XcmV1MultiassetMultiAssets',1861      },1862      InitiateReserveWithdraw: {1863        assets: 'XcmV1MultiassetMultiAssetFilter',1864        reserve: 'XcmV1MultiLocation',1865        effects: 'Vec<XcmV1Order>',1866      },1867      InitiateTeleport: {1868        assets: 'XcmV1MultiassetMultiAssetFilter',1869        dest: 'XcmV1MultiLocation',1870        effects: 'Vec<XcmV1Order>',1871      },1872      QueryHolding: {1873        queryId: 'Compact<u64>',1874        dest: 'XcmV1MultiLocation',1875        assets: 'XcmV1MultiassetMultiAssetFilter',1876      },1877      BuyExecution: {1878        fees: 'XcmV1MultiAsset',1879        weight: 'u64',1880        debt: 'u64',1881        haltOnError: 'bool',1882        instructions: 'Vec<XcmV1Xcm>'1883      }1884    }1885  },1886  /**1887   * Lookup206: xcm::v1::Response1888   **/1889  XcmV1Response: {1890    _enum: {1891      Assets: 'XcmV1MultiassetMultiAssets',1892      Version: 'u32'1893    }1894  },1895  /**1896   * Lookup220: cumulus_pallet_xcm::pallet::Call<T>1897   **/1898  CumulusPalletXcmCall: 'Null',1899  /**1900   * Lookup221: cumulus_pallet_dmp_queue::pallet::Call<T>1901   **/1902  CumulusPalletDmpQueueCall: {1903    _enum: {1904      service_overweight: {1905        index: 'u64',1906        weightLimit: 'u64'1907      }1908    }1909  },1910  /**1911   * Lookup222: pallet_inflation::pallet::Call<T>1912   **/1913  PalletInflationCall: {1914    _enum: {1915      start_inflation: {1916        inflationStartRelayBlock: 'u32'1917      }1918    }1919  },1920  /**1921   * Lookup223: pallet_unique::Call<T>1922   **/1923  PalletUniqueCall: {1924    _enum: {1925      create_collection: {1926        collectionName: 'Vec<u16>',1927        collectionDescription: 'Vec<u16>',1928        tokenPrefix: 'Bytes',1929        mode: 'UpDataStructsCollectionMode',1930      },1931      create_collection_ex: {1932        data: 'UpDataStructsCreateCollectionData',1933      },1934      destroy_collection: {1935        collectionId: 'u32',1936      },1937      add_to_allow_list: {1938        collectionId: 'u32',1939        address: 'PalletEvmAccountBasicCrossAccountIdRepr',1940      },1941      remove_from_allow_list: {1942        collectionId: 'u32',1943        address: 'PalletEvmAccountBasicCrossAccountIdRepr',1944      },1945      change_collection_owner: {1946        collectionId: 'u32',1947        newOwner: 'AccountId32',1948      },1949      add_collection_admin: {1950        collectionId: 'u32',1951        newAdminId: 'PalletEvmAccountBasicCrossAccountIdRepr',1952      },1953      remove_collection_admin: {1954        collectionId: 'u32',1955        accountId: 'PalletEvmAccountBasicCrossAccountIdRepr',1956      },1957      set_collection_sponsor: {1958        collectionId: 'u32',1959        newSponsor: 'AccountId32',1960      },1961      confirm_sponsorship: {1962        collectionId: 'u32',1963      },1964      remove_collection_sponsor: {1965        collectionId: 'u32',1966      },1967      create_item: {1968        collectionId: 'u32',1969        owner: 'PalletEvmAccountBasicCrossAccountIdRepr',1970        data: 'UpDataStructsCreateItemData',1971      },1972      create_multiple_items: {1973        collectionId: 'u32',1974        owner: 'PalletEvmAccountBasicCrossAccountIdRepr',1975        itemsData: 'Vec<UpDataStructsCreateItemData>',1976      },1977      set_collection_properties: {1978        collectionId: 'u32',1979        properties: 'Vec<UpDataStructsProperty>',1980      },1981      delete_collection_properties: {1982        collectionId: 'u32',1983        propertyKeys: 'Vec<Bytes>',1984      },1985      set_token_properties: {1986        collectionId: 'u32',1987        tokenId: 'u32',1988        properties: 'Vec<UpDataStructsProperty>',1989      },1990      delete_token_properties: {1991        collectionId: 'u32',1992        tokenId: 'u32',1993        propertyKeys: 'Vec<Bytes>',1994      },1995      set_token_property_permissions: {1996        collectionId: 'u32',1997        propertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',1998      },1999      create_multiple_items_ex: {2000        collectionId: 'u32',2001        data: 'UpDataStructsCreateItemExData',2002      },2003      set_transfers_enabled_flag: {2004        collectionId: 'u32',2005        value: 'bool',2006      },2007      burn_item: {2008        collectionId: 'u32',2009        itemId: 'u32',2010        value: 'u128',2011      },2012      burn_from: {2013        collectionId: 'u32',2014        from: 'PalletEvmAccountBasicCrossAccountIdRepr',2015        itemId: 'u32',2016        value: 'u128',2017      },2018      transfer: {2019        recipient: 'PalletEvmAccountBasicCrossAccountIdRepr',2020        collectionId: 'u32',2021        itemId: 'u32',2022        value: 'u128',2023      },2024      approve: {2025        spender: 'PalletEvmAccountBasicCrossAccountIdRepr',2026        collectionId: 'u32',2027        itemId: 'u32',2028        amount: 'u128',2029      },2030      transfer_from: {2031        from: 'PalletEvmAccountBasicCrossAccountIdRepr',2032        recipient: 'PalletEvmAccountBasicCrossAccountIdRepr',2033        collectionId: 'u32',2034        itemId: 'u32',2035        value: 'u128',2036      },2037      set_collection_limits: {2038        collectionId: 'u32',2039        newLimit: 'UpDataStructsCollectionLimits',2040      },2041      set_collection_permissions: {2042        collectionId: 'u32',2043        newPermission: 'UpDataStructsCollectionPermissions',2044      },2045      repartition: {2046        collectionId: 'u32',2047        tokenId: 'u32',2048        amount: 'u128'2049      }2050    }2051  },2052  /**2053   * Lookup228: up_data_structs::CollectionMode2054   **/2055  UpDataStructsCollectionMode: {2056    _enum: {2057      NFT: 'Null',2058      Fungible: 'u8',2059      ReFungible: 'Null'2060    }2061  },2062  /**2063   * Lookup229: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>2064   **/2065  UpDataStructsCreateCollectionData: {2066    mode: 'UpDataStructsCollectionMode',2067    access: 'Option<UpDataStructsAccessMode>',2068    name: 'Vec<u16>',2069    description: 'Vec<u16>',2070    tokenPrefix: 'Bytes',2071    pendingSponsor: 'Option<AccountId32>',2072    limits: 'Option<UpDataStructsCollectionLimits>',2073    permissions: 'Option<UpDataStructsCollectionPermissions>',2074    tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',2075    properties: 'Vec<UpDataStructsProperty>'2076  },2077  /**2078   * Lookup231: up_data_structs::AccessMode2079   **/2080  UpDataStructsAccessMode: {2081    _enum: ['Normal', 'AllowList']2082  },2083  /**2084   * Lookup233: up_data_structs::CollectionLimits2085   **/2086  UpDataStructsCollectionLimits: {2087    accountTokenOwnershipLimit: 'Option<u32>',2088    sponsoredDataSize: 'Option<u32>',2089    sponsoredDataRateLimit: 'Option<UpDataStructsSponsoringRateLimit>',2090    tokenLimit: 'Option<u32>',2091    sponsorTransferTimeout: 'Option<u32>',2092    sponsorApproveTimeout: 'Option<u32>',2093    ownerCanTransfer: 'Option<bool>',2094    ownerCanDestroy: 'Option<bool>',2095    transfersEnabled: 'Option<bool>'2096  },2097  /**2098   * Lookup235: up_data_structs::SponsoringRateLimit2099   **/2100  UpDataStructsSponsoringRateLimit: {2101    _enum: {2102      SponsoringDisabled: 'Null',2103      Blocks: 'u32'2104    }2105  },2106  /**2107   * Lookup238: up_data_structs::CollectionPermissions2108   **/2109  UpDataStructsCollectionPermissions: {2110    access: 'Option<UpDataStructsAccessMode>',2111    mintMode: 'Option<bool>',2112    nesting: 'Option<UpDataStructsNestingPermissions>'2113  },2114  /**2115   * Lookup240: up_data_structs::NestingPermissions2116   **/2117  UpDataStructsNestingPermissions: {2118    tokenOwner: 'bool',2119    collectionAdmin: 'bool',2120    restricted: 'Option<UpDataStructsOwnerRestrictedSet>'2121  },2122  /**2123   * Lookup242: up_data_structs::OwnerRestrictedSet2124   **/2125  UpDataStructsOwnerRestrictedSet: 'BTreeSet<u32>',2126  /**2127   * Lookup247: up_data_structs::PropertyKeyPermission2128   **/2129  UpDataStructsPropertyKeyPermission: {2130    key: 'Bytes',2131    permission: 'UpDataStructsPropertyPermission'2132  },2133  /**2134   * Lookup248: up_data_structs::PropertyPermission2135   **/2136  UpDataStructsPropertyPermission: {2137    mutable: 'bool',2138    collectionAdmin: 'bool',2139    tokenOwner: 'bool'2140  },2141  /**2142   * Lookup251: up_data_structs::Property2143   **/2144  UpDataStructsProperty: {2145    key: 'Bytes',2146    value: 'Bytes'2147  },2148  /**2149   * Lookup254: up_data_structs::CreateItemData2150   **/2151  UpDataStructsCreateItemData: {2152    _enum: {2153      NFT: 'UpDataStructsCreateNftData',2154      Fungible: 'UpDataStructsCreateFungibleData',2155      ReFungible: 'UpDataStructsCreateReFungibleData'2156    }2157  },2158  /**2159   * Lookup255: up_data_structs::CreateNftData2160   **/2161  UpDataStructsCreateNftData: {2162    properties: 'Vec<UpDataStructsProperty>'2163  },2164  /**2165   * Lookup256: up_data_structs::CreateFungibleData2166   **/2167  UpDataStructsCreateFungibleData: {2168    value: 'u128'2169  },2170  /**2171   * Lookup257: up_data_structs::CreateReFungibleData2172   **/2173  UpDataStructsCreateReFungibleData: {2174    pieces: 'u128',2175    properties: 'Vec<UpDataStructsProperty>'2176  },2177  /**2178   * Lookup260: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2179   **/2180  UpDataStructsCreateItemExData: {2181    _enum: {2182      NFT: 'Vec<UpDataStructsCreateNftExData>',2183      Fungible: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',2184      RefungibleMultipleItems: 'Vec<UpDataStructsCreateRefungibleExSingleOwner>',2185      RefungibleMultipleOwners: 'UpDataStructsCreateRefungibleExMultipleOwners'2186    }2187  },2188  /**2189   * Lookup262: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2190   **/2191  UpDataStructsCreateNftExData: {2192    properties: 'Vec<UpDataStructsProperty>',2193    owner: 'PalletEvmAccountBasicCrossAccountIdRepr'2194  },2195  /**2196   * Lookup269: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2197   **/2198  UpDataStructsCreateRefungibleExSingleOwner: {2199    user: 'PalletEvmAccountBasicCrossAccountIdRepr',2200    pieces: 'u128',2201    properties: 'Vec<UpDataStructsProperty>'2202  },2203  /**2204   * Lookup271: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2205   **/2206  UpDataStructsCreateRefungibleExMultipleOwners: {2207    users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',2208    properties: 'Vec<UpDataStructsProperty>'2209  },2210  /**2211   * Lookup272: pallet_unique_scheduler::pallet::Call<T>2212   **/2213  PalletUniqueSchedulerCall: {2214    _enum: {2215      schedule_named: {2216        id: '[u8;16]',2217        when: 'u32',2218        maybePeriodic: 'Option<(u32,u32)>',2219        priority: 'u8',2220        call: 'FrameSupportScheduleMaybeHashed',2221      },2222      cancel_named: {2223        id: '[u8;16]',2224      },2225      schedule_named_after: {2226        id: '[u8;16]',2227        after: 'u32',2228        maybePeriodic: 'Option<(u32,u32)>',2229        priority: 'u8',2230        call: 'FrameSupportScheduleMaybeHashed'2231      }2232    }2233  },2234  /**2235   * Lookup274: frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>2236   **/2237  FrameSupportScheduleMaybeHashed: {2238    _enum: {2239      Value: 'Call',2240      Hash: 'H256'2241    }2242  },2243  /**2244   * Lookup275: pallet_configuration::pallet::Call<T>2245   **/2246  PalletConfigurationCall: {2247    _enum: {2248      set_weight_to_fee_coefficient_override: {2249        coeff: 'Option<u32>',2250      },2251      set_min_gas_price_override: {2252        coeff: 'Option<u64>'2253      }2254    }2255  },2256  /**2257   * Lookup276: pallet_template_transaction_payment::Call<T>2258   **/2259  PalletTemplateTransactionPaymentCall: 'Null',2260  /**2261   * Lookup277: pallet_structure::pallet::Call<T>2262   **/2263  PalletStructureCall: 'Null',2264  /**2265   * Lookup278: pallet_rmrk_core::pallet::Call<T>2266   **/2267  PalletRmrkCoreCall: {2268    _enum: {2269      create_collection: {2270        metadata: 'Bytes',2271        max: 'Option<u32>',2272        symbol: 'Bytes',2273      },2274      destroy_collection: {2275        collectionId: 'u32',2276      },2277      change_collection_issuer: {2278        collectionId: 'u32',2279        newIssuer: 'MultiAddress',2280      },2281      lock_collection: {2282        collectionId: 'u32',2283      },2284      mint_nft: {2285        owner: 'Option<AccountId32>',2286        collectionId: 'u32',2287        recipient: 'Option<AccountId32>',2288        royaltyAmount: 'Option<Permill>',2289        metadata: 'Bytes',2290        transferable: 'bool',2291        resources: 'Option<Vec<RmrkTraitsResourceResourceTypes>>',2292      },2293      burn_nft: {2294        collectionId: 'u32',2295        nftId: 'u32',2296        maxBurns: 'u32',2297      },2298      send: {2299        rmrkCollectionId: 'u32',2300        rmrkNftId: 'u32',2301        newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2302      },2303      accept_nft: {2304        rmrkCollectionId: 'u32',2305        rmrkNftId: 'u32',2306        newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2307      },2308      reject_nft: {2309        rmrkCollectionId: 'u32',2310        rmrkNftId: 'u32',2311      },2312      accept_resource: {2313        rmrkCollectionId: 'u32',2314        rmrkNftId: 'u32',2315        resourceId: 'u32',2316      },2317      accept_resource_removal: {2318        rmrkCollectionId: 'u32',2319        rmrkNftId: 'u32',2320        resourceId: 'u32',2321      },2322      set_property: {2323        rmrkCollectionId: 'Compact<u32>',2324        maybeNftId: 'Option<u32>',2325        key: 'Bytes',2326        value: 'Bytes',2327      },2328      set_priority: {2329        rmrkCollectionId: 'u32',2330        rmrkNftId: 'u32',2331        priorities: 'Vec<u32>',2332      },2333      add_basic_resource: {2334        rmrkCollectionId: 'u32',2335        nftId: 'u32',2336        resource: 'RmrkTraitsResourceBasicResource',2337      },2338      add_composable_resource: {2339        rmrkCollectionId: 'u32',2340        nftId: 'u32',2341        resource: 'RmrkTraitsResourceComposableResource',2342      },2343      add_slot_resource: {2344        rmrkCollectionId: 'u32',2345        nftId: 'u32',2346        resource: 'RmrkTraitsResourceSlotResource',2347      },2348      remove_resource: {2349        rmrkCollectionId: 'u32',2350        nftId: 'u32',2351        resourceId: 'u32'2352      }2353    }2354  },2355  /**2356   * Lookup284: rmrk_traits::resource::ResourceTypes<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2357   **/2358  RmrkTraitsResourceResourceTypes: {2359    _enum: {2360      Basic: 'RmrkTraitsResourceBasicResource',2361      Composable: 'RmrkTraitsResourceComposableResource',2362      Slot: 'RmrkTraitsResourceSlotResource'2363    }2364  },2365  /**2366   * Lookup286: rmrk_traits::resource::BasicResource<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2367   **/2368  RmrkTraitsResourceBasicResource: {2369    src: 'Option<Bytes>',2370    metadata: 'Option<Bytes>',2371    license: 'Option<Bytes>',2372    thumb: 'Option<Bytes>'2373  },2374  /**2375   * Lookup288: rmrk_traits::resource::ComposableResource<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2376   **/2377  RmrkTraitsResourceComposableResource: {2378    parts: 'Vec<u32>',2379    base: 'u32',2380    src: 'Option<Bytes>',2381    metadata: 'Option<Bytes>',2382    license: 'Option<Bytes>',2383    thumb: 'Option<Bytes>'2384  },2385  /**2386   * Lookup289: rmrk_traits::resource::SlotResource<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2387   **/2388  RmrkTraitsResourceSlotResource: {2389    base: 'u32',2390    src: 'Option<Bytes>',2391    metadata: 'Option<Bytes>',2392    slot: 'u32',2393    license: 'Option<Bytes>',2394    thumb: 'Option<Bytes>'2395  },2396  /**2397   * Lookup292: pallet_rmrk_equip::pallet::Call<T>2398   **/2399  PalletRmrkEquipCall: {2400    _enum: {2401      create_base: {2402        baseType: 'Bytes',2403        symbol: 'Bytes',2404        parts: 'Vec<RmrkTraitsPartPartType>',2405      },2406      theme_add: {2407        baseId: 'u32',2408        theme: 'RmrkTraitsTheme',2409      },2410      equippable: {2411        baseId: 'u32',2412        slotId: 'u32',2413        equippables: 'RmrkTraitsPartEquippableList'2414      }2415    }2416  },2417  /**2418   * Lookup295: rmrk_traits::part::PartType<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2419   **/2420  RmrkTraitsPartPartType: {2421    _enum: {2422      FixedPart: 'RmrkTraitsPartFixedPart',2423      SlotPart: 'RmrkTraitsPartSlotPart'2424    }2425  },2426  /**2427   * Lookup297: rmrk_traits::part::FixedPart<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2428   **/2429  RmrkTraitsPartFixedPart: {2430    id: 'u32',2431    z: 'u32',2432    src: 'Bytes'2433  },2434  /**2435   * Lookup298: rmrk_traits::part::SlotPart<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2436   **/2437  RmrkTraitsPartSlotPart: {2438    id: 'u32',2439    equippable: 'RmrkTraitsPartEquippableList',2440    src: 'Bytes',2441    z: 'u32'2442  },2443  /**2444   * Lookup299: rmrk_traits::part::EquippableList<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2445   **/2446  RmrkTraitsPartEquippableList: {2447    _enum: {2448      All: 'Null',2449      Empty: 'Null',2450      Custom: 'Vec<u32>'2451    }2452  },2453  /**2454   * Lookup301: rmrk_traits::theme::Theme<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<rmrk_traits::theme::ThemeProperty<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>, S>>2455   **/2456  RmrkTraitsTheme: {2457    name: 'Bytes',2458    properties: 'Vec<RmrkTraitsThemeThemeProperty>',2459    inherit: 'bool'2460  },2461  /**2462   * Lookup303: rmrk_traits::theme::ThemeProperty<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2463   **/2464  RmrkTraitsThemeThemeProperty: {2465    key: 'Bytes',2466    value: 'Bytes'2467  },2468  /**2469   * Lookup305: pallet_app_promotion::pallet::Call<T>2470   **/2471  PalletAppPromotionCall: {2472    _enum: {2473      set_admin_address: {2474        admin: 'PalletEvmAccountBasicCrossAccountIdRepr',2475      },2476      stake: {2477        amount: 'u128',2478      },2479      unstake: 'Null',2480      sponsor_collection: {2481        collectionId: 'u32',2482      },2483      stop_sponsoring_collection: {2484        collectionId: 'u32',2485      },2486      sponsor_contract: {2487        contractId: 'H160',2488      },2489      stop_sponsoring_contract: {2490        contractId: 'H160',2491      },2492      payout_stakers: {2493        stakersNumber: 'Option<u8>'2494      }2495    }2496  },2497  /**2498   * Lookup307: pallet_evm::pallet::Call<T>2499   **/2500  PalletEvmCall: {2501    _enum: {2502      withdraw: {2503        address: 'H160',2504        value: 'u128',2505      },2506      call: {2507        source: 'H160',2508        target: 'H160',2509        input: 'Bytes',2510        value: 'U256',2511        gasLimit: 'u64',2512        maxFeePerGas: 'U256',2513        maxPriorityFeePerGas: 'Option<U256>',2514        nonce: 'Option<U256>',2515        accessList: 'Vec<(H160,Vec<H256>)>',2516      },2517      create: {2518        source: 'H160',2519        init: 'Bytes',2520        value: 'U256',2521        gasLimit: 'u64',2522        maxFeePerGas: 'U256',2523        maxPriorityFeePerGas: 'Option<U256>',2524        nonce: 'Option<U256>',2525        accessList: 'Vec<(H160,Vec<H256>)>',2526      },2527      create2: {2528        source: 'H160',2529        init: 'Bytes',2530        salt: 'H256',2531        value: 'U256',2532        gasLimit: 'u64',2533        maxFeePerGas: 'U256',2534        maxPriorityFeePerGas: 'Option<U256>',2535        nonce: 'Option<U256>',2536        accessList: 'Vec<(H160,Vec<H256>)>'2537      }2538    }2539  },2540  /**2541   * Lookup311: pallet_ethereum::pallet::Call<T>2542   **/2543  PalletEthereumCall: {2544    _enum: {2545      transact: {2546        transaction: 'EthereumTransactionTransactionV2'2547      }2548    }2549  },2550  /**2551   * Lookup312: ethereum::transaction::TransactionV22552   **/2553  EthereumTransactionTransactionV2: {2554    _enum: {2555      Legacy: 'EthereumTransactionLegacyTransaction',2556      EIP2930: 'EthereumTransactionEip2930Transaction',2557      EIP1559: 'EthereumTransactionEip1559Transaction'2558    }2559  },2560  /**2561   * Lookup313: ethereum::transaction::LegacyTransaction2562   **/2563  EthereumTransactionLegacyTransaction: {2564    nonce: 'U256',2565    gasPrice: 'U256',2566    gasLimit: 'U256',2567    action: 'EthereumTransactionTransactionAction',2568    value: 'U256',2569    input: 'Bytes',2570    signature: 'EthereumTransactionTransactionSignature'2571  },2572  /**2573   * Lookup314: ethereum::transaction::TransactionAction2574   **/2575  EthereumTransactionTransactionAction: {2576    _enum: {2577      Call: 'H160',2578      Create: 'Null'2579    }2580  },2581  /**2582   * Lookup315: ethereum::transaction::TransactionSignature2583   **/2584  EthereumTransactionTransactionSignature: {2585    v: 'u64',2586    r: 'H256',2587    s: 'H256'2588  },2589  /**2590   * Lookup317: ethereum::transaction::EIP2930Transaction2591   **/2592  EthereumTransactionEip2930Transaction: {2593    chainId: 'u64',2594    nonce: 'U256',2595    gasPrice: 'U256',2596    gasLimit: 'U256',2597    action: 'EthereumTransactionTransactionAction',2598    value: 'U256',2599    input: 'Bytes',2600    accessList: 'Vec<EthereumTransactionAccessListItem>',2601    oddYParity: 'bool',2602    r: 'H256',2603    s: 'H256'2604  },2605  /**2606   * Lookup319: ethereum::transaction::AccessListItem2607   **/2608  EthereumTransactionAccessListItem: {2609    address: 'H160',2610    storageKeys: 'Vec<H256>'2611  },2612  /**2613   * Lookup320: ethereum::transaction::EIP1559Transaction2614   **/2615  EthereumTransactionEip1559Transaction: {2616    chainId: 'u64',2617    nonce: 'U256',2618    maxPriorityFeePerGas: 'U256',2619    maxFeePerGas: 'U256',2620    gasLimit: 'U256',2621    action: 'EthereumTransactionTransactionAction',2622    value: 'U256',2623    input: 'Bytes',2624    accessList: 'Vec<EthereumTransactionAccessListItem>',2625    oddYParity: 'bool',2626    r: 'H256',2627    s: 'H256'2628  },2629  /**2630   * Lookup321: pallet_evm_migration::pallet::Call<T>2631   **/2632  PalletEvmMigrationCall: {2633    _enum: {2634      begin: {2635        address: 'H160',2636      },2637      set_data: {2638        address: 'H160',2639        data: 'Vec<(H256,H256)>',2640      },2641      finish: {2642        address: 'H160',2643        code: 'Bytes'2644      }2645    }2646  },2647  /**2648   * Lookup324: pallet_sudo::pallet::Error<T>2649   **/2650  PalletSudoError: {2651    _enum: ['RequireSudo']2652  },2653  /**2654   * Lookup326: orml_vesting::module::Error<T>2655   **/2656  OrmlVestingModuleError: {2657    _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded']2658  },2659  /**2660   * Lookup328: cumulus_pallet_xcmp_queue::InboundChannelDetails2661   **/2662  CumulusPalletXcmpQueueInboundChannelDetails: {2663    sender: 'u32',2664    state: 'CumulusPalletXcmpQueueInboundState',2665    messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>'2666  },2667  /**2668   * Lookup329: cumulus_pallet_xcmp_queue::InboundState2669   **/2670  CumulusPalletXcmpQueueInboundState: {2671    _enum: ['Ok', 'Suspended']2672  },2673  /**2674   * Lookup332: polkadot_parachain::primitives::XcmpMessageFormat2675   **/2676  PolkadotParachainPrimitivesXcmpMessageFormat: {2677    _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals']2678  },2679  /**2680   * Lookup335: cumulus_pallet_xcmp_queue::OutboundChannelDetails2681   **/2682  CumulusPalletXcmpQueueOutboundChannelDetails: {2683    recipient: 'u32',2684    state: 'CumulusPalletXcmpQueueOutboundState',2685    signalsExist: 'bool',2686    firstIndex: 'u16',2687    lastIndex: 'u16'2688  },2689  /**2690   * Lookup336: cumulus_pallet_xcmp_queue::OutboundState2691   **/2692  CumulusPalletXcmpQueueOutboundState: {2693    _enum: ['Ok', 'Suspended']2694  },2695  /**2696   * Lookup338: cumulus_pallet_xcmp_queue::QueueConfigData2697   **/2698  CumulusPalletXcmpQueueQueueConfigData: {2699    suspendThreshold: 'u32',2700    dropThreshold: 'u32',2701    resumeThreshold: 'u32',2702    thresholdWeight: 'u64',2703    weightRestrictDecay: 'u64',2704    xcmpMaxIndividualWeight: 'u64'2705  },2706  /**2707   * Lookup340: cumulus_pallet_xcmp_queue::pallet::Error<T>2708   **/2709  CumulusPalletXcmpQueueError: {2710    _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit']2711  },2712  /**2713   * Lookup341: pallet_xcm::pallet::Error<T>2714   **/2715  PalletXcmError: {2716    _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed']2717  },2718  /**2719   * Lookup342: cumulus_pallet_xcm::pallet::Error<T>2720   **/2721  CumulusPalletXcmError: 'Null',2722  /**2723   * Lookup343: cumulus_pallet_dmp_queue::ConfigData2724   **/2725  CumulusPalletDmpQueueConfigData: {2726    maxIndividual: 'u64'2727  },2728  /**2729   * Lookup344: cumulus_pallet_dmp_queue::PageIndexData2730   **/2731  CumulusPalletDmpQueuePageIndexData: {2732    beginUsed: 'u32',2733    endUsed: 'u32',2734    overweightCount: 'u64'2735  },2736  /**2737   * Lookup347: cumulus_pallet_dmp_queue::pallet::Error<T>2738   **/2739  CumulusPalletDmpQueueError: {2740    _enum: ['Unknown', 'OverLimit']2741  },2742  /**2743   * Lookup351: pallet_unique::Error<T>2744   **/2745  PalletUniqueError: {2746    _enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection']2747  },2748  /**2749   * Lookup354: pallet_unique_scheduler::ScheduledV3<frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>2750   **/2751  PalletUniqueSchedulerScheduledV3: {2752    maybeId: 'Option<[u8;16]>',2753    priority: 'u8',2754    call: 'FrameSupportScheduleMaybeHashed',2755    maybePeriodic: 'Option<(u32,u32)>',2756    origin: 'OpalRuntimeOriginCaller'2757  },2758  /**2759   * Lookup355: opal_runtime::OriginCaller2760   **/2761  OpalRuntimeOriginCaller: {2762    _enum: {2763      system: 'FrameSupportDispatchRawOrigin',2764      __Unused1: 'Null',2765      __Unused2: 'Null',2766      __Unused3: 'Null',2767      Void: 'SpCoreVoid',2768      __Unused5: 'Null',2769      __Unused6: 'Null',2770      __Unused7: 'Null',2771      __Unused8: 'Null',2772      __Unused9: 'Null',2773      __Unused10: 'Null',2774      __Unused11: 'Null',2775      __Unused12: 'Null',2776      __Unused13: 'Null',2777      __Unused14: 'Null',2778      __Unused15: 'Null',2779      __Unused16: 'Null',2780      __Unused17: 'Null',2781      __Unused18: 'Null',2782      __Unused19: 'Null',2783      __Unused20: 'Null',2784      __Unused21: 'Null',2785      __Unused22: 'Null',2786      __Unused23: 'Null',2787      __Unused24: 'Null',2788      __Unused25: 'Null',2789      __Unused26: 'Null',2790      __Unused27: 'Null',2791      __Unused28: 'Null',2792      __Unused29: 'Null',2793      __Unused30: 'Null',2794      __Unused31: 'Null',2795      __Unused32: 'Null',2796      __Unused33: 'Null',2797      __Unused34: 'Null',2798      __Unused35: 'Null',2799      __Unused36: 'Null',2800      __Unused37: 'Null',2801      __Unused38: 'Null',2802      __Unused39: 'Null',2803      __Unused40: 'Null',2804      __Unused41: 'Null',2805      __Unused42: 'Null',2806      __Unused43: 'Null',2807      __Unused44: 'Null',2808      __Unused45: 'Null',2809      __Unused46: 'Null',2810      __Unused47: 'Null',2811      __Unused48: 'Null',2812      __Unused49: 'Null',2813      __Unused50: 'Null',2814      PolkadotXcm: 'PalletXcmOrigin',2815      CumulusXcm: 'CumulusPalletXcmOrigin',2816      __Unused53: 'Null',2817      __Unused54: 'Null',2818      __Unused55: 'Null',2819      __Unused56: 'Null',2820      __Unused57: 'Null',2821      __Unused58: 'Null',2822      __Unused59: 'Null',2823      __Unused60: 'Null',2824      __Unused61: 'Null',2825      __Unused62: 'Null',2826      __Unused63: 'Null',2827      __Unused64: 'Null',2828      __Unused65: 'Null',2829      __Unused66: 'Null',2830      __Unused67: 'Null',2831      __Unused68: 'Null',2832      __Unused69: 'Null',2833      __Unused70: 'Null',2834      __Unused71: 'Null',2835      __Unused72: 'Null',2836      __Unused73: 'Null',2837      __Unused74: 'Null',2838      __Unused75: 'Null',2839      __Unused76: 'Null',2840      __Unused77: 'Null',2841      __Unused78: 'Null',2842      __Unused79: 'Null',2843      __Unused80: 'Null',2844      __Unused81: 'Null',2845      __Unused82: 'Null',2846      __Unused83: 'Null',2847      __Unused84: 'Null',2848      __Unused85: 'Null',2849      __Unused86: 'Null',2850      __Unused87: 'Null',2851      __Unused88: 'Null',2852      __Unused89: 'Null',2853      __Unused90: 'Null',2854      __Unused91: 'Null',2855      __Unused92: 'Null',2856      __Unused93: 'Null',2857      __Unused94: 'Null',2858      __Unused95: 'Null',2859      __Unused96: 'Null',2860      __Unused97: 'Null',2861      __Unused98: 'Null',2862      __Unused99: 'Null',2863      __Unused100: 'Null',2864      Ethereum: 'PalletEthereumRawOrigin'2865    }2866  },2867  /**2868   * Lookup356: frame_support::dispatch::RawOrigin<sp_core::crypto::AccountId32>2869   **/2870  FrameSupportDispatchRawOrigin: {2871    _enum: {2872      Root: 'Null',2873      Signed: 'AccountId32',2874      None: 'Null'2875    }2876  },2877  /**2878   * Lookup357: pallet_xcm::pallet::Origin2879   **/2880  PalletXcmOrigin: {2881    _enum: {2882      Xcm: 'XcmV1MultiLocation',2883      Response: 'XcmV1MultiLocation'2884    }2885  },2886  /**2887   * Lookup358: cumulus_pallet_xcm::pallet::Origin2888   **/2889  CumulusPalletXcmOrigin: {2890    _enum: {2891      Relay: 'Null',2892      SiblingParachain: 'u32'2893    }2894  },2895  /**2896   * Lookup359: pallet_ethereum::RawOrigin2897   **/2898  PalletEthereumRawOrigin: {2899    _enum: {2900      EthereumTransaction: 'H160'2901    }2902  },2903  /**2904   * Lookup360: sp_core::Void2905   **/2906  SpCoreVoid: 'Null',2907  /**2908   * Lookup361: pallet_unique_scheduler::pallet::Error<T>2909   **/2910  PalletUniqueSchedulerError: {2911    _enum: ['FailedToSchedule', 'NotFound', 'TargetBlockNumberInPast', 'RescheduleNoChange']2912  },2913  /**2914   * Lookup362: up_data_structs::Collection<sp_core::crypto::AccountId32>2915   **/2916  UpDataStructsCollection: {2917    owner: 'AccountId32',2918    mode: 'UpDataStructsCollectionMode',2919    name: 'Vec<u16>',2920    description: 'Vec<u16>',2921    tokenPrefix: 'Bytes',2922    sponsorship: 'UpDataStructsSponsorshipStateAccountId32',2923    limits: 'UpDataStructsCollectionLimits',2924    permissions: 'UpDataStructsCollectionPermissions',2925    externalCollection: 'bool'2926  },2927  /**2928   * Lookup363: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>2929   **/2930  UpDataStructsSponsorshipStateAccountId32: {2931    _enum: {2932      Disabled: 'Null',2933      Unconfirmed: 'AccountId32',2934      Confirmed: 'AccountId32'2935    }2936  },2937  /**2938   * Lookup364: up_data_structs::Properties2939   **/2940  UpDataStructsProperties: {2941    map: 'UpDataStructsPropertiesMapBoundedVec',2942    consumedSpace: 'u32',2943    spaceLimit: 'u32'2944  },2945  /**2946   * Lookup365: up_data_structs::PropertiesMap<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>2947   **/2948  UpDataStructsPropertiesMapBoundedVec: 'BTreeMap<Bytes, Bytes>',2949  /**2950   * Lookup370: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>2951   **/2952  UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap<Bytes, UpDataStructsPropertyPermission>',2953  /**2954   * Lookup377: up_data_structs::CollectionStats2955   **/2956  UpDataStructsCollectionStats: {2957    created: 'u32',2958    destroyed: 'u32',2959    alive: 'u32'2960  },2961  /**2962   * Lookup378: up_data_structs::TokenChild2963   **/2964  UpDataStructsTokenChild: {2965    token: 'u32',2966    collection: 'u32'2967  },2968  /**2969   * Lookup379: PhantomType::up_data_structs<T>2970   **/2971  PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild);0]',2972  /**2973   * Lookup381: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2974   **/2975  UpDataStructsTokenData: {2976    properties: 'Vec<UpDataStructsProperty>',2977    owner: 'Option<PalletEvmAccountBasicCrossAccountIdRepr>',2978    pieces: 'u128'2979  },2980  /**2981   * Lookup383: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>2982   **/2983  UpDataStructsRpcCollection: {2984    owner: 'AccountId32',2985    mode: 'UpDataStructsCollectionMode',2986    name: 'Vec<u16>',2987    description: 'Vec<u16>',2988    tokenPrefix: 'Bytes',2989    sponsorship: 'UpDataStructsSponsorshipStateAccountId32',2990    limits: 'UpDataStructsCollectionLimits',2991    permissions: 'UpDataStructsCollectionPermissions',2992    tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',2993    properties: 'Vec<UpDataStructsProperty>',2994    readOnly: 'bool'2995  },2996  /**2997   * Lookup384: rmrk_traits::collection::CollectionInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>2998   **/2999  RmrkTraitsCollectionCollectionInfo: {3000    issuer: 'AccountId32',3001    metadata: 'Bytes',3002    max: 'Option<u32>',3003    symbol: 'Bytes',3004    nftsCount: 'u32'3005  },3006  /**3007   * Lookup385: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>3008   **/3009  RmrkTraitsNftNftInfo: {3010    owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',3011    royalty: 'Option<RmrkTraitsNftRoyaltyInfo>',3012    metadata: 'Bytes',3013    equipped: 'bool',3014    pending: 'bool'3015  },3016  /**3017   * Lookup387: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>3018   **/3019  RmrkTraitsNftRoyaltyInfo: {3020    recipient: 'AccountId32',3021    amount: 'Permill'3022  },3023  /**3024   * Lookup388: rmrk_traits::resource::ResourceInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>3025   **/3026  RmrkTraitsResourceResourceInfo: {3027    id: 'u32',3028    resource: 'RmrkTraitsResourceResourceTypes',3029    pending: 'bool',3030    pendingRemoval: 'bool'3031  },3032  /**3033   * Lookup389: rmrk_traits::property::PropertyInfo<sp_runtime::bounded::bounded_vec::BoundedVec<T, S>, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>3034   **/3035  RmrkTraitsPropertyPropertyInfo: {3036    key: 'Bytes',3037    value: 'Bytes'3038  },3039  /**3040   * Lookup390: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, sp_runtime::bounded::bounded_vec::BoundedVec<T, S>>3041   **/3042  RmrkTraitsBaseBaseInfo: {3043    issuer: 'AccountId32',3044    baseType: 'Bytes',3045    symbol: 'Bytes'3046  },3047  /**3048   * Lookup391: rmrk_traits::nft::NftChild3049   **/3050  RmrkTraitsNftNftChild: {3051    collectionId: 'u32',3052    nftId: 'u32'3053  },3054  /**3055   * Lookup393: pallet_common::pallet::Error<T>3056   **/3057  PalletCommonError: {3058    _enum: ['CollectionNotFound', 'MustBeTokenOwner', 'NoPermission', 'CantDestroyNotEmptyCollection', 'PublicMintingNotAllowed', 'AddressNotInAllowlist', 'CollectionNameLimitExceeded', 'CollectionDescriptionLimitExceeded', 'CollectionTokenPrefixLimitExceeded', 'TotalCollectionsLimitExceeded', 'CollectionAdminCountExceeded', 'CollectionLimitBoundsExceeded', 'OwnerPermissionsCantBeReverted', 'TransferNotAllowed', 'AccountTokenLimitExceeded', 'CollectionTokenLimitExceeded', 'MetadataFlagFrozen', 'TokenNotFound', 'TokenValueTooLow', 'ApprovedValueTooLow', 'CantApproveMoreThanOwned', 'AddressIsZero', 'UnsupportedOperation', 'NotSufficientFounds', 'UserIsNotAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'PropertyKeyIsTooLong', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey', 'CollectionIsExternal', 'CollectionIsInternal']3059  },3060  /**3061   * Lookup395: pallet_fungible::pallet::Error<T>3062   **/3063  PalletFungibleError: {3064    _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed']3065  },3066  /**3067   * Lookup396: pallet_refungible::ItemData3068   **/3069  PalletRefungibleItemData: {3070    constData: 'Bytes'3071  },3072  /**3073   * Lookup401: pallet_refungible::pallet::Error<T>3074   **/3075  PalletRefungibleError: {3076    _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed']3077  },3078  /**3079   * Lookup402: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>3080   **/3081  PalletNonfungibleItemData: {3082    owner: 'PalletEvmAccountBasicCrossAccountIdRepr'3083  },3084  /**3085   * Lookup404: up_data_structs::PropertyScope3086   **/3087  UpDataStructsPropertyScope: {3088    _enum: ['None', 'Rmrk']3089  },3090  /**3091   * Lookup406: pallet_nonfungible::pallet::Error<T>3092   **/3093  PalletNonfungibleError: {3094    _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren']3095  },3096  /**3097   * Lookup407: pallet_structure::pallet::Error<T>3098   **/3099  PalletStructureError: {3100    _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound']3101  },3102  /**3103   * Lookup408: pallet_rmrk_core::pallet::Error<T>3104   **/3105  PalletRmrkCoreError: {3106    _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId']3107  },3108  /**3109   * Lookup410: pallet_rmrk_equip::pallet::Error<T>3110   **/3111  PalletRmrkEquipError: {3112    _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart']3113  },3114  /**3115   * Lookup416: pallet_app_promotion::pallet::Error<T>3116   **/3117  PalletAppPromotionError: {3118    _enum: ['AdminNotSet', 'NoPermission', 'NotSufficientFunds', 'PendingForBlockOverflow', 'SponsorNotSet', 'IncorrectLockedBalanceOperation']3119  },3120  /**3121   * Lookup419: pallet_evm::pallet::Error<T>3122   **/3123  PalletEvmError: {3124    _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce']3125  },3126  /**3127   * Lookup422: fp_rpc::TransactionStatus3128   **/3129  FpRpcTransactionStatus: {3130    transactionHash: 'H256',3131    transactionIndex: 'u32',3132    from: 'H160',3133    to: 'Option<H160>',3134    contractAddress: 'Option<H160>',3135    logs: 'Vec<EthereumLog>',3136    logsBloom: 'EthbloomBloom'3137  },3138  /**3139   * Lookup424: ethbloom::Bloom3140   **/3141  EthbloomBloom: '[u8;256]',3142  /**3143   * Lookup426: ethereum::receipt::ReceiptV33144   **/3145  EthereumReceiptReceiptV3: {3146    _enum: {3147      Legacy: 'EthereumReceiptEip658ReceiptData',3148      EIP2930: 'EthereumReceiptEip658ReceiptData',3149      EIP1559: 'EthereumReceiptEip658ReceiptData'3150    }3151  },3152  /**3153   * Lookup427: ethereum::receipt::EIP658ReceiptData3154   **/3155  EthereumReceiptEip658ReceiptData: {3156    statusCode: 'u8',3157    usedGas: 'U256',3158    logsBloom: 'EthbloomBloom',3159    logs: 'Vec<EthereumLog>'3160  },3161  /**3162   * Lookup428: ethereum::block::Block<ethereum::transaction::TransactionV2>3163   **/3164  EthereumBlock: {3165    header: 'EthereumHeader',3166    transactions: 'Vec<EthereumTransactionTransactionV2>',3167    ommers: 'Vec<EthereumHeader>'3168  },3169  /**3170   * Lookup429: ethereum::header::Header3171   **/3172  EthereumHeader: {3173    parentHash: 'H256',3174    ommersHash: 'H256',3175    beneficiary: 'H160',3176    stateRoot: 'H256',3177    transactionsRoot: 'H256',3178    receiptsRoot: 'H256',3179    logsBloom: 'EthbloomBloom',3180    difficulty: 'U256',3181    number: 'U256',3182    gasLimit: 'U256',3183    gasUsed: 'U256',3184    timestamp: 'u64',3185    extraData: 'Bytes',3186    mixHash: 'H256',3187    nonce: 'EthereumTypesHashH64'3188  },3189  /**3190   * Lookup430: ethereum_types::hash::H643191   **/3192  EthereumTypesHashH64: '[u8;8]',3193  /**3194   * Lookup435: pallet_ethereum::pallet::Error<T>3195   **/3196  PalletEthereumError: {3197    _enum: ['InvalidSignature', 'PreLogExists']3198  },3199  /**3200   * Lookup436: pallet_evm_coder_substrate::pallet::Error<T>3201   **/3202  PalletEvmCoderSubstrateError: {3203    _enum: ['OutOfGas', 'OutOfFund']3204  },3205  /**3206   * Lookup437: up_data_structs::SponsorshipState<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>3207   **/3208  UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: {3209    _enum: {3210      Disabled: 'Null',3211      Unconfirmed: 'PalletEvmAccountBasicCrossAccountIdRepr',3212      Confirmed: 'PalletEvmAccountBasicCrossAccountIdRepr'3213    }3214  },3215  /**3216   * Lookup438: pallet_evm_contract_helpers::SponsoringModeT3217   **/3218  PalletEvmContractHelpersSponsoringModeT: {3219    _enum: ['Disabled', 'Allowlisted', 'Generous']3220  },3221  /**3222   * Lookup440: pallet_evm_contract_helpers::pallet::Error<T>3223   **/3224  PalletEvmContractHelpersError: {3225    _enum: ['NoPermission', 'NoPendingSponsor']3226  },3227  /**3228   * Lookup441: pallet_evm_migration::pallet::Error<T>3229   **/3230  PalletEvmMigrationError: {3231    _enum: ['AccountNotEmpty', 'AccountIsNotMigrating']3232  },3233  /**3234   * Lookup443: sp_runtime::MultiSignature3235   **/3236  SpRuntimeMultiSignature: {3237    _enum: {3238      Ed25519: 'SpCoreEd25519Signature',3239      Sr25519: 'SpCoreSr25519Signature',3240      Ecdsa: 'SpCoreEcdsaSignature'3241    }3242  },3243  /**3244   * Lookup444: sp_core::ed25519::Signature3245   **/3246  SpCoreEd25519Signature: '[u8;64]',3247  /**3248   * Lookup446: sp_core::sr25519::Signature3249   **/3250  SpCoreSr25519Signature: '[u8;64]',3251  /**3252   * Lookup447: sp_core::ecdsa::Signature3253   **/3254  SpCoreEcdsaSignature: '[u8;65]',3255  /**3256   * Lookup450: frame_system::extensions::check_spec_version::CheckSpecVersion<T>3257   **/3258  FrameSystemExtensionsCheckSpecVersion: 'Null',3259  /**3260   * Lookup451: frame_system::extensions::check_genesis::CheckGenesis<T>3261   **/3262  FrameSystemExtensionsCheckGenesis: 'Null',3263  /**3264   * Lookup454: frame_system::extensions::check_nonce::CheckNonce<T>3265   **/3266  FrameSystemExtensionsCheckNonce: 'Compact<u32>',3267  /**3268   * Lookup455: frame_system::extensions::check_weight::CheckWeight<T>3269   **/3270  FrameSystemExtensionsCheckWeight: 'Null',3271  /**3272   * Lookup456: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>3273   **/3274  PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact<u128>',3275  /**3276   * Lookup457: opal_runtime::Runtime3277   **/3278  OpalRuntimeRuntime: 'Null',3279  /**3280   * Lookup458: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>3281   **/3282  PalletEthereumFakeTransactionFinalizer: 'Null'3283};
modifiedtests/src/interfaces/registry.tsdiffbeforeafterboth
--- a/tests/src/interfaces/registry.ts
+++ b/tests/src/interfaces/registry.ts
@@ -5,7 +5,7 @@
 // this is required to allow for ambient/previous definitions
 import '@polkadot/types/types/registry';
 
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
 
 declare module '@polkadot/types/types/registry' {
   interface InterfaceTypes {
@@ -83,6 +83,9 @@
     OrmlVestingModuleError: OrmlVestingModuleError;
     OrmlVestingModuleEvent: OrmlVestingModuleEvent;
     OrmlVestingVestingSchedule: OrmlVestingVestingSchedule;
+    PalletAppPromotionCall: PalletAppPromotionCall;
+    PalletAppPromotionError: PalletAppPromotionError;
+    PalletAppPromotionEvent: PalletAppPromotionEvent;
     PalletBalancesAccountData: PalletBalancesAccountData;
     PalletBalancesBalanceLock: PalletBalancesBalanceLock;
     PalletBalancesCall: PalletBalancesCall;
@@ -103,6 +106,7 @@
     PalletEvmCall: PalletEvmCall;
     PalletEvmCoderSubstrateError: PalletEvmCoderSubstrateError;
     PalletEvmContractHelpersError: PalletEvmContractHelpersError;
+    PalletEvmContractHelpersEvent: PalletEvmContractHelpersEvent;
     PalletEvmContractHelpersSponsoringModeT: PalletEvmContractHelpersSponsoringModeT;
     PalletEvmError: PalletEvmError;
     PalletEvmEvent: PalletEvmEvent;
@@ -213,7 +217,8 @@
     UpDataStructsPropertyScope: UpDataStructsPropertyScope;
     UpDataStructsRpcCollection: UpDataStructsRpcCollection;
     UpDataStructsSponsoringRateLimit: UpDataStructsSponsoringRateLimit;
-    UpDataStructsSponsorshipState: UpDataStructsSponsorshipState;
+    UpDataStructsSponsorshipStateAccountId32: UpDataStructsSponsorshipStateAccountId32;
+    UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: UpDataStructsSponsorshipStateBasicCrossAccountIdRepr;
     UpDataStructsTokenChild: UpDataStructsTokenChild;
     UpDataStructsTokenData: UpDataStructsTokenData;
     XcmDoubleEncoded: XcmDoubleEncoded;
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -1198,7 +1198,20 @@
     readonly type: 'BaseCreated' | 'EquippablesUpdated';
   }
 
-  /** @name PalletEvmEvent (103) */
+  /** @name PalletAppPromotionEvent (103) */
+  interface PalletAppPromotionEvent extends Enum {
+    readonly isStakingRecalculation: boolean;
+    readonly asStakingRecalculation: ITuple<[AccountId32, u128, u128]>;
+    readonly isStake: boolean;
+    readonly asStake: ITuple<[AccountId32, u128]>;
+    readonly isUnstake: boolean;
+    readonly asUnstake: ITuple<[AccountId32, u128]>;
+    readonly isSetAdmin: boolean;
+    readonly asSetAdmin: AccountId32;
+    readonly type: 'StakingRecalculation' | 'Stake' | 'Unstake' | 'SetAdmin';
+  }
+
+  /** @name PalletEvmEvent (104) */
   interface PalletEvmEvent extends Enum {
     readonly isLog: boolean;
     readonly asLog: EthereumLog;
@@ -1217,21 +1230,21 @@
     readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed' | 'BalanceDeposit' | 'BalanceWithdraw';
   }
 
-  /** @name EthereumLog (104) */
+  /** @name EthereumLog (105) */
   interface EthereumLog extends Struct {
     readonly address: H160;
     readonly topics: Vec<H256>;
     readonly data: Bytes;
   }
 
-  /** @name PalletEthereumEvent (108) */
+  /** @name PalletEthereumEvent (109) */
   interface PalletEthereumEvent extends Enum {
     readonly isExecuted: boolean;
     readonly asExecuted: ITuple<[H160, H160, H256, EvmCoreErrorExitReason]>;
     readonly type: 'Executed';
   }
 
-  /** @name EvmCoreErrorExitReason (109) */
+  /** @name EvmCoreErrorExitReason (110) */
   interface EvmCoreErrorExitReason extends Enum {
     readonly isSucceed: boolean;
     readonly asSucceed: EvmCoreErrorExitSucceed;
@@ -1244,7 +1257,7 @@
     readonly type: 'Succeed' | 'Error' | 'Revert' | 'Fatal';
   }
 
-  /** @name EvmCoreErrorExitSucceed (110) */
+  /** @name EvmCoreErrorExitSucceed (111) */
   interface EvmCoreErrorExitSucceed extends Enum {
     readonly isStopped: boolean;
     readonly isReturned: boolean;
@@ -1252,7 +1265,7 @@
     readonly type: 'Stopped' | 'Returned' | 'Suicided';
   }
 
-  /** @name EvmCoreErrorExitError (111) */
+  /** @name EvmCoreErrorExitError (112) */
   interface EvmCoreErrorExitError extends Enum {
     readonly isStackUnderflow: boolean;
     readonly isStackOverflow: boolean;
@@ -1273,13 +1286,13 @@
     readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode';
   }
 
-  /** @name EvmCoreErrorExitRevert (114) */
+  /** @name EvmCoreErrorExitRevert (115) */
   interface EvmCoreErrorExitRevert extends Enum {
     readonly isReverted: boolean;
     readonly type: 'Reverted';
   }
 
-  /** @name EvmCoreErrorExitFatal (115) */
+  /** @name EvmCoreErrorExitFatal (116) */
   interface EvmCoreErrorExitFatal extends Enum {
     readonly isNotSupported: boolean;
     readonly isUnhandledInterrupt: boolean;
@@ -1290,7 +1303,18 @@
     readonly type: 'NotSupported' | 'UnhandledInterrupt' | 'CallErrorAsFatal' | 'Other';
   }
 
-  /** @name FrameSystemPhase (116) */
+  /** @name PalletEvmContractHelpersEvent (117) */
+  interface PalletEvmContractHelpersEvent extends Enum {
+    readonly isContractSponsorSet: boolean;
+    readonly asContractSponsorSet: ITuple<[H160, AccountId32]>;
+    readonly isContractSponsorshipConfirmed: boolean;
+    readonly asContractSponsorshipConfirmed: ITuple<[H160, AccountId32]>;
+    readonly isContractSponsorRemoved: boolean;
+    readonly asContractSponsorRemoved: H160;
+    readonly type: 'ContractSponsorSet' | 'ContractSponsorshipConfirmed' | 'ContractSponsorRemoved';
+  }
+
+  /** @name FrameSystemPhase (118) */
   interface FrameSystemPhase extends Enum {
     readonly isApplyExtrinsic: boolean;
     readonly asApplyExtrinsic: u32;
@@ -1299,13 +1323,13 @@
     readonly type: 'ApplyExtrinsic' | 'Finalization' | 'Initialization';
   }
 
-  /** @name FrameSystemLastRuntimeUpgradeInfo (118) */
+  /** @name FrameSystemLastRuntimeUpgradeInfo (120) */
   interface FrameSystemLastRuntimeUpgradeInfo extends Struct {
     readonly specVersion: Compact<u32>;
     readonly specName: Text;
   }
 
-  /** @name FrameSystemCall (119) */
+  /** @name FrameSystemCall (121) */
   interface FrameSystemCall extends Enum {
     readonly isFillBlock: boolean;
     readonly asFillBlock: {
@@ -1347,21 +1371,21 @@
     readonly type: 'FillBlock' | 'Remark' | 'SetHeapPages' | 'SetCode' | 'SetCodeWithoutChecks' | 'SetStorage' | 'KillStorage' | 'KillPrefix' | 'RemarkWithEvent';
   }
 
-  /** @name FrameSystemLimitsBlockWeights (124) */
+  /** @name FrameSystemLimitsBlockWeights (126) */
   interface FrameSystemLimitsBlockWeights extends Struct {
     readonly baseBlock: u64;
     readonly maxBlock: u64;
     readonly perClass: FrameSupportWeightsPerDispatchClassWeightsPerClass;
   }
 
-  /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (125) */
+  /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (127) */
   interface FrameSupportWeightsPerDispatchClassWeightsPerClass extends Struct {
     readonly normal: FrameSystemLimitsWeightsPerClass;
     readonly operational: FrameSystemLimitsWeightsPerClass;
     readonly mandatory: FrameSystemLimitsWeightsPerClass;
   }
 
-  /** @name FrameSystemLimitsWeightsPerClass (126) */
+  /** @name FrameSystemLimitsWeightsPerClass (128) */
   interface FrameSystemLimitsWeightsPerClass extends Struct {
     readonly baseExtrinsic: u64;
     readonly maxExtrinsic: Option<u64>;
@@ -1369,25 +1393,25 @@
     readonly reserved: Option<u64>;
   }
 
-  /** @name FrameSystemLimitsBlockLength (128) */
+  /** @name FrameSystemLimitsBlockLength (130) */
   interface FrameSystemLimitsBlockLength extends Struct {
     readonly max: FrameSupportWeightsPerDispatchClassU32;
   }
 
-  /** @name FrameSupportWeightsPerDispatchClassU32 (129) */
+  /** @name FrameSupportWeightsPerDispatchClassU32 (131) */
   interface FrameSupportWeightsPerDispatchClassU32 extends Struct {
     readonly normal: u32;
     readonly operational: u32;
     readonly mandatory: u32;
   }
 
-  /** @name FrameSupportWeightsRuntimeDbWeight (130) */
+  /** @name FrameSupportWeightsRuntimeDbWeight (132) */
   interface FrameSupportWeightsRuntimeDbWeight extends Struct {
     readonly read: u64;
     readonly write: u64;
   }
 
-  /** @name SpVersionRuntimeVersion (131) */
+  /** @name SpVersionRuntimeVersion (133) */
   interface SpVersionRuntimeVersion extends Struct {
     readonly specName: Text;
     readonly implName: Text;
@@ -1399,7 +1423,7 @@
     readonly stateVersion: u8;
   }
 
-  /** @name FrameSystemError (136) */
+  /** @name FrameSystemError (138) */
   interface FrameSystemError extends Enum {
     readonly isInvalidSpecName: boolean;
     readonly isSpecVersionNeedsToIncrease: boolean;
@@ -1410,7 +1434,7 @@
     readonly type: 'InvalidSpecName' | 'SpecVersionNeedsToIncrease' | 'FailedToExtractRuntimeVersion' | 'NonDefaultComposite' | 'NonZeroRefCount' | 'CallFiltered';
   }
 
-  /** @name PolkadotPrimitivesV2PersistedValidationData (137) */
+  /** @name PolkadotPrimitivesV2PersistedValidationData (139) */
   interface PolkadotPrimitivesV2PersistedValidationData extends Struct {
     readonly parentHead: Bytes;
     readonly relayParentNumber: u32;
@@ -1418,18 +1442,18 @@
     readonly maxPovSize: u32;
   }
 
-  /** @name PolkadotPrimitivesV2UpgradeRestriction (140) */
+  /** @name PolkadotPrimitivesV2UpgradeRestriction (142) */
   interface PolkadotPrimitivesV2UpgradeRestriction extends Enum {
     readonly isPresent: boolean;
     readonly type: 'Present';
   }
 
-  /** @name SpTrieStorageProof (141) */
+  /** @name SpTrieStorageProof (143) */
   interface SpTrieStorageProof extends Struct {
     readonly trieNodes: BTreeSet<Bytes>;
   }
 
-  /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (143) */
+  /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (145) */
   interface CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot extends Struct {
     readonly dmqMqcHead: H256;
     readonly relayDispatchQueueSize: ITuple<[u32, u32]>;
@@ -1437,7 +1461,7 @@
     readonly egressChannels: Vec<ITuple<[u32, PolkadotPrimitivesV2AbridgedHrmpChannel]>>;
   }
 
-  /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (146) */
+  /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (148) */
   interface PolkadotPrimitivesV2AbridgedHrmpChannel extends Struct {
     readonly maxCapacity: u32;
     readonly maxTotalSize: u32;
@@ -1447,7 +1471,7 @@
     readonly mqcHead: Option<H256>;
   }
 
-  /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (147) */
+  /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (149) */
   interface PolkadotPrimitivesV2AbridgedHostConfiguration extends Struct {
     readonly maxCodeSize: u32;
     readonly maxHeadDataSize: u32;
@@ -1460,13 +1484,13 @@
     readonly validationUpgradeDelay: u32;
   }
 
-  /** @name PolkadotCorePrimitivesOutboundHrmpMessage (153) */
+  /** @name PolkadotCorePrimitivesOutboundHrmpMessage (155) */
   interface PolkadotCorePrimitivesOutboundHrmpMessage extends Struct {
     readonly recipient: u32;
     readonly data: Bytes;
   }
 
-  /** @name CumulusPalletParachainSystemCall (154) */
+  /** @name CumulusPalletParachainSystemCall (156) */
   interface CumulusPalletParachainSystemCall extends Enum {
     readonly isSetValidationData: boolean;
     readonly asSetValidationData: {
@@ -1487,7 +1511,7 @@
     readonly type: 'SetValidationData' | 'SudoSendUpwardMessage' | 'AuthorizeUpgrade' | 'EnactAuthorizedUpgrade';
   }
 
-  /** @name CumulusPrimitivesParachainInherentParachainInherentData (155) */
+  /** @name CumulusPrimitivesParachainInherentParachainInherentData (157) */
   interface CumulusPrimitivesParachainInherentParachainInherentData extends Struct {
     readonly validationData: PolkadotPrimitivesV2PersistedValidationData;
     readonly relayChainState: SpTrieStorageProof;
@@ -1495,19 +1519,19 @@
     readonly horizontalMessages: BTreeMap<u32, Vec<PolkadotCorePrimitivesInboundHrmpMessage>>;
   }
 
-  /** @name PolkadotCorePrimitivesInboundDownwardMessage (157) */
+  /** @name PolkadotCorePrimitivesInboundDownwardMessage (159) */
   interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct {
     readonly sentAt: u32;
     readonly msg: Bytes;
   }
 
-  /** @name PolkadotCorePrimitivesInboundHrmpMessage (160) */
+  /** @name PolkadotCorePrimitivesInboundHrmpMessage (162) */
   interface PolkadotCorePrimitivesInboundHrmpMessage extends Struct {
     readonly sentAt: u32;
     readonly data: Bytes;
   }
 
-  /** @name CumulusPalletParachainSystemError (163) */
+  /** @name CumulusPalletParachainSystemError (165) */
   interface CumulusPalletParachainSystemError extends Enum {
     readonly isOverlappingUpgrades: boolean;
     readonly isProhibitedByPolkadot: boolean;
@@ -1520,14 +1544,14 @@
     readonly type: 'OverlappingUpgrades' | 'ProhibitedByPolkadot' | 'TooBig' | 'ValidationDataNotAvailable' | 'HostConfigurationNotAvailable' | 'NotScheduled' | 'NothingAuthorized' | 'Unauthorized';
   }
 
-  /** @name PalletBalancesBalanceLock (165) */
+  /** @name PalletBalancesBalanceLock (167) */
   interface PalletBalancesBalanceLock extends Struct {
     readonly id: U8aFixed;
     readonly amount: u128;
     readonly reasons: PalletBalancesReasons;
   }
 
-  /** @name PalletBalancesReasons (166) */
+  /** @name PalletBalancesReasons (168) */
   interface PalletBalancesReasons extends Enum {
     readonly isFee: boolean;
     readonly isMisc: boolean;
@@ -1535,20 +1559,20 @@
     readonly type: 'Fee' | 'Misc' | 'All';
   }
 
-  /** @name PalletBalancesReserveData (169) */
+  /** @name PalletBalancesReserveData (171) */
   interface PalletBalancesReserveData extends Struct {
     readonly id: U8aFixed;
     readonly amount: u128;
   }
 
-  /** @name PalletBalancesReleases (171) */
+  /** @name PalletBalancesReleases (173) */
   interface PalletBalancesReleases extends Enum {
     readonly isV100: boolean;
     readonly isV200: boolean;
     readonly type: 'V100' | 'V200';
   }
 
-  /** @name PalletBalancesCall (172) */
+  /** @name PalletBalancesCall (174) */
   interface PalletBalancesCall extends Enum {
     readonly isTransfer: boolean;
     readonly asTransfer: {
@@ -1585,7 +1609,7 @@
     readonly type: 'Transfer' | 'SetBalance' | 'ForceTransfer' | 'TransferKeepAlive' | 'TransferAll' | 'ForceUnreserve';
   }
 
-  /** @name PalletBalancesError (175) */
+  /** @name PalletBalancesError (177) */
   interface PalletBalancesError extends Enum {
     readonly isVestingBalance: boolean;
     readonly isLiquidityRestrictions: boolean;
@@ -1598,7 +1622,7 @@
     readonly type: 'VestingBalance' | 'LiquidityRestrictions' | 'InsufficientBalance' | 'ExistentialDeposit' | 'KeepAlive' | 'ExistingVestingSchedule' | 'DeadAccount' | 'TooManyReserves';
   }
 
-  /** @name PalletTimestampCall (177) */
+  /** @name PalletTimestampCall (179) */
   interface PalletTimestampCall extends Enum {
     readonly isSet: boolean;
     readonly asSet: {
@@ -1607,14 +1631,14 @@
     readonly type: 'Set';
   }
 
-  /** @name PalletTransactionPaymentReleases (179) */
+  /** @name PalletTransactionPaymentReleases (181) */
   interface PalletTransactionPaymentReleases extends Enum {
     readonly isV1Ancient: boolean;
     readonly isV2: boolean;
     readonly type: 'V1Ancient' | 'V2';
   }
 
-  /** @name PalletTreasuryProposal (180) */
+  /** @name PalletTreasuryProposal (182) */
   interface PalletTreasuryProposal extends Struct {
     readonly proposer: AccountId32;
     readonly value: u128;
@@ -1622,7 +1646,7 @@
     readonly bond: u128;
   }
 
-  /** @name PalletTreasuryCall (183) */
+  /** @name PalletTreasuryCall (185) */
   interface PalletTreasuryCall extends Enum {
     readonly isProposeSpend: boolean;
     readonly asProposeSpend: {
@@ -1649,10 +1673,10 @@
     readonly type: 'ProposeSpend' | 'RejectProposal' | 'ApproveProposal' | 'Spend' | 'RemoveApproval';
   }
 
-  /** @name FrameSupportPalletId (186) */
+  /** @name FrameSupportPalletId (188) */
   interface FrameSupportPalletId extends U8aFixed {}
 
-  /** @name PalletTreasuryError (187) */
+  /** @name PalletTreasuryError (189) */
   interface PalletTreasuryError extends Enum {
     readonly isInsufficientProposersBalance: boolean;
     readonly isInvalidIndex: boolean;
@@ -1662,7 +1686,7 @@
     readonly type: 'InsufficientProposersBalance' | 'InvalidIndex' | 'TooManyApprovals' | 'InsufficientPermission' | 'ProposalNotApproved';
   }
 
-  /** @name PalletSudoCall (188) */
+  /** @name PalletSudoCall (190) */
   interface PalletSudoCall extends Enum {
     readonly isSudo: boolean;
     readonly asSudo: {
@@ -1685,7 +1709,7 @@
     readonly type: 'Sudo' | 'SudoUncheckedWeight' | 'SetKey' | 'SudoAs';
   }
 
-  /** @name OrmlVestingModuleCall (190) */
+  /** @name OrmlVestingModuleCall (192) */
   interface OrmlVestingModuleCall extends Enum {
     readonly isClaim: boolean;
     readonly isVestedTransfer: boolean;
@@ -1705,7 +1729,7 @@
     readonly type: 'Claim' | 'VestedTransfer' | 'UpdateVestingSchedules' | 'ClaimFor';
   }
 
-  /** @name CumulusPalletXcmpQueueCall (192) */
+  /** @name CumulusPalletXcmpQueueCall (194) */
   interface CumulusPalletXcmpQueueCall extends Enum {
     readonly isServiceOverweight: boolean;
     readonly asServiceOverweight: {
@@ -1741,7 +1765,7 @@
     readonly type: 'ServiceOverweight' | 'SuspendXcmExecution' | 'ResumeXcmExecution' | 'UpdateSuspendThreshold' | 'UpdateDropThreshold' | 'UpdateResumeThreshold' | 'UpdateThresholdWeight' | 'UpdateWeightRestrictDecay' | 'UpdateXcmpMaxIndividualWeight';
   }
 
-  /** @name PalletXcmCall (193) */
+  /** @name PalletXcmCall (195) */
   interface PalletXcmCall extends Enum {
     readonly isSend: boolean;
     readonly asSend: {
@@ -1803,7 +1827,7 @@
     readonly type: 'Send' | 'TeleportAssets' | 'ReserveTransferAssets' | 'Execute' | 'ForceXcmVersion' | 'ForceDefaultXcmVersion' | 'ForceSubscribeVersionNotify' | 'ForceUnsubscribeVersionNotify' | 'LimitedReserveTransferAssets' | 'LimitedTeleportAssets';
   }
 
-  /** @name XcmVersionedXcm (194) */
+  /** @name XcmVersionedXcm (196) */
   interface XcmVersionedXcm extends Enum {
     readonly isV0: boolean;
     readonly asV0: XcmV0Xcm;
@@ -1814,7 +1838,7 @@
     readonly type: 'V0' | 'V1' | 'V2';
   }
 
-  /** @name XcmV0Xcm (195) */
+  /** @name XcmV0Xcm (197) */
   interface XcmV0Xcm extends Enum {
     readonly isWithdrawAsset: boolean;
     readonly asWithdrawAsset: {
@@ -1877,7 +1901,7 @@
     readonly type: 'WithdrawAsset' | 'ReserveAssetDeposit' | 'TeleportAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom';
   }
 
-  /** @name XcmV0Order (197) */
+  /** @name XcmV0Order (199) */
   interface XcmV0Order extends Enum {
     readonly isNull: boolean;
     readonly isDepositAsset: boolean;
@@ -1925,14 +1949,14 @@
     readonly type: 'Null' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution';
   }
 
-  /** @name XcmV0Response (199) */
+  /** @name XcmV0Response (201) */
   interface XcmV0Response extends Enum {
     readonly isAssets: boolean;
     readonly asAssets: Vec<XcmV0MultiAsset>;
     readonly type: 'Assets';
   }
 
-  /** @name XcmV1Xcm (200) */
+  /** @name XcmV1Xcm (202) */
   interface XcmV1Xcm extends Enum {
     readonly isWithdrawAsset: boolean;
     readonly asWithdrawAsset: {
@@ -2001,7 +2025,7 @@
     readonly type: 'WithdrawAsset' | 'ReserveAssetDeposited' | 'ReceiveTeleportedAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom' | 'SubscribeVersion' | 'UnsubscribeVersion';
   }
 
-  /** @name XcmV1Order (202) */
+  /** @name XcmV1Order (204) */
   interface XcmV1Order extends Enum {
     readonly isNoop: boolean;
     readonly isDepositAsset: boolean;
@@ -2051,7 +2075,7 @@
     readonly type: 'Noop' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution';
   }
 
-  /** @name XcmV1Response (204) */
+  /** @name XcmV1Response (206) */
   interface XcmV1Response extends Enum {
     readonly isAssets: boolean;
     readonly asAssets: XcmV1MultiassetMultiAssets;
@@ -2060,10 +2084,10 @@
     readonly type: 'Assets' | 'Version';
   }
 
-  /** @name CumulusPalletXcmCall (218) */
+  /** @name CumulusPalletXcmCall (220) */
   type CumulusPalletXcmCall = Null;
 
-  /** @name CumulusPalletDmpQueueCall (219) */
+  /** @name CumulusPalletDmpQueueCall (221) */
   interface CumulusPalletDmpQueueCall extends Enum {
     readonly isServiceOverweight: boolean;
     readonly asServiceOverweight: {
@@ -2073,7 +2097,7 @@
     readonly type: 'ServiceOverweight';
   }
 
-  /** @name PalletInflationCall (220) */
+  /** @name PalletInflationCall (222) */
   interface PalletInflationCall extends Enum {
     readonly isStartInflation: boolean;
     readonly asStartInflation: {
@@ -2082,7 +2106,7 @@
     readonly type: 'StartInflation';
   }
 
-  /** @name PalletUniqueCall (221) */
+  /** @name PalletUniqueCall (223) */
   interface PalletUniqueCall extends Enum {
     readonly isCreateCollection: boolean;
     readonly asCreateCollection: {
@@ -2240,7 +2264,7 @@
     readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition';
   }
 
-  /** @name UpDataStructsCollectionMode (226) */
+  /** @name UpDataStructsCollectionMode (228) */
   interface UpDataStructsCollectionMode extends Enum {
     readonly isNft: boolean;
     readonly isFungible: boolean;
@@ -2249,7 +2273,7 @@
     readonly type: 'Nft' | 'Fungible' | 'ReFungible';
   }
 
-  /** @name UpDataStructsCreateCollectionData (227) */
+  /** @name UpDataStructsCreateCollectionData (229) */
   interface UpDataStructsCreateCollectionData extends Struct {
     readonly mode: UpDataStructsCollectionMode;
     readonly access: Option<UpDataStructsAccessMode>;
@@ -2263,14 +2287,14 @@
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsAccessMode (229) */
+  /** @name UpDataStructsAccessMode (231) */
   interface UpDataStructsAccessMode extends Enum {
     readonly isNormal: boolean;
     readonly isAllowList: boolean;
     readonly type: 'Normal' | 'AllowList';
   }
 
-  /** @name UpDataStructsCollectionLimits (231) */
+  /** @name UpDataStructsCollectionLimits (233) */
   interface UpDataStructsCollectionLimits extends Struct {
     readonly accountTokenOwnershipLimit: Option<u32>;
     readonly sponsoredDataSize: Option<u32>;
@@ -2283,7 +2307,7 @@
     readonly transfersEnabled: Option<bool>;
   }
 
-  /** @name UpDataStructsSponsoringRateLimit (233) */
+  /** @name UpDataStructsSponsoringRateLimit (235) */
   interface UpDataStructsSponsoringRateLimit extends Enum {
     readonly isSponsoringDisabled: boolean;
     readonly isBlocks: boolean;
@@ -2291,43 +2315,43 @@
     readonly type: 'SponsoringDisabled' | 'Blocks';
   }
 
-  /** @name UpDataStructsCollectionPermissions (236) */
+  /** @name UpDataStructsCollectionPermissions (238) */
   interface UpDataStructsCollectionPermissions extends Struct {
     readonly access: Option<UpDataStructsAccessMode>;
     readonly mintMode: Option<bool>;
     readonly nesting: Option<UpDataStructsNestingPermissions>;
   }
 
-  /** @name UpDataStructsNestingPermissions (238) */
+  /** @name UpDataStructsNestingPermissions (240) */
   interface UpDataStructsNestingPermissions extends Struct {
     readonly tokenOwner: bool;
     readonly collectionAdmin: bool;
     readonly restricted: Option<UpDataStructsOwnerRestrictedSet>;
   }
 
-  /** @name UpDataStructsOwnerRestrictedSet (240) */
+  /** @name UpDataStructsOwnerRestrictedSet (242) */
   interface UpDataStructsOwnerRestrictedSet extends BTreeSet<u32> {}
 
-  /** @name UpDataStructsPropertyKeyPermission (245) */
+  /** @name UpDataStructsPropertyKeyPermission (247) */
   interface UpDataStructsPropertyKeyPermission extends Struct {
     readonly key: Bytes;
     readonly permission: UpDataStructsPropertyPermission;
   }
 
-  /** @name UpDataStructsPropertyPermission (246) */
+  /** @name UpDataStructsPropertyPermission (248) */
   interface UpDataStructsPropertyPermission extends Struct {
     readonly mutable: bool;
     readonly collectionAdmin: bool;
     readonly tokenOwner: bool;
   }
 
-  /** @name UpDataStructsProperty (249) */
+  /** @name UpDataStructsProperty (251) */
   interface UpDataStructsProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name UpDataStructsCreateItemData (252) */
+  /** @name UpDataStructsCreateItemData (254) */
   interface UpDataStructsCreateItemData extends Enum {
     readonly isNft: boolean;
     readonly asNft: UpDataStructsCreateNftData;
@@ -2338,23 +2362,23 @@
     readonly type: 'Nft' | 'Fungible' | 'ReFungible';
   }
 
-  /** @name UpDataStructsCreateNftData (253) */
+  /** @name UpDataStructsCreateNftData (255) */
   interface UpDataStructsCreateNftData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateFungibleData (254) */
+  /** @name UpDataStructsCreateFungibleData (256) */
   interface UpDataStructsCreateFungibleData extends Struct {
     readonly value: u128;
   }
 
-  /** @name UpDataStructsCreateReFungibleData (255) */
+  /** @name UpDataStructsCreateReFungibleData (257) */
   interface UpDataStructsCreateReFungibleData extends Struct {
     readonly pieces: u128;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateItemExData (258) */
+  /** @name UpDataStructsCreateItemExData (260) */
   interface UpDataStructsCreateItemExData extends Enum {
     readonly isNft: boolean;
     readonly asNft: Vec<UpDataStructsCreateNftExData>;
@@ -2367,26 +2391,26 @@
     readonly type: 'Nft' | 'Fungible' | 'RefungibleMultipleItems' | 'RefungibleMultipleOwners';
   }
 
-  /** @name UpDataStructsCreateNftExData (260) */
+  /** @name UpDataStructsCreateNftExData (262) */
   interface UpDataStructsCreateNftExData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name UpDataStructsCreateRefungibleExSingleOwner (267) */
+  /** @name UpDataStructsCreateRefungibleExSingleOwner (269) */
   interface UpDataStructsCreateRefungibleExSingleOwner extends Struct {
     readonly user: PalletEvmAccountBasicCrossAccountIdRepr;
     readonly pieces: u128;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateRefungibleExMultipleOwners (269) */
+  /** @name UpDataStructsCreateRefungibleExMultipleOwners (271) */
   interface UpDataStructsCreateRefungibleExMultipleOwners extends Struct {
     readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name PalletUniqueSchedulerCall (270) */
+  /** @name PalletUniqueSchedulerCall (272) */
   interface PalletUniqueSchedulerCall extends Enum {
     readonly isScheduleNamed: boolean;
     readonly asScheduleNamed: {
@@ -2411,7 +2435,7 @@
     readonly type: 'ScheduleNamed' | 'CancelNamed' | 'ScheduleNamedAfter';
   }
 
-  /** @name FrameSupportScheduleMaybeHashed (272) */
+  /** @name FrameSupportScheduleMaybeHashed (274) */
   interface FrameSupportScheduleMaybeHashed extends Enum {
     readonly isValue: boolean;
     readonly asValue: Call;
@@ -2420,7 +2444,7 @@
     readonly type: 'Value' | 'Hash';
   }
 
-  /** @name PalletConfigurationCall (273) */
+  /** @name PalletConfigurationCall (275) */
   interface PalletConfigurationCall extends Enum {
     readonly isSetWeightToFeeCoefficientOverride: boolean;
     readonly asSetWeightToFeeCoefficientOverride: {
@@ -2433,13 +2457,13 @@
     readonly type: 'SetWeightToFeeCoefficientOverride' | 'SetMinGasPriceOverride';
   }
 
-  /** @name PalletTemplateTransactionPaymentCall (274) */
+  /** @name PalletTemplateTransactionPaymentCall (276) */
   type PalletTemplateTransactionPaymentCall = Null;
 
-  /** @name PalletStructureCall (275) */
+  /** @name PalletStructureCall (277) */
   type PalletStructureCall = Null;
 
-  /** @name PalletRmrkCoreCall (276) */
+  /** @name PalletRmrkCoreCall (278) */
   interface PalletRmrkCoreCall extends Enum {
     readonly isCreateCollection: boolean;
     readonly asCreateCollection: {
@@ -2545,7 +2569,7 @@
     readonly type: 'CreateCollection' | 'DestroyCollection' | 'ChangeCollectionIssuer' | 'LockCollection' | 'MintNft' | 'BurnNft' | 'Send' | 'AcceptNft' | 'RejectNft' | 'AcceptResource' | 'AcceptResourceRemoval' | 'SetProperty' | 'SetPriority' | 'AddBasicResource' | 'AddComposableResource' | 'AddSlotResource' | 'RemoveResource';
   }
 
-  /** @name RmrkTraitsResourceResourceTypes (282) */
+  /** @name RmrkTraitsResourceResourceTypes (284) */
   interface RmrkTraitsResourceResourceTypes extends Enum {
     readonly isBasic: boolean;
     readonly asBasic: RmrkTraitsResourceBasicResource;
@@ -2556,7 +2580,7 @@
     readonly type: 'Basic' | 'Composable' | 'Slot';
   }
 
-  /** @name RmrkTraitsResourceBasicResource (284) */
+  /** @name RmrkTraitsResourceBasicResource (286) */
   interface RmrkTraitsResourceBasicResource extends Struct {
     readonly src: Option<Bytes>;
     readonly metadata: Option<Bytes>;
@@ -2564,7 +2588,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name RmrkTraitsResourceComposableResource (286) */
+  /** @name RmrkTraitsResourceComposableResource (288) */
   interface RmrkTraitsResourceComposableResource extends Struct {
     readonly parts: Vec<u32>;
     readonly base: u32;
@@ -2574,7 +2598,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name RmrkTraitsResourceSlotResource (287) */
+  /** @name RmrkTraitsResourceSlotResource (289) */
   interface RmrkTraitsResourceSlotResource extends Struct {
     readonly base: u32;
     readonly src: Option<Bytes>;
@@ -2584,7 +2608,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name PalletRmrkEquipCall (290) */
+  /** @name PalletRmrkEquipCall (292) */
   interface PalletRmrkEquipCall extends Enum {
     readonly isCreateBase: boolean;
     readonly asCreateBase: {
@@ -2606,7 +2630,7 @@
     readonly type: 'CreateBase' | 'ThemeAdd' | 'Equippable';
   }
 
-  /** @name RmrkTraitsPartPartType (293) */
+  /** @name RmrkTraitsPartPartType (295) */
   interface RmrkTraitsPartPartType extends Enum {
     readonly isFixedPart: boolean;
     readonly asFixedPart: RmrkTraitsPartFixedPart;
@@ -2615,14 +2639,14 @@
     readonly type: 'FixedPart' | 'SlotPart';
   }
 
-  /** @name RmrkTraitsPartFixedPart (295) */
+  /** @name RmrkTraitsPartFixedPart (297) */
   interface RmrkTraitsPartFixedPart extends Struct {
     readonly id: u32;
     readonly z: u32;
     readonly src: Bytes;
   }
 
-  /** @name RmrkTraitsPartSlotPart (296) */
+  /** @name RmrkTraitsPartSlotPart (298) */
   interface RmrkTraitsPartSlotPart extends Struct {
     readonly id: u32;
     readonly equippable: RmrkTraitsPartEquippableList;
@@ -2630,7 +2654,7 @@
     readonly z: u32;
   }
 
-  /** @name RmrkTraitsPartEquippableList (297) */
+  /** @name RmrkTraitsPartEquippableList (299) */
   interface RmrkTraitsPartEquippableList extends Enum {
     readonly isAll: boolean;
     readonly isEmpty: boolean;
@@ -2639,20 +2663,54 @@
     readonly type: 'All' | 'Empty' | 'Custom';
   }
 
-  /** @name RmrkTraitsTheme (299) */
+  /** @name RmrkTraitsTheme (301) */
   interface RmrkTraitsTheme extends Struct {
     readonly name: Bytes;
     readonly properties: Vec<RmrkTraitsThemeThemeProperty>;
     readonly inherit: bool;
   }
 
-  /** @name RmrkTraitsThemeThemeProperty (301) */
+  /** @name RmrkTraitsThemeThemeProperty (303) */
   interface RmrkTraitsThemeThemeProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name PalletEvmCall (303) */
+  /** @name PalletAppPromotionCall (305) */
+  interface PalletAppPromotionCall extends Enum {
+    readonly isSetAdminAddress: boolean;
+    readonly asSetAdminAddress: {
+      readonly admin: PalletEvmAccountBasicCrossAccountIdRepr;
+    } & Struct;
+    readonly isStake: boolean;
+    readonly asStake: {
+      readonly amount: u128;
+    } & Struct;
+    readonly isUnstake: boolean;
+    readonly isSponsorCollection: boolean;
+    readonly asSponsorCollection: {
+      readonly collectionId: u32;
+    } & Struct;
+    readonly isStopSponsoringCollection: boolean;
+    readonly asStopSponsoringCollection: {
+      readonly collectionId: u32;
+    } & Struct;
+    readonly isSponsorContract: boolean;
+    readonly asSponsorContract: {
+      readonly contractId: H160;
+    } & Struct;
+    readonly isStopSponsoringContract: boolean;
+    readonly asStopSponsoringContract: {
+      readonly contractId: H160;
+    } & Struct;
+    readonly isPayoutStakers: boolean;
+    readonly asPayoutStakers: {
+      readonly stakersNumber: Option<u8>;
+    } & Struct;
+    readonly type: 'SetAdminAddress' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers';
+  }
+
+  /** @name PalletEvmCall (307) */
   interface PalletEvmCall extends Enum {
     readonly isWithdraw: boolean;
     readonly asWithdraw: {
@@ -2697,7 +2755,7 @@
     readonly type: 'Withdraw' | 'Call' | 'Create' | 'Create2';
   }
 
-  /** @name PalletEthereumCall (307) */
+  /** @name PalletEthereumCall (311) */
   interface PalletEthereumCall extends Enum {
     readonly isTransact: boolean;
     readonly asTransact: {
@@ -2706,7 +2764,7 @@
     readonly type: 'Transact';
   }
 
-  /** @name EthereumTransactionTransactionV2 (308) */
+  /** @name EthereumTransactionTransactionV2 (312) */
   interface EthereumTransactionTransactionV2 extends Enum {
     readonly isLegacy: boolean;
     readonly asLegacy: EthereumTransactionLegacyTransaction;
@@ -2717,7 +2775,7 @@
     readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
   }
 
-  /** @name EthereumTransactionLegacyTransaction (309) */
+  /** @name EthereumTransactionLegacyTransaction (313) */
   interface EthereumTransactionLegacyTransaction extends Struct {
     readonly nonce: U256;
     readonly gasPrice: U256;
@@ -2728,7 +2786,7 @@
     readonly signature: EthereumTransactionTransactionSignature;
   }
 
-  /** @name EthereumTransactionTransactionAction (310) */
+  /** @name EthereumTransactionTransactionAction (314) */
   interface EthereumTransactionTransactionAction extends Enum {
     readonly isCall: boolean;
     readonly asCall: H160;
@@ -2736,14 +2794,14 @@
     readonly type: 'Call' | 'Create';
   }
 
-  /** @name EthereumTransactionTransactionSignature (311) */
+  /** @name EthereumTransactionTransactionSignature (315) */
   interface EthereumTransactionTransactionSignature extends Struct {
     readonly v: u64;
     readonly r: H256;
     readonly s: H256;
   }
 
-  /** @name EthereumTransactionEip2930Transaction (313) */
+  /** @name EthereumTransactionEip2930Transaction (317) */
   interface EthereumTransactionEip2930Transaction extends Struct {
     readonly chainId: u64;
     readonly nonce: U256;
@@ -2758,13 +2816,13 @@
     readonly s: H256;
   }
 
-  /** @name EthereumTransactionAccessListItem (315) */
+  /** @name EthereumTransactionAccessListItem (319) */
   interface EthereumTransactionAccessListItem extends Struct {
     readonly address: H160;
     readonly storageKeys: Vec<H256>;
   }
 
-  /** @name EthereumTransactionEip1559Transaction (316) */
+  /** @name EthereumTransactionEip1559Transaction (320) */
   interface EthereumTransactionEip1559Transaction extends Struct {
     readonly chainId: u64;
     readonly nonce: U256;
@@ -2780,7 +2838,7 @@
     readonly s: H256;
   }
 
-  /** @name PalletEvmMigrationCall (317) */
+  /** @name PalletEvmMigrationCall (321) */
   interface PalletEvmMigrationCall extends Enum {
     readonly isBegin: boolean;
     readonly asBegin: {
@@ -2799,13 +2857,13 @@
     readonly type: 'Begin' | 'SetData' | 'Finish';
   }
 
-  /** @name PalletSudoError (320) */
+  /** @name PalletSudoError (324) */
   interface PalletSudoError extends Enum {
     readonly isRequireSudo: boolean;
     readonly type: 'RequireSudo';
   }
 
-  /** @name OrmlVestingModuleError (322) */
+  /** @name OrmlVestingModuleError (326) */
   interface OrmlVestingModuleError extends Enum {
     readonly isZeroVestingPeriod: boolean;
     readonly isZeroVestingPeriodCount: boolean;
@@ -2816,21 +2874,21 @@
     readonly type: 'ZeroVestingPeriod' | 'ZeroVestingPeriodCount' | 'InsufficientBalanceToLock' | 'TooManyVestingSchedules' | 'AmountLow' | 'MaxVestingSchedulesExceeded';
   }
 
-  /** @name CumulusPalletXcmpQueueInboundChannelDetails (324) */
+  /** @name CumulusPalletXcmpQueueInboundChannelDetails (328) */
   interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct {
     readonly sender: u32;
     readonly state: CumulusPalletXcmpQueueInboundState;
     readonly messageMetadata: Vec<ITuple<[u32, PolkadotParachainPrimitivesXcmpMessageFormat]>>;
   }
 
-  /** @name CumulusPalletXcmpQueueInboundState (325) */
+  /** @name CumulusPalletXcmpQueueInboundState (329) */
   interface CumulusPalletXcmpQueueInboundState extends Enum {
     readonly isOk: boolean;
     readonly isSuspended: boolean;
     readonly type: 'Ok' | 'Suspended';
   }
 
-  /** @name PolkadotParachainPrimitivesXcmpMessageFormat (328) */
+  /** @name PolkadotParachainPrimitivesXcmpMessageFormat (332) */
   interface PolkadotParachainPrimitivesXcmpMessageFormat extends Enum {
     readonly isConcatenatedVersionedXcm: boolean;
     readonly isConcatenatedEncodedBlob: boolean;
@@ -2838,7 +2896,7 @@
     readonly type: 'ConcatenatedVersionedXcm' | 'ConcatenatedEncodedBlob' | 'Signals';
   }
 
-  /** @name CumulusPalletXcmpQueueOutboundChannelDetails (331) */
+  /** @name CumulusPalletXcmpQueueOutboundChannelDetails (335) */
   interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct {
     readonly recipient: u32;
     readonly state: CumulusPalletXcmpQueueOutboundState;
@@ -2847,14 +2905,14 @@
     readonly lastIndex: u16;
   }
 
-  /** @name CumulusPalletXcmpQueueOutboundState (332) */
+  /** @name CumulusPalletXcmpQueueOutboundState (336) */
   interface CumulusPalletXcmpQueueOutboundState extends Enum {
     readonly isOk: boolean;
     readonly isSuspended: boolean;
     readonly type: 'Ok' | 'Suspended';
   }
 
-  /** @name CumulusPalletXcmpQueueQueueConfigData (334) */
+  /** @name CumulusPalletXcmpQueueQueueConfigData (338) */
   interface CumulusPalletXcmpQueueQueueConfigData extends Struct {
     readonly suspendThreshold: u32;
     readonly dropThreshold: u32;
@@ -2864,7 +2922,7 @@
     readonly xcmpMaxIndividualWeight: u64;
   }
 
-  /** @name CumulusPalletXcmpQueueError (336) */
+  /** @name CumulusPalletXcmpQueueError (340) */
   interface CumulusPalletXcmpQueueError extends Enum {
     readonly isFailedToSend: boolean;
     readonly isBadXcmOrigin: boolean;
@@ -2874,7 +2932,7 @@
     readonly type: 'FailedToSend' | 'BadXcmOrigin' | 'BadXcm' | 'BadOverweightIndex' | 'WeightOverLimit';
   }
 
-  /** @name PalletXcmError (337) */
+  /** @name PalletXcmError (341) */
   interface PalletXcmError extends Enum {
     readonly isUnreachable: boolean;
     readonly isSendFailure: boolean;
@@ -2892,29 +2950,29 @@
     readonly type: 'Unreachable' | 'SendFailure' | 'Filtered' | 'UnweighableMessage' | 'DestinationNotInvertible' | 'Empty' | 'CannotReanchor' | 'TooManyAssets' | 'InvalidOrigin' | 'BadVersion' | 'BadLocation' | 'NoSubscription' | 'AlreadySubscribed';
   }
 
-  /** @name CumulusPalletXcmError (338) */
+  /** @name CumulusPalletXcmError (342) */
   type CumulusPalletXcmError = Null;
 
-  /** @name CumulusPalletDmpQueueConfigData (339) */
+  /** @name CumulusPalletDmpQueueConfigData (343) */
   interface CumulusPalletDmpQueueConfigData extends Struct {
     readonly maxIndividual: u64;
   }
 
-  /** @name CumulusPalletDmpQueuePageIndexData (340) */
+  /** @name CumulusPalletDmpQueuePageIndexData (344) */
   interface CumulusPalletDmpQueuePageIndexData extends Struct {
     readonly beginUsed: u32;
     readonly endUsed: u32;
     readonly overweightCount: u64;
   }
 
-  /** @name CumulusPalletDmpQueueError (343) */
+  /** @name CumulusPalletDmpQueueError (347) */
   interface CumulusPalletDmpQueueError extends Enum {
     readonly isUnknown: boolean;
     readonly isOverLimit: boolean;
     readonly type: 'Unknown' | 'OverLimit';
   }
 
-  /** @name PalletUniqueError (347) */
+  /** @name PalletUniqueError (351) */
   interface PalletUniqueError extends Enum {
     readonly isCollectionDecimalPointLimitExceeded: boolean;
     readonly isConfirmUnsetSponsorFail: boolean;
@@ -2923,7 +2981,7 @@
     readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection';
   }
 
-  /** @name PalletUniqueSchedulerScheduledV3 (350) */
+  /** @name PalletUniqueSchedulerScheduledV3 (354) */
   interface PalletUniqueSchedulerScheduledV3 extends Struct {
     readonly maybeId: Option<U8aFixed>;
     readonly priority: u8;
@@ -2932,7 +2990,7 @@
     readonly origin: OpalRuntimeOriginCaller;
   }
 
-  /** @name OpalRuntimeOriginCaller (351) */
+  /** @name OpalRuntimeOriginCaller (355) */
   interface OpalRuntimeOriginCaller extends Enum {
     readonly isSystem: boolean;
     readonly asSystem: FrameSupportDispatchRawOrigin;
@@ -2946,7 +3004,7 @@
     readonly type: 'System' | 'Void' | 'PolkadotXcm' | 'CumulusXcm' | 'Ethereum';
   }
 
-  /** @name FrameSupportDispatchRawOrigin (352) */
+  /** @name FrameSupportDispatchRawOrigin (356) */
   interface FrameSupportDispatchRawOrigin extends Enum {
     readonly isRoot: boolean;
     readonly isSigned: boolean;
@@ -2955,7 +3013,7 @@
     readonly type: 'Root' | 'Signed' | 'None';
   }
 
-  /** @name PalletXcmOrigin (353) */
+  /** @name PalletXcmOrigin (357) */
   interface PalletXcmOrigin extends Enum {
     readonly isXcm: boolean;
     readonly asXcm: XcmV1MultiLocation;
@@ -2964,7 +3022,7 @@
     readonly type: 'Xcm' | 'Response';
   }
 
-  /** @name CumulusPalletXcmOrigin (354) */
+  /** @name CumulusPalletXcmOrigin (358) */
   interface CumulusPalletXcmOrigin extends Enum {
     readonly isRelay: boolean;
     readonly isSiblingParachain: boolean;
@@ -2972,17 +3030,17 @@
     readonly type: 'Relay' | 'SiblingParachain';
   }
 
-  /** @name PalletEthereumRawOrigin (355) */
+  /** @name PalletEthereumRawOrigin (359) */
   interface PalletEthereumRawOrigin extends Enum {
     readonly isEthereumTransaction: boolean;
     readonly asEthereumTransaction: H160;
     readonly type: 'EthereumTransaction';
   }
 
-  /** @name SpCoreVoid (356) */
+  /** @name SpCoreVoid (360) */
   type SpCoreVoid = Null;
 
-  /** @name PalletUniqueSchedulerError (357) */
+  /** @name PalletUniqueSchedulerError (361) */
   interface PalletUniqueSchedulerError extends Enum {
     readonly isFailedToSchedule: boolean;
     readonly isNotFound: boolean;
@@ -2991,21 +3049,21 @@
     readonly type: 'FailedToSchedule' | 'NotFound' | 'TargetBlockNumberInPast' | 'RescheduleNoChange';
   }
 
-  /** @name UpDataStructsCollection (358) */
+  /** @name UpDataStructsCollection (362) */
   interface UpDataStructsCollection extends Struct {
     readonly owner: AccountId32;
     readonly mode: UpDataStructsCollectionMode;
     readonly name: Vec<u16>;
     readonly description: Vec<u16>;
     readonly tokenPrefix: Bytes;
-    readonly sponsorship: UpDataStructsSponsorshipState;
+    readonly sponsorship: UpDataStructsSponsorshipStateAccountId32;
     readonly limits: UpDataStructsCollectionLimits;
     readonly permissions: UpDataStructsCollectionPermissions;
     readonly externalCollection: bool;
   }
 
-  /** @name UpDataStructsSponsorshipState (359) */
-  interface UpDataStructsSponsorshipState extends Enum {
+  /** @name UpDataStructsSponsorshipStateAccountId32 (363) */
+  interface UpDataStructsSponsorshipStateAccountId32 extends Enum {
     readonly isDisabled: boolean;
     readonly isUnconfirmed: boolean;
     readonly asUnconfirmed: AccountId32;
@@ -3014,50 +3072,50 @@
     readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
   }
 
-  /** @name UpDataStructsProperties (360) */
+  /** @name UpDataStructsProperties (364) */
   interface UpDataStructsProperties extends Struct {
     readonly map: UpDataStructsPropertiesMapBoundedVec;
     readonly consumedSpace: u32;
     readonly spaceLimit: u32;
   }
 
-  /** @name UpDataStructsPropertiesMapBoundedVec (361) */
+  /** @name UpDataStructsPropertiesMapBoundedVec (365) */
   interface UpDataStructsPropertiesMapBoundedVec extends BTreeMap<Bytes, Bytes> {}
 
-  /** @name UpDataStructsPropertiesMapPropertyPermission (366) */
+  /** @name UpDataStructsPropertiesMapPropertyPermission (370) */
   interface UpDataStructsPropertiesMapPropertyPermission extends BTreeMap<Bytes, UpDataStructsPropertyPermission> {}
 
-  /** @name UpDataStructsCollectionStats (373) */
+  /** @name UpDataStructsCollectionStats (377) */
   interface UpDataStructsCollectionStats extends Struct {
     readonly created: u32;
     readonly destroyed: u32;
     readonly alive: u32;
   }
 
-  /** @name UpDataStructsTokenChild (374) */
+  /** @name UpDataStructsTokenChild (378) */
   interface UpDataStructsTokenChild extends Struct {
     readonly token: u32;
     readonly collection: u32;
   }
 
-  /** @name PhantomTypeUpDataStructs (375) */
+  /** @name PhantomTypeUpDataStructs (379) */
   interface PhantomTypeUpDataStructs extends Vec<ITuple<[UpDataStructsTokenData, UpDataStructsRpcCollection, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftNftInfo, RmrkTraitsResourceResourceInfo, RmrkTraitsPropertyPropertyInfo, RmrkTraitsBaseBaseInfo, RmrkTraitsPartPartType, RmrkTraitsTheme, RmrkTraitsNftNftChild]>> {}
 
-  /** @name UpDataStructsTokenData (377) */
+  /** @name UpDataStructsTokenData (381) */
   interface UpDataStructsTokenData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: Option<PalletEvmAccountBasicCrossAccountIdRepr>;
     readonly pieces: u128;
   }
 
-  /** @name UpDataStructsRpcCollection (379) */
+  /** @name UpDataStructsRpcCollection (383) */
   interface UpDataStructsRpcCollection extends Struct {
     readonly owner: AccountId32;
     readonly mode: UpDataStructsCollectionMode;
     readonly name: Vec<u16>;
     readonly description: Vec<u16>;
     readonly tokenPrefix: Bytes;
-    readonly sponsorship: UpDataStructsSponsorshipState;
+    readonly sponsorship: UpDataStructsSponsorshipStateAccountId32;
     readonly limits: UpDataStructsCollectionLimits;
     readonly permissions: UpDataStructsCollectionPermissions;
     readonly tokenPropertyPermissions: Vec<UpDataStructsPropertyKeyPermission>;
@@ -3065,7 +3123,7 @@
     readonly readOnly: bool;
   }
 
-  /** @name RmrkTraitsCollectionCollectionInfo (380) */
+  /** @name RmrkTraitsCollectionCollectionInfo (384) */
   interface RmrkTraitsCollectionCollectionInfo extends Struct {
     readonly issuer: AccountId32;
     readonly metadata: Bytes;
@@ -3074,7 +3132,7 @@
     readonly nftsCount: u32;
   }
 
-  /** @name RmrkTraitsNftNftInfo (381) */
+  /** @name RmrkTraitsNftNftInfo (385) */
   interface RmrkTraitsNftNftInfo extends Struct {
     readonly owner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
     readonly royalty: Option<RmrkTraitsNftRoyaltyInfo>;
@@ -3083,13 +3141,13 @@
     readonly pending: bool;
   }
 
-  /** @name RmrkTraitsNftRoyaltyInfo (383) */
+  /** @name RmrkTraitsNftRoyaltyInfo (387) */
   interface RmrkTraitsNftRoyaltyInfo extends Struct {
     readonly recipient: AccountId32;
     readonly amount: Permill;
   }
 
-  /** @name RmrkTraitsResourceResourceInfo (384) */
+  /** @name RmrkTraitsResourceResourceInfo (388) */
   interface RmrkTraitsResourceResourceInfo extends Struct {
     readonly id: u32;
     readonly resource: RmrkTraitsResourceResourceTypes;
@@ -3097,26 +3155,26 @@
     readonly pendingRemoval: bool;
   }
 
-  /** @name RmrkTraitsPropertyPropertyInfo (385) */
+  /** @name RmrkTraitsPropertyPropertyInfo (389) */
   interface RmrkTraitsPropertyPropertyInfo extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name RmrkTraitsBaseBaseInfo (386) */
+  /** @name RmrkTraitsBaseBaseInfo (390) */
   interface RmrkTraitsBaseBaseInfo extends Struct {
     readonly issuer: AccountId32;
     readonly baseType: Bytes;
     readonly symbol: Bytes;
   }
 
-  /** @name RmrkTraitsNftNftChild (387) */
+  /** @name RmrkTraitsNftNftChild (391) */
   interface RmrkTraitsNftNftChild extends Struct {
     readonly collectionId: u32;
     readonly nftId: u32;
   }
 
-  /** @name PalletCommonError (389) */
+  /** @name PalletCommonError (393) */
   interface PalletCommonError extends Enum {
     readonly isCollectionNotFound: boolean;
     readonly isMustBeTokenOwner: boolean;
@@ -3155,7 +3213,7 @@
     readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal';
   }
 
-  /** @name PalletFungibleError (391) */
+  /** @name PalletFungibleError (395) */
   interface PalletFungibleError extends Enum {
     readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isFungibleItemsHaveNoId: boolean;
@@ -3165,12 +3223,12 @@
     readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
   }
 
-  /** @name PalletRefungibleItemData (392) */
+  /** @name PalletRefungibleItemData (396) */
   interface PalletRefungibleItemData extends Struct {
     readonly constData: Bytes;
   }
 
-  /** @name PalletRefungibleError (397) */
+  /** @name PalletRefungibleError (401) */
   interface PalletRefungibleError extends Enum {
     readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isWrongRefungiblePieces: boolean;
@@ -3180,20 +3238,19 @@
     readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RepartitionWhileNotOwningAllPieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
   }
 
-  /** @name PalletNonfungibleItemData (398) */
+  /** @name PalletNonfungibleItemData (402) */
   interface PalletNonfungibleItemData extends Struct {
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name UpDataStructsPropertyScope (400) */
+  /** @name UpDataStructsPropertyScope (404) */
   interface UpDataStructsPropertyScope extends Enum {
     readonly isNone: boolean;
     readonly isRmrk: boolean;
-    readonly isEth: boolean;
-    readonly type: 'None' | 'Rmrk' | 'Eth';
+    readonly type: 'None' | 'Rmrk';
   }
 
-  /** @name PalletNonfungibleError (402) */
+  /** @name PalletNonfungibleError (406) */
   interface PalletNonfungibleError extends Enum {
     readonly isNotNonfungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isNonfungibleItemsHaveNoAmount: boolean;
@@ -3201,7 +3258,7 @@
     readonly type: 'NotNonfungibleDataUsedToMintFungibleCollectionToken' | 'NonfungibleItemsHaveNoAmount' | 'CantBurnNftWithChildren';
   }
 
-  /** @name PalletStructureError (403) */
+  /** @name PalletStructureError (407) */
   interface PalletStructureError extends Enum {
     readonly isOuroborosDetected: boolean;
     readonly isDepthLimit: boolean;
@@ -3210,7 +3267,7 @@
     readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound';
   }
 
-  /** @name PalletRmrkCoreError (404) */
+  /** @name PalletRmrkCoreError (408) */
   interface PalletRmrkCoreError extends Enum {
     readonly isCorruptedCollectionType: boolean;
     readonly isRmrkPropertyKeyIsTooLong: boolean;
@@ -3234,7 +3291,7 @@
     readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId';
   }
 
-  /** @name PalletRmrkEquipError (406) */
+  /** @name PalletRmrkEquipError (410) */
   interface PalletRmrkEquipError extends Enum {
     readonly isPermissionError: boolean;
     readonly isNoAvailableBaseId: boolean;
@@ -3246,7 +3303,18 @@
     readonly type: 'PermissionError' | 'NoAvailableBaseId' | 'NoAvailablePartId' | 'BaseDoesntExist' | 'NeedsDefaultThemeFirst' | 'PartDoesntExist' | 'NoEquippableOnFixedPart';
   }
 
-  /** @name PalletEvmError (409) */
+  /** @name PalletAppPromotionError (416) */
+  interface PalletAppPromotionError extends Enum {
+    readonly isAdminNotSet: boolean;
+    readonly isNoPermission: boolean;
+    readonly isNotSufficientFunds: boolean;
+    readonly isPendingForBlockOverflow: boolean;
+    readonly isSponsorNotSet: boolean;
+    readonly isIncorrectLockedBalanceOperation: boolean;
+    readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation';
+  }
+
+  /** @name PalletEvmError (419) */
   interface PalletEvmError extends Enum {
     readonly isBalanceLow: boolean;
     readonly isFeeOverflow: boolean;
@@ -3257,7 +3325,7 @@
     readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce';
   }
 
-  /** @name FpRpcTransactionStatus (412) */
+  /** @name FpRpcTransactionStatus (422) */
   interface FpRpcTransactionStatus extends Struct {
     readonly transactionHash: H256;
     readonly transactionIndex: u32;
@@ -3268,10 +3336,10 @@
     readonly logsBloom: EthbloomBloom;
   }
 
-  /** @name EthbloomBloom (414) */
+  /** @name EthbloomBloom (424) */
   interface EthbloomBloom extends U8aFixed {}
 
-  /** @name EthereumReceiptReceiptV3 (416) */
+  /** @name EthereumReceiptReceiptV3 (426) */
   interface EthereumReceiptReceiptV3 extends Enum {
     readonly isLegacy: boolean;
     readonly asLegacy: EthereumReceiptEip658ReceiptData;
@@ -3282,7 +3350,7 @@
     readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
   }
 
-  /** @name EthereumReceiptEip658ReceiptData (417) */
+  /** @name EthereumReceiptEip658ReceiptData (427) */
   interface EthereumReceiptEip658ReceiptData extends Struct {
     readonly statusCode: u8;
     readonly usedGas: U256;
@@ -3290,14 +3358,14 @@
     readonly logs: Vec<EthereumLog>;
   }
 
-  /** @name EthereumBlock (418) */
+  /** @name EthereumBlock (428) */
   interface EthereumBlock extends Struct {
     readonly header: EthereumHeader;
     readonly transactions: Vec<EthereumTransactionTransactionV2>;
     readonly ommers: Vec<EthereumHeader>;
   }
 
-  /** @name EthereumHeader (419) */
+  /** @name EthereumHeader (429) */
   interface EthereumHeader extends Struct {
     readonly parentHash: H256;
     readonly ommersHash: H256;
@@ -3316,24 +3384,34 @@
     readonly nonce: EthereumTypesHashH64;
   }
 
-  /** @name EthereumTypesHashH64 (420) */
+  /** @name EthereumTypesHashH64 (430) */
   interface EthereumTypesHashH64 extends U8aFixed {}
 
-  /** @name PalletEthereumError (425) */
+  /** @name PalletEthereumError (435) */
   interface PalletEthereumError extends Enum {
     readonly isInvalidSignature: boolean;
     readonly isPreLogExists: boolean;
     readonly type: 'InvalidSignature' | 'PreLogExists';
   }
 
-  /** @name PalletEvmCoderSubstrateError (426) */
+  /** @name PalletEvmCoderSubstrateError (436) */
   interface PalletEvmCoderSubstrateError extends Enum {
     readonly isOutOfGas: boolean;
     readonly isOutOfFund: boolean;
     readonly type: 'OutOfGas' | 'OutOfFund';
   }
 
-  /** @name PalletEvmContractHelpersSponsoringModeT (427) */
+  /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (437) */
+  interface UpDataStructsSponsorshipStateBasicCrossAccountIdRepr extends Enum {
+    readonly isDisabled: boolean;
+    readonly isUnconfirmed: boolean;
+    readonly asUnconfirmed: PalletEvmAccountBasicCrossAccountIdRepr;
+    readonly isConfirmed: boolean;
+    readonly asConfirmed: PalletEvmAccountBasicCrossAccountIdRepr;
+    readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
+  }
+
+  /** @name PalletEvmContractHelpersSponsoringModeT (438) */
   interface PalletEvmContractHelpersSponsoringModeT extends Enum {
     readonly isDisabled: boolean;
     readonly isAllowlisted: boolean;
@@ -3341,20 +3419,21 @@
     readonly type: 'Disabled' | 'Allowlisted' | 'Generous';
   }
 
-  /** @name PalletEvmContractHelpersError (429) */
+  /** @name PalletEvmContractHelpersError (440) */
   interface PalletEvmContractHelpersError extends Enum {
     readonly isNoPermission: boolean;
-    readonly type: 'NoPermission';
+    readonly isNoPendingSponsor: boolean;
+    readonly type: 'NoPermission' | 'NoPendingSponsor';
   }
 
-  /** @name PalletEvmMigrationError (430) */
+  /** @name PalletEvmMigrationError (441) */
   interface PalletEvmMigrationError extends Enum {
     readonly isAccountNotEmpty: boolean;
     readonly isAccountIsNotMigrating: boolean;
     readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating';
   }
 
-  /** @name SpRuntimeMultiSignature (432) */
+  /** @name SpRuntimeMultiSignature (443) */
   interface SpRuntimeMultiSignature extends Enum {
     readonly isEd25519: boolean;
     readonly asEd25519: SpCoreEd25519Signature;
@@ -3365,34 +3444,34 @@
     readonly type: 'Ed25519' | 'Sr25519' | 'Ecdsa';
   }
 
-  /** @name SpCoreEd25519Signature (433) */
+  /** @name SpCoreEd25519Signature (444) */
   interface SpCoreEd25519Signature extends U8aFixed {}
 
-  /** @name SpCoreSr25519Signature (435) */
+  /** @name SpCoreSr25519Signature (446) */
   interface SpCoreSr25519Signature extends U8aFixed {}
 
-  /** @name SpCoreEcdsaSignature (436) */
+  /** @name SpCoreEcdsaSignature (447) */
   interface SpCoreEcdsaSignature extends U8aFixed {}
 
-  /** @name FrameSystemExtensionsCheckSpecVersion (439) */
+  /** @name FrameSystemExtensionsCheckSpecVersion (450) */
   type FrameSystemExtensionsCheckSpecVersion = Null;
 
-  /** @name FrameSystemExtensionsCheckGenesis (440) */
+  /** @name FrameSystemExtensionsCheckGenesis (451) */
   type FrameSystemExtensionsCheckGenesis = Null;
 
-  /** @name FrameSystemExtensionsCheckNonce (443) */
+  /** @name FrameSystemExtensionsCheckNonce (454) */
   interface FrameSystemExtensionsCheckNonce extends Compact<u32> {}
 
-  /** @name FrameSystemExtensionsCheckWeight (444) */
+  /** @name FrameSystemExtensionsCheckWeight (455) */
   type FrameSystemExtensionsCheckWeight = Null;
 
-  /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (445) */
+  /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (456) */
   interface PalletTemplateTransactionPaymentChargeTransactionPayment extends Compact<u128> {}
 
-  /** @name OpalRuntimeRuntime (446) */
+  /** @name OpalRuntimeRuntime (457) */
   type OpalRuntimeRuntime = Null;
 
-  /** @name PalletEthereumFakeTransactionFinalizer (447) */
+  /** @name PalletEthereumFakeTransactionFinalizer (458) */
   type PalletEthereumFakeTransactionFinalizer = Null;
 
 } // declare module
modifiedtests/src/interfaces/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types.ts
+++ b/tests/src/interfaces/types.ts
@@ -2,5 +2,6 @@
 /* eslint-disable */
 
 export * from './unique/types';
+export * from './appPromotion/types';
 export * from './rmrk/types';
 export * from './default/types';
modifiedtests/src/pallet-presence.test.tsdiffbeforeafterboth
--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -68,9 +68,10 @@
       const refungible = 'refungible';
       const scheduler = 'scheduler';
       const rmrkPallets = ['rmrkcore', 'rmrkequip'];
+      const appPromotion = 'apppromotion';
 
       if (chain.eq('OPAL by UNIQUE')) {
-        requiredPallets.push(refungible, scheduler, ...rmrkPallets);
+        requiredPallets.push(refungible, scheduler, appPromotion, ...rmrkPallets);
       } else if (chain.eq('QUARTZ by UNIQUE')) {
         // Insert Quartz additional pallets here
       } else if (chain.eq('UNIQUE')) {
modifiedtests/src/refungible.test.tsdiffbeforeafterboth
--- a/tests/src/refungible.test.ts
+++ b/tests/src/refungible.test.ts
@@ -245,8 +245,8 @@
         section: 'common',
         index: '0x4202',
         data: [ 
-          collection.collectionId.toString(), 
-          token.tokenId.toString(), 
+          helper.api!.createType('u32', collection.collectionId).toHuman(), 
+          helper.api!.createType('u32', token.tokenId).toHuman(),
           {Substrate: alice.address}, 
           '100',
         ],
@@ -265,8 +265,8 @@
         section: 'common',
         index: '0x4203',
         data: [ 
-          collection.collectionId.toString(), 
-          token.tokenId.toString(), 
+          helper.api!.createType('u32', collection.collectionId).toHuman(), 
+          helper.api!.createType('u32', token.tokenId).toHuman(),
           {Substrate: alice.address}, 
           '50',
         ],
modifiedtests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -27,6 +27,7 @@
       const alice = privateKey('//Alice');
       const bob = privateKey('//Bob');
       const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+      
       const collectionInfo = await collection.getData();
       expect(collectionInfo?.raw.owner.toString()).to.be.deep.eq(alice.address);
       // first - add collection admin Bob
modifiedtests/src/substrate/substrate-api.tsdiffbeforeafterboth
--- a/tests/src/substrate/substrate-api.ts
+++ b/tests/src/substrate/substrate-api.ts
@@ -25,6 +25,8 @@
 import privateKey from './privateKey';
 import promisifySubstrate from './promisify-substrate';
 
+import {SilentConsole} from '../util/playgrounds/unique.dev';
+
 
 
 function defaultApiOptions(): ApiOptions {
@@ -42,6 +44,7 @@
     },
     rpc: {
       unique: defs.unique.rpc,
+      appPromotion: defs.appPromotion.rpc,
       rmrk: defs.rmrk.rpc,
       eth: {
         feeHistory: {
@@ -75,25 +78,8 @@
   const api: ApiPromise = new ApiPromise(settings);
   let result: T = null as unknown as T;
 
-  // TODO: Remove, this is temporary: Filter unneeded API output
-  // (Jaco promised it will be removed in the next version)
-  const consoleErr = console.error;
-  const consoleLog = console.log;
-  const consoleWarn = console.warn;
-
-  const outFn = (printer: any) => (...args: any[]) => {
-    for (const arg of args) {
-      if (typeof arg !== 'string')
-        continue;
-      if (arg.includes('1000:: Normal connection closure') || arg.includes('Not decorating unknown runtime apis:') || arg.includes('RPC methods not decorated:') || arg === 'Normal connection closure')
-        return;
-    }
-    printer(...args);
-  };
-
-  console.error = outFn(consoleErr.bind(console));
-  console.log = outFn(consoleLog.bind(console));
-  console.warn = outFn(consoleWarn.bind(console));
+  const silentConsole = new SilentConsole();
+  silentConsole.enable();
 
   try {
     await promisifySubstrate(api, async () => {
@@ -106,9 +92,7 @@
     })();
   } finally {
     await api.disconnect();
-    console.error = consoleErr;
-    console.log = consoleLog;
-    console.warn = consoleWarn;
+    silentConsole.disable();
   }
   return result as T;
 }
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -17,10 +17,11 @@
 import '../interfaces/augment-api-rpc';
 import '../interfaces/augment-api-query';
 import {ApiPromise} from '@polkadot/api';
-import type {AccountId, EventRecord, Event} from '@polkadot/types/interfaces';
+import type {AccountId, EventRecord, Event, BlockNumber} from '@polkadot/types/interfaces';
 import type {GenericEventData} from '@polkadot/types';
 import {AnyTuple, IEvent, IKeyringPair} from '@polkadot/types/types';
 import {evmToAddress} from '@polkadot/util-crypto';
+import {AnyNumber} from '@polkadot/types-codec/types';
 import BN from 'bn.js';
 import chai from 'chai';
 import chaiAsPromised from 'chai-as-promised';
@@ -48,6 +49,7 @@
   Fungible = 'fungible',
   NFT = 'nonfungible',
   Scheduler = 'scheduler',
+  AppPromotion = 'apppromotion',
 }
 
 export async function isUnique(): Promise<boolean> {
@@ -1779,3 +1781,23 @@
 
 itApi.only = (name: string, cb: (apis: { api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair }) => any) => itApi(name, cb, {only: true});
 itApi.skip = (name: string, cb: (apis: { api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair }) => any) => itApi(name, cb, {skip: true});
+
+
+export async function expectSubstrateEventsAtBlock(api: ApiPromise, blockNumber: AnyNumber | BlockNumber, section: string, methods: string[], dryRun = false) {
+  const blockHash = await api.rpc.chain.getBlockHash(blockNumber);
+  const subEvents = (await api.query.system.events.at(blockHash))
+    .filter(x => x.event.section === section)
+    .map((x) => x.toHuman());
+  const events = methods.map((m) => {
+    return {
+      event: {
+        method: m,
+        section,
+      },
+    };
+  });
+  if (!dryRun) {
+    expect(subEvents).to.be.like(events);
+  }
+  return subEvents;
+}
\ No newline at end of file
modifiedtests/src/util/playgrounds/index.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/index.ts
+++ b/tests/src/util/playgrounds/index.ts
@@ -2,39 +2,16 @@
 // SPDX-License-Identifier: Apache-2.0
 
 import {IKeyringPair} from '@polkadot/types/types';
+import {Context} from 'mocha';
 import config from '../../config';
 import '../../interfaces/augment-api-events';
-import {DevUniqueHelper} from './unique.dev';
+import {DevUniqueHelper, SilentLogger, SilentConsole} from './unique.dev';
 
-class SilentLogger {
-  log(msg: any, level: any): void { }
-  level = {
-    ERROR: 'ERROR' as const,
-    WARNING: 'WARNING' as const,
-    INFO: 'INFO' as const,
-  };
-}
 
 export const usingPlaygrounds = async (code: (helper: DevUniqueHelper, privateKey: (seed: string) => IKeyringPair) => Promise<void>) => {
-  // TODO: Remove, this is temporary: Filter unneeded API output
-  // (Jaco promised it will be removed in the next version)
-  const consoleErr = console.error;
-  const consoleLog = console.log;
-  const consoleWarn = console.warn;
+  const silentConsole = new SilentConsole();
+  silentConsole.enable();
 
-  const outFn = (printer: any) => (...args: any[]) => {
-    for (const arg of args) {
-      if (typeof arg !== 'string')
-        continue;
-      if (arg.includes('1000:: Normal connection closure') || arg.includes('Not decorating unknown runtime apis:') || arg.includes('RPC methods not decorated:') || arg === 'Normal connection closure')
-        return;
-    }
-    printer(...args);
-  };
-
-  console.error = outFn(consoleErr.bind(console));
-  console.log = outFn(consoleLog.bind(console));
-  console.warn = outFn(consoleWarn.bind(console));
   const helper = new DevUniqueHelper(new SilentLogger());
 
   try {
@@ -45,8 +22,42 @@
   }
   finally {
     await helper.disconnect();
-    console.error = consoleErr;
-    console.log = consoleLog;
-    console.warn = consoleWarn;
+    silentConsole.disable();
   }
 };
+
+export enum Pallets {
+  Inflation = 'inflation',
+  RmrkCore = 'rmrkcore',
+  RmrkEquip = 'rmrkequip',
+  ReFungible = 'refungible',
+  Fungible = 'fungible',
+  NFT = 'nonfungible',
+  Scheduler = 'scheduler',
+}
+
+export function requirePalletsOrSkip(test: Context, helper: DevUniqueHelper, requiredPallets: string[]) {
+  const missingPallets = helper.fetchMissingPalletNames(requiredPallets);
+    
+  if (missingPallets.length > 0) {
+    const skipMsg = `\tSkipping test '${test.test?.title}'.\n\tThe following pallets are missing:\n\t- ${missingPallets.join('\n\t- ')}`;
+    console.warn('\x1b[38:5:208m%s\x1b[0m', skipMsg);
+    test.skip();
+  }
+}
+
+export async function itSub(name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => IKeyringPair }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {}) {
+  (opts.only ? it.only : 
+    opts.skip ? it.skip : it)(name, async function () {
+    await usingPlaygrounds(async (helper, privateKey) => {
+      if (opts.requiredPallets) {
+        requirePalletsOrSkip(this, helper, opts.requiredPallets);
+      }
+      
+      await cb({helper, privateKey});
+    });
+  });
+}
+itSub.only = (name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => IKeyringPair }) => any) => itSub(name, cb, {only: true});
+itSub.skip = (name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => IKeyringPair }) => any) => itSub(name, cb, {skip: true});
+itSub.ifWithPallets = (name: string, required: string[], cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => IKeyringPair }) => any) => itSub(name, cb, {requiredPallets: required});
modifiedtests/src/util/playgrounds/types.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/types.ts
+++ b/tests/src/util/playgrounds/types.ts
@@ -101,10 +101,27 @@
   tokenId: number;
 }
 
+export interface IBlock {
+  extrinsics: IExtrinsic[]
+  header: {
+    parentHash: string,
+    number: number,
+  };
+}
+
+export interface IExtrinsic {
+  isSigned: boolean,
+  method: {
+    method: string,
+    section: string,
+    args: any[]
+  }
+}
+
 export interface ICollectionCreationOptions {
-  name: string | number[];
-  description: string | number[];
-  tokenPrefix: string | number[];
+  name?: string | number[];
+  description?: string | number[];
+  tokenPrefix?: string | number[];
   mode?: {
     nft?: null;
     refungible?: null;
@@ -123,8 +140,15 @@
   tokenSymbol: string[]
 }
 
+export interface ISubstrateBalance {
+  free: bigint,
+  reserved: bigint,
+  miscFrozen: bigint,
+  feeFrozen: bigint
+}
+
 export type TSubstrateAccount = string;
 export type TEthereumAccount = string;
 export type TApiAllowedListeners = 'connected' | 'disconnected' | 'error' | 'ready' | 'decorated';
 export type TUniqueNetworks = 'opal' | 'quartz' | 'unique';
-export type TSigner = IKeyringPair; // | 'string'
\ No newline at end of file
+export type TSigner = IKeyringPair; // | 'string'
modifiedtests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.dev.ts
+++ b/tests/src/util/playgrounds/unique.dev.ts
@@ -5,22 +5,69 @@
 import {UniqueHelper} from './unique';
 import {ApiPromise, WsProvider} from '@polkadot/api';
 import * as defs from '../../interfaces/definitions';
-import {TSigner} from './types';
 import {IKeyringPair} from '@polkadot/types/types';
 
 
+export class SilentLogger {
+  log(_msg: any, _level: any): void { }
+  level = {
+    ERROR: 'ERROR' as const,
+    WARNING: 'WARNING' as const,
+    INFO: 'INFO' as const,
+  };
+}
+
+export class SilentConsole {
+  // TODO: Remove, this is temporary: Filter unneeded API output
+  // (Jaco promised it will be removed in the next version)
+  consoleErr: any;
+  consoleLog: any;
+  consoleWarn: any;
+
+  constructor() {
+    this.consoleErr = console.error;
+    this.consoleLog = console.log;
+    this.consoleWarn = console.warn;
+  }
+
+  enable() {  
+    const outFn = (printer: any) => (...args: any[]) => {
+      for (const arg of args) {
+        if (typeof arg !== 'string')
+          continue;
+        if (arg.includes('1000:: Normal connection closure') || arg.includes('Not decorating unknown runtime apis:') || arg.includes('RPC methods not decorated:') || arg === 'Normal connection closure')
+          return;
+      }
+      printer(...args);
+    };
+  
+    console.error = outFn(this.consoleErr.bind(console));
+    console.log = outFn(this.consoleLog.bind(console));
+    console.warn = outFn(this.consoleWarn.bind(console));
+  }
+
+  disable() {
+    console.error = this.consoleErr;
+    console.log = this.consoleLog;
+    console.warn = this.consoleWarn;
+  }
+}
+
+
 export class DevUniqueHelper extends UniqueHelper {
   /**
    * Arrange methods for tests
    */
   arrange: ArrangeGroup;
+  wait: WaitGroup;
 
   constructor(logger: { log: (msg: any, level: any) => void, level: any }) {
     super(logger);
     this.arrange = new ArrangeGroup(this);
+    this.wait = new WaitGroup(this);
   }
 
-  async connect(wsEndpoint: string, listeners?: any): Promise<void> {
+  async connect(wsEndpoint: string, _listeners?: any): Promise<void> {
     const wsProvider = new WsProvider(wsEndpoint);
     this.api = new ApiPromise({
       provider: wsProvider,
@@ -36,6 +83,7 @@
       },
       rpc: {
         unique: defs.unique.rpc,
+        appPromotion: defs.appPromotion.rpc,
         rmrk: defs.rmrk.rpc,
         eth: {
           feeHistory: {
@@ -72,20 +120,21 @@
    */
   createAccounts = async (balances: bigint[], donor: IKeyringPair): Promise<IKeyringPair[]> => {
     let nonce = await this.helper.chain.getNonce(donor.address);
+    const ss58Format = this.helper.chain.getChainProperties().ss58Format;
     const tokenNominal = this.helper.balance.getOneTokenNominal();
     const transactions = [];
     const accounts: IKeyringPair[] = [];
     for (const balance of balances) {
-      const recepient = this.helper.util.fromSeed(mnemonicGenerate());
-      accounts.push(recepient);
+      const recipient = this.helper.util.fromSeed(mnemonicGenerate(), ss58Format);
+      accounts.push(recipient);
       if (balance !== 0n) {
-        const tx = this.helper.constructApiCall('api.tx.balances.transfer', [{Id: recepient.address}, balance * tokenNominal]);
+        const tx = this.helper.constructApiCall('api.tx.balances.transfer', [{Id: recipient.address}, balance * tokenNominal]);
         transactions.push(this.helper.signTransaction(donor, tx, 'account generation', {nonce}));
         nonce++;
       }
     }
 
-    await Promise.all(transactions).catch(e => {});
+    await Promise.all(transactions).catch(_e => {});
     
     //#region TODO remove this region, when nonce problem will be solved
     const checkBalances = async () => {
@@ -105,7 +154,7 @@
     for (let index = 0; index < 5; index++) {
       accountsCreated = await checkBalances();
       if(accountsCreated) break;
-      await this.waitNewBlocks(1);
+      
     }
 
     if (!accountsCreated) throw Error('Accounts generation failed');
@@ -114,12 +163,86 @@
     return accounts;
   };
 
+  // TODO combine this method and createAccounts into one
+  createCrowd = async (accountsToCreate: number, withBalance: bigint, donor: IKeyringPair): Promise<IKeyringPair[]> => {  
+    const createAsManyAsCan = async () => {
+      let transactions: any = [];
+      const accounts: IKeyringPair[] = [];
+      let nonce = await this.helper.chain.getNonce(donor.address);
+      const tokenNominal = this.helper.balance.getOneTokenNominal();
+      for (let i = 0; i < accountsToCreate; i++) {
+        if (i === 500) { // if there are too many accounts to create
+          await Promise.allSettled(transactions); // wait while first 500 (should be 100 for devnode) tx will be settled 
+          transactions = []; //
+          nonce = await this.helper.chain.getNonce(donor.address); // update nonce 
+        }
+        const recepient = this.helper.util.fromSeed(mnemonicGenerate());
+        accounts.push(recepient);
+        if (withBalance !== 0n) {
+          const tx = this.helper.constructApiCall('api.tx.balances.transfer', [{Id: recepient.address}, withBalance * tokenNominal]);
+          transactions.push(this.helper.signTransaction(donor, tx, 'account generation', {nonce}));
+          nonce++;
+        }
+      }
+      
+      const fullfilledAccounts = [];
+      await Promise.allSettled(transactions);
+      for (const account of accounts) {
+        const accountBalance = await this.helper.balance.getSubstrate(account.address);
+        if (accountBalance === withBalance * tokenNominal) {
+          fullfilledAccounts.push(account);
+        }
+      }
+      return fullfilledAccounts;
+    };
+
+    
+    const crowd: IKeyringPair[] = [];
+    // do up to 5 retries
+    for (let index = 0; index < 5 && accountsToCreate !== 0; index++) {
+      const asManyAsCan = await createAsManyAsCan();
+      crowd.push(...asManyAsCan);
+      accountsToCreate -= asManyAsCan.length;
+    }
+
+    if (accountsToCreate !== 0) throw Error(`Crowd generation failed: ${accountsToCreate} accounts left`);
+
+    return crowd;
+  };
+
+  isDevNode = async () => {
+    const block1 = await this.helper.api?.rpc.chain.getBlock(await this.helper.api?.rpc.chain.getBlockHash(1));
+    const block2 = await this.helper.api?.rpc.chain.getBlock(await this.helper.api?.rpc.chain.getBlockHash(2));
+    const findCreationDate = async (block: any) => {
+      const humanBlock = block.toHuman();
+      let date;
+      humanBlock.block.extrinsics.forEach((ext: any) => {
+        if(ext.method.section === 'timestamp') {
+          date = Number(ext.method.args.now.replaceAll(',', ''));
+        }
+      });
+      return date;
+    };
+    const block1date = await findCreationDate(block1);
+    const block2date = await findCreationDate(block2);
+    if(block2date! - block1date! < 9000) return true;
+  };
+}
+
+class WaitGroup {
+  helper: UniqueHelper;
+
+  constructor(helper: UniqueHelper) {
+    this.helper = helper;
+  }
+
   /**
    * Wait for specified bnumber of blocks
    * @param blocksCount number of blocks to wait
    * @returns 
    */
-  async waitNewBlocks(blocksCount = 1): Promise<void> {
+  async newBlocks(blocksCount = 1): Promise<void> {
+    // eslint-disable-next-line no-async-promise-executor
     const promise = new Promise<void>(async (resolve) => {
       const unsubscribe = await this.helper.api!.rpc.chain.subscribeNewHeads(() => {
         if (blocksCount > 0) {
@@ -132,4 +255,27 @@
     });
     return promise;
   }
-}
\ No newline at end of file
+
+  async forParachainBlockNumber(blockNumber: bigint) {
+    return new Promise<void>(async (resolve) => {
+      const unsubscribe = await this.helper.api!.rpc.chain.subscribeNewHeads(async (data: any) => {
+        if (data.number.toNumber() >= blockNumber) {
+          unsubscribe();
+          resolve();
+        }
+      });
+    });
+  }
+  
+  async forRelayBlockNumber(blockNumber: bigint) {
+    return new Promise<void>(async (resolve) => {
+      const unsubscribe = await this.helper.api!.query.parachainSystem.validationData(async (data: any) => {
+        if (data.value.relayParentNumber.toNumber() >= blockNumber) {
+          // @ts-ignore
+          unsubscribe();
+          resolve();
+        }
+      });
+    });
+  }
+}
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -9,15 +9,14 @@
 import {ApiInterfaceEvents} from '@polkadot/api/types';
 import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';
 import {IKeyringPair} from '@polkadot/types/types';
-import {IApiListeners, IChainEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types';
+import {IApiListeners, IBlock, IChainEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types';
 
-const crossAccountIdFromLower = (lowerAddress: ICrossAccountIdLower): ICrossAccountId => {
+export const crossAccountIdFromLower = (lowerAddress: ICrossAccountIdLower): ICrossAccountId => {
   const address = {} as ICrossAccountId;
   if(lowerAddress.substrate) address.Substrate = lowerAddress.substrate;
   if(lowerAddress.ethereum) address.Ethereum = lowerAddress.ethereum;
   return address;
 };
-
 
 const nesting = {
   toChecksumAddress(address: string): string {
@@ -91,9 +90,9 @@
     return encodeAddress(decodeAddress(address), ss58Format);
   }
 
-  static extractCollectionIdFromCreationResult(creationResult: ITransactionResult, label = 'new collection') {
+  static extractCollectionIdFromCreationResult(creationResult: ITransactionResult) {
     if (creationResult.status !== this.transactionStatus.SUCCESS) {
-      throw Error(`Unable to create collection for ${label}`);
+      throw Error('Unable to create collection!');
     }
 
     let collectionId = null;
@@ -104,15 +103,15 @@
     });
 
     if (collectionId === null) {
-      throw Error(`No CollectionCreated event for ${label}`);
+      throw Error('No CollectionCreated event was found!');
     }
 
     return collectionId;
   }
 
-  static extractTokensFromCreationResult(creationResult: ITransactionResult, label = 'new tokens') {
+  static extractTokensFromCreationResult(creationResult: ITransactionResult) {
     if (creationResult.status !== this.transactionStatus.SUCCESS) {
-      throw Error(`Unable to create tokens for ${label}`);
+      throw Error('Unable to create tokens!');
     }
     let success = false;
     const tokens = [] as any;
@@ -130,9 +129,9 @@
     return {success, tokens};
   }
 
-  static extractTokensFromBurnResult(burnResult: ITransactionResult, label = 'burned tokens') {
+  static extractTokensFromBurnResult(burnResult: ITransactionResult) {
     if (burnResult.status !== this.transactionStatus.SUCCESS) {
-      throw Error(`Unable to burn tokens for ${label}`);
+      throw Error('Unable to burn tokens!');
     }
     let success = false;
     const tokens = [] as any;
@@ -150,7 +149,7 @@
     return {success, tokens};
   }
 
-  static findCollectionInEvents(events: {event: IChainEvent}[], collectionId: number, expectedSection: string, expectedMethod: string, label?: string) {
+  static findCollectionInEvents(events: {event: IChainEvent}[], collectionId: number, expectedSection: string, expectedMethod: string) {
     let eventId = null;
     events.forEach(({event: {data, method, section}}) => {
       if ((section === expectedSection) && (method === expectedMethod)) {
@@ -159,7 +158,7 @@
     });
 
     if (eventId === null) {
-      throw Error(`No ${expectedMethod} event for ${label}`);
+      throw Error(`No ${expectedMethod} event was found!`);
     }
     return eventId === collectionId;
   }
@@ -317,6 +316,7 @@
       if(options !== null) return transaction.signAndSend(sender, options, callback);
       return transaction.signAndSend(sender, callback);
     };
+    // eslint-disable-next-line no-async-promise-executor
     return new Promise(async (resolve, reject) => {
       try {
         const unsub = await sign((result: any) => {
@@ -364,7 +364,7 @@
     return call(...params);
   }
 
-  async executeExtrinsic(sender: TSigner, extrinsic: string, params: any[], expectSuccess=false, failureMessage='expected success') {
+  async executeExtrinsic(sender: TSigner, extrinsic: string, params: any[], expectSuccess=false/*, failureMessage='expected success'*/) {
     if(this.api === null) throw Error('API not initialized');
     if(!extrinsic.startsWith('api.tx.')) throw Error(`${extrinsic} is not transaction`);
 
@@ -388,6 +388,7 @@
       type: this.chainLogType.EXTRINSIC,
       status: result.status,
       call: extrinsic,
+      signer: this.getSignerAddress(sender),
       params,
     } as IUniqueHelperLog;
 
@@ -396,7 +397,7 @@
 
     this.chainLog.push(log);
 
-    if(expectSuccess && result.status !== this.transactionStatus.SUCCESS) throw Error(failureMessage);
+    if(expectSuccess && result.status !== this.transactionStatus.SUCCESS) throw Error(`${result.moduleError}`);
     return result;
   }
 
@@ -438,6 +439,16 @@
     if(typeof signer === 'string') return signer;
     return signer.address;
   }
+
+  fetchAllPalletNames(): string[] {
+    if(this.api === null) throw Error('API not initialized');
+    return this.api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase());
+  }
+
+  fetchMissingPalletNames(requiredPallets: string[]): string[] {
+    const palletNames = this.fetchAllPalletNames();
+    return requiredPallets.filter(p => !palletNames.includes(p));
+  }
 }
 
 
@@ -474,7 +485,9 @@
   }
 
   /**
-   * Get information about the collection with additional data, including the number of tokens it contains, its administrators, the normalized address of the collection's owner, and decoded name and description.
+   * Get information about the collection with additional data,
+   * including the number of tokens it contains, its administrators,
+   * the normalized address of the collection's owner, and decoded name and description.
    *
    * @param collectionId ID of collection
    * @example await getData(2)
@@ -502,42 +515,50 @@
       collectionData[key] = this.helper.util.vec2str(humanCollection[key]);
     }
 
-    collectionData.tokensCount = (['RFT', 'NFT'].includes(humanCollection.mode)) ? await this.helper[humanCollection.mode.toLocaleLowerCase() as 'nft' | 'rft'].getLastTokenId(collectionId) : 0;
+    collectionData.tokensCount = (['RFT', 'NFT'].includes(humanCollection.mode))
+      ? await this.helper[humanCollection.mode.toLocaleLowerCase() as 'nft' | 'rft'].getLastTokenId(collectionId)
+      : 0;
     collectionData.admins = await this.getAdmins(collectionId);
 
     return collectionData;
   }
 
   /**
-   * Get the normalized addresses of the collection's administrators.
+   * Get the addresses of the collection's administrators, optionally normalized.
    *
    * @param collectionId ID of collection
+   * @param normalize whether to normalize the addresses to the default ss58 format
    * @example await getAdmins(1)
    * @returns array of administrators
    */
-  async getAdmins(collectionId: number): Promise<ICrossAccountId[]> {
-    const normalized = [];
-    for(const admin of (await this.helper.callRpc('api.rpc.unique.adminlist', [collectionId])).toHuman()) {
-      if(admin.Substrate) normalized.push({Substrate: this.helper.address.normalizeSubstrate(admin.Substrate)});
-      else normalized.push(admin);
-    }
-    return normalized;
+  async getAdmins(collectionId: number, normalize = false): Promise<ICrossAccountId[]> {
+    const admins = (await this.helper.callRpc('api.rpc.unique.adminlist', [collectionId])).toHuman();
+
+    return normalize
+      ? admins.map((address: any) => {
+        return address.Substrate
+          ? {Substrate: this.helper.address.normalizeSubstrate(address.Substrate)}
+          : address;
+      })
+      : admins;
   }
 
   /**
-   * Get the normalized addresses added to the collection allow-list.
+   * Get the addresses added to the collection allow-list, optionally normalized.
    * @param collectionId ID of collection
+   * @param normalize whether to normalize the addresses to the default ss58 format
    * @example await getAllowList(1)
    * @returns array of allow-listed addresses
    */
-  async getAllowList(collectionId: number): Promise<ICrossAccountId[]> {
-    const normalized = [];
+  async getAllowList(collectionId: number, normalize = false): Promise<ICrossAccountId[]> {
     const allowListed = (await this.helper.callRpc('api.rpc.unique.allowlist', [collectionId])).toHuman();
-    for (const address of allowListed) {
-      if (address.Substrate) normalized.push({Substrate: this.helper.address.normalizeSubstrate(address.Substrate)});
-      else normalized.push(address);
-    }
-    return normalized;
+    return normalize
+      ? allowListed.map((address: any) => {
+        return address.Substrate
+          ? {Substrate: this.helper.address.normalizeSubstrate(address.Substrate)}
+          : address;
+      })
+      : allowListed;
   }
 
   /**
@@ -556,40 +577,36 @@
    *
    * @param signer keyring of signer
    * @param collectionId ID of collection
-   * @param label extra label for log
    * @example await helper.collection.burn(aliceKeyring, 3);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async burn(signer: TSigner, collectionId: number, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async burn(signer: TSigner, collectionId: number): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.destroyCollection', [collectionId],
-      true, `Unable to burn collection for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionDestroyed', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionDestroyed');
   }
 
   /**
-   * Sets the sponsor for the collection (Requires the Substrate address).
+   * Sets the sponsor for the collection (Requires the Substrate address). Needs confirmation by the sponsor.
    *
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param sponsorAddress Sponsor substrate address
-   * @param label extra label for log
    * @example setSponsor(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async setSponsor(signer: TSigner, collectionId: number, sponsorAddress: TSubstrateAccount, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async setSponsor(signer: TSigner, collectionId: number, sponsorAddress: TSubstrateAccount): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.setCollectionSponsor', [collectionId, sponsorAddress],
-      true, `Unable to set collection sponsor for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionSponsorSet', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionSponsorSet');
   }
 
   /**
@@ -597,19 +614,35 @@
    *
    * @param signer keyring of signer
    * @param collectionId ID of collection
-   * @param label extra label for log
    * @example confirmSponsorship(aliceKeyring, 10)
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async confirmSponsorship(signer: TSigner, collectionId: number, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async confirmSponsorship(signer: TSigner, collectionId: number): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.confirmSponsorship', [collectionId],
-      true, `Unable to confirm collection sponsorship for ${label}`,
+      true,
+    );
+
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'SponsorshipConfirmed');
+  }
+
+  /**
+   * Removes the sponsor of a collection, regardless if it consented or not.
+   *
+   * @param signer keyring of signer
+   * @param collectionId ID of collection
+   * @example removeSponsor(aliceKeyring, 10)
+   * @returns ```true``` if extrinsic success, otherwise ```false```
+   */
+  async removeSponsor(signer: TSigner, collectionId: number): Promise<boolean> {
+    const result = await this.helper.executeExtrinsic(
+      signer,
+      'api.tx.unique.removeCollectionSponsor', [collectionId],
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'SponsorshipConfirmed', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionSponsorRemoved');
   }
 
   /**
@@ -618,7 +651,6 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param limits collection limits object
-   * @param label extra label for log
    * @example
    * await setLimits(
    *   aliceKeyring,
@@ -630,15 +662,14 @@
    * )
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async setLimits(signer: TSigner, collectionId: number, limits: ICollectionLimits, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async setLimits(signer: TSigner, collectionId: number, limits: ICollectionLimits): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.setCollectionLimits', [collectionId, limits],
-      true, `Unable to set collection limits for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionLimitSet', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionLimitSet');
   }
 
   /**
@@ -647,19 +678,17 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param ownerAddress substrate address of new owner
-   * @param label extra label for log
    * @example changeOwner(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async changeOwner(signer: TSigner, collectionId: number, ownerAddress: TSubstrateAccount, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async changeOwner(signer: TSigner, collectionId: number, ownerAddress: TSubstrateAccount): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.changeCollectionOwner', [collectionId, ownerAddress],
-      true, `Unable to change collection owner for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionOwnedChanged', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionOwnedChanged');
   }
 
   /**
@@ -668,80 +697,71 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param adminAddressObj Administrator address (substrate or ethereum)
-   * @param label extra label for log
    * @example addAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async addAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async addAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.addCollectionAdmin', [collectionId, adminAddressObj],
-      true, `Unable to add collection admin for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminAdded', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminAdded');
   }
 
   /**
-   * Adds an address to allow list
+   * Removes a collection administrator.
+   *
    * @param signer keyring of signer
    * @param collectionId ID of collection
-   * @param addressObj address to add to the allow list
-   * @param label extra label for log
+   * @param adminAddressObj Administrator address (substrate or ethereum)
+   * @example removeAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async addToAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async removeAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
-      'api.tx.unique.addToAllowList', [collectionId, addressObj],
-      true, `Unable to add address to allow list for ${label}`,
+      'api.tx.unique.removeCollectionAdmin', [collectionId, adminAddressObj],
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressAdded');
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminRemoved');
   }
 
   /**
-   * Removes an address from allow list.
-   *
+   * Adds an address to allow list
    * @param signer keyring of signer
    * @param collectionId ID of collection
-   * @param addressObj address to be removed from allow list (substrate or ethereum)
-   * @param label extra label for log
-   * @example removeFromAllowList(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})
+   * @param addressObj address to add to the allow list
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async removeFromAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async addToAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
-      'api.tx.unique.removeFromAllowList', [collectionId, addressObj],
-      true, `Unable to remove address from allow list for ${label}`,
+      'api.tx.unique.addToAllowList', [collectionId, addressObj],
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressRemoved', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressAdded');
   }
 
   /**
-   * Removes a collection administrator.
+   * Removes an address from allow list
    *
    * @param signer keyring of signer
    * @param collectionId ID of collection
-   * @param adminAddressObj Administrator address (substrate or ethereum)
-   * @param label extra label for log
-   * @example removeAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})
+   * @param addressObj address to remove from the allow list
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async removeAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async removeFromAllowList(signer: TSigner, collectionId: number, addressObj: ICrossAccountId): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
-      'api.tx.unique.removeCollectionAdmin', [collectionId, adminAddressObj],
-      true, `Unable to remove collection admin for ${label}`,
+      'api.tx.unique.removeFromAllowList', [collectionId, addressObj],
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminRemoved', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'AllowListAddressRemoved');
   }
 
   /**
@@ -750,19 +770,17 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param permissions collection permissions object
-   * @param label extra label for log
    * @example setPermissions(aliceKeyring, 10, {access:'AllowList', mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true}});
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async setPermissions(signer: TSigner, collectionId: number, permissions: ICollectionPermissions, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async setPermissions(signer: TSigner, collectionId: number, permissions: ICollectionPermissions): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.setCollectionPermissions', [collectionId, permissions],
-      true, `Unable to set collection permissions for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionPermissionSet', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionPermissionSet');
   }
 
   /**
@@ -771,12 +789,11 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param permissions nesting permissions object
-   * @param label extra label for log
    * @example enableNesting(aliceKeyring, 10, {collectionAdmin: true, tokenOwner: true});
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async enableNesting(signer: TSigner, collectionId: number, permissions: INestingPermissions, label?: string): Promise<boolean> {
-    return await this.setPermissions(signer, collectionId, {nesting: permissions}, label);
+  async enableNesting(signer: TSigner, collectionId: number, permissions: INestingPermissions): Promise<boolean> {
+    return await this.setPermissions(signer, collectionId, {nesting: permissions});
   }
 
   /**
@@ -784,12 +801,11 @@
    *
    * @param signer keyring of signer
    * @param collectionId ID of collection
-   * @param label extra label for log
    * @example disableNesting(aliceKeyring, 10);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async disableNesting(signer: TSigner, collectionId: number, label?: string): Promise<boolean> {
-    return await this.setPermissions(signer, collectionId, {nesting: {tokenOwner: false, collectionAdmin: false}}, label);
+  async disableNesting(signer: TSigner, collectionId: number): Promise<boolean> {
+    return await this.setPermissions(signer, collectionId, {nesting: {tokenOwner: false, collectionAdmin: false}});
   }
 
   /**
@@ -798,19 +814,17 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param properties array of property objects
-   * @param label extra label for log
    * @example setProperties(aliceKeyring, 10, [{key: "gender", value: "male"}]);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async setProperties(signer: TSigner, collectionId: number, properties: IProperty[], label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async setProperties(signer: TSigner, collectionId: number, properties: IProperty[]): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.setCollectionProperties', [collectionId, properties],
-      true, `Unable to set collection properties for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertySet', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertySet');
   }
 
   /**
@@ -819,19 +833,17 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param propertyKeys array of property keys to delete
-   * @param label
    * @example deleteProperties(aliceKeyring, 10, ["gender", "age"]);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async deleteProperties(signer: TSigner, collectionId: number, propertyKeys: string[], label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async deleteProperties(signer: TSigner, collectionId: number, propertyKeys: string[]): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.deleteCollectionProperties', [collectionId, propertyKeys],
-      true, `Unable to delete collection properties for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertyDeleted', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertyDeleted');
   }
 
   /**
@@ -849,7 +861,7 @@
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.transfer', [addressObj, collectionId, tokenId, amount],
-      true, `Unable to transfer token #${tokenId} from collection #${collectionId}`,
+      true, // `Unable to transfer token #${tokenId} from collection #${collectionId}`,
     );
 
     return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, {Substrate: typeof signer === 'string' ? signer : signer.address}, addressObj, amount);
@@ -872,7 +884,7 @@
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.transferFrom', [fromAddressObj, toAddressObj, collectionId, tokenId, amount],
-      true, `Unable to transfer token #${tokenId} from collection #${collectionId}`,
+      true, // `Unable to transfer token #${tokenId} from collection #${collectionId}`,
     );
     return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, fromAddressObj, toAddressObj, amount);
   }
@@ -884,22 +896,20 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param tokenId ID of token
-   * @param label
    * @param amount amount of tokens to be burned. For NFT must be set to 1n
    * @example burnToken(aliceKeyring, 10, 5);
    * @returns ```true``` and burnt token number is extrinsic success. Otherwise ```false``` and ```null```
    */
-  async burnToken(signer: TSigner, collectionId: number, tokenId: number, label?: string, amount=1n): Promise<{
+  async burnToken(signer: TSigner, collectionId: number, tokenId: number, amount=1n): Promise<{
     success: boolean,
     token: number | null
   }> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
     const burnResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.burnItem', [collectionId, tokenId, amount],
-      true, `Unable to burn token for ${label}`,
+      true, // `Unable to burn token for ${label}`,
     );
-    const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult, label);
+    const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult);
     if (burnedTokens.tokens.length > 1) throw Error('Burned multiple tokens');
     return {success: burnedTokens.success, token: burnedTokens.tokens.length > 0 ? burnedTokens.tokens[0] : null};
   }
@@ -911,19 +921,17 @@
    * @param collectionId ID of collection
    * @param fromAddressObj address on behalf of which the token will be burnt
    * @param tokenId ID of token
-   * @param label
    * @param amount amount of tokens to be burned. For NFT must be set to 1n
    * @example burnTokenFrom(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."}, 5, {Ethereum: "0x9F0583DbB85..."})
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async burnTokenFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, tokenId: number, label?: string, amount=1n): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async burnTokenFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, tokenId: number, amount=1n): Promise<boolean> {
     const burnResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.burnFrom', [collectionId, fromAddressObj, tokenId, amount],
-      true, `Unable to burn token from for ${label}`,
+      true, // `Unable to burn token from for ${label}`,
     );
-    const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult, label);
+    const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult);
     return burnedTokens.success && burnedTokens.tokens.length > 0;
   }
 
@@ -933,28 +941,27 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param tokenId ID of token
-   * @param toAddressObj
-   * @param label
+   * @param toAddressObj Substrate or Ethereum address which gets approved use of the signer's tokens
    * @param amount amount of token to be approved. For NFT must be set to 1n
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, label?: string, amount=1n) {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {
     const approveResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.approve', [toAddressObj, collectionId, tokenId, amount],
-      true, `Unable to approve token for ${label}`,
+      true, // `Unable to approve token for ${label}`,
     );
 
-    return this.helper.util.findCollectionInEvents(approveResult.result.events, collectionId, 'common', 'Approved', label);
+    return this.helper.util.findCollectionInEvents(approveResult.result.events, collectionId, 'common', 'Approved');
   }
 
   /**
-   * Get the amount of token pieces approved to transfer
+   * Get the amount of token pieces approved to transfer or burn. Normally 0.
+   *
    * @param collectionId ID of collection
    * @param tokenId ID of token
-   * @param toAccountObj
-   * @param fromAccountObj
+   * @param toAccountObj address which is approved to use token pieces
+   * @param fromAccountObj address which may have allowed the use of its owned tokens
    * @example getTokenApprovedPieces(10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5ERZNF88Mm7UGfPP3mdG..."})
    * @returns number of approved to transfer pieces
    */
@@ -963,7 +970,8 @@
   }
 
   /**
-   * Get the last created token id
+   * Get the last created token ID in a collection
+   *
    * @param collectionId ID of collection
    * @example getLastTokenId(10);
    * @returns id of the last created token
@@ -974,6 +982,7 @@
 
   /**
    * Check if token exists
+   *
    * @param collectionId ID of collection
    * @param tokenId ID of token
    * @example isTokenExists(10, 20);
@@ -999,14 +1008,15 @@
 
   /**
    * Get token data
+   *
    * @param collectionId ID of collection
    * @param tokenId ID of token
-   * @param blockHashAt
-   * @param propertyKeys
+   * @param propertyKeys optionally filter the token properties to only these keys
+   * @param blockHashAt optionally query the data at some block with this hash
    * @example getToken(10, 5);
    * @returns human readable token data
    */
-  async getToken(collectionId: number, tokenId: number, blockHashAt?: string, propertyKeys?: string[]): Promise<{
+  async getToken(collectionId: number, tokenId: number, propertyKeys: string[] = [], blockHashAt?: string): Promise<{
     properties: IProperty[];
     owner: ICrossAccountId;
     normalizedOwner: ICrossAccountId;
@@ -1016,7 +1026,7 @@
       tokenData = await this.helper.callRpc('api.rpc.unique.tokenData', [collectionId, tokenId]);
     }
     else {
-      if(typeof propertyKeys === 'undefined') {
+      if(propertyKeys.length == 0) {
         const collection = (await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId])).toHuman();
         if(!collection) return null;
         propertyKeys = collection.tokenPropertyPermissions.map((x: ITokenPropertyPermission) => x.key);
@@ -1035,45 +1045,43 @@
 
   /**
    * Set permissions to change token properties
+   *
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param permissions permissions to change a property by the collection owner or admin
-   * @param label
    * @example setTokenPropertyPermissions(
    *   aliceKeyring, 10, [{key: "gender", permission: {tokenOwner: true, mutable: true, collectionAdmin: true}}]
    * )
    * @returns true if extrinsic success otherwise false
    */
-  async setTokenPropertyPermissions(signer: TSigner, collectionId: number, permissions: ITokenPropertyPermission[], label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async setTokenPropertyPermissions(signer: TSigner, collectionId: number, permissions: ITokenPropertyPermission[]): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.setTokenPropertyPermissions', [collectionId, permissions],
-      true, `Unable to set token property permissions for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'PropertyPermissionSet', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'PropertyPermissionSet');
   }
 
   /**
    * Set token properties
+   *
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param tokenId ID of token
-   * @param properties
-   * @param label
+   * @param properties key-value pairs of metadata which to add to a token. Keys must be permitted in the collection
    * @example setTokenProperties(aliceKeyring, 10, 5, [{key: "gender", value: "female"}, {key: "age", value: "23"}])
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async setTokenProperties(signer: TSigner, collectionId: number, tokenId: number, properties: IProperty[], label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `token #${tokenId} from collection #${collectionId}`;
+  async setTokenProperties(signer: TSigner, collectionId: number, tokenId: number, properties: IProperty[]): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.setTokenProperties', [collectionId, tokenId, properties],
-      true, `Unable to set token properties for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertySet', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertySet');
   }
 
   /**
@@ -1082,31 +1090,29 @@
    * @param collectionId ID of collection
    * @param tokenId ID of token
    * @param propertyKeys property keys to be deleted
-   * @param label
    * @example deleteTokenProperties(aliceKeyring, 10, 5, ["gender", "age"])
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async deleteTokenProperties(signer: TSigner, collectionId: number, tokenId: number, propertyKeys: string[], label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `token #${tokenId} from collection #${collectionId}`;
+  async deleteTokenProperties(signer: TSigner, collectionId: number, tokenId: number, propertyKeys: string[]): Promise<boolean> {
     const result = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.deleteTokenProperties', [collectionId, tokenId, propertyKeys],
-      true, `Unable to delete token properties for ${label}`,
+      true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertyDeleted', label);
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertyDeleted');
   }
 
   /**
    * Mint new collection
+   *
    * @param signer keyring of signer
    * @param collectionOptions basic collection options and properties
    * @param mode NFT or RFT type of a collection
-   * @param errorLabel
    * @example mintCollection(aliceKeyring, {name: 'New', description: "New collection", tokenPrefix: "NEW"}, "NFT")
    * @returns object of the created collection
    */
-  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT', errorLabel = 'Unable to mint collection'): Promise<UniqueCollectionBase> {
+  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT'): Promise<UniqueCollectionBase> {
     collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object
     collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};
     for (const key of ['name', 'description', 'tokenPrefix']) {
@@ -1115,16 +1121,16 @@
     const creationResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.createCollectionEx', [collectionOptions],
-      true, errorLabel,
+      true, // errorLabel,
     );
-    return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult, errorLabel));
+    return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult));
   }
 
-  getCollectionObject(collectionId: number): any {
+  getCollectionObject(_collectionId: number): any {
     return null;
   }
 
-  getTokenObject(collectionId: number, tokenId: number): any {
+  getTokenObject(_collectionId: number, _tokenId: number): any {
     return null;
   }
 }
@@ -1156,7 +1162,7 @@
    * Get token's owner
    * @param collectionId ID of collection
    * @param tokenId ID of token
-   * @param blockHashAt
+   * @param blockHashAt optionally query the data at the block with this hash
    * @example getTokenOwner(10, 5);
    * @returns Address in CrossAccountId format, e.g. {Substrate: "5DnSF6RRjwteE3BrCj..."}
    */
@@ -1238,7 +1244,7 @@
    * Get tokens nested in the provided token
    * @param collectionId ID of collection
    * @param tokenId ID of token
-   * @param blockHashAt
+   * @param blockHashAt optionally query the data at the block with this hash
    * @example getTokenChildren(10, 5);
    * @returns tokens whose depth of nesting is <= 5
    */
@@ -1260,15 +1266,14 @@
    * @param signer keyring of signer
    * @param tokenObj token to be nested
    * @param rootTokenObj token to be parent
-   * @param label
    * @example nestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4});
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async nestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, label='nest token'): Promise<boolean> {
+  async nestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken): Promise<boolean> {
     const rootTokenAddress = {Ethereum: this.helper.util.getNestingTokenAddress(rootTokenObj.collectionId, rootTokenObj.tokenId)};
     const result = await this.transferToken(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress);
     if(!result) {
-      throw Error(`Unable to nest token for ${label}`);
+      throw Error('Unable to nest token!');
     }
     return result;
   }
@@ -1279,15 +1284,14 @@
    * @param tokenObj token to unnest
    * @param rootTokenObj parent of a token
    * @param toAddressObj address of a new token owner
-   * @param label
    * @example unnestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4}, {Substrate: "5DyN4Y92vZCjv38fg..."});
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async unnestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, toAddressObj: ICrossAccountId, label='unnest token'): Promise<boolean> {
+  async unnestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, toAddressObj: ICrossAccountId): Promise<boolean> {
     const rootTokenAddress = {Ethereum: this.helper.util.getNestingTokenAddress(rootTokenObj.collectionId, rootTokenObj.tokenId)};
     const result = await this.transferTokenFrom(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress, toAddressObj);
     if(!result) {
-      throw Error(`Unable to unnest token for ${label}`);
+      throw Error('Unable to unnest token!');
     }
     return result;
   }
@@ -1296,7 +1300,6 @@
    * Mint new collection
    * @param signer keyring of signer
    * @param collectionOptions Collection options
-   * @param label
    * @example
    * mintCollection(aliceKeyring, {
    *   name: 'New',
@@ -1305,19 +1308,17 @@
    * })
    * @returns object of the created collection
    */
-  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, label = 'new collection'): Promise<UniqueNFTCollection> {
-    return await super.mintCollection(signer, collectionOptions, 'NFT', `Unable to mint NFT collection for ${label}`) as UniqueNFTCollection;
+  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions): Promise<UniqueNFTCollection> {
+    return await super.mintCollection(signer, collectionOptions, 'NFT') as UniqueNFTCollection;
   }
 
   /**
    * Mint new token
    * @param signer keyring of signer
    * @param data token data
-   * @param label
    * @returns created token object
    */
-  async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; properties?: IProperty[]; }, label?: string): Promise<UniqueNFTToken> {
-    if(typeof label === 'undefined') label = `collection #${data.collectionId}`;
+  async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; properties?: IProperty[]; }): Promise<UniqueNFTToken> {
     const creationResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {
@@ -1325,9 +1326,9 @@
           properties: data.properties,
         },
       }],
-      true, `Unable to mint NFT token for ${label}`,
+      true,
     );
-    const createdTokens = this.helper.util.extractTokensFromCreationResult(creationResult, label);
+    const createdTokens = this.helper.util.extractTokensFromCreationResult(creationResult);
     if (createdTokens.tokens.length > 1) throw Error('Minted multiple tokens');
     if (createdTokens.tokens.length < 1) throw Error('No tokens minted');
     return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);
@@ -1338,7 +1339,6 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param tokens array of tokens with owner and properties
-   * @param label
    * @example
    * mintMultipleTokens(aliceKeyring, 10, [{
    *     owner: {Substrate: "5DyN4Y92vZCjv38fg..."},
@@ -1349,15 +1349,14 @@
    * }]);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[], label?: string): Promise<UniqueNFTToken[]> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]): Promise<UniqueNFTToken[]> {
     const creationResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.createMultipleItemsEx', [collectionId, {NFT: tokens}],
-      true, `Unable to mint NFT tokens for ${label}`,
+      true,
     );
     const collection = this.getCollectionObject(collectionId);
-    return this.helper.util.extractTokensFromCreationResult(creationResult, label).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
+    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
   }
 
   /**
@@ -1366,7 +1365,6 @@
    * @param collectionId ID of collection
    * @param owner tokens owner
    * @param tokens array of tokens with owner and properties
-   * @param label
    * @example
    * mintMultipleTokensWithOneOwner(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...", [{
    *   properties: [{
@@ -1379,8 +1377,7 @@
    * }]);
    * @returns array of newly created tokens
    */
-  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {properties?: IProperty[]}[], label?: string): Promise<UniqueNFTToken[]> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {properties?: IProperty[]}[]): Promise<UniqueNFTToken[]> {
     const rawTokens = [];
     for (const token of tokens) {
       const raw = {NFT: {properties: token.properties}};
@@ -1389,23 +1386,10 @@
     const creationResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],
-      true, `Unable to mint NFT tokens for ${label}`,
+      true,
     );
     const collection = this.getCollectionObject(collectionId);
-    return this.helper.util.extractTokensFromCreationResult(creationResult, label).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
-  }
-
-  /**
-   * Destroys a concrete instance of NFT.
-   * @param signer keyring of signer
-   * @param collectionId ID of collection
-   * @param tokenId ID of token
-   * @param label
-   * @example burnToken(aliceKeyring, 10, 5);
-   * @returns ```true``` and burnt token number is extrinsic success. Otherwise ```false``` and ```null```
-   */
-  async burnToken(signer: IKeyringPair, collectionId: number, tokenId: number, label?: string): Promise<{ success: boolean; token: number | null; }> {
-    return await super.burnToken(signer, collectionId, tokenId, label, 1n);
+    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
   }
 
   /**
@@ -1415,12 +1399,11 @@
    * @param collectionId ID of collection
    * @param tokenId ID of token
    * @param toAddressObj address to approve
-   * @param label
    * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, label?: string, amount=1n) {
-    return super.approveToken(signer, collectionId, tokenId, toAddressObj, label, amount);
+  async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId) {
+    return super.approveToken(signer, collectionId, tokenId, toAddressObj, 1n);
   }
 }
 
@@ -1480,7 +1463,7 @@
    * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, 2000n)
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId, amount=100n): Promise<boolean> {
+  async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId, amount=1n): Promise<boolean> {
     return await super.transferToken(signer, collectionId, tokenId, addressObj, amount);
   }
 
@@ -1495,7 +1478,7 @@
    * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5DfhbVfww7ThF8q6f3i..."}, 2000n)
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=100n): Promise<boolean> {
+  async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {
     return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, amount);
   }
 
@@ -1503,7 +1486,6 @@
    * Mint new collection
    * @param signer keyring of signer
    * @param collectionOptions Collection options
-   * @param label
    * @example
    * mintCollection(aliceKeyring, {
    *   name: 'New',
@@ -1512,20 +1494,18 @@
    * })
    * @returns object of the created collection
    */
-  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, label = 'new collection'): Promise<UniqueRFTCollection> {
-    return await super.mintCollection(signer, collectionOptions, 'RFT', `Unable to mint RFT collection for ${label}`) as UniqueRFTCollection;
+  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions): Promise<UniqueRFTCollection> {
+    return await super.mintCollection(signer, collectionOptions, 'RFT') as UniqueRFTCollection;
   }
 
   /**
    * Mint new token
    * @param signer keyring of signer
    * @param data token data
-   * @param label
    * @example mintToken(aliceKeyring, {collectionId: 10, owner: {Substrate: '5GHoZe9c73RYbVzq...'}, pieces: 10000n});
    * @returns created token object
    */
-  async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; pieces: bigint; properties?: IProperty[]; }, label?: string): Promise<UniqueRFTToken> {
-    if(typeof label === 'undefined') label = `collection #${data.collectionId}`;
+  async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; pieces: bigint; properties?: IProperty[]; }): Promise<UniqueRFTToken> {
     const creationResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {
@@ -1534,24 +1514,23 @@
           properties: data.properties,
         },
       }],
-      true, `Unable to mint RFT token for ${label}`,
+      true,
     );
-    const createdTokens = this.helper.util.extractTokensFromCreationResult(creationResult, label);
+    const createdTokens = this.helper.util.extractTokensFromCreationResult(creationResult);
     if (createdTokens.tokens.length > 1) throw Error('Minted multiple tokens');
     if (createdTokens.tokens.length < 1) throw Error('No tokens minted');
     return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);
   }
 
-  async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[], label?: string): Promise<UniqueRFTToken[]> {
+  async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[]): Promise<UniqueRFTToken[]> {
     throw Error('Not implemented');
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
     const creationResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.createMultipleItemsEx', [collectionId, {RefungibleMultipleOwners: tokens}],
-      true, `Unable to mint RFT tokens for ${label}`,
+      true, // `Unable to mint RFT tokens for ${label}`,
     );
     const collection = this.getCollectionObject(collectionId);
-    return this.helper.util.extractTokensFromCreationResult(creationResult, label).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
+    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
   }
 
   /**
@@ -1560,12 +1539,10 @@
    * @param collectionId ID of collection
    * @param owner tokens owner
    * @param tokens array of tokens with properties and pieces
-   * @param label
    * @example mintMultipleTokensWithOneOwner(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, [{pieces: 100000n, properties: [{key: "gender", value: "male"}]}]);
    * @returns array of newly created RFT tokens
    */
-  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {pieces: bigint, properties?: IProperty[]}[], label?: string): Promise<UniqueRFTToken[]> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {pieces: bigint, properties?: IProperty[]}[]): Promise<UniqueRFTToken[]> {
     const rawTokens = [];
     for (const token of tokens) {
       const raw = {ReFungible: {pieces: token.pieces, properties: token.properties}};
@@ -1574,10 +1551,10 @@
     const creationResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],
-      true, `Unable to mint RFT tokens for ${label}`,
+      true,
     );
     const collection = this.getCollectionObject(collectionId);
-    return this.helper.util.extractTokensFromCreationResult(creationResult, label).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
+    return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
   }
 
   /**
@@ -1585,13 +1562,12 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param tokenId ID of token
-   * @param label
    * @param amount number of pieces to be burnt
    * @example burnToken(aliceKeyring, 10, 5);
    * @returns ```true``` and burnt token number is extrinsic success. Otherwise ```false``` and ```null```
    */
-  async burnToken(signer: IKeyringPair, collectionId: number, tokenId: number, label?: string, amount=100n): Promise<{ success: boolean; token: number | null; }> {
-    return await super.burnToken(signer, collectionId, tokenId, label, amount);
+  async burnToken(signer: IKeyringPair, collectionId: number, tokenId: number, amount=1n): Promise<{ success: boolean; token: number | null; }> {
+    return await super.burnToken(signer, collectionId, tokenId, amount);
   }
 
   /**
@@ -1601,13 +1577,12 @@
    * @param collectionId ID of collection
    * @param tokenId ID of token
    * @param toAddressObj address to approve
-   * @param label
    * @param amount number of pieces to be approved
    * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5GHoZe9c73RYbVzq..."}, "", 10000n);
    * @returns true if the token success, otherwise false
    */
-  async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, label?: string, amount=100n) {
-    return super.approveToken(signer, collectionId, tokenId, toAddressObj, label, amount);
+  async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {
+    return super.approveToken(signer, collectionId, tokenId, toAddressObj, amount);
   }
 
   /**
@@ -1627,20 +1602,18 @@
    * @param collectionId ID of collection
    * @param tokenId ID of token
    * @param amount new number of pieces
-   * @param label
    * @example repartitionToken(aliceKeyring, 10, 5, 12345n);
    * @returns true if the repartion was success, otherwise false
    */
-  async repartitionToken(signer: TSigner, collectionId: number, tokenId: number, amount: bigint, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async repartitionToken(signer: TSigner, collectionId: number, tokenId: number, amount: bigint): Promise<boolean> {
     const currentAmount = await this.getTokenTotalPieces(collectionId, tokenId);
     const repartitionResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.repartition', [collectionId, tokenId, amount],
-      true, `Unable to repartition RFT token for ${label}`,
+      true,
     );
-    if(currentAmount < amount) return this.helper.util.findCollectionInEvents(repartitionResult.result.events, collectionId, 'common', 'ItemCreated', label);
-    return this.helper.util.findCollectionInEvents(repartitionResult.result.events, collectionId, 'common', 'ItemDestroyed', label);
+    if(currentAmount < amount) return this.helper.util.findCollectionInEvents(repartitionResult.result.events, collectionId, 'common', 'ItemCreated');
+    return this.helper.util.findCollectionInEvents(repartitionResult.result.events, collectionId, 'common', 'ItemDestroyed');
   }
 }
 
@@ -1661,7 +1634,6 @@
    * @param signer keyring of signer
    * @param collectionOptions Collection options
    * @param decimalPoints number of token decimals
-   * @param errorLabel
    * @example
    * mintCollection(aliceKeyring, {
    *   name: 'New',
@@ -1670,7 +1642,7 @@
    * }, 18)
    * @returns newly created fungible collection
    */
-  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, decimalPoints = 0, errorLabel = 'Unable to mint collection'): Promise<UniqueFTCollection> {
+  async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, decimalPoints = 0): Promise<UniqueFTCollection> {
     collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object
     if(collectionOptions.tokenPropertyPermissions) throw Error('Fungible collections has no tokenPropertyPermissions');
     collectionOptions.mode = {fungible: decimalPoints};
@@ -1680,9 +1652,9 @@
     const creationResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.createCollectionEx', [collectionOptions],
-      true, errorLabel,
+      true,
     );
-    return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult, errorLabel));
+    return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult));
   }
 
   /**
@@ -1691,12 +1663,10 @@
    * @param collectionId ID of collection
    * @param owner address owner of new tokens
    * @param amount amount of tokens to be meanted
-   * @param label
    * @example mintTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq"}, 1000n);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async mintTokens(signer: TSigner, collectionId: number, owner: ICrossAccountId | string, amount: bigint, label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async mintTokens(signer: TSigner, collectionId: number, owner: ICrossAccountId | string, amount: bigint): Promise<boolean> {
     const creationResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.createItem', [collectionId, (typeof owner === 'string') ? {Substrate: owner} : owner, {
@@ -1704,9 +1674,9 @@
           value: amount,
         },
       }],
-      true, `Unable to mint fungible tokens for ${label}`,
+      true, // `Unable to mint fungible tokens for ${label}`,
     );
-    return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated', label);
+    return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated');
   }
 
   /**
@@ -1715,11 +1685,9 @@
    * @param collectionId ID of collection
    * @param owner tokens owner
    * @param tokens array of tokens with properties and pieces
-   * @param label
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {value: bigint}[], label?: string): Promise<boolean> {
-    if(typeof label === 'undefined') label = `collection #${collectionId}`;
+  async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {value: bigint}[]): Promise<boolean> {
     const rawTokens = [];
     for (const token of tokens) {
       const raw = {Fungible: {Value: token.value}};
@@ -1728,9 +1696,9 @@
     const creationResult = await this.helper.executeExtrinsic(
       signer,
       'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],
-      true, `Unable to mint RFT tokens for ${label}`,
+      true,
     );
-    return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated', label);
+    return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated');
   }
 
   /**
@@ -1758,12 +1726,12 @@
    * Transfer tokens to address
    * @param signer keyring of signer
    * @param collectionId ID of collection
-   * @param toAddressObj address recepient
+   * @param toAddressObj address recipient
    * @param amount amount of tokens to be sent
    * @example transfer(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async transfer(signer: TSigner, collectionId: number, toAddressObj: ICrossAccountId, amount: bigint) {
+  async transfer(signer: TSigner, collectionId: number, toAddressObj: ICrossAccountId, amount=1n) {
     return await super.transferToken(signer, collectionId, 0, toAddressObj, amount);
   }
 
@@ -1777,7 +1745,7 @@
    * @example transferFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, {Substrate: "5DfhbVfww7ThF8q6f3ij..."}, 10000n);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async transferFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount: bigint) {
+  async transferFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {
     return await super.transferTokenFrom(signer, collectionId, 0, fromAddressObj, toAddressObj, amount);
   }
 
@@ -1786,12 +1754,11 @@
    * @param signer keyring of signer
    * @param collectionId ID of collection
    * @param amount amount of tokens to be destroyed
-   * @param label
    * @example burnTokens(aliceKeyring, 10, 1000n);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async burnTokens(signer: IKeyringPair, collectionId: number, amount=100n, label?: string): Promise<boolean> {
-    return (await super.burnToken(signer, collectionId, 0, label, amount)).success;
+  async burnTokens(signer: IKeyringPair, collectionId: number, amount=1n): Promise<boolean> {
+    return (await super.burnToken(signer, collectionId, 0, amount)).success;
   }
 
   /**
@@ -1800,12 +1767,11 @@
    * @param collectionId ID of collection
    * @param fromAddressObj address on behalf of which tokens will be burnt
    * @param amount amount of tokens to be burnt
-   * @param label
    * @example burnTokensFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async burnTokensFrom(signer: IKeyringPair, collectionId: number, fromAddressObj: ICrossAccountId, amount=100n, label?: string): Promise<boolean> {
-    return await super.burnTokenFrom(signer, collectionId, fromAddressObj, 0, label, amount);
+  async burnTokensFrom(signer: IKeyringPair, collectionId: number, fromAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {
+    return await super.burnTokenFrom(signer, collectionId, fromAddressObj, 0, amount);
   }
 
   /**
@@ -1824,12 +1790,11 @@
    * @param collectionId ID of collection
    * @param toAddressObj address to be approved
    * @param amount amount of tokens to be approved
-   * @param label
    * @example approveTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n)
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  async approveTokens(signer: IKeyringPair, collectionId: number, toAddressObj: ICrossAccountId, amount=100n, label?: string) {
-    return super.approveToken(signer, collectionId, 0, toAddressObj, label, amount);
+  async approveTokens(signer: IKeyringPair, collectionId: number, toAddressObj: ICrossAccountId, amount=1n) {
+    return super.approveToken(signer, collectionId, 0, toAddressObj, amount);
   }
 
   /**
@@ -1881,6 +1846,13 @@
     return blockHash;
   }
 
+  // TODO add docs
+  async getBlock(blockHashOrNumber: string | number): Promise<IBlock | null> {
+    const blockHash = typeof blockHashOrNumber === 'string' ? blockHashOrNumber : await this.getBlockHashByNumber(blockHashOrNumber);
+    if (!blockHash) return null;
+    return (await this.helper.callRpc('api.rpc.chain.getBlock', [blockHash])).toHuman().block;
+  }
+
   /**
    * Get account nonce
    * @param address substrate address
@@ -1915,6 +1887,16 @@
   }
 
   /**
+   * Get full substrate balance including free, miscFrozen, feeFrozen, and reserved
+   * @param address substrate address
+   * @returns
+   */
+  async getSubstrateFull(address: TSubstrateAccount): Promise<ISubstrateBalance> {
+    const accountInfo = (await this.helper.callRpc('api.query.system.account', [address])).data;
+    return {free: accountInfo.free.toBigInt(), miscFrozen: accountInfo.miscFrozen.toBigInt(), feeFrozen: accountInfo.feeFrozen.toBigInt(), reserved: accountInfo.reserved.toBigInt()};
+  }
+
+  /**
    * Get ethereum address balance
    * @param address ethereum address
    * @example getEthereum("0x9F0583DbB855d...")
@@ -1927,13 +1909,13 @@
   /**
    * Transfer tokens to substrate address
    * @param signer keyring of signer
-   * @param address substrate address of a recepient
+   * @param address substrate address of a recipient
    * @param amount amount of tokens to be transfered
    * @example transferToSubstrate(aliceKeyring, "5GrwvaEF5zXb26Fz...", 100_000_000_000n);
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
   async transferToSubstrate(signer: TSigner, address: TSubstrateAccount, amount: bigint | string): Promise<boolean> {
-    const result = await this.helper.executeExtrinsic(signer, 'api.tx.balances.transfer', [address, amount], true, `Unable to transfer balance from ${this.helper.getSignerAddress(signer)} to ${address}`);
+    const result = await this.helper.executeExtrinsic(signer, 'api.tx.balances.transfer', [address, amount], true/*, `Unable to transfer balance from ${this.helper.getSignerAddress(signer)} to ${address}`*/);
 
     let transfer = {from: null, to: null, amount: 0n} as any;
     result.result.events.forEach(({event: {data, method, section}}) => {
@@ -2000,7 +1982,59 @@
   }
 }
 
+class StakingGroup extends HelperGroup {
+  /**
+   * Stake tokens for App Promotion
+   * @param signer keyring of signer
+   * @param amountToStake amount of tokens to stake
+   * @param label extra label for log
+   * @returns
+   */
+  async stake(signer: TSigner, amountToStake: bigint, label?: string): Promise<boolean> {
+    if(typeof label === 'undefined') label = `${signer.address} amount: ${amountToStake}`;
+    const stakeResult = await this.helper.executeExtrinsic(
+      signer, 'api.tx.appPromotion.stake',
+      [amountToStake], true,
+    );
+    // TODO extract info from stakeResult
+    return true;
+  }
 
+  /**
+   * Unstake tokens for App Promotion
+   * @param signer keyring of signer
+   * @param amountToUnstake amount of tokens to unstake
+   * @param label extra label for log
+   * @returns block number where balances will be unlocked
+   */
+  async unstake(signer: TSigner, label?: string): Promise<number> {
+    if(typeof label === 'undefined') label = `${signer.address}`;
+    const unstakeResult = await this.helper.executeExtrinsic(
+      signer, 'api.tx.appPromotion.unstake',
+      [], true,
+    );
+    // TODO extract block number fron events
+    return 1;
+  }
+
+  async getTotalStaked(address?: ICrossAccountId): Promise<bigint> {
+    if (address) return (await this.helper.callRpc('api.rpc.appPromotion.totalStaked', [address])).toBigInt();
+    return (await this.helper.callRpc('api.rpc.appPromotion.totalStaked')).toBigInt();
+  }
+
+  async getTotalStakedPerBlock(address: ICrossAccountId): Promise<bigint[][]> {
+    return (await this.helper.callRpc('api.rpc.appPromotion.totalStakedPerBlock', [address])).map(([block, amount]: any[]) => [block.toBigInt(), amount.toBigInt()]);
+  }
+
+  async getPendingUnstake(address: ICrossAccountId): Promise<bigint> {
+    return (await this.helper.callRpc('api.rpc.appPromotion.pendingUnstake', [address])).toBigInt();
+  }
+
+  async getPendingUnstakePerBlock(address: ICrossAccountId): Promise<bigint[][]> {
+    return (await this.helper.callRpc('api.rpc.appPromotion.pendingUnstakePerBlock', [address])).map(([block, amount]: any[]) => [block.toBigInt(), amount.toBigInt()]);
+  }
+}
+
 export class UniqueHelper extends ChainHelperBase {
   chain: ChainGroup;
   balance: BalanceGroup;
@@ -2009,6 +2043,7 @@
   nft: NFTGroup;
   rft: RFTGroup;
   ft: FTGroup;
+  staking: StakingGroup;
 
   constructor(logger?: ILogger) {
     super(logger);
@@ -2019,6 +2054,7 @@
     this.nft = new NFTGroup(this);
     this.rft = new RFTGroup(this);
     this.ft = new FTGroup(this);
+    this.staking = new StakingGroup(this);
   }
 }
 
@@ -2056,64 +2092,72 @@
     return await this.helper.collection.getEffectiveLimits(this.collectionId);
   }
 
-  async setSponsor(signer: TSigner, sponsorAddress: TSubstrateAccount, label?: string) {
-    return await this.helper.collection.setSponsor(signer, this.collectionId, sponsorAddress, label);
+  async setSponsor(signer: TSigner, sponsorAddress: TSubstrateAccount) {
+    return await this.helper.collection.setSponsor(signer, this.collectionId, sponsorAddress);
   }
 
-  async confirmSponsorship(signer: TSigner, label?: string) {
-    return await this.helper.collection.confirmSponsorship(signer, this.collectionId, label);
+  async confirmSponsorship(signer: TSigner) {
+    return await this.helper.collection.confirmSponsorship(signer, this.collectionId);
   }
 
-  async setLimits(signer: TSigner, limits: ICollectionLimits, label?: string) {
-    return await this.helper.collection.setLimits(signer, this.collectionId, limits, label);
+  async removeSponsor(signer: TSigner) {
+    return await this.helper.collection.removeSponsor(signer, this.collectionId);
   }
 
-  async changeOwner(signer: TSigner, ownerAddress: TSubstrateAccount, label?: string) {
-    return await this.helper.collection.changeOwner(signer, this.collectionId, ownerAddress, label);
+  async setLimits(signer: TSigner, limits: ICollectionLimits) {
+    return await this.helper.collection.setLimits(signer, this.collectionId, limits);
+  }
+
+  async changeOwner(signer: TSigner, ownerAddress: TSubstrateAccount) {
+    return await this.helper.collection.changeOwner(signer, this.collectionId, ownerAddress);
+  }
+
+  async addAdmin(signer: TSigner, adminAddressObj: ICrossAccountId) {
+    return await this.helper.collection.addAdmin(signer, this.collectionId, adminAddressObj);
   }
 
-  async addAdmin(signer: TSigner, adminAddressObj: ICrossAccountId, label?: string) {
-    return await this.helper.collection.addAdmin(signer, this.collectionId, adminAddressObj, label);
+  async enableCertainPermissions(signer: TSigner, accessMode: 'AllowList' | 'Normal' | undefined = 'AllowList', mintMode: boolean | undefined = true) {
+    return await this.setPermissions(signer, {access: accessMode, mintMode: mintMode});
   }
 
-  async addToAllowList(signer: TSigner, addressObj: ICrossAccountId, label?: string) {
-    return await this.helper.collection.addToAllowList(signer, this.collectionId, addressObj, label);
+  async addToAllowList(signer: TSigner, addressObj: ICrossAccountId) {
+    return await this.helper.collection.addToAllowList(signer, this.collectionId, addressObj);
   }
 
-  async removeFromAllowList(signer: TSigner, addressObj: ICrossAccountId, label?: string) {
-    return await this.helper.collection.removeFromAllowList(signer, this.collectionId, addressObj, label);
+  async removeFromAllowList(signer: TSigner, addressObj: ICrossAccountId) {
+    return await this.helper.collection.removeFromAllowList(signer, this.collectionId, addressObj);
   }
 
-  async removeAdmin(signer: TSigner, adminAddressObj: ICrossAccountId, label?: string) {
-    return await this.helper.collection.removeAdmin(signer, this.collectionId, adminAddressObj, label);
+  async removeAdmin(signer: TSigner, adminAddressObj: ICrossAccountId) {
+    return await this.helper.collection.removeAdmin(signer, this.collectionId, adminAddressObj);
   }
 
-  async setProperties(signer: TSigner, properties: IProperty[], label?: string) {
-    return await this.helper.collection.setProperties(signer, this.collectionId, properties, label);
+  async setProperties(signer: TSigner, properties: IProperty[]) {
+    return await this.helper.collection.setProperties(signer, this.collectionId, properties);
   }
 
-  async deleteProperties(signer: TSigner, propertyKeys: string[], label?: string) {
-    return await this.helper.collection.deleteProperties(signer, this.collectionId, propertyKeys, label);
+  async deleteProperties(signer: TSigner, propertyKeys: string[]) {
+    return await this.helper.collection.deleteProperties(signer, this.collectionId, propertyKeys);
   }
 
   async getTokenNextSponsored(tokenId: number, addressObj: ICrossAccountId) {
     return await this.helper.collection.getTokenNextSponsored(this.collectionId, tokenId, addressObj);
   }
 
-  async setPermissions(signer: TSigner, permissions: ICollectionPermissions, label?: string) {
-    return await this.helper.collection.setPermissions(signer, this.collectionId, permissions, label);
+  async setPermissions(signer: TSigner, permissions: ICollectionPermissions) {
+    return await this.helper.collection.setPermissions(signer, this.collectionId, permissions);
   }
 
-  async enableNesting(signer: TSigner, permissions: INestingPermissions, label?: string) {
-    return await this.helper.collection.enableNesting(signer, this.collectionId, permissions, label);
+  async enableNesting(signer: TSigner, permissions: INestingPermissions) {
+    return await this.helper.collection.enableNesting(signer, this.collectionId, permissions);
   }
 
-  async disableNesting(signer: TSigner, label?: string) {
-    return await this.helper.collection.disableNesting(signer, this.collectionId, label);
+  async disableNesting(signer: TSigner) {
+    return await this.helper.collection.disableNesting(signer, this.collectionId);
   }
 
-  async burn(signer: TSigner, label?: string) {
-    return await this.helper.collection.burn(signer, this.collectionId, label);
+  async burn(signer: TSigner) {
+    return await this.helper.collection.burn(signer, this.collectionId);
   }
 }
 
@@ -2128,7 +2172,7 @@
   }
 
   async getToken(tokenId: number, blockHashAt?: string) {
-    return await this.helper.nft.getToken(this.collectionId, tokenId, blockHashAt);
+    return await this.helper.nft.getToken(this.collectionId, tokenId, [], blockHashAt);
   }
 
   async getTokenOwner(tokenId: number, blockHashAt?: string) {
@@ -2151,44 +2195,44 @@
     return await this.helper.nft.transferTokenFrom(signer, this.collectionId, tokenId, fromAddressObj, toAddressObj);
   }
 
-  async approveToken(signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId, label?: string) {
-    return await this.helper.nft.approveToken(signer, this.collectionId, tokenId, toAddressObj, label);
+  async approveToken(signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId) {
+    return await this.helper.nft.approveToken(signer, this.collectionId, tokenId, toAddressObj);
   }
 
   async isTokenApproved(tokenId: number, toAddressObj: ICrossAccountId) {
     return await this.helper.nft.isTokenApproved(this.collectionId, tokenId, toAddressObj);
   }
 
-  async mintToken(signer: TSigner, owner: ICrossAccountId, properties?: IProperty[], label?: string) {
-    return await this.helper.nft.mintToken(signer, {collectionId: this.collectionId, owner, properties}, label);
+  async mintToken(signer: TSigner, owner: ICrossAccountId, properties?: IProperty[]) {
+    return await this.helper.nft.mintToken(signer, {collectionId: this.collectionId, owner, properties});
   }
 
-  async mintMultipleTokens(signer: TSigner, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[], label?: string) {
-    return await this.helper.nft.mintMultipleTokens(signer, this.collectionId, tokens, label);
+  async mintMultipleTokens(signer: TSigner, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]) {
+    return await this.helper.nft.mintMultipleTokens(signer, this.collectionId, tokens);
   }
 
-  async burnToken(signer: TSigner, tokenId: number, label?: string) {
-    return await this.helper.nft.burnToken(signer, this.collectionId, tokenId, label);
+  async burnToken(signer: TSigner, tokenId: number) {
+    return await this.helper.nft.burnToken(signer, this.collectionId, tokenId);
   }
 
-  async setTokenProperties(signer: TSigner, tokenId: number, properties: IProperty[], label?: string) {
-    return await this.helper.nft.setTokenProperties(signer, this.collectionId, tokenId, properties, label);
+  async setTokenProperties(signer: TSigner, tokenId: number, properties: IProperty[]) {
+    return await this.helper.nft.setTokenProperties(signer, this.collectionId, tokenId, properties);
   }
 
-  async deleteTokenProperties(signer: TSigner, tokenId: number, propertyKeys: string[], label?: string) {
-    return await this.helper.nft.deleteTokenProperties(signer, this.collectionId, tokenId, propertyKeys, label);
+  async deleteTokenProperties(signer: TSigner, tokenId: number, propertyKeys: string[]) {
+    return await this.helper.nft.deleteTokenProperties(signer, this.collectionId, tokenId, propertyKeys);
   }
 
-  async setTokenPropertyPermissions(signer: TSigner, permissions: ITokenPropertyPermission[], label?: string) {
-    return await this.helper.nft.setTokenPropertyPermissions(signer, this.collectionId, permissions, label);
+  async setTokenPropertyPermissions(signer: TSigner, permissions: ITokenPropertyPermission[]) {
+    return await this.helper.nft.setTokenPropertyPermissions(signer, this.collectionId, permissions);
   }
 
-  async nestToken(signer: TSigner, tokenId: number, toTokenObj: IToken, label?: string) {
-    return await this.helper.nft.nestToken(signer, {collectionId: this.collectionId, tokenId}, toTokenObj, label);
+  async nestToken(signer: TSigner, tokenId: number, toTokenObj: IToken) {
+    return await this.helper.nft.nestToken(signer, {collectionId: this.collectionId, tokenId}, toTokenObj);
   }
 
-  async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: IToken, toAddressObj: ICrossAccountId, label?: string) {
-    return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj, label);
+  async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {
+    return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);
   }
 }
 
@@ -2214,59 +2258,59 @@
     return await this.helper.rft.getTokenTotalPieces(this.collectionId, tokenId);
   }
 
-  async transferToken(signer: TSigner, tokenId: number, addressObj: ICrossAccountId, amount=100n) {
+  async transferToken(signer: TSigner, tokenId: number, addressObj: ICrossAccountId, amount=1n) {
     return await this.helper.rft.transferToken(signer, this.collectionId, tokenId, addressObj, amount);
   }
 
-  async transferTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=100n) {
+  async transferTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {
     return await this.helper.rft.transferTokenFrom(signer, this.collectionId, tokenId, fromAddressObj, toAddressObj, amount);
   }
 
-  async approveToken(signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId, amount=100n, label?: string) {
-    return await this.helper.rft.approveToken(signer, this.collectionId, tokenId, toAddressObj, label, amount);
+  async approveToken(signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {
+    return await this.helper.rft.approveToken(signer, this.collectionId, tokenId, toAddressObj, amount);
   }
 
   async getTokenApprovedPieces(tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {
     return await this.helper.rft.getTokenApprovedPieces(this.collectionId, tokenId, toAddressObj, fromAddressObj);
   }
 
-  async repartitionToken(signer: TSigner, tokenId: number, amount: bigint, label?: string) {
-    return await this.helper.rft.repartitionToken(signer, this.collectionId, tokenId, amount, label);
+  async repartitionToken(signer: TSigner, tokenId: number, amount: bigint) {
+    return await this.helper.rft.repartitionToken(signer, this.collectionId, tokenId, amount);
   }
 
-  async mintToken(signer: TSigner, owner: ICrossAccountId, pieces=100n, properties?: IProperty[], label?: string) {
-    return await this.helper.rft.mintToken(signer, {collectionId: this.collectionId, owner, pieces, properties}, label);
+  async mintToken(signer: TSigner, owner: ICrossAccountId, pieces=100n, properties?: IProperty[]) {
+    return await this.helper.rft.mintToken(signer, {collectionId: this.collectionId, owner, pieces, properties});
   }
 
-  async mintMultipleTokens(signer: TSigner, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[], label?: string) {
-    return await this.helper.rft.mintMultipleTokens(signer, this.collectionId, tokens, label);
+  async mintMultipleTokens(signer: TSigner, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[]) {
+    return await this.helper.rft.mintMultipleTokens(signer, this.collectionId, tokens);
   }
 
-  async burnToken(signer: TSigner, tokenId: number, amount=100n, label?: string) {
-    return await this.helper.rft.burnToken(signer, this.collectionId, tokenId, label, amount);
+  async burnToken(signer: TSigner, tokenId: number, amount=1n) {
+    return await this.helper.rft.burnToken(signer, this.collectionId, tokenId, amount);
   }
 
-  async setTokenProperties(signer: TSigner, tokenId: number, properties: IProperty[], label?: string) {
-    return await this.helper.rft.setTokenProperties(signer, this.collectionId, tokenId, properties, label);
+  async setTokenProperties(signer: TSigner, tokenId: number, properties: IProperty[]) {
+    return await this.helper.rft.setTokenProperties(signer, this.collectionId, tokenId, properties);
   }
 
-  async deleteTokenProperties(signer: TSigner, tokenId: number, propertyKeys: string[], label?: string) {
-    return await this.helper.rft.deleteTokenProperties(signer, this.collectionId, tokenId, propertyKeys, label);
+  async deleteTokenProperties(signer: TSigner, tokenId: number, propertyKeys: string[]) {
+    return await this.helper.rft.deleteTokenProperties(signer, this.collectionId, tokenId, propertyKeys);
   }
 
-  async setTokenPropertyPermissions(signer: TSigner, permissions: ITokenPropertyPermission[], label?: string) {
-    return await this.helper.rft.setTokenPropertyPermissions(signer, this.collectionId, permissions, label);
+  async setTokenPropertyPermissions(signer: TSigner, permissions: ITokenPropertyPermission[]) {
+    return await this.helper.rft.setTokenPropertyPermissions(signer, this.collectionId, permissions);
   }
 }
 
 
 class UniqueFTCollection extends UniqueCollectionBase {
-  async mint(signer: TSigner, owner: ICrossAccountId, amount: bigint, label?: string) {
-    return await this.helper.ft.mintTokens(signer, this.collectionId, owner, amount, label);
+  async mint(signer: TSigner, owner: ICrossAccountId, amount: bigint) {
+    return await this.helper.ft.mintTokens(signer, this.collectionId, owner, amount);
   }
 
-  async mintWithOneOwner(signer: TSigner, owner: ICrossAccountId, tokens: {value: bigint}[], label?: string) {
-    return await this.helper.ft.mintMultipleTokensWithOneOwner(signer, this.collectionId, owner, tokens, label);
+  async mintWithOneOwner(signer: TSigner, owner: ICrossAccountId, tokens: {value: bigint}[]) {
+    return await this.helper.ft.mintMultipleTokensWithOneOwner(signer, this.collectionId, owner, tokens);
   }
 
   async getBalance(addressObj: ICrossAccountId) {
@@ -2277,28 +2321,28 @@
     return await this.helper.ft.getTop10Owners(this.collectionId);
   }
 
-  async transfer(signer: TSigner, toAddressObj: ICrossAccountId, amount: bigint) {
+  async transfer(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {
     return await this.helper.ft.transfer(signer, this.collectionId, toAddressObj, amount);
   }
 
-  async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount: bigint) {
+  async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {
     return await this.helper.ft.transferFrom(signer, this.collectionId, fromAddressObj, toAddressObj, amount);
   }
 
-  async burnTokens(signer: TSigner, amount: bigint, label?: string) {
-    return await this.helper.ft.burnTokens(signer, this.collectionId, amount, label);
+  async burnTokens(signer: TSigner, amount=1n) {
+    return await this.helper.ft.burnTokens(signer, this.collectionId, amount);
   }
 
-  async burnTokensFrom(signer: TSigner, fromAddressObj: ICrossAccountId, amount: bigint, label?: string) {
-    return await this.helper.ft.burnTokensFrom(signer, this.collectionId, fromAddressObj, amount, label);
+  async burnTokensFrom(signer: TSigner, fromAddressObj: ICrossAccountId, amount=1n) {
+    return await this.helper.ft.burnTokensFrom(signer, this.collectionId, fromAddressObj, amount);
   }
 
   async getTotalPieces() {
     return await this.helper.ft.getTotalPieces(this.collectionId);
   }
 
-  async approveTokens(signer: TSigner, toAddressObj: ICrossAccountId, amount=100n, label?: string) {
-    return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount, label);
+  async approveTokens(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {
+    return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount);
   }
 
   async getApprovedTokens(fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {
@@ -2322,12 +2366,12 @@
     return await this.collection.getTokenNextSponsored(this.tokenId, addressObj);
   }
 
-  async setProperties(signer: TSigner, properties: IProperty[], label?: string) {
-    return await this.collection.setTokenProperties(signer, this.tokenId, properties, label);
+  async setProperties(signer: TSigner, properties: IProperty[]) {
+    return await this.collection.setTokenProperties(signer, this.tokenId, properties);
   }
 
-  async deleteProperties(signer: TSigner, propertyKeys: string[], label?: string) {
-    return await this.collection.deleteTokenProperties(signer, this.tokenId, propertyKeys, label);
+  async deleteProperties(signer: TSigner, propertyKeys: string[]) {
+    return await this.collection.deleteTokenProperties(signer, this.tokenId, propertyKeys);
   }
 }
 
@@ -2356,12 +2400,12 @@
     return await this.collection.getTokenChildren(this.tokenId, blockHashAt);
   }
 
-  async nest(signer: TSigner, toTokenObj: IToken, label?: string) {
-    return await this.collection.nestToken(signer, this.tokenId, toTokenObj, label);
+  async nest(signer: TSigner, toTokenObj: IToken) {
+    return await this.collection.nestToken(signer, this.tokenId, toTokenObj);
   }
 
-  async unnest(signer: TSigner, fromTokenObj: IToken, toAddressObj: ICrossAccountId, label?: string) {
-    return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj, label);
+  async unnest(signer: TSigner, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {
+    return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj);
   }
 
   async transfer(signer: TSigner, addressObj: ICrossAccountId) {
@@ -2372,16 +2416,16 @@
     return await this.collection.transferTokenFrom(signer, this.tokenId, fromAddressObj, toAddressObj);
   }
 
-  async approve(signer: TSigner, toAddressObj: ICrossAccountId, label?: string) {
-    return await this.collection.approveToken(signer, this.tokenId, toAddressObj, label);
+  async approve(signer: TSigner, toAddressObj: ICrossAccountId) {
+    return await this.collection.approveToken(signer, this.tokenId, toAddressObj);
   }
 
   async isApproved(toAddressObj: ICrossAccountId) {
     return await this.collection.isTokenApproved(this.tokenId, toAddressObj);
   }
 
-  async burn(signer: TSigner, label?: string) {
-    return await this.collection.burnToken(signer, this.tokenId, label);
+  async burn(signer: TSigner) {
+    return await this.collection.burnToken(signer, this.tokenId);
   }
 }
 
@@ -2405,27 +2449,27 @@
     return await this.collection.getTokenTotalPieces(this.tokenId);
   }
 
-  async transfer(signer: TSigner, addressObj: ICrossAccountId, amount=100n) {
+  async transfer(signer: TSigner, addressObj: ICrossAccountId, amount=1n) {
     return await this.collection.transferToken(signer, this.tokenId, addressObj, amount);
   }
 
-  async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=100n) {
+  async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {
     return await this.collection.transferTokenFrom(signer, this.tokenId, fromAddressObj, toAddressObj, amount);
   }
 
-  async approve(signer: TSigner, toAddressObj: ICrossAccountId, amount=100n, label?: string) {
-    return await this.collection.approveToken(signer, this.tokenId, toAddressObj, amount, label);
+  async approve(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {
+    return await this.collection.approveToken(signer, this.tokenId, toAddressObj, amount);
   }
 
   async getApprovedPieces(fromAddressObj: ICrossAccountId, toAccountObj: ICrossAccountId) {
     return await this.collection.getTokenApprovedPieces(this.tokenId, fromAddressObj, toAccountObj);
   }
 
-  async repartition(signer: TSigner, amount: bigint, label?: string) {
-    return await this.collection.repartitionToken(signer, this.tokenId, amount, label);
+  async repartition(signer: TSigner, amount: bigint) {
+    return await this.collection.repartitionToken(signer, this.tokenId, amount);
   }
 
-  async burn(signer: TSigner, amount=100n, label?: string) {
-    return await this.collection.burnToken(signer, this.tokenId, amount, label);
+  async burn(signer: TSigner, amount=1n) {
+    return await this.collection.burnToken(signer, this.tokenId, amount);
   }
 }