git.delta.rocks / unique-network / refs/commits / 0f4242c739ad

difftreelog

feat add ApproveFrom eth mirror

Grigoriy Simonov2023-01-09parent: #fe83568.patch.diff
in: master

26 files changed

modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -746,6 +746,8 @@
 		ApprovedValueTooLow,
 		/// Tried to approve more than owned
 		CantApproveMoreThanOwned,
+		/// Only spending from eth mirror could be approved
+		AddressIsNotEthMirror,
 
 		/// Can't transfer tokens to ethereum zero address
 		AddressIsZero,
@@ -1797,6 +1799,9 @@
 	/// The price of setting the permission of the operation from another user.
 	fn approve() -> Weight;
 
+	/// The price of setting the permission of the operation from another user for eth mirror.
+	fn approve_from() -> Weight;
+
 	/// Transfer price from another user.
 	fn transfer_from() -> Weight;
 
@@ -2008,6 +2013,22 @@
 		amount: u128,
 	) -> DispatchResultWithPostInfo;
 
+	/// Grant access to another account to transfer parts of the token owned by the calling user's eth mirror via [Self::transfer_from].
+	///
+	/// * `sender` - The user who grants access to the token.
+	/// * `from` - Spender's eth mirror.
+	/// * `to` - The user to whom the rights are granted.
+	/// * `token` - The token to which access is granted.
+	/// * `amount` - The amount of pieces that another user can dispose of.
+	fn approve_from(
+		&self,
+		sender: T::CrossAccountId,
+		from: T::CrossAccountId,
+		to: T::CrossAccountId,
+		token: TokenId,
+		amount: u128,
+	) -> DispatchResultWithPostInfo;
+
 	/// Send parts of a token owned by another user.
 	///
 	/// Before calling this method, you must grant rights to the calling user via [`Self::approve`].
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
@@ -283,8 +283,8 @@
 
 /// Ethereum representation of Optional value with CrossAddress.
 struct OptionCrossAddress {
-	/// TODO: field description
+	/// Whether or not this CrossAdress is valid and has meaning.
 	bool status;
-	/// TODO: field description
+	/// The underlying CrossAddress value. If the status is false, can be set to whatever.
 	CrossAddress value;
 }
modifiedpallets/fungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/fungible/src/benchmarking.rs
+++ b/pallets/fungible/src/benchmarking.rs
@@ -82,6 +82,16 @@
 		<Pallet<T>>::create_item(&collection, &owner, (sender.clone(), 200), &Unlimited)?;
 	}: {<Pallet<T>>::set_allowance(&collection, &sender, &spender, 100)?}
 
+	approve_from {
+		bench_init!{
+			owner: sub; collection: collection(owner);
+			owner: cross_from_sub; sender: cross_sub; spender: cross_sub;
+
+		};
+		let owner_eth = T::CrossAccountId::from_eth(*sender.as_eth());
+		<Pallet<T>>::create_item(&collection, &owner, (owner_eth.clone(), 200), &Unlimited)?;
+	}: {<Pallet<T>>::set_allowance_for(&collection, &sender, &owner_eth, &spender, 100)?}
+
 	transfer_from {
 		bench_init!{
 			owner: sub; collection: collection(owner);
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -87,6 +87,10 @@
 		<SelfWeightOf<T>>::approve()
 	}
 
+	fn approve_from() -> Weight {
+		<SelfWeightOf<T>>::approve_from()
+	}
+
 	fn transfer_from() -> Weight {
 		<SelfWeightOf<T>>::transfer_from()
 	}
@@ -254,6 +258,25 @@
 		)
 	}
 
+	fn approve_from(
+		&self,
+		sender: T::CrossAccountId,
+		from: T::CrossAccountId,
+		to: T::CrossAccountId,
+		token: TokenId,
+		amount: u128,
+	) -> DispatchResultWithPostInfo {
+		ensure!(
+			token == TokenId::default(),
+			<Error<T>>::FungibleItemsHaveNoId
+		);
+
+		with_weight(
+			<Pallet<T>>::set_allowance_for(self, &sender, &from, &to, amount),
+			<CommonWeights<T>>::approve_from(),
+		)
+	}
+
 	fn transfer_from(
 		&self,
 		sender: T::CrossAccountId,
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -613,6 +613,45 @@
 		Ok(())
 	}
 
+	/// Set allowance for the spender to `transfer` or `burn` owner's tokens from eth mirror.
+	///
+	/// - `collection`: Collection that contains the token
+	/// - `sender`: Owner of tokens that sets the allowance.
+	/// - `from`: Owner's eth mirror.
+	/// - `to`: Recipient of the allowance rights.
+	/// - `amount`: Amount of tokens the spender is allowed to `transfer` or `burn`.
+	pub fn set_allowance_for(
+		collection: &FungibleHandle<T>,
+		sender: &T::CrossAccountId,
+		from: &T::CrossAccountId,
+		to: &T::CrossAccountId,
+		amount: u128,
+	) -> DispatchResult {
+		if collection.permissions.access() == AccessMode::AllowList {
+			collection.check_allowlist(sender)?;
+			collection.check_allowlist(from)?;
+			collection.check_allowlist(to)?;
+		}
+
+		ensure!(
+			*sender.as_eth() == *from.as_eth(),
+			<CommonError<T>>::AddressIsNotEthMirror
+		);
+
+		if <Balance<T>>::get((collection.id, from)) < amount {
+			ensure!(
+				collection.limits.owner_can_transfer()
+					&& (collection.is_owner_or_admin(sender) || collection.is_owner_or_admin(from)),
+				<CommonError<T>>::CantApproveMoreThanOwned
+			);
+		}
+
+		// =========
+
+		Self::set_allowance_unchecked(collection, from, to, amount);
+		Ok(())
+	}
+
 	/// Checks if a non-owner has (enough) allowance from the owner to perform operations on the tokens.
 	/// Returns the expected remaining allowance - it should be set manually if the transaction proceeds.
 	///
modifiedpallets/fungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/fungible/src/weights.rs
+++ b/pallets/fungible/src/weights.rs
@@ -39,6 +39,7 @@
 	fn burn_item() -> Weight;
 	fn transfer() -> Weight;
 	fn approve() -> Weight;
+	fn approve_from() -> Weight;
 	fn transfer_from() -> Weight;
 	fn burn_from() -> Weight;
 }
@@ -84,6 +85,13 @@
 			.saturating_add(T::DbWeight::get().reads(1 as u64))
 			.saturating_add(T::DbWeight::get().writes(1 as u64))
 	}
+	// Storage: Fungible Balance (r:1 w:0)
+	// Storage: Fungible Allowance (r:0 w:1)
+	fn approve_from() -> Weight {
+		Weight::from_ref_time(19_817_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(1 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
 	// Storage: Fungible Allowance (r:1 w:1)
 	// Storage: Fungible Balance (r:2 w:2)
 	fn transfer_from() -> Weight {
@@ -141,6 +149,13 @@
 			.saturating_add(RocksDbWeight::get().reads(1 as u64))
 			.saturating_add(RocksDbWeight::get().writes(1 as u64))
 	}
+	// Storage: Fungible Balance (r:1 w:0)
+	// Storage: Fungible Allowance (r:0 w:1)
+	fn approve_from() -> Weight {
+		Weight::from_ref_time(19_817_000 as u64)
+			.saturating_add(RocksDbWeight::get().reads(1 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
 	// Storage: Fungible Allowance (r:1 w:1)
 	// Storage: Fungible Balance (r:2 w:2)
 	fn transfer_from() -> Weight {
modifiedpallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -134,6 +134,15 @@
 		let item = create_max_item(&collection, &owner, sender.clone())?;
 	}: {<Pallet<T>>::set_allowance(&collection, &sender, item, Some(&spender))?}
 
+	approve_from {
+		bench_init!{
+			owner: sub; collection: collection(owner);
+			owner: cross_from_sub; sender: cross_sub; spender: cross_sub;
+		};
+		let owner_eth = T::CrossAccountId::from_eth(*sender.as_eth());
+		let item = create_max_item(&collection, &owner, owner_eth.clone())?;
+	}: {<Pallet<T>>::set_allowance_for(&collection, &sender, &owner_eth, item, Some(&spender))?}
+
 	transfer_from {
 		bench_init!{
 			owner: sub; collection: collection(owner);
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -102,6 +102,10 @@
 		<SelfWeightOf<T>>::approve()
 	}
 
+	fn approve_from() -> Weight {
+		<SelfWeightOf<T>>::approve_from()
+	}
+
 	fn transfer_from() -> Weight {
 		<SelfWeightOf<T>>::transfer_from()
 	}
@@ -353,6 +357,26 @@
 		)
 	}
 
+	fn approve_from(
+		&self,
+		sender: T::CrossAccountId,
+		from: T::CrossAccountId,
+		to: T::CrossAccountId,
+		token: TokenId,
+		amount: u128,
+	) -> DispatchResultWithPostInfo {
+		ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
+
+		with_weight(
+			if amount == 1 {
+				<Pallet<T>>::set_allowance_for(self, &sender, &from, token, Some(&to))
+			} else {
+				<Pallet<T>>::set_allowance_for(self, &sender, &from, token, None)
+			},
+			<CommonWeights<T>>::approve_from(),
+		)
+	}
+
 	fn transfer_from(
 		&self,
 		sender: T::CrossAccountId,
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -1171,6 +1171,51 @@
 		Ok(())
 	}
 
+	/// Set allowance for the spender to `transfer` or `burn` sender's token from eth mirror.
+	///
+	/// - `from`: Address of sender's eth mirror.
+	/// - `to`: Adress of spender.
+	/// - `token`: Token the spender is allowed to `transfer` or `burn`.
+	pub fn set_allowance_for(
+		collection: &NonfungibleHandle<T>,
+		sender: &T::CrossAccountId,
+		from: &T::CrossAccountId,
+		token: TokenId,
+		to: Option<&T::CrossAccountId>,
+	) -> DispatchResult {
+		if collection.permissions.access() == AccessMode::AllowList {
+			collection.check_allowlist(sender)?;
+			collection.check_allowlist(from)?;
+			if let Some(to) = to {
+				collection.check_allowlist(to)?;
+			}
+		}
+
+		if let Some(to) = to {
+			<PalletCommon<T>>::ensure_correct_receiver(to)?;
+		}
+
+		ensure!(
+			*sender.as_eth() == *from.as_eth(),
+			<CommonError<T>>::AddressIsNotEthMirror
+		);
+
+		let token_data =
+			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
+		if token_data.owner != *from {
+			ensure!(
+				collection.limits.owner_can_transfer()
+					&& (collection.is_owner_or_admin(sender) || collection.is_owner_or_admin(from)),
+				<CommonError<T>>::CantApproveMoreThanOwned
+			);
+		}
+
+		// =========
+
+		Self::set_allowance_unchecked(collection, from, token, to, false);
+		Ok(())
+	}
+
 	/// Checks allowance for the spender to use the token.
 	fn check_allowed(
 		collection: &NonfungibleHandle<T>,
modifiedpallets/nonfungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/weights.rs
+++ b/pallets/nonfungible/src/weights.rs
@@ -42,6 +42,7 @@
 	fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight;
 	fn transfer() -> Weight;
 	fn approve() -> Weight;
+	fn approve_from() -> Weight;
 	fn transfer_from() -> Weight;
 	fn burn_from() -> Weight;
 	fn set_token_property_permissions(b: u32, ) -> Weight;
@@ -147,6 +148,13 @@
 			.saturating_add(T::DbWeight::get().reads(2 as u64))
 			.saturating_add(T::DbWeight::get().writes(1 as u64))
 	}
+	// Storage: Nonfungible TokenData (r:1 w:0)
+	// Storage: Nonfungible Allowance (r:1 w:1)
+	fn approve_from() -> Weight {
+		Weight::from_ref_time(18_965_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(2 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
 	// Storage: Nonfungible Allowance (r:1 w:1)
 	// Storage: Nonfungible TokenData (r:1 w:1)
 	// Storage: Nonfungible AccountBalance (r:2 w:2)
@@ -310,6 +318,13 @@
 			.saturating_add(RocksDbWeight::get().reads(2 as u64))
 			.saturating_add(RocksDbWeight::get().writes(1 as u64))
 	}
+	// Storage: Nonfungible TokenData (r:1 w:0)
+	// Storage: Nonfungible Allowance (r:1 w:1)
+	fn approve_from() -> Weight {
+		Weight::from_ref_time(18_965_000 as u64)
+			.saturating_add(RocksDbWeight::get().reads(2 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
 	// Storage: Nonfungible Allowance (r:1 w:1)
 	// Storage: Nonfungible TokenData (r:1 w:1)
 	// Storage: Nonfungible AccountBalance (r:2 w:2)
modifiedpallets/refungible/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -163,6 +163,15 @@
 		let item = create_max_item(&collection, &owner, [(sender.clone(), 200)])?;
 	}: {<Pallet<T>>::set_allowance(&collection, &sender, &spender, item, 100)?}
 
+	approve_from {
+		bench_init!{
+			owner: sub; collection: collection(owner);
+			owner: cross_from_sub; sender: cross_sub; spender: cross_sub;
+		};
+		let owner_eth = T::CrossAccountId::from_eth(*sender.as_eth());
+		let item = create_max_item(&collection, &owner, [(owner_eth.clone(), 200)])?;
+	}: {<Pallet<T>>::set_allowance_for(&collection, &sender, &owner_eth, &spender, item, 100)?}
+
 	transfer_from_normal {
 		bench_init!{
 			owner: sub; collection: collection(owner);
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -127,6 +127,10 @@
 		<SelfWeightOf<T>>::approve()
 	}
 
+	fn approve_from() -> Weight {
+		<SelfWeightOf<T>>::approve_from()
+	}
+
 	fn transfer_from() -> Weight {
 		max_weight_of!(
 			transfer_from_normal(),
@@ -314,6 +318,20 @@
 		)
 	}
 
+	fn approve_from(
+		&self,
+		sender: T::CrossAccountId,
+		from: T::CrossAccountId,
+		to: T::CrossAccountId,
+		token_id: TokenId,
+		amount: u128,
+	) -> DispatchResultWithPostInfo {
+		with_weight(
+			<Pallet<T>>::set_allowance_for(self, &sender, &from, &to, token_id, amount),
+			<CommonWeights<T>>::approve_from(),
+		)
+	}
+
 	fn transfer_from(
 		&self,
 		sender: T::CrossAccountId,
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -1102,6 +1102,47 @@
 		Ok(())
 	}
 
+	/// Set allowance to spend from sender's eth mirror
+	///
+	/// - `from`: Address of sender's eth mirror.
+	/// - `to`: Adress of spender.
+	/// - `amount`: Amount of token pieces the spender is allowed to `transfer` or `burn.
+	pub fn set_allowance_for(
+		collection: &RefungibleHandle<T>,
+		sender: &T::CrossAccountId,
+		from: &T::CrossAccountId,
+		to: &T::CrossAccountId,
+		token_id: TokenId,
+		amount: u128,
+	) -> DispatchResult {
+		if collection.permissions.access() == AccessMode::AllowList {
+			collection.check_allowlist(sender)?;
+			collection.check_allowlist(from)?;
+			collection.check_allowlist(to)?;
+		}
+
+		<PalletCommon<T>>::ensure_correct_receiver(to)?;
+
+		ensure!(
+			*sender.as_eth() == *from.as_eth(),
+			<CommonError<T>>::AddressIsNotEthMirror
+		);
+
+		if <Balance<T>>::get((collection.id, token_id, from)) < amount {
+			ensure!(
+				collection.limits.owner_can_transfer()
+					&& (collection.is_owner_or_admin(sender) || collection.is_owner_or_admin(from))
+					&& Self::token_exists(collection, token_id),
+				<CommonError<T>>::CantApproveMoreThanOwned
+			);
+		}
+
+		// =========
+
+		Self::set_allowance_unchecked(collection, from, to, token_id, amount);
+		Ok(())
+	}
+
 	/// Returns allowance, which should be set after transaction
 	fn check_allowed(
 		collection: &RefungibleHandle<T>,
modifiedpallets/refungible/src/weights.rsdiffbeforeafterboth
--- a/pallets/refungible/src/weights.rs
+++ b/pallets/refungible/src/weights.rs
@@ -45,6 +45,7 @@
 	fn transfer_removing() -> Weight;
 	fn transfer_creating_removing() -> Weight;
 	fn approve() -> Weight;
+	fn approve_from() -> Weight;
 	fn transfer_from_normal() -> Weight;
 	fn transfer_from_creating() -> Weight;
 	fn transfer_from_removing() -> Weight;
@@ -175,6 +176,13 @@
 			.saturating_add(T::DbWeight::get().reads(1 as u64))
 			.saturating_add(T::DbWeight::get().writes(1 as u64))
 	}
+	// Storage: Refungible Balance (r:1 w:0)
+	// Storage: Refungible Allowance (r:0 w:1)
+	fn approve_from() -> Weight {
+		Weight::from_ref_time(20_649_000 as u64)
+			.saturating_add(T::DbWeight::get().reads(1 as u64))
+			.saturating_add(T::DbWeight::get().writes(1 as u64))
+	}
 	// Storage: Refungible Allowance (r:1 w:1)
 	// Storage: Refungible CollectionAllowance (r:1 w:0)
 	// Storage: Refungible Balance (r:2 w:2)
@@ -400,6 +408,13 @@
 			.saturating_add(RocksDbWeight::get().reads(1 as u64))
 			.saturating_add(RocksDbWeight::get().writes(1 as u64))
 	}
+	// Storage: Refungible Balance (r:1 w:0)
+	// Storage: Refungible Allowance (r:0 w:1)
+	fn approve_from() -> Weight {
+		Weight::from_ref_time(20_649_000 as u64)
+			.saturating_add(RocksDbWeight::get().reads(1 as u64))
+			.saturating_add(RocksDbWeight::get().writes(1 as u64))
+	}
 	// Storage: Refungible Allowance (r:1 w:1)
 	// Storage: Refungible CollectionAllowance (r:1 w:0)
 	// Storage: Refungible Balance (r:2 w:2)
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -851,6 +851,29 @@
 			dispatch_tx::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
 		}
 
+		/// Allow a non-permissioned address to transfer or burn an item from owner's eth mirror.
+		///
+		/// # Permissions
+		///
+		/// * Collection owner
+		/// * Collection admin
+		/// * Current item owner
+		///
+		/// # Arguments
+		///
+		/// * `from`: Owner's account eth mirror
+		/// * `to`: Account to be approved to make specific transactions on non-owned tokens.
+		/// * `collection_id`: ID of the collection the item belongs to.
+		/// * `item_id`: ID of the item transactions on which are now approved.
+		/// * `amount`: Number of pieces of the item approved for a transaction (maximum of 1 for NFTs).
+		/// Set to 0 to revoke the approval.
+		#[weight = T::CommonWeightInfo::approve_from()]
+		pub fn approve_from(origin, from:T::CrossAccountId, to: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {
+			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+
+			dispatch_tx::<T, _>(collection_id, |d| d.approve_from(sender, from, to, item_id, amount))
+		}
+
 		/// Change ownership of an item on behalf of the owner as a non-owner account.
 		///
 		/// See the [`approve`][`Pallet::approve`] method for additional information.
modifiedruntime/common/identity.rsdiffbeforeafterboth
--- a/runtime/common/identity.rs
+++ b/runtime/common/identity.rs
@@ -21,9 +21,7 @@
 
 use sp_runtime::{
 	traits::{DispatchInfoOf, SignedExtension},
-	transaction_validity::{
-		TransactionValidity, ValidTransaction, InvalidTransaction, TransactionValidityError,
-	},
+	transaction_validity::{TransactionValidity, ValidTransaction, TransactionValidityError},
 };
 
 #[derive(Debug, Encode, Decode, PartialEq, Eq, Clone, TypeInfo)]
modifiedruntime/common/weights.rsdiffbeforeafterboth
--- a/runtime/common/weights.rs
+++ b/runtime/common/weights.rs
@@ -101,6 +101,10 @@
 		dispatch_weight::<T>() + max_weight_of!(approve())
 	}
 
+	fn approve_from() -> Weight {
+		dispatch_weight::<T>() + max_weight_of!(approve_from())
+	}
+
 	fn transfer_from() -> Weight {
 		dispatch_weight::<T>() + max_weight_of!(transfer_from())
 	}
modifiedtests/src/approve.test.tsdiffbeforeafterboth
--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -16,336 +16,521 @@
 
 import {IKeyringPair} from '@polkadot/types/types';
 import {expect, itSub, Pallets, usingPlaygrounds} from './util';
+import {CrossAccountId} from './util/playgrounds/unique';
+
 
 
-describe('Integration Test approve(spender, collection_id, item_id, amount):', () => {
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-  let charlie: IKeyringPair;
+[
+  {method: 'approveToken', account: (account: IKeyringPair) => CrossAccountId.fromKeyring(account)},
+  {method: 'approveTokenFromEth', account: (account: IKeyringPair) => CrossAccountId.fromKeyring(account).toEthereum()},
+].map(testCase => {
+  describe(`Integration Test ${testCase.method}(spender, collection_id, item_id, amount):`, () => {
+    let alice: IKeyringPair;
+    let bob: IKeyringPair;
+    let charlie: IKeyringPair;
 
-  before(async () => {
-    await usingPlaygrounds(async (helper, privateKey) => {
-      const donor = await privateKey({filename: __filename});
-      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+    before(async () => {
+      await usingPlaygrounds(async (helper, privateKey) => {
+        const donor = await privateKey({filename: __filename});
+        [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+      });
     });
-  });
 
-  itSub('[nft] Execute the extrinsic and check approvedList', 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: 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;
-  });
+    itSub('[nft] Execute the extrinsic and check approvedList', 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: testCase.account(alice)});
+      await (helper.nft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address});
+      expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
+    });
+
+    itSub('[fungible] Execute the extrinsic and check approvedList', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+      await helper.ft.mintTokens(alice, collectionId, 10n, testCase.account(alice));
+      const tokenId = await helper.ft.getLastTokenId(collectionId);
+      await (helper.ft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address});
+      const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, testCase.account(alice));
+      expect(amount).to.be.equal(BigInt(1));
+    });
+
+    itSub.ifWithPallets('[refungible] Execute the extrinsic and check approvedList', [Pallets.ReFungible], 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: testCase.account(alice), pieces: 100n});
+      await (helper.rft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address});
+      const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, testCase.account(alice));
+      expect(amount).to.be.equal(BigInt(1));
+    });
+
+    itSub('[nft] Remove approval by using 0 amount', async ({helper}) => {
+      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: testCase.account(alice)});
+      await (helper.nft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address});
+      expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
+      await (helper.nft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
+      expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;
+    });
 
-  itSub('[fungible] Execute the extrinsic and check approvedList', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
-    await helper.ft.mintTokens(alice, collectionId, 10n, {Substrate: alice.address});
-    const tokenId = await helper.ft.getLastTokenId(collectionId);
-    await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
-    const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
-    expect(amount).to.be.equal(BigInt(1));
-  });
+    itSub('[fungible] Remove approval by using 0 amount', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+      await helper.ft.mintTokens(alice, collectionId, 10n, testCase.account(alice));
+      const tokenId = await helper.ft.getLastTokenId(collectionId);
+      await (helper.ft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address});
+      const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, testCase.account(alice));
+      expect(amountBefore).to.be.equal(BigInt(1));
 
