git.delta.rocks / unique-network / refs/commits / 504df77ef385

difftreelog

refactor nesting permission structure

Yaroslav Bolyukin2022-06-10parent: #bb7c8cc.patch.diff
in: master

20 files changed

modifiedpallets/common/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/common/src/benchmarking.rs
+++ b/pallets/common/src/benchmarking.rs
@@ -20,7 +20,7 @@
 use frame_benchmarking::{benchmarks, account};
 use up_data_structs::{
 	CollectionMode, CreateCollectionData, CollectionId, Property, PropertyKey, PropertyValue,
-	CollectionPermissions, NestingRule, MAX_COLLECTION_NAME_LENGTH,
+	CollectionPermissions, NestingPermissions, MAX_COLLECTION_NAME_LENGTH,
 	MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, MAX_PROPERTIES_PER_ITEM,
 };
 use frame_support::{
@@ -94,7 +94,12 @@
 			description,
 			token_prefix,
 			permissions: Some(CollectionPermissions {
-				nesting: Some(NestingRule::Permissive),
+				nesting: Some(NestingPermissions {
+					token_owner: false,
+					admin: false,
+					restricted: None,
+					permissive: true,
+				}),
 				..Default::default()
 			}),
 			..Default::default()
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -22,7 +22,7 @@
 pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};
 use pallet_evm_coder_substrate::dispatch_to_evm;
 use sp_std::vec::Vec;
-use up_data_structs::{Property, SponsoringRateLimit, NestingRule, OwnerRestrictedSet, AccessMode};
+use up_data_structs::{Property, SponsoringRateLimit, OwnerRestrictedSet, AccessMode};
 use alloc::format;
 
 use crate::{Pallet, CollectionHandle, Config, CollectionProperties};
@@ -215,12 +215,21 @@
 		let caller = T::CrossAccountId::from_eth(caller);
 		self.check_is_owner_or_admin(&caller)
 			.map_err(dispatch_to_evm::<T>)?;
-		self.collection.permissions.nesting = Some(match enable {
-			false => NestingRule::Disabled,
-			true => NestingRule::Owner,
-		});
-		save(self)?;
-		Ok(())
+
+		let mut permissions = self.collection.permissions.clone();
+		let mut nesting = permissions.nesting().clone();
+		nesting.token_owner = enable;
+		nesting.restricted = None;
+		permissions.nesting = Some(nesting);
+
+		self.collection.permissions = <Pallet<T>>::clamp_permissions(
+			self.collection.mode.clone(),
+			&self.collection.permissions,
+			permissions,
+		)
+		.map_err(dispatch_to_evm::<T>)?;
+
+		save(self)
 	}
 
 	#[solidity(rename_selector = "setCollectionNesting")]
@@ -233,31 +242,41 @@
 		if collections.is_empty() {
 			return Err("No addresses provided".into());
 		}
-		if collections.len() >= OwnerRestrictedSet::bound() {
-			return Err(Error::Revert(format!(
-				"Out of bound: {} >= {}",
-				collections.len(),
-				OwnerRestrictedSet::bound()
-			)));
-		}
 		let caller = T::CrossAccountId::from_eth(caller);
 		self.check_is_owner_or_admin(&caller)
 			.map_err(dispatch_to_evm::<T>)?;
-		self.collection.permissions.nesting = Some(match enable {
-			false => NestingRule::Disabled,
+
+		let mut permissions = self.collection.permissions.clone();
+		match enable {
+			false => {
+				let mut nesting = permissions.nesting().clone();
+				nesting.token_owner = false;
+				nesting.restricted = None;
+				permissions.nesting = Some(nesting);
+			}
 			true => {
 				let mut bv = OwnerRestrictedSet::new();
 				for i in collections {
 					bv.try_insert(crate::eth::map_eth_to_id(&i).ok_or(Error::Revert(
 						"Can't convert address into collection id".into(),
 					))?)
-					.map_err(|e| Error::Revert(format!("{:?}", e)))?;
+					.map_err(|_| "too many collections")?;
 				}
-				NestingRule::OwnerRestricted(bv)
+				let mut nesting = permissions.nesting().clone();
+				nesting.token_owner = true;
+				nesting.restricted = Some(bv);
+				permissions.nesting = Some(nesting);
 			}
-		});
-		save(self)?;
-		Ok(())
+		};
+
+		self.collection.permissions = <Pallet<T>>::clamp_permissions(
+			self.collection.mode.clone(),
+			&self.collection.permissions,
+			permissions,
+		)
+		.map_err(dispatch_to_evm::<T>)?;
+
+		save(self)
 	}
 
 	fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -430,10 +430,8 @@
 		/// Not sufficient funds to perform action
 		NotSufficientFounds,
 
-		/// Collection has nesting disabled
-		NestingIsDisabled,
-		/// Only owner may nest tokens under this collection
-		OnlyOwnerAllowedToNest,
+		/// User not passed nesting rule
+		UserIsNotAllowedToNest,
 		/// Only tokens from specific collections may nest tokens under this
 		SourceCollectionIsNotAllowedToNest,
 