-  itSub.ifWithPallets('[refungible] Execute the extrinsic and check approvedList', [Pallets.ReFungible], 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});
-    await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
-    const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
-    expect(amount).to.be.equal(BigInt(1));
-  });
+      await (helper.ft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
+      const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, testCase.account(alice));
+      expect(amountAfter).to.be.equal(BigInt(0));
+    });
 
-  itSub('[nft] Remove approval by using 0 amount', async ({helper}) => {
-    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.signTransaction(alice, helper.constructApiCall('api.tx.unique.approve', [{Substrate: bob.address}, collectionId, tokenId, 0]));
-    expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;
-  });
+    itSub.ifWithPallets('[refungible] Remove approval by using 0 amount', [Pallets.ReFungible], 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: testCase.account(alice), pieces: 100n});
+      await (helper.rft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address});
+      const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, testCase.account(alice));
+      expect(amountBefore).to.be.equal(BigInt(1));
 
-  itSub('[fungible] Remove approval by using 0 amount', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
-    await helper.ft.mintTokens(alice, collectionId, 10n, {Substrate: alice.address});
-    const tokenId = await helper.ft.getLastTokenId(collectionId);
-    await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
-    const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
-    expect(amountBefore).to.be.equal(BigInt(1));
+      await (helper.rft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
+      const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, testCase.account(alice));
+      expect(amountAfter).to.be.equal(BigInt(0));
+    });
 
-    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));
+    itSub('can`t be called by collection owner on non-owned item when OwnerCanTransfer == false', 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: testCase.account(bob)});
+      const result = (helper.nft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: charlie.address});
+      await expect(result).to.be.rejected;
+    });
   });
 
-  itSub.ifWithPallets('[refungible] Remove approval by using 0 amount', [Pallets.ReFungible], 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});
-    await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
-    const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
-    expect(amountBefore).to.be.equal(BigInt(1));
+  describe(`[${testCase.method}] Normal user can approve other users to transfer:`, () => {
+    let alice: IKeyringPair;
+    let bob: IKeyringPair;
+    let charlie: IKeyringPair;
 
-    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));
-  });
+    before(async () => {
+      await usingPlaygrounds(async (helper, privateKey) => {
+        const donor = await privateKey({filename: __filename});
+        [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+      });
+    });
 
-  itSub('can`t be called by collection owner on non-owned item when OwnerCanTransfer == false', 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 approveTokenTx = () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});
-    await expect(approveTokenTx()).to.be.rejected;
-  });
-});
+    itSub('NFT', 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: testCase.account(bob)});
+      await (helper.nft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address});
+      expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.true;
+    });
 
-describe('Normal user can approve other users to transfer:', () => {
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-  let charlie: IKeyringPair;
+    itSub('Fungible up to an approved amount', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+      await helper.ft.mintTokens(alice, collectionId, 10n, testCase.account(bob));
+      const tokenId = await helper.ft.getLastTokenId(collectionId);
+      await (helper.ft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address});
+      const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, testCase.account(bob));
+      expect(amount).to.be.equal(BigInt(1));
+    });
 
-  before(async () => {
-    await usingPlaygrounds(async (helper, privateKey) => {
-      const donor = await privateKey({filename: __filename});
-      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+    itSub.ifWithPallets('ReFungible up to an approved amount', [Pallets.ReFungible], 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: testCase.account(bob), pieces: 100n});
+      await (helper.rft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);
+      const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, testCase.account(bob));
+      expect(amount).to.be.equal(BigInt(100n));
     });
   });
 
-  itSub('NFT', 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});
-    await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
-    expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.true;
-  });
+  describe(`[${testCase.method}] Approved users can transferFrom up to approved amount:`, () => {
+    let alice: IKeyringPair;
+    let bob: IKeyringPair;
+    let charlie: IKeyringPair;
 
-  itSub('Fungible up to an approved amount', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
-    await helper.ft.mintTokens(alice, collectionId, 10n, bob.address);
-    const tokenId = await helper.ft.getLastTokenId(collectionId);
-    await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
-    const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});
-    expect(amount).to.be.equal(BigInt(1));
-  });
+    before(async () => {
+      await usingPlaygrounds(async (helper, privateKey) => {
+        const donor = await privateKey({filename: __filename});
+        [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+      });
+    });
 
-  itSub.ifWithPallets('ReFungible up to an approved amount', [Pallets.ReFungible], 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: bob.address, pieces: 100n});
-    await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);
-    const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});
-    expect(amount).to.be.equal(BigInt(100n));
+    itSub('NFT', 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: testCase.account(bob)});
+      await (helper.nft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address});
+      await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, testCase.account(bob), {Substrate: alice.address});
+      const owner = await helper.nft.getTokenOwner(collectionId, tokenId);
+      expect(owner.Substrate).to.be.equal(alice.address);
+    });
+
+    itSub('Fungible up to an approved amount', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+      await helper.ft.mintTokens(alice, collectionId, 10n, testCase.account(bob));
+      const tokenId = await helper.ft.getLastTokenId(collectionId);
+      await (helper.ft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address});
+      const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
+      await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, testCase.account(bob), {Substrate: alice.address}, 1n);
+      const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
+      expect(after - before).to.be.equal(BigInt(1));
+    });
+
+    itSub.ifWithPallets('ReFungible up to an approved amount', [Pallets.ReFungible], 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: testCase.account(bob), pieces: 100n});
+      await (helper.rft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address});
+      const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
+      await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, testCase.account(bob), {Substrate: alice.address}, 1n);
+      const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
+      expect(after - before).to.be.equal(BigInt(1));
+    });
   });
-});
 
-describe('Approved users can transferFrom up to approved amount:', () => {
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-  let charlie: IKeyringPair;
+  describe(`[${testCase.method}] Approved users cannot use transferFrom to repeat transfers if approved amount was already transferred:`, () => {
+    let alice: IKeyringPair;
+    let bob: IKeyringPair;
+    let charlie: IKeyringPair;
+
+    before(async () => {
+      await usingPlaygrounds(async (helper, privateKey) => {
+        const donor = await privateKey({filename: __filename});
+        [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+      });
+    });
+
+    itSub('NFT', 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: testCase.account(bob)});
+      await (helper.nft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address});
+      await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, testCase.account(bob), {Substrate: alice.address});
+      const owner = await helper.nft.getTokenOwner(collectionId, tokenId);
+      expect(owner.Substrate).to.be.equal(alice.address);
+      const transferTokenFromTx = () => helper.nft.transferTokenFrom(charlie, collectionId, tokenId, testCase.account(bob), {Substrate: alice.address});
+      await expect(transferTokenFromTx()).to.be.rejected;
+    });
+
+    itSub('Fungible up to an approved amount', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+      await helper.ft.mintTokens(alice, collectionId, 10n, testCase.account(bob));
+      const tokenId = await helper.ft.getLastTokenId(collectionId);
+      await (helper.ft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address});
+      const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
+      await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, testCase.account(bob), {Substrate: alice.address}, 1n);
+      const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
+      expect(after - before).to.be.equal(BigInt(1));
+
+      const transferTokenFromTx = () => helper.ft.transferTokenFrom(charlie, collectionId, tokenId, testCase.account(bob), {Substrate: alice.address}, 1n);
+      await expect(transferTokenFromTx()).to.be.rejected;
+    });
 
-  before(async () => {
-    await usingPlaygrounds(async (helper, privateKey) => {
-      const donor = await privateKey({filename: __filename});
-      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+    itSub.ifWithPallets('ReFungible up to an approved amount', [Pallets.ReFungible], 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: testCase.account(bob), pieces: 100n});
+      await (helper.ft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);
+      const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
+      await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, testCase.account(bob), {Substrate: alice.address}, 100n);
+      const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
+      expect(after - before).to.be.equal(BigInt(100));
+      const transferTokenFromTx = () => helper.rft.transferTokenFrom(charlie, collectionId, tokenId, testCase.account(bob), {Substrate: alice.address}, 100n);
+      await expect(transferTokenFromTx()).to.be.rejected;
     });
   });
 
-  itSub('NFT', 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});
-    await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
-    await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
-    const owner = await helper.nft.getTokenOwner(collectionId, tokenId);
-    expect(owner.Substrate).to.be.equal(alice.address);
+  describe(`[${testCase.method}] Approved amount decreases by the transferred amount:`, () => {
+    let alice: IKeyringPair;
+    let bob: IKeyringPair;
+    let charlie: IKeyringPair;
+    let dave: IKeyringPair;
+
+    before(async () => {
+      await usingPlaygrounds(async (helper, privateKey) => {
+        const donor = await privateKey({filename: __filename});
+        [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);
+      });
+    });
+
+    itSub('If a user B is approved to transfer 10 Fungible tokens from user A, they can transfer 2 tokens to user C, which will result in decreasing approval from 10 to 8. Then user B can transfer 8 tokens to user D.', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+      await helper.ft.mintTokens(alice, collectionId, 10n, testCase.account(alice));
+      const tokenId = await helper.ft.getLastTokenId(collectionId);
+      await (helper.ft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address}, 10n);
+
+      const charlieBefore = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});
+      await helper.ft.transferTokenFrom(bob, collectionId, tokenId, testCase.account(alice), {Substrate: charlie.address}, 2n);
+      const charlieAfter = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});
+      expect(charlieAfter - charlieBefore).to.be.equal(BigInt(2));
+
+      const daveBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
+      await helper.ft.transferTokenFrom(bob, collectionId, tokenId, testCase.account(alice), {Substrate: dave.address}, 8n);
+      const daveAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
+      expect(daveAfter - daveBefore).to.be.equal(BigInt(8));
+    });
   });
 
-  itSub('Fungible up to an approved amount', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
-    await helper.ft.mintTokens(alice, collectionId, 10n, bob.address);
-    const tokenId = await helper.ft.getLastTokenId(collectionId);
-    await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
-    const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
-    await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
-    const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
-    expect(after - before).to.be.equal(BigInt(1));
+  describe(`[${testCase.method}] User may clear the approvals to approving for 0 amount:`, () => {
+    let alice: IKeyringPair;
+    let bob: IKeyringPair;
+    let charlie: IKeyringPair;
+
+    before(async () => {
+      await usingPlaygrounds(async (helper, privateKey) => {
+        const donor = await privateKey({filename: __filename});
+        [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+      });
+    });
+
+    itSub('NFT', 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: testCase.account(alice)});
+      await (helper.nft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address});
+      expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
+      await (helper.nft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
+      expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;
+      const transferTokenFromTx = () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});
+      await expect(transferTokenFromTx()).to.be.rejected;
+    });
+
+    itSub('Fungible', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+      await helper.ft.mintTokens(alice, collectionId, 10n, testCase.account(alice));
+      const tokenId = await helper.ft.getLastTokenId(collectionId);
+      await (helper.ft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address});
+      const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, testCase.account(alice));
+      expect(amountBefore).to.be.equal(BigInt(1));
+
+      await (helper.ft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
+      const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, testCase.account(alice));
+      expect(amountAfter).to.be.equal(BigInt(0));
+
+      const transferTokenFromTx = () => helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 1n);
+      await expect(transferTokenFromTx()).to.be.rejected;
+    });
+
+    itSub.ifWithPallets('ReFungible', [Pallets.ReFungible], 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: testCase.account(alice), pieces: 100n});
+      await (helper.rft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address});
+      const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, testCase.account(alice));
+      expect(amountBefore).to.be.equal(BigInt(1));
+
+      await (helper.rft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
+      const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, testCase.account(alice));
+      expect(amountAfter).to.be.equal(BigInt(0));
+
+      const transferTokenFromTx = () => helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 100n);
+      await expect(transferTokenFromTx()).to.be.rejected;
+    });
   });
 
-  itSub.ifWithPallets('ReFungible up to an approved amount', [Pallets.ReFungible], 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: bob.address, pieces: 100n});
-    await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
-    const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
-    await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
-    const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
-    expect(after - before).to.be.equal(BigInt(1));
+  describe(`[${testCase.method}] User cannot approve for the amount greater than they own:`, () => {
+    let alice: IKeyringPair;
+    let bob: IKeyringPair;
+    let charlie: IKeyringPair;
+
+    before(async () => {
+      await usingPlaygrounds(async (helper, privateKey) => {
+        const donor = await privateKey({filename: __filename});
+        [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+      });
+    });
+
+    itSub('1 for NFT', 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: testCase.account(bob)});
+      const result = (helper.nft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address}, 2n);
+      await expect(result).to.be.rejected;
+      expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;
+    });
+
+    itSub('Fungible', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+      await helper.ft.mintTokens(alice, collectionId, 10n, testCase.account(alice));
+      const tokenId = await helper.ft.getLastTokenId(collectionId);
+      const result = (helper.ft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address}, 11n);
+      await expect(result).to.be.rejected;
+    });
+
+    itSub.ifWithPallets('ReFungible', [Pallets.ReFungible], 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: testCase.account(alice), pieces: 100n});
+      const result = (helper.rft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: bob.address}, 101n);
+      await expect(result).to.be.rejected;
+    });
   });
-});
 
-describe('Approved users cannot use transferFrom to repeat transfers if approved amount was already transferred:', () => {
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-  let charlie: IKeyringPair;
+  describe(`[${testCase.method}] Integration Test approve(spender, collection_id, item_id, amount) with collection admin permissions:`, () => {
+    let alice: IKeyringPair;
+    let bob: IKeyringPair;
+    let charlie: IKeyringPair;
+
+    before(async () => {
+      await usingPlaygrounds(async (helper, privateKey) => {
+        const donor = await privateKey({filename: __filename});
+        [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+      });
+    });
 
-  before(async () => {
-    await usingPlaygrounds(async (helper, privateKey) => {
-      const donor = await privateKey({filename: __filename});
-      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+    itSub('can be called by collection admin on non-owned item', 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: testCase.account(alice)});
+      await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});
+      const result = (helper.nft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: charlie.address});
+      await expect(result).to.be.rejected;
     });
   });
 
-  itSub('NFT', 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});
-    await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
-    await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
-    const owner = await helper.nft.getTokenOwner(collectionId, tokenId);
-    expect(owner.Substrate).to.be.equal(alice.address);
-    const transferTokenFromTx = () => helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
-    await expect(transferTokenFromTx()).to.be.rejected;
-  });
+  describe(`[${testCase.method}] Negative Integration Test approve(spender, collection_id, item_id, amount):`, () => {
+    let alice: IKeyringPair;
+    let bob: IKeyringPair;
+    let charlie: IKeyringPair;
 
-  itSub('Fungible up to an approved amount', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
-    await helper.ft.mintTokens(alice, collectionId, 10n, bob.address);
-    const tokenId = await helper.ft.getLastTokenId(collectionId);
-    await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
-    const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
-    await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
-    const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
-    expect(after - before).to.be.equal(BigInt(1));
+    before(async () => {
+      await usingPlaygrounds(async (helper, privateKey) => {
+        const donor = await privateKey({filename: __filename});
+        [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+      });
+    });
 
-    const transferTokenFromTx = () => helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
-    await expect(transferTokenFromTx()).to.be.rejected;
-  });
+    itSub('[nft] Approve for a collection that does not exist', async ({helper}) => {
+      const collectionId = 1 << 32 - 1;
+      await expect((helper.nft as any)[testCase.method](bob, collectionId, 1, {Substrate: charlie.address})).to.be.rejected;
+    });
+
+    itSub('[fungible] Approve for a collection that does not exist', async ({helper}) => {
+      const collectionId = 1 << 32 - 1;
+      const approveTx = () => (helper.ft as any)[testCase.method](bob, collectionId, 1, {Substrate: charlie.address});
+      await expect(approveTx()).to.be.rejected;
+    });
 
-  itSub.ifWithPallets('ReFungible up to an approved amount', [Pallets.ReFungible], 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: bob.address, pieces: 100n});
-    await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);
-    const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
-    await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);
-    const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
-    expect(after - before).to.be.equal(BigInt(100));
-    const transferTokenFromTx = () => helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);
-    await expect(transferTokenFromTx()).to.be.rejected;
-  });
-});
+    itSub.ifWithPallets('[refungible] Approve for a collection that does not exist', [Pallets.ReFungible], async ({helper}) => {
+      const collectionId = 1 << 32 - 1;
+      const approveTx = () => (helper.rft as any)[testCase.method](bob, collectionId, 1, {Substrate: charlie.address});
+      await expect(approveTx()).to.be.rejected;
+    });
 
-describe('Approved amount decreases by the transferred amount:', () => {
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-  let charlie: IKeyringPair;
-  let dave: IKeyringPair;
+    itSub('[nft] Approve for a collection that was destroyed', async ({helper}) => {
+      const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+      await helper.nft.burn(alice, collectionId);
+      const approveTx = () => (helper.nft as any)[testCase.method](alice, collectionId, 1, {Substrate: bob.address});
+      await expect(approveTx()).to.be.rejected;
+    });
 
-  before(async () => {
-    await usingPlaygrounds(async (helper, privateKey) => {
-      const donor = await privateKey({filename: __filename});
-      [alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);
+    itSub('[fungible] Approve for a collection that was destroyed', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+      await helper.ft.burn(alice, collectionId);
+      const approveTx = () => (helper.ft as any)[testCase.method](alice, collectionId, 1, {Substrate: bob.address});
+      await expect(approveTx()).to.be.rejected;
     });
-  });
 
-  itSub('If a user B is approved to transfer 10 Fungible tokens from user A, they can transfer 2 tokens to user C, which will result in decreasing approval from 10 to 8. Then user B can transfer 8 tokens to user D.', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
-    await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
-    const tokenId = await helper.ft.getLastTokenId(collectionId);
-    await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);
+    itSub.ifWithPallets('[refungible] Approve for a collection that was destroyed', [Pallets.ReFungible], async ({helper}) => {
+      const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+      await helper.rft.burn(alice, collectionId);
+      const approveTx = () => (helper.rft as any)[testCase.method](alice, collectionId, 1, {Substrate: bob.address});
+      await expect(approveTx()).to.be.rejected;
+    });
 
-    const charlieBefore = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});
-    await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: charlie.address}, 2n);
-    const charlieAfter = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});
-    expect(charlieAfter - charlieBefore).to.be.equal(BigInt(2));
+    itSub('[nft] Approve transfer of a token that does not exist', async ({helper}) => {
+      const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+      const approveTx = () => (helper.nft as any)[testCase.method](alice, collectionId, 2, {Substrate: bob.address});
+      await expect(approveTx()).to.be.rejected;
+    });
 
-    const daveBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
-    await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: dave.address}, 8n);
-    const daveAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
-    expect(daveAfter - daveBefore).to.be.equal(BigInt(8));
-  });
-});
+    itSub.ifWithPallets('[refungible] Approve transfer of a token that does not exist', [Pallets.ReFungible], async ({helper}) => {
+      const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+      const approveTx = () => (helper.rft as any)[testCase.method](alice, collectionId, 2, {Substrate: bob.address});
+      await expect(approveTx()).to.be.rejected;
+    });
 
-describe('User may clear the approvals to approving for 0 amount:', () => {
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-  let charlie: IKeyringPair;
+    itSub('[nft] Approve using the address that does not own the approved token', 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: testCase.account(alice)});
+      const approveTx = () => (helper.nft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: alice.address});
+      await expect(approveTx()).to.be.rejected;
+    });
 
-  before(async () => {
-    await usingPlaygrounds(async (helper, privateKey) => {
-      const donor = await privateKey({filename: __filename});
-      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+    itSub('[fungible] Approve using the address that does not own the approved token', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+      await helper.ft.mintTokens(alice, collectionId, 10n, testCase.account(alice));
+      const tokenId = await helper.ft.getLastTokenId(collectionId);
+      const approveTx = () => (helper.ft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: alice.address});
+      await expect(approveTx()).to.be.rejected;
     });
-  });
 
-  itSub('NFT', 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: 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.signTransaction(alice, helper.constructApiCall('api.tx.unique.approve', [{Substrate: bob.address}, collectionId, tokenId, 0]));
-    expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;
-    const transferTokenFromTx = () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});
-    await expect(transferTokenFromTx()).to.be.rejected;
-  });
+    itSub.ifWithPallets('[refungible] Approve using the address that does not own the approved token', [Pallets.ReFungible], 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: testCase.account(alice), pieces: 100n});
+      const approveTx = () => (helper.rft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: alice.address});
+      await expect(approveTx()).to.be.rejected;
+    });
 
-  itSub('Fungible', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
-    await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
-    const tokenId = await helper.ft.getLastTokenId(collectionId);
-    await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
-    const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
-    expect(amountBefore).to.be.equal(BigInt(1));
+    itSub.ifWithPallets('should fail if approved more ReFungibles than owned', [Pallets.ReFungible], 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});
+      await helper.rft.transferToken(alice, collectionId, tokenId, testCase.account(bob), 100n);
+      await (helper.rft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: alice.address}, 100n);
 
-    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));
+      const approveTx = () => (helper.rft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: alice.address}, 101n);
+      await expect(approveTx()).to.be.rejected;
+    });
 
-    const transferTokenFromTx = () => helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 1n);
-    await expect(transferTokenFromTx()).to.be.rejected;
-  });
+    itSub('should fail if approved more Fungibles than owned', async ({helper}) => {
+      const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+      await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
+      const tokenId = await helper.ft.getLastTokenId(collectionId);
 
-  itSub.ifWithPallets('ReFungible', [Pallets.ReFungible], 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});
-    await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
-    const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
-    expect(amountBefore).to.be.equal(BigInt(1));
+      await helper.ft.transferToken(alice, collectionId, tokenId, testCase.account(bob), 10n);
+      await (helper.ft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: alice.address}, 10n);
+      const approveTx = () => (helper.ft as any)[testCase.method](bob, collectionId, tokenId, {Substrate: alice.address}, 11n);
+      await expect(approveTx()).to.be.rejected;
+    });
 
-    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));
+    itSub('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', 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: testCase.account(bob)});
+      await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: false});
 
-    const transferTokenFromTx = () => helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 100n);
-    await expect(transferTokenFromTx()).to.be.rejected;
+      const approveTx = () => (helper.nft as any)[testCase.method](alice, collectionId, tokenId, {Substrate: charlie.address});
+      await expect(approveTx()).to.be.rejected;
+    });
   });
 });
 
-describe('User cannot approve for the amount greater than they own:', () => {
+describe('Normal user can approve other users to be wallet operator:', () => {
   let alice: IKeyringPair;
   let bob: IKeyringPair;
-  let charlie: IKeyringPair;
 
   before(async () => {
     await usingPlaygrounds(async (helper, privateKey) => {
       const donor = await privateKey({filename: __filename});
-      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
+      [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);
     });
   });
 
-  itSub('1 for NFT', async ({helper}) => {
+  itSub('[nft] Enable and disable approval', 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 = () => helper.signTransaction(bob, helper.constructApiCall('api.tx.unique.approve', [{Substrate: charlie.address}, collectionId, tokenId, 2]));
-    await expect(approveTx()).to.be.rejected;
-    expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;
-  });
 
-  itSub('Fungible', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
-    await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
-    const tokenId = await helper.ft.getLastTokenId(collectionId);
-    const approveTx = () => helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 11n);
-    await expect(approveTx()).to.be.rejected;
+    const checkBeforeApproval = await helper.nft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(checkBeforeApproval).to.be.false;
+
+    await helper.nft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, true);
+    const checkAfterApproval = await helper.nft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(checkAfterApproval).to.be.true;
+
+    await helper.nft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, false);
+    const checkAfterDisapproval = await helper.nft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(checkAfterDisapproval).to.be.false;
   });
 
-  itSub.ifWithPallets('ReFungible', [Pallets.ReFungible], async ({helper}) => {
+  itSub.ifWithPallets('[rft] Enable and disable approval', [Pallets.ReFungible], 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 = () => helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 101n);
-    await expect(approveTx()).to.be.rejected;
+
+    const checkBeforeApproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(checkBeforeApproval).to.be.false;
+
+    await helper.rft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, true);
+    const checkAfterApproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(checkAfterApproval).to.be.true;
+
+    await helper.rft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, false);
+    const checkAfterDisapproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
+    expect(checkAfterDisapproval).to.be.false;
   });
 });
 
@@ -464,184 +649,5 @@
     await token.approve(dave, {Substrate: bob.address}, 50n);
     await expect(token.approve(dave, {Substrate: charlie.address}, 51n))
       .to.be.rejectedWith('this test would fail (since it is skipped), replace this expecting message with what would have been received');