@@ -1212,7 +1210,11 @@
 		limit_default_clone!(old_limit, new_limit,
 			access => {},
 			mint_mode => {},
-			nesting => {},
+			nesting => ensure!(
+				// Permissive is only allowed for tests and internal usage of chain for now
+				old_limit.permissive || !new_limit.permissive,
+				<Error<T>>::NoPermission,
+			),
 		);
 		Ok(new_limit)
 	}
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -27,8 +27,8 @@
 };
 use up_data_structs::{
 	AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData, CreateNftExData,
-	mapping::TokenAddressMapping, NestingRule, budget::Budget, Property, PropertyPermission,
-	PropertyKey, PropertyKeyPermission, Properties, PropertyScope, TrySetProperty, TokenChild,
+	mapping::TokenAddressMapping, budget::Budget, Property, PropertyPermission, PropertyKey,
+	PropertyKeyPermission, Properties, PropertyScope, TrySetProperty, TokenChild,
 };
 use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
 use pallet_common::{
@@ -996,38 +996,29 @@
 		under: TokenId,
 		nesting_budget: &dyn Budget,
 	) -> DispatchResult {
-		fn ensure_sender_allowed<T: Config>(
-			collection: CollectionId,
-			token: TokenId,
-			for_nest: (CollectionId, TokenId),
-			sender: T::CrossAccountId,
-			budget: &dyn Budget,
-		) -> DispatchResult {
+		let nesting = handle.permissions.nesting();
+		if nesting.permissive {
+			// Pass
+		} else if nesting.token_owner
+			&& <PalletStructure<T>>::check_indirectly_owned(
+				sender.clone(),
+				handle.id,
+				under,
+				Some(from),
+				nesting_budget,
+			)? {
+			// Pass
+		} else if nesting.admin && handle.is_owner_or_admin(&sender) {
+			// Pass
+		} else {
+			fail!(<CommonError<T>>::UserIsNotAllowedToNest);
+		}
+
+		if let Some(whitelist) = &nesting.restricted {
 			ensure!(
-				<PalletStructure<T>>::check_indirectly_owned(
-					sender,
-					collection,
-					token,
-					Some(for_nest),
-					budget
-				)?,
-				<CommonError<T>>::OnlyOwnerAllowedToNest,
+				whitelist.contains(&from.0),
+				<CommonError<T>>::SourceCollectionIsNotAllowedToNest
 			);
-			Ok(())
-		}
-		match handle.permissions.nesting() {
-			NestingRule::Disabled => fail!(<CommonError<T>>::NestingIsDisabled),
-			NestingRule::Owner => {
-				ensure_sender_allowed::<T>(handle.id, under, from, sender, nesting_budget)?
-			}
-			NestingRule::OwnerRestricted(whitelist) => {
-				ensure!(
-					whitelist.contains(&from.0),
-					<CommonError<T>>::SourceCollectionIsNotAllowedToNest
-				);
-				ensure_sender_allowed::<T>(handle.id, under, from, sender, nesting_budget)?
-			}
-			NestingRule::Permissive => {}
 		}
 		Ok(())
 	}
modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
before · pallets/proxy-rmrk-core/src/lib.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![cfg_attr(not(feature = "std"), no_std)]1819use frame_support::{pallet_prelude::*, transactional, BoundedVec, dispatch::DispatchResult};20use frame_system::{pallet_prelude::*, ensure_signed};21use sp_runtime::{DispatchError, Permill, traits::StaticLookup};22use sp_std::vec::Vec;23use up_data_structs::{*, mapping::TokenAddressMapping};24use pallet_common::{25	Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,26};27use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};28use pallet_structure::{Pallet as PalletStructure, Error as StructureError};29use pallet_evm::account::CrossAccountId;30use core::convert::AsRef;3132pub use pallet::*;3334#[cfg(feature = "runtime-benchmarks")]35pub mod benchmarking;36pub mod misc;37pub mod property;38pub mod weights;3940pub type SelfWeightOf<T> = <T as Config>::WeightInfo;4142use weights::WeightInfo;43use misc::*;44pub use property::*;4546use RmrkProperty::*;4748const NESTING_BUDGET: u32 = 5;4950#[frame_support::pallet]51pub mod pallet {52	use super::*;53	use pallet_evm::account;5455	#[pallet::config]56	pub trait Config:57		frame_system::Config + pallet_common::Config + pallet_nonfungible::Config + account::Config58	{59		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;60		type WeightInfo: WeightInfo;61	}6263	#[pallet::storage]64	#[pallet::getter(fn collection_index)]65	pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;6667	#[pallet::storage]68	pub type UniqueCollectionId<T: Config> =69		StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;7071	#[pallet::storage]72	pub type RmrkInernalCollectionId<T: Config> =73		StorageMap<_, Twox64Concat, CollectionId, RmrkCollectionId, ValueQuery>;7475	#[pallet::pallet]76	#[pallet::generate_store(pub(super) trait Store)]77	pub struct Pallet<T>(_);7879	#[pallet::event]80	#[pallet::generate_deposit(pub(super) fn deposit_event)]81	pub enum Event<T: Config> {82		CollectionCreated {83			issuer: T::AccountId,84			collection_id: RmrkCollectionId,85		},86		CollectionDestroyed {87			issuer: T::AccountId,88			collection_id: RmrkCollectionId,89		},90		IssuerChanged {91			old_issuer: T::AccountId,92			new_issuer: T::AccountId,93			collection_id: RmrkCollectionId,94		},95		CollectionLocked {96			issuer: T::AccountId,97			collection_id: RmrkCollectionId,98		},99		NftMinted {100			owner: T::AccountId,101			collection_id: RmrkCollectionId,102			nft_id: RmrkNftId,103		},104		NFTBurned {105			owner: T::AccountId,106			nft_id: RmrkNftId,107		},108		NFTSent {109			sender: T::AccountId,110			recipient: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,111			collection_id: RmrkCollectionId,112			nft_id: RmrkNftId,113			approval_required: bool,114		},115		NFTAccepted {116			sender: T::AccountId,117			recipient: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,118			collection_id: RmrkCollectionId,119			nft_id: RmrkNftId,120		},121		NFTRejected {122			sender: T::AccountId,123			collection_id: RmrkCollectionId,124			nft_id: RmrkNftId,125		},126		PropertySet {127			collection_id: RmrkCollectionId,128			maybe_nft_id: Option<RmrkNftId>,129			key: RmrkKeyString,130			value: RmrkValueString,131		},132		ResourceAdded {133			nft_id: RmrkNftId,134			resource_id: RmrkResourceId,135		},136		ResourceRemoval {137			nft_id: RmrkNftId,138			resource_id: RmrkResourceId,139		},140		ResourceAccepted {141			nft_id: RmrkNftId,142			resource_id: RmrkResourceId,143		},144		ResourceRemovalAccepted {145			nft_id: RmrkNftId,146			resource_id: RmrkResourceId,147		},148		PrioritySet {149			collection_id: RmrkCollectionId,150			nft_id: RmrkNftId,151		},152	}153154	#[pallet::error]155	pub enum Error<T> {156		/* Unique-specific events */157		CorruptedCollectionType,158		NftTypeEncodeError,159		RmrkPropertyKeyIsTooLong,160		RmrkPropertyValueIsTooLong,161162		/* RMRK compatible events */163		CollectionNotEmpty,164		NoAvailableCollectionId,165		NoAvailableNftId,166		CollectionUnknown,167		NoPermission,168		NonTransferable,169		CollectionFullOrLocked,170		ResourceDoesntExist,171		CannotSendToDescendentOrSelf,172		CannotAcceptNonOwnedNft,173		CannotRejectNonOwnedNft,174		ResourceNotPending,175	}176177	#[pallet::call]178	impl<T: Config> Pallet<T> {179		/// Create a collection180		#[transactional]181		#[pallet::weight(<SelfWeightOf<T>>::create_collection())]182		pub fn create_collection(183			origin: OriginFor<T>,184			metadata: RmrkString,185			max: Option<u32>,186			symbol: RmrkCollectionSymbol,187		) -> DispatchResult {188			let sender = ensure_signed(origin)?;189190			let limits = CollectionLimits {191				owner_can_transfer: Some(false),192				token_limit: max,193				..Default::default()194			};195196			let data = CreateCollectionData {197				limits: Some(limits),198				token_prefix: symbol199					.into_inner()200					.try_into()201					.map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,202				permissions: Some(CollectionPermissions {203					nesting: Some(NestingRule::Owner),204					..Default::default()205				}),206				..Default::default()207			};208209			let unique_collection_id = Self::init_collection(210				T::CrossAccountId::from_sub(sender.clone()),211				data,212				[213					Self::rmrk_property(Metadata, &metadata)?,214					Self::rmrk_property(CollectionType, &misc::CollectionType::Regular)?,215				]216				.into_iter(),217			)?;218			let rmrk_collection_id = <CollectionIndex<T>>::get();219220			<UniqueCollectionId<T>>::insert(rmrk_collection_id, unique_collection_id);221			<RmrkInernalCollectionId<T>>::insert(unique_collection_id, rmrk_collection_id);222223			<CollectionIndex<T>>::mutate(|n| *n += 1);224225			Self::deposit_event(Event::CollectionCreated {226				issuer: sender,227				collection_id: rmrk_collection_id,228			});229230			Ok(())231		}232233		/// destroy collection234		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]235		#[transactional]236		pub fn destroy_collection(237			origin: OriginFor<T>,238			collection_id: RmrkCollectionId,239		) -> DispatchResult {240			let sender = ensure_signed(origin)?;241			let cross_sender = T::CrossAccountId::from_sub(sender.clone());242243			let collection = Self::get_typed_nft_collection(244				Self::unique_collection_id(collection_id)?,245				misc::CollectionType::Regular,246			)?;247			collection.check_is_external()?;248249			<PalletNft<T>>::destroy_collection(collection, &cross_sender)250				.map_err(Self::map_unique_err_to_proxy)?;251252			Self::deposit_event(Event::CollectionDestroyed {253				issuer: sender,254				collection_id,255			});256257			Ok(())258		}259260		/// Change the issuer of a collection261		///262		/// Parameters:263		/// - `origin`: sender of the transaction264		/// - `collection_id`: collection id of the nft to change issuer of265		/// - `new_issuer`: Collection's new issuer266		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]267		#[transactional]268		pub fn change_collection_issuer(269			origin: OriginFor<T>,270			collection_id: RmrkCollectionId,271			new_issuer: <T::Lookup as StaticLookup>::Source,272		) -> DispatchResult {273			let sender = ensure_signed(origin)?;274275			let collection = Self::get_nft_collection(Self::unique_collection_id(collection_id)?)?;276			collection.check_is_external()?;277278			let new_issuer = T::Lookup::lookup(new_issuer)?;279280			Self::change_collection_owner(281				Self::unique_collection_id(collection_id)?,282				misc::CollectionType::Regular,283				sender.clone(),284				new_issuer.clone(),285			)?;286287			Self::deposit_event(Event::IssuerChanged {288				old_issuer: sender,289				new_issuer,290				collection_id,291			});292293			Ok(())294		}295296		/// lock collection297		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]298		#[transactional]299		pub fn lock_collection(300			origin: OriginFor<T>,301			collection_id: RmrkCollectionId,302		) -> DispatchResult {303			let sender = ensure_signed(origin)?;304			let cross_sender = T::CrossAccountId::from_sub(sender.clone());305306			let collection = Self::get_typed_nft_collection(307				Self::unique_collection_id(collection_id)?,308				misc::CollectionType::Regular,309			)?;310			collection.check_is_external()?;311312			Self::check_collection_owner(&collection, &cross_sender)?;313314			let token_count = collection.total_supply();315316			let mut collection = collection.into_inner();317			collection.limits.token_limit = Some(token_count);318			collection.save()?;319320			Self::deposit_event(Event::CollectionLocked {321				issuer: sender,322				collection_id,323			});324325			Ok(())326		}327328		/// Mints an NFT in the specified collection329		/// Sets metadata and the royalty attribute330		///331		/// Parameters:332		/// - `collection_id`: The class of the asset to be minted.333		/// - `nft_id`: The nft value of the asset to be minted.334		/// - `recipient`: Receiver of the royalty335		/// - `royalty`: Permillage reward from each trade for the Recipient336		/// - `metadata`: Arbitrary data about an nft, e.g. IPFS hash337		/// - `transferable`: Ability to transfer this NFT338		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]339		#[transactional]340		pub fn mint_nft(341			origin: OriginFor<T>,342			owner: T::AccountId,343			collection_id: RmrkCollectionId,344			recipient: Option<T::AccountId>,345			royalty_amount: Option<Permill>,346			metadata: RmrkString,347			transferable: bool,348		) -> DispatchResult {349			let sender = ensure_signed(origin)?;350			let sender = T::CrossAccountId::from_sub(sender);351			let cross_owner = T::CrossAccountId::from_sub(owner.clone());352353			let collection = Self::get_typed_nft_collection(354				Self::unique_collection_id(collection_id)?,355				misc::CollectionType::Regular,356			)?;357			collection.check_is_external()?;358359			let royalty_info = royalty_amount.map(|amount| rmrk_traits::RoyaltyInfo {360				recipient: recipient.unwrap_or_else(|| owner.clone()),361				amount,362			});363364			let nft_id = Self::create_nft(365				&sender,366				&cross_owner,367				&collection,368				[369					Self::rmrk_property(TokenType, &NftType::Regular)?,370					Self::rmrk_property(Transferable, &transferable)?,371					Self::rmrk_property(PendingNftAccept, &false)?,372					Self::rmrk_property(RoyaltyInfo, &royalty_info)?,373					Self::rmrk_property(Metadata, &metadata)?,374					Self::rmrk_property(Equipped, &false)?,375					Self::rmrk_property(376						ResourceCollection,377						&Self::init_collection(378							sender.clone(),379							CreateCollectionData {380								..Default::default()381							},382							[Self::rmrk_property(383								CollectionType,384								&misc::CollectionType::Resource,385							)?]386							.into_iter(),387						)?,388					)?, // todo possibly add limits to the collection if rmrk warrants them389					Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,390				]391				.into_iter(),392			)393			.map_err(|err| match err {394				DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),395				err => Self::map_unique_err_to_proxy(err),396			})?;397398			Self::deposit_event(Event::NftMinted {399				owner,400				collection_id,401				nft_id: nft_id.0,402			});403404			Ok(())405		}406407		/// burn nft408		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]409		#[transactional]410		pub fn burn_nft(411			origin: OriginFor<T>,412			collection_id: RmrkCollectionId,413			nft_id: RmrkNftId,414		) -> DispatchResult {415			let sender = ensure_signed(origin)?;416			let cross_sender = T::CrossAccountId::from_sub(sender.clone());417418			let collection = Self::get_typed_nft_collection(419				Self::unique_collection_id(collection_id)?,420				misc::CollectionType::Regular,421			)?;422			collection.check_is_external()?;423424			Self::destroy_nft(425				cross_sender,426				Self::unique_collection_id(collection_id)?,427				nft_id.into(),428			)429			.map_err(Self::map_unique_err_to_proxy)?;430431			Self::deposit_event(Event::NFTBurned {432				owner: sender,433				nft_id,434			});435436			Ok(())437		}438439		/// Transfers a NFT from an Account or NFT A to another Account or NFT B440		///441		/// Parameters:442		/// - `origin`: sender of the transaction443		/// - `rmrk_collection_id`: collection id of the nft to be transferred444		/// - `rmrk_nft_id`: nft id of the nft to be transferred445		/// - `new_owner`: new owner of the nft which can be either an account or a NFT446		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]447		#[transactional]448		pub fn send(449			origin: OriginFor<T>,450			rmrk_collection_id: RmrkCollectionId,451			rmrk_nft_id: RmrkNftId,452			new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,453		) -> DispatchResult {454			let sender = ensure_signed(origin.clone())?;455			let cross_sender = T::CrossAccountId::from_sub(sender.clone());456457			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;458			let nft_id = rmrk_nft_id.into();459460			let collection =461				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;462			collection.check_is_external()?;463464			let token_data =465				<TokenData<T>>::get((collection_id, nft_id)).ok_or(<Error<T>>::NoAvailableNftId)?;466467			let from = token_data.owner;468469			ensure!(470				Self::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Transferable)?,471				<Error<T>>::NonTransferable472			);473474			ensure!(475				!Self::get_nft_property_decoded(476					collection_id,477					nft_id,478					RmrkProperty::PendingNftAccept479				)?,480				<Error<T>>::NoPermission481			);482483			let target_owner;484			let approval_required;485486			match new_owner {487				RmrkAccountIdOrCollectionNftTuple::AccountId(ref account_id) => {488					target_owner = T::CrossAccountId::from_sub(account_id.clone());489					approval_required = false;490				}491				RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(492					target_collection_id,493					target_nft_id,494				) => {495					let target_collection_id = Self::unique_collection_id(target_collection_id)?;496497					let target_nft_budget = budget::Value::new(NESTING_BUDGET);498499					let target_nft_owner = <PalletStructure<T>>::get_checked_topmost_owner(500						target_collection_id,501						target_nft_id.into(),502						Some((collection_id, nft_id)),503						&target_nft_budget,504					)505					.map_err(Self::map_unique_err_to_proxy)?;506507					approval_required = cross_sender != target_nft_owner;508509					if approval_required {510						target_owner = target_nft_owner;511512						<PalletNft<T>>::set_scoped_token_property(513							collection.id,514							nft_id,515							PropertyScope::Rmrk,516							Self::rmrk_property(PendingNftAccept, &approval_required)?,517						)?;518					} else {519						target_owner = T::CrossTokenAddressMapping::token_to_address(520							target_collection_id,521							target_nft_id.into(),522						);523					}524				}525			}526527			let src_nft_budget = budget::Value::new(NESTING_BUDGET);528529			<PalletNft<T>>::transfer_from(530				&collection,531				&cross_sender,532				&from,533				&target_owner,534				nft_id,535				&src_nft_budget,536			)537			.map_err(Self::map_unique_err_to_proxy)?;538539			Self::deposit_event(Event::NFTSent {540				sender,541				recipient: new_owner,542				collection_id: rmrk_collection_id,543				nft_id: rmrk_nft_id,544				approval_required,545			});546547			Ok(())548		}549550		/// Accepts an NFT sent from another account to self or owned NFT551		///552		/// Parameters:553		/// - `origin`: sender of the transaction554		/// - `rmrk_collection_id`: collection id of the nft to be accepted555		/// - `rmrk_nft_id`: nft id of the nft to be accepted556		/// - `new_owner`: either origin's account ID or origin-owned NFT, whichever the NFT was557		///   sent to558		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]559		#[transactional]560		pub fn accept_nft(561			origin: OriginFor<T>,562			rmrk_collection_id: RmrkCollectionId,563			rmrk_nft_id: RmrkNftId,564			new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,565		) -> DispatchResult {566			let sender = ensure_signed(origin.clone())?;567			let cross_sender = T::CrossAccountId::from_sub(sender.clone());568569			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;570			let nft_id = rmrk_nft_id.into();571572			let collection =573				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;574			collection.check_is_external()?;575576			let new_cross_owner = match new_owner {577				RmrkAccountIdOrCollectionNftTuple::AccountId(ref account_id) => {578					T::CrossAccountId::from_sub(account_id.clone())579				}580				RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(581					target_collection_id,582					target_nft_id,583				) => {584					let target_collection_id = Self::unique_collection_id(target_collection_id)?;585586					T::CrossTokenAddressMapping::token_to_address(587						target_collection_id,588						TokenId(target_nft_id),589					)590				}591			};592593			let budget = budget::Value::new(NESTING_BUDGET);594595			<PalletNft<T>>::transfer(596				&collection,597				&cross_sender,598				&new_cross_owner,599				nft_id,600				&budget,601			)602			.map_err(|err| {603				if err == <CommonError<T>>::OnlyOwnerAllowedToNest.into() {604					<Error<T>>::CannotAcceptNonOwnedNft.into()605				} else {606					Self::map_unique_err_to_proxy(err)607				}608			})?;609610			<PalletNft<T>>::set_scoped_token_property(611				collection.id,612				nft_id,613				PropertyScope::Rmrk,614				Self::rmrk_property(PendingNftAccept, &false)?,615			)?;616617			Self::deposit_event(Event::NFTAccepted {618				sender,619				recipient: new_owner,620				collection_id: rmrk_collection_id,621				nft_id: rmrk_nft_id,622			});623624			Ok(())625		}626627		/// Rejects an NFT sent from another account to self or owned NFT628		///629		/// Parameters:630		/// - `origin`: sender of the transaction631		/// - `rmrk_collection_id`: collection id of the nft to be accepted632		/// - `rmrk_nft_id`: nft id of the nft to be accepted633		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]634		#[transactional]635		pub fn reject_nft(636			origin: OriginFor<T>,637			rmrk_collection_id: RmrkCollectionId,638			rmrk_nft_id: RmrkNftId,639		) -> DispatchResult {640			let sender = ensure_signed(origin)?;641			let cross_sender = T::CrossAccountId::from_sub(sender.clone());642643			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;644			let nft_id = rmrk_nft_id.into();645646			let collection =647				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;648			collection.check_is_external()?;649650			Self::destroy_nft(cross_sender, collection_id, nft_id).map_err(|err| {651				if err == <CommonError<T>>::NoPermission.into()652					|| err == <CommonError<T>>::ApprovedValueTooLow.into()653				{654					<Error<T>>::CannotRejectNonOwnedNft.into()655				} else {656					Self::map_unique_err_to_proxy(err)657				}658			})?;659660			Self::deposit_event(Event::NFTRejected {661				sender,662				collection_id: rmrk_collection_id,663				nft_id: rmrk_nft_id,664			});665666			Ok(())667		}668669		/// accept the addition of a new resource to an existing NFT670		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]671		#[transactional]672		pub fn accept_resource(673			origin: OriginFor<T>,674			rmrk_collection_id: RmrkCollectionId,675			rmrk_nft_id: RmrkNftId,676			rmrk_resource_id: RmrkResourceId,677		) -> DispatchResult {678			let sender = ensure_signed(origin)?;679			let cross_sender = T::CrossAccountId::from_sub(sender);680681			let collection_id = Self::unique_collection_id(rmrk_collection_id)682				.map_err(|_| <Error<T>>::ResourceDoesntExist)?;683			let collection =684				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;685			collection.check_is_external()?;686687			let nft_id = rmrk_nft_id.into();688			let resource_id = rmrk_resource_id.into();689690			let budget = budget::Value::new(NESTING_BUDGET);691692			let nft_owner =693				<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)694					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;695696			let resource_collection_id: CollectionId =697				Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)698					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;699700			let is_pending: bool = Self::get_nft_property_decoded(701				resource_collection_id,702				resource_id,703				PendingResourceAccept,704			)705			.map_err(|_| <Error<T>>::ResourceDoesntExist)?;706707			ensure!(is_pending, <Error<T>>::ResourceNotPending);708709			ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);710711			<PalletNft<T>>::set_scoped_token_property(712				resource_collection_id,713				rmrk_resource_id.into(),714				PropertyScope::Rmrk,715				Self::rmrk_property(PendingResourceAccept, &false)?,716			)?;717718			Self::deposit_event(Event::<T>::ResourceAccepted {719				nft_id: rmrk_nft_id,720				resource_id: rmrk_resource_id,721			});722723			Ok(())724		}725726		/// accept the removal of a resource of an existing NFT727		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]728		#[transactional]729		pub fn accept_resource_removal(730			origin: OriginFor<T>,731			rmrk_collection_id: RmrkCollectionId,732			rmrk_nft_id: RmrkNftId,733			rmrk_resource_id: RmrkResourceId,734		) -> DispatchResult {735			let sender = ensure_signed(origin)?;736			let cross_sender = T::CrossAccountId::from_sub(sender);737738			let collection_id = Self::unique_collection_id(rmrk_collection_id)739				.map_err(|_| <Error<T>>::ResourceDoesntExist)?;740			let collection =741				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;742			collection.check_is_external()?;743744			let nft_id = rmrk_nft_id.into();745			let resource_id = rmrk_resource_id.into();746747			let budget = budget::Value::new(NESTING_BUDGET);748749			let nft_owner =750				<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)751					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;752753			ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);754755			let resource_collection_id: CollectionId =756				Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)757					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;758759			let is_pending: bool = Self::get_nft_property_decoded(760				resource_collection_id,761				resource_id,762				PendingResourceRemoval,763			)764			.map_err(|_| <Error<T>>::ResourceDoesntExist)?;765766			ensure!(is_pending, <Error<T>>::ResourceNotPending);767768			let resource_collection = Self::get_typed_nft_collection(769				resource_collection_id,770				misc::CollectionType::Resource,771			)?;772773			<PalletNft<T>>::burn(&resource_collection, &cross_sender, rmrk_resource_id.into())774				.map_err(Self::map_unique_err_to_proxy)?;775776			Self::deposit_event(Event::<T>::ResourceRemovalAccepted {777				nft_id: rmrk_nft_id,778				resource_id: rmrk_resource_id,779			});780781			Ok(())782		}783784		/// set a custom value on an NFT785		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]786		#[transactional]787		pub fn set_property(788			origin: OriginFor<T>,789			#[pallet::compact] rmrk_collection_id: RmrkCollectionId,790			maybe_nft_id: Option<RmrkNftId>,791			key: RmrkKeyString,792			value: RmrkValueString,793		) -> DispatchResult {794			let sender = ensure_signed(origin)?;795			let sender = T::CrossAccountId::from_sub(sender);796797			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;798			let collection =799				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;800			collection.check_is_external()?;801802			let budget = budget::Value::new(NESTING_BUDGET);803804			match maybe_nft_id {805				Some(nft_id) => {806					let token_id: TokenId = nft_id.into();807808					Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;809					Self::ensure_nft_owner(collection_id, token_id, &sender, &budget)?;810811					<PalletNft<T>>::set_scoped_token_property(812						collection_id,813						token_id,814						PropertyScope::Rmrk,815						Self::rmrk_property(UserProperty(key.as_slice()), &value)?,816					)?;817				}818				None => {819					let collection = Self::get_typed_nft_collection(820						collection_id,821						misc::CollectionType::Regular,822					)?;823824					Self::check_collection_owner(&collection, &sender)?;825826					<PalletCommon<T>>::set_scoped_collection_property(827						collection_id,828						PropertyScope::Rmrk,829						Self::rmrk_property(UserProperty(key.as_slice()), &value)?,830					)?;831				}832			}833834			Self::deposit_event(Event::PropertySet {835				collection_id: rmrk_collection_id,836				maybe_nft_id,837				key,838				value,839			});840841			Ok(())842		}843844		/// set a different order of resource priority845		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]846		#[transactional]847		pub fn set_priority(848			origin: OriginFor<T>,849			rmrk_collection_id: RmrkCollectionId,850			rmrk_nft_id: RmrkNftId,851			priorities: BoundedVec<RmrkResourceId, RmrkMaxPriorities>,852		) -> DispatchResult {853			let sender = ensure_signed(origin)?;854			let sender = T::CrossAccountId::from_sub(sender);855856			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;857			let nft_id = rmrk_nft_id.into();858859			let collection =860				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;861			collection.check_is_external()?;862863			let budget = budget::Value::new(NESTING_BUDGET);864865			Self::ensure_nft_type(collection_id, nft_id, NftType::Regular)?;866			Self::ensure_nft_owner(collection_id, nft_id, &sender, &budget)?;867868			<PalletNft<T>>::set_scoped_token_property(869				collection_id,870				nft_id,871				PropertyScope::Rmrk,872				Self::rmrk_property(ResourcePriorities, &priorities.into_inner())?,873			)?;874875			Self::deposit_event(Event::<T>::PrioritySet {876				collection_id: rmrk_collection_id,877				nft_id: rmrk_nft_id,878			});879880			Ok(())881		}882883		/// Create basic resource884		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]885		#[transactional]886		pub fn add_basic_resource(887			origin: OriginFor<T>,888			rmrk_collection_id: RmrkCollectionId,889			nft_id: RmrkNftId,890			resource: RmrkBasicResource,891		) -> DispatchResult {892			let sender = ensure_signed(origin.clone())?;893894			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;895			let collection =896				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;897			collection.check_is_external()?;898899			let resource_id = Self::resource_add(900				sender,901				collection_id,902				nft_id.into(),903				[904					Self::rmrk_property(TokenType, &NftType::Resource)?,905					Self::rmrk_property(ResourceType, &misc::ResourceType::Basic)?,906					Self::rmrk_property(Src, &resource.src)?,907					Self::rmrk_property(Metadata, &resource.metadata)?,908					Self::rmrk_property(License, &resource.license)?,909					Self::rmrk_property(Thumb, &resource.thumb)?,910				]911				.into_iter(),912			)?;913914			Self::deposit_event(Event::ResourceAdded {915				nft_id,916				resource_id,917			});918			Ok(())919		}920921		/// Create composable resource922		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]923		#[transactional]924		pub fn add_composable_resource(925			origin: OriginFor<T>,926			rmrk_collection_id: RmrkCollectionId,927			nft_id: RmrkNftId,928			_resource_id: RmrkBoundedResource,929			resource: RmrkComposableResource,930		) -> DispatchResult {931			let sender = ensure_signed(origin.clone())?;932933			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;934			let collection =935				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;936			collection.check_is_external()?;937938			let resource_id = Self::resource_add(939				sender,940				collection_id,941				nft_id.into(),942				[943					Self::rmrk_property(TokenType, &NftType::Resource)?,944					Self::rmrk_property(ResourceType, &misc::ResourceType::Composable)?,945					Self::rmrk_property(Parts, &resource.parts)?,946					Self::rmrk_property(Base, &resource.base)?,947					Self::rmrk_property(Src, &resource.src)?,948					Self::rmrk_property(Metadata, &resource.metadata)?,949					Self::rmrk_property(License, &resource.license)?,950					Self::rmrk_property(Thumb, &resource.thumb)?,951				]952				.into_iter(),953			)?;954955			Self::deposit_event(Event::ResourceAdded {956				nft_id,957				resource_id,958			});959			Ok(())960		}961962		/// Create slot resource963		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]964		#[transactional]965		pub fn add_slot_resource(966			origin: OriginFor<T>,967			rmrk_collection_id: RmrkCollectionId,968			nft_id: RmrkNftId,969			resource: RmrkSlotResource,970		) -> DispatchResult {971			let sender = ensure_signed(origin.clone())?;972973			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;974			let collection =975				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;976			collection.check_is_external()?;977978			let resource_id = Self::resource_add(979				sender,980				collection_id,981				nft_id.into(),982				[983					Self::rmrk_property(TokenType, &NftType::Resource)?,984					Self::rmrk_property(ResourceType, &misc::ResourceType::Slot)?,985					Self::rmrk_property(Base, &resource.base)?,986					Self::rmrk_property(Src, &resource.src)?,987					Self::rmrk_property(Metadata, &resource.metadata)?,988					Self::rmrk_property(Slot, &resource.slot)?,989					Self::rmrk_property(License, &resource.license)?,990					Self::rmrk_property(Thumb, &resource.thumb)?,991				]992				.into_iter(),993			)?;994995			Self::deposit_event(Event::ResourceAdded {996				nft_id,997				resource_id,998			});999			Ok(())1000		}10011002		/// remove resource1003		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]1004		#[transactional]1005		pub fn remove_resource(1006			origin: OriginFor<T>,1007			rmrk_collection_id: RmrkCollectionId,1008			nft_id: RmrkNftId,1009			resource_id: RmrkResourceId,1010		) -> DispatchResult {1011			let sender = ensure_signed(origin.clone())?;10121013			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1014			let collection =1015				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1016			collection.check_is_external()?;10171018			Self::resource_remove(sender, collection_id, nft_id.into(), resource_id.into())?;10191020			Self::deposit_event(Event::ResourceRemoval {1021				nft_id,1022				resource_id,1023			});1024			Ok(())1025		}1026	}1027}10281029impl<T: Config> Pallet<T> {1030	pub fn rmrk_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {1031		let key = rmrk_key.to_key::<T>()?;10321033		let scoped_key = PropertyScope::Rmrk1034			.apply(key)1035			.map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;10361037		Ok(scoped_key)1038	}10391040	// todo think about renaming these1041	pub fn rmrk_property<E: Encode>(1042		rmrk_key: RmrkProperty,1043		value: &E,1044	) -> Result<Property, DispatchError> {1045		let key = rmrk_key.to_key::<T>()?;10461047		let value = value1048			.encode()1049			.try_into()1050			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;10511052		let property = Property { key, value };10531054		Ok(property)1055	}10561057	pub fn decode_property<D: Decode>(vec: PropertyValue) -> Result<D, DispatchError> {1058		vec.decode()1059			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())1060	}10611062	pub fn rebind<L, S>(vec: &BoundedVec<u8, L>) -> Result<BoundedVec<u8, S>, DispatchError>1063	where1064		BoundedVec<u8, S>: TryFrom<Vec<u8>>,1065	{1066		vec.rebind()1067			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())1068	}10691070	fn init_collection(1071		sender: T::CrossAccountId,1072		data: CreateCollectionData<T::AccountId>,1073		properties: impl Iterator<Item = Property>,1074	) -> Result<CollectionId, DispatchError> {1075		let collection_id = <PalletNft<T>>::init_collection(sender, data, true);10761077		if let Err(DispatchError::Arithmetic(_)) = &collection_id {1078			return Err(<Error<T>>::NoAvailableCollectionId.into());1079		}10801081		<PalletCommon<T>>::set_scoped_collection_properties(1082			collection_id?,1083			PropertyScope::Rmrk,1084			properties,1085		)?;10861087		collection_id1088	}10891090	pub fn create_nft(1091		sender: &T::CrossAccountId,1092		owner: &T::CrossAccountId,1093		collection: &NonfungibleHandle<T>,1094		properties: impl Iterator<Item = Property>,1095	) -> Result<TokenId, DispatchError> {1096		let data = CreateNftExData {1097			properties: BoundedVec::default(),1098			owner: owner.clone(),1099		};11001101		let budget = budget::Value::new(NESTING_BUDGET);11021103		<PalletNft<T>>::create_item(collection, sender, data, &budget)?;11041105		let nft_id = <PalletNft<T>>::current_token_id(collection.id);11061107		<PalletNft<T>>::set_scoped_token_properties(1108			collection.id,1109			nft_id,1110			PropertyScope::Rmrk,1111			properties,1112		)?;11131114		Ok(nft_id)1115	}11161117	fn destroy_nft(1118		sender: T::CrossAccountId,1119		collection_id: CollectionId,1120		token_id: TokenId,1121	) -> DispatchResult {1122		let collection =1123			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;11241125		let token_data =1126			<TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;11271128		let from = token_data.owner;11291130		let budget = budget::Value::new(NESTING_BUDGET);11311132		<PalletNft<T>>::burn_from(&collection, &sender, &from, token_id, &budget)1133	}11341135	fn resource_add(1136		sender: T::AccountId,1137		collection_id: CollectionId,1138		token_id: TokenId,1139		resource_properties: impl Iterator<Item = Property>,1140	) -> Result<RmrkResourceId, DispatchError> {1141		let collection =1142			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1143		ensure!(collection.owner == sender, Error::<T>::NoPermission);11441145		let sender = T::CrossAccountId::from_sub(sender);1146		let budget = budget::Value::new(NESTING_BUDGET);11471148		let nft_owner = <PalletStructure<T>>::find_topmost_owner(collection_id, token_id, &budget)1149			.map_err(Self::map_unique_err_to_proxy)?;11501151		let pending = sender != nft_owner;11521153		let resource_collection_id: CollectionId =1154			Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;1155		let resource_collection =1156			Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;11571158		// todo probably add extra connections to bases, slots, etc., when RMRK starts to use them11591160		let resource_id = Self::create_nft(1161			&sender,1162			&nft_owner,1163			&resource_collection,1164			resource_properties.chain(1165				[1166					Self::rmrk_property(PendingResourceAccept, &pending)?,1167					Self::rmrk_property(PendingResourceRemoval, &false)?,1168				]1169				.into_iter(),1170			),1171		)1172		.map_err(|err| match err {1173			DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),1174			err => Self::map_unique_err_to_proxy(err),1175		})?;11761177		Ok(resource_id.0)1178	}11791180	fn resource_remove(1181		sender: T::AccountId,1182		collection_id: CollectionId,1183		nft_id: TokenId,1184		resource_id: TokenId,1185	) -> DispatchResult {1186		let collection =1187			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1188		ensure!(collection.owner == sender, Error::<T>::NoPermission);11891190		let resource_collection_id: CollectionId =1191			Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)?;1192		let resource_collection =1193			Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;1194		ensure!(1195			<PalletNft<T>>::token_exists(&resource_collection, resource_id),1196			Error::<T>::ResourceDoesntExist1197		);11981199		let budget = up_data_structs::budget::Value::new(10);1200		let topmost_owner =1201			<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)?;12021203		let sender = T::CrossAccountId::from_sub(sender);1204		if topmost_owner == sender {1205			<PalletNft<T>>::burn(&resource_collection, &sender, resource_id)1206				.map_err(Self::map_unique_err_to_proxy)?;1207		} else {1208			<PalletNft<T>>::set_scoped_token_property(1209				resource_collection_id,1210				resource_id,1211				PropertyScope::Rmrk,1212				Self::rmrk_property(PendingResourceRemoval, &true)?,1213			)?;1214		}12151216		Ok(())1217	}12181219	fn change_collection_owner(1220		collection_id: CollectionId,1221		collection_type: misc::CollectionType,1222		sender: T::AccountId,1223		new_owner: T::AccountId,1224	) -> DispatchResult {1225		let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;1226		Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;12271228		let mut collection = collection.into_inner();12291230		collection.owner = new_owner;1231		collection.save()1232	}12331234	fn check_collection_owner(1235		collection: &NonfungibleHandle<T>,1236		account: &T::CrossAccountId,1237	) -> DispatchResult {1238		collection1239			.check_is_owner(account)1240			.map_err(Self::map_unique_err_to_proxy)1241	}12421243	pub fn last_collection_idx() -> RmrkCollectionId {1244		<CollectionIndex<T>>::get()1245	}12461247	pub fn unique_collection_id(1248		rmrk_collection_id: RmrkCollectionId,1249	) -> Result<CollectionId, DispatchError> {1250		<UniqueCollectionId<T>>::try_get(rmrk_collection_id)1251			.map_err(|_| <Error<T>>::CollectionUnknown.into())1252	}12531254	pub fn rmrk_collection_id(1255		unique_collection_id: CollectionId,1256	) -> Result<RmrkCollectionId, DispatchError> {1257		<RmrkInernalCollectionId<T>>::try_get(unique_collection_id)1258			.map_err(|_| <Error<T>>::CollectionUnknown.into())1259	}12601261	pub fn get_nft_collection(1262		collection_id: CollectionId,1263	) -> Result<NonfungibleHandle<T>, DispatchError> {1264		let collection = <CollectionHandle<T>>::try_get(collection_id)1265			.map_err(|_| <Error<T>>::CollectionUnknown)?;12661267		match collection.mode {1268			CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),1269			_ => Err(<Error<T>>::CollectionUnknown.into()),1270		}1271	}12721273	pub fn collection_exists(collection_id: CollectionId) -> bool {1274		<CollectionHandle<T>>::try_get(collection_id).is_ok()1275	}12761277	pub fn get_collection_property(1278		collection_id: CollectionId,1279		key: RmrkProperty,1280	) -> Result<PropertyValue, DispatchError> {1281		let collection_property = <PalletCommon<T>>::collection_properties(collection_id)1282			.get(&Self::rmrk_property_key(key)?)1283			.ok_or(<Error<T>>::CollectionUnknown)?1284			.clone();12851286		Ok(collection_property)1287	}12881289	pub fn get_collection_property_decoded<V: Decode>(1290		collection_id: CollectionId,1291		key: RmrkProperty,1292	) -> Result<V, DispatchError> {1293		Self::decode_property(Self::get_collection_property(collection_id, key)?)1294	}12951296	pub fn get_collection_type(1297		collection_id: CollectionId,1298	) -> Result<misc::CollectionType, DispatchError> {1299		Self::get_collection_property_decoded(collection_id, CollectionType)1300			.map_err(|_| <Error<T>>::CorruptedCollectionType.into())1301	}13021303	pub fn ensure_collection_type(1304		collection_id: CollectionId,1305		collection_type: misc::CollectionType,1306	) -> DispatchResult {1307		let actual_type = Self::get_collection_type(collection_id)?;1308		ensure!(1309			actual_type == collection_type,1310			<CommonError<T>>::NoPermission1311		);13121313		Ok(())1314	}13151316	pub fn get_typed_nft_collection(1317		collection_id: CollectionId,1318		collection_type: misc::CollectionType,1319	) -> Result<NonfungibleHandle<T>, DispatchError> {1320		Self::ensure_collection_type(collection_id, collection_type)?;13211322		Self::get_nft_collection(collection_id)1323	}13241325	pub fn get_typed_nft_collection_mapped(1326		rmrk_collection_id: RmrkCollectionId,1327		collection_type: misc::CollectionType,1328	) -> Result<(NonfungibleHandle<T>, CollectionId), DispatchError> {1329		let unique_collection_id = match collection_type {1330			misc::CollectionType::Regular => Self::unique_collection_id(rmrk_collection_id)?,1331			_ => rmrk_collection_id.into(),1332		};13331334		let collection = Self::get_typed_nft_collection(unique_collection_id, collection_type)?;13351336		Ok((collection, unique_collection_id))1337	}13381339	pub fn get_nft_property(1340		collection_id: CollectionId,1341		nft_id: TokenId,1342		key: RmrkProperty,1343	) -> Result<PropertyValue, DispatchError> {1344		let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))1345			.get(&Self::rmrk_property_key(key)?)1346			.ok_or(<Error<T>>::NoAvailableNftId)? // todo replace with better error?1347			.clone();13481349		Ok(nft_property)1350	}13511352	pub fn get_nft_property_decoded<V: Decode>(1353		collection_id: CollectionId,1354		nft_id: TokenId,1355		key: RmrkProperty,1356	) -> Result<V, DispatchError> {1357		Self::decode_property(Self::get_nft_property(collection_id, nft_id, key)?)1358	}13591360	pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {1361		<TokenData<T>>::contains_key((collection_id, nft_id))1362	}13631364	pub fn get_nft_type(1365		collection_id: CollectionId,1366		token_id: TokenId,1367	) -> Result<NftType, DispatchError> {1368		Self::get_nft_property_decoded(collection_id, token_id, TokenType)1369			.map_err(|_| <Error<T>>::NoAvailableNftId.into())1370	}13711372	pub fn ensure_nft_type(1373		collection_id: CollectionId,1374		token_id: TokenId,1375		nft_type: NftType,1376	) -> DispatchResult {1377		let actual_type = Self::get_nft_type(collection_id, token_id)?;1378		ensure!(actual_type == nft_type, <Error<T>>::NoPermission);13791380		Ok(())1381	}13821383	pub fn ensure_nft_owner(1384		collection_id: CollectionId,1385		token_id: TokenId,1386		possible_owner: &T::CrossAccountId,1387		nesting_budget: &dyn budget::Budget,1388	) -> DispatchResult {1389		let is_owned = <PalletStructure<T>>::check_indirectly_owned(1390			possible_owner.clone(),1391			collection_id,1392			token_id,1393			None,1394			nesting_budget,1395		)1396		.map_err(Self::map_unique_err_to_proxy)?;13971398		ensure!(is_owned, <Error<T>>::NoPermission);13991400		Ok(())1401	}14021403	pub fn filter_user_properties<Key, Value, R, Mapper>(1404		collection_id: CollectionId,1405		token_id: Option<TokenId>,1406		filter_keys: Option<Vec<RmrkPropertyKey>>,1407		mapper: Mapper,1408	) -> Result<Vec<R>, DispatchError>1409	where1410		Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,1411		Value: Decode + Default,1412		Mapper: Fn(Key, Value) -> R,1413	{1414		filter_keys1415			.map(|keys| {1416				let properties = keys1417					.into_iter()1418					.filter_map(|key| {1419						let key: Key = key.try_into().ok()?;14201421						let value = match token_id {1422							Some(token_id) => Self::get_nft_property_decoded(1423								collection_id,1424								token_id,1425								UserProperty(key.as_ref()),1426							),1427							None => Self::get_collection_property_decoded(1428								collection_id,1429								UserProperty(key.as_ref()),1430							),1431						}1432						.ok()?;14331434						Some(mapper(key, value))1435					})1436					.collect();14371438				Ok(properties)1439			})1440			.unwrap_or_else(|| {1441				let properties =1442					Self::iterate_user_properties(collection_id, token_id, mapper)?.collect();14431444				Ok(properties)1445			})1446	}14471448	pub fn iterate_user_properties<Key, Value, R, Mapper>(1449		collection_id: CollectionId,1450		token_id: Option<TokenId>,1451		mapper: Mapper,1452	) -> Result<impl Iterator<Item = R>, DispatchError>1453	where1454		Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,1455		Value: Decode + Default,1456		Mapper: Fn(Key, Value) -> R,1457	{1458		let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;14591460		let properties = match token_id {1461			Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),1462			None => <PalletCommon<T>>::collection_properties(collection_id),1463		};14641465		let properties = properties.into_iter().filter_map(move |(key, value)| {1466			let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;14671468			let key: Key = key.to_vec().try_into().ok()?;1469			let value: Value = value.decode().ok()?;14701471			Some(mapper(key, value))1472		});14731474		Ok(properties)1475	}14761477	fn map_unique_err_to_proxy(err: DispatchError) -> DispatchError {1478		map_unique_err_to_proxy! {1479			match err {1480				CommonError::NoPermission => NoPermission,1481				CommonError::CollectionTokenLimitExceeded => CollectionFullOrLocked,1482				CommonError::PublicMintingNotAllowed => NoPermission,1483				CommonError::TokenNotFound => NoAvailableNftId,1484				CommonError::ApprovedValueTooLow => NoPermission,1485				CommonError::CantDestroyNotEmptyCollection => CollectionNotEmpty,1486				StructureError::TokenNotFound => NoAvailableNftId,1487				StructureError::OuroborosDetected => CannotSendToDescendentOrSelf,1488			}1489		}1490	}1491}
after · pallets/proxy-rmrk-core/src/lib.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![cfg_attr(not(feature = "std"), no_std)]1819use frame_support::{pallet_prelude::*, transactional, BoundedVec, dispatch::DispatchResult};20use frame_system::{pallet_prelude::*, ensure_signed};21use sp_runtime::{DispatchError, Permill, traits::StaticLookup};22use sp_std::vec::Vec;23use up_data_structs::{*, mapping::TokenAddressMapping};24use pallet_common::{25	Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,26};27use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};28use pallet_structure::{Pallet as PalletStructure, Error as StructureError};29use pallet_evm::account::CrossAccountId;30use core::convert::AsRef;3132pub use pallet::*;3334#[cfg(feature = "runtime-benchmarks")]35pub mod benchmarking;36pub mod misc;37pub mod property;38pub mod weights;3940pub type SelfWeightOf<T> = <T as Config>::WeightInfo;4142use weights::WeightInfo;43use misc::*;44pub use property::*;4546use RmrkProperty::*;4748const NESTING_BUDGET: u32 = 5;4950#[frame_support::pallet]51pub mod pallet {52	use super::*;53	use pallet_evm::account;5455	#[pallet::config]56	pub trait Config:57		frame_system::Config + pallet_common::Config + pallet_nonfungible::Config + account::Config58	{59		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;60		type WeightInfo: WeightInfo;61	}6263	#[pallet::storage]64	#[pallet::getter(fn collection_index)]65	pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;6667	#[pallet::storage]68	pub type UniqueCollectionId<T: Config> =69		StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;7071	#[pallet::storage]72	pub type RmrkInernalCollectionId<T: Config> =73		StorageMap<_, Twox64Concat, CollectionId, RmrkCollectionId, ValueQuery>;7475	#[pallet::pallet]76	#[pallet::generate_store(pub(super) trait Store)]77	pub struct Pallet<T>(_);7879	#[pallet::event]80	#[pallet::generate_deposit(pub(super) fn deposit_event)]81	pub enum Event<T: Config> {82		CollectionCreated {83			issuer: T::AccountId,84			collection_id: RmrkCollectionId,85		},86		CollectionDestroyed {87			issuer: T::AccountId,88			collection_id: RmrkCollectionId,89		},90		IssuerChanged {91			old_issuer: T::AccountId,92			new_issuer: T::AccountId,93			collection_id: RmrkCollectionId,94		},95		CollectionLocked {96			issuer: T::AccountId,97			collection_id: RmrkCollectionId,98		},99		NftMinted {100			owner: T::AccountId,101			collection_id: RmrkCollectionId,102			nft_id: RmrkNftId,103		},104		NFTBurned {105			owner: T::AccountId,106			nft_id: RmrkNftId,107		},108		NFTSent {109			sender: T::AccountId,110			recipient: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,111			collection_id: RmrkCollectionId,112			nft_id: RmrkNftId,113			approval_required: bool,114		},115		NFTAccepted {116			sender: T::AccountId,117			recipient: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,118			collection_id: RmrkCollectionId,119			nft_id: RmrkNftId,120		},121		NFTRejected {122			sender: T::AccountId,123			collection_id: RmrkCollectionId,124			nft_id: RmrkNftId,125		},126		PropertySet {127			collection_id: RmrkCollectionId,128			maybe_nft_id: Option<RmrkNftId>,129			key: RmrkKeyString,130			value: RmrkValueString,131		},132		ResourceAdded {133			nft_id: RmrkNftId,134			resource_id: RmrkResourceId,135		},136		ResourceRemoval {137			nft_id: RmrkNftId,138			resource_id: RmrkResourceId,139		},140		ResourceAccepted {141			nft_id: RmrkNftId,142			resource_id: RmrkResourceId,143		},144		ResourceRemovalAccepted {145			nft_id: RmrkNftId,146			resource_id: RmrkResourceId,147		},148		PrioritySet {149			collection_id: RmrkCollectionId,150			nft_id: RmrkNftId,151		},152	}153154	#[pallet::error]155	pub enum Error<T> {156		/* Unique-specific events */157		CorruptedCollectionType,158		NftTypeEncodeError,159		RmrkPropertyKeyIsTooLong,160		RmrkPropertyValueIsTooLong,161162		/* RMRK compatible events */163		CollectionNotEmpty,164		NoAvailableCollectionId,165		NoAvailableNftId,166		CollectionUnknown,167		NoPermission,168		NonTransferable,169		CollectionFullOrLocked,170		ResourceDoesntExist,171		CannotSendToDescendentOrSelf,172		CannotAcceptNonOwnedNft,173		CannotRejectNonOwnedNft,174		ResourceNotPending,175	}176177	#[pallet::call]178	impl<T: Config> Pallet<T> {179		/// Create a collection180		#[transactional]181		#[pallet::weight(<SelfWeightOf<T>>::create_collection())]182		pub fn create_collection(183			origin: OriginFor<T>,184			metadata: RmrkString,185			max: Option<u32>,186			symbol: RmrkCollectionSymbol,187		) -> DispatchResult {188			let sender = ensure_signed(origin)?;189190			let limits = CollectionLimits {191				owner_can_transfer: Some(false),192				token_limit: max,193				..Default::default()194			};195196			let data = CreateCollectionData {197				limits: Some(limits),198				token_prefix: symbol199					.into_inner()200					.try_into()201					.map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,202				permissions: Some(CollectionPermissions {203					nesting: Some(NestingPermissions {204						token_owner: true,205						admin: false,206						restricted: None,207208						permissive: false,209					}),210					..Default::default()211				}),212				..Default::default()213			};214215			let unique_collection_id = Self::init_collection(216				T::CrossAccountId::from_sub(sender.clone()),217				data,218				[219					Self::rmrk_property(Metadata, &metadata)?,220					Self::rmrk_property(CollectionType, &misc::CollectionType::Regular)?,221				]222				.into_iter(),223			)?;224			let rmrk_collection_id = <CollectionIndex<T>>::get();225226			<UniqueCollectionId<T>>::insert(rmrk_collection_id, unique_collection_id);227			<RmrkInernalCollectionId<T>>::insert(unique_collection_id, rmrk_collection_id);228229			<CollectionIndex<T>>::mutate(|n| *n += 1);230231			Self::deposit_event(Event::CollectionCreated {232				issuer: sender,233				collection_id: rmrk_collection_id,234			});235236			Ok(())237		}238239		/// destroy collection240		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]241		#[transactional]242		pub fn destroy_collection(243			origin: OriginFor<T>,244			collection_id: RmrkCollectionId,245		) -> DispatchResult {246			let sender = ensure_signed(origin)?;247			let cross_sender = T::CrossAccountId::from_sub(sender.clone());248249			let collection = Self::get_typed_nft_collection(250				Self::unique_collection_id(collection_id)?,251				misc::CollectionType::Regular,252			)?;253			collection.check_is_external()?;254255			<PalletNft<T>>::destroy_collection(collection, &cross_sender)256				.map_err(Self::map_unique_err_to_proxy)?;257258			Self::deposit_event(Event::CollectionDestroyed {259				issuer: sender,260				collection_id,261			});262263			Ok(())264		}265266		/// Change the issuer of a collection267		///268		/// Parameters:269		/// - `origin`: sender of the transaction270		/// - `collection_id`: collection id of the nft to change issuer of271		/// - `new_issuer`: Collection's new issuer272		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]273		#[transactional]274		pub fn change_collection_issuer(275			origin: OriginFor<T>,276			collection_id: RmrkCollectionId,277			new_issuer: <T::Lookup as StaticLookup>::Source,278		) -> DispatchResult {279			let sender = ensure_signed(origin)?;280281			let collection = Self::get_nft_collection(Self::unique_collection_id(collection_id)?)?;282			collection.check_is_external()?;283284			let new_issuer = T::Lookup::lookup(new_issuer)?;285286			Self::change_collection_owner(287				Self::unique_collection_id(collection_id)?,288				misc::CollectionType::Regular,289				sender.clone(),290				new_issuer.clone(),291			)?;292293			Self::deposit_event(Event::IssuerChanged {294				old_issuer: sender,295				new_issuer,296				collection_id,297			});298299			Ok(())300		}301302		/// lock collection303		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]304		#[transactional]305		pub fn lock_collection(306			origin: OriginFor<T>,307			collection_id: RmrkCollectionId,308		) -> DispatchResult {309			let sender = ensure_signed(origin)?;310			let cross_sender = T::CrossAccountId::from_sub(sender.clone());311312			let collection = Self::get_typed_nft_collection(313				Self::unique_collection_id(collection_id)?,314				misc::CollectionType::Regular,315			)?;316			collection.check_is_external()?;317318			Self::check_collection_owner(&collection, &cross_sender)?;319320			let token_count = collection.total_supply();321322			let mut collection = collection.into_inner();323			collection.limits.token_limit = Some(token_count);324			collection.save()?;325326			Self::deposit_event(Event::CollectionLocked {327				issuer: sender,328				collection_id,329			});330331			Ok(())332		}333334		/// Mints an NFT in the specified collection335		/// Sets metadata and the royalty attribute336		///337		/// Parameters:338		/// - `collection_id`: The class of the asset to be minted.339		/// - `nft_id`: The nft value of the asset to be minted.340		/// - `recipient`: Receiver of the royalty341		/// - `royalty`: Permillage reward from each trade for the Recipient342		/// - `metadata`: Arbitrary data about an nft, e.g. IPFS hash343		/// - `transferable`: Ability to transfer this NFT344		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]345		#[transactional]346		pub fn mint_nft(347			origin: OriginFor<T>,348			owner: T::AccountId,349			collection_id: RmrkCollectionId,350			recipient: Option<T::AccountId>,351			royalty_amount: Option<Permill>,352			metadata: RmrkString,353			transferable: bool,354		) -> DispatchResult {355			let sender = ensure_signed(origin)?;356			let sender = T::CrossAccountId::from_sub(sender);357			let cross_owner = T::CrossAccountId::from_sub(owner.clone());358359			let collection = Self::get_typed_nft_collection(360				Self::unique_collection_id(collection_id)?,361				misc::CollectionType::Regular,362			)?;363			collection.check_is_external()?;364365			let royalty_info = royalty_amount.map(|amount| rmrk_traits::RoyaltyInfo {366				recipient: recipient.unwrap_or_else(|| owner.clone()),367				amount,368			});369370			let nft_id = Self::create_nft(371				&sender,372				&cross_owner,373				&collection,374				[375					Self::rmrk_property(TokenType, &NftType::Regular)?,376					Self::rmrk_property(Transferable, &transferable)?,377					Self::rmrk_property(PendingNftAccept, &false)?,378					Self::rmrk_property(RoyaltyInfo, &royalty_info)?,379					Self::rmrk_property(Metadata, &metadata)?,380					Self::rmrk_property(Equipped, &false)?,381					Self::rmrk_property(382						ResourceCollection,383						&Self::init_collection(384							sender.clone(),385							CreateCollectionData {386								..Default::default()387							},388							[Self::rmrk_property(389								CollectionType,390								&misc::CollectionType::Resource,391							)?]392							.into_iter(),393						)?,394					)?, // todo possibly add limits to the collection if rmrk warrants them395					Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,396				]397				.into_iter(),398			)399			.map_err(|err| match err {400				DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),401				err => Self::map_unique_err_to_proxy(err),402			})?;403404			Self::deposit_event(Event::NftMinted {405				owner,406				collection_id,407				nft_id: nft_id.0,408			});409410			Ok(())411		}412413		/// burn nft414		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]415		#[transactional]416		pub fn burn_nft(417			origin: OriginFor<T>,418			collection_id: RmrkCollectionId,419			nft_id: RmrkNftId,420		) -> DispatchResult {421			let sender = ensure_signed(origin)?;422			let cross_sender = T::CrossAccountId::from_sub(sender.clone());423424			let collection = Self::get_typed_nft_collection(425				Self::unique_collection_id(collection_id)?,426				misc::CollectionType::Regular,427			)?;428			collection.check_is_external()?;429430			Self::destroy_nft(431				cross_sender,432				Self::unique_collection_id(collection_id)?,433				nft_id.into(),434			)435			.map_err(Self::map_unique_err_to_proxy)?;436437			Self::deposit_event(Event::NFTBurned {438				owner: sender,439				nft_id,440			});441442			Ok(())443		}444445		/// Transfers a NFT from an Account or NFT A to another Account or NFT B446		///447		/// Parameters:448		/// - `origin`: sender of the transaction449		/// - `rmrk_collection_id`: collection id of the nft to be transferred450		/// - `rmrk_nft_id`: nft id of the nft to be transferred451		/// - `new_owner`: new owner of the nft which can be either an account or a NFT452		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]453		#[transactional]454		pub fn send(455			origin: OriginFor<T>,456			rmrk_collection_id: RmrkCollectionId,457			rmrk_nft_id: RmrkNftId,458			new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,459		) -> DispatchResult {460			let sender = ensure_signed(origin.clone())?;461			let cross_sender = T::CrossAccountId::from_sub(sender.clone());462463			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;464			let nft_id = rmrk_nft_id.into();465466			let collection =467				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;468			collection.check_is_external()?;469470			let token_data =471				<TokenData<T>>::get((collection_id, nft_id)).ok_or(<Error<T>>::NoAvailableNftId)?;472473			let from = token_data.owner;474475			ensure!(476				Self::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Transferable)?,477				<Error<T>>::NonTransferable478			);479480			ensure!(481				!Self::get_nft_property_decoded(482					collection_id,483					nft_id,484					RmrkProperty::PendingNftAccept485				)?,486				<Error<T>>::NoPermission487			);488489			let target_owner;490			let approval_required;491492			match new_owner {493				RmrkAccountIdOrCollectionNftTuple::AccountId(ref account_id) => {494					target_owner = T::CrossAccountId::from_sub(account_id.clone());495					approval_required = false;496				}497				RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(498					target_collection_id,499					target_nft_id,500				) => {501					let target_collection_id = Self::unique_collection_id(target_collection_id)?;502503					let target_nft_budget = budget::Value::new(NESTING_BUDGET);504505					let target_nft_owner = <PalletStructure<T>>::get_checked_topmost_owner(506						target_collection_id,507						target_nft_id.into(),508						Some((collection_id, nft_id)),509						&target_nft_budget,510					)511					.map_err(Self::map_unique_err_to_proxy)?;512513					approval_required = cross_sender != target_nft_owner;514515					if approval_required {516						target_owner = target_nft_owner;517518						<PalletNft<T>>::set_scoped_token_property(519							collection.id,520							nft_id,521							PropertyScope::Rmrk,522							Self::rmrk_property(PendingNftAccept, &approval_required)?,523						)?;524					} else {525						target_owner = T::CrossTokenAddressMapping::token_to_address(526							target_collection_id,527							target_nft_id.into(),528						);529					}530				}531			}532533			let src_nft_budget = budget::Value::new(NESTING_BUDGET);534535			<PalletNft<T>>::transfer_from(536				&collection,537				&cross_sender,538				&from,539				&target_owner,540				nft_id,541				&src_nft_budget,542			)543			.map_err(Self::map_unique_err_to_proxy)?;544545			Self::deposit_event(Event::NFTSent {546				sender,547				recipient: new_owner,548				collection_id: rmrk_collection_id,549				nft_id: rmrk_nft_id,550				approval_required,551			});552553			Ok(())554		}555556		/// Accepts an NFT sent from another account to self or owned NFT557		///558		/// Parameters:559		/// - `origin`: sender of the transaction560		/// - `rmrk_collection_id`: collection id of the nft to be accepted561		/// - `rmrk_nft_id`: nft id of the nft to be accepted562		/// - `new_owner`: either origin's account ID or origin-owned NFT, whichever the NFT was563		///   sent to564		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]565		#[transactional]566		pub fn accept_nft(567			origin: OriginFor<T>,568			rmrk_collection_id: RmrkCollectionId,569			rmrk_nft_id: RmrkNftId,570			new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,571		) -> DispatchResult {572			let sender = ensure_signed(origin.clone())?;573			let cross_sender = T::CrossAccountId::from_sub(sender.clone());574575			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;576			let nft_id = rmrk_nft_id.into();577578			let collection =579				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;580			collection.check_is_external()?;581582			let new_cross_owner = match new_owner {583				RmrkAccountIdOrCollectionNftTuple::AccountId(ref account_id) => {584					T::CrossAccountId::from_sub(account_id.clone())585				}586				RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(587					target_collection_id,588					target_nft_id,589				) => {590					let target_collection_id = Self::unique_collection_id(target_collection_id)?;591592					T::CrossTokenAddressMapping::token_to_address(593						target_collection_id,594						TokenId(target_nft_id),595					)596				}597			};598599			let budget = budget::Value::new(NESTING_BUDGET);600601			<PalletNft<T>>::transfer(602				&collection,603				&cross_sender,604				&new_cross_owner,605				nft_id,606				&budget,607			)608			.map_err(|err| {609				if err == <CommonError<T>>::UserIsNotAllowedToNest.into() {610					<Error<T>>::CannotAcceptNonOwnedNft.into()611				} else {612					Self::map_unique_err_to_proxy(err)613				}614			})?;615616			<PalletNft<T>>::set_scoped_token_property(617				collection.id,618				nft_id,619				PropertyScope::Rmrk,620				Self::rmrk_property(PendingNftAccept, &false)?,621			)?;622623			Self::deposit_event(Event::NFTAccepted {624				sender,625				recipient: new_owner,626				collection_id: rmrk_collection_id,627				nft_id: rmrk_nft_id,628			});629630			Ok(())631		}632633		/// Rejects an NFT sent from another account to self or owned NFT634		///635		/// Parameters:636		/// - `origin`: sender of the transaction637		/// - `rmrk_collection_id`: collection id of the nft to be accepted638		/// - `rmrk_nft_id`: nft id of the nft to be accepted639		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]640		#[transactional]641		pub fn reject_nft(642			origin: OriginFor<T>,643			rmrk_collection_id: RmrkCollectionId,644			rmrk_nft_id: RmrkNftId,645		) -> DispatchResult {646			let sender = ensure_signed(origin)?;647			let cross_sender = T::CrossAccountId::from_sub(sender.clone());648649			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;650			let nft_id = rmrk_nft_id.into();651652			let collection =653				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;654			collection.check_is_external()?;655656			Self::destroy_nft(cross_sender, collection_id, nft_id).map_err(|err| {657				if err == <CommonError<T>>::NoPermission.into()658					|| err == <CommonError<T>>::ApprovedValueTooLow.into()659				{660					<Error<T>>::CannotRejectNonOwnedNft.into()661				} else {662					Self::map_unique_err_to_proxy(err)663				}664			})?;665666			Self::deposit_event(Event::NFTRejected {667				sender,668				collection_id: rmrk_collection_id,669				nft_id: rmrk_nft_id,670			});671672			Ok(())673		}674675		/// accept the addition of a new resource to an existing NFT676		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]677		#[transactional]678		pub fn accept_resource(679			origin: OriginFor<T>,680			rmrk_collection_id: RmrkCollectionId,681			rmrk_nft_id: RmrkNftId,682			rmrk_resource_id: RmrkResourceId,683		) -> DispatchResult {684			let sender = ensure_signed(origin)?;685			let cross_sender = T::CrossAccountId::from_sub(sender);686687			let collection_id = Self::unique_collection_id(rmrk_collection_id)688				.map_err(|_| <Error<T>>::ResourceDoesntExist)?;689			let collection =690				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;691			collection.check_is_external()?;692693			let nft_id = rmrk_nft_id.into();694			let resource_id = rmrk_resource_id.into();695696			let budget = budget::Value::new(NESTING_BUDGET);697698			let nft_owner =699				<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)700					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;701702			let resource_collection_id: CollectionId =703				Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)704					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;705706			let is_pending: bool = Self::get_nft_property_decoded(707				resource_collection_id,708				resource_id,709				PendingResourceAccept,710			)711			.map_err(|_| <Error<T>>::ResourceDoesntExist)?;712713			ensure!(is_pending, <Error<T>>::ResourceNotPending);714715			ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);716717			<PalletNft<T>>::set_scoped_token_property(718				resource_collection_id,719				rmrk_resource_id.into(),720				PropertyScope::Rmrk,721				Self::rmrk_property(PendingResourceAccept, &false)?,722			)?;723724			Self::deposit_event(Event::<T>::ResourceAccepted {725				nft_id: rmrk_nft_id,726				resource_id: rmrk_resource_id,727			});728729			Ok(())730		}731732		/// accept the removal of a resource of an existing NFT733		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]734		#[transactional]735		pub fn accept_resource_removal(736			origin: OriginFor<T>,737			rmrk_collection_id: RmrkCollectionId,738			rmrk_nft_id: RmrkNftId,739			rmrk_resource_id: RmrkResourceId,740		) -> DispatchResult {741			let sender = ensure_signed(origin)?;742			let cross_sender = T::CrossAccountId::from_sub(sender);743744			let collection_id = Self::unique_collection_id(rmrk_collection_id)745				.map_err(|_| <Error<T>>::ResourceDoesntExist)?;746			let collection =747				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;748			collection.check_is_external()?;749750			let nft_id = rmrk_nft_id.into();751			let resource_id = rmrk_resource_id.into();752753			let budget = budget::Value::new(NESTING_BUDGET);754755			let nft_owner =756				<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)757					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;758759			ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);760761			let resource_collection_id: CollectionId =762				Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)763					.map_err(|_| <Error<T>>::ResourceDoesntExist)?;764765			let is_pending: bool = Self::get_nft_property_decoded(766				resource_collection_id,767				resource_id,768				PendingResourceRemoval,769			)770			.map_err(|_| <Error<T>>::ResourceDoesntExist)?;771772			ensure!(is_pending, <Error<T>>::ResourceNotPending);773774			let resource_collection = Self::get_typed_nft_collection(775				resource_collection_id,776				misc::CollectionType::Resource,777			)?;778779			<PalletNft<T>>::burn(&resource_collection, &cross_sender, rmrk_resource_id.into())780				.map_err(Self::map_unique_err_to_proxy)?;781782			Self::deposit_event(Event::<T>::ResourceRemovalAccepted {783				nft_id: rmrk_nft_id,784				resource_id: rmrk_resource_id,785			});786787			Ok(())788		}789790		/// set a custom value on an NFT791		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]792		#[transactional]793		pub fn set_property(794			origin: OriginFor<T>,795			#[pallet::compact] rmrk_collection_id: RmrkCollectionId,796			maybe_nft_id: Option<RmrkNftId>,797			key: RmrkKeyString,798			value: RmrkValueString,799		) -> DispatchResult {800			let sender = ensure_signed(origin)?;801			let sender = T::CrossAccountId::from_sub(sender);802803			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;804			let collection =805				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;806			collection.check_is_external()?;807808			let budget = budget::Value::new(NESTING_BUDGET);809810			match maybe_nft_id {811				Some(nft_id) => {812					let token_id: TokenId = nft_id.into();813814					Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;815					Self::ensure_nft_owner(collection_id, token_id, &sender, &budget)?;816817					<PalletNft<T>>::set_scoped_token_property(818						collection_id,819						token_id,820						PropertyScope::Rmrk,821						Self::rmrk_property(UserProperty(key.as_slice()), &value)?,822					)?;823				}824				None => {825					let collection = Self::get_typed_nft_collection(826						collection_id,827						misc::CollectionType::Regular,828					)?;829830					Self::check_collection_owner(&collection, &sender)?;831832					<PalletCommon<T>>::set_scoped_collection_property(833						collection_id,834						PropertyScope::Rmrk,835						Self::rmrk_property(UserProperty(key.as_slice()), &value)?,836					)?;837				}838			}839840			Self::deposit_event(Event::PropertySet {841				collection_id: rmrk_collection_id,842				maybe_nft_id,843				key,844				value,845			});846847			Ok(())848		}849850		/// set a different order of resource priority851		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]852		#[transactional]853		pub fn set_priority(854			origin: OriginFor<T>,855			rmrk_collection_id: RmrkCollectionId,856			rmrk_nft_id: RmrkNftId,857			priorities: BoundedVec<RmrkResourceId, RmrkMaxPriorities>,858		) -> DispatchResult {859			let sender = ensure_signed(origin)?;860			let sender = T::CrossAccountId::from_sub(sender);861862			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;863			let nft_id = rmrk_nft_id.into();864865			let collection =866				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;867			collection.check_is_external()?;868869			let budget = budget::Value::new(NESTING_BUDGET);870871			Self::ensure_nft_type(collection_id, nft_id, NftType::Regular)?;872			Self::ensure_nft_owner(collection_id, nft_id, &sender, &budget)?;873874			<PalletNft<T>>::set_scoped_token_property(875				collection_id,876				nft_id,877				PropertyScope::Rmrk,878				Self::rmrk_property(ResourcePriorities, &priorities.into_inner())?,879			)?;880881			Self::deposit_event(Event::<T>::PrioritySet {882				collection_id: rmrk_collection_id,883				nft_id: rmrk_nft_id,884			});885886			Ok(())887		}888889		/// Create basic resource890		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]891		#[transactional]892		pub fn add_basic_resource(893			origin: OriginFor<T>,894			rmrk_collection_id: RmrkCollectionId,895			nft_id: RmrkNftId,896			resource: RmrkBasicResource,897		) -> DispatchResult {898			let sender = ensure_signed(origin.clone())?;899900			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;901			let collection =902				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;903			collection.check_is_external()?;904905			let resource_id = Self::resource_add(906				sender,907				collection_id,908				nft_id.into(),909				[910					Self::rmrk_property(TokenType, &NftType::Resource)?,911					Self::rmrk_property(ResourceType, &misc::ResourceType::Basic)?,912					Self::rmrk_property(Src, &resource.src)?,913					Self::rmrk_property(Metadata, &resource.metadata)?,914					Self::rmrk_property(License, &resource.license)?,915					Self::rmrk_property(Thumb, &resource.thumb)?,916				]917				.into_iter(),918			)?;919920			Self::deposit_event(Event::ResourceAdded {921				nft_id,922				resource_id,923			});924			Ok(())925		}926927		/// Create composable resource928		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]929		#[transactional]930		pub fn add_composable_resource(931			origin: OriginFor<T>,932			rmrk_collection_id: RmrkCollectionId,933			nft_id: RmrkNftId,934			_resource_id: RmrkBoundedResource,935			resource: RmrkComposableResource,936		) -> DispatchResult {937			let sender = ensure_signed(origin.clone())?;938939			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;940			let collection =941				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;942			collection.check_is_external()?;943944			let resource_id = Self::resource_add(945				sender,946				collection_id,947				nft_id.into(),948				[949					Self::rmrk_property(TokenType, &NftType::Resource)?,950					Self::rmrk_property(ResourceType, &misc::ResourceType::Composable)?,951					Self::rmrk_property(Parts, &resource.parts)?,952					Self::rmrk_property(Base, &resource.base)?,953					Self::rmrk_property(Src, &resource.src)?,954					Self::rmrk_property(Metadata, &resource.metadata)?,955					Self::rmrk_property(License, &resource.license)?,956					Self::rmrk_property(Thumb, &resource.thumb)?,957				]958				.into_iter(),959			)?;960961			Self::deposit_event(Event::ResourceAdded {962				nft_id,963				resource_id,964			});965			Ok(())966		}967968		/// Create slot resource969		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]970		#[transactional]971		pub fn add_slot_resource(972			origin: OriginFor<T>,973			rmrk_collection_id: RmrkCollectionId,974			nft_id: RmrkNftId,975			resource: RmrkSlotResource,976		) -> DispatchResult {977			let sender = ensure_signed(origin.clone())?;978979			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;980			let collection =981				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;982			collection.check_is_external()?;983984			let resource_id = Self::resource_add(985				sender,986				collection_id,987				nft_id.into(),988				[989					Self::rmrk_property(TokenType, &NftType::Resource)?,990					Self::rmrk_property(ResourceType, &misc::ResourceType::Slot)?,991					Self::rmrk_property(Base, &resource.base)?,992					Self::rmrk_property(Src, &resource.src)?,993					Self::rmrk_property(Metadata, &resource.metadata)?,994					Self::rmrk_property(Slot, &resource.slot)?,995					Self::rmrk_property(License, &resource.license)?,996					Self::rmrk_property(Thumb, &resource.thumb)?,997				]998				.into_iter(),999			)?;10001001			Self::deposit_event(Event::ResourceAdded {1002				nft_id,1003				resource_id,1004			});1005			Ok(())1006		}10071008		/// remove resource1009		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]1010		#[transactional]1011		pub fn remove_resource(1012			origin: OriginFor<T>,1013			rmrk_collection_id: RmrkCollectionId,1014			nft_id: RmrkNftId,1015			resource_id: RmrkResourceId,1016		) -> DispatchResult {1017			let sender = ensure_signed(origin.clone())?;10181019			let collection_id = Self::unique_collection_id(rmrk_collection_id)?;1020			let collection =1021				Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1022			collection.check_is_external()?;10231024			Self::resource_remove(sender, collection_id, nft_id.into(), resource_id.into())?;10251026			Self::deposit_event(Event::ResourceRemoval {1027				nft_id,1028				resource_id,1029			});1030			Ok(())1031		}1032	}1033}10341035impl<T: Config> Pallet<T> {1036	pub fn rmrk_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {1037		let key = rmrk_key.to_key::<T>()?;10381039		let scoped_key = PropertyScope::Rmrk1040			.apply(key)1041			.map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;10421043		Ok(scoped_key)1044	}10451046	// todo think about renaming these1047	pub fn rmrk_property<E: Encode>(1048		rmrk_key: RmrkProperty,1049		value: &E,1050	) -> Result<Property, DispatchError> {1051		let key = rmrk_key.to_key::<T>()?;10521053		let value = value1054			.encode()1055			.try_into()1056			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;10571058		let property = Property { key, value };10591060		Ok(property)1061	}10621063	pub fn decode_property<D: Decode>(vec: PropertyValue) -> Result<D, DispatchError> {1064		vec.decode()1065			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())1066	}10671068	pub fn rebind<L, S>(vec: &BoundedVec<u8, L>) -> Result<BoundedVec<u8, S>, DispatchError>1069	where1070		BoundedVec<u8, S>: TryFrom<Vec<u8>>,1071	{1072		vec.rebind()1073			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())1074	}10751076	fn init_collection(1077		sender: T::CrossAccountId,1078		data: CreateCollectionData<T::AccountId>,1079		properties: impl Iterator<Item = Property>,1080	) -> Result<CollectionId, DispatchError> {1081		let collection_id = <PalletNft<T>>::init_collection(sender, data, true);10821083		if let Err(DispatchError::Arithmetic(_)) = &collection_id {1084			return Err(<Error<T>>::NoAvailableCollectionId.into());1085		}10861087		<PalletCommon<T>>::set_scoped_collection_properties(1088			collection_id?,1089			PropertyScope::Rmrk,1090			properties,1091		)?;10921093		collection_id1094	}10951096	pub fn create_nft(1097		sender: &T::CrossAccountId,1098		owner: &T::CrossAccountId,1099		collection: &NonfungibleHandle<T>,1100		properties: impl Iterator<Item = Property>,1101	) -> Result<TokenId, DispatchError> {1102		let data = CreateNftExData {1103			properties: BoundedVec::default(),1104			owner: owner.clone(),1105		};11061107		let budget = budget::Value::new(NESTING_BUDGET);11081109		<PalletNft<T>>::create_item(collection, sender, data, &budget)?;11101111		let nft_id = <PalletNft<T>>::current_token_id(collection.id);11121113		<PalletNft<T>>::set_scoped_token_properties(1114			collection.id,1115			nft_id,1116			PropertyScope::Rmrk,1117			properties,1118		)?;11191120		Ok(nft_id)1121	}11221123	fn destroy_nft(1124		sender: T::CrossAccountId,1125		collection_id: CollectionId,1126		token_id: TokenId,1127	) -> DispatchResult {1128		let collection =1129			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;11301131		let token_data =1132			<TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;11331134		let from = token_data.owner;11351136		let budget = budget::Value::new(NESTING_BUDGET);11371138		<PalletNft<T>>::burn_from(&collection, &sender, &from, token_id, &budget)1139	}11401141	fn resource_add(1142		sender: T::AccountId,1143		collection_id: CollectionId,1144		token_id: TokenId,1145		resource_properties: impl Iterator<Item = Property>,1146	) -> Result<RmrkResourceId, DispatchError> {1147		let collection =1148			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1149		ensure!(collection.owner == sender, Error::<T>::NoPermission);11501151		let sender = T::CrossAccountId::from_sub(sender);1152		let budget = budget::Value::new(NESTING_BUDGET);11531154		let nft_owner = <PalletStructure<T>>::find_topmost_owner(collection_id, token_id, &budget)1155			.map_err(Self::map_unique_err_to_proxy)?;11561157		let pending = sender != nft_owner;11581159		let resource_collection_id: CollectionId =1160			Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;1161		let resource_collection =1162			Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;11631164		// todo probably add extra connections to bases, slots, etc., when RMRK starts to use them11651166		let resource_id = Self::create_nft(1167			&sender,1168			&nft_owner,1169			&resource_collection,1170			resource_properties.chain(1171				[1172					Self::rmrk_property(PendingResourceAccept, &pending)?,1173					Self::rmrk_property(PendingResourceRemoval, &false)?,1174				]1175				.into_iter(),1176			),1177		)1178		.map_err(|err| match err {1179			DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),1180			err => Self::map_unique_err_to_proxy(err),1181		})?;11821183		Ok(resource_id.0)1184	}11851186	fn resource_remove(1187		sender: T::AccountId,1188		collection_id: CollectionId,1189		nft_id: TokenId,1190		resource_id: TokenId,1191	) -> DispatchResult {1192		let collection =1193			Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;1194		ensure!(collection.owner == sender, Error::<T>::NoPermission);11951196		let resource_collection_id: CollectionId =1197			Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection)?;1198		let resource_collection =1199			Self::get_typed_nft_collection(resource_collection_id, misc::CollectionType::Resource)?;1200		ensure!(1201			<PalletNft<T>>::token_exists(&resource_collection, resource_id),1202			Error::<T>::ResourceDoesntExist1203		);12041205		let budget = up_data_structs::budget::Value::new(10);1206		let topmost_owner =1207			<PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)?;12081209		let sender = T::CrossAccountId::from_sub(sender);1210		if topmost_owner == sender {1211			<PalletNft<T>>::burn(&resource_collection, &sender, resource_id)1212				.map_err(Self::map_unique_err_to_proxy)?;1213		} else {1214			<PalletNft<T>>::set_scoped_token_property(1215				resource_collection_id,1216				resource_id,1217				PropertyScope::Rmrk,1218				Self::rmrk_property(PendingResourceRemoval, &true)?,1219			)?;1220		}12211222		Ok(())1223	}12241225	fn change_collection_owner(1226		collection_id: CollectionId,1227		collection_type: misc::CollectionType,1228		sender: T::AccountId,1229		new_owner: T::AccountId,1230	) -> DispatchResult {1231		let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;1232		Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;12331234		let mut collection = collection.into_inner();12351236		collection.owner = new_owner;1237		collection.save()1238	}12391240	fn check_collection_owner(1241		collection: &NonfungibleHandle<T>,1242		account: &T::CrossAccountId,1243	) -> DispatchResult {1244		collection1245			.check_is_owner(account)1246			.map_err(Self::map_unique_err_to_proxy)1247	}12481249	pub fn last_collection_idx() -> RmrkCollectionId {1250		<CollectionIndex<T>>::get()1251	}12521253	pub fn unique_collection_id(1254		rmrk_collection_id: RmrkCollectionId,1255	) -> Result<CollectionId, DispatchError> {1256		<UniqueCollectionId<T>>::try_get(rmrk_collection_id)1257			.map_err(|_| <Error<T>>::CollectionUnknown.into())1258	}12591260	pub fn rmrk_collection_id(1261		unique_collection_id: CollectionId,1262	) -> Result<RmrkCollectionId, DispatchError> {1263		<RmrkInernalCollectionId<T>>::try_get(unique_collection_id)1264			.map_err(|_| <Error<T>>::CollectionUnknown.into())1265	}12661267	pub fn get_nft_collection(1268		collection_id: CollectionId,1269	) -> Result<NonfungibleHandle<T>, DispatchError> {1270		let collection = <CollectionHandle<T>>::try_get(collection_id)1271			.map_err(|_| <Error<T>>::CollectionUnknown)?;12721273		match collection.mode {1274			CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),1275			_ => Err(<Error<T>>::CollectionUnknown.into()),1276		}1277	}12781279	pub fn collection_exists(collection_id: CollectionId) -> bool {1280		<CollectionHandle<T>>::try_get(collection_id).is_ok()1281	}12821283	pub fn get_collection_property(1284		collection_id: CollectionId,1285		key: RmrkProperty,1286	) -> Result<PropertyValue, DispatchError> {1287		let collection_property = <PalletCommon<T>>::collection_properties(collection_id)1288			.get(&Self::rmrk_property_key(key)?)1289			.ok_or(<Error<T>>::CollectionUnknown)?1290			.clone();12911292		Ok(collection_property)1293	}12941295	pub fn get_collection_property_decoded<V: Decode>(1296		collection_id: CollectionId,1297		key: RmrkProperty,1298	) -> Result<V, DispatchError> {1299		Self::decode_property(Self::get_collection_property(collection_id, key)?)1300	}13011302	pub fn get_collection_type(1303		collection_id: CollectionId,1304	) -> Result<misc::CollectionType, DispatchError> {1305		Self::get_collection_property_decoded(collection_id, CollectionType)1306			.map_err(|_| <Error<T>>::CorruptedCollectionType.into())1307	}13081309	pub fn ensure_collection_type(1310		collection_id: CollectionId,1311		collection_type: misc::CollectionType,1312	) -> DispatchResult {1313		let actual_type = Self::get_collection_type(collection_id)?;1314		ensure!(1315			actual_type == collection_type,1316			<CommonError<T>>::NoPermission1317		);13181319		Ok(())1320	}13211322	pub fn get_typed_nft_collection(1323		collection_id: CollectionId,1324		collection_type: misc::CollectionType,1325	) -> Result<NonfungibleHandle<T>, DispatchError> {1326		Self::ensure_collection_type(collection_id, collection_type)?;13271328		Self::get_nft_collection(collection_id)1329	}13301331	pub fn get_typed_nft_collection_mapped(1332		rmrk_collection_id: RmrkCollectionId,1333		collection_type: misc::CollectionType,1334	) -> Result<(NonfungibleHandle<T>, CollectionId), DispatchError> {1335		let unique_collection_id = match collection_type {1336			misc::CollectionType::Regular => Self::unique_collection_id(rmrk_collection_id)?,1337			_ => rmrk_collection_id.into(),1338		};13391340		let collection = Self::get_typed_nft_collection(unique_collection_id, collection_type)?;13411342		Ok((collection, unique_collection_id))1343	}13441345	pub fn get_nft_property(1346		collection_id: CollectionId,1347		nft_id: TokenId,1348		key: RmrkProperty,1349	) -> Result<PropertyValue, DispatchError> {1350		let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))1351			.get(&Self::rmrk_property_key(key)?)1352			.ok_or(<Error<T>>::NoAvailableNftId)? // todo replace with better error?1353			.clone();13541355		Ok(nft_property)1356	}13571358	pub fn get_nft_property_decoded<V: Decode>(1359		collection_id: CollectionId,1360		nft_id: TokenId,1361		key: RmrkProperty,1362	) -> Result<V, DispatchError> {1363		Self::decode_property(Self::get_nft_property(collection_id, nft_id, key)?)1364	}13651366	pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {1367		<TokenData<T>>::contains_key((collection_id, nft_id))1368	}13691370	pub fn get_nft_type(1371		collection_id: CollectionId,1372		token_id: TokenId,1373	) -> Result<NftType, DispatchError> {1374		Self::get_nft_property_decoded(collection_id, token_id, TokenType)1375			.map_err(|_| <Error<T>>::NoAvailableNftId.into())1376	}13771378	pub fn ensure_nft_type(1379		collection_id: CollectionId,1380		token_id: TokenId,1381		nft_type: NftType,1382	) -> DispatchResult {1383		let actual_type = Self::get_nft_type(collection_id, token_id)?;1384		ensure!(actual_type == nft_type, <Error<T>>::NoPermission);13851386		Ok(())1387	}13881389	pub fn ensure_nft_owner(1390		collection_id: CollectionId,1391		token_id: TokenId,1392		possible_owner: &T::CrossAccountId,1393		nesting_budget: &dyn budget::Budget,1394	) -> DispatchResult {1395		let is_owned = <PalletStructure<T>>::check_indirectly_owned(1396			possible_owner.clone(),1397			collection_id,1398			token_id,1399			None,1400			nesting_budget,1401		)1402		.map_err(Self::map_unique_err_to_proxy)?;14031404		ensure!(is_owned, <Error<T>>::NoPermission);14051406		Ok(())1407	}14081409	pub fn filter_user_properties<Key, Value, R, Mapper>(1410		collection_id: CollectionId,1411		token_id: Option<TokenId>,1412		filter_keys: Option<Vec<RmrkPropertyKey>>,1413		mapper: Mapper,1414	) -> Result<Vec<R>, DispatchError>1415	where1416		Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,1417		Value: Decode + Default,1418		Mapper: Fn(Key, Value) -> R,1419	{1420		filter_keys1421			.map(|keys| {1422				let properties = keys1423					.into_iter()1424					.filter_map(|key| {1425						let key: Key = key.try_into().ok()?;14261427						let value = match token_id {1428							Some(token_id) => Self::get_nft_property_decoded(1429								collection_id,1430								token_id,1431								UserProperty(key.as_ref()),1432							),1433							None => Self::get_collection_property_decoded(1434								collection_id,1435								UserProperty(key.as_ref()),1436							),1437						}1438						.ok()?;14391440						Some(mapper(key, value))1441					})1442					.collect();14431444				Ok(properties)1445			})1446			.unwrap_or_else(|| {1447				let properties =1448					Self::iterate_user_properties(collection_id, token_id, mapper)?.collect();14491450				Ok(properties)1451			})1452	}14531454	pub fn iterate_user_properties<Key, Value, R, Mapper>(1455		collection_id: CollectionId,1456		token_id: Option<TokenId>,1457		mapper: Mapper,1458	) -> Result<impl Iterator<Item = R>, DispatchError>1459	where1460		Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,1461		Value: Decode + Default,1462		Mapper: Fn(Key, Value) -> R,1463	{1464		let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;14651466		let properties = match token_id {1467			Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),1468			None => <PalletCommon<T>>::collection_properties(collection_id),1469		};14701471		let properties = properties.into_iter().filter_map(move |(key, value)| {1472			let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;14731474			let key: Key = key.to_vec().try_into().ok()?;1475			let value: Value = value.decode().ok()?;14761477			Some(mapper(key, value))1478		});14791480		Ok(properties)1481	}14821483	fn map_unique_err_to_proxy(err: DispatchError) -> DispatchError {1484		map_unique_err_to_proxy! {1485			match err {1486				CommonError::NoPermission => NoPermission,1487				CommonError::CollectionTokenLimitExceeded => CollectionFullOrLocked,1488				CommonError::PublicMintingNotAllowed => NoPermission,1489				CommonError::TokenNotFound => NoAvailableNftId,1490				CommonError::ApprovedValueTooLow => NoPermission,1491				CommonError::CantDestroyNotEmptyCollection => CollectionNotEmpty,1492				StructureError::TokenNotFound => NoAvailableNftId,1493				StructureError::OuroborosDetected => CannotSendToDescendentOrSelf,1494			}1495		}1496	}1497}
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -441,7 +441,7 @@
 pub struct CollectionPermissions {
 	pub access: Option<AccessMode>,
 	pub mint_mode: Option<bool>,
-	pub nesting: Option<NestingRule>,
+	pub nesting: Option<NestingPermissions>,
 }
 
 impl CollectionPermissions {
@@ -451,30 +451,58 @@
 	pub fn mint_mode(&self) -> bool {
 		self.mint_mode.unwrap_or(false)
 	}
-	pub fn nesting(&self) -> &NestingRule {
-		static DEFAULT: NestingRule = NestingRule::Disabled;
+	pub fn nesting(&self) -> &NestingPermissions {
+		static DEFAULT: NestingPermissions = NestingPermissions {
+			token_owner: false,
+			admin: false,
+			restricted: None,
+
+			permissive: false,
+		};
 		self.nesting.as_ref().unwrap_or(&DEFAULT)
 	}
 }
 
-pub type OwnerRestrictedSet = BoundedBTreeSet<CollectionId, ConstU32<16>>;
+type OwnerRestrictedSetInner = BoundedBTreeSet<CollectionId, ConstU32<16>>;
+
+#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]
+#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
+#[derivative(Debug)]
+pub struct OwnerRestrictedSet(
+	#[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]
+	#[derivative(Debug(format_with = "bounded::set_debug"))]
+	pub OwnerRestrictedSetInner,
+);
+impl OwnerRestrictedSet {
+	pub fn new() -> Self {
+		Self(Default::default())
+	}
+}
+impl core::ops::Deref for OwnerRestrictedSet {
+	type Target = OwnerRestrictedSetInner;
+	fn deref(&self) -> &Self::Target {
+		&self.0
+	}
+}
+impl core::ops::DerefMut for OwnerRestrictedSet {
+	fn deref_mut(&mut self) -> &mut Self::Target {
+		&mut self.0
+	}
+}
 
 #[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]
 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
 #[derivative(Debug)]
-pub enum NestingRule {
-	/// No one can nest tokens
-	Disabled,
-	/// Owner can nest any tokens
-	Owner,
-	/// Owner can nest tokens from specified collections
-	OwnerRestricted(
-		#[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]
-		#[derivative(Debug(format_with = "bounded::set_debug"))]
-		OwnerRestrictedSet,
-	),
-	/// Used for tests
-	Permissive,
+pub struct NestingPermissions {
+	/// Owner of token can nest tokens under it
+	pub token_owner: bool,
+	/// Admin of token collection can nest tokens under token
+	pub admin: bool,
+	/// If set - only tokens from specified collections can be nested
+	pub restricted: Option<OwnerRestrictedSet>,
+
+	/// Anyone can nest tokens, mutually exclusive with `token_owner`, `admin`
+	pub permissive: bool,
 }
 
 #[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]
modifiedtests/package.jsondiffbeforeafterboth
--- a/tests/package.json
+++ b/tests/package.json
@@ -5,7 +5,7 @@
   "main": "",
   "devDependencies": {
     "@polkadot/ts": "0.4.22",
-    "@polkadot/typegen": "8.7.2-11",
+    "@polkadot/typegen": "8.7.2-15",
     "@types/chai": "^4.3.1",
     "@types/chai-as-promised": "^7.1.5",
     "@types/mocha": "^9.1.1",
@@ -86,8 +86,8 @@
   "license": "SEE LICENSE IN ../LICENSE",
   "homepage": "",
   "dependencies": {
-    "@polkadot/api": "8.7.2-11",
-    "@polkadot/api-contract": "8.7.2-11",
+    "@polkadot/api": "8.7.2-15",
+    "@polkadot/api-contract": "8.7.2-15",
     "@polkadot/util-crypto": "9.4.1",
     "bignumber.js": "^9.0.2",
     "chai-as-promised": "^7.1.1",
modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-errors.ts
+++ b/tests/src/interfaces/augment-api-errors.ts
@@ -125,10 +125,6 @@
        **/
       MustBeTokenOwner: AugmentedError<ApiType>;
       /**
-       * Collection has nesting disabled
-       **/
-      NestingIsDisabled: AugmentedError<ApiType>;
-      /**
        * No permission to perform action
        **/
       NoPermission: AugmentedError<ApiType>;
@@ -137,13 +133,9 @@
        **/
       NoSpaceForProperty: AugmentedError<ApiType>;
       /**
-       * Not sufficient founds to perform action
+       * Not sufficient funds to perform action
        **/
       NotSufficientFounds: AugmentedError<ApiType>;
-      /**
-       * Only owner may nest tokens under this collection
-       **/
-      OnlyOwnerAllowedToNest: AugmentedError<ApiType>;
       /**
        * Tried to enable permissions which are only permitted to be disabled
        **/
@@ -185,6 +177,10 @@
        **/
       UnsupportedOperation: AugmentedError<ApiType>;
       /**
+       * User not passed nesting rule
+       **/
+      UserIsNotAllowedToNest: AugmentedError<ApiType>;
+      /**
        * Generic error
        **/
       [key: string]: AugmentedError<ApiType>;
@@ -502,6 +498,10 @@
     };
     structure: {
       /**
+       * While iterating over children, encountered breadth limit
+       **/
+      BreadthLimit: AugmentedError<ApiType>;
+      /**
        * While searched for owner, encountered depth limit
        **/
       DepthLimit: AugmentedError<ApiType>;
modifiedtests/src/interfaces/augment-api-events.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-events.ts
+++ b/tests/src/interfaces/augment-api-events.ts
@@ -13,45 +13,45 @@
       /**
        * A balance was set by root.
        **/
-      BalanceSet: AugmentedEvent<ApiType, [AccountId32, u128, u128]>;
+      BalanceSet: AugmentedEvent<ApiType, [who: AccountId32, free: u128, reserved: u128], { who: AccountId32, free: u128, reserved: u128 }>;
       /**
        * Some amount was deposited (e.g. for transaction fees).
        **/
-      Deposit: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      Deposit: AugmentedEvent<ApiType, [who: AccountId32, amount: u128], { who: AccountId32, amount: u128 }>;
       /**
        * An account was removed whose balance was non-zero but below ExistentialDeposit,
        * resulting in an outright loss.
        **/
-      DustLost: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      DustLost: AugmentedEvent<ApiType, [account: AccountId32, amount: u128], { account: AccountId32, amount: u128 }>;
       /**
        * An account was created with some free balance.
        **/
-      Endowed: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      Endowed: AugmentedEvent<ApiType, [account: AccountId32, freeBalance: u128], { account: AccountId32, freeBalance: u128 }>;
       /**
        * Some balance was reserved (moved from free to reserved).
        **/
-      Reserved: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      Reserved: AugmentedEvent<ApiType, [who: AccountId32, amount: u128], { who: AccountId32, amount: u128 }>;
       /**
        * Some balance was moved from the reserve of the first account to the second account.
        * Final argument indicates the destination balance type.
        **/
-      ReserveRepatriated: AugmentedEvent<ApiType, [AccountId32, AccountId32, u128, FrameSupportTokensMiscBalanceStatus]>;
+      ReserveRepatriated: AugmentedEvent<ApiType, [from: AccountId32, to: AccountId32, amount: u128, destinationStatus: FrameSupportTokensMiscBalanceStatus], { from: AccountId32, to: AccountId32, amount: u128, destinationStatus: FrameSupportTokensMiscBalanceStatus }>;
       /**
        * Some amount was removed from the account (e.g. for misbehavior).
        **/
-      Slashed: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      Slashed: AugmentedEvent<ApiType, [who: AccountId32, amount: u128], { who: AccountId32, amount: u128 }>;
       /**
        * Transfer succeeded.
        **/
-      Transfer: AugmentedEvent<ApiType, [AccountId32, AccountId32, u128]>;
+      Transfer: AugmentedEvent<ApiType, [from: AccountId32, to: AccountId32, amount: u128], { from: AccountId32, to: AccountId32, amount: u128 }>;
       /**
        * Some balance was unreserved (moved from reserved to free).
        **/
-      Unreserved: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      Unreserved: AugmentedEvent<ApiType, [who: AccountId32, amount: u128], { who: AccountId32, amount: u128 }>;
       /**
        * Some amount was withdrawn from the account (e.g. for transaction fees).
        **/
-      Withdraw: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      Withdraw: AugmentedEvent<ApiType, [who: AccountId32, amount: u128], { who: AccountId32, amount: u128 }>;
       /**
        * Generic event
        **/
@@ -398,28 +398,28 @@
       [key: string]: AugmentedEvent<ApiType>;
     };
     rmrkCore: {
-      CollectionCreated: AugmentedEvent<ApiType, [AccountId32, u32]>;
-      CollectionDestroyed: AugmentedEvent<ApiType, [AccountId32, u32]>;
-      CollectionLocked: AugmentedEvent<ApiType, [AccountId32, u32]>;
-      IssuerChanged: AugmentedEvent<ApiType, [AccountId32, AccountId32, u32]>;
-      NFTAccepted: AugmentedEvent<ApiType, [AccountId32, RmrkTraitsNftAccountIdOrCollectionNftTuple, u32, u32]>;
-      NFTBurned: AugmentedEvent<ApiType, [AccountId32, u32]>;
-      NftMinted: AugmentedEvent<ApiType, [AccountId32, u32, u32]>;
-      NFTRejected: AugmentedEvent<ApiType, [AccountId32, u32, u32]>;
-      NFTSent: AugmentedEvent<ApiType, [AccountId32, RmrkTraitsNftAccountIdOrCollectionNftTuple, u32, u32, bool]>;
-      PrioritySet: AugmentedEvent<ApiType, [u32, u32]>;
-      PropertySet: AugmentedEvent<ApiType, [u32, Option<u32>, Bytes, Bytes]>;
-      ResourceAccepted: AugmentedEvent<ApiType, [u32, u32]>;
-      ResourceAdded: AugmentedEvent<ApiType, [u32, u32]>;
-      ResourceRemoval: AugmentedEvent<ApiType, [u32, u32]>;
-      ResourceRemovalAccepted: AugmentedEvent<ApiType, [u32, u32]>;
+      CollectionCreated: AugmentedEvent<ApiType, [issuer: AccountId32, collectionId: u32], { issuer: AccountId32, collectionId: u32 }>;
+      CollectionDestroyed: AugmentedEvent<ApiType, [issuer: AccountId32, collectionId: u32], { issuer: AccountId32, collectionId: u32 }>;
+      CollectionLocked: AugmentedEvent<ApiType, [issuer: AccountId32, collectionId: u32], { issuer: AccountId32, collectionId: u32 }>;
+      IssuerChanged: AugmentedEvent<ApiType, [oldIssuer: AccountId32, newIssuer: AccountId32, collectionId: u32], { oldIssuer: AccountId32, newIssuer: AccountId32, collectionId: u32 }>;
+      NFTAccepted: AugmentedEvent<ApiType, [sender: AccountId32, recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple, collectionId: u32, nftId: u32], { sender: AccountId32, recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple, collectionId: u32, nftId: u32 }>;
+      NFTBurned: AugmentedEvent<ApiType, [owner: AccountId32, nftId: u32], { owner: AccountId32, nftId: u32 }>;
+      NftMinted: AugmentedEvent<ApiType, [owner: AccountId32, collectionId: u32, nftId: u32], { owner: AccountId32, collectionId: u32, nftId: u32 }>;
+      NFTRejected: AugmentedEvent<ApiType, [sender: AccountId32, collectionId: u32, nftId: u32], { sender: AccountId32, collectionId: u32, nftId: u32 }>;
+      NFTSent: AugmentedEvent<ApiType, [sender: AccountId32, recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple, collectionId: u32, nftId: u32, approvalRequired: bool], { sender: AccountId32, recipient: RmrkTraitsNftAccountIdOrCollectionNftTuple, collectionId: u32, nftId: u32, approvalRequired: bool }>;
+      PrioritySet: AugmentedEvent<ApiType, [collectionId: u32, nftId: u32], { collectionId: u32, nftId: u32 }>;
+      PropertySet: AugmentedEvent<ApiType, [collectionId: u32, maybeNftId: Option<u32>, key: Bytes, value: Bytes], { collectionId: u32, maybeNftId: Option<u32>, key: Bytes, value: Bytes }>;
+      ResourceAccepted: AugmentedEvent<ApiType, [nftId: u32, resourceId: u32], { nftId: u32, resourceId: u32 }>;
+      ResourceAdded: AugmentedEvent<ApiType, [nftId: u32, resourceId: u32], { nftId: u32, resourceId: u32 }>;
+      ResourceRemoval: AugmentedEvent<ApiType, [nftId: u32, resourceId: u32], { nftId: u32, resourceId: u32 }>;
+      ResourceRemovalAccepted: AugmentedEvent<ApiType, [nftId: u32, resourceId: u32], { nftId: u32, resourceId: u32 }>;
       /**
        * Generic event
        **/
       [key: string]: AugmentedEvent<ApiType>;
     };
     rmrkEquip: {
-      BaseCreated: AugmentedEvent<ApiType, [AccountId32, u32]>;
+      BaseCreated: AugmentedEvent<ApiType, [issuer: AccountId32, baseId: u32], { issuer: AccountId32, baseId: u32 }>;
       /**
        * Generic event
        **/
@@ -429,19 +429,19 @@
       /**
        * The call for the provided hash was not found so the task has been aborted.
        **/
-      CallLookupFailed: AugmentedEvent<ApiType, [ITuple<[u32, u32]>, Option<U8aFixed>, FrameSupportScheduleLookupError]>;
+      CallLookupFailed: AugmentedEvent<ApiType, [task: ITuple<[u32, u32]>, id: Option<U8aFixed>, error: FrameSupportScheduleLookupError], { task: ITuple<[u32, u32]>, id: Option<U8aFixed>, error: FrameSupportScheduleLookupError }>;
       /**
        * Canceled some task.
        **/
-      Canceled: AugmentedEvent<ApiType, [u32, u32]>;
+      Canceled: AugmentedEvent<ApiType, [when: u32, index: u32], { when: u32, index: u32 }>;
       /**
        * Dispatched some task.
        **/
-      Dispatched: AugmentedEvent<ApiType, [ITuple<[u32, u32]>, Option<U8aFixed>, Result<Null, SpRuntimeDispatchError>]>;
+      Dispatched: AugmentedEvent<ApiType, [task: ITuple<[u32, u32]>, id: Option<U8aFixed>, result: Result<Null, SpRuntimeDispatchError>], { task: ITuple<[u32, u32]>, id: Option<U8aFixed>, result: Result<Null, SpRuntimeDispatchError> }>;
       /**
        * Scheduled some task.
        **/
-      Scheduled: AugmentedEvent<ApiType, [u32, u32]>;
+      Scheduled: AugmentedEvent<ApiType, [when: u32, index: u32], { when: u32, index: u32 }>;
       /**
        * Generic event
        **/
@@ -461,15 +461,15 @@
       /**
        * The \[sudoer\] just switched identity; the old key is supplied if one existed.
        **/
-      KeyChanged: AugmentedEvent<ApiType, [Option<AccountId32>]>;
+      KeyChanged: AugmentedEvent<ApiType, [oldSudoer: Option<AccountId32>], { oldSudoer: Option<AccountId32> }>;
       /**
        * A sudo just took place. \[result\]
        **/
-      Sudid: AugmentedEvent<ApiType, [Result<Null, SpRuntimeDispatchError>]>;
+      Sudid: AugmentedEvent<ApiType, [sudoResult: Result<Null, SpRuntimeDispatchError>], { sudoResult: Result<Null, SpRuntimeDispatchError> }>;
       /**
        * A sudo just took place. \[result\]
        **/
-      SudoAsDone: AugmentedEvent<ApiType, [Result<Null, SpRuntimeDispatchError>]>;
+      SudoAsDone: AugmentedEvent<ApiType, [sudoResult: Result<Null, SpRuntimeDispatchError>], { sudoResult: Result<Null, SpRuntimeDispatchError> }>;
       /**
        * Generic event
        **/
@@ -483,23 +483,23 @@
       /**
        * An extrinsic failed.
        **/
-      ExtrinsicFailed: AugmentedEvent<ApiType, [SpRuntimeDispatchError, FrameSupportWeightsDispatchInfo]>;
+      ExtrinsicFailed: AugmentedEvent<ApiType, [dispatchError: SpRuntimeDispatchError, dispatchInfo: FrameSupportWeightsDispatchInfo], { dispatchError: SpRuntimeDispatchError, dispatchInfo: FrameSupportWeightsDispatchInfo }>;
       /**
        * An extrinsic completed successfully.
        **/
-      ExtrinsicSuccess: AugmentedEvent<ApiType, [FrameSupportWeightsDispatchInfo]>;
+      ExtrinsicSuccess: AugmentedEvent<ApiType, [dispatchInfo: FrameSupportWeightsDispatchInfo], { dispatchInfo: FrameSupportWeightsDispatchInfo }>;
       /**
        * An account was reaped.
        **/
-      KilledAccount: AugmentedEvent<ApiType, [AccountId32]>;
+      KilledAccount: AugmentedEvent<ApiType, [account: AccountId32], { account: AccountId32 }>;
       /**
        * A new account was created.
        **/
-      NewAccount: AugmentedEvent<ApiType, [AccountId32]>;
+      NewAccount: AugmentedEvent<ApiType, [account: AccountId32], { account: AccountId32 }>;
       /**
        * On on-chain remark happened.
        **/
-      Remarked: AugmentedEvent<ApiType, [AccountId32, H256]>;
+      Remarked: AugmentedEvent<ApiType, [sender: AccountId32, hash_: H256], { sender: AccountId32, hash_: H256 }>;
       /**
        * Generic event
        **/
@@ -509,31 +509,31 @@
       /**
        * Some funds have been allocated.
        **/
-      Awarded: AugmentedEvent<ApiType, [u32, u128, AccountId32]>;
+      Awarded: AugmentedEvent<ApiType, [proposalIndex: u32, award: u128, account: AccountId32], { proposalIndex: u32, award: u128, account: AccountId32 }>;
       /**
        * Some of our funds have been burnt.
        **/
-      Burnt: AugmentedEvent<ApiType, [u128]>;
+      Burnt: AugmentedEvent<ApiType, [burntFunds: u128], { burntFunds: u128 }>;
       /**
        * Some funds have been deposited.
        **/
-      Deposit: AugmentedEvent<ApiType, [u128]>;
+      Deposit: AugmentedEvent<ApiType, [value: u128], { value: u128 }>;
       /**
        * New proposal.
        **/
-      Proposed: AugmentedEvent<ApiType, [u32]>;
+      Proposed: AugmentedEvent<ApiType, [proposalIndex: u32], { proposalIndex: u32 }>;
       /**
        * A proposal was rejected; funds were slashed.
        **/
-      Rejected: AugmentedEvent<ApiType, [u32, u128]>;
+      Rejected: AugmentedEvent<ApiType, [proposalIndex: u32, slashed: u128], { proposalIndex: u32, slashed: u128 }>;
       /**
        * Spending has finished; this is the amount that rolls over until next spend.
        **/
-      Rollover: AugmentedEvent<ApiType, [u128]>;
+      Rollover: AugmentedEvent<ApiType, [rolloverBalance: u128], { rolloverBalance: u128 }>;
       /**
        * We have ended a spend period and will now allocate funds.
        **/
-      Spending: AugmentedEvent<ApiType, [u128]>;
+      Spending: AugmentedEvent<ApiType, [budgetRemaining: u128], { budgetRemaining: u128 }>;
       /**
        * Generic event
        **/
@@ -636,15 +636,15 @@
       /**
        * Claimed vesting.
        **/
-      Claimed: AugmentedEvent<ApiType, [AccountId32, u128]>;
+      Claimed: AugmentedEvent<ApiType, [who: AccountId32, amount: u128], { who: AccountId32, amount: u128 }>;
       /**
        * Added new vesting schedule.
        **/
-      VestingScheduleAdded: AugmentedEvent<ApiType, [AccountId32, AccountId32, OrmlVestingVestingSchedule]>;
+      VestingScheduleAdded: AugmentedEvent<ApiType, [from: AccountId32, to: AccountId32, vestingSchedule: OrmlVestingVestingSchedule], { from: AccountId32, to: AccountId32, vestingSchedule: OrmlVestingVestingSchedule }>;
       /**
        * Updated vesting schedules.
        **/
-      VestingSchedulesUpdated: AugmentedEvent<ApiType, [AccountId32]>;
+      VestingSchedulesUpdated: AugmentedEvent<ApiType, [who: AccountId32], { who: AccountId32 }>;
       /**
        * Generic event
        **/
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -347,22 +347,105 @@
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
     rmrkCore: {
+      /**
+       * Accepts an NFT sent from another account to self or owned NFT
+       * 
+       * Parameters:
+       * - `origin`: sender of the transaction
+       * - `rmrk_collection_id`: collection id of the nft to be accepted
+       * - `rmrk_nft_id`: nft id of the nft to be accepted
+       * - `new_owner`: either origin's account ID or origin-owned NFT, whichever the NFT was
+       * sent to
+       **/
       acceptNft: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple | { AccountId: any } | { CollectionAndNftTuple: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsNftAccountIdOrCollectionNftTuple]>;
+      /**
+       * accept the addition of a new resource to an existing NFT
+       **/
       acceptResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, rmrkResourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
+      /**
+       * accept the removal of a resource of an existing NFT
+       **/
       acceptResourceRemoval: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, rmrkResourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
+      /**
+       * Create basic resource
+       **/
       addBasicResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceBasicResource | { src?: any; metadata?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceBasicResource]>;
+      /**
+       * Create composable resource
+       **/
       addComposableResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resourceId: Bytes | string | Uint8Array, resource: RmrkTraitsResourceComposableResource | { parts?: any; base?: any; src?: any; metadata?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, Bytes, RmrkTraitsResourceComposableResource]>;
+      /**
+       * Create slot resource
+       **/
       addSlotResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resource: RmrkTraitsResourceSlotResource | { base?: any; src?: any; metadata?: any; slot?: any; license?: any; thumb?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsResourceSlotResource]>;
+      /**
+       * burn nft
+       **/
       burnNft: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32]>;
+      /**
+       * Change the issuer of a collection
+       * 
+       * Parameters:
+       * - `origin`: sender of the transaction
+       * - `collection_id`: collection id of the nft to change issuer of
+       * - `new_issuer`: Collection's new issuer
+       **/
       changeCollectionIssuer: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newIssuer: MultiAddress | { Id: any } | { Index: any } | { Raw: any } | { Address32: any } | { Address20: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, MultiAddress]>;
+      /**
+       * Create a collection
+       **/
       createCollection: AugmentedSubmittable<(metadata: Bytes | string | Uint8Array, max: Option<u32> | null | object | string | Uint8Array, symbol: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Bytes, Option<u32>, Bytes]>;
+      /**
+       * destroy collection
+       **/
       destroyCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
+      /**
+       * lock collection
+       **/
       lockCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
+      /**
+       * Mints an NFT in the specified collection
+       * Sets metadata and the royalty attribute
+       * 
+       * Parameters:
+       * - `collection_id`: The class of the asset to be minted.
+       * - `nft_id`: The nft value of the asset to be minted.
+       * - `recipient`: Receiver of the royalty
+       * - `royalty`: Permillage reward from each trade for the Recipient
+       * - `metadata`: Arbitrary data about an nft, e.g. IPFS hash
+       * - `transferable`: Ability to transfer this NFT
+       **/
       mintNft: AugmentedSubmittable<(owner: AccountId32 | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, recipient: Option<AccountId32> | null | object | string | Uint8Array, royaltyAmount: Option<Permill> | null | object | string | Uint8Array, metadata: Bytes | string | Uint8Array, transferable: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [AccountId32, u32, Option<AccountId32>, Option<Permill>, Bytes, bool]>;
+      /**
+       * Rejects an NFT sent from another account to self or owned NFT
+       * 
+       * Parameters:
+       * - `origin`: sender of the transaction
+       * - `rmrk_collection_id`: collection id of the nft to be accepted
+       * - `rmrk_nft_id`: nft id of the nft to be accepted
+       **/
       rejectNft: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32]>;
+      /**
+       * remove resource
+       **/
       removeResource: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, nftId: u32 | AnyNumber | Uint8Array, resourceId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u32]>;
+      /**
+       * Transfers a NFT from an Account or NFT A to another Account or NFT B
+       * 
+       * Parameters:
+       * - `origin`: sender of the transaction
+       * - `rmrk_collection_id`: collection id of the nft to be transferred
+       * - `rmrk_nft_id`: nft id of the nft to be transferred
+       * - `new_owner`: new owner of the nft which can be either an account or a NFT
+       **/
       send: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, newOwner: RmrkTraitsNftAccountIdOrCollectionNftTuple | { AccountId: any } | { CollectionAndNftTuple: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, RmrkTraitsNftAccountIdOrCollectionNftTuple]>;
+      /**
+       * set a different order of resource priority
+       **/
       setPriority: AugmentedSubmittable<(rmrkCollectionId: u32 | AnyNumber | Uint8Array, rmrkNftId: u32 | AnyNumber | Uint8Array, priorities: Vec<u32> | (u32 | AnyNumber | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, u32, Vec<u32>]>;
+      /**
+       * set a custom value on an NFT
+       **/
       setProperty: AugmentedSubmittable<(rmrkCollectionId: Compact<u32> | AnyNumber | Uint8Array, maybeNftId: Option<u32> | null | object | string | Uint8Array, key: Bytes | string | Uint8Array, value: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Compact<u32>, Option<u32>, Bytes, Bytes]>;
       /**
        * Generic tx
@@ -370,7 +453,33 @@
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
     rmrkEquip: {
+      /**
+       * Creates a new Base.
+       * Modeled after [base interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/base.md)
+       * 
+       * Parameters:
+       * - origin: Caller, will be assigned as the issuer of the Base
+       * - base_type: media type, e.g. "svg"
+       * - symbol: arbitrary client-chosen symbol
+       * - parts: array of Fixed and Slot parts composing the base, confined in length by
+       * RmrkPartsLimit
+       **/
       createBase: AugmentedSubmittable<(baseType: Bytes | string | Uint8Array, symbol: Bytes | string | Uint8Array, parts: Vec<RmrkTraitsPartPartType> | (RmrkTraitsPartPartType | { FixedPart: any } | { SlotPart: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [Bytes, Bytes, Vec<RmrkTraitsPartPartType>]>;
+      /**
+       * Adds a Theme to a Base.
+       * Modeled after [themeadd interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/themeadd.md)
+       * Themes are stored in the Themes storage
+       * A Theme named "default" is required prior to adding other Themes.
+       * 
+       * Parameters:
+       * - origin: The caller of the function, must be issuer of the base
+       * - base_id: The Base containing the Theme to be updated
+       * - theme: The Theme to add to the Base.  A Theme has a name and properties, which are an
+       * array of [key, value, inherit].
+       * - key: arbitrary BoundedString, defined by client
+       * - value: arbitrary BoundedString, defined by client
+       * - inherit: optional bool
+       **/
       themeAdd: AugmentedSubmittable<(baseId: u32 | AnyNumber | Uint8Array, theme: RmrkTraitsTheme | { name?: any; properties?: any; inherit?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, RmrkTraitsTheme]>;
       /**
        * Generic tx
modifiedtests/src/interfaces/augment-types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-types.ts
+++ b/tests/src/interfaces/augment-types.ts
@@ -1,7 +1,7 @@
 // Auto-generated via `yarn polkadot-types-from-defs`, do not edit
 /* eslint-disable */
 
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUnqSchedulerCall, PalletUnqSchedulerError, PalletUnqSchedulerEvent, PalletUnqSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingRule, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUnqSchedulerCall, PalletUnqSchedulerError, PalletUnqSchedulerEvent, PalletUnqSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
 import type { Data, StorageKey } from '@polkadot/types';
 import type { BitVec, Bool, Bytes, I128, I16, I256, I32, I64, I8, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec';
 import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';
@@ -1218,7 +1218,8 @@
     UpDataStructsCreateNftExData: UpDataStructsCreateNftExData;
     UpDataStructsCreateReFungibleData: UpDataStructsCreateReFungibleData;
     UpDataStructsCreateRefungibleExData: UpDataStructsCreateRefungibleExData;
-    UpDataStructsNestingRule: UpDataStructsNestingRule;
+    UpDataStructsNestingPermissions: UpDataStructsNestingPermissions;
+    UpDataStructsOwnerRestrictedSet: UpDataStructsOwnerRestrictedSet;
     UpDataStructsProperties: UpDataStructsProperties;
     UpDataStructsPropertiesMapBoundedVec: UpDataStructsPropertiesMapBoundedVec;
     UpDataStructsPropertiesMapPropertyPermission: UpDataStructsPropertiesMapPropertyPermission;
modifiedtests/src/interfaces/default/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -935,8 +935,7 @@
   readonly isAddressIsZero: boolean;
   readonly isUnsupportedOperation: boolean;
   readonly isNotSufficientFounds: boolean;
-  readonly isNestingIsDisabled: boolean;
-  readonly isOnlyOwnerAllowedToNest: boolean;
+  readonly isUserIsNotAllowedToNest: boolean;
   readonly isSourceCollectionIsNotAllowedToNest: boolean;
   readonly isCollectionFieldSizeExceeded: boolean;
   readonly isNoSpaceForProperty: boolean;
@@ -946,7 +945,7 @@
   readonly isEmptyPropertyKey: boolean;
   readonly isCollectionIsExternal: boolean;
   readonly isCollectionIsInternal: 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' | 'NestingIsDisabled' | 'OnlyOwnerAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal';
+  readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal';
 }
 
 /** @name PalletCommonEvent */
@@ -1445,8 +1444,9 @@
 export interface PalletStructureError extends Enum {
   readonly isOuroborosDetected: boolean;
   readonly isDepthLimit: boolean;
+  readonly isBreadthLimit: boolean;
   readonly isTokenNotFound: boolean;
-  readonly type: 'OuroborosDetected' | 'DepthLimit' | 'TokenNotFound';
+  readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound';
 }
 
 /** @name PalletStructureEvent */
@@ -2348,7 +2348,7 @@
 export interface UpDataStructsCollectionPermissions extends Struct {
   readonly access: Option<UpDataStructsAccessMode>;
   readonly mintMode: Option<bool>;
-  readonly nesting: Option<UpDataStructsNestingRule>;
+  readonly nesting: Option<UpDataStructsNestingPermissions>;
 }
 
 /** @name UpDataStructsCollectionStats */
@@ -2424,15 +2424,17 @@
   readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
 }
 
-/** @name UpDataStructsNestingRule */
-export interface UpDataStructsNestingRule extends Enum {
-  readonly isDisabled: boolean;
-  readonly isOwner: boolean;
-  readonly isOwnerRestricted: boolean;
-  readonly asOwnerRestricted: BTreeSet<u32>;
-  readonly type: 'Disabled' | 'Owner' | 'OwnerRestricted';
+/** @name UpDataStructsNestingPermissions */
+export interface UpDataStructsNestingPermissions extends Struct {
+  readonly tokenOwner: bool;
+  readonly admin: bool;
+  readonly restricted: Option<UpDataStructsOwnerRestrictedSet>;
+  readonly permissive: bool;
 }
 
+/** @name UpDataStructsOwnerRestrictedSet */
+export interface UpDataStructsOwnerRestrictedSet extends BTreeSet<u32> {}
+
 /** @name UpDataStructsProperties */
 export interface UpDataStructsProperties extends Struct {
   readonly map: UpDataStructsPropertiesMapBoundedVec;
modifiedtests/src/interfaces/lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -1425,27 +1425,30 @@
   UpDataStructsCollectionPermissions: {
     access: 'Option<UpDataStructsAccessMode>',
     mintMode: 'Option<bool>',
-    nesting: 'Option<UpDataStructsNestingRule>'
+    nesting: 'Option<UpDataStructsNestingPermissions>'
   },
   /**
-   * Lookup169: up_data_structs::NestingRule
+   * Lookup169: up_data_structs::NestingPermissions
    **/
-  UpDataStructsNestingRule: {
-    _enum: {
-      Disabled: 'Null',
-      Owner: 'Null',
-      OwnerRestricted: 'BTreeSet<u32>'
-    }
+  UpDataStructsNestingPermissions: {
+    tokenOwner: 'bool',
+    admin: 'bool',
+    restricted: 'Option<UpDataStructsOwnerRestrictedSet>',
+    permissive: 'bool'
   },
   /**
-   * Lookup175: up_data_structs::PropertyKeyPermission
+   * Lookup171: up_data_structs::OwnerRestrictedSet
    **/
+  UpDataStructsOwnerRestrictedSet: 'BTreeSet<u32>',
+  /**
+   * Lookup177: up_data_structs::PropertyKeyPermission
+   **/
   UpDataStructsPropertyKeyPermission: {
     key: 'Bytes',
     permission: 'UpDataStructsPropertyPermission'
   },
   /**
-   * Lookup177: up_data_structs::PropertyPermission
+   * Lookup179: up_data_structs::PropertyPermission
    **/
   UpDataStructsPropertyPermission: {
     mutable: 'bool',
@@ -1453,14 +1456,14 @@
     tokenOwner: 'bool'
   },
   /**
-   * Lookup180: up_data_structs::Property
+   * Lookup182: up_data_structs::Property
    **/
   UpDataStructsProperty: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup183: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>
+   * Lookup185: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>
    **/
   PalletEvmAccountBasicCrossAccountIdRepr: {
     _enum: {
@@ -1469,7 +1472,7 @@
     }
   },
   /**
-   * Lookup185: up_data_structs::CreateItemData
+   * Lookup187: up_data_structs::CreateItemData
    **/
   UpDataStructsCreateItemData: {
     _enum: {
@@ -1479,26 +1482,26 @@
     }
   },
   /**
-   * Lookup186: up_data_structs::CreateNftData
+   * Lookup188: up_data_structs::CreateNftData
    **/
   UpDataStructsCreateNftData: {
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup187: up_data_structs::CreateFungibleData
+   * Lookup189: up_data_structs::CreateFungibleData
    **/
   UpDataStructsCreateFungibleData: {
     value: 'u128'
   },
   /**
-   * Lookup188: up_data_structs::CreateReFungibleData
+   * Lookup190: up_data_structs::CreateReFungibleData
    **/
   UpDataStructsCreateReFungibleData: {
     constData: 'Bytes',
     pieces: 'u128'
   },
   /**
-   * Lookup193: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup195: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateItemExData: {
     _enum: {
@@ -1509,21 +1512,21 @@
     }
   },
   /**
-   * Lookup195: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup197: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateNftExData: {
     properties: 'Vec<UpDataStructsProperty>',
     owner: 'PalletEvmAccountBasicCrossAccountIdRepr'
   },
   /**
-   * Lookup202: up_data_structs::CreateRefungibleExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup204: up_data_structs::CreateRefungibleExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateRefungibleExData: {
     constData: 'Bytes',
     users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>'
   },
   /**
-   * Lookup204: pallet_unq_scheduler::pallet::Call<T>
+   * Lookup206: pallet_unq_scheduler::pallet::Call<T>
    **/
   PalletUnqSchedulerCall: {
     _enum: {
@@ -1547,7 +1550,7 @@
     }
   },
   /**
-   * Lookup206: frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>
+   * Lookup208: frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>
    **/
   FrameSupportScheduleMaybeHashed: {
     _enum: {
@@ -1556,15 +1559,15 @@
     }
   },
   /**
-   * Lookup207: pallet_template_transaction_payment::Call<T>
+   * Lookup209: pallet_template_transaction_payment::Call<T>
    **/
   PalletTemplateTransactionPaymentCall: 'Null',
   /**
-   * Lookup208: pallet_structure::pallet::Call<T>
+   * Lookup210: pallet_structure::pallet::Call<T>
    **/
   PalletStructureCall: 'Null',
   /**
-   * Lookup209: pallet_rmrk_core::pallet::Call<T>
+   * Lookup211: pallet_rmrk_core::pallet::Call<T>
    **/
   PalletRmrkCoreCall: {
     _enum: {
@@ -1654,7 +1657,7 @@
     }
   },
   /**
-   * Lookup213: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>
+   * Lookup215: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>
    **/
   RmrkTraitsNftAccountIdOrCollectionNftTuple: {
     _enum: {
@@ -1663,7 +1666,7 @@
     }
   },
   /**
-   * Lookup217: rmrk_traits::resource::BasicResource<frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup219: rmrk_traits::resource::BasicResource<frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceBasicResource: {
     src: 'Option<Bytes>',
@@ -1672,7 +1675,7 @@
     thumb: 'Option<Bytes>'
   },
   /**
-   * Lookup220: rmrk_traits::resource::ComposableResource<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup222: rmrk_traits::resource::ComposableResource<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceComposableResource: {
     parts: 'Vec<u32>',
@@ -1683,7 +1686,7 @@
     thumb: 'Option<Bytes>'
   },
   /**
-   * Lookup222: rmrk_traits::resource::SlotResource<frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup224: rmrk_traits::resource::SlotResource<frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceSlotResource: {
     base: 'u32',
@@ -1694,7 +1697,7 @@
     thumb: 'Option<Bytes>'
   },
   /**
-   * Lookup223: pallet_rmrk_equip::pallet::Call<T>
+   * Lookup225: pallet_rmrk_equip::pallet::Call<T>
    **/
   PalletRmrkEquipCall: {
     _enum: {
@@ -1710,7 +1713,7 @@
     }
   },
   /**
-   * Lookup225: rmrk_traits::part::PartType<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup227: rmrk_traits::part::PartType<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartPartType: {
     _enum: {
@@ -1719,7 +1722,7 @@
     }
   },
   /**
-   * Lookup227: rmrk_traits::part::FixedPart<frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup229: rmrk_traits::part::FixedPart<frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartFixedPart: {
     id: 'u32',
@@ -1727,7 +1730,7 @@
     src: 'Bytes'
   },
   /**
-   * Lookup228: rmrk_traits::part::SlotPart<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup230: rmrk_traits::part::SlotPart<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartSlotPart: {
     id: 'u32',
@@ -1736,7 +1739,7 @@
     z: 'u32'
   },
   /**
-   * Lookup229: rmrk_traits::part::EquippableList<frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup231: rmrk_traits::part::EquippableList<frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartEquippableList: {
     _enum: {
@@ -1746,7 +1749,7 @@
     }
   },
   /**
-   * Lookup231: rmrk_traits::theme::Theme<frame_support::storage::bounded_vec::BoundedVec<T, S>, PropertyList>
+   * Lookup233: rmrk_traits::theme::Theme<frame_support::storage::bounded_vec::BoundedVec<T, S>, PropertyList>
    **/
   RmrkTraitsTheme: {
     name: 'Bytes',
@@ -1754,14 +1757,14 @@
     inherit: 'bool'
   },
   /**
-   * Lookup233: rmrk_traits::theme::ThemeProperty<frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup235: rmrk_traits::theme::ThemeProperty<frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsThemeThemeProperty: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup234: pallet_evm::pallet::Call<T>
+   * Lookup236: pallet_evm::pallet::Call<T>
    **/
   PalletEvmCall: {
     _enum: {
@@ -1804,7 +1807,7 @@
     }
   },
   /**
-   * Lookup240: pallet_ethereum::pallet::Call<T>
+   * Lookup242: pallet_ethereum::pallet::Call<T>
    **/
   PalletEthereumCall: {
     _enum: {
@@ -1814,7 +1817,7 @@
     }
   },
   /**
-   * Lookup241: ethereum::transaction::TransactionV2
+   * Lookup243: ethereum::transaction::TransactionV2
    **/
   EthereumTransactionTransactionV2: {
     _enum: {
@@ -1824,7 +1827,7 @@
     }
   },
   /**
-   * Lookup242: ethereum::transaction::LegacyTransaction
+   * Lookup244: ethereum::transaction::LegacyTransaction
    **/
   EthereumTransactionLegacyTransaction: {
     nonce: 'U256',
@@ -1836,7 +1839,7 @@
     signature: 'EthereumTransactionTransactionSignature'
   },
   /**
-   * Lookup243: ethereum::transaction::TransactionAction
+   * Lookup245: ethereum::transaction::TransactionAction
    **/
   EthereumTransactionTransactionAction: {
     _enum: {
@@ -1845,7 +1848,7 @@
     }
   },
   /**
-   * Lookup244: ethereum::transaction::TransactionSignature
+   * Lookup246: ethereum::transaction::TransactionSignature
    **/
   EthereumTransactionTransactionSignature: {
     v: 'u64',
@@ -1853,7 +1856,7 @@
     s: 'H256'
   },
   /**
-   * Lookup246: ethereum::transaction::EIP2930Transaction
+   * Lookup248: ethereum::transaction::EIP2930Transaction
    **/
   EthereumTransactionEip2930Transaction: {
     chainId: 'u64',
@@ -1869,14 +1872,14 @@
     s: 'H256'
   },
   /**
-   * Lookup248: ethereum::transaction::AccessListItem
+   * Lookup250: ethereum::transaction::AccessListItem
    **/
   EthereumTransactionAccessListItem: {
     address: 'H160',
     storageKeys: 'Vec<H256>'
   },
   /**
-   * Lookup249: ethereum::transaction::EIP1559Transaction
+   * Lookup251: ethereum::transaction::EIP1559Transaction
    **/
   EthereumTransactionEip1559Transaction: {
     chainId: 'u64',
@@ -1893,7 +1896,7 @@
     s: 'H256'
   },
   /**
-   * Lookup250: pallet_evm_migration::pallet::Call<T>
+   * Lookup252: pallet_evm_migration::pallet::Call<T>
    **/
   PalletEvmMigrationCall: {
     _enum: {
@@ -1911,7 +1914,7 @@
     }
   },
   /**
-   * Lookup253: pallet_sudo::pallet::Event<T>
+   * Lookup255: pallet_sudo::pallet::Event<T>
    **/
   PalletSudoEvent: {
     _enum: {
@@ -1927,7 +1930,7 @@
     }
   },
   /**
-   * Lookup255: sp_runtime::DispatchError
+   * Lookup257: sp_runtime::DispatchError
    **/
   SpRuntimeDispatchError: {
     _enum: {
@@ -1944,38 +1947,38 @@
     }
   },
   /**
-   * Lookup256: sp_runtime::ModuleError
+   * Lookup258: sp_runtime::ModuleError
    **/
   SpRuntimeModuleError: {
     index: 'u8',
     error: '[u8;4]'
   },
   /**
-   * Lookup257: sp_runtime::TokenError
+   * Lookup259: sp_runtime::TokenError
    **/
   SpRuntimeTokenError: {
     _enum: ['NoFunds', 'WouldDie', 'BelowMinimum', 'CannotCreate', 'UnknownAsset', 'Frozen', 'Unsupported']
   },
   /**
-   * Lookup258: sp_runtime::ArithmeticError
+   * Lookup260: sp_runtime::ArithmeticError
    **/
   SpRuntimeArithmeticError: {
     _enum: ['Underflow', 'Overflow', 'DivisionByZero']
   },
   /**
-   * Lookup259: sp_runtime::TransactionalError
+   * Lookup261: sp_runtime::TransactionalError
    **/
   SpRuntimeTransactionalError: {
     _enum: ['LimitReached', 'NoLayer']
   },
   /**
-   * Lookup260: pallet_sudo::pallet::Error<T>
+   * Lookup262: pallet_sudo::pallet::Error<T>
    **/
   PalletSudoError: {
     _enum: ['RequireSudo']
   },
   /**
-   * Lookup261: frame_system::AccountInfo<Index, pallet_balances::AccountData<Balance>>
+   * Lookup263: frame_system::AccountInfo<Index, pallet_balances::AccountData<Balance>>
    **/
   FrameSystemAccountInfo: {
     nonce: 'u32',
@@ -1985,7 +1988,7 @@
     data: 'PalletBalancesAccountData'
   },
   /**
-   * Lookup262: frame_support::weights::PerDispatchClass<T>
+   * Lookup264: frame_support::weights::PerDispatchClass<T>
    **/
   FrameSupportWeightsPerDispatchClassU64: {
     normal: 'u64',
@@ -1993,13 +1996,13 @@
     mandatory: 'u64'
   },
   /**
-   * Lookup263: sp_runtime::generic::digest::Digest
+   * Lookup265: sp_runtime::generic::digest::Digest
    **/
   SpRuntimeDigest: {
     logs: 'Vec<SpRuntimeDigestDigestItem>'
   },
   /**
-   * Lookup265: sp_runtime::generic::digest::DigestItem
+   * Lookup267: sp_runtime::generic::digest::DigestItem
    **/
   SpRuntimeDigestDigestItem: {
     _enum: {
@@ -2015,7 +2018,7 @@
     }
   },
   /**
-   * Lookup267: frame_system::EventRecord<opal_runtime::Event, primitive_types::H256>
+   * Lookup269: frame_system::EventRecord<opal_runtime::Event, primitive_types::H256>
    **/
   FrameSystemEventRecord: {
     phase: 'FrameSystemPhase',
@@ -2023,7 +2026,7 @@
     topics: 'Vec<H256>'
   },
   /**
-   * Lookup269: frame_system::pallet::Event<T>
+   * Lookup271: frame_system::pallet::Event<T>
    **/
   FrameSystemEvent: {
     _enum: {
@@ -2051,7 +2054,7 @@
     }
   },
   /**
-   * Lookup270: frame_support::weights::DispatchInfo
+   * Lookup272: frame_support::weights::DispatchInfo
    **/
   FrameSupportWeightsDispatchInfo: {
     weight: 'u64',
@@ -2059,19 +2062,19 @@
     paysFee: 'FrameSupportWeightsPays'
   },
   /**
-   * Lookup271: frame_support::weights::DispatchClass
+   * Lookup273: frame_support::weights::DispatchClass
    **/
   FrameSupportWeightsDispatchClass: {
     _enum: ['Normal', 'Operational', 'Mandatory']
   },
   /**
-   * Lookup272: frame_support::weights::Pays
+   * Lookup274: frame_support::weights::Pays
    **/
   FrameSupportWeightsPays: {
     _enum: ['Yes', 'No']
   },
   /**
-   * Lookup273: orml_vesting::module::Event<T>
+   * Lookup275: orml_vesting::module::Event<T>
    **/
   OrmlVestingModuleEvent: {
     _enum: {
@@ -2090,7 +2093,7 @@
     }
   },
   /**
-   * Lookup274: cumulus_pallet_xcmp_queue::pallet::Event<T>
+   * Lookup276: cumulus_pallet_xcmp_queue::pallet::Event<T>
    **/
   CumulusPalletXcmpQueueEvent: {
     _enum: {
@@ -2105,7 +2108,7 @@
     }
   },
   /**
-   * Lookup275: pallet_xcm::pallet::Event<T>
+   * Lookup277: pallet_xcm::pallet::Event<T>
    **/
   PalletXcmEvent: {
     _enum: {
@@ -2128,7 +2131,7 @@
     }
   },
   /**
-   * Lookup276: xcm::v2::traits::Outcome
+   * Lookup278: xcm::v2::traits::Outcome
    **/
   XcmV2TraitsOutcome: {
     _enum: {
@@ -2138,7 +2141,7 @@
     }
   },
   /**
-   * Lookup278: cumulus_pallet_xcm::pallet::Event<T>
+   * Lookup280: cumulus_pallet_xcm::pallet::Event<T>
    **/
   CumulusPalletXcmEvent: {
     _enum: {
@@ -2148,7 +2151,7 @@
     }
   },
   /**
-   * Lookup279: cumulus_pallet_dmp_queue::pallet::Event<T>
+   * Lookup281: cumulus_pallet_dmp_queue::pallet::Event<T>
    **/
   CumulusPalletDmpQueueEvent: {
     _enum: {
@@ -2161,7 +2164,7 @@
     }
   },
   /**
-   * Lookup280: pallet_unique::RawEvent<sp_core::crypto::AccountId32, pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup282: pallet_unique::RawEvent<sp_core::crypto::AccountId32, pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   PalletUniqueRawEvent: {
     _enum: {
@@ -2178,7 +2181,7 @@
     }
   },
   /**
-   * Lookup281: pallet_unq_scheduler::pallet::Event<T>
+   * Lookup283: pallet_unq_scheduler::pallet::Event<T>
    **/
   PalletUnqSchedulerEvent: {
     _enum: {
@@ -2203,13 +2206,13 @@
     }
   },
   /**
-   * Lookup283: frame_support::traits::schedule::LookupError
+   * Lookup285: frame_support::traits::schedule::LookupError
    **/
   FrameSupportScheduleLookupError: {
     _enum: ['Unknown', 'BadFormat']
   },
   /**
-   * Lookup284: pallet_common::pallet::Event<T>
+   * Lookup286: pallet_common::pallet::Event<T>
    **/
   PalletCommonEvent: {
     _enum: {
@@ -2227,7 +2230,7 @@
     }
   },
   /**
-   * Lookup285: pallet_structure::pallet::Event<T>
+   * Lookup287: pallet_structure::pallet::Event<T>
    **/
   PalletStructureEvent: {
     _enum: {
@@ -2235,7 +2238,7 @@
     }
   },
   /**
-   * Lookup286: pallet_rmrk_core::pallet::Event<T>
+   * Lookup288: pallet_rmrk_core::pallet::Event<T>
    **/
   PalletRmrkCoreEvent: {
     _enum: {
@@ -2312,7 +2315,7 @@
     }
   },
   /**
-   * Lookup287: pallet_rmrk_equip::pallet::Event<T>
+   * Lookup289: pallet_rmrk_equip::pallet::Event<T>
    **/
   PalletRmrkEquipEvent: {
     _enum: {
@@ -2323,7 +2326,7 @@
     }
   },
   /**
-   * Lookup288: pallet_evm::pallet::Event<T>
+   * Lookup290: pallet_evm::pallet::Event<T>
    **/
   PalletEvmEvent: {
     _enum: {
@@ -2337,7 +2340,7 @@
     }
   },
   /**
-   * Lookup289: ethereum::log::Log
+   * Lookup291: ethereum::log::Log
    **/
   EthereumLog: {
     address: 'H160',
@@ -2345,7 +2348,7 @@
     data: 'Bytes'
   },
   /**
-   * Lookup290: pallet_ethereum::pallet::Event
+   * Lookup292: pallet_ethereum::pallet::Event
    **/
   PalletEthereumEvent: {
     _enum: {
@@ -2353,7 +2356,7 @@
     }
   },
   /**
-   * Lookup291: evm_core::error::ExitReason
+   * Lookup293: evm_core::error::ExitReason
    **/
   EvmCoreErrorExitReason: {
     _enum: {
@@ -2364,13 +2367,13 @@
     }
   },
   /**
-   * Lookup292: evm_core::error::ExitSucceed
+   * Lookup294: evm_core::error::ExitSucceed
    **/
   EvmCoreErrorExitSucceed: {
     _enum: ['Stopped', 'Returned', 'Suicided']
   },
   /**
-   * Lookup293: evm_core::error::ExitError
+   * Lookup295: evm_core::error::ExitError
    **/
   EvmCoreErrorExitError: {
     _enum: {
@@ -2392,13 +2395,13 @@
     }
   },
   /**
-   * Lookup296: evm_core::error::ExitRevert
+   * Lookup298: evm_core::error::ExitRevert
    **/
   EvmCoreErrorExitRevert: {
     _enum: ['Reverted']
   },
   /**
-   * Lookup297: evm_core::error::ExitFatal
+   * Lookup299: evm_core::error::ExitFatal
    **/
   EvmCoreErrorExitFatal: {
     _enum: {
@@ -2409,7 +2412,7 @@
     }
   },
   /**
-   * Lookup298: frame_system::Phase
+   * Lookup300: frame_system::Phase
    **/
   FrameSystemPhase: {
     _enum: {
@@ -2419,14 +2422,14 @@
     }
   },
   /**
-   * Lookup300: frame_system::LastRuntimeUpgradeInfo
+   * Lookup302: frame_system::LastRuntimeUpgradeInfo
    **/
   FrameSystemLastRuntimeUpgradeInfo: {
     specVersion: 'Compact<u32>',
     specName: 'Text'
   },
   /**
-   * Lookup301: frame_system::limits::BlockWeights
+   * Lookup303: frame_system::limits::BlockWeights
    **/
   FrameSystemLimitsBlockWeights: {
     baseBlock: 'u64',
@@ -2434,7 +2437,7 @@
     perClass: 'FrameSupportWeightsPerDispatchClassWeightsPerClass'
   },
   /**
-   * Lookup302: frame_support::weights::PerDispatchClass<frame_system::limits::WeightsPerClass>
+   * Lookup304: frame_support::weights::PerDispatchClass<frame_system::limits::WeightsPerClass>
    **/
   FrameSupportWeightsPerDispatchClassWeightsPerClass: {
     normal: 'FrameSystemLimitsWeightsPerClass',
@@ -2442,7 +2445,7 @@
     mandatory: 'FrameSystemLimitsWeightsPerClass'
   },
   /**
-   * Lookup303: frame_system::limits::WeightsPerClass
+   * Lookup305: frame_system::limits::WeightsPerClass
    **/
   FrameSystemLimitsWeightsPerClass: {
     baseExtrinsic: 'u64',
@@ -2451,13 +2454,13 @@
     reserved: 'Option<u64>'
   },
   /**
-   * Lookup305: frame_system::limits::BlockLength
+   * Lookup307: frame_system::limits::BlockLength
    **/
   FrameSystemLimitsBlockLength: {
     max: 'FrameSupportWeightsPerDispatchClassU32'
   },
   /**
-   * Lookup306: frame_support::weights::PerDispatchClass<T>
+   * Lookup308: frame_support::weights::PerDispatchClass<T>
    **/
   FrameSupportWeightsPerDispatchClassU32: {
     normal: 'u32',
@@ -2465,14 +2468,14 @@
     mandatory: 'u32'
   },
   /**
-   * Lookup307: frame_support::weights::RuntimeDbWeight
+   * Lookup309: frame_support::weights::RuntimeDbWeight
    **/
   FrameSupportWeightsRuntimeDbWeight: {
     read: 'u64',
     write: 'u64'
   },
   /**
-   * Lookup308: sp_version::RuntimeVersion
+   * Lookup310: sp_version::RuntimeVersion
    **/
   SpVersionRuntimeVersion: {
     specName: 'Text',
@@ -2485,19 +2488,19 @@
     stateVersion: 'u8'
   },
   /**
-   * Lookup312: frame_system::pallet::Error<T>
+   * Lookup314: frame_system::pallet::Error<T>
    **/
   FrameSystemError: {
     _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered']
   },
   /**
-   * Lookup314: orml_vesting::module::Error<T>
+   * Lookup316: orml_vesting::module::Error<T>
    **/
   OrmlVestingModuleError: {
     _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded']
   },
   /**
-   * Lookup316: cumulus_pallet_xcmp_queue::InboundChannelDetails
+   * Lookup318: cumulus_pallet_xcmp_queue::InboundChannelDetails
    **/
   CumulusPalletXcmpQueueInboundChannelDetails: {
     sender: 'u32',
@@ -2505,19 +2508,19 @@
     messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>'
   },
   /**
-   * Lookup317: cumulus_pallet_xcmp_queue::InboundState
+   * Lookup319: cumulus_pallet_xcmp_queue::InboundState
    **/
   CumulusPalletXcmpQueueInboundState: {
     _enum: ['Ok', 'Suspended']
   },
   /**
-   * Lookup320: polkadot_parachain::primitives::XcmpMessageFormat
+   * Lookup322: polkadot_parachain::primitives::XcmpMessageFormat
    **/
   PolkadotParachainPrimitivesXcmpMessageFormat: {
     _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals']
   },
   /**
-   * Lookup323: cumulus_pallet_xcmp_queue::OutboundChannelDetails
+   * Lookup325: cumulus_pallet_xcmp_queue::OutboundChannelDetails
    **/
   CumulusPalletXcmpQueueOutboundChannelDetails: {
     recipient: 'u32',
@@ -2527,13 +2530,13 @@
     lastIndex: 'u16'
   },
   /**
-   * Lookup324: cumulus_pallet_xcmp_queue::OutboundState
+   * Lookup326: cumulus_pallet_xcmp_queue::OutboundState
    **/
   CumulusPalletXcmpQueueOutboundState: {
     _enum: ['Ok', 'Suspended']
   },
   /**
-   * Lookup326: cumulus_pallet_xcmp_queue::QueueConfigData
+   * Lookup328: cumulus_pallet_xcmp_queue::QueueConfigData
    **/
   CumulusPalletXcmpQueueQueueConfigData: {
     suspendThreshold: 'u32',
@@ -2544,29 +2547,29 @@
     xcmpMaxIndividualWeight: 'u64'
   },
   /**
-   * Lookup328: cumulus_pallet_xcmp_queue::pallet::Error<T>
+   * Lookup330: cumulus_pallet_xcmp_queue::pallet::Error<T>
    **/
   CumulusPalletXcmpQueueError: {
     _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit']
   },
   /**
-   * Lookup329: pallet_xcm::pallet::Error<T>
+   * Lookup331: pallet_xcm::pallet::Error<T>
    **/
   PalletXcmError: {
     _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed']
   },
   /**
-   * Lookup330: cumulus_pallet_xcm::pallet::Error<T>
+   * Lookup332: cumulus_pallet_xcm::pallet::Error<T>
    **/
   CumulusPalletXcmError: 'Null',
   /**
-   * Lookup331: cumulus_pallet_dmp_queue::ConfigData
+   * Lookup333: cumulus_pallet_dmp_queue::ConfigData
    **/
   CumulusPalletDmpQueueConfigData: {
     maxIndividual: 'u64'
   },
   /**
-   * Lookup332: cumulus_pallet_dmp_queue::PageIndexData
+   * Lookup334: cumulus_pallet_dmp_queue::PageIndexData
    **/
   CumulusPalletDmpQueuePageIndexData: {
     beginUsed: 'u32',
@@ -2574,19 +2577,19 @@
     overweightCount: 'u64'
   },
   /**
-   * Lookup335: cumulus_pallet_dmp_queue::pallet::Error<T>
+   * Lookup337: cumulus_pallet_dmp_queue::pallet::Error<T>
    **/
   CumulusPalletDmpQueueError: {
     _enum: ['Unknown', 'OverLimit']
   },
   /**
-   * Lookup339: pallet_unique::Error<T>
+   * Lookup341: pallet_unique::Error<T>
    **/
   PalletUniqueError: {
     _enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument']
   },
   /**
-   * Lookup342: pallet_unq_scheduler::ScheduledV3<frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>
+   * Lookup344: pallet_unq_scheduler::ScheduledV3<frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>
    **/
   PalletUnqSchedulerScheduledV3: {
     maybeId: 'Option<[u8;16]>',
@@ -2596,7 +2599,7 @@
     origin: 'OpalRuntimeOriginCaller'
   },
   /**
-   * Lookup343: opal_runtime::OriginCaller
+   * Lookup345: opal_runtime::OriginCaller
    **/
   OpalRuntimeOriginCaller: {
     _enum: {
@@ -2705,7 +2708,7 @@
     }
   },
   /**
-   * Lookup344: frame_support::dispatch::RawOrigin<sp_core::crypto::AccountId32>
+   * Lookup346: frame_support::dispatch::RawOrigin<sp_core::crypto::AccountId32>
    **/
   FrameSupportDispatchRawOrigin: {
     _enum: {
@@ -2715,7 +2718,7 @@
     }
   },
   /**
-   * Lookup345: pallet_xcm::pallet::Origin
+   * Lookup347: pallet_xcm::pallet::Origin
    **/
   PalletXcmOrigin: {
     _enum: {
@@ -2724,7 +2727,7 @@
     }
   },
   /**
-   * Lookup346: cumulus_pallet_xcm::pallet::Origin
+   * Lookup348: cumulus_pallet_xcm::pallet::Origin
    **/
   CumulusPalletXcmOrigin: {
     _enum: {
@@ -2733,7 +2736,7 @@
     }
   },
   /**
-   * Lookup347: pallet_ethereum::RawOrigin
+   * Lookup349: pallet_ethereum::RawOrigin
    **/
   PalletEthereumRawOrigin: {
     _enum: {
@@ -2741,17 +2744,17 @@
     }
   },
   /**
-   * Lookup348: sp_core::Void
+   * Lookup350: sp_core::Void
    **/
   SpCoreVoid: 'Null',
   /**
-   * Lookup349: pallet_unq_scheduler::pallet::Error<T>
+   * Lookup351: pallet_unq_scheduler::pallet::Error<T>
    **/
   PalletUnqSchedulerError: {
     _enum: ['FailedToSchedule', 'NotFound', 'TargetBlockNumberInPast', 'RescheduleNoChange']
   },
   /**
-   * Lookup350: up_data_structs::Collection<sp_core::crypto::AccountId32>
+   * Lookup352: up_data_structs::Collection<sp_core::crypto::AccountId32>
    **/
   UpDataStructsCollection: {
     owner: 'AccountId32',
@@ -2765,7 +2768,7 @@
     externalCollection: 'bool'
   },
   /**
-   * Lookup351: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>
+   * Lookup353: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>
    **/
   UpDataStructsSponsorshipState: {
     _enum: {
@@ -2775,7 +2778,7 @@
     }
   },
   /**
-   * Lookup352: up_data_structs::Properties
+   * Lookup354: up_data_structs::Properties
    **/
   UpDataStructsProperties: {
     map: 'UpDataStructsPropertiesMapBoundedVec',
@@ -2783,15 +2786,15 @@
     spaceLimit: 'u32'
   },
   /**
-   * Lookup353: up_data_structs::PropertiesMap<frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup355: up_data_structs::PropertiesMap<frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   UpDataStructsPropertiesMapBoundedVec: 'BTreeMap<Bytes, Bytes>',
   /**
-   * Lookup358: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>
+   * Lookup360: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>
    **/
   UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap<Bytes, UpDataStructsPropertyPermission>',
   /**
-   * Lookup365: up_data_structs::CollectionStats
+   * Lookup367: up_data_structs::CollectionStats
    **/
   UpDataStructsCollectionStats: {
     created: 'u32',
@@ -2799,25 +2802,25 @@
     alive: 'u32'
   },
   /**
-   * Lookup366: up_data_structs::TokenChild
+   * Lookup368: up_data_structs::TokenChild
    **/
   UpDataStructsTokenChild: {
     token: 'u32',
     collection: 'u32'
   },
   /**
-   * Lookup367: PhantomType::up_data_structs<T>
+   * Lookup369: PhantomType::up_data_structs<T>
    **/
   PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild);0]',
   /**
-   * Lookup369: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup371: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsTokenData: {
     properties: 'Vec<UpDataStructsProperty>',
     owner: 'Option<PalletEvmAccountBasicCrossAccountIdRepr>'
   },
   /**
-   * Lookup371: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>
+   * Lookup373: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>
    **/
   UpDataStructsRpcCollection: {
     owner: 'AccountId32',
@@ -2833,7 +2836,7 @@
     readOnly: 'bool'
   },
   /**
-   * Lookup372: rmrk_traits::collection::CollectionInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>
+   * Lookup374: rmrk_traits::collection::CollectionInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>
    **/
   RmrkTraitsCollectionCollectionInfo: {
     issuer: 'AccountId32',
@@ -2843,7 +2846,7 @@
     nftsCount: 'u32'
   },
   /**
-   * Lookup373: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup375: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsNftNftInfo: {
     owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',
@@ -2853,14 +2856,14 @@
     pending: 'bool'
   },
   /**
-   * Lookup375: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>
+   * Lookup377: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>
    **/
   RmrkTraitsNftRoyaltyInfo: {
     recipient: 'AccountId32',
     amount: 'Permill'
   },
   /**
-   * Lookup376: rmrk_traits::resource::ResourceInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup378: rmrk_traits::resource::ResourceInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceResourceInfo: {
     id: 'u32',
@@ -2869,7 +2872,7 @@
     pendingRemoval: 'bool'
   },
   /**
-   * Lookup377: rmrk_traits::resource::ResourceTypes<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup379: rmrk_traits::resource::ResourceTypes<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceResourceTypes: {
     _enum: {
@@ -2879,14 +2882,14 @@
     }
   },
   /**
-   * Lookup378: rmrk_traits::property::PropertyInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup380: rmrk_traits::property::PropertyInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPropertyPropertyInfo: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup379: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, frame_support::storage::bounded_vec::BoundedVec<T, S>>
+   * Lookup381: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, frame_support::storage::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsBaseBaseInfo: {
     issuer: 'AccountId32',
@@ -2894,74 +2897,74 @@
     symbol: 'Bytes'
   },
   /**
-   * Lookup380: rmrk_traits::nft::NftChild
+   * Lookup382: rmrk_traits::nft::NftChild
    **/
   RmrkTraitsNftNftChild: {
     collectionId: 'u32',
     nftId: 'u32'
   },
   /**
-   * Lookup382: pallet_common::pallet::Error<T>
+   * Lookup384: pallet_common::pallet::Error<T>
    **/
   PalletCommonError: {
-    _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', 'NestingIsDisabled', 'OnlyOwnerAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'PropertyKeyIsTooLong', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey', 'CollectionIsExternal', 'CollectionIsInternal']
+    _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']
   },
   /**
-   * Lookup384: pallet_fungible::pallet::Error<T>
+   * Lookup386: pallet_fungible::pallet::Error<T>
    **/
   PalletFungibleError: {
     _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed']
   },
   /**
-   * Lookup385: pallet_refungible::ItemData
+   * Lookup387: pallet_refungible::ItemData
    **/
   PalletRefungibleItemData: {
     constData: 'Bytes'
   },
   /**
-   * Lookup389: pallet_refungible::pallet::Error<T>
+   * Lookup391: pallet_refungible::pallet::Error<T>
    **/
   PalletRefungibleError: {
     _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed']
   },
   /**
-   * Lookup390: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup392: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   PalletNonfungibleItemData: {
     owner: 'PalletEvmAccountBasicCrossAccountIdRepr'
   },
   /**
-   * Lookup392: pallet_nonfungible::pallet::Error<T>
+   * Lookup394: pallet_nonfungible::pallet::Error<T>
    **/
   PalletNonfungibleError: {
     _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren']
   },
   /**
-   * Lookup393: pallet_structure::pallet::Error<T>
+   * Lookup395: pallet_structure::pallet::Error<T>
    **/
   PalletStructureError: {
-    _enum: ['OuroborosDetected', 'DepthLimit', 'TokenNotFound']
+    _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound']
   },
   /**
-   * Lookup394: pallet_rmrk_core::pallet::Error<T>
+   * Lookup396: pallet_rmrk_core::pallet::Error<T>
    **/
   PalletRmrkCoreError: {
     _enum: ['CorruptedCollectionType', 'NftTypeEncodeError', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'ResourceNotPending']
   },
   /**
-   * Lookup396: pallet_rmrk_equip::pallet::Error<T>
+   * Lookup398: pallet_rmrk_equip::pallet::Error<T>
    **/
   PalletRmrkEquipError: {
     _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst']
   },
   /**
-   * Lookup399: pallet_evm::pallet::Error<T>
+   * Lookup401: pallet_evm::pallet::Error<T>
    **/
   PalletEvmError: {
     _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce']
   },
   /**
-   * Lookup402: fp_rpc::TransactionStatus
+   * Lookup404: fp_rpc::TransactionStatus
    **/
   FpRpcTransactionStatus: {
     transactionHash: 'H256',
@@ -2973,11 +2976,11 @@
     logsBloom: 'EthbloomBloom'
   },
   /**
-   * Lookup404: ethbloom::Bloom
+   * Lookup406: ethbloom::Bloom
    **/
   EthbloomBloom: '[u8;256]',
   /**
-   * Lookup406: ethereum::receipt::ReceiptV3
+   * Lookup408: ethereum::receipt::ReceiptV3
    **/
   EthereumReceiptReceiptV3: {
     _enum: {
@@ -2987,7 +2990,7 @@
     }
   },
   /**
-   * Lookup407: ethereum::receipt::EIP658ReceiptData
+   * Lookup409: ethereum::receipt::EIP658ReceiptData
    **/
   EthereumReceiptEip658ReceiptData: {
     statusCode: 'u8',
@@ -2996,7 +2999,7 @@
     logs: 'Vec<EthereumLog>'
   },
   /**
-   * Lookup408: ethereum::block::Block<ethereum::transaction::TransactionV2>
+   * Lookup410: ethereum::block::Block<ethereum::transaction::TransactionV2>
    **/
   EthereumBlock: {
     header: 'EthereumHeader',
@@ -3004,7 +3007,7 @@
     ommers: 'Vec<EthereumHeader>'
   },
   /**
-   * Lookup409: ethereum::header::Header
+   * Lookup411: ethereum::header::Header
    **/
   EthereumHeader: {
     parentHash: 'H256',
@@ -3024,41 +3027,41 @@
     nonce: 'EthereumTypesHashH64'
   },
   /**
-   * Lookup410: ethereum_types::hash::H64
+   * Lookup412: ethereum_types::hash::H64
    **/
   EthereumTypesHashH64: '[u8;8]',
   /**
-   * Lookup415: pallet_ethereum::pallet::Error<T>
+   * Lookup417: pallet_ethereum::pallet::Error<T>
    **/
   PalletEthereumError: {
     _enum: ['InvalidSignature', 'PreLogExists']
   },
   /**
-   * Lookup416: pallet_evm_coder_substrate::pallet::Error<T>
+   * Lookup418: pallet_evm_coder_substrate::pallet::Error<T>
    **/
   PalletEvmCoderSubstrateError: {
     _enum: ['OutOfGas', 'OutOfFund']
   },
   /**
-   * Lookup417: pallet_evm_contract_helpers::SponsoringModeT
+   * Lookup419: pallet_evm_contract_helpers::SponsoringModeT
    **/
   PalletEvmContractHelpersSponsoringModeT: {
     _enum: ['Disabled', 'Allowlisted', 'Generous']
   },
   /**
-   * Lookup419: pallet_evm_contract_helpers::pallet::Error<T>
+   * Lookup421: pallet_evm_contract_helpers::pallet::Error<T>
    **/
   PalletEvmContractHelpersError: {
     _enum: ['NoPermission']
   },
   /**
-   * Lookup420: pallet_evm_migration::pallet::Error<T>
+   * Lookup422: pallet_evm_migration::pallet::Error<T>
    **/
   PalletEvmMigrationError: {
     _enum: ['AccountNotEmpty', 'AccountIsNotMigrating']
   },
   /**
-   * Lookup422: sp_runtime::MultiSignature
+   * Lookup424: sp_runtime::MultiSignature
    **/
   SpRuntimeMultiSignature: {
     _enum: {
@@ -3068,43 +3071,43 @@
     }
   },
   /**
-   * Lookup423: sp_core::ed25519::Signature
+   * Lookup425: sp_core::ed25519::Signature
    **/
   SpCoreEd25519Signature: '[u8;64]',
   /**
-   * Lookup425: sp_core::sr25519::Signature
+   * Lookup427: sp_core::sr25519::Signature
    **/
   SpCoreSr25519Signature: '[u8;64]',
   /**
-   * Lookup426: sp_core::ecdsa::Signature
+   * Lookup428: sp_core::ecdsa::Signature
    **/
   SpCoreEcdsaSignature: '[u8;65]',
   /**
-   * Lookup429: frame_system::extensions::check_spec_version::CheckSpecVersion<T>
+   * Lookup431: frame_system::extensions::check_spec_version::CheckSpecVersion<T>
    **/
   FrameSystemExtensionsCheckSpecVersion: 'Null',
   /**
-   * Lookup430: frame_system::extensions::check_genesis::CheckGenesis<T>
+   * Lookup432: frame_system::extensions::check_genesis::CheckGenesis<T>
    **/
   FrameSystemExtensionsCheckGenesis: 'Null',
   /**
-   * Lookup433: frame_system::extensions::check_nonce::CheckNonce<T>
+   * Lookup435: frame_system::extensions::check_nonce::CheckNonce<T>
    **/
   FrameSystemExtensionsCheckNonce: 'Compact<u32>',
   /**
-   * Lookup434: frame_system::extensions::check_weight::CheckWeight<T>
+   * Lookup436: frame_system::extensions::check_weight::CheckWeight<T>
    **/
   FrameSystemExtensionsCheckWeight: 'Null',
   /**
-   * Lookup435: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>
+   * Lookup437: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>
    **/
   PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact<u128>',
   /**
-   * Lookup436: opal_runtime::Runtime
+   * Lookup438: opal_runtime::Runtime
    **/
   OpalRuntimeRuntime: 'Null',
   /**
-   * Lookup437: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>
+   * Lookup439: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>
    **/
   PalletEthereumFakeTransactionFinalizer: 'Null'
 };
modifiedtests/src/interfaces/registry.tsdiffbeforeafterboth
--- a/tests/src/interfaces/registry.ts
+++ b/tests/src/interfaces/registry.ts
@@ -1,7 +1,7 @@
 // Auto-generated via `yarn polkadot-types-from-defs`, do not edit
 /* eslint-disable */
 
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUnqSchedulerCall, PalletUnqSchedulerError, PalletUnqSchedulerEvent, PalletUnqSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingRule, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUnqSchedulerCall, PalletUnqSchedulerError, PalletUnqSchedulerEvent, PalletUnqSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
 
 declare module '@polkadot/types/types/registry' {
   export interface InterfaceTypes {
@@ -196,7 +196,8 @@
     UpDataStructsCreateNftExData: UpDataStructsCreateNftExData;
     UpDataStructsCreateReFungibleData: UpDataStructsCreateReFungibleData;
     UpDataStructsCreateRefungibleExData: UpDataStructsCreateRefungibleExData;
-    UpDataStructsNestingRule: UpDataStructsNestingRule;
+    UpDataStructsNestingPermissions: UpDataStructsNestingPermissions;
+    UpDataStructsOwnerRestrictedSet: UpDataStructsOwnerRestrictedSet;
     UpDataStructsProperties: UpDataStructsProperties;
     UpDataStructsPropertiesMapBoundedVec: UpDataStructsPropertiesMapBoundedVec;
     UpDataStructsPropertiesMapPropertyPermission: UpDataStructsPropertiesMapPropertyPermission;
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -1556,38 +1556,40 @@
   export interface UpDataStructsCollectionPermissions extends Struct {
     readonly access: Option<UpDataStructsAccessMode>;
     readonly mintMode: Option<bool>;
-    readonly nesting: Option<UpDataStructsNestingRule>;
+    readonly nesting: Option<UpDataStructsNestingPermissions>;
   }
 
-  /** @name UpDataStructsNestingRule (169) */
-  export interface UpDataStructsNestingRule extends Enum {
-    readonly isDisabled: boolean;
-    readonly isOwner: boolean;
-    readonly isOwnerRestricted: boolean;
-    readonly asOwnerRestricted: BTreeSet<u32>;
-    readonly type: 'Disabled' | 'Owner' | 'OwnerRestricted';
+  /** @name UpDataStructsNestingPermissions (169) */
+  export interface UpDataStructsNestingPermissions extends Struct {
+    readonly tokenOwner: bool;
+    readonly admin: bool;
+    readonly restricted: Option<UpDataStructsOwnerRestrictedSet>;
+    readonly permissive: bool;
   }
 
-  /** @name UpDataStructsPropertyKeyPermission (175) */
+  /** @name UpDataStructsOwnerRestrictedSet (171) */
+  export interface UpDataStructsOwnerRestrictedSet extends BTreeSet<u32> {}
+
+  /** @name UpDataStructsPropertyKeyPermission (177) */
   export interface UpDataStructsPropertyKeyPermission extends Struct {
     readonly key: Bytes;
     readonly permission: UpDataStructsPropertyPermission;
   }
 
-  /** @name UpDataStructsPropertyPermission (177) */
+  /** @name UpDataStructsPropertyPermission (179) */
   export interface UpDataStructsPropertyPermission extends Struct {
     readonly mutable: bool;
     readonly collectionAdmin: bool;
     readonly tokenOwner: bool;
   }
 
-  /** @name UpDataStructsProperty (180) */
+  /** @name UpDataStructsProperty (182) */
   export interface UpDataStructsProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name PalletEvmAccountBasicCrossAccountIdRepr (183) */
+  /** @name PalletEvmAccountBasicCrossAccountIdRepr (185) */
   export interface PalletEvmAccountBasicCrossAccountIdRepr extends Enum {
     readonly isSubstrate: boolean;
     readonly asSubstrate: AccountId32;
@@ -1596,7 +1598,7 @@
     readonly type: 'Substrate' | 'Ethereum';
   }
 
-  /** @name UpDataStructsCreateItemData (185) */
+  /** @name UpDataStructsCreateItemData (187) */
   export interface UpDataStructsCreateItemData extends Enum {
     readonly isNft: boolean;
     readonly asNft: UpDataStructsCreateNftData;
@@ -1607,23 +1609,23 @@
     readonly type: 'Nft' | 'Fungible' | 'ReFungible';
   }
 
-  /** @name UpDataStructsCreateNftData (186) */
+  /** @name UpDataStructsCreateNftData (188) */
   export interface UpDataStructsCreateNftData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateFungibleData (187) */
+  /** @name UpDataStructsCreateFungibleData (189) */
   export interface UpDataStructsCreateFungibleData extends Struct {
     readonly value: u128;
   }
 
-  /** @name UpDataStructsCreateReFungibleData (188) */
+  /** @name UpDataStructsCreateReFungibleData (190) */
   export interface UpDataStructsCreateReFungibleData extends Struct {
     readonly constData: Bytes;
     readonly pieces: u128;
   }
 
-  /** @name UpDataStructsCreateItemExData (193) */
+  /** @name UpDataStructsCreateItemExData (195) */
   export interface UpDataStructsCreateItemExData extends Enum {
     readonly isNft: boolean;
     readonly asNft: Vec<UpDataStructsCreateNftExData>;
@@ -1636,19 +1638,19 @@
     readonly type: 'Nft' | 'Fungible' | 'RefungibleMultipleItems' | 'RefungibleMultipleOwners';
   }
 
-  /** @name UpDataStructsCreateNftExData (195) */
+  /** @name UpDataStructsCreateNftExData (197) */
   export interface UpDataStructsCreateNftExData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name UpDataStructsCreateRefungibleExData (202) */
+  /** @name UpDataStructsCreateRefungibleExData (204) */
   export interface UpDataStructsCreateRefungibleExData extends Struct {
     readonly constData: Bytes;
     readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
   }
 
-  /** @name PalletUnqSchedulerCall (204) */
+  /** @name PalletUnqSchedulerCall (206) */
   export interface PalletUnqSchedulerCall extends Enum {
     readonly isScheduleNamed: boolean;
     readonly asScheduleNamed: {
@@ -1673,7 +1675,7 @@
     readonly type: 'ScheduleNamed' | 'CancelNamed' | 'ScheduleNamedAfter';
   }
 
-  /** @name FrameSupportScheduleMaybeHashed (206) */
+  /** @name FrameSupportScheduleMaybeHashed (208) */
   export interface FrameSupportScheduleMaybeHashed extends Enum {
     readonly isValue: boolean;
     readonly asValue: Call;
@@ -1682,13 +1684,13 @@
     readonly type: 'Value' | 'Hash';
   }
 
-  /** @name PalletTemplateTransactionPaymentCall (207) */
+  /** @name PalletTemplateTransactionPaymentCall (209) */
   export type PalletTemplateTransactionPaymentCall = Null;
 
-  /** @name PalletStructureCall (208) */
+  /** @name PalletStructureCall (210) */
   export type PalletStructureCall = Null;
 
-  /** @name PalletRmrkCoreCall (209) */
+  /** @name PalletRmrkCoreCall (211) */
   export interface PalletRmrkCoreCall extends Enum {
     readonly isCreateCollection: boolean;
     readonly asCreateCollection: {
@@ -1793,7 +1795,7 @@
     readonly type: 'CreateCollection' | 'DestroyCollection' | 'ChangeCollectionIssuer' | 'LockCollection' | 'MintNft' | 'BurnNft' | 'Send' | 'AcceptNft' | 'RejectNft' | 'AcceptResource' | 'AcceptResourceRemoval' | 'SetProperty' | 'SetPriority' | 'AddBasicResource' | 'AddComposableResource' | 'AddSlotResource' | 'RemoveResource';
   }
 
-  /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (213) */
+  /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (215) */
   export interface RmrkTraitsNftAccountIdOrCollectionNftTuple extends Enum {
     readonly isAccountId: boolean;
     readonly asAccountId: AccountId32;
@@ -1802,7 +1804,7 @@
     readonly type: 'AccountId' | 'CollectionAndNftTuple';
   }
 
-  /** @name RmrkTraitsResourceBasicResource (217) */
+  /** @name RmrkTraitsResourceBasicResource (219) */
   export interface RmrkTraitsResourceBasicResource extends Struct {
     readonly src: Option<Bytes>;
     readonly metadata: Option<Bytes>;
@@ -1810,7 +1812,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name RmrkTraitsResourceComposableResource (220) */
+  /** @name RmrkTraitsResourceComposableResource (222) */
   export interface RmrkTraitsResourceComposableResource extends Struct {
     readonly parts: Vec<u32>;
     readonly base: u32;
@@ -1820,7 +1822,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name RmrkTraitsResourceSlotResource (222) */
+  /** @name RmrkTraitsResourceSlotResource (224) */
   export interface RmrkTraitsResourceSlotResource extends Struct {
     readonly base: u32;
     readonly src: Option<Bytes>;
@@ -1830,7 +1832,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name PalletRmrkEquipCall (223) */
+  /** @name PalletRmrkEquipCall (225) */
   export interface PalletRmrkEquipCall extends Enum {
     readonly isCreateBase: boolean;
     readonly asCreateBase: {
@@ -1846,7 +1848,7 @@
     readonly type: 'CreateBase' | 'ThemeAdd';
   }
 
-  /** @name RmrkTraitsPartPartType (225) */
+  /** @name RmrkTraitsPartPartType (227) */
   export interface RmrkTraitsPartPartType extends Enum {
     readonly isFixedPart: boolean;
     readonly asFixedPart: RmrkTraitsPartFixedPart;
@@ -1855,14 +1857,14 @@
     readonly type: 'FixedPart' | 'SlotPart';
   }
 
-  /** @name RmrkTraitsPartFixedPart (227) */
+  /** @name RmrkTraitsPartFixedPart (229) */
   export interface RmrkTraitsPartFixedPart extends Struct {
     readonly id: u32;
     readonly z: u32;
     readonly src: Bytes;
   }
 
-  /** @name RmrkTraitsPartSlotPart (228) */
+  /** @name RmrkTraitsPartSlotPart (230) */
   export interface RmrkTraitsPartSlotPart extends Struct {
     readonly id: u32;
     readonly equippable: RmrkTraitsPartEquippableList;
@@ -1870,7 +1872,7 @@
     readonly z: u32;
   }
 
-  /** @name RmrkTraitsPartEquippableList (229) */
+  /** @name RmrkTraitsPartEquippableList (231) */
   export interface RmrkTraitsPartEquippableList extends Enum {
     readonly isAll: boolean;
     readonly isEmpty: boolean;
@@ -1879,20 +1881,20 @@
     readonly type: 'All' | 'Empty' | 'Custom';
   }
 
-  /** @name RmrkTraitsTheme (231) */
+  /** @name RmrkTraitsTheme (233) */
   export interface RmrkTraitsTheme extends Struct {
     readonly name: Bytes;
     readonly properties: Vec<RmrkTraitsThemeThemeProperty>;
     readonly inherit: bool;
   }
 
-  /** @name RmrkTraitsThemeThemeProperty (233) */
+  /** @name RmrkTraitsThemeThemeProperty (235) */
   export interface RmrkTraitsThemeThemeProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name PalletEvmCall (234) */
+  /** @name PalletEvmCall (236) */
   export interface PalletEvmCall extends Enum {
     readonly isWithdraw: boolean;
     readonly asWithdraw: {
@@ -1937,7 +1939,7 @@
     readonly type: 'Withdraw' | 'Call' | 'Create' | 'Create2';
   }
 
-  /** @name PalletEthereumCall (240) */
+  /** @name PalletEthereumCall (242) */
   export interface PalletEthereumCall extends Enum {
     readonly isTransact: boolean;
     readonly asTransact: {
@@ -1946,7 +1948,7 @@
     readonly type: 'Transact';
   }
 
-  /** @name EthereumTransactionTransactionV2 (241) */
+  /** @name EthereumTransactionTransactionV2 (243) */
   export interface EthereumTransactionTransactionV2 extends Enum {
     readonly isLegacy: boolean;
     readonly asLegacy: EthereumTransactionLegacyTransaction;
@@ -1957,7 +1959,7 @@
     readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
   }
 
-  /** @name EthereumTransactionLegacyTransaction (242) */
+  /** @name EthereumTransactionLegacyTransaction (244) */
   export interface EthereumTransactionLegacyTransaction extends Struct {
     readonly nonce: U256;
     readonly gasPrice: U256;
@@ -1968,7 +1970,7 @@
     readonly signature: EthereumTransactionTransactionSignature;
   }
 
-  /** @name EthereumTransactionTransactionAction (243) */
+  /** @name EthereumTransactionTransactionAction (245) */
   export interface EthereumTransactionTransactionAction extends Enum {
     readonly isCall: boolean;
     readonly asCall: H160;
@@ -1976,14 +1978,14 @@
     readonly type: 'Call' | 'Create';
   }
 
-  /** @name EthereumTransactionTransactionSignature (244) */
+  /** @name EthereumTransactionTransactionSignature (246) */
   export interface EthereumTransactionTransactionSignature extends Struct {
     readonly v: u64;
     readonly r: H256;
     readonly s: H256;
   }
 
-  /** @name EthereumTransactionEip2930Transaction (246) */
+  /** @name EthereumTransactionEip2930Transaction (248) */
   export interface EthereumTransactionEip2930Transaction extends Struct {
     readonly chainId: u64;
     readonly nonce: U256;
@@ -1998,13 +2000,13 @@
     readonly s: H256;
   }
 
-  /** @name EthereumTransactionAccessListItem (248) */
+  /** @name EthereumTransactionAccessListItem (250) */
   export interface EthereumTransactionAccessListItem extends Struct {
     readonly address: H160;
     readonly storageKeys: Vec<H256>;
   }
 
-  /** @name EthereumTransactionEip1559Transaction (249) */
+  /** @name EthereumTransactionEip1559Transaction (251) */
   export interface EthereumTransactionEip1559Transaction extends Struct {
     readonly chainId: u64;
     readonly nonce: U256;
@@ -2020,7 +2022,7 @@
     readonly s: H256;
   }
 
-  /** @name PalletEvmMigrationCall (250) */
+  /** @name PalletEvmMigrationCall (252) */
   export interface PalletEvmMigrationCall extends Enum {
     readonly isBegin: boolean;
     readonly asBegin: {
@@ -2039,7 +2041,7 @@
     readonly type: 'Begin' | 'SetData' | 'Finish';
   }
 
-  /** @name PalletSudoEvent (253) */
+  /** @name PalletSudoEvent (255) */
   export interface PalletSudoEvent extends Enum {
     readonly isSudid: boolean;
     readonly asSudid: {
@@ -2056,7 +2058,7 @@
     readonly type: 'Sudid' | 'KeyChanged' | 'SudoAsDone';
   }
 
-  /** @name SpRuntimeDispatchError (255) */
+  /** @name SpRuntimeDispatchError (257) */
   export interface SpRuntimeDispatchError extends Enum {
     readonly isOther: boolean;
     readonly isCannotLookup: boolean;
@@ -2075,13 +2077,13 @@
     readonly type: 'Other' | 'CannotLookup' | 'BadOrigin' | 'Module' | 'ConsumerRemaining' | 'NoProviders' | 'TooManyConsumers' | 'Token' | 'Arithmetic' | 'Transactional';
   }
 
-  /** @name SpRuntimeModuleError (256) */
+  /** @name SpRuntimeModuleError (258) */
   export interface SpRuntimeModuleError extends Struct {
     readonly index: u8;
     readonly error: U8aFixed;
   }
 
-  /** @name SpRuntimeTokenError (257) */
+  /** @name SpRuntimeTokenError (259) */
   export interface SpRuntimeTokenError extends Enum {
     readonly isNoFunds: boolean;
     readonly isWouldDie: boolean;
@@ -2093,7 +2095,7 @@
     readonly type: 'NoFunds' | 'WouldDie' | 'BelowMinimum' | 'CannotCreate' | 'UnknownAsset' | 'Frozen' | 'Unsupported';
   }
 
-  /** @name SpRuntimeArithmeticError (258) */
+  /** @name SpRuntimeArithmeticError (260) */
   export interface SpRuntimeArithmeticError extends Enum {
     readonly isUnderflow: boolean;
     readonly isOverflow: boolean;
@@ -2101,20 +2103,20 @@
     readonly type: 'Underflow' | 'Overflow' | 'DivisionByZero';
   }
 
-  /** @name SpRuntimeTransactionalError (259) */
+  /** @name SpRuntimeTransactionalError (261) */
   export interface SpRuntimeTransactionalError extends Enum {
     readonly isLimitReached: boolean;
     readonly isNoLayer: boolean;
     readonly type: 'LimitReached' | 'NoLayer';
   }
 
-  /** @name PalletSudoError (260) */
+  /** @name PalletSudoError (262) */
   export interface PalletSudoError extends Enum {
     readonly isRequireSudo: boolean;
     readonly type: 'RequireSudo';
   }
 
-  /** @name FrameSystemAccountInfo (261) */
+  /** @name FrameSystemAccountInfo (263) */
   export interface FrameSystemAccountInfo extends Struct {
     readonly nonce: u32;
     readonly consumers: u32;
@@ -2123,19 +2125,19 @@
     readonly data: PalletBalancesAccountData;
   }
 
-  /** @name FrameSupportWeightsPerDispatchClassU64 (262) */
+  /** @name FrameSupportWeightsPerDispatchClassU64 (264) */
   export interface FrameSupportWeightsPerDispatchClassU64 extends Struct {
     readonly normal: u64;
     readonly operational: u64;
     readonly mandatory: u64;
   }
 
-  /** @name SpRuntimeDigest (263) */
+  /** @name SpRuntimeDigest (265) */
   export interface SpRuntimeDigest extends Struct {
     readonly logs: Vec<SpRuntimeDigestDigestItem>;
   }
 
-  /** @name SpRuntimeDigestDigestItem (265) */
+  /** @name SpRuntimeDigestDigestItem (267) */
   export interface SpRuntimeDigestDigestItem extends Enum {
     readonly isOther: boolean;
     readonly asOther: Bytes;
@@ -2149,14 +2151,14 @@
     readonly type: 'Other' | 'Consensus' | 'Seal' | 'PreRuntime' | 'RuntimeEnvironmentUpdated';
   }
 
-  /** @name FrameSystemEventRecord (267) */
+  /** @name FrameSystemEventRecord (269) */
   export interface FrameSystemEventRecord extends Struct {
     readonly phase: FrameSystemPhase;
     readonly event: Event;
     readonly topics: Vec<H256>;
   }
 
-  /** @name FrameSystemEvent (269) */
+  /** @name FrameSystemEvent (271) */
   export interface FrameSystemEvent extends Enum {
     readonly isExtrinsicSuccess: boolean;
     readonly asExtrinsicSuccess: {
@@ -2184,14 +2186,14 @@
     readonly type: 'ExtrinsicSuccess' | 'ExtrinsicFailed' | 'CodeUpdated' | 'NewAccount' | 'KilledAccount' | 'Remarked';
   }
 
-  /** @name FrameSupportWeightsDispatchInfo (270) */
+  /** @name FrameSupportWeightsDispatchInfo (272) */
   export interface FrameSupportWeightsDispatchInfo extends Struct {
     readonly weight: u64;
     readonly class: FrameSupportWeightsDispatchClass;
     readonly paysFee: FrameSupportWeightsPays;
   }
 
-  /** @name FrameSupportWeightsDispatchClass (271) */
+  /** @name FrameSupportWeightsDispatchClass (273) */
   export interface FrameSupportWeightsDispatchClass extends Enum {
     readonly isNormal: boolean;
     readonly isOperational: boolean;
@@ -2199,14 +2201,14 @@
     readonly type: 'Normal' | 'Operational' | 'Mandatory';
   }
 
-  /** @name FrameSupportWeightsPays (272) */
+  /** @name FrameSupportWeightsPays (274) */
   export interface FrameSupportWeightsPays extends Enum {
     readonly isYes: boolean;
     readonly isNo: boolean;
     readonly type: 'Yes' | 'No';
   }
 
-  /** @name OrmlVestingModuleEvent (273) */
+  /** @name OrmlVestingModuleEvent (275) */
   export interface OrmlVestingModuleEvent extends Enum {
     readonly isVestingScheduleAdded: boolean;
     readonly asVestingScheduleAdded: {
@@ -2226,7 +2228,7 @@
     readonly type: 'VestingScheduleAdded' | 'Claimed' | 'VestingSchedulesUpdated';
   }
 
-  /** @name CumulusPalletXcmpQueueEvent (274) */
+  /** @name CumulusPalletXcmpQueueEvent (276) */
   export interface CumulusPalletXcmpQueueEvent extends Enum {
     readonly isSuccess: boolean;
     readonly asSuccess: Option<H256>;
@@ -2247,7 +2249,7 @@
     readonly type: 'Success' | 'Fail' | 'BadVersion' | 'BadFormat' | 'UpwardMessageSent' | 'XcmpMessageSent' | 'OverweightEnqueued' | 'OverweightServiced';
   }
 
-  /** @name PalletXcmEvent (275) */
+  /** @name PalletXcmEvent (277) */
   export interface PalletXcmEvent extends Enum {
     readonly isAttempted: boolean;
     readonly asAttempted: XcmV2TraitsOutcome;
@@ -2284,7 +2286,7 @@
     readonly type: 'Attempted' | 'Sent' | 'UnexpectedResponse' | 'ResponseReady' | 'Notified' | 'NotifyOverweight' | 'NotifyDispatchError' | 'NotifyDecodeFailed' | 'InvalidResponder' | 'InvalidResponderVersion' | 'ResponseTaken' | 'AssetsTrapped' | 'VersionChangeNotified' | 'SupportedVersionChanged' | 'NotifyTargetSendFail' | 'NotifyTargetMigrationFail';
   }
 
-  /** @name XcmV2TraitsOutcome (276) */
+  /** @name XcmV2TraitsOutcome (278) */
   export interface XcmV2TraitsOutcome extends Enum {
     readonly isComplete: boolean;
     readonly asComplete: u64;
@@ -2295,7 +2297,7 @@
     readonly type: 'Complete' | 'Incomplete' | 'Error';
   }
 
-  /** @name CumulusPalletXcmEvent (278) */
+  /** @name CumulusPalletXcmEvent (280) */
   export interface CumulusPalletXcmEvent extends Enum {
     readonly isInvalidFormat: boolean;
     readonly asInvalidFormat: U8aFixed;
@@ -2306,7 +2308,7 @@
     readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward';
   }
 
-  /** @name CumulusPalletDmpQueueEvent (279) */
+  /** @name CumulusPalletDmpQueueEvent (281) */
   export interface CumulusPalletDmpQueueEvent extends Enum {
     readonly isInvalidFormat: boolean;
     readonly asInvalidFormat: U8aFixed;
@@ -2323,7 +2325,7 @@
     readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward' | 'WeightExhausted' | 'OverweightEnqueued' | 'OverweightServiced';
   }
 
-  /** @name PalletUniqueRawEvent (280) */
+  /** @name PalletUniqueRawEvent (282) */
   export interface PalletUniqueRawEvent extends Enum {
     readonly isCollectionSponsorRemoved: boolean;
     readonly asCollectionSponsorRemoved: u32;
@@ -2348,7 +2350,7 @@
     readonly type: 'CollectionSponsorRemoved' | 'CollectionAdminAdded' | 'CollectionOwnedChanged' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionAdminRemoved' | 'AllowListAddressRemoved' | 'AllowListAddressAdded' | 'CollectionLimitSet' | 'CollectionPermissionSet';
   }
 
-  /** @name PalletUnqSchedulerEvent (281) */
+  /** @name PalletUnqSchedulerEvent (283) */
   export interface PalletUnqSchedulerEvent extends Enum {
     readonly isScheduled: boolean;
     readonly asScheduled: {
@@ -2375,14 +2377,14 @@
     readonly type: 'Scheduled' | 'Canceled' | 'Dispatched' | 'CallLookupFailed';
   }
 
-  /** @name FrameSupportScheduleLookupError (283) */
+  /** @name FrameSupportScheduleLookupError (285) */
   export interface FrameSupportScheduleLookupError extends Enum {
     readonly isUnknown: boolean;
     readonly isBadFormat: boolean;
     readonly type: 'Unknown' | 'BadFormat';
   }
 
-  /** @name PalletCommonEvent (284) */
+  /** @name PalletCommonEvent (286) */
   export interface PalletCommonEvent extends Enum {
     readonly isCollectionCreated: boolean;
     readonly asCollectionCreated: ITuple<[u32, u8, AccountId32]>;
@@ -2409,14 +2411,14 @@
     readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet';
   }
 
-  /** @name PalletStructureEvent (285) */
+  /** @name PalletStructureEvent (287) */
   export interface PalletStructureEvent extends Enum {
     readonly isExecuted: boolean;
     readonly asExecuted: Result<Null, SpRuntimeDispatchError>;
     readonly type: 'Executed';
   }
 
-  /** @name PalletRmrkCoreEvent (286) */
+  /** @name PalletRmrkCoreEvent (288) */
   export interface PalletRmrkCoreEvent extends Enum {
     readonly isCollectionCreated: boolean;
     readonly asCollectionCreated: {
@@ -2506,7 +2508,7 @@
     readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'IssuerChanged' | 'CollectionLocked' | 'NftMinted' | 'NftBurned' | 'NftSent' | 'NftAccepted' | 'NftRejected' | 'PropertySet' | 'ResourceAdded' | 'ResourceRemoval' | 'ResourceAccepted' | 'ResourceRemovalAccepted' | 'PrioritySet';
   }
 
-  /** @name PalletRmrkEquipEvent (287) */
+  /** @name PalletRmrkEquipEvent (289) */
   export interface PalletRmrkEquipEvent extends Enum {
     readonly isBaseCreated: boolean;
     readonly asBaseCreated: {
@@ -2516,7 +2518,7 @@
     readonly type: 'BaseCreated';
   }
 
-  /** @name PalletEvmEvent (288) */
+  /** @name PalletEvmEvent (290) */
   export interface PalletEvmEvent extends Enum {
     readonly isLog: boolean;
     readonly asLog: EthereumLog;
@@ -2535,21 +2537,21 @@
     readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed' | 'BalanceDeposit' | 'BalanceWithdraw';
   }
 
-  /** @name EthereumLog (289) */
+  /** @name EthereumLog (291) */
   export interface EthereumLog extends Struct {
     readonly address: H160;
     readonly topics: Vec<H256>;
     readonly data: Bytes;
   }
 
-  /** @name PalletEthereumEvent (290) */
+  /** @name PalletEthereumEvent (292) */
   export interface PalletEthereumEvent extends Enum {
     readonly isExecuted: boolean;
     readonly asExecuted: ITuple<[H160, H160, H256, EvmCoreErrorExitReason]>;
     readonly type: 'Executed';
   }
 
-  /** @name EvmCoreErrorExitReason (291) */
+  /** @name EvmCoreErrorExitReason (293) */
   export interface EvmCoreErrorExitReason extends Enum {
     readonly isSucceed: boolean;
     readonly asSucceed: EvmCoreErrorExitSucceed;
@@ -2562,7 +2564,7 @@
     readonly type: 'Succeed' | 'Error' | 'Revert' | 'Fatal';
   }
 
-  /** @name EvmCoreErrorExitSucceed (292) */
+  /** @name EvmCoreErrorExitSucceed (294) */
   export interface EvmCoreErrorExitSucceed extends Enum {
     readonly isStopped: boolean;
     readonly isReturned: boolean;
@@ -2570,7 +2572,7 @@
     readonly type: 'Stopped' | 'Returned' | 'Suicided';
   }
 
-  /** @name EvmCoreErrorExitError (293) */
+  /** @name EvmCoreErrorExitError (295) */
   export interface EvmCoreErrorExitError extends Enum {
     readonly isStackUnderflow: boolean;
     readonly isStackOverflow: boolean;
@@ -2591,13 +2593,13 @@
     readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode';
   }
 
-  /** @name EvmCoreErrorExitRevert (296) */
+  /** @name EvmCoreErrorExitRevert (298) */
   export interface EvmCoreErrorExitRevert extends Enum {
     readonly isReverted: boolean;
     readonly type: 'Reverted';
   }
 
-  /** @name EvmCoreErrorExitFatal (297) */
+  /** @name EvmCoreErrorExitFatal (299) */
   export interface EvmCoreErrorExitFatal extends Enum {
     readonly isNotSupported: boolean;
     readonly isUnhandledInterrupt: boolean;
@@ -2608,7 +2610,7 @@
     readonly type: 'NotSupported' | 'UnhandledInterrupt' | 'CallErrorAsFatal' | 'Other';
   }
 
-  /** @name FrameSystemPhase (298) */
+  /** @name FrameSystemPhase (300) */
   export interface FrameSystemPhase extends Enum {
     readonly isApplyExtrinsic: boolean;
     readonly asApplyExtrinsic: u32;
@@ -2617,27 +2619,27 @@
     readonly type: 'ApplyExtrinsic' | 'Finalization' | 'Initialization';
   }
 
-  /** @name FrameSystemLastRuntimeUpgradeInfo (300) */
+  /** @name FrameSystemLastRuntimeUpgradeInfo (302) */
   export interface FrameSystemLastRuntimeUpgradeInfo extends Struct {
     readonly specVersion: Compact<u32>;
     readonly specName: Text;
   }
 
-  /** @name FrameSystemLimitsBlockWeights (301) */
+  /** @name FrameSystemLimitsBlockWeights (303) */
   export interface FrameSystemLimitsBlockWeights extends Struct {
     readonly baseBlock: u64;
     readonly maxBlock: u64;
     readonly perClass: FrameSupportWeightsPerDispatchClassWeightsPerClass;
   }
 
-  /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (302) */
+  /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (304) */
   export interface FrameSupportWeightsPerDispatchClassWeightsPerClass extends Struct {
     readonly normal: FrameSystemLimitsWeightsPerClass;
     readonly operational: FrameSystemLimitsWeightsPerClass;
     readonly mandatory: FrameSystemLimitsWeightsPerClass;
   }
 
-  /** @name FrameSystemLimitsWeightsPerClass (303) */
+  /** @name FrameSystemLimitsWeightsPerClass (305) */
   export interface FrameSystemLimitsWeightsPerClass extends Struct {
     readonly baseExtrinsic: u64;
     readonly maxExtrinsic: Option<u64>;
@@ -2645,25 +2647,25 @@
     readonly reserved: Option<u64>;
   }
 
-  /** @name FrameSystemLimitsBlockLength (305) */
+  /** @name FrameSystemLimitsBlockLength (307) */
   export interface FrameSystemLimitsBlockLength extends Struct {
     readonly max: FrameSupportWeightsPerDispatchClassU32;
   }
 
-  /** @name FrameSupportWeightsPerDispatchClassU32 (306) */
+  /** @name FrameSupportWeightsPerDispatchClassU32 (308) */
   export interface FrameSupportWeightsPerDispatchClassU32 extends Struct {
     readonly normal: u32;
     readonly operational: u32;
     readonly mandatory: u32;
   }
 
-  /** @name FrameSupportWeightsRuntimeDbWeight (307) */
+  /** @name FrameSupportWeightsRuntimeDbWeight (309) */
   export interface FrameSupportWeightsRuntimeDbWeight extends Struct {
     readonly read: u64;
     readonly write: u64;
   }
 
-  /** @name SpVersionRuntimeVersion (308) */
+  /** @name SpVersionRuntimeVersion (310) */
   export interface SpVersionRuntimeVersion extends Struct {
     readonly specName: Text;
     readonly implName: Text;
@@ -2675,7 +2677,7 @@
     readonly stateVersion: u8;
   }
 
-  /** @name FrameSystemError (312) */
+  /** @name FrameSystemError (314) */
   export interface FrameSystemError extends Enum {
     readonly isInvalidSpecName: boolean;
     readonly isSpecVersionNeedsToIncrease: boolean;
@@ -2686,7 +2688,7 @@
     readonly type: 'InvalidSpecName' | 'SpecVersionNeedsToIncrease' | 'FailedToExtractRuntimeVersion' | 'NonDefaultComposite' | 'NonZeroRefCount' | 'CallFiltered';
   }
 
-  /** @name OrmlVestingModuleError (314) */
+  /** @name OrmlVestingModuleError (316) */
   export interface OrmlVestingModuleError extends Enum {
     readonly isZeroVestingPeriod: boolean;
     readonly isZeroVestingPeriodCount: boolean;
@@ -2697,21 +2699,21 @@
     readonly type: 'ZeroVestingPeriod' | 'ZeroVestingPeriodCount' | 'InsufficientBalanceToLock' | 'TooManyVestingSchedules' | 'AmountLow' | 'MaxVestingSchedulesExceeded';
   }
 
-  /** @name CumulusPalletXcmpQueueInboundChannelDetails (316) */
+  /** @name CumulusPalletXcmpQueueInboundChannelDetails (318) */
   export interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct {
     readonly sender: u32;
     readonly state: CumulusPalletXcmpQueueInboundState;
     readonly messageMetadata: Vec<ITuple<[u32, PolkadotParachainPrimitivesXcmpMessageFormat]>>;
   }
 
-  /** @name CumulusPalletXcmpQueueInboundState (317) */
+  /** @name CumulusPalletXcmpQueueInboundState (319) */
   export interface CumulusPalletXcmpQueueInboundState extends Enum {
     readonly isOk: boolean;
     readonly isSuspended: boolean;
     readonly type: 'Ok' | 'Suspended';
   }
 
-  /** @name PolkadotParachainPrimitivesXcmpMessageFormat (320) */
+  /** @name PolkadotParachainPrimitivesXcmpMessageFormat (322) */
   export interface PolkadotParachainPrimitivesXcmpMessageFormat extends Enum {
     readonly isConcatenatedVersionedXcm: boolean;
     readonly isConcatenatedEncodedBlob: boolean;
@@ -2719,7 +2721,7 @@
     readonly type: 'ConcatenatedVersionedXcm' | 'ConcatenatedEncodedBlob' | 'Signals';
   }
 
-  /** @name CumulusPalletXcmpQueueOutboundChannelDetails (323) */
+  /** @name CumulusPalletXcmpQueueOutboundChannelDetails (325) */
   export interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct {
     readonly recipient: u32;
     readonly state: CumulusPalletXcmpQueueOutboundState;
@@ -2728,14 +2730,14 @@
     readonly lastIndex: u16;
   }
 
-  /** @name CumulusPalletXcmpQueueOutboundState (324) */
+  /** @name CumulusPalletXcmpQueueOutboundState (326) */
   export interface CumulusPalletXcmpQueueOutboundState extends Enum {
     readonly isOk: boolean;
     readonly isSuspended: boolean;
     readonly type: 'Ok' | 'Suspended';
   }
 
-  /** @name CumulusPalletXcmpQueueQueueConfigData (326) */
+  /** @name CumulusPalletXcmpQueueQueueConfigData (328) */
   export interface CumulusPalletXcmpQueueQueueConfigData extends Struct {
     readonly suspendThreshold: u32;
     readonly dropThreshold: u32;
@@ -2745,7 +2747,7 @@
     readonly xcmpMaxIndividualWeight: u64;
   }
 
-  /** @name CumulusPalletXcmpQueueError (328) */
+  /** @name CumulusPalletXcmpQueueError (330) */
   export interface CumulusPalletXcmpQueueError extends Enum {
     readonly isFailedToSend: boolean;
     readonly isBadXcmOrigin: boolean;
@@ -2755,7 +2757,7 @@
     readonly type: 'FailedToSend' | 'BadXcmOrigin' | 'BadXcm' | 'BadOverweightIndex' | 'WeightOverLimit';
   }
 
-  /** @name PalletXcmError (329) */
+  /** @name PalletXcmError (331) */
   export interface PalletXcmError extends Enum {
     readonly isUnreachable: boolean;
     readonly isSendFailure: boolean;
@@ -2773,29 +2775,29 @@
     readonly type: 'Unreachable' | 'SendFailure' | 'Filtered' | 'UnweighableMessage' | 'DestinationNotInvertible' | 'Empty' | 'CannotReanchor' | 'TooManyAssets' | 'InvalidOrigin' | 'BadVersion' | 'BadLocation' | 'NoSubscription' | 'AlreadySubscribed';
   }
 
-  /** @name CumulusPalletXcmError (330) */
+  /** @name CumulusPalletXcmError (332) */
   export type CumulusPalletXcmError = Null;
 
-  /** @name CumulusPalletDmpQueueConfigData (331) */
+  /** @name CumulusPalletDmpQueueConfigData (333) */
   export interface CumulusPalletDmpQueueConfigData extends Struct {
     readonly maxIndividual: u64;
   }
 
-  /** @name CumulusPalletDmpQueuePageIndexData (332) */
+  /** @name CumulusPalletDmpQueuePageIndexData (334) */
   export interface CumulusPalletDmpQueuePageIndexData extends Struct {
     readonly beginUsed: u32;
     readonly endUsed: u32;
     readonly overweightCount: u64;
   }
 
-  /** @name CumulusPalletDmpQueueError (335) */
+  /** @name CumulusPalletDmpQueueError (337) */
   export interface CumulusPalletDmpQueueError extends Enum {
     readonly isUnknown: boolean;
     readonly isOverLimit: boolean;
     readonly type: 'Unknown' | 'OverLimit';
   }
 
-  /** @name PalletUniqueError (339) */
+  /** @name PalletUniqueError (341) */
   export interface PalletUniqueError extends Enum {
     readonly isCollectionDecimalPointLimitExceeded: boolean;
     readonly isConfirmUnsetSponsorFail: boolean;
@@ -2803,7 +2805,7 @@
     readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument';
   }
 
-  /** @name PalletUnqSchedulerScheduledV3 (342) */
+  /** @name PalletUnqSchedulerScheduledV3 (344) */
   export interface PalletUnqSchedulerScheduledV3 extends Struct {
     readonly maybeId: Option<U8aFixed>;
     readonly priority: u8;
@@ -2812,7 +2814,7 @@
     readonly origin: OpalRuntimeOriginCaller;
   }
 
-  /** @name OpalRuntimeOriginCaller (343) */
+  /** @name OpalRuntimeOriginCaller (345) */
   export interface OpalRuntimeOriginCaller extends Enum {
     readonly isVoid: boolean;
     readonly isSystem: boolean;
@@ -2826,7 +2828,7 @@
     readonly type: 'Void' | 'System' | 'PolkadotXcm' | 'CumulusXcm' | 'Ethereum';
   }
 
-  /** @name FrameSupportDispatchRawOrigin (344) */
+  /** @name FrameSupportDispatchRawOrigin (346) */
   export interface FrameSupportDispatchRawOrigin extends Enum {
     readonly isRoot: boolean;
     readonly isSigned: boolean;
@@ -2835,7 +2837,7 @@
     readonly type: 'Root' | 'Signed' | 'None';
   }
 
-  /** @name PalletXcmOrigin (345) */
+  /** @name PalletXcmOrigin (347) */
   export interface PalletXcmOrigin extends Enum {
     readonly isXcm: boolean;
     readonly asXcm: XcmV1MultiLocation;
@@ -2844,7 +2846,7 @@
     readonly type: 'Xcm' | 'Response';
   }
 
-  /** @name CumulusPalletXcmOrigin (346) */
+  /** @name CumulusPalletXcmOrigin (348) */
   export interface CumulusPalletXcmOrigin extends Enum {
     readonly isRelay: boolean;
     readonly isSiblingParachain: boolean;
@@ -2852,17 +2854,17 @@
     readonly type: 'Relay' | 'SiblingParachain';
   }
 
-  /** @name PalletEthereumRawOrigin (347) */
+  /** @name PalletEthereumRawOrigin (349) */
   export interface PalletEthereumRawOrigin extends Enum {
     readonly isEthereumTransaction: boolean;
     readonly asEthereumTransaction: H160;
     readonly type: 'EthereumTransaction';
   }
 
-  /** @name SpCoreVoid (348) */
+  /** @name SpCoreVoid (350) */
   export type SpCoreVoid = Null;
 
-  /** @name PalletUnqSchedulerError (349) */
+  /** @name PalletUnqSchedulerError (351) */
   export interface PalletUnqSchedulerError extends Enum {
     readonly isFailedToSchedule: boolean;
     readonly isNotFound: boolean;
@@ -2871,7 +2873,7 @@
     readonly type: 'FailedToSchedule' | 'NotFound' | 'TargetBlockNumberInPast' | 'RescheduleNoChange';
   }
 
-  /** @name UpDataStructsCollection (350) */
+  /** @name UpDataStructsCollection (352) */
   export interface UpDataStructsCollection extends Struct {
     readonly owner: AccountId32;
     readonly mode: UpDataStructsCollectionMode;
@@ -2884,7 +2886,7 @@
     readonly externalCollection: bool;
   }
 
-  /** @name UpDataStructsSponsorshipState (351) */
+  /** @name UpDataStructsSponsorshipState (353) */
   export interface UpDataStructsSponsorshipState extends Enum {
     readonly isDisabled: boolean;
     readonly isUnconfirmed: boolean;
@@ -2894,42 +2896,42 @@
     readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
   }
 
-  /** @name UpDataStructsProperties (352) */
+  /** @name UpDataStructsProperties (354) */
   export interface UpDataStructsProperties extends Struct {
     readonly map: UpDataStructsPropertiesMapBoundedVec;
     readonly consumedSpace: u32;
     readonly spaceLimit: u32;
   }
 
-  /** @name UpDataStructsPropertiesMapBoundedVec (353) */
+  /** @name UpDataStructsPropertiesMapBoundedVec (355) */
   export interface UpDataStructsPropertiesMapBoundedVec extends BTreeMap<Bytes, Bytes> {}
 
-  /** @name UpDataStructsPropertiesMapPropertyPermission (358) */
+  /** @name UpDataStructsPropertiesMapPropertyPermission (360) */
   export interface UpDataStructsPropertiesMapPropertyPermission extends BTreeMap<Bytes, UpDataStructsPropertyPermission> {}
 
-  /** @name UpDataStructsCollectionStats (365) */
+  /** @name UpDataStructsCollectionStats (367) */
   export interface UpDataStructsCollectionStats extends Struct {
     readonly created: u32;
     readonly destroyed: u32;
     readonly alive: u32;
   }
 
-  /** @name UpDataStructsTokenChild (366) */
+  /** @name UpDataStructsTokenChild (368) */
   export interface UpDataStructsTokenChild extends Struct {
     readonly token: u32;
     readonly collection: u32;
   }
 
-  /** @name PhantomTypeUpDataStructs (367) */
+  /** @name PhantomTypeUpDataStructs (369) */
   export interface PhantomTypeUpDataStructs extends Vec<ITuple<[UpDataStructsTokenData, UpDataStructsRpcCollection, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftNftInfo, RmrkTraitsResourceResourceInfo, RmrkTraitsPropertyPropertyInfo, RmrkTraitsBaseBaseInfo, RmrkTraitsPartPartType, RmrkTraitsTheme, RmrkTraitsNftNftChild]>> {}
 
-  /** @name UpDataStructsTokenData (369) */
+  /** @name UpDataStructsTokenData (371) */
   export interface UpDataStructsTokenData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: Option<PalletEvmAccountBasicCrossAccountIdRepr>;
   }
 
-  /** @name UpDataStructsRpcCollection (371) */
+  /** @name UpDataStructsRpcCollection (373) */
   export interface UpDataStructsRpcCollection extends Struct {
     readonly owner: AccountId32;
     readonly mode: UpDataStructsCollectionMode;
@@ -2944,7 +2946,7 @@
     readonly readOnly: bool;
   }
 
-  /** @name RmrkTraitsCollectionCollectionInfo (372) */
+  /** @name RmrkTraitsCollectionCollectionInfo (374) */
   export interface RmrkTraitsCollectionCollectionInfo extends Struct {
     readonly issuer: AccountId32;
     readonly metadata: Bytes;
@@ -2953,7 +2955,7 @@
     readonly nftsCount: u32;
   }
 
-  /** @name RmrkTraitsNftNftInfo (373) */
+  /** @name RmrkTraitsNftNftInfo (375) */
   export interface RmrkTraitsNftNftInfo extends Struct {
     readonly owner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
     readonly royalty: Option<RmrkTraitsNftRoyaltyInfo>;
@@ -2962,13 +2964,13 @@
     readonly pending: bool;
   }
 
-  /** @name RmrkTraitsNftRoyaltyInfo (375) */
+  /** @name RmrkTraitsNftRoyaltyInfo (377) */
   export interface RmrkTraitsNftRoyaltyInfo extends Struct {
     readonly recipient: AccountId32;
     readonly amount: Permill;
   }
 
-  /** @name RmrkTraitsResourceResourceInfo (376) */
+  /** @name RmrkTraitsResourceResourceInfo (378) */
   export interface RmrkTraitsResourceResourceInfo extends Struct {
     readonly id: u32;
     readonly resource: RmrkTraitsResourceResourceTypes;
@@ -2976,7 +2978,7 @@
     readonly pendingRemoval: bool;
   }
 
-  /** @name RmrkTraitsResourceResourceTypes (377) */
+  /** @name RmrkTraitsResourceResourceTypes (379) */
   export interface RmrkTraitsResourceResourceTypes extends Enum {
     readonly isBasic: boolean;
     readonly asBasic: RmrkTraitsResourceBasicResource;
@@ -2987,26 +2989,26 @@
     readonly type: 'Basic' | 'Composable' | 'Slot';
   }
 
-  /** @name RmrkTraitsPropertyPropertyInfo (378) */
+  /** @name RmrkTraitsPropertyPropertyInfo (380) */
   export interface RmrkTraitsPropertyPropertyInfo extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name RmrkTraitsBaseBaseInfo (379) */
+  /** @name RmrkTraitsBaseBaseInfo (381) */
   export interface RmrkTraitsBaseBaseInfo extends Struct {
     readonly issuer: AccountId32;
     readonly baseType: Bytes;
     readonly symbol: Bytes;
   }
 
-  /** @name RmrkTraitsNftNftChild (380) */
+  /** @name RmrkTraitsNftNftChild (382) */
   export interface RmrkTraitsNftNftChild extends Struct {
     readonly collectionId: u32;
     readonly nftId: u32;
   }
 
-  /** @name PalletCommonError (382) */
+  /** @name PalletCommonError (384) */
   export interface PalletCommonError extends Enum {
     readonly isCollectionNotFound: boolean;
     readonly isMustBeTokenOwner: boolean;
@@ -3032,8 +3034,7 @@
     readonly isAddressIsZero: boolean;
     readonly isUnsupportedOperation: boolean;
     readonly isNotSufficientFounds: boolean;
-    readonly isNestingIsDisabled: boolean;
-    readonly isOnlyOwnerAllowedToNest: boolean;
+    readonly isUserIsNotAllowedToNest: boolean;
     readonly isSourceCollectionIsNotAllowedToNest: boolean;
     readonly isCollectionFieldSizeExceeded: boolean;
     readonly isNoSpaceForProperty: boolean;
@@ -3043,10 +3044,10 @@
     readonly isEmptyPropertyKey: boolean;
     readonly isCollectionIsExternal: boolean;
     readonly isCollectionIsInternal: 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' | 'NestingIsDisabled' | 'OnlyOwnerAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal';
+    readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal';
   }
 
-  /** @name PalletFungibleError (384) */
+  /** @name PalletFungibleError (386) */
   export interface PalletFungibleError extends Enum {
     readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isFungibleItemsHaveNoId: boolean;
@@ -3056,12 +3057,12 @@
     readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
   }
 
-  /** @name PalletRefungibleItemData (385) */
+  /** @name PalletRefungibleItemData (387) */
   export interface PalletRefungibleItemData extends Struct {
     readonly constData: Bytes;
   }
 
-  /** @name PalletRefungibleError (389) */
+  /** @name PalletRefungibleError (391) */
   export interface PalletRefungibleError extends Enum {
     readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isWrongRefungiblePieces: boolean;
@@ -3070,12 +3071,12 @@
     readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
   }
 
-  /** @name PalletNonfungibleItemData (390) */
+  /** @name PalletNonfungibleItemData (392) */
   export interface PalletNonfungibleItemData extends Struct {
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name PalletNonfungibleError (392) */
+  /** @name PalletNonfungibleError (394) */
   export interface PalletNonfungibleError extends Enum {
     readonly isNotNonfungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isNonfungibleItemsHaveNoAmount: boolean;
@@ -3083,15 +3084,16 @@
     readonly type: 'NotNonfungibleDataUsedToMintFungibleCollectionToken' | 'NonfungibleItemsHaveNoAmount' | 'CantBurnNftWithChildren';
   }
 
-  /** @name PalletStructureError (393) */
+  /** @name PalletStructureError (395) */
   export interface PalletStructureError extends Enum {
     readonly isOuroborosDetected: boolean;
     readonly isDepthLimit: boolean;
+    readonly isBreadthLimit: boolean;
     readonly isTokenNotFound: boolean;
-    readonly type: 'OuroborosDetected' | 'DepthLimit' | 'TokenNotFound';
+    readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound';
   }
 
-  /** @name PalletRmrkCoreError (394) */
+  /** @name PalletRmrkCoreError (396) */
   export interface PalletRmrkCoreError extends Enum {
     readonly isCorruptedCollectionType: boolean;
     readonly isNftTypeEncodeError: boolean;
@@ -3112,7 +3114,7 @@
     readonly type: 'CorruptedCollectionType' | 'NftTypeEncodeError' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'ResourceNotPending';
   }
 
-  /** @name PalletRmrkEquipError (396) */
+  /** @name PalletRmrkEquipError (398) */
   export interface PalletRmrkEquipError extends Enum {
     readonly isPermissionError: boolean;
     readonly isNoAvailableBaseId: boolean;
@@ -3122,7 +3124,7 @@
     readonly type: 'PermissionError' | 'NoAvailableBaseId' | 'NoAvailablePartId' | 'BaseDoesntExist' | 'NeedsDefaultThemeFirst';
   }
 
-  /** @name PalletEvmError (399) */
+  /** @name PalletEvmError (401) */
   export interface PalletEvmError extends Enum {
     readonly isBalanceLow: boolean;
     readonly isFeeOverflow: boolean;
@@ -3133,7 +3135,7 @@
     readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce';
   }
 
-  /** @name FpRpcTransactionStatus (402) */
+  /** @name FpRpcTransactionStatus (404) */
   export interface FpRpcTransactionStatus extends Struct {
     readonly transactionHash: H256;
     readonly transactionIndex: u32;
@@ -3144,10 +3146,10 @@
     readonly logsBloom: EthbloomBloom;
   }
 
-  /** @name EthbloomBloom (404) */
+  /** @name EthbloomBloom (406) */
   export interface EthbloomBloom extends U8aFixed {}
 
-  /** @name EthereumReceiptReceiptV3 (406) */
+  /** @name EthereumReceiptReceiptV3 (408) */
   export interface EthereumReceiptReceiptV3 extends Enum {
     readonly isLegacy: boolean;
     readonly asLegacy: EthereumReceiptEip658ReceiptData;
@@ -3158,7 +3160,7 @@
     readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
   }
 
-  /** @name EthereumReceiptEip658ReceiptData (407) */
+  /** @name EthereumReceiptEip658ReceiptData (409) */
   export interface EthereumReceiptEip658ReceiptData extends Struct {
     readonly statusCode: u8;
     readonly usedGas: U256;
@@ -3166,14 +3168,14 @@
     readonly logs: Vec<EthereumLog>;
   }
 
-  /** @name EthereumBlock (408) */
+  /** @name EthereumBlock (410) */
   export interface EthereumBlock extends Struct {
     readonly header: EthereumHeader;
     readonly transactions: Vec<EthereumTransactionTransactionV2>;
     readonly ommers: Vec<EthereumHeader>;
   }
 
-  /** @name EthereumHeader (409) */
+  /** @name EthereumHeader (411) */
   export interface EthereumHeader extends Struct {
     readonly parentHash: H256;
     readonly ommersHash: H256;
@@ -3192,24 +3194,24 @@
     readonly nonce: EthereumTypesHashH64;
   }
 
-  /** @name EthereumTypesHashH64 (410) */
+  /** @name EthereumTypesHashH64 (412) */
   export interface EthereumTypesHashH64 extends U8aFixed {}
 
-  /** @name PalletEthereumError (415) */
+  /** @name PalletEthereumError (417) */
   export interface PalletEthereumError extends Enum {
     readonly isInvalidSignature: boolean;
     readonly isPreLogExists: boolean;
     readonly type: 'InvalidSignature' | 'PreLogExists';
   }
 
-  /** @name PalletEvmCoderSubstrateError (416) */
+  /** @name PalletEvmCoderSubstrateError (418) */
   export interface PalletEvmCoderSubstrateError extends Enum {
     readonly isOutOfGas: boolean;
     readonly isOutOfFund: boolean;
     readonly type: 'OutOfGas' | 'OutOfFund';
   }
 
-  /** @name PalletEvmContractHelpersSponsoringModeT (417) */
+  /** @name PalletEvmContractHelpersSponsoringModeT (419) */
   export interface PalletEvmContractHelpersSponsoringModeT extends Enum {
     readonly isDisabled: boolean;
     readonly isAllowlisted: boolean;
@@ -3217,20 +3219,20 @@
     readonly type: 'Disabled' | 'Allowlisted' | 'Generous';
   }
 
-  /** @name PalletEvmContractHelpersError (419) */
+  /** @name PalletEvmContractHelpersError (421) */
   export interface PalletEvmContractHelpersError extends Enum {
     readonly isNoPermission: boolean;
     readonly type: 'NoPermission';
   }
 
-  /** @name PalletEvmMigrationError (420) */
+  /** @name PalletEvmMigrationError (422) */
   export interface PalletEvmMigrationError extends Enum {
     readonly isAccountNotEmpty: boolean;
     readonly isAccountIsNotMigrating: boolean;
     readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating';
   }
 
-  /** @name SpRuntimeMultiSignature (422) */
+  /** @name SpRuntimeMultiSignature (424) */
   export interface SpRuntimeMultiSignature extends Enum {
     readonly isEd25519: boolean;
     readonly asEd25519: SpCoreEd25519Signature;
@@ -3241,34 +3243,34 @@
     readonly type: 'Ed25519' | 'Sr25519' | 'Ecdsa';
   }
 
-  /** @name SpCoreEd25519Signature (423) */
+  /** @name SpCoreEd25519Signature (425) */
   export interface SpCoreEd25519Signature extends U8aFixed {}
 
-  /** @name SpCoreSr25519Signature (425) */
+  /** @name SpCoreSr25519Signature (427) */
   export interface SpCoreSr25519Signature extends U8aFixed {}
 
-  /** @name SpCoreEcdsaSignature (426) */
+  /** @name SpCoreEcdsaSignature (428) */
   export interface SpCoreEcdsaSignature extends U8aFixed {}
 
-  /** @name FrameSystemExtensionsCheckSpecVersion (429) */
+  /** @name FrameSystemExtensionsCheckSpecVersion (431) */
   export type FrameSystemExtensionsCheckSpecVersion = Null;
 
-  /** @name FrameSystemExtensionsCheckGenesis (430) */
+  /** @name FrameSystemExtensionsCheckGenesis (432) */
   export type FrameSystemExtensionsCheckGenesis = Null;
 
-  /** @name FrameSystemExtensionsCheckNonce (433) */
+  /** @name FrameSystemExtensionsCheckNonce (435) */
   export interface FrameSystemExtensionsCheckNonce extends Compact<u32> {}
 
-  /** @name FrameSystemExtensionsCheckWeight (434) */
+  /** @name FrameSystemExtensionsCheckWeight (436) */
   export type FrameSystemExtensionsCheckWeight = Null;
 
-  /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (435) */
+  /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (437) */
   export interface PalletTemplateTransactionPaymentChargeTransactionPayment extends Compact<u128> {}
 
-  /** @name OpalRuntimeRuntime (436) */
+  /** @name OpalRuntimeRuntime (438) */
   export type OpalRuntimeRuntime = Null;
 
-  /** @name PalletEthereumFakeTransactionFinalizer (437) */
+  /** @name PalletEthereumFakeTransactionFinalizer (439) */
   export type PalletEthereumFakeTransactionFinalizer = Null;
 
 } // declare module
modifiedtests/src/nesting/nest.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/nest.test.ts
+++ b/tests/src/nesting/nest.test.ts
@@ -32,7 +32,7 @@
   it('Performs the full suite: bundles a token, transfers, and unnests', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
 
       // Create a nested token
@@ -62,7 +62,7 @@
   it('Transfers an already bundled token', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
 
       const tokenA = await createItemExpectSuccess(alice, collection, 'NFT');
       const tokenB = await createItemExpectSuccess(alice, collection, 'NFT');
@@ -92,7 +92,7 @@
   it('Checks token children', async () => {
     await usingApi(async api => {
       const collectionA = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionA, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collectionA, {nesting: {tokenOwner: true}});
       const collectionB = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
 
       const targetToken = await createItemExpectSuccess(alice, collectionA, 'NFT');
@@ -151,7 +151,7 @@
   it('NFT: allows an Owner to nest/unnest their token', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
 
       // Create a nested token
@@ -170,7 +170,7 @@
   it('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {OwnerRestricted:[collection]}});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, restricted:[collection]}});
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
 
       // Create a nested token
@@ -191,7 +191,7 @@
   it('Fungible: allows an Owner to nest/unnest their token', async () => {
     await usingApi(async api => {
       const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});
       const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});
       const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};
 
@@ -218,7 +218,7 @@
 
       const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
 
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {OwnerRestricted: [collectionFT]}});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted: [collectionFT]}});
 
       // Create a nested token
       await expect(executeTransaction(api, alice, api.tx.unique.createItem(
@@ -238,7 +238,7 @@
   it('ReFungible: allows an Owner to nest/unnest their token', async () => {
     await usingApi(async api => {
       const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});
       const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});
       const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};
 
@@ -265,7 +265,7 @@
 
       const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
 
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {OwnerRestricted:[collectionRFT]}});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[collectionRFT]}});
 
       // Create a nested token
       await expect(executeTransaction(api, alice, api.tx.unique.createItem(
@@ -292,7 +292,7 @@
   it('Disallows excessive token nesting', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
 
       const maxNestingLevel = 5;
@@ -326,7 +326,7 @@
   it('NFT: disallows to nest token if nesting is disabled', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Disabled'});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {}});
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
 
       // Try to create a nested token
@@ -334,12 +334,12 @@
         collection,
         {Ethereum: tokenIdToAddress(collection, targetToken)},
           {nft: {const_data: [], variable_data: []}} as any,
-      )), 'while creating nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);
+      )), 'while creating nested token').to.be.rejectedWith(/^common\.UserIsNotAllowedToNest$/);
 
       // Create a token to be nested
       const newToken = await createItemExpectSuccess(alice, collection, 'NFT');
       // Try to nest
-      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.NestingIsDisabled/);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer({Ethereum: tokenIdToAddress(collection, targetToken)}, collection, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
       expect(await getTopmostTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});
       expect(await getTokenOwner(api, collection, newToken)).to.be.deep.equal({Substrate: alice.address});
     });
@@ -348,7 +348,7 @@
   it('NFT: disallows a non-Owner to nest someone else\'s token', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
 
       await addToAllowListExpectSuccess(alice, collection, bob.address);
       await enableAllowListExpectSuccess(alice, collection);
@@ -362,7 +362,7 @@
         collection,
         {Ethereum: tokenIdToAddress(collection, targetToken)},
           {nft: {const_data: [], variable_data: []}} as any,
-      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
+      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collection, 'NFT');
@@ -374,7 +374,7 @@
   it('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {OwnerRestricted:[collection]}});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, restricted:[collection]}});
 
       await addToAllowListExpectSuccess(alice, collection, bob.address);
       await enableAllowListExpectSuccess(alice, collection);
@@ -388,7 +388,7 @@
         collection,
         {Ethereum: tokenIdToAddress(collection, targetToken)},
           {nft: {const_data: [], variable_data: []}} as any,
-      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
+      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collection, 'NFT');
@@ -400,7 +400,7 @@
   it('NFT: disallows to nest token in an unlisted collection', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {OwnerRestricted:[]}});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true, restricted:[]}});
 
       // Create a token to attempt to be nested into
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
@@ -424,7 +424,7 @@
   it('Fungible: disallows to nest token if nesting is disabled', async () => {
     await usingApi(async api => {
       const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: 'Disabled'});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {}});
       const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');
       const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};
 
@@ -435,12 +435,12 @@
         collectionFT,
         targetAddress,
         {Fungible: {Value: 10}},
-      )), 'while creating nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);
+      )), 'while creating nested token').to.be.rejectedWith(/^common\.UserIsNotAllowedToNest$/);
 
       // Create a token to be nested
       const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');
       // Try to nest
-      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.NestingIsDisabled/);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
       // Create another token to be nested
       const newToken2 = await createItemExpectSuccess(alice, collectionFT, 'Fungible');
@@ -452,7 +452,7 @@
   it('Fungible: disallows a non-Owner to nest someone else\'s token', async () => {
     await usingApi(async api => {
       const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});
 
       await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);
       await enableAllowListExpectSuccess(alice, collectionNFT);
@@ -469,11 +469,11 @@
         collectionFT,
         targetAddress,
         {Fungible: {Value: 10}},
-      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
+      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');
-      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
     });
   });
 
@@ -489,25 +489,25 @@
       const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};
 
       const collectionFT = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {OwnerRestricted:[collectionFT]}});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[collectionFT]}});
 
       // Try to create a nested token in the wrong collection
       await expect(executeTransaction(api, alice, api.tx.unique.createItem(
         collectionFT,
         targetAddress,
         {Fungible: {Value: 10}},
-      )), 'while creating nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
+      )), 'while creating nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collectionFT, 'Fungible');
-      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
     });
   });
 
   it('Fungible: disallows to nest token in an unlisted collection', async () => {
     await usingApi(async api => {
       const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {OwnerRestricted:[]}});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[]}});
 
       // Create a token to attempt to be nested into
       const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');