-  });
-});
-
-describe('Integration Test approve(spender, collection_id, item_id, amount) with collection admin permissions:', () => {
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-  let charlie: IKeyringPair;
-
-  before(async () => {
-    await usingPlaygrounds(async (helper, privateKey) => {
-      const donor = await privateKey({filename: __filename});
-      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
-    });
-  });
-
-  itSub('can be called by collection admin on non-owned item', 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: alice.address});
-    await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});
-    const approveTx = () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-});
-
-describe('Negative Integration Test approve(spender, collection_id, item_id, amount):', () => {
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-  let charlie: IKeyringPair;
-
-  before(async () => {
-    await usingPlaygrounds(async (helper, privateKey) => {
-      const donor = await privateKey({filename: __filename});
-      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
-    });
-  });
-
-  itSub('[nft] Approve for a collection that does not exist', async ({helper}) => {
-    const collectionId = 1 << 32 - 1;
-    const approveTx = () => helper.nft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub('[fungible] Approve for a collection that does not exist', async ({helper}) => {
-    const collectionId = 1 << 32 - 1;
-    const approveTx = () => helper.ft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub.ifWithPallets('[refungible] Approve for a collection that does not exist', [Pallets.ReFungible], async ({helper}) => {
-    const collectionId = 1 << 32 - 1;
-    const approveTx = () => helper.rft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub('[nft] Approve for a collection that was destroyed', async ({helper}) => {
-    const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
-    await helper.nft.burn(alice, collectionId);
-    const approveTx = () => helper.nft.approveToken(alice, collectionId, 1, {Substrate: bob.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub('[fungible] Approve for a collection that was destroyed', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
-    await helper.ft.burn(alice, collectionId);
-    const approveTx = () => helper.ft.approveToken(alice, collectionId, 1, {Substrate: bob.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub.ifWithPallets('[refungible] Approve for a collection that was destroyed', [Pallets.ReFungible], async ({helper}) => {
-    const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
-    await helper.rft.burn(alice, collectionId);
-    const approveTx = () => helper.rft.approveToken(alice, collectionId, 1, {Substrate: bob.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub('[nft] Approve transfer of a token that does not exist', async ({helper}) => {
-    const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
-    const approveTx = () => helper.nft.approveToken(alice, collectionId, 2, {Substrate: bob.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub.ifWithPallets('[refungible] Approve transfer of a token that does not exist', [Pallets.ReFungible], async ({helper}) => {
-    const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
-    const approveTx = () => helper.rft.approveToken(alice, collectionId, 2, {Substrate: bob.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub('[nft] Approve using the address that does not own the approved token', 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: alice.address});
-    const approveTx = () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub('[fungible] Approve using the address that does not own the approved token', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
-    await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
-    const tokenId = await helper.ft.getLastTokenId(collectionId);
-    const approveTx = () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub.ifWithPallets('[refungible] Approve using the address that does not own the approved token', [Pallets.ReFungible], 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 = () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub.ifWithPallets('should fail if approved more ReFungibles than owned', [Pallets.ReFungible], 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});
-    await helper.rft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 100n);
-    await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 100n);
-
-    const approveTx = () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 101n);
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub('should fail if approved more Fungibles than owned', async ({helper}) => {
-    const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
-    await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
-    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}, 10n);
-    const approveTx = () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 11n);
-    await expect(approveTx()).to.be.rejected;
-  });
-
-  itSub('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', 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});
-    await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: false});
-
-    const approveTx = () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});
-    await expect(approveTx()).to.be.rejected;
-  });
-});
-
-describe('Normal user can approve other users to be wallet operator:', () => {
-  let alice: IKeyringPair;
-  let bob: IKeyringPair;
-
-  before(async () => {
-    await usingPlaygrounds(async (helper, privateKey) => {
-      const donor = await privateKey({filename: __filename});
-      [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);
-    });
-  });
-
-  itSub('[nft] Enable and disable approval', async ({helper}) => {
-    const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
-
-    const checkBeforeApproval = await helper.nft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
-    expect(checkBeforeApproval).to.be.false;
-
-    await helper.nft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, true);
-    const checkAfterApproval = await helper.nft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
-    expect(checkAfterApproval).to.be.true;
-
-    await helper.nft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, false);
-    const checkAfterDisapproval = await helper.nft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
-    expect(checkAfterDisapproval).to.be.false;
-  });
-
-  itSub.ifWithPallets('[rft] Enable and disable approval', [Pallets.ReFungible], async ({helper}) => {
-    const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
-
-    const checkBeforeApproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
-    expect(checkBeforeApproval).to.be.false;
-
-    await helper.rft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, true);
-    const checkAfterApproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
-    expect(checkAfterApproval).to.be.true;
-
-    await helper.rft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, false);
-    const checkAfterDisapproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address});
-    expect(checkAfterDisapproval).to.be.false;
   });
 });
modifiedtests/src/eth/api/ContractHelpers.soldiffbeforeafterboth
--- a/tests/src/eth/api/ContractHelpers.sol
+++ b/tests/src/eth/api/ContractHelpers.sol
@@ -183,9 +183,9 @@
 
 /// Ethereum representation of Optional value with CrossAddress.
 struct OptionCrossAddress {
-	/// TODO: field description
+	/// Whether or not this CrossAdress is valid and has meaning.
 	bool status;
-	/// TODO: field description
+	/// The underlying CrossAddress value. If the status is false, can be set to whatever.
 	CrossAddress value;
 }
 
modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-errors.ts
+++ b/tests/src/interfaces/augment-api-errors.ts
@@ -85,6 +85,10 @@
        **/
       AccountTokenLimitExceeded: AugmentedError<ApiType>;
       /**
+       * Only spending from eth mirror could be approved
+       **/
+      AddressIsNotEthMirror: AugmentedError<ApiType>;
+      /**
        * Can't transfer tokens to ethereum zero address
        **/
       AddressIsZero: AugmentedError<ApiType>;
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -1214,6 +1214,25 @@
        **/
       approve: AugmentedSubmittable<(spender: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletEvmAccountBasicCrossAccountIdRepr, u32, u32, u128]>;
       /**
+       * Allow a non-permissioned address to transfer or burn an item from owner's eth mirror.
+       * 
+       * # Permissions
+       * 
+       * * Collection owner
+       * * Collection admin
+       * * Current item owner
+       * 
+       * # Arguments
+       * 
+       * * `from`: Owner's account eth mirror
+       * * `to`: Account to be approved to make specific transactions on non-owned tokens.
+       * * `collection_id`: ID of the collection the item belongs to.
+       * * `item_id`: ID of the item transactions on which are now approved.
+       * * `amount`: Number of pieces of the item approved for a transaction (maximum of 1 for NFTs).
+       * Set to 0 to revoke the approval.
+       **/
+      approveFrom: AugmentedSubmittable<(from: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, to: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u32, u32, u128]>;
+      /**
        * Destroy a token on behalf of the owner as a non-owner account.
        * 
        * See also: [`approve`][`Pallet::approve`].
modifiedtests/src/interfaces/default/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -1216,6 +1216,7 @@
   readonly isTokenValueTooLow: boolean;
   readonly isApprovedValueTooLow: boolean;
   readonly isCantApproveMoreThanOwned: boolean;
+  readonly isAddressIsNotEthMirror: boolean;
   readonly isAddressIsZero: boolean;
   readonly isUnsupportedOperation: boolean;
   readonly isNotSufficientFounds: boolean;
@@ -1231,7 +1232,7 @@
   readonly isCollectionIsInternal: boolean;
   readonly isConfirmSponsorshipFail: boolean;
   readonly isUserIsNotCollectionAdmin: boolean;
-  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' | 'ConfirmSponsorshipFail' | 'UserIsNotCollectionAdmin';
+  readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsNotEthMirror' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal' | 'ConfirmSponsorshipFail' | 'UserIsNotCollectionAdmin';
 }
 
 /** @name PalletCommonEvent */
@@ -2306,6 +2307,14 @@
     readonly itemId: u32;
     readonly amount: u128;
   } & Struct;
+  readonly isApproveFrom: boolean;
+  readonly asApproveFrom: {
+    readonly from: PalletEvmAccountBasicCrossAccountIdRepr;
+    readonly to: PalletEvmAccountBasicCrossAccountIdRepr;
+    readonly collectionId: u32;
+    readonly itemId: u32;
+    readonly amount: u128;
+  } & Struct;
   readonly isTransferFrom: boolean;
   readonly asTransferFrom: {
     readonly from: PalletEvmAccountBasicCrossAccountIdRepr;
@@ -2345,7 +2354,7 @@
     readonly collectionId: u32;
     readonly itemId: u32;
   } & Struct;
-  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' | 'SetAllowanceForAll' | 'ForceRepairCollection' | 'ForceRepairItem';
+  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' | 'ApproveFrom' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetAllowanceForAll' | 'ForceRepairCollection' | 'ForceRepairItem';
 }
 
 /** @name PalletUniqueError */
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::dispatch::PerDispatchClass<sp_weights::weight_v2::Weight>28   **/29  FrameSupportDispatchPerDispatchClassWeight: {30    normal: 'SpWeightsWeightV2Weight',31    operational: 'SpWeightsWeightV2Weight',32    mandatory: 'SpWeightsWeightV2Weight'33  },34  /**35   * Lookup8: sp_weights::weight_v2::Weight36   **/37  SpWeightsWeightV2Weight: {38    refTime: 'Compact<u64>',39    proofSize: 'Compact<u64>'40  },41  /**42   * Lookup13: sp_runtime::generic::digest::Digest43   **/44  SpRuntimeDigest: {45    logs: 'Vec<SpRuntimeDigestDigestItem>'46  },47  /**48   * Lookup15: sp_runtime::generic::digest::DigestItem49   **/50  SpRuntimeDigestDigestItem: {51    _enum: {52      Other: 'Bytes',53      __Unused1: 'Null',54      __Unused2: 'Null',55      __Unused3: 'Null',56      Consensus: '([u8;4],Bytes)',57      Seal: '([u8;4],Bytes)',58      PreRuntime: '([u8;4],Bytes)',59      __Unused7: 'Null',60      RuntimeEnvironmentUpdated: 'Null'61    }62  },63  /**64   * Lookup18: frame_system::EventRecord<opal_runtime::RuntimeEvent, primitive_types::H256>65   **/66  FrameSystemEventRecord: {67    phase: 'FrameSystemPhase',68    event: 'Event',69    topics: 'Vec<H256>'70  },71  /**72   * Lookup20: frame_system::pallet::Event<T>73   **/74  FrameSystemEvent: {75    _enum: {76      ExtrinsicSuccess: {77        dispatchInfo: 'FrameSupportDispatchDispatchInfo',78      },79      ExtrinsicFailed: {80        dispatchError: 'SpRuntimeDispatchError',81        dispatchInfo: 'FrameSupportDispatchDispatchInfo',82      },83      CodeUpdated: 'Null',84      NewAccount: {85        account: 'AccountId32',86      },87      KilledAccount: {88        account: 'AccountId32',89      },90      Remarked: {91        _alias: {92          hash_: 'hash',93        },94        sender: 'AccountId32',95        hash_: 'H256'96      }97    }98  },99  /**100   * Lookup21: frame_support::dispatch::DispatchInfo101   **/102  FrameSupportDispatchDispatchInfo: {103    weight: 'SpWeightsWeightV2Weight',104    class: 'FrameSupportDispatchDispatchClass',105    paysFee: 'FrameSupportDispatchPays'106  },107  /**108   * Lookup22: frame_support::dispatch::DispatchClass109   **/110  FrameSupportDispatchDispatchClass: {111    _enum: ['Normal', 'Operational', 'Mandatory']112  },113  /**114   * Lookup23: frame_support::dispatch::Pays115   **/116  FrameSupportDispatchPays: {117    _enum: ['Yes', 'No']118  },119  /**120   * Lookup24: sp_runtime::DispatchError121   **/122  SpRuntimeDispatchError: {123    _enum: {124      Other: 'Null',125      CannotLookup: 'Null',126      BadOrigin: 'Null',127      Module: 'SpRuntimeModuleError',128      ConsumerRemaining: 'Null',129      NoProviders: 'Null',130      TooManyConsumers: 'Null',131      Token: 'SpRuntimeTokenError',132      Arithmetic: 'SpRuntimeArithmeticError',133      Transactional: 'SpRuntimeTransactionalError',134      Exhausted: 'Null',135      Corruption: 'Null',136      Unavailable: 'Null'137    }138  },139  /**140   * Lookup25: sp_runtime::ModuleError141   **/142  SpRuntimeModuleError: {143    index: 'u8',144    error: '[u8;4]'145  },146  /**147   * Lookup26: sp_runtime::TokenError148   **/149  SpRuntimeTokenError: {150    _enum: ['NoFunds', 'WouldDie', 'BelowMinimum', 'CannotCreate', 'UnknownAsset', 'Frozen', 'Unsupported']151  },152  /**153   * Lookup27: sp_runtime::ArithmeticError154   **/155  SpRuntimeArithmeticError: {156    _enum: ['Underflow', 'Overflow', 'DivisionByZero']157  },158  /**159   * Lookup28: sp_runtime::TransactionalError160   **/161  SpRuntimeTransactionalError: {162    _enum: ['LimitReached', 'NoLayer']163  },164  /**165   * Lookup29: cumulus_pallet_parachain_system::pallet::Event<T>166   **/167  CumulusPalletParachainSystemEvent: {168    _enum: {169      ValidationFunctionStored: 'Null',170      ValidationFunctionApplied: {171        relayChainBlockNum: 'u32',172      },173      ValidationFunctionDiscarded: 'Null',174      UpgradeAuthorized: {175        codeHash: 'H256',176      },177      DownwardMessagesReceived: {178        count: 'u32',179      },180      DownwardMessagesProcessed: {181        weightUsed: 'SpWeightsWeightV2Weight',182        dmqHead: 'H256'183      }184    }185  },186  /**187   * Lookup30: pallet_balances::pallet::Event<T, I>188   **/189  PalletBalancesEvent: {190    _enum: {191      Endowed: {192        account: 'AccountId32',193        freeBalance: 'u128',194      },195      DustLost: {196        account: 'AccountId32',197        amount: 'u128',198      },199      Transfer: {200        from: 'AccountId32',201        to: 'AccountId32',202        amount: 'u128',203      },204      BalanceSet: {205        who: 'AccountId32',206        free: 'u128',207        reserved: 'u128',208      },209      Reserved: {210        who: 'AccountId32',211        amount: 'u128',212      },213      Unreserved: {214        who: 'AccountId32',215        amount: 'u128',216      },217      ReserveRepatriated: {218        from: 'AccountId32',219        to: 'AccountId32',220        amount: 'u128',221        destinationStatus: 'FrameSupportTokensMiscBalanceStatus',222      },223      Deposit: {224        who: 'AccountId32',225        amount: 'u128',226      },227      Withdraw: {228        who: 'AccountId32',229        amount: 'u128',230      },231      Slashed: {232        who: 'AccountId32',233        amount: 'u128'234      }235    }236  },237  /**238   * Lookup31: frame_support::traits::tokens::misc::BalanceStatus239   **/240  FrameSupportTokensMiscBalanceStatus: {241    _enum: ['Free', 'Reserved']242  },243  /**244   * Lookup32: pallet_transaction_payment::pallet::Event<T>245   **/246  PalletTransactionPaymentEvent: {247    _enum: {248      TransactionFeePaid: {249        who: 'AccountId32',250        actualFee: 'u128',251        tip: 'u128'252      }253    }254  },255  /**256   * Lookup33: pallet_treasury::pallet::Event<T, I>257   **/258  PalletTreasuryEvent: {259    _enum: {260      Proposed: {261        proposalIndex: 'u32',262      },263      Spending: {264        budgetRemaining: 'u128',265      },266      Awarded: {267        proposalIndex: 'u32',268        award: 'u128',269        account: 'AccountId32',270      },271      Rejected: {272        proposalIndex: 'u32',273        slashed: 'u128',274      },275      Burnt: {276        burntFunds: 'u128',277      },278      Rollover: {279        rolloverBalance: 'u128',280      },281      Deposit: {282        value: 'u128',283      },284      SpendApproved: {285        proposalIndex: 'u32',286        amount: 'u128',287        beneficiary: 'AccountId32'288      }289    }290  },291  /**292   * Lookup34: pallet_sudo::pallet::Event<T>293   **/294  PalletSudoEvent: {295    _enum: {296      Sudid: {297        sudoResult: 'Result<Null, SpRuntimeDispatchError>',298      },299      KeyChanged: {300        oldSudoer: 'Option<AccountId32>',301      },302      SudoAsDone: {303        sudoResult: 'Result<Null, SpRuntimeDispatchError>'304      }305    }306  },307  /**308   * Lookup38: orml_vesting::module::Event<T>309   **/310  OrmlVestingModuleEvent: {311    _enum: {312      VestingScheduleAdded: {313        from: 'AccountId32',314        to: 'AccountId32',315        vestingSchedule: 'OrmlVestingVestingSchedule',316      },317      Claimed: {318        who: 'AccountId32',319        amount: 'u128',320      },321      VestingSchedulesUpdated: {322        who: 'AccountId32'323      }324    }325  },326  /**327   * Lookup39: orml_vesting::VestingSchedule<BlockNumber, Balance>328   **/329  OrmlVestingVestingSchedule: {330    start: 'u32',331    period: 'u32',332    periodCount: 'u32',333    perPeriod: 'Compact<u128>'334  },335  /**336   * Lookup41: orml_xtokens::module::Event<T>337   **/338  OrmlXtokensModuleEvent: {339    _enum: {340      TransferredMultiAssets: {341        sender: 'AccountId32',342        assets: 'XcmV1MultiassetMultiAssets',343        fee: 'XcmV1MultiAsset',344        dest: 'XcmV1MultiLocation'345      }346    }347  },348  /**349   * Lookup42: xcm::v1::multiasset::MultiAssets350   **/351  XcmV1MultiassetMultiAssets: 'Vec<XcmV1MultiAsset>',352  /**353   * Lookup44: xcm::v1::multiasset::MultiAsset354   **/355  XcmV1MultiAsset: {356    id: 'XcmV1MultiassetAssetId',357    fun: 'XcmV1MultiassetFungibility'358  },359  /**360   * Lookup45: xcm::v1::multiasset::AssetId361   **/362  XcmV1MultiassetAssetId: {363    _enum: {364      Concrete: 'XcmV1MultiLocation',365      Abstract: 'Bytes'366    }367  },368  /**369   * Lookup46: xcm::v1::multilocation::MultiLocation370   **/371  XcmV1MultiLocation: {372    parents: 'u8',373    interior: 'XcmV1MultilocationJunctions'374  },375  /**376   * Lookup47: xcm::v1::multilocation::Junctions377   **/378  XcmV1MultilocationJunctions: {379    _enum: {380      Here: 'Null',381      X1: 'XcmV1Junction',382      X2: '(XcmV1Junction,XcmV1Junction)',383      X3: '(XcmV1Junction,XcmV1Junction,XcmV1Junction)',384      X4: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',385      X5: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',386      X6: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',387      X7: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',388      X8: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)'389    }390  },391  /**392   * Lookup48: xcm::v1::junction::Junction393   **/394  XcmV1Junction: {395    _enum: {396      Parachain: 'Compact<u32>',397      AccountId32: {398        network: 'XcmV0JunctionNetworkId',399        id: '[u8;32]',400      },401      AccountIndex64: {402        network: 'XcmV0JunctionNetworkId',403        index: 'Compact<u64>',404      },405      AccountKey20: {406        network: 'XcmV0JunctionNetworkId',407        key: '[u8;20]',408      },409      PalletInstance: 'u8',410      GeneralIndex: 'Compact<u128>',411      GeneralKey: 'Bytes',412      OnlyChild: 'Null',413      Plurality: {414        id: 'XcmV0JunctionBodyId',415        part: 'XcmV0JunctionBodyPart'416      }417    }418  },419  /**420   * Lookup50: xcm::v0::junction::NetworkId421   **/422  XcmV0JunctionNetworkId: {423    _enum: {424      Any: 'Null',425      Named: 'Bytes',426      Polkadot: 'Null',427      Kusama: 'Null'428    }429  },430  /**431   * Lookup53: xcm::v0::junction::BodyId432   **/433  XcmV0JunctionBodyId: {434    _enum: {435      Unit: 'Null',436      Named: 'Bytes',437      Index: 'Compact<u32>',438      Executive: 'Null',439      Technical: 'Null',440      Legislative: 'Null',441      Judicial: 'Null'442    }443  },444  /**445   * Lookup54: xcm::v0::junction::BodyPart446   **/447  XcmV0JunctionBodyPart: {448    _enum: {449      Voice: 'Null',450      Members: {451        count: 'Compact<u32>',452      },453      Fraction: {454        nom: 'Compact<u32>',455        denom: 'Compact<u32>',456      },457      AtLeastProportion: {458        nom: 'Compact<u32>',459        denom: 'Compact<u32>',460      },461      MoreThanProportion: {462        nom: 'Compact<u32>',463        denom: 'Compact<u32>'464      }465    }466  },467  /**468   * Lookup55: xcm::v1::multiasset::Fungibility469   **/470  XcmV1MultiassetFungibility: {471    _enum: {472      Fungible: 'Compact<u128>',473      NonFungible: 'XcmV1MultiassetAssetInstance'474    }475  },476  /**477   * Lookup56: xcm::v1::multiasset::AssetInstance478   **/479  XcmV1MultiassetAssetInstance: {480    _enum: {481      Undefined: 'Null',482      Index: 'Compact<u128>',483      Array4: '[u8;4]',484      Array8: '[u8;8]',485      Array16: '[u8;16]',486      Array32: '[u8;32]',487      Blob: 'Bytes'488    }489  },490  /**491   * Lookup59: orml_tokens::module::Event<T>492   **/493  OrmlTokensModuleEvent: {494    _enum: {495      Endowed: {496        currencyId: 'PalletForeignAssetsAssetIds',497        who: 'AccountId32',498        amount: 'u128',499      },500      DustLost: {501        currencyId: 'PalletForeignAssetsAssetIds',502        who: 'AccountId32',503        amount: 'u128',504      },505      Transfer: {506        currencyId: 'PalletForeignAssetsAssetIds',507        from: 'AccountId32',508        to: 'AccountId32',509        amount: 'u128',510      },511      Reserved: {512        currencyId: 'PalletForeignAssetsAssetIds',513        who: 'AccountId32',514        amount: 'u128',515      },516      Unreserved: {517        currencyId: 'PalletForeignAssetsAssetIds',518        who: 'AccountId32',519        amount: 'u128',520      },521      ReserveRepatriated: {522        currencyId: 'PalletForeignAssetsAssetIds',523        from: 'AccountId32',524        to: 'AccountId32',525        amount: 'u128',526        status: 'FrameSupportTokensMiscBalanceStatus',527      },528      BalanceSet: {529        currencyId: 'PalletForeignAssetsAssetIds',530        who: 'AccountId32',531        free: 'u128',532        reserved: 'u128',533      },534      TotalIssuanceSet: {535        currencyId: 'PalletForeignAssetsAssetIds',536        amount: 'u128',537      },538      Withdrawn: {539        currencyId: 'PalletForeignAssetsAssetIds',540        who: 'AccountId32',541        amount: 'u128',542      },543      Slashed: {544        currencyId: 'PalletForeignAssetsAssetIds',545        who: 'AccountId32',546        freeAmount: 'u128',547        reservedAmount: 'u128',548      },549      Deposited: {550        currencyId: 'PalletForeignAssetsAssetIds',551        who: 'AccountId32',552        amount: 'u128',553      },554      LockSet: {555        lockId: '[u8;8]',556        currencyId: 'PalletForeignAssetsAssetIds',557        who: 'AccountId32',558        amount: 'u128',559      },560      LockRemoved: {561        lockId: '[u8;8]',562        currencyId: 'PalletForeignAssetsAssetIds',563        who: 'AccountId32'564      }565    }566  },567  /**568   * Lookup60: pallet_foreign_assets::AssetIds569   **/570  PalletForeignAssetsAssetIds: {571    _enum: {572      ForeignAssetId: 'u32',573      NativeAssetId: 'PalletForeignAssetsNativeCurrency'574    }575  },576  /**577   * Lookup61: pallet_foreign_assets::NativeCurrency578   **/579  PalletForeignAssetsNativeCurrency: {580    _enum: ['Here', 'Parent']581  },582  /**583   * Lookup62: cumulus_pallet_xcmp_queue::pallet::Event<T>584   **/585  CumulusPalletXcmpQueueEvent: {586    _enum: {587      Success: {588        messageHash: 'Option<H256>',589        weight: 'SpWeightsWeightV2Weight',590      },591      Fail: {592        messageHash: 'Option<H256>',593        error: 'XcmV2TraitsError',594        weight: 'SpWeightsWeightV2Weight',595      },596      BadVersion: {597        messageHash: 'Option<H256>',598      },599      BadFormat: {600        messageHash: 'Option<H256>',601      },602      UpwardMessageSent: {603        messageHash: 'Option<H256>',604      },605      XcmpMessageSent: {606        messageHash: 'Option<H256>',607      },608      OverweightEnqueued: {609        sender: 'u32',610        sentAt: 'u32',611        index: 'u64',612        required: 'SpWeightsWeightV2Weight',613      },614      OverweightServiced: {615        index: 'u64',616        used: 'SpWeightsWeightV2Weight'617      }618    }619  },620  /**621   * Lookup64: xcm::v2::traits::Error622   **/623  XcmV2TraitsError: {624    _enum: {625      Overflow: 'Null',626      Unimplemented: 'Null',627      UntrustedReserveLocation: 'Null',628      UntrustedTeleportLocation: 'Null',629      MultiLocationFull: 'Null',630      MultiLocationNotInvertible: 'Null',631      BadOrigin: 'Null',632      InvalidLocation: 'Null',633      AssetNotFound: 'Null',634      FailedToTransactAsset: 'Null',635      NotWithdrawable: 'Null',636      LocationCannotHold: 'Null',637      ExceedsMaxMessageSize: 'Null',638      DestinationUnsupported: 'Null',639      Transport: 'Null',640      Unroutable: 'Null',641      UnknownClaim: 'Null',642      FailedToDecode: 'Null',643      MaxWeightInvalid: 'Null',644      NotHoldingFees: 'Null',645      TooExpensive: 'Null',646      Trap: 'u64',647      UnhandledXcmVersion: 'Null',648      WeightLimitReached: 'u64',649      Barrier: 'Null',650      WeightNotComputable: 'Null'651    }652  },653  /**654   * Lookup66: pallet_xcm::pallet::Event<T>655   **/656  PalletXcmEvent: {657    _enum: {658      Attempted: 'XcmV2TraitsOutcome',659      Sent: '(XcmV1MultiLocation,XcmV1MultiLocation,XcmV2Xcm)',660      UnexpectedResponse: '(XcmV1MultiLocation,u64)',661      ResponseReady: '(u64,XcmV2Response)',662      Notified: '(u64,u8,u8)',663      NotifyOverweight: '(u64,u8,u8,SpWeightsWeightV2Weight,SpWeightsWeightV2Weight)',664      NotifyDispatchError: '(u64,u8,u8)',665      NotifyDecodeFailed: '(u64,u8,u8)',666      InvalidResponder: '(XcmV1MultiLocation,u64,Option<XcmV1MultiLocation>)',667      InvalidResponderVersion: '(XcmV1MultiLocation,u64)',668      ResponseTaken: 'u64',669      AssetsTrapped: '(H256,XcmV1MultiLocation,XcmVersionedMultiAssets)',670      VersionChangeNotified: '(XcmV1MultiLocation,u32)',671      SupportedVersionChanged: '(XcmV1MultiLocation,u32)',672      NotifyTargetSendFail: '(XcmV1MultiLocation,u64,XcmV2TraitsError)',673      NotifyTargetMigrationFail: '(XcmVersionedMultiLocation,u64)',674      AssetsClaimed: '(H256,XcmV1MultiLocation,XcmVersionedMultiAssets)'675    }676  },677  /**678   * Lookup67: xcm::v2::traits::Outcome679   **/680  XcmV2TraitsOutcome: {681    _enum: {682      Complete: 'u64',683      Incomplete: '(u64,XcmV2TraitsError)',684      Error: 'XcmV2TraitsError'685    }686  },687  /**688   * Lookup68: xcm::v2::Xcm<RuntimeCall>689   **/690  XcmV2Xcm: 'Vec<XcmV2Instruction>',691  /**692   * Lookup70: xcm::v2::Instruction<RuntimeCall>693   **/694  XcmV2Instruction: {695    _enum: {696      WithdrawAsset: 'XcmV1MultiassetMultiAssets',697      ReserveAssetDeposited: 'XcmV1MultiassetMultiAssets',698      ReceiveTeleportedAsset: 'XcmV1MultiassetMultiAssets',699      QueryResponse: {700        queryId: 'Compact<u64>',701        response: 'XcmV2Response',702        maxWeight: 'Compact<u64>',703      },704      TransferAsset: {705        assets: 'XcmV1MultiassetMultiAssets',706        beneficiary: 'XcmV1MultiLocation',707      },708      TransferReserveAsset: {709        assets: 'XcmV1MultiassetMultiAssets',710        dest: 'XcmV1MultiLocation',711        xcm: 'XcmV2Xcm',712      },713      Transact: {714        originType: 'XcmV0OriginKind',715        requireWeightAtMost: 'Compact<u64>',716        call: 'XcmDoubleEncoded',717      },718      HrmpNewChannelOpenRequest: {719        sender: 'Compact<u32>',720        maxMessageSize: 'Compact<u32>',721        maxCapacity: 'Compact<u32>',722      },723      HrmpChannelAccepted: {724        recipient: 'Compact<u32>',725      },726      HrmpChannelClosing: {727        initiator: 'Compact<u32>',728        sender: 'Compact<u32>',729        recipient: 'Compact<u32>',730      },731      ClearOrigin: 'Null',732      DescendOrigin: 'XcmV1MultilocationJunctions',733      ReportError: {734        queryId: 'Compact<u64>',735        dest: 'XcmV1MultiLocation',736        maxResponseWeight: 'Compact<u64>',737      },738      DepositAsset: {739        assets: 'XcmV1MultiassetMultiAssetFilter',740        maxAssets: 'Compact<u32>',741        beneficiary: 'XcmV1MultiLocation',742      },743      DepositReserveAsset: {744        assets: 'XcmV1MultiassetMultiAssetFilter',745        maxAssets: 'Compact<u32>',746        dest: 'XcmV1MultiLocation',747        xcm: 'XcmV2Xcm',748      },749      ExchangeAsset: {750        give: 'XcmV1MultiassetMultiAssetFilter',751        receive: 'XcmV1MultiassetMultiAssets',752      },753      InitiateReserveWithdraw: {754        assets: 'XcmV1MultiassetMultiAssetFilter',755        reserve: 'XcmV1MultiLocation',756        xcm: 'XcmV2Xcm',757      },758      InitiateTeleport: {759        assets: 'XcmV1MultiassetMultiAssetFilter',760        dest: 'XcmV1MultiLocation',761        xcm: 'XcmV2Xcm',762      },763      QueryHolding: {764        queryId: 'Compact<u64>',765        dest: 'XcmV1MultiLocation',766        assets: 'XcmV1MultiassetMultiAssetFilter',767        maxResponseWeight: 'Compact<u64>',768      },769      BuyExecution: {770        fees: 'XcmV1MultiAsset',771        weightLimit: 'XcmV2WeightLimit',772      },773      RefundSurplus: 'Null',774      SetErrorHandler: 'XcmV2Xcm',775      SetAppendix: 'XcmV2Xcm',776      ClearError: 'Null',777      ClaimAsset: {778        assets: 'XcmV1MultiassetMultiAssets',779        ticket: 'XcmV1MultiLocation',780      },781      Trap: 'Compact<u64>',782      SubscribeVersion: {783        queryId: 'Compact<u64>',784        maxResponseWeight: 'Compact<u64>',785      },786      UnsubscribeVersion: 'Null'787    }788  },789  /**790   * Lookup71: xcm::v2::Response791   **/792  XcmV2Response: {793    _enum: {794      Null: 'Null',795      Assets: 'XcmV1MultiassetMultiAssets',796      ExecutionResult: 'Option<(u32,XcmV2TraitsError)>',797      Version: 'u32'798    }799  },800  /**801   * Lookup74: xcm::v0::OriginKind802   **/803  XcmV0OriginKind: {804    _enum: ['Native', 'SovereignAccount', 'Superuser', 'Xcm']805  },806  /**807   * Lookup75: xcm::double_encoded::DoubleEncoded<T>808   **/809  XcmDoubleEncoded: {810    encoded: 'Bytes'811  },812  /**813   * Lookup76: xcm::v1::multiasset::MultiAssetFilter814   **/815  XcmV1MultiassetMultiAssetFilter: {816    _enum: {817      Definite: 'XcmV1MultiassetMultiAssets',818      Wild: 'XcmV1MultiassetWildMultiAsset'819    }820  },821  /**822   * Lookup77: xcm::v1::multiasset::WildMultiAsset823   **/824  XcmV1MultiassetWildMultiAsset: {825    _enum: {826      All: 'Null',827      AllOf: {828        id: 'XcmV1MultiassetAssetId',829        fun: 'XcmV1MultiassetWildFungibility'830      }831    }832  },833  /**834   * Lookup78: xcm::v1::multiasset::WildFungibility835   **/836  XcmV1MultiassetWildFungibility: {837    _enum: ['Fungible', 'NonFungible']838  },839  /**840   * Lookup79: xcm::v2::WeightLimit841   **/842  XcmV2WeightLimit: {843    _enum: {844      Unlimited: 'Null',845      Limited: 'Compact<u64>'846    }847  },848  /**849   * Lookup81: xcm::VersionedMultiAssets850   **/851  XcmVersionedMultiAssets: {852    _enum: {853      V0: 'Vec<XcmV0MultiAsset>',854      V1: 'XcmV1MultiassetMultiAssets'855    }856  },857  /**858   * Lookup83: xcm::v0::multi_asset::MultiAsset859   **/860  XcmV0MultiAsset: {861    _enum: {862      None: 'Null',863      All: 'Null',864      AllFungible: 'Null',865      AllNonFungible: 'Null',866      AllAbstractFungible: {867        id: 'Bytes',868      },869      AllAbstractNonFungible: {870        class: 'Bytes',871      },872      AllConcreteFungible: {873        id: 'XcmV0MultiLocation',874      },875      AllConcreteNonFungible: {876        class: 'XcmV0MultiLocation',877      },878      AbstractFungible: {879        id: 'Bytes',880        amount: 'Compact<u128>',881      },882      AbstractNonFungible: {883        class: 'Bytes',884        instance: 'XcmV1MultiassetAssetInstance',885      },886      ConcreteFungible: {887        id: 'XcmV0MultiLocation',888        amount: 'Compact<u128>',889      },890      ConcreteNonFungible: {891        class: 'XcmV0MultiLocation',892        instance: 'XcmV1MultiassetAssetInstance'893      }894    }895  },896  /**897   * Lookup84: xcm::v0::multi_location::MultiLocation898   **/899  XcmV0MultiLocation: {900    _enum: {901      Null: 'Null',902      X1: 'XcmV0Junction',903      X2: '(XcmV0Junction,XcmV0Junction)',904      X3: '(XcmV0Junction,XcmV0Junction,XcmV0Junction)',905      X4: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',906      X5: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',907      X6: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',908      X7: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',909      X8: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)'910    }911  },912  /**913   * Lookup85: xcm::v0::junction::Junction914   **/915  XcmV0Junction: {916    _enum: {917      Parent: 'Null',918      Parachain: 'Compact<u32>',919      AccountId32: {920        network: 'XcmV0JunctionNetworkId',921        id: '[u8;32]',922      },923      AccountIndex64: {924        network: 'XcmV0JunctionNetworkId',925        index: 'Compact<u64>',926      },927      AccountKey20: {928        network: 'XcmV0JunctionNetworkId',929        key: '[u8;20]',930      },931      PalletInstance: 'u8',932      GeneralIndex: 'Compact<u128>',933      GeneralKey: 'Bytes',934      OnlyChild: 'Null',935      Plurality: {936        id: 'XcmV0JunctionBodyId',937        part: 'XcmV0JunctionBodyPart'938      }939    }940  },941  /**942   * Lookup86: xcm::VersionedMultiLocation943   **/944  XcmVersionedMultiLocation: {945    _enum: {946      V0: 'XcmV0MultiLocation',947      V1: 'XcmV1MultiLocation'948    }949  },950  /**951   * Lookup87: cumulus_pallet_xcm::pallet::Event<T>952   **/953  CumulusPalletXcmEvent: {954    _enum: {955      InvalidFormat: '[u8;8]',956      UnsupportedVersion: '[u8;8]',957      ExecutedDownward: '([u8;8],XcmV2TraitsOutcome)'958    }959  },960  /**961   * Lookup88: cumulus_pallet_dmp_queue::pallet::Event<T>962   **/963  CumulusPalletDmpQueueEvent: {964    _enum: {965      InvalidFormat: {966        messageId: '[u8;32]',967      },968      UnsupportedVersion: {969        messageId: '[u8;32]',970      },971      ExecutedDownward: {972        messageId: '[u8;32]',973        outcome: 'XcmV2TraitsOutcome',974      },975      WeightExhausted: {976        messageId: '[u8;32]',977        remainingWeight: 'SpWeightsWeightV2Weight',978        requiredWeight: 'SpWeightsWeightV2Weight',979      },980      OverweightEnqueued: {981        messageId: '[u8;32]',982        overweightIndex: 'u64',983        requiredWeight: 'SpWeightsWeightV2Weight',984      },985      OverweightServiced: {986        overweightIndex: 'u64',987        weightUsed: 'SpWeightsWeightV2Weight'988      }989    }990  },991  /**992   * Lookup89: pallet_configuration::pallet::Event<T>993   **/994  PalletConfigurationEvent: {995    _enum: {996      NewDesiredCollators: {997        desiredCollators: 'Option<u32>',998      },999      NewCollatorLicenseBond: {1000        bondCost: 'Option<u128>',1001      },1002      NewCollatorKickThreshold: {1003        lengthInBlocks: 'Option<u32>'1004      }1005    }1006  },1007  /**1008   * Lookup92: pallet_common::pallet::Event<T>1009   **/1010  PalletCommonEvent: {1011    _enum: {1012      CollectionCreated: '(u32,u8,AccountId32)',1013      CollectionDestroyed: 'u32',1014      ItemCreated: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',1015      ItemDestroyed: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',1016      Transfer: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',1017      Approved: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',1018      ApprovedForAll: '(u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,bool)',1019      CollectionPropertySet: '(u32,Bytes)',1020      CollectionPropertyDeleted: '(u32,Bytes)',1021      TokenPropertySet: '(u32,u32,Bytes)',1022      TokenPropertyDeleted: '(u32,u32,Bytes)',1023      PropertyPermissionSet: '(u32,Bytes)',1024      AllowListAddressAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',1025      AllowListAddressRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',1026      CollectionAdminAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',1027      CollectionAdminRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',1028      CollectionLimitSet: 'u32',1029      CollectionOwnerChanged: '(u32,AccountId32)',1030      CollectionPermissionSet: 'u32',1031      CollectionSponsorSet: '(u32,AccountId32)',1032      SponsorshipConfirmed: '(u32,AccountId32)',1033      CollectionSponsorRemoved: 'u32'1034    }1035  },1036  /**1037   * Lookup95: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>1038   **/1039  PalletEvmAccountBasicCrossAccountIdRepr: {1040    _enum: {1041      Substrate: 'AccountId32',1042      Ethereum: 'H160'1043    }1044  },1045  /**1046   * Lookup99: pallet_structure::pallet::Event<T>1047   **/1048  PalletStructureEvent: {1049    _enum: {1050      Executed: 'Result<Null, SpRuntimeDispatchError>'1051    }1052  },1053  /**1054   * Lookup100: pallet_rmrk_core::pallet::Event<T>1055   **/1056  PalletRmrkCoreEvent: {1057    _enum: {1058      CollectionCreated: {1059        issuer: 'AccountId32',1060        collectionId: 'u32',1061      },1062      CollectionDestroyed: {1063        issuer: 'AccountId32',1064        collectionId: 'u32',1065      },1066      IssuerChanged: {1067        oldIssuer: 'AccountId32',1068        newIssuer: 'AccountId32',1069        collectionId: 'u32',1070      },1071      CollectionLocked: {1072        issuer: 'AccountId32',1073        collectionId: 'u32',1074      },1075      NftMinted: {1076        owner: 'AccountId32',1077        collectionId: 'u32',1078        nftId: 'u32',1079      },1080      NFTBurned: {1081        owner: 'AccountId32',1082        nftId: 'u32',1083      },1084      NFTSent: {1085        sender: 'AccountId32',1086        recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',1087        collectionId: 'u32',1088        nftId: 'u32',1089        approvalRequired: 'bool',1090      },1091      NFTAccepted: {1092        sender: 'AccountId32',1093        recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',1094        collectionId: 'u32',1095        nftId: 'u32',1096      },1097      NFTRejected: {1098        sender: 'AccountId32',1099        collectionId: 'u32',1100        nftId: 'u32',1101      },1102      PropertySet: {1103        collectionId: 'u32',1104        maybeNftId: 'Option<u32>',1105        key: 'Bytes',1106        value: 'Bytes',1107      },1108      ResourceAdded: {1109        nftId: 'u32',1110        resourceId: 'u32',1111      },1112      ResourceRemoval: {1113        nftId: 'u32',1114        resourceId: 'u32',1115      },1116      ResourceAccepted: {1117        nftId: 'u32',1118        resourceId: 'u32',1119      },1120      ResourceRemovalAccepted: {1121        nftId: 'u32',1122        resourceId: 'u32',1123      },1124      PrioritySet: {1125        collectionId: 'u32',1126        nftId: 'u32'1127      }1128    }1129  },1130  /**1131   * Lookup101: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>1132   **/1133  RmrkTraitsNftAccountIdOrCollectionNftTuple: {1134    _enum: {1135      AccountId: 'AccountId32',1136      CollectionAndNftTuple: '(u32,u32)'1137    }1138  },1139  /**1140   * Lookup104: pallet_rmrk_equip::pallet::Event<T>1141   **/1142  PalletRmrkEquipEvent: {1143    _enum: {1144      BaseCreated: {1145        issuer: 'AccountId32',1146        baseId: 'u32',1147      },1148      EquippablesUpdated: {1149        baseId: 'u32',1150        slotId: 'u32'1151      }1152    }1153  },1154  /**1155   * Lookup105: pallet_app_promotion::pallet::Event<T>1156   **/1157  PalletAppPromotionEvent: {1158    _enum: {1159      StakingRecalculation: '(AccountId32,u128,u128)',1160      Stake: '(AccountId32,u128)',1161      Unstake: '(AccountId32,u128)',1162      SetAdmin: 'AccountId32'1163    }1164  },1165  /**1166   * Lookup106: pallet_foreign_assets::module::Event<T>1167   **/1168  PalletForeignAssetsModuleEvent: {1169    _enum: {1170      ForeignAssetRegistered: {1171        assetId: 'u32',1172        assetAddress: 'XcmV1MultiLocation',1173        metadata: 'PalletForeignAssetsModuleAssetMetadata',1174      },1175      ForeignAssetUpdated: {1176        assetId: 'u32',1177        assetAddress: 'XcmV1MultiLocation',1178        metadata: 'PalletForeignAssetsModuleAssetMetadata',1179      },1180      AssetRegistered: {1181        assetId: 'PalletForeignAssetsAssetIds',1182        metadata: 'PalletForeignAssetsModuleAssetMetadata',1183      },1184      AssetUpdated: {1185        assetId: 'PalletForeignAssetsAssetIds',1186        metadata: 'PalletForeignAssetsModuleAssetMetadata'1187      }1188    }1189  },1190  /**1191   * Lookup107: pallet_foreign_assets::module::AssetMetadata<Balance>1192   **/1193  PalletForeignAssetsModuleAssetMetadata: {1194    name: 'Bytes',1195    symbol: 'Bytes',1196    decimals: 'u8',1197    minimalBalance: 'u128'1198  },1199  /**1200   * Lookup108: pallet_evm::pallet::Event<T>1201   **/1202  PalletEvmEvent: {1203    _enum: {1204      Log: {1205        log: 'EthereumLog',1206      },1207      Created: {1208        address: 'H160',1209      },1210      CreatedFailed: {1211        address: 'H160',1212      },1213      Executed: {1214        address: 'H160',1215      },1216      ExecutedFailed: {1217        address: 'H160'1218      }1219    }1220  },1221  /**1222   * Lookup109: ethereum::log::Log1223   **/1224  EthereumLog: {1225    address: 'H160',1226    topics: 'Vec<H256>',1227    data: 'Bytes'1228  },1229  /**1230   * Lookup111: pallet_ethereum::pallet::Event1231   **/1232  PalletEthereumEvent: {1233    _enum: {1234      Executed: {1235        from: 'H160',1236        to: 'H160',1237        transactionHash: 'H256',1238        exitReason: 'EvmCoreErrorExitReason'1239      }1240    }1241  },1242  /**1243   * Lookup112: evm_core::error::ExitReason1244   **/1245  EvmCoreErrorExitReason: {1246    _enum: {1247      Succeed: 'EvmCoreErrorExitSucceed',1248      Error: 'EvmCoreErrorExitError',1249      Revert: 'EvmCoreErrorExitRevert',1250      Fatal: 'EvmCoreErrorExitFatal'1251    }1252  },1253  /**1254   * Lookup113: evm_core::error::ExitSucceed1255   **/1256  EvmCoreErrorExitSucceed: {1257    _enum: ['Stopped', 'Returned', 'Suicided']1258  },1259  /**1260   * Lookup114: evm_core::error::ExitError1261   **/1262  EvmCoreErrorExitError: {1263    _enum: {1264      StackUnderflow: 'Null',1265      StackOverflow: 'Null',1266      InvalidJump: 'Null',1267      InvalidRange: 'Null',1268      DesignatedInvalid: 'Null',1269      CallTooDeep: 'Null',1270      CreateCollision: 'Null',1271      CreateContractLimit: 'Null',1272      OutOfOffset: 'Null',1273      OutOfGas: 'Null',1274      OutOfFund: 'Null',1275      PCUnderflow: 'Null',1276      CreateEmpty: 'Null',1277      Other: 'Text',1278      InvalidCode: 'Null'1279    }1280  },1281  /**1282   * Lookup117: evm_core::error::ExitRevert1283   **/1284  EvmCoreErrorExitRevert: {1285    _enum: ['Reverted']1286  },1287  /**1288   * Lookup118: evm_core::error::ExitFatal1289   **/1290  EvmCoreErrorExitFatal: {1291    _enum: {1292      NotSupported: 'Null',1293      UnhandledInterrupt: 'Null',1294      CallErrorAsFatal: 'EvmCoreErrorExitError',1295      Other: 'Text'1296    }1297  },1298  /**1299   * Lookup119: pallet_evm_contract_helpers::pallet::Event<T>1300   **/1301  PalletEvmContractHelpersEvent: {1302    _enum: {1303      ContractSponsorSet: '(H160,AccountId32)',1304      ContractSponsorshipConfirmed: '(H160,AccountId32)',1305      ContractSponsorRemoved: 'H160'1306    }1307  },1308  /**1309   * Lookup120: pallet_evm_migration::pallet::Event<T>1310   **/1311  PalletEvmMigrationEvent: {1312    _enum: ['TestEvent']1313  },1314  /**1315   * Lookup121: pallet_maintenance::pallet::Event<T>1316   **/1317  PalletMaintenanceEvent: {1318    _enum: ['MaintenanceEnabled', 'MaintenanceDisabled']1319  },1320  /**1321   * Lookup122: pallet_test_utils::pallet::Event<T>1322   **/1323  PalletTestUtilsEvent: {1324    _enum: ['ValueIsSet', 'ShouldRollback', 'BatchCompleted']1325  },1326  /**1327   * Lookup123: frame_system::Phase1328   **/1329  FrameSystemPhase: {1330    _enum: {1331      ApplyExtrinsic: 'u32',1332      Finalization: 'Null',1333      Initialization: 'Null'1334    }1335  },1336  /**1337   * Lookup126: frame_system::LastRuntimeUpgradeInfo1338   **/1339  FrameSystemLastRuntimeUpgradeInfo: {1340    specVersion: 'Compact<u32>',1341    specName: 'Text'1342  },1343  /**1344   * Lookup127: frame_system::pallet::Call<T>1345   **/1346  FrameSystemCall: {1347    _enum: {1348      remark: {1349        remark: 'Bytes',1350      },1351      set_heap_pages: {1352        pages: 'u64',1353      },1354      set_code: {1355        code: 'Bytes',1356      },1357      set_code_without_checks: {1358        code: 'Bytes',1359      },1360      set_storage: {1361        items: 'Vec<(Bytes,Bytes)>',1362      },1363      kill_storage: {1364        _alias: {1365          keys_: 'keys',1366        },1367        keys_: 'Vec<Bytes>',1368      },1369      kill_prefix: {1370        prefix: 'Bytes',1371        subkeys: 'u32',1372      },1373      remark_with_event: {1374        remark: 'Bytes'1375      }1376    }1377  },1378  /**1379   * Lookup131: frame_system::limits::BlockWeights1380   **/1381  FrameSystemLimitsBlockWeights: {1382    baseBlock: 'SpWeightsWeightV2Weight',1383    maxBlock: 'SpWeightsWeightV2Weight',1384    perClass: 'FrameSupportDispatchPerDispatchClassWeightsPerClass'1385  },1386  /**1387   * Lookup132: frame_support::dispatch::PerDispatchClass<frame_system::limits::WeightsPerClass>1388   **/1389  FrameSupportDispatchPerDispatchClassWeightsPerClass: {1390    normal: 'FrameSystemLimitsWeightsPerClass',1391    operational: 'FrameSystemLimitsWeightsPerClass',1392    mandatory: 'FrameSystemLimitsWeightsPerClass'1393  },1394  /**1395   * Lookup133: frame_system::limits::WeightsPerClass1396   **/1397  FrameSystemLimitsWeightsPerClass: {1398    baseExtrinsic: 'SpWeightsWeightV2Weight',1399    maxExtrinsic: 'Option<SpWeightsWeightV2Weight>',1400    maxTotal: 'Option<SpWeightsWeightV2Weight>',1401    reserved: 'Option<SpWeightsWeightV2Weight>'1402  },1403  /**1404   * Lookup135: frame_system::limits::BlockLength1405   **/1406  FrameSystemLimitsBlockLength: {1407    max: 'FrameSupportDispatchPerDispatchClassU32'1408  },1409  /**1410   * Lookup136: frame_support::dispatch::PerDispatchClass<T>1411   **/1412  FrameSupportDispatchPerDispatchClassU32: {1413    normal: 'u32',1414    operational: 'u32',1415    mandatory: 'u32'1416  },1417  /**1418   * Lookup137: sp_weights::RuntimeDbWeight1419   **/1420  SpWeightsRuntimeDbWeight: {1421    read: 'u64',1422    write: 'u64'1423  },1424  /**1425   * Lookup138: sp_version::RuntimeVersion1426   **/1427  SpVersionRuntimeVersion: {1428    specName: 'Text',1429    implName: 'Text',1430    authoringVersion: 'u32',1431    specVersion: 'u32',1432    implVersion: 'u32',1433    apis: 'Vec<([u8;8],u32)>',1434    transactionVersion: 'u32',1435    stateVersion: 'u8'1436  },1437  /**1438   * Lookup143: frame_system::pallet::Error<T>1439   **/1440  FrameSystemError: {1441    _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered']1442  },1443  /**1444   * Lookup144: polkadot_primitives::v2::PersistedValidationData<primitive_types::H256, N>1445   **/1446  PolkadotPrimitivesV2PersistedValidationData: {1447    parentHead: 'Bytes',1448    relayParentNumber: 'u32',1449    relayParentStorageRoot: 'H256',1450    maxPovSize: 'u32'1451  },1452  /**1453   * Lookup147: polkadot_primitives::v2::UpgradeRestriction1454   **/1455  PolkadotPrimitivesV2UpgradeRestriction: {1456    _enum: ['Present']1457  },1458  /**1459   * Lookup148: sp_trie::storage_proof::StorageProof1460   **/1461  SpTrieStorageProof: {1462    trieNodes: 'BTreeSet<Bytes>'1463  },1464  /**1465   * Lookup150: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot1466   **/1467  CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: {1468    dmqMqcHead: 'H256',1469    relayDispatchQueueSize: '(u32,u32)',1470    ingressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>',1471    egressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>'1472  },1473  /**1474   * Lookup153: polkadot_primitives::v2::AbridgedHrmpChannel1475   **/1476  PolkadotPrimitivesV2AbridgedHrmpChannel: {1477    maxCapacity: 'u32',1478    maxTotalSize: 'u32',1479    maxMessageSize: 'u32',1480    msgCount: 'u32',1481    totalSize: 'u32',1482    mqcHead: 'Option<H256>'1483  },1484  /**1485   * Lookup154: polkadot_primitives::v2::AbridgedHostConfiguration1486   **/1487  PolkadotPrimitivesV2AbridgedHostConfiguration: {1488    maxCodeSize: 'u32',1489    maxHeadDataSize: 'u32',1490    maxUpwardQueueCount: 'u32',1491    maxUpwardQueueSize: 'u32',1492    maxUpwardMessageSize: 'u32',1493    maxUpwardMessageNumPerCandidate: 'u32',1494    hrmpMaxMessageNumPerCandidate: 'u32',1495    validationUpgradeCooldown: 'u32',1496    validationUpgradeDelay: 'u32'1497  },1498  /**1499   * Lookup160: polkadot_core_primitives::OutboundHrmpMessage<polkadot_parachain::primitives::Id>1500   **/1501  PolkadotCorePrimitivesOutboundHrmpMessage: {1502    recipient: 'u32',1503    data: 'Bytes'1504  },1505  /**1506   * Lookup161: cumulus_pallet_parachain_system::pallet::Call<T>1507   **/1508  CumulusPalletParachainSystemCall: {1509    _enum: {1510      set_validation_data: {1511        data: 'CumulusPrimitivesParachainInherentParachainInherentData',1512      },1513      sudo_send_upward_message: {1514        message: 'Bytes',1515      },1516      authorize_upgrade: {1517        codeHash: 'H256',1518      },1519      enact_authorized_upgrade: {1520        code: 'Bytes'1521      }1522    }1523  },1524  /**1525   * Lookup162: cumulus_primitives_parachain_inherent::ParachainInherentData1526   **/1527  CumulusPrimitivesParachainInherentParachainInherentData: {1528    validationData: 'PolkadotPrimitivesV2PersistedValidationData',1529    relayChainState: 'SpTrieStorageProof',1530    downwardMessages: 'Vec<PolkadotCorePrimitivesInboundDownwardMessage>',1531    horizontalMessages: 'BTreeMap<u32, Vec<PolkadotCorePrimitivesInboundHrmpMessage>>'1532  },1533  /**1534   * Lookup164: polkadot_core_primitives::InboundDownwardMessage<BlockNumber>1535   **/1536  PolkadotCorePrimitivesInboundDownwardMessage: {1537    sentAt: 'u32',1538    msg: 'Bytes'1539  },1540  /**1541   * Lookup167: polkadot_core_primitives::InboundHrmpMessage<BlockNumber>1542   **/1543  PolkadotCorePrimitivesInboundHrmpMessage: {1544    sentAt: 'u32',1545    data: 'Bytes'1546  },1547  /**1548   * Lookup170: cumulus_pallet_parachain_system::pallet::Error<T>1549   **/1550  CumulusPalletParachainSystemError: {1551    _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized']1552  },1553  /**1554   * Lookup172: pallet_balances::BalanceLock<Balance>1555   **/1556  PalletBalancesBalanceLock: {1557    id: '[u8;8]',1558    amount: 'u128',1559    reasons: 'PalletBalancesReasons'1560  },1561  /**1562   * Lookup173: pallet_balances::Reasons1563   **/1564  PalletBalancesReasons: {1565    _enum: ['Fee', 'Misc', 'All']1566  },1567  /**1568   * Lookup176: pallet_balances::ReserveData<ReserveIdentifier, Balance>1569   **/1570  PalletBalancesReserveData: {1571    id: '[u8;16]',1572    amount: 'u128'1573  },1574  /**1575   * Lookup178: pallet_balances::pallet::Call<T, I>1576   **/1577  PalletBalancesCall: {1578    _enum: {1579      transfer: {1580        dest: 'MultiAddress',1581        value: 'Compact<u128>',1582      },1583      set_balance: {1584        who: 'MultiAddress',1585        newFree: 'Compact<u128>',1586        newReserved: 'Compact<u128>',1587      },1588      force_transfer: {1589        source: 'MultiAddress',1590        dest: 'MultiAddress',1591        value: 'Compact<u128>',1592      },1593      transfer_keep_alive: {1594        dest: 'MultiAddress',1595        value: 'Compact<u128>',1596      },1597      transfer_all: {1598        dest: 'MultiAddress',1599        keepAlive: 'bool',1600      },1601      force_unreserve: {1602        who: 'MultiAddress',1603        amount: 'u128'1604      }1605    }1606  },1607  /**1608   * Lookup181: pallet_balances::pallet::Error<T, I>1609   **/1610  PalletBalancesError: {1611    _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves']1612  },1613  /**1614   * Lookup183: pallet_timestamp::pallet::Call<T>1615   **/1616  PalletTimestampCall: {1617    _enum: {1618      set: {1619        now: 'Compact<u64>'1620      }1621    }1622  },1623  /**1624   * Lookup185: pallet_transaction_payment::Releases1625   **/1626  PalletTransactionPaymentReleases: {1627    _enum: ['V1Ancient', 'V2']1628  },1629  /**1630   * Lookup186: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>1631   **/1632  PalletTreasuryProposal: {1633    proposer: 'AccountId32',1634    value: 'u128',1635    beneficiary: 'AccountId32',1636    bond: 'u128'1637  },1638  /**1639   * Lookup189: pallet_treasury::pallet::Call<T, I>1640   **/1641  PalletTreasuryCall: {1642    _enum: {1643      propose_spend: {1644        value: 'Compact<u128>',1645        beneficiary: 'MultiAddress',1646      },1647      reject_proposal: {1648        proposalId: 'Compact<u32>',1649      },1650      approve_proposal: {1651        proposalId: 'Compact<u32>',1652      },1653      spend: {1654        amount: 'Compact<u128>',1655        beneficiary: 'MultiAddress',1656      },1657      remove_approval: {1658        proposalId: 'Compact<u32>'1659      }1660    }1661  },1662  /**1663   * Lookup191: frame_support::PalletId1664   **/1665  FrameSupportPalletId: '[u8;8]',1666  /**1667   * Lookup192: pallet_treasury::pallet::Error<T, I>1668   **/1669  PalletTreasuryError: {1670    _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'InsufficientPermission', 'ProposalNotApproved']1671  },1672  /**1673   * Lookup193: pallet_sudo::pallet::Call<T>1674   **/1675  PalletSudoCall: {1676    _enum: {1677      sudo: {1678        call: 'Call',1679      },1680      sudo_unchecked_weight: {1681        call: 'Call',1682        weight: 'SpWeightsWeightV2Weight',1683      },1684      set_key: {1685        _alias: {1686          new_: 'new',1687        },1688        new_: 'MultiAddress',1689      },1690      sudo_as: {1691        who: 'MultiAddress',1692        call: 'Call'1693      }1694    }1695  },1696  /**1697   * Lookup195: orml_vesting::module::Call<T>1698   **/1699  OrmlVestingModuleCall: {1700    _enum: {1701      claim: 'Null',1702      vested_transfer: {1703        dest: 'MultiAddress',1704        schedule: 'OrmlVestingVestingSchedule',1705      },1706      update_vesting_schedules: {1707        who: 'MultiAddress',1708        vestingSchedules: 'Vec<OrmlVestingVestingSchedule>',1709      },1710      claim_for: {1711        dest: 'MultiAddress'1712      }1713    }1714  },1715  /**1716   * Lookup197: orml_xtokens::module::Call<T>1717   **/1718  OrmlXtokensModuleCall: {1719    _enum: {1720      transfer: {1721        currencyId: 'PalletForeignAssetsAssetIds',1722        amount: 'u128',1723        dest: 'XcmVersionedMultiLocation',1724        destWeightLimit: 'XcmV2WeightLimit',1725      },1726      transfer_multiasset: {1727        asset: 'XcmVersionedMultiAsset',1728        dest: 'XcmVersionedMultiLocation',1729        destWeightLimit: 'XcmV2WeightLimit',1730      },1731      transfer_with_fee: {1732        currencyId: 'PalletForeignAssetsAssetIds',1733        amount: 'u128',1734        fee: 'u128',1735        dest: 'XcmVersionedMultiLocation',1736        destWeightLimit: 'XcmV2WeightLimit',1737      },1738      transfer_multiasset_with_fee: {1739        asset: 'XcmVersionedMultiAsset',1740        fee: 'XcmVersionedMultiAsset',1741        dest: 'XcmVersionedMultiLocation',1742        destWeightLimit: 'XcmV2WeightLimit',1743      },1744      transfer_multicurrencies: {1745        currencies: 'Vec<(PalletForeignAssetsAssetIds,u128)>',1746        feeItem: 'u32',1747        dest: 'XcmVersionedMultiLocation',1748        destWeightLimit: 'XcmV2WeightLimit',1749      },1750      transfer_multiassets: {1751        assets: 'XcmVersionedMultiAssets',1752        feeItem: 'u32',1753        dest: 'XcmVersionedMultiLocation',1754        destWeightLimit: 'XcmV2WeightLimit'1755      }1756    }1757  },1758  /**1759   * Lookup198: xcm::VersionedMultiAsset1760   **/1761  XcmVersionedMultiAsset: {1762    _enum: {1763      V0: 'XcmV0MultiAsset',1764      V1: 'XcmV1MultiAsset'1765    }1766  },1767  /**1768   * Lookup201: orml_tokens::module::Call<T>1769   **/1770  OrmlTokensModuleCall: {1771    _enum: {1772      transfer: {1773        dest: 'MultiAddress',1774        currencyId: 'PalletForeignAssetsAssetIds',1775        amount: 'Compact<u128>',1776      },1777      transfer_all: {1778        dest: 'MultiAddress',1779        currencyId: 'PalletForeignAssetsAssetIds',1780        keepAlive: 'bool',1781      },1782      transfer_keep_alive: {1783        dest: 'MultiAddress',1784        currencyId: 'PalletForeignAssetsAssetIds',1785        amount: 'Compact<u128>',1786      },1787      force_transfer: {1788        source: 'MultiAddress',1789        dest: 'MultiAddress',1790        currencyId: 'PalletForeignAssetsAssetIds',1791        amount: 'Compact<u128>',1792      },1793      set_balance: {1794        who: 'MultiAddress',1795        currencyId: 'PalletForeignAssetsAssetIds',1796        newFree: 'Compact<u128>',1797        newReserved: 'Compact<u128>'1798      }1799    }1800  },1801  /**1802   * Lookup202: cumulus_pallet_xcmp_queue::pallet::Call<T>1803   **/1804  CumulusPalletXcmpQueueCall: {1805    _enum: {1806      service_overweight: {1807        index: 'u64',1808        weightLimit: 'u64',1809      },1810      suspend_xcm_execution: 'Null',1811      resume_xcm_execution: 'Null',1812      update_suspend_threshold: {1813        _alias: {1814          new_: 'new',1815        },1816        new_: 'u32',1817      },1818      update_drop_threshold: {1819        _alias: {1820          new_: 'new',1821        },1822        new_: 'u32',1823      },1824      update_resume_threshold: {1825        _alias: {1826          new_: 'new',1827        },1828        new_: 'u32',1829      },1830      update_threshold_weight: {1831        _alias: {1832          new_: 'new',1833        },1834        new_: 'u64',1835      },1836      update_weight_restrict_decay: {1837        _alias: {1838          new_: 'new',1839        },1840        new_: 'u64',1841      },1842      update_xcmp_max_individual_weight: {1843        _alias: {1844          new_: 'new',1845        },1846        new_: 'u64'1847      }1848    }1849  },1850  /**1851   * Lookup203: pallet_xcm::pallet::Call<T>1852   **/1853  PalletXcmCall: {1854    _enum: {1855      send: {1856        dest: 'XcmVersionedMultiLocation',1857        message: 'XcmVersionedXcm',1858      },1859      teleport_assets: {1860        dest: 'XcmVersionedMultiLocation',1861        beneficiary: 'XcmVersionedMultiLocation',1862        assets: 'XcmVersionedMultiAssets',1863        feeAssetItem: 'u32',1864      },1865      reserve_transfer_assets: {1866        dest: 'XcmVersionedMultiLocation',1867        beneficiary: 'XcmVersionedMultiLocation',1868        assets: 'XcmVersionedMultiAssets',1869        feeAssetItem: 'u32',1870      },1871      execute: {1872        message: 'XcmVersionedXcm',1873        maxWeight: 'u64',1874      },1875      force_xcm_version: {1876        location: 'XcmV1MultiLocation',1877        xcmVersion: 'u32',1878      },1879      force_default_xcm_version: {1880        maybeXcmVersion: 'Option<u32>',1881      },1882      force_subscribe_version_notify: {1883        location: 'XcmVersionedMultiLocation',1884      },1885      force_unsubscribe_version_notify: {1886        location: 'XcmVersionedMultiLocation',1887      },1888      limited_reserve_transfer_assets: {1889        dest: 'XcmVersionedMultiLocation',1890        beneficiary: 'XcmVersionedMultiLocation',1891        assets: 'XcmVersionedMultiAssets',1892        feeAssetItem: 'u32',1893        weightLimit: 'XcmV2WeightLimit',1894      },1895      limited_teleport_assets: {1896        dest: 'XcmVersionedMultiLocation',1897        beneficiary: 'XcmVersionedMultiLocation',1898        assets: 'XcmVersionedMultiAssets',1899        feeAssetItem: 'u32',1900        weightLimit: 'XcmV2WeightLimit'1901      }1902    }1903  },1904  /**1905   * Lookup204: xcm::VersionedXcm<RuntimeCall>1906   **/1907  XcmVersionedXcm: {1908    _enum: {1909      V0: 'XcmV0Xcm',1910      V1: 'XcmV1Xcm',1911      V2: 'XcmV2Xcm'1912    }1913  },1914  /**1915   * Lookup205: xcm::v0::Xcm<RuntimeCall>1916   **/1917  XcmV0Xcm: {1918    _enum: {1919      WithdrawAsset: {1920        assets: 'Vec<XcmV0MultiAsset>',1921        effects: 'Vec<XcmV0Order>',1922      },1923      ReserveAssetDeposit: {1924        assets: 'Vec<XcmV0MultiAsset>',1925        effects: 'Vec<XcmV0Order>',1926      },1927      TeleportAsset: {1928        assets: 'Vec<XcmV0MultiAsset>',1929        effects: 'Vec<XcmV0Order>',1930      },1931      QueryResponse: {1932        queryId: 'Compact<u64>',1933        response: 'XcmV0Response',1934      },1935      TransferAsset: {1936        assets: 'Vec<XcmV0MultiAsset>',1937        dest: 'XcmV0MultiLocation',1938      },1939      TransferReserveAsset: {1940        assets: 'Vec<XcmV0MultiAsset>',1941        dest: 'XcmV0MultiLocation',1942        effects: 'Vec<XcmV0Order>',1943      },1944      Transact: {1945        originType: 'XcmV0OriginKind',1946        requireWeightAtMost: 'u64',1947        call: 'XcmDoubleEncoded',1948      },1949      HrmpNewChannelOpenRequest: {1950        sender: 'Compact<u32>',1951        maxMessageSize: 'Compact<u32>',1952        maxCapacity: 'Compact<u32>',1953      },1954      HrmpChannelAccepted: {1955        recipient: 'Compact<u32>',1956      },1957      HrmpChannelClosing: {1958        initiator: 'Compact<u32>',1959        sender: 'Compact<u32>',1960        recipient: 'Compact<u32>',1961      },1962      RelayedFrom: {1963        who: 'XcmV0MultiLocation',1964        message: 'XcmV0Xcm'1965      }1966    }1967  },1968  /**1969   * Lookup207: xcm::v0::order::Order<RuntimeCall>1970   **/1971  XcmV0Order: {1972    _enum: {1973      Null: 'Null',1974      DepositAsset: {1975        assets: 'Vec<XcmV0MultiAsset>',1976        dest: 'XcmV0MultiLocation',1977      },1978      DepositReserveAsset: {1979        assets: 'Vec<XcmV0MultiAsset>',1980        dest: 'XcmV0MultiLocation',1981        effects: 'Vec<XcmV0Order>',1982      },1983      ExchangeAsset: {1984        give: 'Vec<XcmV0MultiAsset>',1985        receive: 'Vec<XcmV0MultiAsset>',1986      },1987      InitiateReserveWithdraw: {1988        assets: 'Vec<XcmV0MultiAsset>',1989        reserve: 'XcmV0MultiLocation',1990        effects: 'Vec<XcmV0Order>',1991      },1992      InitiateTeleport: {1993        assets: 'Vec<XcmV0MultiAsset>',1994        dest: 'XcmV0MultiLocation',1995        effects: 'Vec<XcmV0Order>',1996      },1997      QueryHolding: {1998        queryId: 'Compact<u64>',1999        dest: 'XcmV0MultiLocation',2000        assets: 'Vec<XcmV0MultiAsset>',2001      },2002      BuyExecution: {2003        fees: 'XcmV0MultiAsset',2004        weight: 'u64',2005        debt: 'u64',2006        haltOnError: 'bool',2007        xcm: 'Vec<XcmV0Xcm>'2008      }2009    }2010  },2011  /**2012   * Lookup209: xcm::v0::Response2013   **/2014  XcmV0Response: {2015    _enum: {2016      Assets: 'Vec<XcmV0MultiAsset>'2017    }2018  },2019  /**2020   * Lookup210: xcm::v1::Xcm<RuntimeCall>2021   **/2022  XcmV1Xcm: {2023    _enum: {2024      WithdrawAsset: {2025        assets: 'XcmV1MultiassetMultiAssets',2026        effects: 'Vec<XcmV1Order>',2027      },2028      ReserveAssetDeposited: {2029        assets: 'XcmV1MultiassetMultiAssets',2030        effects: 'Vec<XcmV1Order>',2031      },2032      ReceiveTeleportedAsset: {2033        assets: 'XcmV1MultiassetMultiAssets',2034        effects: 'Vec<XcmV1Order>',2035      },2036      QueryResponse: {2037        queryId: 'Compact<u64>',2038        response: 'XcmV1Response',2039      },2040      TransferAsset: {2041        assets: 'XcmV1MultiassetMultiAssets',2042        beneficiary: 'XcmV1MultiLocation',2043      },2044      TransferReserveAsset: {2045        assets: 'XcmV1MultiassetMultiAssets',2046        dest: 'XcmV1MultiLocation',2047        effects: 'Vec<XcmV1Order>',2048      },2049      Transact: {2050        originType: 'XcmV0OriginKind',2051        requireWeightAtMost: 'u64',2052        call: 'XcmDoubleEncoded',2053      },2054      HrmpNewChannelOpenRequest: {2055        sender: 'Compact<u32>',2056        maxMessageSize: 'Compact<u32>',2057        maxCapacity: 'Compact<u32>',2058      },2059      HrmpChannelAccepted: {2060        recipient: 'Compact<u32>',2061      },2062      HrmpChannelClosing: {2063        initiator: 'Compact<u32>',2064        sender: 'Compact<u32>',2065        recipient: 'Compact<u32>',2066      },2067      RelayedFrom: {2068        who: 'XcmV1MultilocationJunctions',2069        message: 'XcmV1Xcm',2070      },2071      SubscribeVersion: {2072        queryId: 'Compact<u64>',2073        maxResponseWeight: 'Compact<u64>',2074      },2075      UnsubscribeVersion: 'Null'2076    }2077  },2078  /**2079   * Lookup212: xcm::v1::order::Order<RuntimeCall>2080   **/2081  XcmV1Order: {2082    _enum: {2083      Noop: 'Null',2084      DepositAsset: {2085        assets: 'XcmV1MultiassetMultiAssetFilter',2086        maxAssets: 'u32',2087        beneficiary: 'XcmV1MultiLocation',2088      },2089      DepositReserveAsset: {2090        assets: 'XcmV1MultiassetMultiAssetFilter',2091        maxAssets: 'u32',2092        dest: 'XcmV1MultiLocation',2093        effects: 'Vec<XcmV1Order>',2094      },2095      ExchangeAsset: {2096        give: 'XcmV1MultiassetMultiAssetFilter',2097        receive: 'XcmV1MultiassetMultiAssets',2098      },2099      InitiateReserveWithdraw: {2100        assets: 'XcmV1MultiassetMultiAssetFilter',2101        reserve: 'XcmV1MultiLocation',2102        effects: 'Vec<XcmV1Order>',2103      },2104      InitiateTeleport: {2105        assets: 'XcmV1MultiassetMultiAssetFilter',2106        dest: 'XcmV1MultiLocation',2107        effects: 'Vec<XcmV1Order>',2108      },2109      QueryHolding: {2110        queryId: 'Compact<u64>',2111        dest: 'XcmV1MultiLocation',2112        assets: 'XcmV1MultiassetMultiAssetFilter',2113      },2114      BuyExecution: {2115        fees: 'XcmV1MultiAsset',2116        weight: 'u64',2117        debt: 'u64',2118        haltOnError: 'bool',2119        instructions: 'Vec<XcmV1Xcm>'2120      }2121    }2122  },2123  /**2124   * Lookup214: xcm::v1::Response2125   **/2126  XcmV1Response: {2127    _enum: {2128      Assets: 'XcmV1MultiassetMultiAssets',2129      Version: 'u32'2130    }2131  },2132  /**2133   * Lookup228: cumulus_pallet_xcm::pallet::Call<T>2134   **/2135  CumulusPalletXcmCall: 'Null',2136  /**2137   * Lookup229: cumulus_pallet_dmp_queue::pallet::Call<T>2138   **/2139  CumulusPalletDmpQueueCall: {2140    _enum: {2141      service_overweight: {2142        index: 'u64',2143        weightLimit: 'u64'2144      }2145    }2146  },2147  /**2148   * Lookup230: pallet_inflation::pallet::Call<T>2149   **/2150  PalletInflationCall: {2151    _enum: {2152      start_inflation: {2153        inflationStartRelayBlock: 'u32'2154      }2155    }2156  },2157  /**2158   * Lookup231: pallet_unique::Call<T>2159   **/2160  PalletUniqueCall: {2161    _enum: {2162      create_collection: {2163        collectionName: 'Vec<u16>',2164        collectionDescription: 'Vec<u16>',2165        tokenPrefix: 'Bytes',2166        mode: 'UpDataStructsCollectionMode',2167      },2168      create_collection_ex: {2169        data: 'UpDataStructsCreateCollectionData',2170      },2171      destroy_collection: {2172        collectionId: 'u32',2173      },2174      add_to_allow_list: {2175        collectionId: 'u32',2176        address: 'PalletEvmAccountBasicCrossAccountIdRepr',2177      },2178      remove_from_allow_list: {2179        collectionId: 'u32',2180        address: 'PalletEvmAccountBasicCrossAccountIdRepr',2181      },2182      change_collection_owner: {2183        collectionId: 'u32',2184        newOwner: 'AccountId32',2185      },2186      add_collection_admin: {2187        collectionId: 'u32',2188        newAdminId: 'PalletEvmAccountBasicCrossAccountIdRepr',2189      },2190      remove_collection_admin: {2191        collectionId: 'u32',2192        accountId: 'PalletEvmAccountBasicCrossAccountIdRepr',2193      },2194      set_collection_sponsor: {2195        collectionId: 'u32',2196        newSponsor: 'AccountId32',2197      },2198      confirm_sponsorship: {2199        collectionId: 'u32',2200      },2201      remove_collection_sponsor: {2202        collectionId: 'u32',2203      },2204      create_item: {2205        collectionId: 'u32',2206        owner: 'PalletEvmAccountBasicCrossAccountIdRepr',2207        data: 'UpDataStructsCreateItemData',2208      },2209      create_multiple_items: {2210        collectionId: 'u32',2211        owner: 'PalletEvmAccountBasicCrossAccountIdRepr',2212        itemsData: 'Vec<UpDataStructsCreateItemData>',2213      },2214      set_collection_properties: {2215        collectionId: 'u32',2216        properties: 'Vec<UpDataStructsProperty>',2217      },2218      delete_collection_properties: {2219        collectionId: 'u32',2220        propertyKeys: 'Vec<Bytes>',2221      },2222      set_token_properties: {2223        collectionId: 'u32',2224        tokenId: 'u32',2225        properties: 'Vec<UpDataStructsProperty>',2226      },2227      delete_token_properties: {2228        collectionId: 'u32',2229        tokenId: 'u32',2230        propertyKeys: 'Vec<Bytes>',2231      },2232      set_token_property_permissions: {2233        collectionId: 'u32',2234        propertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',2235      },2236      create_multiple_items_ex: {2237        collectionId: 'u32',2238        data: 'UpDataStructsCreateItemExData',2239      },2240      set_transfers_enabled_flag: {2241        collectionId: 'u32',2242        value: 'bool',2243      },2244      burn_item: {2245        collectionId: 'u32',2246        itemId: 'u32',2247        value: 'u128',2248      },2249      burn_from: {2250        collectionId: 'u32',2251        from: 'PalletEvmAccountBasicCrossAccountIdRepr',2252        itemId: 'u32',2253        value: 'u128',2254      },2255      transfer: {2256        recipient: 'PalletEvmAccountBasicCrossAccountIdRepr',2257        collectionId: 'u32',2258        itemId: 'u32',2259        value: 'u128',2260      },2261      approve: {2262        spender: 'PalletEvmAccountBasicCrossAccountIdRepr',2263        collectionId: 'u32',2264        itemId: 'u32',2265        amount: 'u128',2266      },2267      transfer_from: {2268        from: 'PalletEvmAccountBasicCrossAccountIdRepr',2269        recipient: 'PalletEvmAccountBasicCrossAccountIdRepr',2270        collectionId: 'u32',2271        itemId: 'u32',2272        value: 'u128',2273      },2274      set_collection_limits: {2275        collectionId: 'u32',2276        newLimit: 'UpDataStructsCollectionLimits',2277      },2278      set_collection_permissions: {2279        collectionId: 'u32',2280        newPermission: 'UpDataStructsCollectionPermissions',2281      },2282      repartition: {2283        collectionId: 'u32',2284        tokenId: 'u32',2285        amount: 'u128',2286      },2287      set_allowance_for_all: {2288        collectionId: 'u32',2289        operator: 'PalletEvmAccountBasicCrossAccountIdRepr',2290        approve: 'bool',2291      },2292      force_repair_collection: {2293        collectionId: 'u32',2294      },2295      force_repair_item: {2296        collectionId: 'u32',2297        itemId: 'u32'2298      }2299    }2300  },2301  /**2302   * Lookup236: up_data_structs::CollectionMode2303   **/2304  UpDataStructsCollectionMode: {2305    _enum: {2306      NFT: 'Null',2307      Fungible: 'u8',2308      ReFungible: 'Null'2309    }2310  },2311  /**2312   * Lookup237: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>2313   **/2314  UpDataStructsCreateCollectionData: {2315    mode: 'UpDataStructsCollectionMode',2316    access: 'Option<UpDataStructsAccessMode>',2317    name: 'Vec<u16>',2318    description: 'Vec<u16>',2319    tokenPrefix: 'Bytes',2320    pendingSponsor: 'Option<AccountId32>',2321    limits: 'Option<UpDataStructsCollectionLimits>',2322    permissions: 'Option<UpDataStructsCollectionPermissions>',2323    tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',2324    properties: 'Vec<UpDataStructsProperty>'2325  },2326  /**2327   * Lookup239: up_data_structs::AccessMode2328   **/2329  UpDataStructsAccessMode: {2330    _enum: ['Normal', 'AllowList']2331  },2332  /**2333   * Lookup241: up_data_structs::CollectionLimits2334   **/2335  UpDataStructsCollectionLimits: {2336    accountTokenOwnershipLimit: 'Option<u32>',2337    sponsoredDataSize: 'Option<u32>',2338    sponsoredDataRateLimit: 'Option<UpDataStructsSponsoringRateLimit>',2339    tokenLimit: 'Option<u32>',2340    sponsorTransferTimeout: 'Option<u32>',2341    sponsorApproveTimeout: 'Option<u32>',2342    ownerCanTransfer: 'Option<bool>',2343    ownerCanDestroy: 'Option<bool>',2344    transfersEnabled: 'Option<bool>'2345  },2346  /**2347   * Lookup243: up_data_structs::SponsoringRateLimit2348   **/2349  UpDataStructsSponsoringRateLimit: {2350    _enum: {2351      SponsoringDisabled: 'Null',2352      Blocks: 'u32'2353    }2354  },2355  /**2356   * Lookup246: up_data_structs::CollectionPermissions2357   **/2358  UpDataStructsCollectionPermissions: {2359    access: 'Option<UpDataStructsAccessMode>',2360    mintMode: 'Option<bool>',2361    nesting: 'Option<UpDataStructsNestingPermissions>'2362  },2363  /**2364   * Lookup248: up_data_structs::NestingPermissions2365   **/2366  UpDataStructsNestingPermissions: {2367    tokenOwner: 'bool',2368    collectionAdmin: 'bool',2369    restricted: 'Option<UpDataStructsOwnerRestrictedSet>'2370  },2371  /**2372   * Lookup250: up_data_structs::OwnerRestrictedSet2373   **/2374  UpDataStructsOwnerRestrictedSet: 'BTreeSet<u32>',2375  /**2376   * Lookup255: up_data_structs::PropertyKeyPermission2377   **/2378  UpDataStructsPropertyKeyPermission: {2379    key: 'Bytes',2380    permission: 'UpDataStructsPropertyPermission'2381  },2382  /**2383   * Lookup256: up_data_structs::PropertyPermission2384   **/2385  UpDataStructsPropertyPermission: {2386    mutable: 'bool',2387    collectionAdmin: 'bool',2388    tokenOwner: 'bool'2389  },2390  /**2391   * Lookup259: up_data_structs::Property2392   **/2393  UpDataStructsProperty: {2394    key: 'Bytes',2395    value: 'Bytes'2396  },2397  /**2398   * Lookup262: up_data_structs::CreateItemData2399   **/2400  UpDataStructsCreateItemData: {2401    _enum: {2402      NFT: 'UpDataStructsCreateNftData',2403      Fungible: 'UpDataStructsCreateFungibleData',2404      ReFungible: 'UpDataStructsCreateReFungibleData'2405    }2406  },2407  /**2408   * Lookup263: up_data_structs::CreateNftData2409   **/2410  UpDataStructsCreateNftData: {2411    properties: 'Vec<UpDataStructsProperty>'2412  },2413  /**2414   * Lookup264: up_data_structs::CreateFungibleData2415   **/2416  UpDataStructsCreateFungibleData: {2417    value: 'u128'2418  },2419  /**2420   * Lookup265: up_data_structs::CreateReFungibleData2421   **/2422  UpDataStructsCreateReFungibleData: {2423    pieces: 'u128',2424    properties: 'Vec<UpDataStructsProperty>'2425  },2426  /**2427   * Lookup268: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2428   **/2429  UpDataStructsCreateItemExData: {2430    _enum: {2431      NFT: 'Vec<UpDataStructsCreateNftExData>',2432      Fungible: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',2433      RefungibleMultipleItems: 'Vec<UpDataStructsCreateRefungibleExSingleOwner>',2434      RefungibleMultipleOwners: 'UpDataStructsCreateRefungibleExMultipleOwners'2435    }2436  },2437  /**2438   * Lookup270: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2439   **/2440  UpDataStructsCreateNftExData: {2441    properties: 'Vec<UpDataStructsProperty>',2442    owner: 'PalletEvmAccountBasicCrossAccountIdRepr'2443  },2444  /**2445   * Lookup277: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2446   **/2447  UpDataStructsCreateRefungibleExSingleOwner: {2448    user: 'PalletEvmAccountBasicCrossAccountIdRepr',2449    pieces: 'u128',2450    properties: 'Vec<UpDataStructsProperty>'2451  },2452  /**2453   * Lookup279: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2454   **/2455  UpDataStructsCreateRefungibleExMultipleOwners: {2456    users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',2457    properties: 'Vec<UpDataStructsProperty>'2458  },2459  /**2460   * Lookup280: pallet_configuration::pallet::Call<T>2461   **/2462  PalletConfigurationCall: {2463    _enum: {2464      set_weight_to_fee_coefficient_override: {2465        coeff: 'Option<u64>',2466      },2467      set_min_gas_price_override: {2468        coeff: 'Option<u64>',2469      },2470      set_xcm_allowed_locations: {2471        locations: 'Option<Vec<XcmV1MultiLocation>>',2472      },2473      set_app_promotion_configuration_override: {2474        configuration: 'PalletConfigurationAppPromotionConfiguration',2475      },2476      set_collator_selection_desired_collators: {2477        max: 'Option<u32>',2478      },2479      set_collator_selection_license_bond: {2480        amount: 'Option<u128>',2481      },2482      set_collator_selection_kick_threshold: {2483        threshold: 'Option<u32>'2484      }2485    }2486  },2487  /**2488   * Lookup285: pallet_configuration::AppPromotionConfiguration<BlockNumber>2489   **/2490  PalletConfigurationAppPromotionConfiguration: {2491    recalculationInterval: 'Option<u32>',2492    pendingInterval: 'Option<u32>',2493    intervalIncome: 'Option<Perbill>',2494    maxStakersPerCalculation: 'Option<u8>'2495  },2496  /**2497   * Lookup289: pallet_template_transaction_payment::Call<T>2498   **/2499  PalletTemplateTransactionPaymentCall: 'Null',2500  /**2501   * Lookup290: pallet_structure::pallet::Call<T>2502   **/2503  PalletStructureCall: 'Null',2504  /**2505   * Lookup291: pallet_rmrk_core::pallet::Call<T>2506   **/2507  PalletRmrkCoreCall: {2508    _enum: {2509      create_collection: {2510        metadata: 'Bytes',2511        max: 'Option<u32>',2512        symbol: 'Bytes',2513      },2514      destroy_collection: {2515        collectionId: 'u32',2516      },2517      change_collection_issuer: {2518        collectionId: 'u32',2519        newIssuer: 'MultiAddress',2520      },2521      lock_collection: {2522        collectionId: 'u32',2523      },2524      mint_nft: {2525        owner: 'Option<AccountId32>',2526        collectionId: 'u32',2527        recipient: 'Option<AccountId32>',2528        royaltyAmount: 'Option<Permill>',2529        metadata: 'Bytes',2530        transferable: 'bool',2531        resources: 'Option<Vec<RmrkTraitsResourceResourceTypes>>',2532      },2533      burn_nft: {2534        collectionId: 'u32',2535        nftId: 'u32',2536        maxBurns: 'u32',2537      },2538      send: {2539        rmrkCollectionId: 'u32',2540        rmrkNftId: 'u32',2541        newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2542      },2543      accept_nft: {2544        rmrkCollectionId: 'u32',2545        rmrkNftId: 'u32',2546        newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2547      },2548      reject_nft: {2549        rmrkCollectionId: 'u32',2550        rmrkNftId: 'u32',2551      },2552      accept_resource: {2553        rmrkCollectionId: 'u32',2554        rmrkNftId: 'u32',2555        resourceId: 'u32',2556      },2557      accept_resource_removal: {2558        rmrkCollectionId: 'u32',2559        rmrkNftId: 'u32',2560        resourceId: 'u32',2561      },2562      set_property: {2563        rmrkCollectionId: 'Compact<u32>',2564        maybeNftId: 'Option<u32>',2565        key: 'Bytes',2566        value: 'Bytes',2567      },2568      set_priority: {2569        rmrkCollectionId: 'u32',2570        rmrkNftId: 'u32',2571        priorities: 'Vec<u32>',2572      },2573      add_basic_resource: {2574        rmrkCollectionId: 'u32',2575        nftId: 'u32',2576        resource: 'RmrkTraitsResourceBasicResource',2577      },2578      add_composable_resource: {2579        rmrkCollectionId: 'u32',2580        nftId: 'u32',2581        resource: 'RmrkTraitsResourceComposableResource',2582      },2583      add_slot_resource: {2584        rmrkCollectionId: 'u32',2585        nftId: 'u32',2586        resource: 'RmrkTraitsResourceSlotResource',2587      },2588      remove_resource: {2589        rmrkCollectionId: 'u32',2590        nftId: 'u32',2591        resourceId: 'u32'2592      }2593    }2594  },2595  /**2596   * Lookup297: rmrk_traits::resource::ResourceTypes<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>2597   **/2598  RmrkTraitsResourceResourceTypes: {2599    _enum: {2600      Basic: 'RmrkTraitsResourceBasicResource',2601      Composable: 'RmrkTraitsResourceComposableResource',2602      Slot: 'RmrkTraitsResourceSlotResource'2603    }2604  },2605  /**2606   * Lookup299: rmrk_traits::resource::BasicResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>2607   **/2608  RmrkTraitsResourceBasicResource: {2609    src: 'Option<Bytes>',2610    metadata: 'Option<Bytes>',2611    license: 'Option<Bytes>',2612    thumb: 'Option<Bytes>'2613  },2614  /**2615   * Lookup301: rmrk_traits::resource::ComposableResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>2616   **/2617  RmrkTraitsResourceComposableResource: {2618    parts: 'Vec<u32>',2619    base: 'u32',2620    src: 'Option<Bytes>',2621    metadata: 'Option<Bytes>',2622    license: 'Option<Bytes>',2623    thumb: 'Option<Bytes>'2624  },2625  /**2626   * Lookup302: rmrk_traits::resource::SlotResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>2627   **/2628  RmrkTraitsResourceSlotResource: {2629    base: 'u32',2630    src: 'Option<Bytes>',2631    metadata: 'Option<Bytes>',2632    slot: 'u32',2633    license: 'Option<Bytes>',2634    thumb: 'Option<Bytes>'2635  },2636  /**2637   * Lookup305: pallet_rmrk_equip::pallet::Call<T>2638   **/2639  PalletRmrkEquipCall: {2640    _enum: {2641      create_base: {2642        baseType: 'Bytes',2643        symbol: 'Bytes',2644        parts: 'Vec<RmrkTraitsPartPartType>',2645      },2646      theme_add: {2647        baseId: 'u32',2648        theme: 'RmrkTraitsTheme',2649      },2650      equippable: {2651        baseId: 'u32',2652        slotId: 'u32',2653        equippables: 'RmrkTraitsPartEquippableList'2654      }2655    }2656  },2657  /**2658   * Lookup308: rmrk_traits::part::PartType<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>2659   **/2660  RmrkTraitsPartPartType: {2661    _enum: {2662      FixedPart: 'RmrkTraitsPartFixedPart',2663      SlotPart: 'RmrkTraitsPartSlotPart'2664    }2665  },2666  /**2667   * Lookup310: rmrk_traits::part::FixedPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>>2668   **/2669  RmrkTraitsPartFixedPart: {2670    id: 'u32',2671    z: 'u32',2672    src: 'Bytes'2673  },2674  /**2675   * Lookup311: rmrk_traits::part::SlotPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>2676   **/2677  RmrkTraitsPartSlotPart: {2678    id: 'u32',2679    equippable: 'RmrkTraitsPartEquippableList',2680    src: 'Bytes',2681    z: 'u32'2682  },2683  /**2684   * Lookup312: rmrk_traits::part::EquippableList<sp_core::bounded::bounded_vec::BoundedVec<T, S>>2685   **/2686  RmrkTraitsPartEquippableList: {2687    _enum: {2688      All: 'Null',2689      Empty: 'Null',2690      Custom: 'Vec<u32>'2691    }2692  },2693  /**2694   * Lookup314: rmrk_traits::theme::Theme<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>, S>>2695   **/2696  RmrkTraitsTheme: {2697    name: 'Bytes',2698    properties: 'Vec<RmrkTraitsThemeThemeProperty>',2699    inherit: 'bool'2700  },2701  /**2702   * Lookup316: rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>2703   **/2704  RmrkTraitsThemeThemeProperty: {2705    key: 'Bytes',2706    value: 'Bytes'2707  },2708  /**2709   * Lookup318: pallet_app_promotion::pallet::Call<T>2710   **/2711  PalletAppPromotionCall: {2712    _enum: {2713      set_admin_address: {2714        admin: 'PalletEvmAccountBasicCrossAccountIdRepr',2715      },2716      stake: {2717        amount: 'u128',2718      },2719      unstake: 'Null',2720      sponsor_collection: {2721        collectionId: 'u32',2722      },2723      stop_sponsoring_collection: {2724        collectionId: 'u32',2725      },2726      sponsor_contract: {2727        contractId: 'H160',2728      },2729      stop_sponsoring_contract: {2730        contractId: 'H160',2731      },2732      payout_stakers: {2733        stakersNumber: 'Option<u8>'2734      }2735    }2736  },2737  /**2738   * Lookup319: pallet_foreign_assets::module::Call<T>2739   **/2740  PalletForeignAssetsModuleCall: {2741    _enum: {2742      register_foreign_asset: {2743        owner: 'AccountId32',2744        location: 'XcmVersionedMultiLocation',2745        metadata: 'PalletForeignAssetsModuleAssetMetadata',2746      },2747      update_foreign_asset: {2748        foreignAssetId: 'u32',2749        location: 'XcmVersionedMultiLocation',2750        metadata: 'PalletForeignAssetsModuleAssetMetadata'2751      }2752    }2753  },2754  /**2755   * Lookup320: pallet_evm::pallet::Call<T>2756   **/2757  PalletEvmCall: {2758    _enum: {2759      withdraw: {2760        address: 'H160',2761        value: 'u128',2762      },2763      call: {2764        source: 'H160',2765        target: 'H160',2766        input: 'Bytes',2767        value: 'U256',2768        gasLimit: 'u64',2769        maxFeePerGas: 'U256',2770        maxPriorityFeePerGas: 'Option<U256>',2771        nonce: 'Option<U256>',2772        accessList: 'Vec<(H160,Vec<H256>)>',2773      },2774      create: {2775        source: 'H160',2776        init: 'Bytes',2777        value: 'U256',2778        gasLimit: 'u64',2779        maxFeePerGas: 'U256',2780        maxPriorityFeePerGas: 'Option<U256>',2781        nonce: 'Option<U256>',2782        accessList: 'Vec<(H160,Vec<H256>)>',2783      },2784      create2: {2785        source: 'H160',2786        init: 'Bytes',2787        salt: 'H256',2788        value: 'U256',2789        gasLimit: 'u64',2790        maxFeePerGas: 'U256',2791        maxPriorityFeePerGas: 'Option<U256>',2792        nonce: 'Option<U256>',2793        accessList: 'Vec<(H160,Vec<H256>)>'2794      }2795    }2796  },2797  /**2798   * Lookup326: pallet_ethereum::pallet::Call<T>2799   **/2800  PalletEthereumCall: {2801    _enum: {2802      transact: {2803        transaction: 'EthereumTransactionTransactionV2'2804      }2805    }2806  },2807  /**2808   * Lookup327: ethereum::transaction::TransactionV22809   **/2810  EthereumTransactionTransactionV2: {2811    _enum: {2812      Legacy: 'EthereumTransactionLegacyTransaction',2813      EIP2930: 'EthereumTransactionEip2930Transaction',2814      EIP1559: 'EthereumTransactionEip1559Transaction'2815    }2816  },2817  /**2818   * Lookup328: ethereum::transaction::LegacyTransaction2819   **/2820  EthereumTransactionLegacyTransaction: {2821    nonce: 'U256',2822    gasPrice: 'U256',2823    gasLimit: 'U256',2824    action: 'EthereumTransactionTransactionAction',2825    value: 'U256',2826    input: 'Bytes',2827    signature: 'EthereumTransactionTransactionSignature'2828  },2829  /**2830   * Lookup329: ethereum::transaction::TransactionAction2831   **/2832  EthereumTransactionTransactionAction: {2833    _enum: {2834      Call: 'H160',2835      Create: 'Null'2836    }2837  },2838  /**2839   * Lookup330: ethereum::transaction::TransactionSignature2840   **/2841  EthereumTransactionTransactionSignature: {2842    v: 'u64',2843    r: 'H256',2844    s: 'H256'2845  },2846  /**2847   * Lookup332: ethereum::transaction::EIP2930Transaction2848   **/2849  EthereumTransactionEip2930Transaction: {2850    chainId: 'u64',2851    nonce: 'U256',2852    gasPrice: 'U256',2853    gasLimit: 'U256',2854    action: 'EthereumTransactionTransactionAction',2855    value: 'U256',2856    input: 'Bytes',2857    accessList: 'Vec<EthereumTransactionAccessListItem>',2858    oddYParity: 'bool',2859    r: 'H256',2860    s: 'H256'2861  },2862  /**2863   * Lookup334: ethereum::transaction::AccessListItem2864   **/2865  EthereumTransactionAccessListItem: {2866    address: 'H160',2867    storageKeys: 'Vec<H256>'2868  },2869  /**2870   * Lookup335: ethereum::transaction::EIP1559Transaction2871   **/2872  EthereumTransactionEip1559Transaction: {2873    chainId: 'u64',2874    nonce: 'U256',2875    maxPriorityFeePerGas: 'U256',2876    maxFeePerGas: 'U256',2877    gasLimit: 'U256',2878    action: 'EthereumTransactionTransactionAction',2879    value: 'U256',2880    input: 'Bytes',2881    accessList: 'Vec<EthereumTransactionAccessListItem>',2882    oddYParity: 'bool',2883    r: 'H256',2884    s: 'H256'2885  },2886  /**2887   * Lookup336: pallet_evm_migration::pallet::Call<T>2888   **/2889  PalletEvmMigrationCall: {2890    _enum: {2891      begin: {2892        address: 'H160',2893      },2894      set_data: {2895        address: 'H160',2896        data: 'Vec<(H256,H256)>',2897      },2898      finish: {2899        address: 'H160',2900        code: 'Bytes',2901      },2902      insert_eth_logs: {2903        logs: 'Vec<EthereumLog>',2904      },2905      insert_events: {2906        events: 'Vec<Bytes>'2907      }2908    }2909  },2910  /**2911   * Lookup340: pallet_maintenance::pallet::Call<T>2912   **/2913  PalletMaintenanceCall: {2914    _enum: ['enable', 'disable']2915  },2916  /**2917   * Lookup341: pallet_test_utils::pallet::Call<T>2918   **/2919  PalletTestUtilsCall: {2920    _enum: {2921      enable: 'Null',2922      set_test_value: {2923        value: 'u32',2924      },2925      set_test_value_and_rollback: {2926        value: 'u32',2927      },2928      inc_test_value: 'Null',2929      just_take_fee: 'Null',2930      batch_all: {2931        calls: 'Vec<Call>'2932      }2933    }2934  },2935  /**2936   * Lookup343: pallet_sudo::pallet::Error<T>2937   **/2938  PalletSudoError: {2939    _enum: ['RequireSudo']2940  },2941  /**2942   * Lookup345: orml_vesting::module::Error<T>2943   **/2944  OrmlVestingModuleError: {2945    _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded']2946  },2947  /**2948   * Lookup346: orml_xtokens::module::Error<T>2949   **/2950  OrmlXtokensModuleError: {2951    _enum: ['AssetHasNoReserve', 'NotCrossChainTransfer', 'InvalidDest', 'NotCrossChainTransferableCurrency', 'UnweighableMessage', 'XcmExecutionFailed', 'CannotReanchor', 'InvalidAncestry', 'InvalidAsset', 'DestinationNotInvertible', 'BadVersion', 'DistinctReserveForAssetAndFee', 'ZeroFee', 'ZeroAmount', 'TooManyAssetsBeingSent', 'AssetIndexNonExistent', 'FeeNotEnough', 'NotSupportedMultiLocation', 'MinXcmFeeNotDefined']2952  },2953  /**2954   * Lookup349: orml_tokens::BalanceLock<Balance>2955   **/2956  OrmlTokensBalanceLock: {2957    id: '[u8;8]',2958    amount: 'u128'2959  },2960  /**2961   * Lookup351: orml_tokens::AccountData<Balance>2962   **/2963  OrmlTokensAccountData: {2964    free: 'u128',2965    reserved: 'u128',2966    frozen: 'u128'2967  },2968  /**2969   * Lookup353: orml_tokens::ReserveData<ReserveIdentifier, Balance>2970   **/2971  OrmlTokensReserveData: {2972    id: 'Null',2973    amount: 'u128'2974  },2975  /**2976   * Lookup355: orml_tokens::module::Error<T>2977   **/2978  OrmlTokensModuleError: {2979    _enum: ['BalanceTooLow', 'AmountIntoBalanceFailed', 'LiquidityRestrictions', 'MaxLocksExceeded', 'KeepAlive', 'ExistentialDeposit', 'DeadAccount', 'TooManyReserves']2980  },2981  /**2982   * Lookup357: cumulus_pallet_xcmp_queue::InboundChannelDetails2983   **/2984  CumulusPalletXcmpQueueInboundChannelDetails: {2985    sender: 'u32',2986    state: 'CumulusPalletXcmpQueueInboundState',2987    messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>'2988  },2989  /**2990   * Lookup358: cumulus_pallet_xcmp_queue::InboundState2991   **/2992  CumulusPalletXcmpQueueInboundState: {2993    _enum: ['Ok', 'Suspended']2994  },2995  /**2996   * Lookup361: polkadot_parachain::primitives::XcmpMessageFormat2997   **/2998  PolkadotParachainPrimitivesXcmpMessageFormat: {2999    _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals']3000  },3001  /**3002   * Lookup364: cumulus_pallet_xcmp_queue::OutboundChannelDetails3003   **/3004  CumulusPalletXcmpQueueOutboundChannelDetails: {3005    recipient: 'u32',3006    state: 'CumulusPalletXcmpQueueOutboundState',3007    signalsExist: 'bool',3008    firstIndex: 'u16',3009    lastIndex: 'u16'3010  },3011  /**3012   * Lookup365: cumulus_pallet_xcmp_queue::OutboundState3013   **/3014  CumulusPalletXcmpQueueOutboundState: {3015    _enum: ['Ok', 'Suspended']3016  },3017  /**3018   * Lookup367: cumulus_pallet_xcmp_queue::QueueConfigData3019   **/3020  CumulusPalletXcmpQueueQueueConfigData: {3021    suspendThreshold: 'u32',3022    dropThreshold: 'u32',3023    resumeThreshold: 'u32',3024    thresholdWeight: 'SpWeightsWeightV2Weight',3025    weightRestrictDecay: 'SpWeightsWeightV2Weight',3026    xcmpMaxIndividualWeight: 'SpWeightsWeightV2Weight'3027  },3028  /**3029   * Lookup369: cumulus_pallet_xcmp_queue::pallet::Error<T>3030   **/3031  CumulusPalletXcmpQueueError: {3032    _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit']3033  },3034  /**3035   * Lookup370: pallet_xcm::pallet::Error<T>3036   **/3037  PalletXcmError: {3038    _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed']3039  },3040  /**3041   * Lookup371: cumulus_pallet_xcm::pallet::Error<T>3042   **/3043  CumulusPalletXcmError: 'Null',3044  /**3045   * Lookup372: cumulus_pallet_dmp_queue::ConfigData3046   **/3047  CumulusPalletDmpQueueConfigData: {3048    maxIndividual: 'SpWeightsWeightV2Weight'3049  },3050  /**3051   * Lookup373: cumulus_pallet_dmp_queue::PageIndexData3052   **/3053  CumulusPalletDmpQueuePageIndexData: {3054    beginUsed: 'u32',3055    endUsed: 'u32',3056    overweightCount: 'u64'3057  },3058  /**3059   * Lookup376: cumulus_pallet_dmp_queue::pallet::Error<T>3060   **/3061  CumulusPalletDmpQueueError: {3062    _enum: ['Unknown', 'OverLimit']3063  },3064  /**3065   * Lookup380: pallet_unique::Error<T>3066   **/3067  PalletUniqueError: {3068    _enum: ['CollectionDecimalPointLimitExceeded', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection']3069  },3070  /**3071   * Lookup381: pallet_configuration::pallet::Error<T>3072   **/3073  PalletConfigurationError: {3074    _enum: ['InconsistentConfiguration']3075  },3076  /**3077   * Lookup382: up_data_structs::Collection<sp_core::crypto::AccountId32>3078   **/3079  UpDataStructsCollection: {3080    owner: 'AccountId32',3081    mode: 'UpDataStructsCollectionMode',3082    name: 'Vec<u16>',3083    description: 'Vec<u16>',3084    tokenPrefix: 'Bytes',3085    sponsorship: 'UpDataStructsSponsorshipStateAccountId32',3086    limits: 'UpDataStructsCollectionLimits',3087    permissions: 'UpDataStructsCollectionPermissions',3088    flags: '[u8;1]'3089  },3090  /**3091   * Lookup383: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>3092   **/3093  UpDataStructsSponsorshipStateAccountId32: {3094    _enum: {3095      Disabled: 'Null',3096      Unconfirmed: 'AccountId32',3097      Confirmed: 'AccountId32'3098    }3099  },3100  /**3101   * Lookup385: up_data_structs::Properties3102   **/3103  UpDataStructsProperties: {3104    map: 'UpDataStructsPropertiesMapBoundedVec',3105    consumedSpace: 'u32',3106    spaceLimit: 'u32'3107  },3108  /**3109   * Lookup386: up_data_structs::PropertiesMap<sp_core::bounded::bounded_vec::BoundedVec<T, S>>3110   **/3111  UpDataStructsPropertiesMapBoundedVec: 'BTreeMap<Bytes, Bytes>',3112  /**3113   * Lookup391: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>3114   **/3115  UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap<Bytes, UpDataStructsPropertyPermission>',3116  /**3117   * Lookup398: up_data_structs::CollectionStats3118   **/3119  UpDataStructsCollectionStats: {3120    created: 'u32',3121    destroyed: 'u32',3122    alive: 'u32'3123  },3124  /**3125   * Lookup399: up_data_structs::TokenChild3126   **/3127  UpDataStructsTokenChild: {3128    token: 'u32',3129    collection: 'u32'3130  },3131  /**3132   * Lookup400: PhantomType::up_data_structs<T>3133   **/3134  PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild,UpPovEstimateRpcPovInfo);0]',3135  /**3136   * Lookup402: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>3137   **/3138  UpDataStructsTokenData: {3139    properties: 'Vec<UpDataStructsProperty>',3140    owner: 'Option<PalletEvmAccountBasicCrossAccountIdRepr>',3141    pieces: 'u128'3142  },3143  /**3144   * Lookup404: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>3145   **/3146  UpDataStructsRpcCollection: {3147    owner: 'AccountId32',3148    mode: 'UpDataStructsCollectionMode',3149    name: 'Vec<u16>',3150    description: 'Vec<u16>',3151    tokenPrefix: 'Bytes',3152    sponsorship: 'UpDataStructsSponsorshipStateAccountId32',3153    limits: 'UpDataStructsCollectionLimits',3154    permissions: 'UpDataStructsCollectionPermissions',3155    tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',3156    properties: 'Vec<UpDataStructsProperty>',3157    readOnly: 'bool',3158    flags: 'UpDataStructsRpcCollectionFlags'3159  },3160  /**3161   * Lookup405: up_data_structs::RpcCollectionFlags3162   **/3163  UpDataStructsRpcCollectionFlags: {3164    foreign: 'bool',3165    erc721metadata: 'bool'3166  },3167  /**3168   * Lookup406: rmrk_traits::collection::CollectionInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>3169   **/3170  RmrkTraitsCollectionCollectionInfo: {3171    issuer: 'AccountId32',3172    metadata: 'Bytes',3173    max: 'Option<u32>',3174    symbol: 'Bytes',3175    nftsCount: 'u32'3176  },3177  /**3178   * Lookup407: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, sp_core::bounded::bounded_vec::BoundedVec<T, S>>3179   **/3180  RmrkTraitsNftNftInfo: {3181    owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',3182    royalty: 'Option<RmrkTraitsNftRoyaltyInfo>',3183    metadata: 'Bytes',3184    equipped: 'bool',3185    pending: 'bool'3186  },3187  /**3188   * Lookup409: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>3189   **/3190  RmrkTraitsNftRoyaltyInfo: {3191    recipient: 'AccountId32',3192    amount: 'Permill'3193  },3194  /**3195   * Lookup410: rmrk_traits::resource::ResourceInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>3196   **/3197  RmrkTraitsResourceResourceInfo: {3198    id: 'u32',3199    resource: 'RmrkTraitsResourceResourceTypes',3200    pending: 'bool',3201    pendingRemoval: 'bool'3202  },3203  /**3204   * Lookup411: rmrk_traits::property::PropertyInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>3205   **/3206  RmrkTraitsPropertyPropertyInfo: {3207    key: 'Bytes',3208    value: 'Bytes'3209  },3210  /**3211   * Lookup412: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, sp_core::bounded::bounded_vec::BoundedVec<T, S>>3212   **/3213  RmrkTraitsBaseBaseInfo: {3214    issuer: 'AccountId32',3215    baseType: 'Bytes',3216    symbol: 'Bytes'3217  },3218  /**3219   * Lookup413: rmrk_traits::nft::NftChild3220   **/3221  RmrkTraitsNftNftChild: {3222    collectionId: 'u32',3223    nftId: 'u32'3224  },3225  /**3226   * Lookup414: up_pov_estimate_rpc::PovInfo3227   **/3228  UpPovEstimateRpcPovInfo: {3229    proofSize: 'u64',3230    compactProofSize: 'u64',3231    compressedProofSize: 'u64',3232    results: 'Vec<Result<Result<Null, SpRuntimeDispatchError>, SpRuntimeTransactionValidityTransactionValidityError>>',3233    keyValues: 'Vec<UpPovEstimateRpcTrieKeyValue>'3234  },3235  /**3236   * Lookup417: sp_runtime::transaction_validity::TransactionValidityError3237   **/3238  SpRuntimeTransactionValidityTransactionValidityError: {3239    _enum: {3240      Invalid: 'SpRuntimeTransactionValidityInvalidTransaction',3241      Unknown: 'SpRuntimeTransactionValidityUnknownTransaction'3242    }3243  },3244  /**3245   * Lookup418: sp_runtime::transaction_validity::InvalidTransaction3246   **/3247  SpRuntimeTransactionValidityInvalidTransaction: {3248    _enum: {3249      Call: 'Null',3250      Payment: 'Null',3251      Future: 'Null',3252      Stale: 'Null',3253      BadProof: 'Null',3254      AncientBirthBlock: 'Null',3255      ExhaustsResources: 'Null',3256      Custom: 'u8',3257      BadMandatory: 'Null',3258      MandatoryValidation: 'Null',3259      BadSigner: 'Null'3260    }3261  },3262  /**3263   * Lookup419: sp_runtime::transaction_validity::UnknownTransaction3264   **/3265  SpRuntimeTransactionValidityUnknownTransaction: {3266    _enum: {3267      CannotLookup: 'Null',3268      NoUnsignedValidator: 'Null',3269      Custom: 'u8'3270    }3271  },3272  /**3273   * Lookup421: up_pov_estimate_rpc::TrieKeyValue3274   **/3275  UpPovEstimateRpcTrieKeyValue: {3276    key: 'Bytes',3277    value: 'Bytes'3278  },3279  /**3280   * Lookup423: pallet_common::pallet::Error<T>3281   **/3282  PalletCommonError: {3283    _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', 'ConfirmSponsorshipFail', 'UserIsNotCollectionAdmin']3284  },3285  /**3286   * Lookup425: pallet_fungible::pallet::Error<T>3287   **/3288  PalletFungibleError: {3289    _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed', 'SettingAllowanceForAllNotAllowed', 'FungibleTokensAreAlwaysValid']3290  },3291  /**3292   * Lookup429: pallet_refungible::pallet::Error<T>3293   **/3294  PalletRefungibleError: {3295    _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed']3296  },3297  /**3298   * Lookup430: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>3299   **/3300  PalletNonfungibleItemData: {3301    owner: 'PalletEvmAccountBasicCrossAccountIdRepr'3302  },3303  /**3304   * Lookup432: up_data_structs::PropertyScope3305   **/3306  UpDataStructsPropertyScope: {3307    _enum: ['None', 'Rmrk']3308  },3309  /**3310   * Lookup435: pallet_nonfungible::pallet::Error<T>3311   **/3312  PalletNonfungibleError: {3313    _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren']3314  },3315  /**3316   * Lookup436: pallet_structure::pallet::Error<T>3317   **/3318  PalletStructureError: {3319    _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound']3320  },3321  /**3322   * Lookup437: pallet_rmrk_core::pallet::Error<T>3323   **/3324  PalletRmrkCoreError: {3325    _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId']3326  },3327  /**3328   * Lookup439: pallet_rmrk_equip::pallet::Error<T>3329   **/3330  PalletRmrkEquipError: {3331    _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart']3332  },3333  /**3334   * Lookup445: pallet_app_promotion::pallet::Error<T>3335   **/3336  PalletAppPromotionError: {3337    _enum: ['AdminNotSet', 'NoPermission', 'NotSufficientFunds', 'PendingForBlockOverflow', 'SponsorNotSet', 'IncorrectLockedBalanceOperation']3338  },3339  /**3340   * Lookup446: pallet_foreign_assets::module::Error<T>3341   **/3342  PalletForeignAssetsModuleError: {3343    _enum: ['BadLocation', 'MultiLocationExisted', 'AssetIdNotExists', 'AssetIdExisted']3344  },3345  /**3346   * Lookup448: pallet_evm::pallet::Error<T>3347   **/3348  PalletEvmError: {3349    _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce', 'GasLimitTooLow', 'GasLimitTooHigh', 'Undefined', 'Reentrancy', 'TransactionMustComeFromEOA']3350  },3351  /**3352   * Lookup451: fp_rpc::TransactionStatus3353   **/3354  FpRpcTransactionStatus: {3355    transactionHash: 'H256',3356    transactionIndex: 'u32',3357    from: 'H160',3358    to: 'Option<H160>',3359    contractAddress: 'Option<H160>',3360    logs: 'Vec<EthereumLog>',3361    logsBloom: 'EthbloomBloom'3362  },3363  /**3364   * Lookup453: ethbloom::Bloom3365   **/3366  EthbloomBloom: '[u8;256]',3367  /**3368   * Lookup455: ethereum::receipt::ReceiptV33369   **/3370  EthereumReceiptReceiptV3: {3371    _enum: {3372      Legacy: 'EthereumReceiptEip658ReceiptData',3373      EIP2930: 'EthereumReceiptEip658ReceiptData',3374      EIP1559: 'EthereumReceiptEip658ReceiptData'3375    }3376  },3377  /**3378   * Lookup456: ethereum::receipt::EIP658ReceiptData3379   **/3380  EthereumReceiptEip658ReceiptData: {3381    statusCode: 'u8',3382    usedGas: 'U256',3383    logsBloom: 'EthbloomBloom',3384    logs: 'Vec<EthereumLog>'3385  },3386  /**3387   * Lookup457: ethereum::block::Block<ethereum::transaction::TransactionV2>3388   **/3389  EthereumBlock: {3390    header: 'EthereumHeader',3391    transactions: 'Vec<EthereumTransactionTransactionV2>',3392    ommers: 'Vec<EthereumHeader>'3393  },3394  /**3395   * Lookup458: ethereum::header::Header3396   **/3397  EthereumHeader: {3398    parentHash: 'H256',3399    ommersHash: 'H256',3400    beneficiary: 'H160',3401    stateRoot: 'H256',3402    transactionsRoot: 'H256',3403    receiptsRoot: 'H256',3404    logsBloom: 'EthbloomBloom',3405    difficulty: 'U256',3406    number: 'U256',3407    gasLimit: 'U256',3408    gasUsed: 'U256',3409    timestamp: 'u64',3410    extraData: 'Bytes',3411    mixHash: 'H256',3412    nonce: 'EthereumTypesHashH64'3413  },3414  /**3415   * Lookup459: ethereum_types::hash::H643416   **/3417  EthereumTypesHashH64: '[u8;8]',3418  /**3419   * Lookup464: pallet_ethereum::pallet::Error<T>3420   **/3421  PalletEthereumError: {3422    _enum: ['InvalidSignature', 'PreLogExists']3423  },3424  /**3425   * Lookup465: pallet_evm_coder_substrate::pallet::Error<T>3426   **/3427  PalletEvmCoderSubstrateError: {3428    _enum: ['OutOfGas', 'OutOfFund']3429  },3430  /**3431   * Lookup466: up_data_structs::SponsorshipState<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>3432   **/3433  UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: {3434    _enum: {3435      Disabled: 'Null',3436      Unconfirmed: 'PalletEvmAccountBasicCrossAccountIdRepr',3437      Confirmed: 'PalletEvmAccountBasicCrossAccountIdRepr'3438    }3439  },3440  /**3441   * Lookup467: pallet_evm_contract_helpers::SponsoringModeT3442   **/3443  PalletEvmContractHelpersSponsoringModeT: {3444    _enum: ['Disabled', 'Allowlisted', 'Generous']3445  },3446  /**3447   * Lookup473: pallet_evm_contract_helpers::pallet::Error<T>3448   **/3449  PalletEvmContractHelpersError: {3450    _enum: ['NoPermission', 'NoPendingSponsor', 'TooManyMethodsHaveSponsoredLimit']3451  },3452  /**3453   * Lookup474: pallet_evm_migration::pallet::Error<T>3454   **/3455  PalletEvmMigrationError: {3456    _enum: ['AccountNotEmpty', 'AccountIsNotMigrating', 'BadEvent']3457  },3458  /**3459   * Lookup475: pallet_maintenance::pallet::Error<T>3460   **/3461  PalletMaintenanceError: 'Null',3462  /**3463   * Lookup476: pallet_test_utils::pallet::Error<T>3464   **/3465  PalletTestUtilsError: {3466    _enum: ['TestPalletDisabled', 'TriggerRollback']3467  },3468  /**3469   * Lookup478: sp_runtime::MultiSignature3470   **/3471  SpRuntimeMultiSignature: {3472    _enum: {3473      Ed25519: 'SpCoreEd25519Signature',3474      Sr25519: 'SpCoreSr25519Signature',3475      Ecdsa: 'SpCoreEcdsaSignature'3476    }3477  },3478  /**3479   * Lookup479: sp_core::ed25519::Signature3480   **/3481  SpCoreEd25519Signature: '[u8;64]',3482  /**3483   * Lookup481: sp_core::sr25519::Signature3484   **/3485  SpCoreSr25519Signature: '[u8;64]',3486  /**3487   * Lookup482: sp_core::ecdsa::Signature3488   **/3489  SpCoreEcdsaSignature: '[u8;65]',3490  /**3491   * Lookup485: frame_system::extensions::check_spec_version::CheckSpecVersion<T>3492   **/3493  FrameSystemExtensionsCheckSpecVersion: 'Null',3494  /**3495   * Lookup486: frame_system::extensions::check_tx_version::CheckTxVersion<T>3496   **/3497  FrameSystemExtensionsCheckTxVersion: 'Null',3498  /**3499   * Lookup487: frame_system::extensions::check_genesis::CheckGenesis<T>3500   **/3501  FrameSystemExtensionsCheckGenesis: 'Null',3502  /**3503   * Lookup490: frame_system::extensions::check_nonce::CheckNonce<T>3504   **/3505  FrameSystemExtensionsCheckNonce: 'Compact<u32>',3506  /**3507   * Lookup491: frame_system::extensions::check_weight::CheckWeight<T>3508   **/3509  FrameSystemExtensionsCheckWeight: 'Null',3510  /**3511   * Lookup492: opal_runtime::runtime_common::maintenance::CheckMaintenance3512   **/3513  OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance: 'Null',3514  /**3515   * Lookup493: opal_runtime::runtime_common::identity::DisableIdentityCalls3516   **/3517  OpalRuntimeRuntimeCommonIdentityDisableIdentityCalls: 'Null',3518  /**3519   * Lookup494: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>3520   **/3521  PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact<u128>',3522  /**3523   * Lookup495: opal_runtime::Runtime3524   **/3525  OpalRuntimeRuntime: 'Null',3526  /**3527   * Lookup496: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>3528   **/3529  PalletEthereumFakeTransactionFinalizer: 'Null'3530};
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -2493,6 +2493,14 @@
       readonly itemId: u32;
       readonly amount: u128;
     } & Struct;
+    readonly isApproveFrom: boolean;
+    readonly asApproveFrom: {
+      readonly from: PalletEvmAccountBasicCrossAccountIdRepr;
+      readonly to: PalletEvmAccountBasicCrossAccountIdRepr;
+      readonly collectionId: u32;
+      readonly itemId: u32;
+      readonly amount: u128;
+    } & Struct;
     readonly isTransferFrom: boolean;
     readonly asTransferFrom: {
       readonly from: PalletEvmAccountBasicCrossAccountIdRepr;
@@ -2532,7 +2540,7 @@
       readonly collectionId: u32;
       readonly itemId: u32;
     } & Struct;
-    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' | 'SetAllowanceForAll' | 'ForceRepairCollection' | 'ForceRepairItem';
+    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' | 'ApproveFrom' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetAllowanceForAll' | 'ForceRepairCollection' | 'ForceRepairItem';
   }
 
   /** @name UpDataStructsCollectionMode (236) */
@@ -3564,6 +3572,7 @@
     readonly isTokenValueTooLow: boolean;
     readonly isApprovedValueTooLow: boolean;
     readonly isCantApproveMoreThanOwned: boolean;
+    readonly isAddressIsNotEthMirror: boolean;
     readonly isAddressIsZero: boolean;
     readonly isUnsupportedOperation: boolean;
     readonly isNotSufficientFounds: boolean;