@@ -533,7 +533,7 @@
   it('ReFungible: disallows to nest token if nesting is disabled', async () => {
     await usingApi(async api => {
       const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: 'Disabled'});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {}});
       const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');
       const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};
 
@@ -544,14 +544,14 @@
         collectionRFT,
         targetAddress,
         {ReFungible: {const_data: [], pieces: 100}},
-      )), 'while creating a nested token').to.be.rejectedWith(/^common\.NestingIsDisabled$/);
+      )), 'while creating a nested token').to.be.rejectedWith(/^common\.UserIsNotAllowedToNest$/);
 
       // Create a token to be nested
       const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');
       // Try to nest
       await transferExpectFailure(collectionRFT, newToken, alice, targetAddress, 100);
       // Try to nest
-      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.NestingIsDisabled/);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
       // Create another token to be nested
       const newToken2 = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');
@@ -563,7 +563,7 @@
   it('ReFungible: disallows a non-Owner to nest someone else\'s token', async () => {
     await usingApi(async api => {
       const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});
 
       await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);
       await enableAllowListExpectSuccess(alice, collectionNFT);
@@ -580,11 +580,11 @@
         collectionRFT,
         targetAddress,
         {ReFungible: {const_data: [], pieces: 100}},
-      )), 'while creating a nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
+      )), 'while creating a nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');
-      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
     });
   });
 
@@ -600,25 +600,25 @@
       const targetAddress = {Ethereum: tokenIdToAddress(collectionNFT, targetToken)};
 
       const collectionRFT = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {OwnerRestricted:[collectionRFT]}});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[collectionRFT]}});
 
       // Try to create a nested token in the wrong collection
       await expect(executeTransaction(api, alice, api.tx.unique.createItem(
         collectionRFT,
         targetAddress,
         {ReFungible: {const_data: [], pieces: 100}},
-      )), 'while creating a nested token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
+      )), 'while creating a nested token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
 
       // Try to create and nest a token in the wrong collection
       const newToken = await createItemExpectSuccess(alice, collectionRFT, 'ReFungible');
-      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.OnlyOwnerAllowedToNest/);
+      await expect(executeTransaction(api, alice, api.tx.unique.transfer(targetAddress, collectionRFT, newToken, 1)), 'while nesting new token').to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
     });
   });
 
   it('ReFungible: disallows to nest token to an unlisted collection', async () => {
     await usingApi(async api => {
       const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {OwnerRestricted:[]}});
+      await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[]}});
 
       // Create a token to attempt to be nested into
       const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT');
modifiedtests/src/nesting/rules-smoke.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/rules-smoke.test.ts
+++ b/tests/src/nesting/rules-smoke.test.ts
@@ -14,7 +14,7 @@
       const events = await executeTransaction(api, alice, api.tx.unique.createCollectionEx({
         mode: 'NFT',
         permissions: {
-          nesting: {OwnerRestricted: []},
+          nesting: {tokenOwner: true, restricted: []},
         },
       }));
       const collection = getCreateCollectionResult(events).collectionId;