@@ -3579,7 +3588,7 @@
     readonly isCollectionIsInternal: boolean;
     readonly isConfirmSponsorshipFail: boolean;
     readonly isUserIsNotCollectionAdmin: boolean;
-    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' | 'ConfirmSponsorshipFail' | 'UserIsNotCollectionAdmin';
+    readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsNotEthMirror' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal' | 'ConfirmSponsorshipFail' | 'UserIsNotCollectionAdmin';
   }
 
   /** @name PalletFungibleError (425) */
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -633,6 +633,10 @@
     let call = this.getApi() as any;
     for(const part of apiCall.slice(4).split('.')) {
       call = call[part];
+      if (!call) {
+        const advice = part.includes('_') ? ' Looks like it needs to be converted to camel case.' : '';
+        throw Error(`Function ${part} of api call ${apiCall} not found.${advice}`);
+      }
     }
     return call(...params);
   }
@@ -1259,6 +1263,42 @@
   }
 
   /**
+   * Set, change, or remove approved address to transfer the ownership of the NFT from eth mirror.
+   *
+   * @param signer keyring of signer
+   * @param collectionId ID of collection
+   * @param tokenId ID of token
+   * @param fromAddressObj Signer's Ethereum address containing her tokens
+   * @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 approveTokenFrom(signer: IKeyringPair, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {
+    const approveResult = await this.helper.executeExtrinsic(
+      signer,
+      'api.tx.unique.approveFrom', [fromAddressObj, toAddressObj, collectionId, tokenId, amount],
+      true, // `Unable to approve token for ${label}`,
+    );
+
+    return this.helper.util.findCollectionInEvents(approveResult.result.events, collectionId, 'common', 'Approved');
+  }
+
+  /**
+   * Set, change, or remove approved address to transfer the ownership of the NFT from eth mirror.
+   *
+   * @param signer keyring of signer
+   * @param collectionId ID of collection
+   * @param tokenId ID of token
+   * @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 approveTokenFromEth(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {
+    const ethMirror = CrossAccountId.fromKeyring(signer).toEthereum();
+    return await this.approveTokenFrom(signer, collectionId, tokenId, ethMirror, toAddressObj, amount);
+  }
+
+  /**
    * Get the amount of token pieces approved to transfer or burn. Normally 0.
    *
    * @param collectionId ID of collection
@@ -1756,8 +1796,8 @@
    * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})
    * @returns ```true``` if extrinsic success, otherwise ```false```
    */
-  approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId) {
-    return super.approveToken(signer, collectionId, tokenId, toAddressObj, 1n);
+  approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, amount=1n) {
+    return super.approveToken(signer, collectionId, tokenId, toAddressObj, amount);
   }
 }