modifiedtests/src/nesting/unnest.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/unnest.test.ts
+++ b/tests/src/nesting/unnest.test.ts
@@ -27,7 +27,7 @@
   it('NFT: allows the owner to successfully unnest a token', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
       const targetAddress = {Ethereum: tokenIdToAddress(collection, targetToken)};
 
@@ -56,7 +56,7 @@
   it('Fungible: allows the owner to successfully unnest a token', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
       const targetAddress = {Ethereum: tokenIdToAddress(collection, targetToken)};
 
@@ -83,7 +83,7 @@
   it('ReFungible: allows the owner to successfully unnest a token', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
       const targetAddress = {Ethereum: tokenIdToAddress(collection, targetToken)};
 
@@ -118,7 +118,7 @@
   it('Disallows a non-owner to unnest/burn a token', async () => {
     await usingApi(async api => {
       const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Owner'});
+      await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
       const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
       const targetAddress = {Ethereum: tokenIdToAddress(collection, targetToken)};
 
@@ -148,7 +148,7 @@
   // Recursive nesting
   it('Prevents Ouroboros creation', async () => {
     const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-    await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: 'Owner'});
+    await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
     const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');
 
     // Create a nested token ouroboros
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -193,7 +193,7 @@
     if (method === 'ExtrinsicSuccess') {
       success = true;
     } else if ((expectSection == section) && (expectMethod == method)) {
-      successData = extractAction!(data);
+      successData = extractAction!(data as any);
     }
   });
 
@@ -547,7 +547,7 @@
   });
 }
 
-export const setCollectionPermissionsExpectSuccess = async (sender: IKeyringPair, collectionId: number, permissions: {mintMode?: boolean, access?: 'Normal' | 'AllowList', nesting?: 'Disabled' | 'Owner' | {OwnerRestricted: number[]}}) => {
+export const setCollectionPermissionsExpectSuccess = async (sender: IKeyringPair, collectionId: number, permissions: any) => {
   await usingApi(async(api) => {
     const tx = api.tx.unique.setCollectionPermissions(collectionId, permissions);
     const events = await submitTransactionAsync(sender, tx);
modifiedtests/yarn.lockdiffbeforeafterboth
--- a/tests/yarn.lock
+++ b/tests/yarn.lock
@@ -508,78 +508,78 @@
     "@nodelib/fs.scandir" "2.1.5"
     fastq "^1.6.0"
 
-"@polkadot/api-augment@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-augment/-/api-augment-8.7.2-11.tgz#7f174f830c181d82863eb41f48e24fd6bbde3065"
-  integrity sha512-yKsuxjez1ArwSEZJ+g8mausm38CgOtaWBG5ob5cmO9M2v45HBXy3Kmviqr8Dputtu23deT85p7m/8RFLlAnzSA==
+"@polkadot/api-augment@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-augment/-/api-augment-8.7.2-15.tgz#a141d3cd595a39e7e2965330268b5eb92bdd5849"
+  integrity sha512-QGXosX6p0RFYNhWepZCIaRiyCvHnVt5Pb6U7/77UxIszgGRHfHFDsYr4v5bGiaRTOj/E8moc2Ufi/+VgOiG9sw==
   dependencies:
     "@babel/runtime" "^7.18.3"
-    "@polkadot/api-base" "8.7.2-11"
-    "@polkadot/rpc-augment" "8.7.2-11"
-    "@polkadot/types" "8.7.2-11"
-    "@polkadot/types-augment" "8.7.2-11"
-    "@polkadot/types-codec" "8.7.2-11"
+    "@polkadot/api-base" "8.7.2-15"
+    "@polkadot/rpc-augment" "8.7.2-15"
+    "@polkadot/types" "8.7.2-15"
+    "@polkadot/types-augment" "8.7.2-15"
+    "@polkadot/types-codec" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
 
-"@polkadot/api-base@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-base/-/api-base-8.7.2-11.tgz#7e297a0ca283a58bc9d8d11c1edb099bc61da9f1"
-  integrity sha512-WQE5uvb7W7AKSfy4ekW2i6mJJzZYLMS/eNPNXYpURW/cRPt9NhT9lNz2Ae2d7gaWgWil+jNLecXTHTUzxobRbA==
+"@polkadot/api-base@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-base/-/api-base-8.7.2-15.tgz#c909d3bf0fbfb3cc46ca7067199e36e72b959bdb"
+  integrity sha512-HXdtaqbpnfFbOazjI9CPSYM37S4mzhxUs8hLMKrWqpHL//at4tiMa5dRyev9VSKeE6gqeqCT9JTBvEAZ9eNR6Q==
   dependencies:
     "@babel/runtime" "^7.18.3"
-    "@polkadot/rpc-core" "8.7.2-11"
-    "@polkadot/types" "8.7.2-11"
+    "@polkadot/rpc-core" "8.7.2-15"
+    "@polkadot/types" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
     rxjs "^7.5.5"
 
-"@polkadot/api-contract@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-8.7.2-11.tgz#9487394286e536a7b1edfb6296529722fa63a43a"
-  integrity sha512-vOi4FX33ttkotJDzSum0nFUworWJ2+yfDejZkC33mM8zb+ne0Quggfz2nQqiKS2lgkj2z4YwJbsf/9paRQeS3w==
+"@polkadot/api-contract@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-8.7.2-15.tgz#687706fb4bd33c4a88187db3a269292f6e559892"
+  integrity sha512-Pr1Nm5zBpW9foCKm/Q6hIT5KHCeFVE8EFSfHBgjbitYpFOGnz19kduEpa0vxIcfq2WVXcVPTQ2eqjGtHoThNqA==
   dependencies:
     "@babel/runtime" "^7.18.3"
-    "@polkadot/api" "8.7.2-11"
-    "@polkadot/types" "8.7.2-11"
-    "@polkadot/types-codec" "8.7.2-11"
-    "@polkadot/types-create" "8.7.2-11"
+    "@polkadot/api" "8.7.2-15"
+    "@polkadot/types" "8.7.2-15"
+    "@polkadot/types-codec" "8.7.2-15"
+    "@polkadot/types-create" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
     "@polkadot/util-crypto" "^9.4.1"
     rxjs "^7.5.5"
 
-"@polkadot/api-derive@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-8.7.2-11.tgz#21e315d554a8cd31bb1f3b10077960e35391a311"
-  integrity sha512-8fkYidDgNjJcWHtiRfJQaI4H386uGZh5Ie0t21KG4sSC5R+Lbnm0CJwIX4scJvQ/U+38gCyQW07b+Pxt9oDwvg==
+"@polkadot/api-derive@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-8.7.2-15.tgz#b29f24d435c036c9bf5624d18a9d93196cf2c4f4"
+  integrity sha512-0R3M9LFKoQ0d7elIDQjPKuV5EAHTtkU/72Lgxw2GYStsOqcnfFNomfLoLMuk8Xy4ETUAp/Kq1eMJpvsY6hSTtA==
   dependencies:
     "@babel/runtime" "^7.18.3"
-    "@polkadot/api" "8.7.2-11"
-    "@polkadot/api-augment" "8.7.2-11"
-    "@polkadot/api-base" "8.7.2-11"
-    "@polkadot/rpc-core" "8.7.2-11"
-    "@polkadot/types" "8.7.2-11"
-    "@polkadot/types-codec" "8.7.2-11"
+    "@polkadot/api" "8.7.2-15"
+    "@polkadot/api-augment" "8.7.2-15"
+    "@polkadot/api-base" "8.7.2-15"
+    "@polkadot/rpc-core" "8.7.2-15"
+    "@polkadot/types" "8.7.2-15"
+    "@polkadot/types-codec" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
     "@polkadot/util-crypto" "^9.4.1"
     rxjs "^7.5.5"
 
-"@polkadot/api@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-8.7.2-11.tgz#d76ad24f96fc9eba49825c11277105d12bf5e05c"
-  integrity sha512-eFQtZOJOVK5IbNSjvrk1JrOZJrtZRjaecMAhnQiglMPoIfQJiRbnXhUslGbXsgFoJsfWW6DAVY5aJi/PjuF9OQ==
+"@polkadot/api@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-8.7.2-15.tgz#c7ede416e4d277c227fc93fdfdc4d27634935d08"
+  integrity sha512-tzEUWsXIPzPbnpn/3LTGtJ7SXzMgCJ/da5d9q0UH3vsx1gDEjuZEWXOeSYLHgbqQSgwPukvMVuGtRjcC+A/WZQ==
   dependencies:
     "@babel/runtime" "^7.18.3"
-    "@polkadot/api-augment" "8.7.2-11"
-    "@polkadot/api-base" "8.7.2-11"
-    "@polkadot/api-derive" "8.7.2-11"
+    "@polkadot/api-augment" "8.7.2-15"
+    "@polkadot/api-base" "8.7.2-15"
+    "@polkadot/api-derive" "8.7.2-15"
     "@polkadot/keyring" "^9.4.1"
-    "@polkadot/rpc-augment" "8.7.2-11"
-    "@polkadot/rpc-core" "8.7.2-11"
-    "@polkadot/rpc-provider" "8.7.2-11"
-    "@polkadot/types" "8.7.2-11"
-    "@polkadot/types-augment" "8.7.2-11"
-    "@polkadot/types-codec" "8.7.2-11"
-    "@polkadot/types-create" "8.7.2-11"
-    "@polkadot/types-known" "8.7.2-11"
+    "@polkadot/rpc-augment" "8.7.2-15"
+    "@polkadot/rpc-core" "8.7.2-15"
+    "@polkadot/rpc-provider" "8.7.2-15"
+    "@polkadot/types" "8.7.2-15"
+    "@polkadot/types-augment" "8.7.2-15"
+    "@polkadot/types-codec" "8.7.2-15"
+    "@polkadot/types-create" "8.7.2-15"
+    "@polkadot/types-known" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
     "@polkadot/util-crypto" "^9.4.1"
     eventemitter3 "^4.0.7"
@@ -603,38 +603,38 @@
     "@polkadot/util" "9.4.1"
     "@substrate/ss58-registry" "^1.22.0"
 
-"@polkadot/rpc-augment@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/rpc-augment/-/rpc-augment-8.7.2-11.tgz#b118303653fb6f80688c62600fde2ed489e1c974"
-  integrity sha512-/h50Kzz/UZwhsV+g7bwGWf0fkVvlWIQ/zaA7H9xtuE4VGvmZRE4Uu06011ToVWNyAwM5xQfXBx1gUznRhem+pg==
+"@polkadot/rpc-augment@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-augment/-/rpc-augment-8.7.2-15.tgz#6175126968dfb79ba5549b03cac8c3860666e72b"
+  integrity sha512-IgfkR9CHT8jDuGYkb75DBFu+yJNW32+vOt3oS0sf57VqkHketSq9rD3mtZD37V/21Q4a17yrqKQOte7mMl9kcg==
   dependencies:
     "@babel/runtime" "^7.18.3"
-    "@polkadot/rpc-core" "8.7.2-11"
-    "@polkadot/types" "8.7.2-11"
-    "@polkadot/types-codec" "8.7.2-11"
+    "@polkadot/rpc-core" "8.7.2-15"
+    "@polkadot/types" "8.7.2-15"
+    "@polkadot/types-codec" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
 
-"@polkadot/rpc-core@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-8.7.2-11.tgz#9c31a34bc2f70e4dab40f9ba08ca9b89c8f3e5c0"
-  integrity sha512-DyHYgzBusMFfsDJ/2VBaVTNHRwZ2cf/woaeJA/ijJbxK2Ke/sg9UW6zr+3Ip8T62GnSNnJoSHMOaMdqvebkNVQ==
+"@polkadot/rpc-core@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-8.7.2-15.tgz#827a31adf833fb866cb5f39dbd86c5f0b44d63a4"
+  integrity sha512-yGmpESOmGyzY7+D3yUxbKToz/eP/q8vDyOGajLnHn12TcnjgbAfMdc4xdU6cQex+mSsPwS0YQFuPrPXGloCOHA==
   dependencies:
     "@babel/runtime" "^7.18.3"
-    "@polkadot/rpc-augment" "8.7.2-11"
-    "@polkadot/rpc-provider" "8.7.2-11"
-    "@polkadot/types" "8.7.2-11"
+    "@polkadot/rpc-augment" "8.7.2-15"
+    "@polkadot/rpc-provider" "8.7.2-15"
+    "@polkadot/types" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
     rxjs "^7.5.5"
 
-"@polkadot/rpc-provider@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-8.7.2-11.tgz#1f4ef542aee83e0c4e1b2a126ed00ade7c818660"
-  integrity sha512-LE5kKEMxL4mZ+dLbU8lOPG2GuPYliYtX1SnXv509zAgUjSCWW9fkdeMBF3tFCjSJJcUmle3mlxG8kYuAqNUScA==
+"@polkadot/rpc-provider@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-8.7.2-15.tgz#99dd30085284442265225e0f12aef3849b7bfe44"
+  integrity sha512-EwgBnUIpGhEfSanDXVviQQ784HYD3DWUPdv9pIvn9qnCZPk7o+MGPvKW73A+XbQpPV9j8tAGnVsSnbDuoSVp1g==
   dependencies:
     "@babel/runtime" "^7.18.3"
     "@polkadot/keyring" "^9.4.1"
-    "@polkadot/types" "8.7.2-11"
-    "@polkadot/types-support" "8.7.2-11"
+    "@polkadot/types" "8.7.2-15"
+    "@polkadot/types-support" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
     "@polkadot/util-crypto" "^9.4.1"
     "@polkadot/x-fetch" "^9.4.1"
@@ -652,86 +652,86 @@
   dependencies:
     "@types/chrome" "^0.0.171"
 
-"@polkadot/typegen@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/typegen/-/typegen-8.7.2-11.tgz#047c3c91f4b34f0188853bed606fd12f6a0fbf4d"
-  integrity sha512-YZpyT8LJFm3akFurrxHpRWxZU50yKvrfdgyZpJh+JJOhSIIDtkx58JNj2+lv0QvhUFOUkd4IWap9bbCPmeLf6w==
+"@polkadot/typegen@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/typegen/-/typegen-8.7.2-15.tgz#06e9d054db1c63d9862186429a8017b2b80bce2a"
+  integrity sha512-NC8Ticirh20k1Co17D8cqQawIJ8W9HWDuq6oDyEMT4XkeBbZ1hQRO9JBO14neWDJmYJBhlUotP65jgjs8D5bMw==
   dependencies:
     "@babel/core" "^7.18.2"
     "@babel/register" "^7.17.7"
     "@babel/runtime" "^7.18.3"
-    "@polkadot/api" "8.7.2-11"
-    "@polkadot/api-augment" "8.7.2-11"
-    "@polkadot/rpc-augment" "8.7.2-11"
-    "@polkadot/rpc-provider" "8.7.2-11"
-    "@polkadot/types" "8.7.2-11"
-    "@polkadot/types-augment" "8.7.2-11"
-    "@polkadot/types-codec" "8.7.2-11"
-    "@polkadot/types-create" "8.7.2-11"
-    "@polkadot/types-support" "8.7.2-11"
+    "@polkadot/api" "8.7.2-15"
+    "@polkadot/api-augment" "8.7.2-15"
+    "@polkadot/rpc-augment" "8.7.2-15"
+    "@polkadot/rpc-provider" "8.7.2-15"
+    "@polkadot/types" "8.7.2-15"
+    "@polkadot/types-augment" "8.7.2-15"
+    "@polkadot/types-codec" "8.7.2-15"
+    "@polkadot/types-create" "8.7.2-15"
+    "@polkadot/types-support" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
     "@polkadot/x-ws" "^9.4.1"
     handlebars "^4.7.7"
     websocket "^1.0.34"
     yargs "^17.5.1"
 
-"@polkadot/types-augment@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/types-augment/-/types-augment-8.7.2-11.tgz#c63105c76f8d85f7e642f8e81e16c3ffc3b3e7c4"
-  integrity sha512-1meIbpS0Synfdz+Jo90jc/utxwbwl9XQiH5WoFCUYLlbtE/H/yQcIoeme5o6gr/q7BalFQMYYwGBfctGT/KGjA==
+"@polkadot/types-augment@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/types-augment/-/types-augment-8.7.2-15.tgz#7ab077a1a31190ad17183196efb1da065c0d0bcd"
+  integrity sha512-th1jVBDqpyQVB2gCNzo/HV0dIeNinjyPla01BFdhQ5mDKYXJ8fugsLCk5oKUPpItBrj+5NWCgynVvCwm0YJw3g==
   dependencies:
     "@babel/runtime" "^7.18.3"
-    "@polkadot/types" "8.7.2-11"
-    "@polkadot/types-codec" "8.7.2-11"
+    "@polkadot/types" "8.7.2-15"
+    "@polkadot/types-codec" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
 
-"@polkadot/types-codec@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/types-codec/-/types-codec-8.7.2-11.tgz#a852d3493062ee1052f7a837d07cce4146f2c67e"
-  integrity sha512-ZvRBiVo5IwZ+vcbKIMv6l0kRG2bVpBmU+pCPdWV9zGtKpgumz1FTvxBmjXoNo6OJVX23fKNMF8qBD/DEiC9ZwA==
+"@polkadot/types-codec@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/types-codec/-/types-codec-8.7.2-15.tgz#6afa4ff45dc7afb9250f283f70a40be641367941"
+  integrity sha512-k8t7/Ern7sY4ZKQc5cYY3h1bg7/GAEaTPmKz094DhPJmEhi3NNgeJ4uyeB/JYCo5GbxXQG6W2M021s582urjMw==
   dependencies:
     "@babel/runtime" "^7.18.3"
     "@polkadot/util" "^9.4.1"
 
-"@polkadot/types-create@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/types-create/-/types-create-8.7.2-11.tgz#2489409155d55c941a322349d740e9f8f8325147"
-  integrity sha512-489UaZP7JKfZ2Fn0oDQ32setAiV7vv9Q3Kg4a+j4m2TGEEXAVeiNE4Uvijmsw3ayLTtzO9hL0WtMpFWa8GlIMg==
+"@polkadot/types-create@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/types-create/-/types-create-8.7.2-15.tgz#106a11eb71dc2743b140d8640a3b3e7fc5ccf10e"
+  integrity sha512-xB9jAJ3XQh/U05b+X77m5TPh4N9oBwwpePkAmLhovTSOSeobj7qeUKrZqccs0BSxJnJPlLwrwuusjeTtTfZCHw==
   dependencies:
     "@babel/runtime" "^7.18.3"
-    "@polkadot/types-codec" "8.7.2-11"
+    "@polkadot/types-codec" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
 
-"@polkadot/types-known@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-8.7.2-11.tgz#89cb0cdea197ed3887b30948a560b0cd13b39c23"
-  integrity sha512-ulPQCmwJTJ/MGJGVJZfjWEGq28HGl7D4sOrigbfLOlo6/KyFl2p5H4GUFeF/s+/lGfUQsxfu4Q6QgXDZAOkB1A==
+"@polkadot/types-known@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-8.7.2-15.tgz#171b8d3963a5c38d46f98a7c14be59033f9a4da8"
+  integrity sha512-c5YuuauPCu70chDnV7Fphh7SbAQl8JWj+PoY37I5BACCNFxtUx5KnP93BChiD0QxcHs2QqD6RdjW6O7cVRUKfA==
   dependencies:
     "@babel/runtime" "^7.18.3"
     "@polkadot/networks" "^9.4.1"
-    "@polkadot/types" "8.7.2-11"
-    "@polkadot/types-codec" "8.7.2-11"
-    "@polkadot/types-create" "8.7.2-11"
+    "@polkadot/types" "8.7.2-15"
+    "@polkadot/types-codec" "8.7.2-15"
+    "@polkadot/types-create" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
 
-"@polkadot/types-support@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-8.7.2-11.tgz#ed08331ba1faf7a803e35aafa0692eefd28baa90"
-  integrity sha512-oflUi0eahFMoS3Sxz6EKjZKNl7GMRnd91kClEV0FzR1wEha+3CL1BCXTGV3n8YoJtfztUUNInVHPQTvMW78WvQ==
+"@polkadot/types-support@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-8.7.2-15.tgz#2d726e3d5615383ca97db3f32ee21e2aad077fcb"
+  integrity sha512-Tl6xm9r/uqrKQK1OUdi5X9MaTgplBYPj3tY9677ZPV7QGYWt0Uz912u9fC2v0PGNReDXtzvrlgvk0aoErwzF5Q==
   dependencies:
     "@babel/runtime" "^7.18.3"
     "@polkadot/util" "^9.4.1"
 
-"@polkadot/types@8.7.2-11":
-  version "8.7.2-11"
-  resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-8.7.2-11.tgz#84b1dca2896fec4af23d4096fa810b59f44071ac"
-  integrity sha512-PSreCXr/csWpMVqtByEj7Pk5j+JEqxOiipsP+PdtOJaRnWtBMFpMqs7Fj2uULVYqFJKKPyp+JofnRDRcH1YDYg==
+"@polkadot/types@8.7.2-15":
+  version "8.7.2-15"
+  resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-8.7.2-15.tgz#5b25b6b76c916637a1d15133b5880a73079e65bc"
+  integrity sha512-KfJKzk6/Ta8vZVJH8+xYYPvd9SD+4fdl4coGgKuPGYZFsjDGnYvAX4ls6/WKby51JK5s24sqaUP3vZisIgh4wA==
   dependencies:
     "@babel/runtime" "^7.18.3"
     "@polkadot/keyring" "^9.4.1"
-    "@polkadot/types-augment" "8.7.2-11"
-    "@polkadot/types-codec" "8.7.2-11"
-    "@polkadot/types-create" "8.7.2-11"
+    "@polkadot/types-augment" "8.7.2-15"
+    "@polkadot/types-codec" "8.7.2-15"
+    "@polkadot/types-create" "8.7.2-15"
     "@polkadot/util" "^9.4.1"
     "@polkadot/util-crypto" "^9.4.1"
     rxjs "^7.5.5"