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

difftreelog

fix PR

Trubnikov Sergey2022-12-12parent: #6028430.patch.diff
in: master

18 files changed

modifiedpallets/common/src/lib.rsdiffbeforeafterboth
before · pallets/common/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//! # Common pallet18//!19//! The Common pallet provides functionality for handling collections.20//!21//! ## Overview22//!23//! The Common pallet provides an interface for common collection operations for different collection types24//! (see [CommonCollectionOperations]), as well as a generic dispatcher for these, see [dispatch] module.25//! It also provides this functionality to EVM, see [erc] and [eth] modules.26//!27//! The Common pallet provides functions for:28//!29//! - Setting and approving collection sponsor.30//! - Get\set\delete allow list.31//! - Get\set\delete collection properties.32//! - Get\set\delete collection property permissions.33//! - Get\set\delete token property permissions.34//! - Get\set\delete collection administrators.35//! - Checking access permissions.36//!37//! ### Terminology38//! **Collection sponsor** - For the collection, you can set a sponsor, at whose expense it will39//! be possible to mint tokens.40//!41//! **Allow list** - List of users who have the right to minting tokens.42//!43//! **Collection properties** - Collection properties are simply key-value stores where various44//! metadata can be placed.45//!46//! **Permissions on token properties** - For each property in the token can be set permission47//! to change, see [`PropertyPermission`].48//!49//! **Collection administrator** - For a collection, you can set administrators who have the right50//! to most actions on the collection.5152#![warn(missing_docs)]53#![cfg_attr(not(feature = "std"), no_std)]54extern crate alloc;5556use core::ops::{Deref, DerefMut};57use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};58use sp_std::vec::Vec;59use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};60use evm_coder::ToLog;61use frame_support::{62	dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, Weight, PostDispatchInfo},63	ensure,64	traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement},65	dispatch::Pays,66	transactional,67};68use pallet_evm::GasWeightMapping;69use up_data_structs::{70	COLLECTION_NUMBER_LIMIT,71	Collection,72	RpcCollection,73	CollectionFlags,74	RpcCollectionFlags,75	CollectionId,76	CreateItemData,77	MAX_TOKEN_PREFIX_LENGTH,78	COLLECTION_ADMINS_LIMIT,79	TokenId,80	TokenChild,81	CollectionStats,82	MAX_TOKEN_OWNERSHIP,83	CollectionMode,84	NFT_SPONSOR_TRANSFER_TIMEOUT,85	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,86	REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,87	MAX_SPONSOR_TIMEOUT,88	CUSTOM_DATA_LIMIT,89	CollectionLimits,90	CreateCollectionData,91	SponsorshipState,92	CreateItemExData,93	SponsoringRateLimit,94	budget::Budget,95	PhantomType,96	Property,97	Properties,98	PropertiesPermissionMap,99	PropertyKey,100	PropertyValue,101	PropertyPermission,102	PropertiesError,103	PropertyKeyPermission,104	TokenData,105	TrySetProperty,106	PropertyScope,107	// RMRK108	RmrkCollectionInfo,109	RmrkInstanceInfo,110	RmrkResourceInfo,111	RmrkPropertyInfo,112	RmrkBaseInfo,113	RmrkPartType,114	RmrkBoundedTheme,115	RmrkNftChild,116	CollectionPermissions,117};118119pub use pallet::*;120use sp_core::H160;121use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};122#[cfg(feature = "runtime-benchmarks")]123pub mod benchmarking;124pub mod dispatch;125pub mod erc;126pub mod eth;127pub mod weights;128129/// Weight info.130pub type SelfWeightOf<T> = <T as Config>::WeightInfo;131132/// Collection handle contains information about collection data and id.133/// Also provides functionality to count consumed gas.134///135/// CollectionHandle is used as a generic wrapper for collections of all types.136/// It allows to perform common operations and queries on any collection type,137/// both completely general for all, as well as their respective implementations of [`CommonCollectionOperations`].138#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]139pub struct CollectionHandle<T: Config> {140	/// Collection id141	pub id: CollectionId,142	collection: Collection<T::AccountId>,143	/// Substrate recorder for counting consumed gas144	pub recorder: SubstrateRecorder<T>,145}146147impl<T: Config> WithRecorder<T> for CollectionHandle<T> {148	fn recorder(&self) -> &SubstrateRecorder<T> {149		&self.recorder150	}151	fn into_recorder(self) -> SubstrateRecorder<T> {152		self.recorder153	}154}155156impl<T: Config> CollectionHandle<T> {157	/// Same as [CollectionHandle::new] but with an explicit gas limit.158	pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {159		<CollectionById<T>>::get(id).map(|collection| Self {160			id,161			collection,162			recorder: SubstrateRecorder::new(gas_limit),163		})164	}165166	/// Same as [CollectionHandle::new] but with an existed [`SubstrateRecorder`].167	pub fn new_with_recorder(id: CollectionId, recorder: SubstrateRecorder<T>) -> Option<Self> {168		<CollectionById<T>>::get(id).map(|collection| Self {169			id,170			collection,171			recorder,172		})173	}174175	/// Retrives collection data from storage and creates collection handle with default parameters.176	/// If collection not found return `None`177	pub fn new(id: CollectionId) -> Option<Self> {178		Self::new_with_gas_limit(id, u64::MAX)179	}180181	/// Same as [`CollectionHandle::new`] but if collection not found [CollectionNotFound](Error::CollectionNotFound) returned.182	pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {183		Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)184	}185186	/// Consume gas for reading.187	pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {188		self.recorder189			.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_ref_time(190				<T as frame_system::Config>::DbWeight::get()191					.read192					.saturating_mul(reads),193			)))194	}195196	/// Consume gas for writing.197	pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {198		self.recorder199			.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_ref_time(200				<T as frame_system::Config>::DbWeight::get()201					.write202					.saturating_mul(writes),203			)))204	}205206	/// Consume gas for reading and writing.207	pub fn consume_store_reads_and_writes(208		&self,209		reads: u64,210		writes: u64,211	) -> evm_coder::execution::Result<()> {212		let weight = <T as frame_system::Config>::DbWeight::get();213		let reads = weight.read.saturating_mul(reads);214		let writes = weight.read.saturating_mul(writes);215		self.recorder216			.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_ref_time(217				reads.saturating_add(writes),218			)))219	}220221	/// Save collection to storage.222	pub fn save(&self) -> DispatchResult {223		<CollectionById<T>>::insert(self.id, &self.collection);224		Ok(())225	}226227	/// Set collection sponsor.228	///229	/// Unique collections allows sponsoring for certain actions.230	/// This method allows you to set the sponsor of the collection.231	/// In order for sponsorship to become active, it must be confirmed through [`Self::confirm_sponsorship`].232	pub fn set_sponsor(233		&mut self,234		sender: &T::CrossAccountId,235		sponsor: T::AccountId,236	) -> DispatchResult {237		self.check_is_internal()?;238		self.check_is_owner_or_admin(sender)?;239240		self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor.clone());241242		<Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(self.id, sponsor));243		<PalletEvm<T>>::deposit_log(244			erc::CollectionHelpersEvents::CollectionChanged {245				collection_id: eth::collection_id_to_address(self.id),246			}247			.to_log(T::ContractAddress::get()),248		);249250		self.save()251	}252253	/// Force set `sponsor`.254	///255	/// Differs from [`set_sponsor`][`Self::set_sponsor`] in that confirmation256	/// from the `sponsor` is not required.257	///258	/// # Arguments259	///260	/// * `sender`: Caller's account.261	/// * `sponsor`: ID of the account of the sponsor-to-be.262	pub fn force_set_sponsor(&mut self, sponsor: T::AccountId) -> DispatchResult {263		self.check_is_internal()?;264265		self.collection.sponsorship = SponsorshipState::Confirmed(sponsor.clone());266267		<Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(self.id, sponsor.clone()));268		<Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(self.id, sponsor));269		<PalletEvm<T>>::deposit_log(270			erc::CollectionHelpersEvents::CollectionChanged {271				collection_id: eth::collection_id_to_address(self.id),272			}273			.to_log(T::ContractAddress::get()),274		);275276		self.save()277	}278279	/// Confirm sponsorship280	///281	/// In order for the sponsorship to become active, the user set as the sponsor must confirm their participation.282	/// Before confirming sponsorship, the user must be specified as the sponsor of the collection via [`Self::set_sponsor`].283	pub fn confirm_sponsorship(&mut self, sender: &T::AccountId) -> DispatchResult {284		self.check_is_internal()?;285		ensure!(286			self.collection.sponsorship.pending_sponsor() == Some(sender),287			Error::<T>::ConfirmUnsetSponsorFail288		);289290		self.collection.sponsorship = SponsorshipState::Confirmed(sender.clone());291292		<Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(self.id, sender.clone()));293		<PalletEvm<T>>::deposit_log(294			erc::CollectionHelpersEvents::CollectionChanged {295				collection_id: eth::collection_id_to_address(self.id),296			}297			.to_log(T::ContractAddress::get()),298		);299300		self.save()301	}302303	/// Remove collection sponsor.304	pub fn remove_sponsor(&mut self, sender: &T::CrossAccountId) -> DispatchResult {305		self.check_is_internal()?;306		self.check_is_owner(sender)?;307308		self.collection.sponsorship = SponsorshipState::Disabled;309310		<Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(self.id));311		<PalletEvm<T>>::deposit_log(312			erc::CollectionHelpersEvents::CollectionChanged {313				collection_id: eth::collection_id_to_address(self.id),314			}315			.to_log(T::ContractAddress::get()),316		);317		self.save()318	}319320	/// Force remove `sponsor`.321	///322	/// Differs from `remove_sponsor` in that323	/// it doesn't require consent from the `owner` of the collection.324	pub fn force_remove_sponsor(&mut self) -> DispatchResult {325		self.check_is_internal()?;326327		self.collection.sponsorship = SponsorshipState::Disabled;328329		<Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(self.id));330		<PalletEvm<T>>::deposit_log(331			erc::CollectionHelpersEvents::CollectionChanged {332				collection_id: eth::collection_id_to_address(self.id),333			}334			.to_log(T::ContractAddress::get()),335		);336		self.save()337	}338339	/// Checks that the collection was created with, and must be operated upon through **Unique API**.340	/// Now check only the `external` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error.341	pub fn check_is_internal(&self) -> DispatchResult {342		if self.flags.external {343			return Err(<Error<T>>::CollectionIsExternal)?;344		}345346		Ok(())347	}348349	/// Checks that the collection was created with, and must be operated upon through an **assimilated API**.350	/// Now check only the `external` flag and if it's **false**, then return [`Error::CollectionIsInternal`] error.351	pub fn check_is_external(&self) -> DispatchResult {352		if !self.flags.external {353			return Err(<Error<T>>::CollectionIsInternal)?;354		}355356		Ok(())357	}358}359360impl<T: Config> Deref for CollectionHandle<T> {361	type Target = Collection<T::AccountId>;362363	fn deref(&self) -> &Self::Target {364		&self.collection365	}366}367368impl<T: Config> DerefMut for CollectionHandle<T> {369	fn deref_mut(&mut self) -> &mut Self::Target {370		&mut self.collection371	}372}373374impl<T: Config> CollectionHandle<T> {375	/// Checks if the `user` is the owner of the collection.376	pub fn check_is_owner(&self, user: &T::CrossAccountId) -> DispatchResult {377		ensure!(*user.as_sub() == self.owner, <Error<T>>::NoPermission);378		Ok(())379	}380381	/// Returns **true** if the `user` is the owner or administrator of the collection.382	pub fn is_owner_or_admin(&self, user: &T::CrossAccountId) -> bool {383		*user.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, user))384	}385386	/// Checks if the `user` is the owner or administrator of the collection.387	pub fn check_is_owner_or_admin(&self, user: &T::CrossAccountId) -> DispatchResult {388		ensure!(self.is_owner_or_admin(user), <Error<T>>::NoPermission);389		Ok(())390	}391392	/// Return **true** if `user` was not allowed to have tokens, and he can ignore such restrictions.393	pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {394		self.limits.owner_can_transfer() && self.is_owner_or_admin(user)395	}396397	/// Return **true** if `user` does not have enough token parts, and he can ignore such restrictions.398	pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> bool {399		self.limits.owner_can_transfer() && self.is_owner_or_admin(user)400	}401402	/// Checks if the user is in the allow list. If not [Error::AddressNotInAllowlist] returns.403	pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {404		ensure!(405			<Allowlist<T>>::get((self.id, user)),406			<Error<T>>::AddressNotInAllowlist407		);408		Ok(())409	}410411	/// Changes collection owner to another account412	/// #### Store read/writes413	/// 1 writes414	pub fn change_owner(415		&mut self,416		caller: T::CrossAccountId,417		new_owner: T::CrossAccountId,418	) -> DispatchResult {419		self.check_is_internal()?;420		self.check_is_owner(&caller)?;421		self.collection.owner = new_owner.as_sub().clone();422423		<Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(424			self.id,425			new_owner.as_sub().clone(),426		));427		<PalletEvm<T>>::deposit_log(428			erc::CollectionHelpersEvents::CollectionChanged {429				collection_id: eth::collection_id_to_address(self.id),430			}431			.to_log(T::ContractAddress::get()),432		);433434		self.save()435	}436}437438#[frame_support::pallet]439pub mod pallet {440	use super::*;441	use dispatch::CollectionDispatch;442	use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key, traits::StorageVersion};443	use frame_system::pallet_prelude::*;444	use frame_support::traits::Currency;445	use up_data_structs::{TokenId, mapping::TokenAddressMapping};446	use scale_info::TypeInfo;447	use weights::WeightInfo;448449	#[pallet::config]450	pub trait Config:451		frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::Config + TypeInfo452	{453		/// Weight information for functions of this pallet.454		type WeightInfo: WeightInfo;455456		/// Events compatible with [`frame_system::Config::Event`].457		type RuntimeEvent: IsType<<Self as frame_system::Config>::RuntimeEvent> + From<Event<Self>>;458459		/// Handler of accounts and payment.460		type Currency: Currency<Self::AccountId>;461462		/// Set price to create a collection.463		#[pallet::constant]464		type CollectionCreationPrice: Get<465			<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,466		>;467468		/// Dispatcher of operations on collections.469		type CollectionDispatch: CollectionDispatch<Self>;470471		/// Account which holds the chain's treasury.472		type TreasuryAccountId: Get<Self::AccountId>;473474		/// Address under which the CollectionHelper contract would be available.475		#[pallet::constant]476		type ContractAddress: Get<H160>;477478		/// Mapper for token addresses to Ethereum addresses.479		type EvmTokenAddressMapping: TokenAddressMapping<H160>;480481		/// Mapper for token addresses to [`CrossAccountId`].482		type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;483	}484485	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);486487	#[pallet::pallet]488	#[pallet::storage_version(STORAGE_VERSION)]489	#[pallet::generate_store(pub(super) trait Store)]490	pub struct Pallet<T>(_);491492	#[pallet::extra_constants]493	impl<T: Config> Pallet<T> {494		/// Maximum admins per collection.495		pub fn collection_admins_limit() -> u32 {496			COLLECTION_ADMINS_LIMIT497		}498	}499500	#[pallet::event]501	#[pallet::generate_deposit(pub fn deposit_event)]502	pub enum Event<T: Config> {503		/// New collection was created504		CollectionCreated(505			/// Globally unique identifier of newly created collection.506			CollectionId,507			/// [`CollectionMode`] converted into _u8_.508			u8,509			/// Collection owner.510			T::AccountId,511		),512513		/// New collection was destroyed514		CollectionDestroyed(515			/// Globally unique identifier of collection.516			CollectionId,517		),518519		/// New item was created.520		ItemCreated(521			/// Id of the collection where item was created.522			CollectionId,523			/// Id of an item. Unique within the collection.524			TokenId,525			/// Owner of newly created item526			T::CrossAccountId,527			/// Always 1 for NFT528			u128,529		),530531		/// Collection item was burned.532		ItemDestroyed(533			/// Id of the collection where item was destroyed.534			CollectionId,535			/// Identifier of burned NFT.536			TokenId,537			/// Which user has destroyed its tokens.538			T::CrossAccountId,539			/// Amount of token pieces destroed. Always 1 for NFT.540			u128,541		),542543		/// Item was transferred544		Transfer(545			/// Id of collection to which item is belong.546			CollectionId,547			/// Id of an item.548			TokenId,549			/// Original owner of item.550			T::CrossAccountId,551			/// New owner of item.552			T::CrossAccountId,553			/// Amount of token pieces transfered. Always 1 for NFT.554			u128,555		),556557		/// Amount pieces of token owned by `sender` was approved for `spender`.558		Approved(559			/// Id of collection to which item is belong.560			CollectionId,561			/// Id of an item.562			TokenId,563			/// Original owner of item.564			T::CrossAccountId,565			/// Id for which the approval was granted.566			T::CrossAccountId,567			/// Amount of token pieces transfered. Always 1 for NFT.568			u128,569		),570571		/// A `sender` approves operations on all owned tokens for `spender`.572		ApprovedForAll(573			/// Id of collection to which item is belong.574			CollectionId,575			/// Owner of a wallet.576			T::CrossAccountId,577			/// Id for which operator status was granted or rewoked.578			T::CrossAccountId,579			/// Is operator status granted or revoked?580			bool,581		),582583		/// The colletion property has been added or edited.584		CollectionPropertySet(585			/// Id of collection to which property has been set.586			CollectionId,587			/// The property that was set.588			PropertyKey,589		),590591		/// The property has been deleted.592		CollectionPropertyDeleted(593			/// Id of collection to which property has been deleted.594			CollectionId,595			/// The property that was deleted.596			PropertyKey,597		),598599		/// The token property has been added or edited.600		TokenPropertySet(601			/// Identifier of the collection whose token has the property set.602			CollectionId,603			/// The token for which the property was set.604			TokenId,605			/// The property that was set.606			PropertyKey,607		),608609		/// The token property has been deleted.610		TokenPropertyDeleted(611			/// Identifier of the collection whose token has the property deleted.612			CollectionId,613			/// The token for which the property was deleted.614			TokenId,615			/// The property that was deleted.616			PropertyKey,617		),618619		/// The token property permission of a collection has been set.620		PropertyPermissionSet(621			/// ID of collection to which property permission has been set.622			CollectionId,623			/// The property permission that was set.624			PropertyKey,625		),626627		/// Address was added to the allow list.628		AllowListAddressAdded(629			/// ID of the affected collection.630			CollectionId,631			/// Address of the added account.632			T::CrossAccountId,633		),634635		/// Address was removed from the allow list.636		AllowListAddressRemoved(637			/// ID of the affected collection.638			CollectionId,639			/// Address of the removed account.640			T::CrossAccountId,641		),642643		/// Collection admin was added.644		CollectionAdminAdded(645			/// ID of the affected collection.646			CollectionId,647			/// Admin address.648			T::CrossAccountId,649		),650651		/// Collection admin was removed.652		CollectionAdminRemoved(653			/// ID of the affected collection.654			CollectionId,655			/// Removed admin address.656			T::CrossAccountId,657		),658659		/// Collection limits were set.660		CollectionLimitSet(661			/// ID of the affected collection.662			CollectionId,663		),664665		/// Collection owned was changed.666		CollectionOwnedChanged(667			/// ID of the affected collection.668			CollectionId,669			/// New owner address.670			T::AccountId,671		),672673		/// Collection permissions were set.674		CollectionPermissionSet(675			/// ID of the affected collection.676			CollectionId,677		),678679		/// Collection sponsor was set.680		CollectionSponsorSet(681			/// ID of the affected collection.682			CollectionId,683			/// New sponsor address.684			T::AccountId,685		),686687		/// New sponsor was confirm.688		SponsorshipConfirmed(689			/// ID of the affected collection.690			CollectionId,691			/// New sponsor address.692			T::AccountId,693		),694695		/// Collection sponsor was removed.696		CollectionSponsorRemoved(697			/// ID of the affected collection.698			CollectionId,699		),700	}701702	#[pallet::error]703	pub enum Error<T> {704		/// This collection does not exist.705		CollectionNotFound,706		/// Sender parameter and item owner must be equal.707		MustBeTokenOwner,708		/// No permission to perform action709		NoPermission,710		/// Destroying only empty collections is allowed711		CantDestroyNotEmptyCollection,712		/// Collection is not in mint mode.713		PublicMintingNotAllowed,714		/// Address is not in allow list.715		AddressNotInAllowlist,716717		/// Collection name can not be longer than 63 char.718		CollectionNameLimitExceeded,719		/// Collection description can not be longer than 255 char.720		CollectionDescriptionLimitExceeded,721		/// Token prefix can not be longer than 15 char.722		CollectionTokenPrefixLimitExceeded,723		/// Total collections bound exceeded.724		TotalCollectionsLimitExceeded,725		/// Exceeded max admin count726		CollectionAdminCountExceeded,727		/// Collection limit bounds per collection exceeded728		CollectionLimitBoundsExceeded,729		/// Tried to enable permissions which are only permitted to be disabled730		OwnerPermissionsCantBeReverted,731		/// Collection settings not allowing items transferring732		TransferNotAllowed,733		/// Account token limit exceeded per collection734		AccountTokenLimitExceeded,735		/// Collection token limit exceeded736		CollectionTokenLimitExceeded,737		/// Metadata flag frozen738		MetadataFlagFrozen,739740		/// Item does not exist741		TokenNotFound,742		/// Item is balance not enough743		TokenValueTooLow,744		/// Requested value is more than the approved745		ApprovedValueTooLow,746		/// Tried to approve more than owned747		CantApproveMoreThanOwned,748749		/// Can't transfer tokens to ethereum zero address750		AddressIsZero,751752		/// The operation is not supported753		UnsupportedOperation,754755		/// Insufficient funds to perform an action756		NotSufficientFounds,757758		/// User does not satisfy the nesting rule759		UserIsNotAllowedToNest,760		/// Only tokens from specific collections may nest tokens under this one761		SourceCollectionIsNotAllowedToNest,762763		/// Tried to store more data than allowed in collection field764		CollectionFieldSizeExceeded,765766		/// Tried to store more property data than allowed767		NoSpaceForProperty,768769		/// Tried to store more property keys than allowed770		PropertyLimitReached,771772		/// Property key is too long773		PropertyKeyIsTooLong,774775		/// Only ASCII letters, digits, and symbols `_`, `-`, and `.` are allowed776		InvalidCharacterInPropertyKey,777778		/// Empty property keys are forbidden779		EmptyPropertyKey,780781		/// Tried to access an external collection with an internal API782		CollectionIsExternal,783784		/// Tried to access an internal collection with an external API785		CollectionIsInternal,786787		/// This address is not set as sponsor, use setCollectionSponsor first.788		ConfirmUnsetSponsorFail,789790		/// The user is not an administrator.791		UserIsNotAdmin,792	}793794	/// Storage of the count of created collections. Essentially contains the last collection ID.795	#[pallet::storage]796	pub type CreatedCollectionCount<T> = StorageValue<Value = CollectionId, QueryKind = ValueQuery>;797798	/// Storage of the count of deleted collections.799	#[pallet::storage]800	pub type DestroyedCollectionCount<T> =801		StorageValue<Value = CollectionId, QueryKind = ValueQuery>;802803	/// Storage of collection info.804	#[pallet::storage]805	pub type CollectionById<T> = StorageMap<806		Hasher = Blake2_128Concat,807		Key = CollectionId,808		Value = Collection<<T as frame_system::Config>::AccountId>,809		QueryKind = OptionQuery,810	>;811812	/// Storage of collection properties.813	#[pallet::storage]814	#[pallet::getter(fn collection_properties)]815	pub type CollectionProperties<T> = StorageMap<816		Hasher = Blake2_128Concat,817		Key = CollectionId,818		Value = Properties,819		QueryKind = ValueQuery,820		OnEmpty = up_data_structs::CollectionProperties,821	>;822823	/// Storage of token property permissions of a collection.824	#[pallet::storage]825	#[pallet::getter(fn property_permissions)]826	pub type CollectionPropertyPermissions<T> = StorageMap<827		Hasher = Blake2_128Concat,828		Key = CollectionId,829		Value = PropertiesPermissionMap,830		QueryKind = ValueQuery,831	>;832833	/// Storage of the amount of collection admins.834	#[pallet::storage]835	pub type AdminAmount<T> = StorageMap<836		Hasher = Blake2_128Concat,837		Key = CollectionId,838		Value = u32,839		QueryKind = ValueQuery,840	>;841842	/// List of collection admins.843	#[pallet::storage]844	pub type IsAdmin<T: Config> = StorageNMap<845		Key = (846			Key<Blake2_128Concat, CollectionId>,847			Key<Blake2_128Concat, T::CrossAccountId>,848		),849		Value = bool,850		QueryKind = ValueQuery,851	>;852853	/// Allowlisted collection users.854	#[pallet::storage]855	pub type Allowlist<T: Config> = StorageNMap<856		Key = (857			Key<Blake2_128Concat, CollectionId>,858			Key<Blake2_128Concat, T::CrossAccountId>,859		),860		Value = bool,861		QueryKind = ValueQuery,862	>;863864	/// Not used by code, exists only to provide some types to metadata.865	#[pallet::storage]866	pub type DummyStorageValue<T: Config> = StorageValue<867		Value = (868			CollectionStats,869			CollectionId,870			TokenId,871			TokenChild,872			PhantomType<(873				TokenData<T::CrossAccountId>,874				RpcCollection<T::AccountId>,875				// RMRK876				RmrkCollectionInfo<T::AccountId>,877				RmrkInstanceInfo<T::AccountId>,878				RmrkResourceInfo,879				RmrkPropertyInfo,880				RmrkBaseInfo<T::AccountId>,881				RmrkPartType,882				RmrkBoundedTheme,883				RmrkNftChild,884			)>,885		),886		QueryKind = OptionQuery,887	>;888889	#[pallet::hooks]890	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {891		fn on_runtime_upgrade() -> Weight {892			StorageVersion::new(1).put::<Pallet<T>>();893894			Weight::zero()895		}896	}897}898899impl<T: Config> Pallet<T> {900	/// Enshure that receiver address is correct.901	///902	/// Ethereum receiver 0x0000000000000000000000000000000000000000 is reserved, and shouldn't own tokens.903	pub fn ensure_correct_receiver(receiver: &T::CrossAccountId) -> DispatchResult {904		ensure!(905			&T::CrossAccountId::from_eth(H160([0; 20])) != receiver,906			<Error<T>>::AddressIsZero907		);908		Ok(())909	}910911	/// Get a vector of collection admins.912	pub fn adminlist(collection: CollectionId) -> Vec<T::CrossAccountId> {913		<IsAdmin<T>>::iter_prefix((collection,))914			.map(|(a, _)| a)915			.collect()916	}917918	/// Get a vector of users allowed to mint tokens.919	pub fn allowlist(collection: CollectionId) -> Vec<T::CrossAccountId> {920		<Allowlist<T>>::iter_prefix((collection,))921			.map(|(a, _)| a)922			.collect()923	}924925	/// Is `user` allowed to mint token in `collection`.926	pub fn allowed(collection: CollectionId, user: T::CrossAccountId) -> bool {927		<Allowlist<T>>::get((collection, user))928	}929930	/// Get statistics of collections.931	pub fn collection_stats() -> CollectionStats {932		let created = <CreatedCollectionCount<T>>::get();933		let destroyed = <DestroyedCollectionCount<T>>::get();934		CollectionStats {935			created: created.0,936			destroyed: destroyed.0,937			alive: created.0 - destroyed.0,938		}939	}940941	/// Get the effective limits for the collection.942	pub fn effective_collection_limits(collection: CollectionId) -> Option<CollectionLimits> {943		let collection = <CollectionById<T>>::get(collection)?;944		let limits = collection.limits;945		let effective_limits = CollectionLimits {946			account_token_ownership_limit: Some(limits.account_token_ownership_limit()),947			sponsored_data_size: Some(limits.sponsored_data_size()),948			sponsored_data_rate_limit: Some(949				limits950					.sponsored_data_rate_limit951					.unwrap_or(SponsoringRateLimit::SponsoringDisabled),952			),953			token_limit: Some(limits.token_limit()),954			sponsor_transfer_timeout: Some(limits.sponsor_transfer_timeout(955				match collection.mode {956					CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,957					CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,958					CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,959				},960			)),961			sponsor_approve_timeout: Some(limits.sponsor_approve_timeout()),962			owner_can_transfer: Some(limits.owner_can_transfer()),963			owner_can_destroy: Some(limits.owner_can_destroy()),964			transfers_enabled: Some(limits.transfers_enabled()),965		};966967		Some(effective_limits)968	}969970	/// Returns information about the `collection` adapted for rpc.971	pub fn rpc_collection(collection: CollectionId) -> Option<RpcCollection<T::AccountId>> {972		let Collection {973			name,974			description,975			owner,976			mode,977			token_prefix,978			sponsorship,979			limits,980			permissions,981			flags,982		} = <CollectionById<T>>::get(collection)?;983984		let token_property_permissions = <CollectionPropertyPermissions<T>>::get(collection)985			.into_iter()986			.map(|(key, permission)| PropertyKeyPermission { key, permission })987			.collect();988989		let properties = <CollectionProperties<T>>::get(collection)990			.into_iter()991			.map(|(key, value)| Property { key, value })992			.collect();993994		let permissions = CollectionPermissions {995			access: Some(permissions.access()),996			mint_mode: Some(permissions.mint_mode()),997			nesting: Some(permissions.nesting().clone()),998		};9991000		Some(RpcCollection {1001			name: name.into_inner(),1002			description: description.into_inner(),1003			owner,1004			mode,1005			token_prefix: token_prefix.into_inner(),1006			sponsorship,1007			limits,1008			permissions,1009			token_property_permissions,1010			properties,1011			read_only: flags.external,10121013			flags: RpcCollectionFlags {1014				foreign: flags.foreign,1015				erc721metadata: flags.erc721metadata,1016			},1017		})1018	}1019}10201021macro_rules! limit_default {1022	($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{1023		$(1024			if let Some($new) = $new.$field {1025				let $old = $old.$field($($arg)?);1026				let _ = $new;1027				let _ = $old;1028				$check1029			} else {1030				$new.$field = $old.$field1031			}1032		)*1033	}};1034}1035macro_rules! limit_default_clone {1036	($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{1037		$(1038			if let Some($new) = $new.$field.clone() {1039				let $old = $old.$field($($arg)?);1040				let _ = $new;1041				let _ = $old;1042				$check1043			} else {1044				$new.$field = $old.$field.clone()1045			}1046		)*1047	}};1048}10491050impl<T: Config> Pallet<T> {1051	/// Create new collection.1052	///1053	/// * `owner` - The owner of the collection.1054	/// * `data` - Description of the created collection.1055	/// * `flags` - Extra flags to store.1056	pub fn init_collection(1057		owner: T::CrossAccountId,1058		payer: T::CrossAccountId,1059		data: CreateCollectionData<T::AccountId>,1060		flags: CollectionFlags,1061	) -> Result<CollectionId, DispatchError> {1062		{1063			ensure!(1064				data.token_prefix.len() <= MAX_TOKEN_PREFIX_LENGTH as usize,1065				Error::<T>::CollectionTokenPrefixLimitExceeded1066			);1067		}10681069		let created_count = <CreatedCollectionCount<T>>::get()1070			.01071			.checked_add(1)1072			.ok_or(ArithmeticError::Overflow)?;1073		let destroyed_count = <DestroyedCollectionCount<T>>::get().0;1074		let id = CollectionId(created_count);10751076		// bound Total number of collections1077		ensure!(1078			created_count - destroyed_count <= COLLECTION_NUMBER_LIMIT,1079			<Error<T>>::TotalCollectionsLimitExceeded1080		);10811082		// =========10831084		let collection = Collection {1085			owner: owner.as_sub().clone(),1086			name: data.name,1087			mode: data.mode.clone(),1088			description: data.description,1089			token_prefix: data.token_prefix,1090			sponsorship: data1091				.pending_sponsor1092				.map(SponsorshipState::Unconfirmed)1093				.unwrap_or_default(),1094			limits: data1095				.limits1096				.map(|limits| Self::clamp_limits(data.mode.clone(), &Default::default(), limits))1097				.unwrap_or_else(|| Ok(CollectionLimits::default()))?,1098			permissions: data1099				.permissions1100				.map(|permissions| {1101					Self::clamp_permissions(data.mode.clone(), &Default::default(), permissions)1102				})1103				.unwrap_or_else(|| Ok(CollectionPermissions::default()))?,1104			flags,1105		};11061107		let mut collection_properties = up_data_structs::CollectionProperties::get();1108		collection_properties1109			.try_set_from_iter(data.properties.into_iter())1110			.map_err(<Error<T>>::from)?;11111112		CollectionProperties::<T>::insert(id, collection_properties);11131114		let mut token_props_permissions = PropertiesPermissionMap::new();1115		token_props_permissions1116			.try_set_from_iter(data.token_property_permissions.into_iter())1117			.map_err(<Error<T>>::from)?;11181119		CollectionPropertyPermissions::<T>::insert(id, token_props_permissions);11201121		// Take a (non-refundable) deposit of collection creation1122		{1123			let mut imbalance =1124				<<<T as Config>::Currency as Currency<T::AccountId>>::PositiveImbalance>::zero();1125			imbalance.subsume(1126				<<T as Config>::Currency as Currency<T::AccountId>>::deposit_creating(1127					&T::TreasuryAccountId::get(),1128					T::CollectionCreationPrice::get(),1129				),1130			);1131			<T as Config>::Currency::settle(1132				payer.as_sub(),1133				imbalance,1134				WithdrawReasons::TRANSFER,1135				ExistenceRequirement::KeepAlive,1136			)1137			.map_err(|_| Error::<T>::NotSufficientFounds)?;1138		}11391140		<CreatedCollectionCount<T>>::put(created_count);1141		<Pallet<T>>::deposit_event(Event::CollectionCreated(1142			id,1143			data.mode.id(),1144			owner.as_sub().clone(),1145		));1146		<PalletEvm<T>>::deposit_log(1147			erc::CollectionHelpersEvents::CollectionCreated {1148				owner: *owner.as_eth(),1149				collection_id: eth::collection_id_to_address(id),1150			}1151			.to_log(T::ContractAddress::get()),1152		);1153		<CollectionById<T>>::insert(id, collection);1154		Ok(id)1155	}11561157	/// Destroy collection.1158	///1159	/// * `collection` - Collection handler.1160	/// * `sender` - The owner or administrator of the collection.1161	pub fn destroy_collection(1162		collection: CollectionHandle<T>,1163		sender: &T::CrossAccountId,1164	) -> DispatchResult {1165		ensure!(1166			collection.limits.owner_can_destroy(),1167			<Error<T>>::NoPermission,1168		);1169		collection.check_is_owner(sender)?;11701171		let destroyed_collections = <DestroyedCollectionCount<T>>::get()1172			.01173			.checked_add(1)1174			.ok_or(ArithmeticError::Overflow)?;11751176		// =========11771178		<DestroyedCollectionCount<T>>::put(destroyed_collections);1179		<CollectionById<T>>::remove(collection.id);1180		<AdminAmount<T>>::remove(collection.id);1181		let _ = <IsAdmin<T>>::clear_prefix((collection.id,), u32::MAX, None);1182		let _ = <Allowlist<T>>::clear_prefix((collection.id,), u32::MAX, None);1183		<CollectionProperties<T>>::remove(collection.id);11841185		<Pallet<T>>::deposit_event(Event::CollectionDestroyed(collection.id));11861187		<PalletEvm<T>>::deposit_log(1188			erc::CollectionHelpersEvents::CollectionDestroyed {1189				collection_id: eth::collection_id_to_address(collection.id),1190			}1191			.to_log(T::ContractAddress::get()),1192		);1193		Ok(())1194	}11951196	/// Set collection property.1197	///1198	/// * `collection` - Collection handler.1199	/// * `sender` - The owner or administrator of the collection.1200	/// * `property` - The property to set.1201	pub fn set_collection_property(1202		collection: &CollectionHandle<T>,1203		sender: &T::CrossAccountId,1204		property: Property,1205	) -> DispatchResult {1206		collection.check_is_owner_or_admin(sender)?;12071208		CollectionProperties::<T>::try_mutate(collection.id, |properties| {1209			let property = property.clone();1210			properties.try_set(property.key, property.value)1211		})1212		.map_err(<Error<T>>::from)?;12131214		Self::deposit_event(Event::CollectionPropertySet(collection.id, property.key));1215		<PalletEvm<T>>::deposit_log(1216			erc::CollectionHelpersEvents::CollectionChanged {1217				collection_id: eth::collection_id_to_address(collection.id),1218			}1219			.to_log(T::ContractAddress::get()),1220		);12211222		Ok(())1223	}12241225	/// Set scouped collection property.1226	///1227	/// * `collection_id` - ID of the collection for which the property is being set.1228	/// * `scope` - Property scope.1229	/// * `property` - The property to set.1230	pub fn set_scoped_collection_property(1231		collection_id: CollectionId,1232		scope: PropertyScope,1233		property: Property,1234	) -> DispatchResult {1235		CollectionProperties::<T>::try_mutate(collection_id, |properties| {1236			properties.try_scoped_set(scope, property.key, property.value)1237		})1238		.map_err(<Error<T>>::from)?;12391240		Ok(())1241	}12421243	/// Set scouped collection properties.1244	///1245	/// * `collection_id` - ID of the collection for which the properties is being set.1246	/// * `scope` - Property scope.1247	/// * `properties` - The properties to set.1248	pub fn set_scoped_collection_properties(1249		collection_id: CollectionId,1250		scope: PropertyScope,1251		properties: impl Iterator<Item = Property>,1252	) -> DispatchResult {1253		CollectionProperties::<T>::try_mutate(collection_id, |stored_properties| {1254			stored_properties.try_scoped_set_from_iter(scope, properties)1255		})1256		.map_err(<Error<T>>::from)?;12571258		Ok(())1259	}12601261	/// Set collection properties.1262	///1263	/// * `collection` - Collection handler.1264	/// * `sender` - The owner or administrator of the collection.1265	/// * `properties` - The properties to set.1266	#[transactional]1267	pub fn set_collection_properties(1268		collection: &CollectionHandle<T>,1269		sender: &T::CrossAccountId,1270		properties: Vec<Property>,1271	) -> DispatchResult {1272		for property in properties {1273			Self::set_collection_property(collection, sender, property)?;1274		}12751276		Ok(())1277	}12781279	/// Delete collection property.1280	///1281	/// * `collection` - Collection handler.1282	/// * `sender` - The owner or administrator of the collection.1283	/// * `property` - The property to delete.1284	pub fn delete_collection_property(1285		collection: &CollectionHandle<T>,1286		sender: &T::CrossAccountId,1287		property_key: PropertyKey,1288	) -> DispatchResult {1289		collection.check_is_owner_or_admin(sender)?;12901291		CollectionProperties::<T>::try_mutate(collection.id, |properties| {1292			properties.remove(&property_key)1293		})1294		.map_err(<Error<T>>::from)?;12951296		Self::deposit_event(Event::CollectionPropertyDeleted(1297			collection.id,1298			property_key,1299		));1300		<PalletEvm<T>>::deposit_log(1301			erc::CollectionHelpersEvents::CollectionChanged {1302				collection_id: eth::collection_id_to_address(collection.id),1303			}1304			.to_log(T::ContractAddress::get()),1305		);13061307		Ok(())1308	}13091310	/// Delete collection properties.1311	///1312	/// * `collection` - Collection handler.1313	/// * `sender` - The owner or administrator of the collection.1314	/// * `properties` - The properties to delete.1315	#[transactional]1316	pub fn delete_collection_properties(1317		collection: &CollectionHandle<T>,1318		sender: &T::CrossAccountId,1319		property_keys: Vec<PropertyKey>,1320	) -> DispatchResult {1321		for key in property_keys {1322			Self::delete_collection_property(collection, sender, key)?;1323		}13241325		Ok(())1326	}13271328	/// Set collection propetry permission without any checks.1329	///1330	/// Used for migrations.1331	///1332	/// * `collection` - Collection handler.1333	/// * `property_permissions` - Property permissions.1334	pub fn set_property_permission_unchecked(1335		collection: CollectionId,1336		property_permission: PropertyKeyPermission,1337	) -> DispatchResult {1338		<CollectionPropertyPermissions<T>>::try_mutate(collection, |permissions| {1339			permissions.try_set(property_permission.key, property_permission.permission)1340		})1341		.map_err(<Error<T>>::from)?;1342		Ok(())1343	}13441345	/// Set collection property permission.1346	///1347	/// * `collection` - Collection handler.1348	/// * `sender` - The owner or administrator of the collection.1349	/// * `property_permission` - Property permission.1350	pub fn set_property_permission(1351		collection: &CollectionHandle<T>,1352		sender: &T::CrossAccountId,1353		property_permission: PropertyKeyPermission,1354	) -> DispatchResult {1355		Self::set_scoped_property_permission(1356			collection,1357			sender,1358			PropertyScope::None,1359			property_permission,1360		)1361	}13621363	/// Set collection property permission with scope.1364	///1365	/// * `collection` - Collection handler.1366	/// * `sender` - The owner or administrator of the collection.1367	/// * `scope` - Property scope.1368	/// * `property_permission` - Property permission.1369	pub fn set_scoped_property_permission(1370		collection: &CollectionHandle<T>,1371		sender: &T::CrossAccountId,1372		scope: PropertyScope,1373		property_permission: PropertyKeyPermission,1374	) -> DispatchResult {1375		collection.check_is_owner_or_admin(sender)?;13761377		let all_permissions = CollectionPropertyPermissions::<T>::get(collection.id);1378		let current_permission = all_permissions.get(&property_permission.key);1379		if matches![1380			current_permission,1381			Some(PropertyPermission { mutable: false, .. })1382		] {1383			return Err(<Error<T>>::NoPermission.into());1384		}13851386		CollectionPropertyPermissions::<T>::try_mutate(collection.id, |permissions| {1387			let property_permission = property_permission.clone();1388			permissions.try_scoped_set(1389				scope,1390				property_permission.key,1391				property_permission.permission,1392			)1393		})1394		.map_err(<Error<T>>::from)?;13951396		Self::deposit_event(Event::PropertyPermissionSet(1397			collection.id,1398			property_permission.key,1399		));1400		<PalletEvm<T>>::deposit_log(1401			erc::CollectionHelpersEvents::CollectionChanged {1402				collection_id: eth::collection_id_to_address(collection.id),1403			}1404			.to_log(T::ContractAddress::get()),1405		);14061407		Ok(())1408	}14091410	/// Set token property permission.1411	///1412	/// * `collection` - Collection handler.1413	/// * `sender` - The owner or administrator of the collection.1414	/// * `property_permissions` - Property permissions.1415	#[transactional]1416	pub fn set_token_property_permissions(1417		collection: &CollectionHandle<T>,1418		sender: &T::CrossAccountId,1419		property_permissions: Vec<PropertyKeyPermission>,1420	) -> DispatchResult {1421		Self::set_scoped_token_property_permissions(1422			collection,1423			sender,1424			PropertyScope::None,1425			property_permissions,1426		)1427	}14281429	/// Set token property permission with scope.1430	///1431	/// * `collection` - Collection handler.1432	/// * `sender` - The owner or administrator of the collection.1433	/// * `scope` - Property scope.1434	/// * `property_permissions` - Property permissions.1435	#[transactional]1436	pub fn set_scoped_token_property_permissions(1437		collection: &CollectionHandle<T>,1438		sender: &T::CrossAccountId,1439		scope: PropertyScope,1440		property_permissions: Vec<PropertyKeyPermission>,1441	) -> DispatchResult {1442		for prop_pemission in property_permissions {1443			Self::set_scoped_property_permission(collection, sender, scope, prop_pemission)?;1444		}14451446		Ok(())1447	}14481449	/// Get collection property.1450	pub fn get_collection_property(1451		collection_id: CollectionId,1452		key: &PropertyKey,1453	) -> Option<PropertyValue> {1454		Self::collection_properties(collection_id).get(key).cloned()1455	}14561457	/// Convert byte vector to property key vector.1458	pub fn bytes_keys_to_property_keys(1459		keys: Vec<Vec<u8>>,1460	) -> Result<Vec<PropertyKey>, DispatchError> {1461		keys.into_iter()1462			.map(|key| -> Result<PropertyKey, DispatchError> {1463				key.try_into()1464					.map_err(|_| <Error<T>>::PropertyKeyIsTooLong.into())1465			})1466			.collect::<Result<Vec<PropertyKey>, DispatchError>>()1467	}14681469	/// Get properties according to given keys.1470	pub fn filter_collection_properties(1471		collection_id: CollectionId,1472		keys: Option<Vec<PropertyKey>>,1473	) -> Result<Vec<Property>, DispatchError> {1474		let properties = Self::collection_properties(collection_id);14751476		let properties = keys1477			.map(|keys| {1478				keys.into_iter()1479					.filter_map(|key| {1480						properties.get(&key).map(|value| Property {1481							key,1482							value: value.clone(),1483						})1484					})1485					.collect()1486			})1487			.unwrap_or_else(|| {1488				properties1489					.into_iter()1490					.map(|(key, value)| Property { key, value })1491					.collect()1492			});14931494		Ok(properties)1495	}14961497	/// Get property permissions according to given keys.1498	pub fn filter_property_permissions(1499		collection_id: CollectionId,1500		keys: Option<Vec<PropertyKey>>,1501	) -> Result<Vec<PropertyKeyPermission>, DispatchError> {1502		let permissions = Self::property_permissions(collection_id);15031504		let key_permissions = keys1505			.map(|keys| {1506				keys.into_iter()1507					.filter_map(|key| {1508						permissions1509							.get(&key)1510							.map(|permission| PropertyKeyPermission {1511								key,1512								permission: permission.clone(),1513							})1514					})1515					.collect()1516			})1517			.unwrap_or_else(|| {1518				permissions1519					.into_iter()1520					.map(|(key, permission)| PropertyKeyPermission { key, permission })1521					.collect()1522			});15231524		Ok(key_permissions)1525	}15261527	/// Toggle `user` participation in the `collection`'s allow list.1528	/// #### Store read/writes1529	/// 1 writes1530	pub fn toggle_allowlist(1531		collection: &CollectionHandle<T>,1532		sender: &T::CrossAccountId,1533		user: &T::CrossAccountId,1534		allowed: bool,1535	) -> DispatchResult {1536		collection.check_is_owner_or_admin(sender)?;15371538		// =========15391540		if allowed {1541			<Allowlist<T>>::insert((collection.id, user), true);1542			Self::deposit_event(Event::<T>::AllowListAddressAdded(1543				collection.id,1544				user.clone(),1545			));1546		} else {1547			<Allowlist<T>>::remove((collection.id, user));1548			Self::deposit_event(Event::<T>::AllowListAddressRemoved(1549				collection.id,1550				user.clone(),1551			));1552		}15531554		<PalletEvm<T>>::deposit_log(1555			erc::CollectionHelpersEvents::CollectionChanged {1556				collection_id: eth::collection_id_to_address(collection.id),1557			}1558			.to_log(T::ContractAddress::get()),1559		);15601561		Ok(())1562	}15631564	/// Toggle `user` participation in the `collection`'s admin list.1565	/// #### Store read/writes1566	/// 2 reads, 2 writes1567	pub fn toggle_admin(1568		collection: &CollectionHandle<T>,1569		sender: &T::CrossAccountId,1570		user: &T::CrossAccountId,1571		admin: bool,1572	) -> DispatchResult {1573		collection.check_is_internal()?;1574		collection.check_is_owner(sender)?;15751576		let is_admin = <IsAdmin<T>>::get((collection.id, user));1577		if is_admin == admin {1578			if admin {1579				return Ok(());1580			} else {1581				ensure!(false, Error::<T>::UserIsNotAdmin);1582			}1583		}1584		let amount = <AdminAmount<T>>::get(collection.id);15851586		if admin {1587			let amount = amount1588				.checked_add(1)1589				.ok_or(<Error<T>>::CollectionAdminCountExceeded)?;1590			ensure!(1591				amount <= Self::collection_admins_limit(),1592				<Error<T>>::CollectionAdminCountExceeded,1593			);15941595			// =========15961597			<AdminAmount<T>>::insert(collection.id, amount);1598			<IsAdmin<T>>::insert((collection.id, user), true);15991600			Self::deposit_event(Event::<T>::CollectionAdminAdded(1601				collection.id,1602				user.clone(),1603			));1604		} else {1605			<AdminAmount<T>>::insert(collection.id, amount.saturating_sub(1));1606			<IsAdmin<T>>::remove((collection.id, user));16071608			Self::deposit_event(Event::<T>::CollectionAdminRemoved(1609				collection.id,1610				user.clone(),1611			));1612		}16131614		<PalletEvm<T>>::deposit_log(1615			erc::CollectionHelpersEvents::CollectionChanged {1616				collection_id: eth::collection_id_to_address(collection.id),1617			}1618			.to_log(T::ContractAddress::get()),1619		);16201621		Ok(())1622	}16231624	/// Update collection limits.1625	pub fn update_limits(1626		user: &T::CrossAccountId,1627		collection: &mut CollectionHandle<T>,1628		new_limit: CollectionLimits,1629	) -> DispatchResult {1630		collection.check_is_internal()?;1631		collection.check_is_owner_or_admin(user)?;16321633		collection.limits =1634			Self::clamp_limits(collection.mode.clone(), &collection.limits, new_limit)?;16351636		Self::deposit_event(Event::<T>::CollectionLimitSet(collection.id));1637		<PalletEvm<T>>::deposit_log(1638			erc::CollectionHelpersEvents::CollectionChanged {1639				collection_id: eth::collection_id_to_address(collection.id),1640			}1641			.to_log(T::ContractAddress::get()),1642		);16431644		collection.save()1645	}16461647	/// Merge set fields from `new_limit` to `old_limit`.1648	fn clamp_limits(1649		mode: CollectionMode,1650		old_limit: &CollectionLimits,1651		mut new_limit: CollectionLimits,1652	) -> Result<CollectionLimits, DispatchError> {1653		let limits = old_limit;1654		limit_default!(old_limit, new_limit,1655			account_token_ownership_limit => ensure!(1656				new_limit <= MAX_TOKEN_OWNERSHIP,1657				<Error<T>>::CollectionLimitBoundsExceeded,1658			),1659			sponsored_data_size => ensure!(1660				new_limit <= CUSTOM_DATA_LIMIT,1661				<Error<T>>::CollectionLimitBoundsExceeded,1662			),16631664			sponsored_data_rate_limit => {},1665			token_limit => ensure!(1666				old_limit >= new_limit && new_limit > 0,1667				<Error<T>>::CollectionTokenLimitExceeded1668			),16691670			sponsor_transfer_timeout(match mode {1671				CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,1672				CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1673				CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1674			}) => ensure!(1675				new_limit <= MAX_SPONSOR_TIMEOUT,1676				<Error<T>>::CollectionLimitBoundsExceeded,1677			),1678			sponsor_approve_timeout => {},1679			owner_can_transfer => ensure!(1680				!limits.owner_can_transfer_instaled() ||1681				old_limit || !new_limit,1682				<Error<T>>::OwnerPermissionsCantBeReverted,1683			),1684			owner_can_destroy => ensure!(1685				old_limit || !new_limit,1686				<Error<T>>::OwnerPermissionsCantBeReverted,1687			),1688			transfers_enabled => {},1689		);1690		Ok(new_limit)1691	}16921693	/// Update collection permissions.1694	pub fn update_permissions(1695		user: &T::CrossAccountId,1696		collection: &mut CollectionHandle<T>,1697		new_permission: CollectionPermissions,1698	) -> DispatchResult {1699		collection.check_is_internal()?;1700		collection.check_is_owner_or_admin(user)?;1701		collection.permissions = Self::clamp_permissions(1702			collection.mode.clone(),1703			&collection.permissions,1704			new_permission,1705		)?;17061707		Self::deposit_event(Event::<T>::CollectionPermissionSet(collection.id));1708		<PalletEvm<T>>::deposit_log(1709			erc::CollectionHelpersEvents::CollectionChanged {1710				collection_id: eth::collection_id_to_address(collection.id),1711			}1712			.to_log(T::ContractAddress::get()),1713		);17141715		collection.save()1716	}17171718	/// Merge set fields from `new_permission` to `old_permission`.1719	fn clamp_permissions(1720		_mode: CollectionMode,1721		old_permission: &CollectionPermissions,1722		mut new_permission: CollectionPermissions,1723	) -> Result<CollectionPermissions, DispatchError> {1724		limit_default_clone!(old_permission, new_permission,1725			access => {},1726			mint_mode => {},1727			nesting => { /* todo check for permissive, if only it gets out of benchmarks */ },1728		);1729		Ok(new_permission)1730	}1731}17321733/// Indicates unsupported methods by returning [Error::UnsupportedOperation].1734#[macro_export]1735macro_rules! unsupported {1736	($runtime:path) => {1737		Err($crate::Error::<$runtime>::UnsupportedOperation.into())1738	};1739}17401741/// Return weights for various worst-case operations.1742pub trait CommonWeightInfo<CrossAccountId> {1743	/// Weight of item creation.1744	fn create_item() -> Weight;17451746	/// Weight of items creation.1747	fn create_multiple_items(amount: &[CreateItemData]) -> Weight;17481749	/// Weight of items creation.1750	fn create_multiple_items_ex(cost: &CreateItemExData<CrossAccountId>) -> Weight;17511752	/// The weight of the burning item.1753	fn burn_item() -> Weight;17541755	/// Property setting weight.1756	///1757	/// * `amount`- The number of properties to set.1758	fn set_collection_properties(amount: u32) -> Weight;17591760	/// Collection property deletion weight.1761	///1762	/// * `amount`- The number of properties to set.1763	fn delete_collection_properties(amount: u32) -> Weight;17641765	/// Token property setting weight.1766	///1767	/// * `amount`- The number of properties to set.1768	fn set_token_properties(amount: u32) -> Weight;17691770	/// Token property deletion weight.1771	///1772	/// * `amount`- The number of properties to delete.1773	fn delete_token_properties(amount: u32) -> Weight;17741775	/// Token property permissions set weight.1776	///1777	/// * `amount`- The number of property permissions to set.1778	fn set_token_property_permissions(amount: u32) -> Weight;17791780	/// Transfer price of the token or its parts.1781	fn transfer() -> Weight;17821783	/// The price of setting the permission of the operation from another user.1784	fn approve() -> Weight;17851786	/// Transfer price from another user.1787	fn transfer_from() -> Weight;17881789	/// The price of burning a token from another user.1790	fn burn_from() -> Weight;17911792	/// Differs from burn_item in case of Fungible and Refungible, as it should burn1793	/// whole users's balance.1794	///1795	/// This method shouldn't be used directly, as it doesn't count breadth price, use [burn_recursively](CommonWeightInfo::burn_recursively) instead1796	fn burn_recursively_self_raw() -> Weight;17971798	/// Cost of iterating over `amount` children while burning, without counting child burning itself.1799	///1800	/// This method shouldn't be used directly, as it doesn't count depth price, use [burn_recursively](CommonWeightInfo::burn_recursively) instead1801	fn burn_recursively_breadth_raw(amount: u32) -> Weight;18021803	/// The price of recursive burning a token.1804	///1805	/// `max_selfs` - The maximum burning weight of the token itself.1806	/// `max_breadth` - The maximum number of nested tokens to burn.1807	fn burn_recursively(max_selfs: u32, max_breadth: u32) -> Weight {1808		Self::burn_recursively_self_raw()1809			.saturating_mul(max_selfs.max(1) as u64)1810			.saturating_add(Self::burn_recursively_breadth_raw(max_breadth))1811	}18121813	/// The price of retrieving token owner1814	fn token_owner() -> Weight;18151816	/// The price of setting approval for all1817	fn set_allowance_for_all() -> Weight;1818}18191820/// Weight info extension trait for refungible pallet.1821pub trait RefungibleExtensionsWeightInfo {1822	/// Weight of token repartition.1823	fn repartition() -> Weight;1824}18251826/// Common collection operations.1827///1828/// It wraps methods in Fungible, Nonfungible and Refungible pallets1829/// and adds weight info.1830pub trait CommonCollectionOperations<T: Config> {1831	/// Create token.1832	///1833	/// * `sender` - The user who mint the token and pays for the transaction.1834	/// * `to` - The user who will own the token.1835	/// * `data` - Token data.1836	/// * `nesting_budget` - A budget that can be spent on nesting tokens.1837	fn create_item(1838		&self,1839		sender: T::CrossAccountId,1840		to: T::CrossAccountId,1841		data: CreateItemData,1842		nesting_budget: &dyn Budget,1843	) -> DispatchResultWithPostInfo;18441845	/// Create multiple tokens.1846	///1847	/// * `sender` - The user who mint the token and pays for the transaction.1848	/// * `to` - The user who will own the token.1849	/// * `data` - Token data.1850	/// * `nesting_budget` - A budget that can be spent on nesting tokens.1851	fn create_multiple_items(1852		&self,1853		sender: T::CrossAccountId,1854		to: T::CrossAccountId,1855		data: Vec<CreateItemData>,1856		nesting_budget: &dyn Budget,1857	) -> DispatchResultWithPostInfo;18581859	/// Create multiple tokens.1860	///1861	/// * `sender` - The user who mint the token and pays for the transaction.1862	/// * `to` - The user who will own the token.1863	/// * `data` - Token data.1864	/// * `nesting_budget` - A budget that can be spent on nesting tokens.1865	fn create_multiple_items_ex(1866		&self,1867		sender: T::CrossAccountId,1868		data: CreateItemExData<T::CrossAccountId>,1869		nesting_budget: &dyn Budget,1870	) -> DispatchResultWithPostInfo;18711872	/// Burn token.1873	///1874	/// * `sender` - The user who owns the token.1875	/// * `token` - Token id that will burned.1876	/// * `amount` - The number of parts of the token that will be burned.1877	fn burn_item(1878		&self,1879		sender: T::CrossAccountId,1880		token: TokenId,1881		amount: u128,1882	) -> DispatchResultWithPostInfo;18831884	/// Burn token and all nested tokens recursievly.1885	///1886	/// * `sender` - The user who owns the token.1887	/// * `token` - Token id that will burned.1888	/// * `self_budget` - The budget that can be spent on burning tokens.1889	/// * `breadth_budget` - The budget that can be spent on burning nested tokens.1890	fn burn_item_recursively(1891		&self,1892		sender: T::CrossAccountId,1893		token: TokenId,1894		self_budget: &dyn Budget,1895		breadth_budget: &dyn Budget,1896	) -> DispatchResultWithPostInfo;18971898	/// Set collection properties.1899	///1900	/// * `sender` - Must be either the owner of the collection or its admin.1901	/// * `properties` - Properties to be set.1902	fn set_collection_properties(1903		&self,1904		sender: T::CrossAccountId,1905		properties: Vec<Property>,1906	) -> DispatchResultWithPostInfo;19071908	/// Delete collection properties.1909	///1910	/// * `sender` - Must be either the owner of the collection or its admin.1911	/// * `properties` - The properties to be removed.1912	fn delete_collection_properties(1913		&self,1914		sender: &T::CrossAccountId,1915		property_keys: Vec<PropertyKey>,1916	) -> DispatchResultWithPostInfo;19171918	/// Set token properties.1919	///1920	/// The appropriate [`PropertyPermission`] for the token property1921	/// must be set with [`Self::set_token_property_permissions`].1922	///1923	/// * `sender` - Must be either the owner of the token or its admin.1924	/// * `token_id` - The token for which the properties are being set.1925	/// * `properties` - Properties to be set.1926	/// * `budget` - Budget for setting properties.1927	fn set_token_properties(1928		&self,1929		sender: T::CrossAccountId,1930		token_id: TokenId,1931		properties: Vec<Property>,1932		budget: &dyn Budget,1933	) -> DispatchResultWithPostInfo;19341935	/// Remove token properties.1936	///1937	/// The appropriate [`PropertyPermission`] for the token property1938	/// must be set with [`Self::set_token_property_permissions`].1939	///1940	/// * `sender` - Must be either the owner of the token or its admin.1941	/// * `token_id` - The token for which the properties are being remove.1942	/// * `property_keys` - Keys to remove corresponding properties.1943	/// * `budget` - Budget for removing properties.1944	fn delete_token_properties(1945		&self,1946		sender: T::CrossAccountId,1947		token_id: TokenId,1948		property_keys: Vec<PropertyKey>,1949		budget: &dyn Budget,1950	) -> DispatchResultWithPostInfo;19511952	/// Set token property permissions.1953	///1954	/// * `sender` - Must be either the owner of the token or its admin.1955	/// * `token_id` - The token for which the properties are being set.1956	/// * `property_permissions` - Property permissions to be set.1957	/// * `budget` - Budget for setting properties.1958	fn set_token_property_permissions(1959		&self,1960		sender: &T::CrossAccountId,1961		property_permissions: Vec<PropertyKeyPermission>,1962	) -> DispatchResultWithPostInfo;19631964	/// Transfer amount of token pieces.1965	///1966	/// * `sender` - Donor user.1967	/// * `to` - Recepient user.1968	/// * `token` - The token of which parts are being sent.1969	/// * `amount` - The number of parts of the token that will be transferred.1970	/// * `budget` - The maximum budget that can be spent on the transfer.1971	fn transfer(1972		&self,1973		sender: T::CrossAccountId,1974		to: T::CrossAccountId,1975		token: TokenId,1976		amount: u128,1977		budget: &dyn Budget,1978	) -> DispatchResultWithPostInfo;19791980	/// Grant access to another account to transfer parts of the token owned by the calling user via [Self::transfer_from].1981	///1982	/// * `sender` - The user who grants access to the token.1983	/// * `spender` - The user to whom the rights are granted.1984	/// * `token` - The token to which access is granted.1985	/// * `amount` - The amount of pieces that another user can dispose of.1986	fn approve(1987		&self,1988		sender: T::CrossAccountId,1989		spender: T::CrossAccountId,1990		token: TokenId,1991		amount: u128,1992	) -> DispatchResultWithPostInfo;19931994	/// Send parts of a token owned by another user.1995	///1996	/// Before calling this method, you must grant rights to the calling user via [`Self::approve`].1997	///1998	/// * `sender` - The user who must have access to the token (see [`Self::approve`]).1999	/// * `from` - The user who owns the token.2000	/// * `to` - Recepient user.2001	/// * `token` - The token of which parts are being sent.2002	/// * `amount` - The number of parts of the token that will be transferred.2003	/// * `budget` - The maximum budget that can be spent on the transfer.2004	fn transfer_from(2005		&self,2006		sender: T::CrossAccountId,2007		from: T::CrossAccountId,2008		to: T::CrossAccountId,2009		token: TokenId,2010		amount: u128,2011		budget: &dyn Budget,2012	) -> DispatchResultWithPostInfo;20132014	/// Burn parts of a token owned by another user.2015	///2016	/// Before calling this method, you must grant rights to the calling user via [`Self::approve`].2017	///2018	/// * `sender` - The user who must have access to the token (see [`Self::approve`]).2019	/// * `from` - The user who owns the token.2020	/// * `token` - The token of which parts are being sent.2021	/// * `amount` - The number of parts of the token that will be transferred.2022	/// * `budget` - The maximum budget that can be spent on the burn.2023	fn burn_from(2024		&self,2025		sender: T::CrossAccountId,2026		from: T::CrossAccountId,2027		token: TokenId,2028		amount: u128,2029		budget: &dyn Budget,2030	) -> DispatchResultWithPostInfo;20312032	/// Check permission to nest token.2033	///2034	/// * `sender` - The user who initiated the check.2035	/// * `from` - The token that is checked for embedding.2036	/// * `under` - Token under which to check.2037	/// * `budget` - The maximum budget that can be spent on the check.2038	fn check_nesting(2039		&self,2040		sender: T::CrossAccountId,2041		from: (CollectionId, TokenId),2042		under: TokenId,2043		budget: &dyn Budget,2044	) -> DispatchResult;20452046	/// Nest one token into another.2047	///2048	/// * `under` - Token holder.2049	/// * `to_nest` - Nested token.2050	fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId));20512052	/// Unnest token.2053	///2054	/// * `under` - Token holder.2055	/// * `to_nest` - Token to unnest.2056	fn unnest(&self, under: TokenId, to_nest: (CollectionId, TokenId));20572058	/// Get all user tokens.2059	///2060	/// * `account` - Account for which you need to get tokens.2061	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;20622063	/// Get all the tokens in the collection.2064	fn collection_tokens(&self) -> Vec<TokenId>;20652066	/// Check if the token exists.2067	///2068	/// * `token` - Id token to check.2069	fn token_exists(&self, token: TokenId) -> bool;20702071	/// Get the id of the last minted token.2072	fn last_token_id(&self) -> TokenId;20732074	/// Get the owner of the token.2075	///2076	/// * `token` - The token for which you need to find out the owner.2077	fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;20782079	/// Returns 10 tokens owners in no particular order.2080	///2081	/// * `token` - The token for which you need to find out the owners.2082	fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId>;20832084	/// Get the value of the token property by key.2085	///2086	/// * `token` - Token with the property to get.2087	/// * `key` - Property name.2088	fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue>;20892090	/// Get a set of token properties by key vector.2091	///2092	/// * `token` - Token with the property to get.2093	/// * `keys` - Vector of property keys. If this parameter is [None](sp_std::result::Result),2094	/// then all properties are returned.2095	fn token_properties(&self, token: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property>;20962097	/// Amount of unique collection tokens2098	fn total_supply(&self) -> u32;20992100	/// Amount of different tokens account has.2101	///2102	/// * `account` - The account for which need to get the balance.2103	fn account_balance(&self, account: T::CrossAccountId) -> u32;21042105	/// Amount of specific token account have.2106	fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;21072108	/// Amount of token pieces2109	fn total_pieces(&self, token: TokenId) -> Option<u128>;21102111	/// Get the number of parts of the token that a trusted user can manage.2112	///2113	/// * `sender` - Trusted user.2114	/// * `spender` - Owner of the token.2115	/// * `token` - The token for which to get the value.2116	fn allowance(2117		&self,2118		sender: T::CrossAccountId,2119		spender: T::CrossAccountId,2120		token: TokenId,2121	) -> u128;21222123	/// Get extension for RFT collection.2124	fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>>;21252126	/// The `operator` is allowed to transfer all tokens of the `owner` on their behalf.2127	/// * `owner` - Token owner2128	/// * `operator` - Operator2129	/// * `approve` - Should operator status be granted or revoked?2130	fn set_allowance_for_all(2131		&self,2132		owner: T::CrossAccountId,2133		operator: T::CrossAccountId,2134		approve: bool,2135	) -> DispatchResultWithPostInfo;21362137	/// Tells whether the given `owner` approves the `operator`.2138	fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool;2139}21402141/// Extension for RFT collection.2142pub trait RefungibleExtensions<T>2143where2144	T: Config,2145{2146	/// Change the number of parts of the token.2147	///2148	/// When the value changes down, this function is equivalent to burning parts of the token.2149	///2150	/// * `sender` - The user calling the repartition operation. Must be the owner of the token.2151	/// * `token` - The token for which you want to change the number of parts.2152	/// * `amount` - The new value of the parts of the token.2153	fn repartition(2154		&self,2155		sender: &T::CrossAccountId,2156		token: TokenId,2157		amount: u128,2158	) -> DispatchResultWithPostInfo;2159}21602161/// Merge [`DispatchResult`] with [`Weight`] into [`DispatchResultWithPostInfo`].2162///2163/// Used for [`CommonCollectionOperations`] implementations and flexible enough to do so.2164pub fn with_weight(res: DispatchResult, weight: Weight) -> DispatchResultWithPostInfo {2165	let post_info = PostDispatchInfo {2166		actual_weight: Some(weight),2167		pays_fee: Pays::Yes,2168	};2169	match res {2170		Ok(()) => Ok(post_info),2171		Err(error) => Err(DispatchErrorWithPostInfo { post_info, error }),2172	}2173}21742175impl<T: Config> From<PropertiesError> for Error<T> {2176	fn from(error: PropertiesError) -> Self {2177		match error {2178			PropertiesError::NoSpaceForProperty => Self::NoSpaceForProperty,2179			PropertiesError::PropertyLimitReached => Self::PropertyLimitReached,2180			PropertiesError::InvalidCharacterInPropertyKey => Self::InvalidCharacterInPropertyKey,2181			PropertiesError::PropertyKeyIsTooLong => Self::PropertyKeyIsTooLong,2182			PropertiesError::EmptyPropertyKey => Self::EmptyPropertyKey,2183		}2184	}2185}
after · pallets/common/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//! # Common pallet18//!19//! The Common pallet provides functionality for handling collections.20//!21//! ## Overview22//!23//! The Common pallet provides an interface for common collection operations for different collection types24//! (see [CommonCollectionOperations]), as well as a generic dispatcher for these, see [dispatch] module.25//! It also provides this functionality to EVM, see [erc] and [eth] modules.26//!27//! The Common pallet provides functions for:28//!29//! - Setting and approving collection sponsor.30//! - Get\set\delete allow list.31//! - Get\set\delete collection properties.32//! - Get\set\delete collection property permissions.33//! - Get\set\delete token property permissions.34//! - Get\set\delete collection administrators.35//! - Checking access permissions.36//!37//! ### Terminology38//! **Collection sponsor** - For the collection, you can set a sponsor, at whose expense it will39//! be possible to mint tokens.40//!41//! **Allow list** - List of users who have the right to minting tokens.42//!43//! **Collection properties** - Collection properties are simply key-value stores where various44//! metadata can be placed.45//!46//! **Permissions on token properties** - For each property in the token can be set permission47//! to change, see [`PropertyPermission`].48//!49//! **Collection administrator** - For a collection, you can set administrators who have the right50//! to most actions on the collection.5152#![warn(missing_docs)]53#![cfg_attr(not(feature = "std"), no_std)]54extern crate alloc;5556use core::ops::{Deref, DerefMut};57use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};58use sp_std::vec::Vec;59use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};60use evm_coder::ToLog;61use frame_support::{62	dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, Weight, PostDispatchInfo},63	ensure,64	traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement},65	dispatch::Pays,66	transactional,67};68use pallet_evm::GasWeightMapping;69use up_data_structs::{70	COLLECTION_NUMBER_LIMIT,71	Collection,72	RpcCollection,73	CollectionFlags,74	RpcCollectionFlags,75	CollectionId,76	CreateItemData,77	MAX_TOKEN_PREFIX_LENGTH,78	COLLECTION_ADMINS_LIMIT,79	TokenId,80	TokenChild,81	CollectionStats,82	MAX_TOKEN_OWNERSHIP,83	CollectionMode,84	NFT_SPONSOR_TRANSFER_TIMEOUT,85	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,86	REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,87	MAX_SPONSOR_TIMEOUT,88	CUSTOM_DATA_LIMIT,89	CollectionLimits,90	CreateCollectionData,91	SponsorshipState,92	CreateItemExData,93	SponsoringRateLimit,94	budget::Budget,95	PhantomType,96	Property,97	Properties,98	PropertiesPermissionMap,99	PropertyKey,100	PropertyValue,101	PropertyPermission,102	PropertiesError,103	PropertyKeyPermission,104	TokenData,105	TrySetProperty,106	PropertyScope,107	// RMRK108	RmrkCollectionInfo,109	RmrkInstanceInfo,110	RmrkResourceInfo,111	RmrkPropertyInfo,112	RmrkBaseInfo,113	RmrkPartType,114	RmrkBoundedTheme,115	RmrkNftChild,116	CollectionPermissions,117};118119pub use pallet::*;120use sp_core::H160;121use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};122#[cfg(feature = "runtime-benchmarks")]123pub mod benchmarking;124pub mod dispatch;125pub mod erc;126pub mod eth;127pub mod weights;128129/// Weight info.130pub type SelfWeightOf<T> = <T as Config>::WeightInfo;131132/// Collection handle contains information about collection data and id.133/// Also provides functionality to count consumed gas.134///135/// CollectionHandle is used as a generic wrapper for collections of all types.136/// It allows to perform common operations and queries on any collection type,137/// both completely general for all, as well as their respective implementations of [`CommonCollectionOperations`].138#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]139pub struct CollectionHandle<T: Config> {140	/// Collection id141	pub id: CollectionId,142	collection: Collection<T::AccountId>,143	/// Substrate recorder for counting consumed gas144	pub recorder: SubstrateRecorder<T>,145}146147impl<T: Config> WithRecorder<T> for CollectionHandle<T> {148	fn recorder(&self) -> &SubstrateRecorder<T> {149		&self.recorder150	}151	fn into_recorder(self) -> SubstrateRecorder<T> {152		self.recorder153	}154}155156impl<T: Config> CollectionHandle<T> {157	/// Same as [CollectionHandle::new] but with an explicit gas limit.158	pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {159		<CollectionById<T>>::get(id).map(|collection| Self {160			id,161			collection,162			recorder: SubstrateRecorder::new(gas_limit),163		})164	}165166	/// Same as [CollectionHandle::new] but with an existed [`SubstrateRecorder`].167	pub fn new_with_recorder(id: CollectionId, recorder: SubstrateRecorder<T>) -> Option<Self> {168		<CollectionById<T>>::get(id).map(|collection| Self {169			id,170			collection,171			recorder,172		})173	}174175	/// Retrives collection data from storage and creates collection handle with default parameters.176	/// If collection not found return `None`177	pub fn new(id: CollectionId) -> Option<Self> {178		Self::new_with_gas_limit(id, u64::MAX)179	}180181	/// Same as [`CollectionHandle::new`] but if collection not found [CollectionNotFound](Error::CollectionNotFound) returned.182	pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {183		Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)184	}185186	/// Consume gas for reading.187	pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {188		self.recorder189			.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_ref_time(190				<T as frame_system::Config>::DbWeight::get()191					.read192					.saturating_mul(reads),193			)))194	}195196	/// Consume gas for writing.197	pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {198		self.recorder199			.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_ref_time(200				<T as frame_system::Config>::DbWeight::get()201					.write202					.saturating_mul(writes),203			)))204	}205206	/// Consume gas for reading and writing.207	pub fn consume_store_reads_and_writes(208		&self,209		reads: u64,210		writes: u64,211	) -> evm_coder::execution::Result<()> {212		let weight = <T as frame_system::Config>::DbWeight::get();213		let reads = weight.read.saturating_mul(reads);214		let writes = weight.read.saturating_mul(writes);215		self.recorder216			.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_ref_time(217				reads.saturating_add(writes),218			)))219	}220221	/// Save collection to storage.222	pub fn save(&self) -> DispatchResult {223		<CollectionById<T>>::insert(self.id, &self.collection);224		Ok(())225	}226227	/// Set collection sponsor.228	///229	/// Unique collections allows sponsoring for certain actions.230	/// This method allows you to set the sponsor of the collection.231	/// In order for sponsorship to become active, it must be confirmed through [`Self::confirm_sponsorship`].232	pub fn set_sponsor(233		&mut self,234		sender: &T::CrossAccountId,235		sponsor: T::AccountId,236	) -> DispatchResult {237		self.check_is_internal()?;238		self.check_is_owner_or_admin(sender)?;239240		self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor.clone());241242		<Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(self.id, sponsor));243		<PalletEvm<T>>::deposit_log(244			erc::CollectionHelpersEvents::CollectionChanged {245				collection_id: eth::collection_id_to_address(self.id),246			}247			.to_log(T::ContractAddress::get()),248		);249250		self.save()251	}252253	/// Force set `sponsor`.254	///255	/// Differs from [`set_sponsor`][`Self::set_sponsor`] in that confirmation256	/// from the `sponsor` is not required.257	///258	/// # Arguments259	///260	/// * `sender`: Caller's account.261	/// * `sponsor`: ID of the account of the sponsor-to-be.262	pub fn force_set_sponsor(&mut self, sponsor: T::AccountId) -> DispatchResult {263		self.check_is_internal()?;264265		self.collection.sponsorship = SponsorshipState::Confirmed(sponsor.clone());266267		<Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(self.id, sponsor.clone()));268		<Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(self.id, sponsor));269		<PalletEvm<T>>::deposit_log(270			erc::CollectionHelpersEvents::CollectionChanged {271				collection_id: eth::collection_id_to_address(self.id),272			}273			.to_log(T::ContractAddress::get()),274		);275276		self.save()277	}278279	/// Confirm sponsorship280	///281	/// In order for the sponsorship to become active, the user set as the sponsor must confirm their participation.282	/// Before confirming sponsorship, the user must be specified as the sponsor of the collection via [`Self::set_sponsor`].283	pub fn confirm_sponsorship(&mut self, sender: &T::AccountId) -> DispatchResult {284		self.check_is_internal()?;285		ensure!(286			self.collection.sponsorship.pending_sponsor() == Some(sender),287			Error::<T>::ConfirmSponsorshipFail288		);289290		self.collection.sponsorship = SponsorshipState::Confirmed(sender.clone());291292		<Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(self.id, sender.clone()));293		<PalletEvm<T>>::deposit_log(294			erc::CollectionHelpersEvents::CollectionChanged {295				collection_id: eth::collection_id_to_address(self.id),296			}297			.to_log(T::ContractAddress::get()),298		);299300		self.save()301	}302303	/// Remove collection sponsor.304	pub fn remove_sponsor(&mut self, sender: &T::CrossAccountId) -> DispatchResult {305		self.check_is_internal()?;306		self.check_is_owner_or_admin(sender)?;307308		self.collection.sponsorship = SponsorshipState::Disabled;309310		<Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(self.id));311		<PalletEvm<T>>::deposit_log(312			erc::CollectionHelpersEvents::CollectionChanged {313				collection_id: eth::collection_id_to_address(self.id),314			}315			.to_log(T::ContractAddress::get()),316		);317		self.save()318	}319320	/// Force remove `sponsor`.321	///322	/// Differs from `remove_sponsor` in that323	/// it doesn't require consent from the `owner` of the collection.324	pub fn force_remove_sponsor(&mut self) -> DispatchResult {325		self.check_is_internal()?;326327		self.collection.sponsorship = SponsorshipState::Disabled;328329		<Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(self.id));330		<PalletEvm<T>>::deposit_log(331			erc::CollectionHelpersEvents::CollectionChanged {332				collection_id: eth::collection_id_to_address(self.id),333			}334			.to_log(T::ContractAddress::get()),335		);336		self.save()337	}338339	/// Checks that the collection was created with, and must be operated upon through **Unique API**.340	/// Now check only the `external` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error.341	pub fn check_is_internal(&self) -> DispatchResult {342		if self.flags.external {343			return Err(<Error<T>>::CollectionIsExternal)?;344		}345346		Ok(())347	}348349	/// Checks that the collection was created with, and must be operated upon through an **assimilated API**.350	/// Now check only the `external` flag and if it's **false**, then return [`Error::CollectionIsInternal`] error.351	pub fn check_is_external(&self) -> DispatchResult {352		if !self.flags.external {353			return Err(<Error<T>>::CollectionIsInternal)?;354		}355356		Ok(())357	}358}359360impl<T: Config> Deref for CollectionHandle<T> {361	type Target = Collection<T::AccountId>;362363	fn deref(&self) -> &Self::Target {364		&self.collection365	}366}367368impl<T: Config> DerefMut for CollectionHandle<T> {369	fn deref_mut(&mut self) -> &mut Self::Target {370		&mut self.collection371	}372}373374impl<T: Config> CollectionHandle<T> {375	/// Checks if the `user` is the owner of the collection.376	pub fn check_is_owner(&self, user: &T::CrossAccountId) -> DispatchResult {377		ensure!(*user.as_sub() == self.owner, <Error<T>>::NoPermission);378		Ok(())379	}380381	/// Returns **true** if the `user` is the owner or administrator of the collection.382	pub fn is_owner_or_admin(&self, user: &T::CrossAccountId) -> bool {383		*user.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, user))384	}385386	/// Checks if the `user` is the owner or administrator of the collection.387	pub fn check_is_owner_or_admin(&self, user: &T::CrossAccountId) -> DispatchResult {388		ensure!(self.is_owner_or_admin(user), <Error<T>>::NoPermission);389		Ok(())390	}391392	/// Return **true** if `user` was not allowed to have tokens, and he can ignore such restrictions.393	pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {394		self.limits.owner_can_transfer() && self.is_owner_or_admin(user)395	}396397	/// Return **true** if `user` does not have enough token parts, and he can ignore such restrictions.398	pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> bool {399		self.limits.owner_can_transfer() && self.is_owner_or_admin(user)400	}401402	/// Checks if the user is in the allow list. If not [Error::AddressNotInAllowlist] returns.403	pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {404		ensure!(405			<Allowlist<T>>::get((self.id, user)),406			<Error<T>>::AddressNotInAllowlist407		);408		Ok(())409	}410411	/// Changes collection owner to another account412	/// #### Store read/writes413	/// 1 writes414	pub fn change_owner(415		&mut self,416		caller: T::CrossAccountId,417		new_owner: T::CrossAccountId,418	) -> DispatchResult {419		self.check_is_internal()?;420		self.check_is_owner(&caller)?;421		self.collection.owner = new_owner.as_sub().clone();422423		<Pallet<T>>::deposit_event(Event::<T>::CollectionOwnerChanged(424			self.id,425			new_owner.as_sub().clone(),426		));427		<PalletEvm<T>>::deposit_log(428			erc::CollectionHelpersEvents::CollectionChanged {429				collection_id: eth::collection_id_to_address(self.id),430			}431			.to_log(T::ContractAddress::get()),432		);433434		self.save()435	}436}437438#[frame_support::pallet]439pub mod pallet {440	use super::*;441	use dispatch::CollectionDispatch;442	use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key, traits::StorageVersion};443	use frame_system::pallet_prelude::*;444	use frame_support::traits::Currency;445	use up_data_structs::{TokenId, mapping::TokenAddressMapping};446	use scale_info::TypeInfo;447	use weights::WeightInfo;448449	#[pallet::config]450	pub trait Config:451		frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::Config + TypeInfo452	{453		/// Weight information for functions of this pallet.454		type WeightInfo: WeightInfo;455456		/// Events compatible with [`frame_system::Config::Event`].457		type RuntimeEvent: IsType<<Self as frame_system::Config>::RuntimeEvent> + From<Event<Self>>;458459		/// Handler of accounts and payment.460		type Currency: Currency<Self::AccountId>;461462		/// Set price to create a collection.463		#[pallet::constant]464		type CollectionCreationPrice: Get<465			<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,466		>;467468		/// Dispatcher of operations on collections.469		type CollectionDispatch: CollectionDispatch<Self>;470471		/// Account which holds the chain's treasury.472		type TreasuryAccountId: Get<Self::AccountId>;473474		/// Address under which the CollectionHelper contract would be available.475		#[pallet::constant]476		type ContractAddress: Get<H160>;477478		/// Mapper for token addresses to Ethereum addresses.479		type EvmTokenAddressMapping: TokenAddressMapping<H160>;480481		/// Mapper for token addresses to [`CrossAccountId`].482		type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;483	}484485	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);486487	#[pallet::pallet]488	#[pallet::storage_version(STORAGE_VERSION)]489	#[pallet::generate_store(pub(super) trait Store)]490	pub struct Pallet<T>(_);491492	#[pallet::extra_constants]493	impl<T: Config> Pallet<T> {494		/// Maximum admins per collection.495		pub fn collection_admins_limit() -> u32 {496			COLLECTION_ADMINS_LIMIT497		}498	}499500	#[pallet::event]501	#[pallet::generate_deposit(pub fn deposit_event)]502	pub enum Event<T: Config> {503		/// New collection was created504		CollectionCreated(505			/// Globally unique identifier of newly created collection.506			CollectionId,507			/// [`CollectionMode`] converted into _u8_.508			u8,509			/// Collection owner.510			T::AccountId,511		),512513		/// New collection was destroyed514		CollectionDestroyed(515			/// Globally unique identifier of collection.516			CollectionId,517		),518519		/// New item was created.520		ItemCreated(521			/// Id of the collection where item was created.522			CollectionId,523			/// Id of an item. Unique within the collection.524			TokenId,525			/// Owner of newly created item526			T::CrossAccountId,527			/// Always 1 for NFT528			u128,529		),530531		/// Collection item was burned.532		ItemDestroyed(533			/// Id of the collection where item was destroyed.534			CollectionId,535			/// Identifier of burned NFT.536			TokenId,537			/// Which user has destroyed its tokens.538			T::CrossAccountId,539			/// Amount of token pieces destroed. Always 1 for NFT.540			u128,541		),542543		/// Item was transferred544		Transfer(545			/// Id of collection to which item is belong.546			CollectionId,547			/// Id of an item.548			TokenId,549			/// Original owner of item.550			T::CrossAccountId,551			/// New owner of item.552			T::CrossAccountId,553			/// Amount of token pieces transfered. Always 1 for NFT.554			u128,555		),556557		/// Amount pieces of token owned by `sender` was approved for `spender`.558		Approved(559			/// Id of collection to which item is belong.560			CollectionId,561			/// Id of an item.562			TokenId,563			/// Original owner of item.564			T::CrossAccountId,565			/// Id for which the approval was granted.566			T::CrossAccountId,567			/// Amount of token pieces transfered. Always 1 for NFT.568			u128,569		),570571		/// A `sender` approves operations on all owned tokens for `spender`.572		ApprovedForAll(573			/// Id of collection to which item is belong.574			CollectionId,575			/// Owner of a wallet.576			T::CrossAccountId,577			/// Id for which operator status was granted or rewoked.578			T::CrossAccountId,579			/// Is operator status granted or revoked?580			bool,581		),582583		/// The colletion property has been added or edited.584		CollectionPropertySet(585			/// Id of collection to which property has been set.586			CollectionId,587			/// The property that was set.588			PropertyKey,589		),590591		/// The property has been deleted.592		CollectionPropertyDeleted(593			/// Id of collection to which property has been deleted.594			CollectionId,595			/// The property that was deleted.596			PropertyKey,597		),598599		/// The token property has been added or edited.600		TokenPropertySet(601			/// Identifier of the collection whose token has the property set.602			CollectionId,603			/// The token for which the property was set.604			TokenId,605			/// The property that was set.606			PropertyKey,607		),608609		/// The token property has been deleted.610		TokenPropertyDeleted(611			/// Identifier of the collection whose token has the property deleted.612			CollectionId,613			/// The token for which the property was deleted.614			TokenId,615			/// The property that was deleted.616			PropertyKey,617		),618619		/// The token property permission of a collection has been set.620		PropertyPermissionSet(621			/// ID of collection to which property permission has been set.622			CollectionId,623			/// The property permission that was set.624			PropertyKey,625		),626627		/// Address was added to the allow list.628		AllowListAddressAdded(629			/// ID of the affected collection.630			CollectionId,631			/// Address of the added account.632			T::CrossAccountId,633		),634635		/// Address was removed from the allow list.636		AllowListAddressRemoved(637			/// ID of the affected collection.638			CollectionId,639			/// Address of the removed account.640			T::CrossAccountId,641		),642643		/// Collection admin was added.644		CollectionAdminAdded(645			/// ID of the affected collection.646			CollectionId,647			/// Admin address.648			T::CrossAccountId,649		),650651		/// Collection admin was removed.652		CollectionAdminRemoved(653			/// ID of the affected collection.654			CollectionId,655			/// Removed admin address.656			T::CrossAccountId,657		),658659		/// Collection limits were set.660		CollectionLimitSet(661			/// ID of the affected collection.662			CollectionId,663		),664665		/// Collection owned was changed.666		CollectionOwnerChanged(667			/// ID of the affected collection.668			CollectionId,669			/// New owner address.670			T::AccountId,671		),672673		/// Collection permissions were set.674		CollectionPermissionSet(675			/// ID of the affected collection.676			CollectionId,677		),678679		/// Collection sponsor was set.680		CollectionSponsorSet(681			/// ID of the affected collection.682			CollectionId,683			/// New sponsor address.684			T::AccountId,685		),686687		/// New sponsor was confirm.688		SponsorshipConfirmed(689			/// ID of the affected collection.690			CollectionId,691			/// New sponsor address.692			T::AccountId,693		),694695		/// Collection sponsor was removed.696		CollectionSponsorRemoved(697			/// ID of the affected collection.698			CollectionId,699		),700	}701702	#[pallet::error]703	pub enum Error<T> {704		/// This collection does not exist.705		CollectionNotFound,706		/// Sender parameter and item owner must be equal.707		MustBeTokenOwner,708		/// No permission to perform action709		NoPermission,710		/// Destroying only empty collections is allowed711		CantDestroyNotEmptyCollection,712		/// Collection is not in mint mode.713		PublicMintingNotAllowed,714		/// Address is not in allow list.715		AddressNotInAllowlist,716717		/// Collection name can not be longer than 63 char.718		CollectionNameLimitExceeded,719		/// Collection description can not be longer than 255 char.720		CollectionDescriptionLimitExceeded,721		/// Token prefix can not be longer than 15 char.722		CollectionTokenPrefixLimitExceeded,723		/// Total collections bound exceeded.724		TotalCollectionsLimitExceeded,725		/// Exceeded max admin count726		CollectionAdminCountExceeded,727		/// Collection limit bounds per collection exceeded728		CollectionLimitBoundsExceeded,729		/// Tried to enable permissions which are only permitted to be disabled730		OwnerPermissionsCantBeReverted,731		/// Collection settings not allowing items transferring732		TransferNotAllowed,733		/// Account token limit exceeded per collection734		AccountTokenLimitExceeded,735		/// Collection token limit exceeded736		CollectionTokenLimitExceeded,737		/// Metadata flag frozen738		MetadataFlagFrozen,739740		/// Item does not exist741		TokenNotFound,742		/// Item is balance not enough743		TokenValueTooLow,744		/// Requested value is more than the approved745		ApprovedValueTooLow,746		/// Tried to approve more than owned747		CantApproveMoreThanOwned,748749		/// Can't transfer tokens to ethereum zero address750		AddressIsZero,751752		/// The operation is not supported753		UnsupportedOperation,754755		/// Insufficient funds to perform an action756		NotSufficientFounds,757758		/// User does not satisfy the nesting rule759		UserIsNotAllowedToNest,760		/// Only tokens from specific collections may nest tokens under this one761		SourceCollectionIsNotAllowedToNest,762763		/// Tried to store more data than allowed in collection field764		CollectionFieldSizeExceeded,765766		/// Tried to store more property data than allowed767		NoSpaceForProperty,768769		/// Tried to store more property keys than allowed770		PropertyLimitReached,771772		/// Property key is too long773		PropertyKeyIsTooLong,774775		/// Only ASCII letters, digits, and symbols `_`, `-`, and `.` are allowed776		InvalidCharacterInPropertyKey,777778		/// Empty property keys are forbidden779		EmptyPropertyKey,780781		/// Tried to access an external collection with an internal API782		CollectionIsExternal,783784		/// Tried to access an internal collection with an external API785		CollectionIsInternal,786787		/// This address is not set as sponsor, use setCollectionSponsor first.788		ConfirmSponsorshipFail,789790		/// The user is not an administrator.791		UserIsNotCollectionAdmin,792	}793794	/// Storage of the count of created collections. Essentially contains the last collection ID.795	#[pallet::storage]796	pub type CreatedCollectionCount<T> = StorageValue<Value = CollectionId, QueryKind = ValueQuery>;797798	/// Storage of the count of deleted collections.799	#[pallet::storage]800	pub type DestroyedCollectionCount<T> =801		StorageValue<Value = CollectionId, QueryKind = ValueQuery>;802803	/// Storage of collection info.804	#[pallet::storage]805	pub type CollectionById<T> = StorageMap<806		Hasher = Blake2_128Concat,807		Key = CollectionId,808		Value = Collection<<T as frame_system::Config>::AccountId>,809		QueryKind = OptionQuery,810	>;811812	/// Storage of collection properties.813	#[pallet::storage]814	#[pallet::getter(fn collection_properties)]815	pub type CollectionProperties<T> = StorageMap<816		Hasher = Blake2_128Concat,817		Key = CollectionId,818		Value = Properties,819		QueryKind = ValueQuery,820		OnEmpty = up_data_structs::CollectionProperties,821	>;822823	/// Storage of token property permissions of a collection.824	#[pallet::storage]825	#[pallet::getter(fn property_permissions)]826	pub type CollectionPropertyPermissions<T> = StorageMap<827		Hasher = Blake2_128Concat,828		Key = CollectionId,829		Value = PropertiesPermissionMap,830		QueryKind = ValueQuery,831	>;832833	/// Storage of the amount of collection admins.834	#[pallet::storage]835	pub type AdminAmount<T> = StorageMap<836		Hasher = Blake2_128Concat,837		Key = CollectionId,838		Value = u32,839		QueryKind = ValueQuery,840	>;841842	/// List of collection admins.843	#[pallet::storage]844	pub type IsAdmin<T: Config> = StorageNMap<845		Key = (846			Key<Blake2_128Concat, CollectionId>,847			Key<Blake2_128Concat, T::CrossAccountId>,848		),849		Value = bool,850		QueryKind = ValueQuery,851	>;852853	/// Allowlisted collection users.854	#[pallet::storage]855	pub type Allowlist<T: Config> = StorageNMap<856		Key = (857			Key<Blake2_128Concat, CollectionId>,858			Key<Blake2_128Concat, T::CrossAccountId>,859		),860		Value = bool,861		QueryKind = ValueQuery,862	>;863864	/// Not used by code, exists only to provide some types to metadata.865	#[pallet::storage]866	pub type DummyStorageValue<T: Config> = StorageValue<867		Value = (868			CollectionStats,869			CollectionId,870			TokenId,871			TokenChild,872			PhantomType<(873				TokenData<T::CrossAccountId>,874				RpcCollection<T::AccountId>,875				// RMRK876				RmrkCollectionInfo<T::AccountId>,877				RmrkInstanceInfo<T::AccountId>,878				RmrkResourceInfo,879				RmrkPropertyInfo,880				RmrkBaseInfo<T::AccountId>,881				RmrkPartType,882				RmrkBoundedTheme,883				RmrkNftChild,884			)>,885		),886		QueryKind = OptionQuery,887	>;888889	#[pallet::hooks]890	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {891		fn on_runtime_upgrade() -> Weight {892			StorageVersion::new(1).put::<Pallet<T>>();893894			Weight::zero()895		}896	}897}898899impl<T: Config> Pallet<T> {900	/// Enshure that receiver address is correct.901	///902	/// Ethereum receiver 0x0000000000000000000000000000000000000000 is reserved, and shouldn't own tokens.903	pub fn ensure_correct_receiver(receiver: &T::CrossAccountId) -> DispatchResult {904		ensure!(905			&T::CrossAccountId::from_eth(H160([0; 20])) != receiver,906			<Error<T>>::AddressIsZero907		);908		Ok(())909	}910911	/// Get a vector of collection admins.912	pub fn adminlist(collection: CollectionId) -> Vec<T::CrossAccountId> {913		<IsAdmin<T>>::iter_prefix((collection,))914			.map(|(a, _)| a)915			.collect()916	}917918	/// Get a vector of users allowed to mint tokens.919	pub fn allowlist(collection: CollectionId) -> Vec<T::CrossAccountId> {920		<Allowlist<T>>::iter_prefix((collection,))921			.map(|(a, _)| a)922			.collect()923	}924925	/// Is `user` allowed to mint token in `collection`.926	pub fn allowed(collection: CollectionId, user: T::CrossAccountId) -> bool {927		<Allowlist<T>>::get((collection, user))928	}929930	/// Get statistics of collections.931	pub fn collection_stats() -> CollectionStats {932		let created = <CreatedCollectionCount<T>>::get();933		let destroyed = <DestroyedCollectionCount<T>>::get();934		CollectionStats {935			created: created.0,936			destroyed: destroyed.0,937			alive: created.0 - destroyed.0,938		}939	}940941	/// Get the effective limits for the collection.942	pub fn effective_collection_limits(collection: CollectionId) -> Option<CollectionLimits> {943		let collection = <CollectionById<T>>::get(collection)?;944		let limits = collection.limits;945		let effective_limits = CollectionLimits {946			account_token_ownership_limit: Some(limits.account_token_ownership_limit()),947			sponsored_data_size: Some(limits.sponsored_data_size()),948			sponsored_data_rate_limit: Some(949				limits950					.sponsored_data_rate_limit951					.unwrap_or(SponsoringRateLimit::SponsoringDisabled),952			),953			token_limit: Some(limits.token_limit()),954			sponsor_transfer_timeout: Some(limits.sponsor_transfer_timeout(955				match collection.mode {956					CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,957					CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,958					CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,959				},960			)),961			sponsor_approve_timeout: Some(limits.sponsor_approve_timeout()),962			owner_can_transfer: Some(limits.owner_can_transfer()),963			owner_can_destroy: Some(limits.owner_can_destroy()),964			transfers_enabled: Some(limits.transfers_enabled()),965		};966967		Some(effective_limits)968	}969970	/// Returns information about the `collection` adapted for rpc.971	pub fn rpc_collection(collection: CollectionId) -> Option<RpcCollection<T::AccountId>> {972		let Collection {973			name,974			description,975			owner,976			mode,977			token_prefix,978			sponsorship,979			limits,980			permissions,981			flags,982		} = <CollectionById<T>>::get(collection)?;983984		let token_property_permissions = <CollectionPropertyPermissions<T>>::get(collection)985			.into_iter()986			.map(|(key, permission)| PropertyKeyPermission { key, permission })987			.collect();988989		let properties = <CollectionProperties<T>>::get(collection)990			.into_iter()991			.map(|(key, value)| Property { key, value })992			.collect();993994		let permissions = CollectionPermissions {995			access: Some(permissions.access()),996			mint_mode: Some(permissions.mint_mode()),997			nesting: Some(permissions.nesting().clone()),998		};9991000		Some(RpcCollection {1001			name: name.into_inner(),1002			description: description.into_inner(),1003			owner,1004			mode,1005			token_prefix: token_prefix.into_inner(),1006			sponsorship,1007			limits,1008			permissions,1009			token_property_permissions,1010			properties,1011			read_only: flags.external,10121013			flags: RpcCollectionFlags {1014				foreign: flags.foreign,1015				erc721metadata: flags.erc721metadata,1016			},1017		})1018	}1019}10201021macro_rules! limit_default {1022	($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{1023		$(1024			if let Some($new) = $new.$field {1025				let $old = $old.$field($($arg)?);1026				let _ = $new;1027				let _ = $old;1028				$check1029			} else {1030				$new.$field = $old.$field1031			}1032		)*1033	}};1034}1035macro_rules! limit_default_clone {1036	($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{1037		$(1038			if let Some($new) = $new.$field.clone() {1039				let $old = $old.$field($($arg)?);1040				let _ = $new;1041				let _ = $old;1042				$check1043			} else {1044				$new.$field = $old.$field.clone()1045			}1046		)*1047	}};1048}10491050impl<T: Config> Pallet<T> {1051	/// Create new collection.1052	///1053	/// * `owner` - The owner of the collection.1054	/// * `data` - Description of the created collection.1055	/// * `flags` - Extra flags to store.1056	pub fn init_collection(1057		owner: T::CrossAccountId,1058		payer: T::CrossAccountId,1059		data: CreateCollectionData<T::AccountId>,1060		flags: CollectionFlags,1061	) -> Result<CollectionId, DispatchError> {1062		{1063			ensure!(1064				data.token_prefix.len() <= MAX_TOKEN_PREFIX_LENGTH as usize,1065				Error::<T>::CollectionTokenPrefixLimitExceeded1066			);1067		}10681069		let created_count = <CreatedCollectionCount<T>>::get()1070			.01071			.checked_add(1)1072			.ok_or(ArithmeticError::Overflow)?;1073		let destroyed_count = <DestroyedCollectionCount<T>>::get().0;1074		let id = CollectionId(created_count);10751076		// bound Total number of collections1077		ensure!(1078			created_count - destroyed_count <= COLLECTION_NUMBER_LIMIT,1079			<Error<T>>::TotalCollectionsLimitExceeded1080		);10811082		// =========10831084		let collection = Collection {1085			owner: owner.as_sub().clone(),1086			name: data.name,1087			mode: data.mode.clone(),1088			description: data.description,1089			token_prefix: data.token_prefix,1090			sponsorship: data1091				.pending_sponsor1092				.map(SponsorshipState::Unconfirmed)1093				.unwrap_or_default(),1094			limits: data1095				.limits1096				.map(|limits| Self::clamp_limits(data.mode.clone(), &Default::default(), limits))1097				.unwrap_or_else(|| Ok(CollectionLimits::default()))?,1098			permissions: data1099				.permissions1100				.map(|permissions| {1101					Self::clamp_permissions(data.mode.clone(), &Default::default(), permissions)1102				})1103				.unwrap_or_else(|| Ok(CollectionPermissions::default()))?,1104			flags,1105		};11061107		let mut collection_properties = up_data_structs::CollectionProperties::get();1108		collection_properties1109			.try_set_from_iter(data.properties.into_iter())1110			.map_err(<Error<T>>::from)?;11111112		CollectionProperties::<T>::insert(id, collection_properties);11131114		let mut token_props_permissions = PropertiesPermissionMap::new();1115		token_props_permissions1116			.try_set_from_iter(data.token_property_permissions.into_iter())1117			.map_err(<Error<T>>::from)?;11181119		CollectionPropertyPermissions::<T>::insert(id, token_props_permissions);11201121		// Take a (non-refundable) deposit of collection creation1122		{1123			let mut imbalance =1124				<<<T as Config>::Currency as Currency<T::AccountId>>::PositiveImbalance>::zero();1125			imbalance.subsume(1126				<<T as Config>::Currency as Currency<T::AccountId>>::deposit_creating(1127					&T::TreasuryAccountId::get(),1128					T::CollectionCreationPrice::get(),1129				),1130			);1131			<T as Config>::Currency::settle(1132				payer.as_sub(),1133				imbalance,1134				WithdrawReasons::TRANSFER,1135				ExistenceRequirement::KeepAlive,1136			)1137			.map_err(|_| Error::<T>::NotSufficientFounds)?;1138		}11391140		<CreatedCollectionCount<T>>::put(created_count);1141		<Pallet<T>>::deposit_event(Event::CollectionCreated(1142			id,1143			data.mode.id(),1144			owner.as_sub().clone(),1145		));1146		<PalletEvm<T>>::deposit_log(1147			erc::CollectionHelpersEvents::CollectionCreated {1148				owner: *owner.as_eth(),1149				collection_id: eth::collection_id_to_address(id),1150			}1151			.to_log(T::ContractAddress::get()),1152		);1153		<CollectionById<T>>::insert(id, collection);1154		Ok(id)1155	}11561157	/// Destroy collection.1158	///1159	/// * `collection` - Collection handler.1160	/// * `sender` - The owner or administrator of the collection.1161	pub fn destroy_collection(1162		collection: CollectionHandle<T>,1163		sender: &T::CrossAccountId,1164	) -> DispatchResult {1165		ensure!(1166			collection.limits.owner_can_destroy(),1167			<Error<T>>::NoPermission,1168		);1169		collection.check_is_owner(sender)?;11701171		let destroyed_collections = <DestroyedCollectionCount<T>>::get()1172			.01173			.checked_add(1)1174			.ok_or(ArithmeticError::Overflow)?;11751176		// =========11771178		<DestroyedCollectionCount<T>>::put(destroyed_collections);1179		<CollectionById<T>>::remove(collection.id);1180		<AdminAmount<T>>::remove(collection.id);1181		let _ = <IsAdmin<T>>::clear_prefix((collection.id,), u32::MAX, None);1182		let _ = <Allowlist<T>>::clear_prefix((collection.id,), u32::MAX, None);1183		<CollectionProperties<T>>::remove(collection.id);11841185		<Pallet<T>>::deposit_event(Event::CollectionDestroyed(collection.id));11861187		<PalletEvm<T>>::deposit_log(1188			erc::CollectionHelpersEvents::CollectionDestroyed {1189				collection_id: eth::collection_id_to_address(collection.id),1190			}1191			.to_log(T::ContractAddress::get()),1192		);1193		Ok(())1194	}11951196	/// Set collection property.1197	///1198	/// * `collection` - Collection handler.1199	/// * `sender` - The owner or administrator of the collection.1200	/// * `property` - The property to set.1201	pub fn set_collection_property(1202		collection: &CollectionHandle<T>,1203		sender: &T::CrossAccountId,1204		property: Property,1205	) -> DispatchResult {1206		collection.check_is_owner_or_admin(sender)?;12071208		CollectionProperties::<T>::try_mutate(collection.id, |properties| {1209			let property = property.clone();1210			properties.try_set(property.key, property.value)1211		})1212		.map_err(<Error<T>>::from)?;12131214		Self::deposit_event(Event::CollectionPropertySet(collection.id, property.key));1215		<PalletEvm<T>>::deposit_log(1216			erc::CollectionHelpersEvents::CollectionChanged {1217				collection_id: eth::collection_id_to_address(collection.id),1218			}1219			.to_log(T::ContractAddress::get()),1220		);12211222		Ok(())1223	}12241225	/// Set scouped collection property.1226	///1227	/// * `collection_id` - ID of the collection for which the property is being set.1228	/// * `scope` - Property scope.1229	/// * `property` - The property to set.1230	pub fn set_scoped_collection_property(1231		collection_id: CollectionId,1232		scope: PropertyScope,1233		property: Property,1234	) -> DispatchResult {1235		CollectionProperties::<T>::try_mutate(collection_id, |properties| {1236			properties.try_scoped_set(scope, property.key, property.value)1237		})1238		.map_err(<Error<T>>::from)?;12391240		Ok(())1241	}12421243	/// Set scouped collection properties.1244	///1245	/// * `collection_id` - ID of the collection for which the properties is being set.1246	/// * `scope` - Property scope.1247	/// * `properties` - The properties to set.1248	pub fn set_scoped_collection_properties(1249		collection_id: CollectionId,1250		scope: PropertyScope,1251		properties: impl Iterator<Item = Property>,1252	) -> DispatchResult {1253		CollectionProperties::<T>::try_mutate(collection_id, |stored_properties| {1254			stored_properties.try_scoped_set_from_iter(scope, properties)1255		})1256		.map_err(<Error<T>>::from)?;12571258		Ok(())1259	}12601261	/// Set collection properties.1262	///1263	/// * `collection` - Collection handler.1264	/// * `sender` - The owner or administrator of the collection.1265	/// * `properties` - The properties to set.1266	#[transactional]1267	pub fn set_collection_properties(1268		collection: &CollectionHandle<T>,1269		sender: &T::CrossAccountId,1270		properties: Vec<Property>,1271	) -> DispatchResult {1272		for property in properties {1273			Self::set_collection_property(collection, sender, property)?;1274		}12751276		Ok(())1277	}12781279	/// Delete collection property.1280	///1281	/// * `collection` - Collection handler.1282	/// * `sender` - The owner or administrator of the collection.1283	/// * `property` - The property to delete.1284	pub fn delete_collection_property(1285		collection: &CollectionHandle<T>,1286		sender: &T::CrossAccountId,1287		property_key: PropertyKey,1288	) -> DispatchResult {1289		collection.check_is_owner_or_admin(sender)?;12901291		CollectionProperties::<T>::try_mutate(collection.id, |properties| {1292			properties.remove(&property_key)1293		})1294		.map_err(<Error<T>>::from)?;12951296		Self::deposit_event(Event::CollectionPropertyDeleted(1297			collection.id,1298			property_key,1299		));1300		<PalletEvm<T>>::deposit_log(1301			erc::CollectionHelpersEvents::CollectionChanged {1302				collection_id: eth::collection_id_to_address(collection.id),1303			}1304			.to_log(T::ContractAddress::get()),1305		);13061307		Ok(())1308	}13091310	/// Delete collection properties.1311	///1312	/// * `collection` - Collection handler.1313	/// * `sender` - The owner or administrator of the collection.1314	/// * `properties` - The properties to delete.1315	#[transactional]1316	pub fn delete_collection_properties(1317		collection: &CollectionHandle<T>,1318		sender: &T::CrossAccountId,1319		property_keys: Vec<PropertyKey>,1320	) -> DispatchResult {1321		for key in property_keys {1322			Self::delete_collection_property(collection, sender, key)?;1323		}13241325		Ok(())1326	}13271328	/// Set collection propetry permission without any checks.1329	///1330	/// Used for migrations.1331	///1332	/// * `collection` - Collection handler.1333	/// * `property_permissions` - Property permissions.1334	pub fn set_property_permission_unchecked(1335		collection: CollectionId,1336		property_permission: PropertyKeyPermission,1337	) -> DispatchResult {1338		<CollectionPropertyPermissions<T>>::try_mutate(collection, |permissions| {1339			permissions.try_set(property_permission.key, property_permission.permission)1340		})1341		.map_err(<Error<T>>::from)?;1342		Ok(())1343	}13441345	/// Set collection property permission.1346	///1347	/// * `collection` - Collection handler.1348	/// * `sender` - The owner or administrator of the collection.1349	/// * `property_permission` - Property permission.1350	pub fn set_property_permission(1351		collection: &CollectionHandle<T>,1352		sender: &T::CrossAccountId,1353		property_permission: PropertyKeyPermission,1354	) -> DispatchResult {1355		Self::set_scoped_property_permission(1356			collection,1357			sender,1358			PropertyScope::None,1359			property_permission,1360		)1361	}13621363	/// Set collection property permission with scope.1364	///1365	/// * `collection` - Collection handler.1366	/// * `sender` - The owner or administrator of the collection.1367	/// * `scope` - Property scope.1368	/// * `property_permission` - Property permission.1369	pub fn set_scoped_property_permission(1370		collection: &CollectionHandle<T>,1371		sender: &T::CrossAccountId,1372		scope: PropertyScope,1373		property_permission: PropertyKeyPermission,1374	) -> DispatchResult {1375		collection.check_is_owner_or_admin(sender)?;13761377		let all_permissions = CollectionPropertyPermissions::<T>::get(collection.id);1378		let current_permission = all_permissions.get(&property_permission.key);1379		if matches![1380			current_permission,1381			Some(PropertyPermission { mutable: false, .. })1382		] {1383			return Err(<Error<T>>::NoPermission.into());1384		}13851386		CollectionPropertyPermissions::<T>::try_mutate(collection.id, |permissions| {1387			let property_permission = property_permission.clone();1388			permissions.try_scoped_set(1389				scope,1390				property_permission.key,1391				property_permission.permission,1392			)1393		})1394		.map_err(<Error<T>>::from)?;13951396		Self::deposit_event(Event::PropertyPermissionSet(1397			collection.id,1398			property_permission.key,1399		));1400		<PalletEvm<T>>::deposit_log(1401			erc::CollectionHelpersEvents::CollectionChanged {1402				collection_id: eth::collection_id_to_address(collection.id),1403			}1404			.to_log(T::ContractAddress::get()),1405		);14061407		Ok(())1408	}14091410	/// Set token property permission.1411	///1412	/// * `collection` - Collection handler.1413	/// * `sender` - The owner or administrator of the collection.1414	/// * `property_permissions` - Property permissions.1415	#[transactional]1416	pub fn set_token_property_permissions(1417		collection: &CollectionHandle<T>,1418		sender: &T::CrossAccountId,1419		property_permissions: Vec<PropertyKeyPermission>,1420	) -> DispatchResult {1421		Self::set_scoped_token_property_permissions(1422			collection,1423			sender,1424			PropertyScope::None,1425			property_permissions,1426		)1427	}14281429	/// Set token property permission with scope.1430	///1431	/// * `collection` - Collection handler.1432	/// * `sender` - The owner or administrator of the collection.1433	/// * `scope` - Property scope.1434	/// * `property_permissions` - Property permissions.1435	#[transactional]1436	pub fn set_scoped_token_property_permissions(1437		collection: &CollectionHandle<T>,1438		sender: &T::CrossAccountId,1439		scope: PropertyScope,1440		property_permissions: Vec<PropertyKeyPermission>,1441	) -> DispatchResult {1442		for prop_pemission in property_permissions {1443			Self::set_scoped_property_permission(collection, sender, scope, prop_pemission)?;1444		}14451446		Ok(())1447	}14481449	/// Get collection property.1450	pub fn get_collection_property(1451		collection_id: CollectionId,1452		key: &PropertyKey,1453	) -> Option<PropertyValue> {1454		Self::collection_properties(collection_id).get(key).cloned()1455	}14561457	/// Convert byte vector to property key vector.1458	pub fn bytes_keys_to_property_keys(1459		keys: Vec<Vec<u8>>,1460	) -> Result<Vec<PropertyKey>, DispatchError> {1461		keys.into_iter()1462			.map(|key| -> Result<PropertyKey, DispatchError> {1463				key.try_into()1464					.map_err(|_| <Error<T>>::PropertyKeyIsTooLong.into())1465			})1466			.collect::<Result<Vec<PropertyKey>, DispatchError>>()1467	}14681469	/// Get properties according to given keys.1470	pub fn filter_collection_properties(1471		collection_id: CollectionId,1472		keys: Option<Vec<PropertyKey>>,1473	) -> Result<Vec<Property>, DispatchError> {1474		let properties = Self::collection_properties(collection_id);14751476		let properties = keys1477			.map(|keys| {1478				keys.into_iter()1479					.filter_map(|key| {1480						properties.get(&key).map(|value| Property {1481							key,1482							value: value.clone(),1483						})1484					})1485					.collect()1486			})1487			.unwrap_or_else(|| {1488				properties1489					.into_iter()1490					.map(|(key, value)| Property { key, value })1491					.collect()1492			});14931494		Ok(properties)1495	}14961497	/// Get property permissions according to given keys.1498	pub fn filter_property_permissions(1499		collection_id: CollectionId,1500		keys: Option<Vec<PropertyKey>>,1501	) -> Result<Vec<PropertyKeyPermission>, DispatchError> {1502		let permissions = Self::property_permissions(collection_id);15031504		let key_permissions = keys1505			.map(|keys| {1506				keys.into_iter()1507					.filter_map(|key| {1508						permissions1509							.get(&key)1510							.map(|permission| PropertyKeyPermission {1511								key,1512								permission: permission.clone(),1513							})1514					})1515					.collect()1516			})1517			.unwrap_or_else(|| {1518				permissions1519					.into_iter()1520					.map(|(key, permission)| PropertyKeyPermission { key, permission })1521					.collect()1522			});15231524		Ok(key_permissions)1525	}15261527	/// Toggle `user` participation in the `collection`'s allow list.1528	/// #### Store read/writes1529	/// 1 writes1530	pub fn toggle_allowlist(1531		collection: &CollectionHandle<T>,1532		sender: &T::CrossAccountId,1533		user: &T::CrossAccountId,1534		allowed: bool,1535	) -> DispatchResult {1536		collection.check_is_owner_or_admin(sender)?;15371538		// =========15391540		if allowed {1541			<Allowlist<T>>::insert((collection.id, user), true);1542			Self::deposit_event(Event::<T>::AllowListAddressAdded(1543				collection.id,1544				user.clone(),1545			));1546		} else {1547			<Allowlist<T>>::remove((collection.id, user));1548			Self::deposit_event(Event::<T>::AllowListAddressRemoved(1549				collection.id,1550				user.clone(),1551			));1552		}15531554		<PalletEvm<T>>::deposit_log(1555			erc::CollectionHelpersEvents::CollectionChanged {1556				collection_id: eth::collection_id_to_address(collection.id),1557			}1558			.to_log(T::ContractAddress::get()),1559		);15601561		Ok(())1562	}15631564	/// Toggle `user` participation in the `collection`'s admin list.1565	/// #### Store read/writes1566	/// 2 reads, 2 writes1567	pub fn toggle_admin(1568		collection: &CollectionHandle<T>,1569		sender: &T::CrossAccountId,1570		user: &T::CrossAccountId,1571		admin: bool,1572	) -> DispatchResult {1573		collection.check_is_internal()?;1574		collection.check_is_owner(sender)?;15751576		let is_admin = <IsAdmin<T>>::get((collection.id, user));1577		if is_admin == admin {1578			if admin {1579				return Ok(());1580			} else {1581				return Err(Error::<T>::UserIsNotCollectionAdmin.into());1582			}1583		}1584		let amount = <AdminAmount<T>>::get(collection.id);15851586		if admin {1587			let amount = amount1588				.checked_add(1)1589				.ok_or(<Error<T>>::CollectionAdminCountExceeded)?;1590			ensure!(1591				amount <= Self::collection_admins_limit(),1592				<Error<T>>::CollectionAdminCountExceeded,1593			);15941595			<AdminAmount<T>>::insert(collection.id, amount);1596			<IsAdmin<T>>::insert((collection.id, user), true);15971598			Self::deposit_event(Event::<T>::CollectionAdminAdded(1599				collection.id,1600				user.clone(),1601			));1602		} else {1603			<AdminAmount<T>>::insert(collection.id, amount.saturating_sub(1));1604			<IsAdmin<T>>::remove((collection.id, user));16051606			Self::deposit_event(Event::<T>::CollectionAdminRemoved(1607				collection.id,1608				user.clone(),1609			));1610		}16111612		<PalletEvm<T>>::deposit_log(1613			erc::CollectionHelpersEvents::CollectionChanged {1614				collection_id: eth::collection_id_to_address(collection.id),1615			}1616			.to_log(T::ContractAddress::get()),1617		);16181619		Ok(())1620	}16211622	/// Update collection limits.1623	pub fn update_limits(1624		user: &T::CrossAccountId,1625		collection: &mut CollectionHandle<T>,1626		new_limit: CollectionLimits,1627	) -> DispatchResult {1628		collection.check_is_internal()?;1629		collection.check_is_owner_or_admin(user)?;16301631		collection.limits =1632			Self::clamp_limits(collection.mode.clone(), &collection.limits, new_limit)?;16331634		Self::deposit_event(Event::<T>::CollectionLimitSet(collection.id));1635		<PalletEvm<T>>::deposit_log(1636			erc::CollectionHelpersEvents::CollectionChanged {1637				collection_id: eth::collection_id_to_address(collection.id),1638			}1639			.to_log(T::ContractAddress::get()),1640		);16411642		collection.save()1643	}16441645	/// Merge set fields from `new_limit` to `old_limit`.1646	fn clamp_limits(1647		mode: CollectionMode,1648		old_limit: &CollectionLimits,1649		mut new_limit: CollectionLimits,1650	) -> Result<CollectionLimits, DispatchError> {1651		let limits = old_limit;1652		limit_default!(old_limit, new_limit,1653			account_token_ownership_limit => ensure!(1654				new_limit <= MAX_TOKEN_OWNERSHIP,1655				<Error<T>>::CollectionLimitBoundsExceeded,1656			),1657			sponsored_data_size => ensure!(1658				new_limit <= CUSTOM_DATA_LIMIT,1659				<Error<T>>::CollectionLimitBoundsExceeded,1660			),16611662			sponsored_data_rate_limit => {},1663			token_limit => ensure!(1664				old_limit >= new_limit && new_limit > 0,1665				<Error<T>>::CollectionTokenLimitExceeded1666			),16671668			sponsor_transfer_timeout(match mode {1669				CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,1670				CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1671				CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1672			}) => ensure!(1673				new_limit <= MAX_SPONSOR_TIMEOUT,1674				<Error<T>>::CollectionLimitBoundsExceeded,1675			),1676			sponsor_approve_timeout => {},1677			owner_can_transfer => ensure!(1678				!limits.owner_can_transfer_instaled() ||1679				old_limit || !new_limit,1680				<Error<T>>::OwnerPermissionsCantBeReverted,1681			),1682			owner_can_destroy => ensure!(1683				old_limit || !new_limit,1684				<Error<T>>::OwnerPermissionsCantBeReverted,1685			),1686			transfers_enabled => {},1687		);1688		Ok(new_limit)1689	}16901691	/// Update collection permissions.1692	pub fn update_permissions(1693		user: &T::CrossAccountId,1694		collection: &mut CollectionHandle<T>,1695		new_permission: CollectionPermissions,1696	) -> DispatchResult {1697		collection.check_is_internal()?;1698		collection.check_is_owner_or_admin(user)?;1699		collection.permissions = Self::clamp_permissions(1700			collection.mode.clone(),1701			&collection.permissions,1702			new_permission,1703		)?;17041705		Self::deposit_event(Event::<T>::CollectionPermissionSet(collection.id));1706		<PalletEvm<T>>::deposit_log(1707			erc::CollectionHelpersEvents::CollectionChanged {1708				collection_id: eth::collection_id_to_address(collection.id),1709			}1710			.to_log(T::ContractAddress::get()),1711		);17121713		collection.save()1714	}17151716	/// Merge set fields from `new_permission` to `old_permission`.1717	fn clamp_permissions(1718		_mode: CollectionMode,1719		old_permission: &CollectionPermissions,1720		mut new_permission: CollectionPermissions,1721	) -> Result<CollectionPermissions, DispatchError> {1722		limit_default_clone!(old_permission, new_permission,1723			access => {},1724			mint_mode => {},1725			nesting => { /* todo check for permissive, if only it gets out of benchmarks */ },1726		);1727		Ok(new_permission)1728	}1729}17301731/// Indicates unsupported methods by returning [Error::UnsupportedOperation].1732#[macro_export]1733macro_rules! unsupported {1734	($runtime:path) => {1735		Err($crate::Error::<$runtime>::UnsupportedOperation.into())1736	};1737}17381739/// Return weights for various worst-case operations.1740pub trait CommonWeightInfo<CrossAccountId> {1741	/// Weight of item creation.1742	fn create_item() -> Weight;17431744	/// Weight of items creation.1745	fn create_multiple_items(amount: &[CreateItemData]) -> Weight;17461747	/// Weight of items creation.1748	fn create_multiple_items_ex(cost: &CreateItemExData<CrossAccountId>) -> Weight;17491750	/// The weight of the burning item.1751	fn burn_item() -> Weight;17521753	/// Property setting weight.1754	///1755	/// * `amount`- The number of properties to set.1756	fn set_collection_properties(amount: u32) -> Weight;17571758	/// Collection property deletion weight.1759	///1760	/// * `amount`- The number of properties to set.1761	fn delete_collection_properties(amount: u32) -> Weight;17621763	/// Token property setting weight.1764	///1765	/// * `amount`- The number of properties to set.1766	fn set_token_properties(amount: u32) -> Weight;17671768	/// Token property deletion weight.1769	///1770	/// * `amount`- The number of properties to delete.1771	fn delete_token_properties(amount: u32) -> Weight;17721773	/// Token property permissions set weight.1774	///1775	/// * `amount`- The number of property permissions to set.1776	fn set_token_property_permissions(amount: u32) -> Weight;17771778	/// Transfer price of the token or its parts.1779	fn transfer() -> Weight;17801781	/// The price of setting the permission of the operation from another user.1782	fn approve() -> Weight;17831784	/// Transfer price from another user.1785	fn transfer_from() -> Weight;17861787	/// The price of burning a token from another user.1788	fn burn_from() -> Weight;17891790	/// Differs from burn_item in case of Fungible and Refungible, as it should burn1791	/// whole users's balance.1792	///1793	/// This method shouldn't be used directly, as it doesn't count breadth price, use [burn_recursively](CommonWeightInfo::burn_recursively) instead1794	fn burn_recursively_self_raw() -> Weight;17951796	/// Cost of iterating over `amount` children while burning, without counting child burning itself.1797	///1798	/// This method shouldn't be used directly, as it doesn't count depth price, use [burn_recursively](CommonWeightInfo::burn_recursively) instead1799	fn burn_recursively_breadth_raw(amount: u32) -> Weight;18001801	/// The price of recursive burning a token.1802	///1803	/// `max_selfs` - The maximum burning weight of the token itself.1804	/// `max_breadth` - The maximum number of nested tokens to burn.1805	fn burn_recursively(max_selfs: u32, max_breadth: u32) -> Weight {1806		Self::burn_recursively_self_raw()1807			.saturating_mul(max_selfs.max(1) as u64)1808			.saturating_add(Self::burn_recursively_breadth_raw(max_breadth))1809	}18101811	/// The price of retrieving token owner1812	fn token_owner() -> Weight;18131814	/// The price of setting approval for all1815	fn set_allowance_for_all() -> Weight;1816}18171818/// Weight info extension trait for refungible pallet.1819pub trait RefungibleExtensionsWeightInfo {1820	/// Weight of token repartition.1821	fn repartition() -> Weight;1822}18231824/// Common collection operations.1825///1826/// It wraps methods in Fungible, Nonfungible and Refungible pallets1827/// and adds weight info.1828pub trait CommonCollectionOperations<T: Config> {1829	/// Create token.1830	///1831	/// * `sender` - The user who mint the token and pays for the transaction.1832	/// * `to` - The user who will own the token.1833	/// * `data` - Token data.1834	/// * `nesting_budget` - A budget that can be spent on nesting tokens.1835	fn create_item(1836		&self,1837		sender: T::CrossAccountId,1838		to: T::CrossAccountId,1839		data: CreateItemData,1840		nesting_budget: &dyn Budget,1841	) -> DispatchResultWithPostInfo;18421843	/// Create multiple tokens.1844	///1845	/// * `sender` - The user who mint the token and pays for the transaction.1846	/// * `to` - The user who will own the token.1847	/// * `data` - Token data.1848	/// * `nesting_budget` - A budget that can be spent on nesting tokens.1849	fn create_multiple_items(1850		&self,1851		sender: T::CrossAccountId,1852		to: T::CrossAccountId,1853		data: Vec<CreateItemData>,1854		nesting_budget: &dyn Budget,1855	) -> DispatchResultWithPostInfo;18561857	/// Create multiple tokens.1858	///1859	/// * `sender` - The user who mint the token and pays for the transaction.1860	/// * `to` - The user who will own the token.1861	/// * `data` - Token data.1862	/// * `nesting_budget` - A budget that can be spent on nesting tokens.1863	fn create_multiple_items_ex(1864		&self,1865		sender: T::CrossAccountId,1866		data: CreateItemExData<T::CrossAccountId>,1867		nesting_budget: &dyn Budget,1868	) -> DispatchResultWithPostInfo;18691870	/// Burn token.1871	///1872	/// * `sender` - The user who owns the token.1873	/// * `token` - Token id that will burned.1874	/// * `amount` - The number of parts of the token that will be burned.1875	fn burn_item(1876		&self,1877		sender: T::CrossAccountId,1878		token: TokenId,1879		amount: u128,1880	) -> DispatchResultWithPostInfo;18811882	/// Burn token and all nested tokens recursievly.1883	///1884	/// * `sender` - The user who owns the token.1885	/// * `token` - Token id that will burned.1886	/// * `self_budget` - The budget that can be spent on burning tokens.1887	/// * `breadth_budget` - The budget that can be spent on burning nested tokens.1888	fn burn_item_recursively(1889		&self,1890		sender: T::CrossAccountId,1891		token: TokenId,1892		self_budget: &dyn Budget,1893		breadth_budget: &dyn Budget,1894	) -> DispatchResultWithPostInfo;18951896	/// Set collection properties.1897	///1898	/// * `sender` - Must be either the owner of the collection or its admin.1899	/// * `properties` - Properties to be set.1900	fn set_collection_properties(1901		&self,1902		sender: T::CrossAccountId,1903		properties: Vec<Property>,1904	) -> DispatchResultWithPostInfo;19051906	/// Delete collection properties.1907	///1908	/// * `sender` - Must be either the owner of the collection or its admin.1909	/// * `properties` - The properties to be removed.1910	fn delete_collection_properties(1911		&self,1912		sender: &T::CrossAccountId,1913		property_keys: Vec<PropertyKey>,1914	) -> DispatchResultWithPostInfo;19151916	/// Set token properties.1917	///1918	/// The appropriate [`PropertyPermission`] for the token property1919	/// must be set with [`Self::set_token_property_permissions`].1920	///1921	/// * `sender` - Must be either the owner of the token or its admin.1922	/// * `token_id` - The token for which the properties are being set.1923	/// * `properties` - Properties to be set.1924	/// * `budget` - Budget for setting properties.1925	fn set_token_properties(1926		&self,1927		sender: T::CrossAccountId,1928		token_id: TokenId,1929		properties: Vec<Property>,1930		budget: &dyn Budget,1931	) -> DispatchResultWithPostInfo;19321933	/// Remove token properties.1934	///1935	/// The appropriate [`PropertyPermission`] for the token property1936	/// must be set with [`Self::set_token_property_permissions`].1937	///1938	/// * `sender` - Must be either the owner of the token or its admin.1939	/// * `token_id` - The token for which the properties are being remove.1940	/// * `property_keys` - Keys to remove corresponding properties.1941	/// * `budget` - Budget for removing properties.1942	fn delete_token_properties(1943		&self,1944		sender: T::CrossAccountId,1945		token_id: TokenId,1946		property_keys: Vec<PropertyKey>,1947		budget: &dyn Budget,1948	) -> DispatchResultWithPostInfo;19491950	/// Set token property permissions.1951	///1952	/// * `sender` - Must be either the owner of the token or its admin.1953	/// * `token_id` - The token for which the properties are being set.1954	/// * `property_permissions` - Property permissions to be set.1955	/// * `budget` - Budget for setting properties.1956	fn set_token_property_permissions(1957		&self,1958		sender: &T::CrossAccountId,1959		property_permissions: Vec<PropertyKeyPermission>,1960	) -> DispatchResultWithPostInfo;19611962	/// Transfer amount of token pieces.1963	///1964	/// * `sender` - Donor user.1965	/// * `to` - Recepient user.1966	/// * `token` - The token of which parts are being sent.1967	/// * `amount` - The number of parts of the token that will be transferred.1968	/// * `budget` - The maximum budget that can be spent on the transfer.1969	fn transfer(1970		&self,1971		sender: T::CrossAccountId,1972		to: T::CrossAccountId,1973		token: TokenId,1974		amount: u128,1975		budget: &dyn Budget,1976	) -> DispatchResultWithPostInfo;19771978	/// Grant access to another account to transfer parts of the token owned by the calling user via [Self::transfer_from].1979	///1980	/// * `sender` - The user who grants access to the token.1981	/// * `spender` - The user to whom the rights are granted.1982	/// * `token` - The token to which access is granted.1983	/// * `amount` - The amount of pieces that another user can dispose of.1984	fn approve(1985		&self,1986		sender: T::CrossAccountId,1987		spender: T::CrossAccountId,1988		token: TokenId,1989		amount: u128,1990	) -> DispatchResultWithPostInfo;19911992	/// Send parts of a token owned by another user.1993	///1994	/// Before calling this method, you must grant rights to the calling user via [`Self::approve`].1995	///1996	/// * `sender` - The user who must have access to the token (see [`Self::approve`]).1997	/// * `from` - The user who owns the token.1998	/// * `to` - Recepient user.1999	/// * `token` - The token of which parts are being sent.2000	/// * `amount` - The number of parts of the token that will be transferred.2001	/// * `budget` - The maximum budget that can be spent on the transfer.2002	fn transfer_from(2003		&self,2004		sender: T::CrossAccountId,2005		from: T::CrossAccountId,2006		to: T::CrossAccountId,2007		token: TokenId,2008		amount: u128,2009		budget: &dyn Budget,2010	) -> DispatchResultWithPostInfo;20112012	/// Burn parts of a token owned by another user.2013	///2014	/// Before calling this method, you must grant rights to the calling user via [`Self::approve`].2015	///2016	/// * `sender` - The user who must have access to the token (see [`Self::approve`]).2017	/// * `from` - The user who owns the token.2018	/// * `token` - The token of which parts are being sent.2019	/// * `amount` - The number of parts of the token that will be transferred.2020	/// * `budget` - The maximum budget that can be spent on the burn.2021	fn burn_from(2022		&self,2023		sender: T::CrossAccountId,2024		from: T::CrossAccountId,2025		token: TokenId,2026		amount: u128,2027		budget: &dyn Budget,2028	) -> DispatchResultWithPostInfo;20292030	/// Check permission to nest token.2031	///2032	/// * `sender` - The user who initiated the check.2033	/// * `from` - The token that is checked for embedding.2034	/// * `under` - Token under which to check.2035	/// * `budget` - The maximum budget that can be spent on the check.2036	fn check_nesting(2037		&self,2038		sender: T::CrossAccountId,2039		from: (CollectionId, TokenId),2040		under: TokenId,2041		budget: &dyn Budget,2042	) -> DispatchResult;20432044	/// Nest one token into another.2045	///2046	/// * `under` - Token holder.2047	/// * `to_nest` - Nested token.2048	fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId));20492050	/// Unnest token.2051	///2052	/// * `under` - Token holder.2053	/// * `to_nest` - Token to unnest.2054	fn unnest(&self, under: TokenId, to_nest: (CollectionId, TokenId));20552056	/// Get all user tokens.2057	///2058	/// * `account` - Account for which you need to get tokens.2059	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;20602061	/// Get all the tokens in the collection.2062	fn collection_tokens(&self) -> Vec<TokenId>;20632064	/// Check if the token exists.2065	///2066	/// * `token` - Id token to check.2067	fn token_exists(&self, token: TokenId) -> bool;20682069	/// Get the id of the last minted token.2070	fn last_token_id(&self) -> TokenId;20712072	/// Get the owner of the token.2073	///2074	/// * `token` - The token for which you need to find out the owner.2075	fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;20762077	/// Returns 10 tokens owners in no particular order.2078	///2079	/// * `token` - The token for which you need to find out the owners.2080	fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId>;20812082	/// Get the value of the token property by key.2083	///2084	/// * `token` - Token with the property to get.2085	/// * `key` - Property name.2086	fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue>;20872088	/// Get a set of token properties by key vector.2089	///2090	/// * `token` - Token with the property to get.2091	/// * `keys` - Vector of property keys. If this parameter is [None](sp_std::result::Result),2092	/// then all properties are returned.2093	fn token_properties(&self, token: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property>;20942095	/// Amount of unique collection tokens2096	fn total_supply(&self) -> u32;20972098	/// Amount of different tokens account has.2099	///2100	/// * `account` - The account for which need to get the balance.2101	fn account_balance(&self, account: T::CrossAccountId) -> u32;21022103	/// Amount of specific token account have.2104	fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;21052106	/// Amount of token pieces2107	fn total_pieces(&self, token: TokenId) -> Option<u128>;21082109	/// Get the number of parts of the token that a trusted user can manage.2110	///2111	/// * `sender` - Trusted user.2112	/// * `spender` - Owner of the token.2113	/// * `token` - The token for which to get the value.2114	fn allowance(2115		&self,2116		sender: T::CrossAccountId,2117		spender: T::CrossAccountId,2118		token: TokenId,2119	) -> u128;21202121	/// Get extension for RFT collection.2122	fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>>;21232124	/// The `operator` is allowed to transfer all tokens of the `owner` on their behalf.2125	/// * `owner` - Token owner2126	/// * `operator` - Operator2127	/// * `approve` - Should operator status be granted or revoked?2128	fn set_allowance_for_all(2129		&self,2130		owner: T::CrossAccountId,2131		operator: T::CrossAccountId,2132		approve: bool,2133	) -> DispatchResultWithPostInfo;21342135	/// Tells whether the given `owner` approves the `operator`.2136	fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool;2137}21382139/// Extension for RFT collection.2140pub trait RefungibleExtensions<T>2141where2142	T: Config,2143{2144	/// Change the number of parts of the token.2145	///2146	/// When the value changes down, this function is equivalent to burning parts of the token.2147	///2148	/// * `sender` - The user calling the repartition operation. Must be the owner of the token.2149	/// * `token` - The token for which you want to change the number of parts.2150	/// * `amount` - The new value of the parts of the token.2151	fn repartition(2152		&self,2153		sender: &T::CrossAccountId,2154		token: TokenId,2155		amount: u128,2156	) -> DispatchResultWithPostInfo;2157}21582159/// Merge [`DispatchResult`] with [`Weight`] into [`DispatchResultWithPostInfo`].2160///2161/// Used for [`CommonCollectionOperations`] implementations and flexible enough to do so.2162pub fn with_weight(res: DispatchResult, weight: Weight) -> DispatchResultWithPostInfo {2163	let post_info = PostDispatchInfo {2164		actual_weight: Some(weight),2165		pays_fee: Pays::Yes,2166	};2167	match res {2168		Ok(()) => Ok(post_info),2169		Err(error) => Err(DispatchErrorWithPostInfo { post_info, error }),2170	}2171}21722173impl<T: Config> From<PropertiesError> for Error<T> {2174	fn from(error: PropertiesError) -> Self {2175		match error {2176			PropertiesError::NoSpaceForProperty => Self::NoSpaceForProperty,2177			PropertiesError::PropertyLimitReached => Self::PropertyLimitReached,2178			PropertiesError::InvalidCharacterInPropertyKey => Self::InvalidCharacterInPropertyKey,2179			PropertiesError::PropertyKeyIsTooLong => Self::PropertyKeyIsTooLong,2180			PropertiesError::EmptyPropertyKey => Self::EmptyPropertyKey,2181		}2182	}2183}
modifiedtests/src/change-collection-owner.test.tsdiffbeforeafterboth
--- a/tests/src/change-collection-owner.test.ts
+++ b/tests/src/change-collection-owner.test.ts
@@ -146,7 +146,7 @@
     const confirmSponsorshipTx = () => collection.confirmSponsorship(alice);
     const removeSponsorTx = () => collection.removeSponsor(alice);
     await expect(setSponsorTx()).to.be.rejectedWith(/common\.NoPermission/);
-    await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
+    await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmSponsorshipFail/);
     await expect(removeSponsorTx()).to.be.rejectedWith(/common\.NoPermission/);
 
     const limits = {
modifiedtests/src/confirmSponsorship.test.tsdiffbeforeafterboth
--- a/tests/src/confirmSponsorship.test.ts
+++ b/tests/src/confirmSponsorship.test.ts
@@ -207,14 +207,14 @@
     const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
     await collection.setSponsor(alice, bob.address);
     const confirmSponsorshipTx = () => collection.confirmSponsorship(charlie);
-    await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
+    await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmSponsorshipFail/);
   });
 
   itSub('(!negative test!) Confirm sponsorship using owner address', async ({helper}) => {
     const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
     await collection.setSponsor(alice, bob.address);
     const confirmSponsorshipTx = () => collection.confirmSponsorship(alice);
-    await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
+    await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmSponsorshipFail/);
   });
 
   itSub('(!negative test!) Confirm sponsorship by collection admin', async ({helper}) => {
@@ -222,13 +222,13 @@
     await collection.setSponsor(alice, bob.address);
     await collection.addAdmin(alice, {Substrate: charlie.address});
     const confirmSponsorshipTx = () => collection.confirmSponsorship(charlie);
-    await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
+    await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmSponsorshipFail/);
   });
 
   itSub('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async ({helper}) => {
     const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
     const confirmSponsorshipTx = () => collection.confirmSponsorship(charlie);
-    await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
+    await expect(confirmSponsorshipTx()).to.be.rejectedWith(/common\.ConfirmSponsorshipFail/);
   });
 
   itSub('(!negative test!) Confirm sponsorship in a collection that was destroyed', async ({helper}) => {
modifiedtests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/collectionSponsoring.test.ts
+++ b/tests/src/eth/collectionSponsoring.test.ts
@@ -128,7 +128,7 @@
       let sponsorship = (await collectionSub.getData())!.raw.sponsorship;
       expect(sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));
       // Account cannot confirm sponsorship if it is not set as a sponsor
-      await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+      await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
       
       // Sponsor can confirm sponsorship:
       await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});
@@ -257,7 +257,7 @@
       await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send();
       let collectionData = (await collectionSub.getData())!;
       expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
-      await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+      await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
   
       await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
       collectionData = (await collectionSub.getData())!;
modifiedtests/src/eth/createFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createFTCollection.test.ts
+++ b/tests/src/eth/createFTCollection.test.ts
@@ -46,7 +46,7 @@
     let data = (await helper.rft.getData(collectionId))!;
     expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
 
-    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
 
     const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
@@ -69,7 +69,7 @@
     let data = (await helper.rft.getData(collectionId))!;
     expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
 
-    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
 
     const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
@@ -192,7 +192,7 @@
       const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor, true);
       await expect(sponsorCollection.methods
         .confirmCollectionSponsorship()
-        .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+        .call()).to.be.rejectedWith('ConfirmSponsorshipFail');
     }
     {
       await expect(peasantCollection.methods
@@ -217,7 +217,7 @@
       const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor);
       await expect(sponsorCollection.methods
         .confirmCollectionSponsorship()
-        .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+        .call()).to.be.rejectedWith('ConfirmSponsorshipFail');
     }
     {
       await expect(peasantCollection.methods
modifiedtests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createNFTCollection.test.ts
+++ b/tests/src/eth/createNFTCollection.test.ts
@@ -86,7 +86,7 @@
     let data = (await helper.nft.getData(collectionId))!;
     expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
 
-    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
 
     const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
@@ -109,7 +109,7 @@
     let data = (await helper.nft.getData(collectionId))!;
     expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
 
-    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
 
     const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
@@ -203,7 +203,7 @@
       const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);
       await expect(sponsorCollection.methods
         .confirmCollectionSponsorship()
-        .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+        .call()).to.be.rejectedWith('ConfirmSponsorshipFail');
     }
     {
       await expect(malfeasantCollection.methods
@@ -228,7 +228,7 @@
       const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);
       await expect(sponsorCollection.methods
         .confirmCollectionSponsorship()
-        .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+        .call()).to.be.rejectedWith('ConfirmSponsorshipFail');
     }
     {
       await expect(malfeasantCollection.methods
modifiedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth
--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -121,7 +121,7 @@
     let data = (await helper.rft.getData(collectionId))!;
     expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
 
-    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
 
     const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
@@ -143,7 +143,7 @@
     let data = (await helper.rft.getData(collectionId))!;
     expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
 
-    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
 
     const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
@@ -235,7 +235,7 @@
       const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
       await expect(sponsorCollection.methods
         .confirmCollectionSponsorship()
-        .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+        .call()).to.be.rejectedWith('ConfirmSponsorshipFail');
     }
     {
       await expect(peasantCollection.methods
@@ -260,7 +260,7 @@
       const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
       await expect(sponsorCollection.methods
         .confirmCollectionSponsorship()
-        .call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');
+        .call()).to.be.rejectedWith('ConfirmSponsorshipFail');
     }
     {
       await expect(peasantCollection.methods
modifiedtests/src/eth/events.test.tsdiffbeforeafterboth
--- a/tests/src/eth/events.test.ts
+++ b/tests/src/eth/events.test.ts
@@ -18,6 +18,7 @@
 import {IKeyringPair} from '@polkadot/types/types';
 import {EthUniqueHelper, itEth, usingEthPlaygrounds} from './util';
 import {TCollectionMode} from '../util/playgrounds/types';
+import {Pallets, requirePalletsOrSkip} from '../util';
 
 let donor: IKeyringPair;
   
@@ -253,7 +254,7 @@
   collectionHelper.events.allEvents((_: any, event: any) => {
     ethEvents.push(event);
   });
-  const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionOwnedChanged']}]);
+  const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionOwnerChanged']}]);
   {
     await collection.methods.changeCollectionOwnerCross(new_owner).send({from: owner});
     await helper.wait.newBlocks(1);
@@ -265,7 +266,7 @@
         },
       },
     ]);
-    expect(subEvents).to.be.like([{method: 'CollectionOwnedChanged'}]);
+    expect(subEvents).to.be.like([{method: 'CollectionOwnerChanged'}]);
   }
   unsubscribe();
 }
@@ -401,6 +402,7 @@
   }
   {
     await collection.methods.deleteProperties(tokenId, ['A']).send({from: owner});
+    await helper.wait.newBlocks(1);
     expect(ethEvents).to.be.like([
       {
         event: 'TokenChanged',
@@ -437,7 +439,7 @@
     await testCollectionLimitSet(helper, mode);
   });
     
-  itEth('CollectionChanged event for CollectionOwnedChanged', async ({helper}) => {
+  itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {
     await testCollectionOwnedChanged(helper, mode);
   });
     
@@ -477,7 +479,7 @@
     await testCollectionLimitSet(helper, mode);
   });
     
-  itEth('CollectionChanged event for CollectionOwnedChanged', async ({helper}) => {
+  itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {
     await testCollectionOwnedChanged(helper, mode);
   });
     
@@ -497,6 +499,13 @@
 describe('[RFT] Sync sub & eth events', () => {
   const mode: TCollectionMode = 'rft';
 
+  before(async function() {
+    await usingEthPlaygrounds(async (helper, privateKey) => {
+      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
+      const _donor = await privateKey({filename: __filename});
+    });
+  });
+
   itEth('CollectionCreated and CollectionDestroyed events', async ({helper}) => {
     await testCollectionCreatedAndDestroy(helper, mode);
   });
@@ -521,7 +530,7 @@
     await testCollectionLimitSet(helper, mode);
   });
     
-  itEth('CollectionChanged event for CollectionOwnedChanged', async ({helper}) => {
+  itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {
     await testCollectionOwnedChanged(helper, mode);
   });
     
modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-errors.ts
+++ b/tests/src/interfaces/augment-api-errors.ts
@@ -145,6 +145,10 @@
        **/
       CollectionTokenPrefixLimitExceeded: AugmentedError<ApiType>;
       /**
+       * This address is not set as sponsor, use setCollectionSponsor first.
+       **/
+      ConfirmSponsorshipFail: AugmentedError<ApiType>;
+      /**
        * Empty property keys are forbidden
        **/
       EmptyPropertyKey: AugmentedError<ApiType>;
@@ -217,6 +221,10 @@
        **/
       UserIsNotAllowedToNest: AugmentedError<ApiType>;
       /**
+       * The user is not an administrator.
+       **/
+      UserIsNotCollectionAdmin: AugmentedError<ApiType>;
+      /**
        * Generic error
        **/
       [key: string]: AugmentedError<ApiType>;
@@ -845,10 +853,6 @@
        * Decimal_points parameter must be lower than [`up_data_structs::MAX_DECIMAL_POINTS`].
        **/
       CollectionDecimalPointLimitExceeded: AugmentedError<ApiType>;
-      /**
-       * This address is not set as sponsor, use setCollectionSponsor first.
-       **/
-      ConfirmUnsetSponsorFail: AugmentedError<ApiType>;
       /**
        * Length of items properties must be greater than 0.
        **/
modifiedtests/src/interfaces/augment-api-events.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-events.ts
+++ b/tests/src/interfaces/augment-api-events.ts
@@ -103,6 +103,14 @@
     };
     common: {
       /**
+       * Address was added to the allow list.
+       **/
+      AllowListAddressAdded: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+      /**
+       * Address was removed from the allow list.
+       **/
+      AllowListAddressRemoved: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+      /**
        * Amount pieces of token owned by `sender` was approved for `spender`.
        **/
       Approved: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;
@@ -111,6 +119,14 @@
        **/
       ApprovedForAll: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, bool]>;
       /**
+       * Collection admin was added.
+       **/
+      CollectionAdminAdded: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+      /**
+       * Collection admin was removed.
+       **/
+      CollectionAdminRemoved: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+      /**
        * New collection was created
        **/
       CollectionCreated: AugmentedEvent<ApiType, [u32, u8, AccountId32]>;
@@ -119,6 +135,18 @@
        **/
       CollectionDestroyed: AugmentedEvent<ApiType, [u32]>;
       /**
+       * Collection limits were set.
+       **/
+      CollectionLimitSet: AugmentedEvent<ApiType, [u32]>;
+      /**
+       * Collection owned was changed.
+       **/
+      CollectionOwnerChanged: AugmentedEvent<ApiType, [u32, AccountId32]>;
+      /**
+       * Collection permissions were set.
+       **/
+      CollectionPermissionSet: AugmentedEvent<ApiType, [u32]>;
+      /**
        * The property has been deleted.
        **/
       CollectionPropertyDeleted: AugmentedEvent<ApiType, [u32, Bytes]>;
@@ -127,6 +155,14 @@
        **/
       CollectionPropertySet: AugmentedEvent<ApiType, [u32, Bytes]>;
       /**
+       * Collection sponsor was removed.
+       **/
+      CollectionSponsorRemoved: AugmentedEvent<ApiType, [u32]>;
+      /**
+       * Collection sponsor was set.
+       **/
+      CollectionSponsorSet: AugmentedEvent<ApiType, [u32, AccountId32]>;
+      /**
        * New item was created.
        **/
       ItemCreated: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;
@@ -139,6 +175,10 @@
        **/
       PropertyPermissionSet: AugmentedEvent<ApiType, [u32, Bytes]>;
       /**
+       * New sponsor was confirm.
+       **/
+      SponsorshipConfirmed: AugmentedEvent<ApiType, [u32, AccountId32]>;
+      /**
        * The token property has been deleted.
        **/
       TokenPropertyDeleted: AugmentedEvent<ApiType, [u32, u32, Bytes]>;
@@ -688,89 +728,6 @@
        * We have ended a spend period and will now allocate funds.
        **/
       Spending: AugmentedEvent<ApiType, [budgetRemaining: u128], { budgetRemaining: u128 }>;
-      /**
-       * Generic event
-       **/
-      [key: string]: AugmentedEvent<ApiType>;
-    };
-    unique: {
-      /**
-       * Address was added to the allow list
-       * 
-       * # Arguments
-       * * collection_id: ID of the affected collection.
-       * * user: Address of the added account.
-       **/
-      AllowListAddressAdded: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-      /**
-       * Address was removed from the allow list
-       * 
-       * # Arguments
-       * * collection_id: ID of the affected collection.
-       * * user: Address of the removed account.
-       **/
-      AllowListAddressRemoved: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-      /**
-       * Collection admin was added
-       * 
-       * # Arguments
-       * * collection_id: ID of the affected collection.
-       * * admin: Admin address.
-       **/
-      CollectionAdminAdded: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-      /**
-       * Collection admin was removed
-       * 
-       * # Arguments
-       * * collection_id: ID of the affected collection.
-       * * admin: Removed admin address.
-       **/
-      CollectionAdminRemoved: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-      /**
-       * Collection limits were set
-       * 
-       * # Arguments
-       * * collection_id: ID of the affected collection.
-       **/
-      CollectionLimitSet: AugmentedEvent<ApiType, [u32]>;
-      /**
-       * Collection owned was changed
-       * 
-       * # Arguments
-       * * collection_id: ID of the affected collection.
-       * * owner: New owner address.
-       **/
-      CollectionOwnedChanged: AugmentedEvent<ApiType, [u32, AccountId32]>;
-      /**
-       * Collection permissions were set
-       * 
-       * # Arguments
-       * * collection_id: ID of the affected collection.
-       **/
-      CollectionPermissionSet: AugmentedEvent<ApiType, [u32]>;
-      /**
-       * Collection sponsor was removed
-       * 
-       * # Arguments
-       * * collection_id: ID of the affected collection.
-       **/
-      CollectionSponsorRemoved: AugmentedEvent<ApiType, [u32]>;
-      /**
-       * Collection sponsor was set
-       * 
-       * # Arguments
-       * * collection_id: ID of the affected collection.
-       * * owner: New sponsor address.
-       **/
-      CollectionSponsorSet: AugmentedEvent<ApiType, [u32, AccountId32]>;
-      /**
-       * New sponsor was confirm
-       * 
-       * # Arguments
-       * * collection_id: ID of the affected collection.
-       * * sponsor: New sponsor address.
-       **/
-      SponsorshipConfirmed: AugmentedEvent<ApiType, [u32, AccountId32]>;
       /**
        * Generic event
        **/
modifiedtests/src/interfaces/augment-types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-types.ts
+++ b/tests/src/interfaces/augment-types.ts
@@ -5,7 +5,7 @@
 // this is required to allow for ambient/previous definitions
 import '@polkadot/types/types/registry';
 
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletEvmMigrationEvent, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerV2BlockAgenda, PalletUniqueSchedulerV2Call, PalletUniqueSchedulerV2Error, PalletUniqueSchedulerV2Event, PalletUniqueSchedulerV2Scheduled, PalletUniqueSchedulerV2ScheduledCall, 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, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, 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, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletEvmMigrationEvent, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueSchedulerV2BlockAgenda, PalletUniqueSchedulerV2Call, PalletUniqueSchedulerV2Error, PalletUniqueSchedulerV2Event, PalletUniqueSchedulerV2Scheduled, PalletUniqueSchedulerV2ScheduledCall, 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, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
 import type { Data, StorageKey } from '@polkadot/types';
 import type { BitVec, Bool, Bytes, F32, F64, I128, I16, I256, I32, I64, I8, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, f32, f64, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec';
 import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';
@@ -902,7 +902,6 @@
     PalletTreasuryProposal: PalletTreasuryProposal;
     PalletUniqueCall: PalletUniqueCall;
     PalletUniqueError: PalletUniqueError;
-    PalletUniqueRawEvent: PalletUniqueRawEvent;
     PalletUniqueSchedulerV2BlockAgenda: PalletUniqueSchedulerV2BlockAgenda;
     PalletUniqueSchedulerV2Call: PalletUniqueSchedulerV2Call;
     PalletUniqueSchedulerV2Error: PalletUniqueSchedulerV2Error;
modifiedtests/src/interfaces/default/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -1269,7 +1269,9 @@
   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' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal';
+  readonly isConfirmSponsorshipFail: boolean;
+  readonly isUserIsNotCollectionAdmin: boolean;
+  readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal' | 'ConfirmSponsorshipFail' | 'UserIsNotCollectionAdmin';
 }
 
 /** @name PalletCommonEvent */
@@ -1298,7 +1300,27 @@
   readonly asTokenPropertyDeleted: ITuple<[u32, u32, Bytes]>;
   readonly isPropertyPermissionSet: boolean;
   readonly asPropertyPermissionSet: ITuple<[u32, Bytes]>;
-  readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'ApprovedForAll' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet';
+  readonly isAllowListAddressAdded: boolean;
+  readonly asAllowListAddressAdded: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+  readonly isAllowListAddressRemoved: boolean;
+  readonly asAllowListAddressRemoved: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+  readonly isCollectionAdminAdded: boolean;
+  readonly asCollectionAdminAdded: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+  readonly isCollectionAdminRemoved: boolean;
+  readonly asCollectionAdminRemoved: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+  readonly isCollectionLimitSet: boolean;
+  readonly asCollectionLimitSet: u32;
+  readonly isCollectionOwnerChanged: boolean;
+  readonly asCollectionOwnerChanged: ITuple<[u32, AccountId32]>;
+  readonly isCollectionPermissionSet: boolean;
+  readonly asCollectionPermissionSet: u32;
+  readonly isCollectionSponsorSet: boolean;
+  readonly asCollectionSponsorSet: ITuple<[u32, AccountId32]>;
+  readonly isSponsorshipConfirmed: boolean;
+  readonly asSponsorshipConfirmed: ITuple<[u32, AccountId32]>;
+  readonly isCollectionSponsorRemoved: boolean;
+  readonly asCollectionSponsorRemoved: u32;
+  readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'ApprovedForAll' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet' | 'AllowListAddressAdded' | 'AllowListAddressRemoved' | 'CollectionAdminAdded' | 'CollectionAdminRemoved' | 'CollectionLimitSet' | 'CollectionOwnerChanged' | 'CollectionPermissionSet' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionSponsorRemoved';
 }
 
 /** @name PalletConfigurationCall */
@@ -2324,35 +2346,9 @@
 /** @name PalletUniqueError */
 export interface PalletUniqueError extends Enum {
   readonly isCollectionDecimalPointLimitExceeded: boolean;
-  readonly isConfirmUnsetSponsorFail: boolean;
   readonly isEmptyArgument: boolean;
   readonly isRepartitionCalledOnNonRefungibleCollection: boolean;
-  readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection';
-}
-
-/** @name PalletUniqueRawEvent */
-export interface PalletUniqueRawEvent extends Enum {
-  readonly isCollectionSponsorRemoved: boolean;
-  readonly asCollectionSponsorRemoved: u32;
-  readonly isCollectionAdminAdded: boolean;
-  readonly asCollectionAdminAdded: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-  readonly isCollectionOwnedChanged: boolean;
-  readonly asCollectionOwnedChanged: ITuple<[u32, AccountId32]>;
-  readonly isCollectionSponsorSet: boolean;
-  readonly asCollectionSponsorSet: ITuple<[u32, AccountId32]>;
-  readonly isSponsorshipConfirmed: boolean;
-  readonly asSponsorshipConfirmed: ITuple<[u32, AccountId32]>;
-  readonly isCollectionAdminRemoved: boolean;
-  readonly asCollectionAdminRemoved: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-  readonly isAllowListAddressRemoved: boolean;
-  readonly asAllowListAddressRemoved: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-  readonly isAllowListAddressAdded: boolean;
-  readonly asAllowListAddressAdded: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-  readonly isCollectionLimitSet: boolean;
-  readonly asCollectionLimitSet: u32;
-  readonly isCollectionPermissionSet: boolean;
-  readonly asCollectionPermissionSet: u32;
-  readonly type: 'CollectionSponsorRemoved' | 'CollectionAdminAdded' | 'CollectionOwnedChanged' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionAdminRemoved' | 'AllowListAddressRemoved' | 'AllowListAddressAdded' | 'CollectionLimitSet' | 'CollectionPermissionSet';
+  readonly type: 'CollectionDecimalPointLimitExceeded' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection';
 }
 
 /** @name PalletUniqueSchedulerV2BlockAgenda */
modifiedtests/src/interfaces/lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -989,34 +989,8 @@
     }
   },
   /**
-   * Lookup89: pallet_unique::RawEvent<sp_core::crypto::AccountId32, pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
-   **/
-  PalletUniqueRawEvent: {
-    _enum: {
-      CollectionSponsorRemoved: 'u32',
-      CollectionAdminAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',
-      CollectionOwnedChanged: '(u32,AccountId32)',
-      CollectionSponsorSet: '(u32,AccountId32)',
-      SponsorshipConfirmed: '(u32,AccountId32)',
-      CollectionAdminRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',
-      AllowListAddressRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',
-      AllowListAddressAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',
-      CollectionLimitSet: 'u32',
-      CollectionPermissionSet: 'u32'
-    }
-  },
-  /**
-   * Lookup90: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>
+   * Lookup89: pallet_unique_scheduler_v2::pallet::Event<T>
    **/
-  PalletEvmAccountBasicCrossAccountIdRepr: {
-    _enum: {
-      Substrate: 'AccountId32',
-      Ethereum: 'H160'
-    }
-  },
-  /**
-   * Lookup93: pallet_unique_scheduler_v2::pallet::Event<T>
-   **/
   PalletUniqueSchedulerV2Event: {
     _enum: {
       Scheduled: {
@@ -1047,7 +1021,7 @@
     }
   },
   /**
-   * Lookup96: pallet_common::pallet::Event<T>
+   * Lookup92: pallet_common::pallet::Event<T>
    **/
   PalletCommonEvent: {
     _enum: {
@@ -1062,11 +1036,30 @@
       CollectionPropertyDeleted: '(u32,Bytes)',
       TokenPropertySet: '(u32,u32,Bytes)',
       TokenPropertyDeleted: '(u32,u32,Bytes)',
-      PropertyPermissionSet: '(u32,Bytes)'
+      PropertyPermissionSet: '(u32,Bytes)',
+      AllowListAddressAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',
+      AllowListAddressRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',
+      CollectionAdminAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',
+      CollectionAdminRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',
+      CollectionLimitSet: 'u32',
+      CollectionOwnerChanged: '(u32,AccountId32)',
+      CollectionPermissionSet: 'u32',
+      CollectionSponsorSet: '(u32,AccountId32)',
+      SponsorshipConfirmed: '(u32,AccountId32)',
+      CollectionSponsorRemoved: 'u32'
+    }
+  },
+  /**
+   * Lookup95: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>
+   **/
+  PalletEvmAccountBasicCrossAccountIdRepr: {
+    _enum: {
+      Substrate: 'AccountId32',
+      Ethereum: 'H160'
     }
   },
   /**
-   * Lookup100: pallet_structure::pallet::Event<T>
+   * Lookup99: pallet_structure::pallet::Event<T>
    **/
   PalletStructureEvent: {
     _enum: {
@@ -1074,7 +1067,7 @@
     }
   },
   /**
-   * Lookup101: pallet_rmrk_core::pallet::Event<T>
+   * Lookup100: pallet_rmrk_core::pallet::Event<T>
    **/
   PalletRmrkCoreEvent: {
     _enum: {
@@ -1151,7 +1144,7 @@
     }
   },
   /**
-   * Lookup102: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>
+   * Lookup101: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>
    **/
   RmrkTraitsNftAccountIdOrCollectionNftTuple: {
     _enum: {
@@ -1160,7 +1153,7 @@
     }
   },
   /**
-   * Lookup106: pallet_rmrk_equip::pallet::Event<T>
+   * Lookup105: pallet_rmrk_equip::pallet::Event<T>
    **/
   PalletRmrkEquipEvent: {
     _enum: {
@@ -1175,7 +1168,7 @@
     }
   },
   /**
-   * Lookup107: pallet_app_promotion::pallet::Event<T>
+   * Lookup106: pallet_app_promotion::pallet::Event<T>
    **/
   PalletAppPromotionEvent: {
     _enum: {
@@ -1186,7 +1179,7 @@
     }
   },
   /**
-   * Lookup108: pallet_foreign_assets::module::Event<T>
+   * Lookup107: pallet_foreign_assets::module::Event<T>
    **/
   PalletForeignAssetsModuleEvent: {
     _enum: {
@@ -1211,7 +1204,7 @@
     }
   },
   /**
-   * Lookup109: pallet_foreign_assets::module::AssetMetadata<Balance>
+   * Lookup108: pallet_foreign_assets::module::AssetMetadata<Balance>
    **/
   PalletForeignAssetsModuleAssetMetadata: {
     name: 'Bytes',
@@ -1220,7 +1213,7 @@
     minimalBalance: 'u128'
   },
   /**
-   * Lookup110: pallet_evm::pallet::Event<T>
+   * Lookup109: pallet_evm::pallet::Event<T>
    **/
   PalletEvmEvent: {
     _enum: {
@@ -1242,7 +1235,7 @@
     }
   },
   /**
-   * Lookup111: ethereum::log::Log
+   * Lookup110: ethereum::log::Log
    **/
   EthereumLog: {
     address: 'H160',
@@ -1250,7 +1243,7 @@
     data: 'Bytes'
   },
   /**
-   * Lookup113: pallet_ethereum::pallet::Event
+   * Lookup112: pallet_ethereum::pallet::Event
    **/
   PalletEthereumEvent: {
     _enum: {
@@ -1263,7 +1256,7 @@
     }
   },
   /**
-   * Lookup114: evm_core::error::ExitReason
+   * Lookup113: evm_core::error::ExitReason
    **/
   EvmCoreErrorExitReason: {
     _enum: {
@@ -1274,13 +1267,13 @@
     }
   },
   /**
-   * Lookup115: evm_core::error::ExitSucceed
+   * Lookup114: evm_core::error::ExitSucceed
    **/
   EvmCoreErrorExitSucceed: {
     _enum: ['Stopped', 'Returned', 'Suicided']
   },
   /**
-   * Lookup116: evm_core::error::ExitError
+   * Lookup115: evm_core::error::ExitError
    **/
   EvmCoreErrorExitError: {
     _enum: {
@@ -1302,13 +1295,13 @@
     }
   },
   /**
-   * Lookup119: evm_core::error::ExitRevert
+   * Lookup118: evm_core::error::ExitRevert
    **/
   EvmCoreErrorExitRevert: {
     _enum: ['Reverted']
   },
   /**
-   * Lookup120: evm_core::error::ExitFatal
+   * Lookup119: evm_core::error::ExitFatal
    **/
   EvmCoreErrorExitFatal: {
     _enum: {
@@ -1319,7 +1312,7 @@
     }
   },
   /**
-   * Lookup121: pallet_evm_contract_helpers::pallet::Event<T>
+   * Lookup120: pallet_evm_contract_helpers::pallet::Event<T>
    **/
   PalletEvmContractHelpersEvent: {
     _enum: {
@@ -1329,25 +1322,25 @@
     }
   },
   /**
-   * Lookup122: pallet_evm_migration::pallet::Event<T>
+   * Lookup121: pallet_evm_migration::pallet::Event<T>
    **/
   PalletEvmMigrationEvent: {
     _enum: ['TestEvent']
   },
   /**
-   * Lookup123: pallet_maintenance::pallet::Event<T>
+   * Lookup122: pallet_maintenance::pallet::Event<T>
    **/
   PalletMaintenanceEvent: {
     _enum: ['MaintenanceEnabled', 'MaintenanceDisabled']
   },
   /**
-   * Lookup124: pallet_test_utils::pallet::Event<T>
+   * Lookup123: pallet_test_utils::pallet::Event<T>
    **/
   PalletTestUtilsEvent: {
     _enum: ['ValueIsSet', 'ShouldRollback', 'BatchCompleted']
   },
   /**
-   * Lookup125: frame_system::Phase
+   * Lookup124: frame_system::Phase
    **/
   FrameSystemPhase: {
     _enum: {
@@ -1357,14 +1350,14 @@
     }
   },
   /**
-   * Lookup127: frame_system::LastRuntimeUpgradeInfo
+   * Lookup126: frame_system::LastRuntimeUpgradeInfo
    **/
   FrameSystemLastRuntimeUpgradeInfo: {
     specVersion: 'Compact<u32>',
     specName: 'Text'
   },
   /**
-   * Lookup128: frame_system::pallet::Call<T>
+   * Lookup127: frame_system::pallet::Call<T>
    **/
   FrameSystemCall: {
     _enum: {
@@ -1402,7 +1395,7 @@
     }
   },
   /**
-   * Lookup133: frame_system::limits::BlockWeights
+   * Lookup132: frame_system::limits::BlockWeights
    **/
   FrameSystemLimitsBlockWeights: {
     baseBlock: 'SpWeightsWeightV2Weight',
@@ -1410,7 +1403,7 @@
     perClass: 'FrameSupportDispatchPerDispatchClassWeightsPerClass'
   },
   /**
-   * Lookup134: frame_support::dispatch::PerDispatchClass<frame_system::limits::WeightsPerClass>
+   * Lookup133: frame_support::dispatch::PerDispatchClass<frame_system::limits::WeightsPerClass>
    **/
   FrameSupportDispatchPerDispatchClassWeightsPerClass: {
     normal: 'FrameSystemLimitsWeightsPerClass',
@@ -1418,7 +1411,7 @@
     mandatory: 'FrameSystemLimitsWeightsPerClass'
   },
   /**
-   * Lookup135: frame_system::limits::WeightsPerClass
+   * Lookup134: frame_system::limits::WeightsPerClass
    **/
   FrameSystemLimitsWeightsPerClass: {
     baseExtrinsic: 'SpWeightsWeightV2Weight',
@@ -1427,13 +1420,13 @@
     reserved: 'Option<SpWeightsWeightV2Weight>'
   },
   /**
-   * Lookup137: frame_system::limits::BlockLength
+   * Lookup136: frame_system::limits::BlockLength
    **/
   FrameSystemLimitsBlockLength: {
     max: 'FrameSupportDispatchPerDispatchClassU32'
   },
   /**
-   * Lookup138: frame_support::dispatch::PerDispatchClass<T>
+   * Lookup137: frame_support::dispatch::PerDispatchClass<T>
    **/
   FrameSupportDispatchPerDispatchClassU32: {
     normal: 'u32',
@@ -1441,14 +1434,14 @@
     mandatory: 'u32'
   },
   /**
-   * Lookup139: sp_weights::RuntimeDbWeight
+   * Lookup138: sp_weights::RuntimeDbWeight
    **/
   SpWeightsRuntimeDbWeight: {
     read: 'u64',
     write: 'u64'
   },
   /**
-   * Lookup140: sp_version::RuntimeVersion
+   * Lookup139: sp_version::RuntimeVersion
    **/
   SpVersionRuntimeVersion: {
     specName: 'Text',
@@ -1461,13 +1454,13 @@
     stateVersion: 'u8'
   },
   /**
-   * Lookup145: frame_system::pallet::Error<T>
+   * Lookup144: frame_system::pallet::Error<T>
    **/
   FrameSystemError: {
     _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered']
   },
   /**
-   * Lookup146: polkadot_primitives::v2::PersistedValidationData<primitive_types::H256, N>
+   * Lookup145: polkadot_primitives::v2::PersistedValidationData<primitive_types::H256, N>
    **/
   PolkadotPrimitivesV2PersistedValidationData: {
     parentHead: 'Bytes',
@@ -1476,19 +1469,19 @@
     maxPovSize: 'u32'
   },
   /**
-   * Lookup149: polkadot_primitives::v2::UpgradeRestriction
+   * Lookup148: polkadot_primitives::v2::UpgradeRestriction
    **/
   PolkadotPrimitivesV2UpgradeRestriction: {
     _enum: ['Present']
   },
   /**
-   * Lookup150: sp_trie::storage_proof::StorageProof
+   * Lookup149: sp_trie::storage_proof::StorageProof
    **/
   SpTrieStorageProof: {
     trieNodes: 'BTreeSet<Bytes>'
   },
   /**
-   * Lookup152: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot
+   * Lookup151: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot
    **/
   CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: {
     dmqMqcHead: 'H256',
@@ -1497,7 +1490,7 @@
     egressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>'
   },
   /**
-   * Lookup155: polkadot_primitives::v2::AbridgedHrmpChannel
+   * Lookup154: polkadot_primitives::v2::AbridgedHrmpChannel
    **/
   PolkadotPrimitivesV2AbridgedHrmpChannel: {
     maxCapacity: 'u32',
@@ -1508,7 +1501,7 @@
     mqcHead: 'Option<H256>'
   },
   /**
-   * Lookup156: polkadot_primitives::v2::AbridgedHostConfiguration
+   * Lookup155: polkadot_primitives::v2::AbridgedHostConfiguration
    **/
   PolkadotPrimitivesV2AbridgedHostConfiguration: {
     maxCodeSize: 'u32',
@@ -1522,14 +1515,14 @@
     validationUpgradeDelay: 'u32'
   },
   /**
-   * Lookup162: polkadot_core_primitives::OutboundHrmpMessage<polkadot_parachain::primitives::Id>
+   * Lookup161: polkadot_core_primitives::OutboundHrmpMessage<polkadot_parachain::primitives::Id>
    **/
   PolkadotCorePrimitivesOutboundHrmpMessage: {
     recipient: 'u32',
     data: 'Bytes'
   },
   /**
-   * Lookup163: cumulus_pallet_parachain_system::pallet::Call<T>
+   * Lookup162: cumulus_pallet_parachain_system::pallet::Call<T>
    **/
   CumulusPalletParachainSystemCall: {
     _enum: {
@@ -1548,7 +1541,7 @@
     }
   },
   /**
-   * Lookup164: cumulus_primitives_parachain_inherent::ParachainInherentData
+   * Lookup163: cumulus_primitives_parachain_inherent::ParachainInherentData
    **/
   CumulusPrimitivesParachainInherentParachainInherentData: {
     validationData: 'PolkadotPrimitivesV2PersistedValidationData',
@@ -1557,27 +1550,27 @@
     horizontalMessages: 'BTreeMap<u32, Vec<PolkadotCorePrimitivesInboundHrmpMessage>>'
   },
   /**
-   * Lookup166: polkadot_core_primitives::InboundDownwardMessage<BlockNumber>
+   * Lookup165: polkadot_core_primitives::InboundDownwardMessage<BlockNumber>
    **/
   PolkadotCorePrimitivesInboundDownwardMessage: {
     sentAt: 'u32',
     msg: 'Bytes'
   },
   /**
-   * Lookup169: polkadot_core_primitives::InboundHrmpMessage<BlockNumber>
+   * Lookup168: polkadot_core_primitives::InboundHrmpMessage<BlockNumber>
    **/
   PolkadotCorePrimitivesInboundHrmpMessage: {
     sentAt: 'u32',
     data: 'Bytes'
   },
   /**
-   * Lookup172: cumulus_pallet_parachain_system::pallet::Error<T>
+   * Lookup171: cumulus_pallet_parachain_system::pallet::Error<T>
    **/
   CumulusPalletParachainSystemError: {
     _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized']
   },
   /**
-   * Lookup174: pallet_balances::BalanceLock<Balance>
+   * Lookup173: pallet_balances::BalanceLock<Balance>
    **/
   PalletBalancesBalanceLock: {
     id: '[u8;8]',
@@ -1585,26 +1578,26 @@
     reasons: 'PalletBalancesReasons'
   },
   /**
-   * Lookup175: pallet_balances::Reasons
+   * Lookup174: pallet_balances::Reasons
    **/
   PalletBalancesReasons: {
     _enum: ['Fee', 'Misc', 'All']
   },
   /**
-   * Lookup178: pallet_balances::ReserveData<ReserveIdentifier, Balance>
+   * Lookup177: pallet_balances::ReserveData<ReserveIdentifier, Balance>
    **/
   PalletBalancesReserveData: {
     id: '[u8;16]',
     amount: 'u128'
   },
   /**
-   * Lookup180: pallet_balances::Releases
+   * Lookup179: pallet_balances::Releases
    **/
   PalletBalancesReleases: {
     _enum: ['V1_0_0', 'V2_0_0']
   },
   /**
-   * Lookup181: pallet_balances::pallet::Call<T, I>
+   * Lookup180: pallet_balances::pallet::Call<T, I>
    **/
   PalletBalancesCall: {
     _enum: {
@@ -1637,13 +1630,13 @@
     }
   },
   /**
-   * Lookup184: pallet_balances::pallet::Error<T, I>
+   * Lookup183: pallet_balances::pallet::Error<T, I>
    **/
   PalletBalancesError: {
     _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves']
   },
   /**
-   * Lookup186: pallet_timestamp::pallet::Call<T>
+   * Lookup185: pallet_timestamp::pallet::Call<T>
    **/
   PalletTimestampCall: {
     _enum: {
@@ -1653,13 +1646,13 @@
     }
   },
   /**
-   * Lookup188: pallet_transaction_payment::Releases
+   * Lookup187: pallet_transaction_payment::Releases
    **/
   PalletTransactionPaymentReleases: {
     _enum: ['V1Ancient', 'V2']
   },
   /**
-   * Lookup189: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>
+   * Lookup188: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>
    **/
   PalletTreasuryProposal: {
     proposer: 'AccountId32',
@@ -1668,7 +1661,7 @@
     bond: 'u128'
   },
   /**
-   * Lookup192: pallet_treasury::pallet::Call<T, I>
+   * Lookup191: pallet_treasury::pallet::Call<T, I>
    **/
   PalletTreasuryCall: {
     _enum: {
@@ -1692,17 +1685,17 @@
     }
   },
   /**
-   * Lookup195: frame_support::PalletId
+   * Lookup194: frame_support::PalletId
    **/
   FrameSupportPalletId: '[u8;8]',
   /**
-   * Lookup196: pallet_treasury::pallet::Error<T, I>
+   * Lookup195: pallet_treasury::pallet::Error<T, I>
    **/
   PalletTreasuryError: {
     _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'InsufficientPermission', 'ProposalNotApproved']
   },
   /**
-   * Lookup197: pallet_sudo::pallet::Call<T>
+   * Lookup196: pallet_sudo::pallet::Call<T>
    **/
   PalletSudoCall: {
     _enum: {
@@ -1726,7 +1719,7 @@
     }
   },
   /**
-   * Lookup199: orml_vesting::module::Call<T>
+   * Lookup198: orml_vesting::module::Call<T>
    **/
   OrmlVestingModuleCall: {
     _enum: {
@@ -1745,7 +1738,7 @@
     }
   },
   /**
-   * Lookup201: orml_xtokens::module::Call<T>
+   * Lookup200: orml_xtokens::module::Call<T>
    **/
   OrmlXtokensModuleCall: {
     _enum: {
@@ -1788,7 +1781,7 @@
     }
   },
   /**
-   * Lookup202: xcm::VersionedMultiAsset
+   * Lookup201: xcm::VersionedMultiAsset
    **/
   XcmVersionedMultiAsset: {
     _enum: {
@@ -1797,7 +1790,7 @@
     }
   },
   /**
-   * Lookup205: orml_tokens::module::Call<T>
+   * Lookup204: orml_tokens::module::Call<T>
    **/
   OrmlTokensModuleCall: {
     _enum: {
@@ -1831,7 +1824,7 @@
     }
   },
   /**
-   * Lookup206: cumulus_pallet_xcmp_queue::pallet::Call<T>
+   * Lookup205: cumulus_pallet_xcmp_queue::pallet::Call<T>
    **/
   CumulusPalletXcmpQueueCall: {
     _enum: {
@@ -1880,7 +1873,7 @@
     }
   },
   /**
-   * Lookup207: pallet_xcm::pallet::Call<T>
+   * Lookup206: pallet_xcm::pallet::Call<T>
    **/
   PalletXcmCall: {
     _enum: {
@@ -1934,7 +1927,7 @@
     }
   },
   /**
-   * Lookup208: xcm::VersionedXcm<RuntimeCall>
+   * Lookup207: xcm::VersionedXcm<RuntimeCall>
    **/
   XcmVersionedXcm: {
     _enum: {
@@ -1944,7 +1937,7 @@
     }
   },
   /**
-   * Lookup209: xcm::v0::Xcm<RuntimeCall>
+   * Lookup208: xcm::v0::Xcm<RuntimeCall>
    **/
   XcmV0Xcm: {
     _enum: {
@@ -1998,7 +1991,7 @@
     }
   },
   /**
-   * Lookup211: xcm::v0::order::Order<RuntimeCall>
+   * Lookup210: xcm::v0::order::Order<RuntimeCall>
    **/
   XcmV0Order: {
     _enum: {
@@ -2041,7 +2034,7 @@
     }
   },
   /**
-   * Lookup213: xcm::v0::Response
+   * Lookup212: xcm::v0::Response
    **/
   XcmV0Response: {
     _enum: {
@@ -2049,7 +2042,7 @@
     }
   },
   /**
-   * Lookup214: xcm::v1::Xcm<RuntimeCall>
+   * Lookup213: xcm::v1::Xcm<RuntimeCall>
    **/
   XcmV1Xcm: {
     _enum: {
@@ -2108,7 +2101,7 @@
     }
   },
   /**
-   * Lookup216: xcm::v1::order::Order<RuntimeCall>
+   * Lookup215: xcm::v1::order::Order<RuntimeCall>
    **/
   XcmV1Order: {
     _enum: {
@@ -2153,7 +2146,7 @@
     }
   },
   /**
-   * Lookup218: xcm::v1::Response
+   * Lookup217: xcm::v1::Response
    **/
   XcmV1Response: {
     _enum: {
@@ -2162,11 +2155,11 @@
     }
   },
   /**
-   * Lookup232: cumulus_pallet_xcm::pallet::Call<T>
+   * Lookup231: cumulus_pallet_xcm::pallet::Call<T>
    **/
   CumulusPalletXcmCall: 'Null',
   /**
-   * Lookup233: cumulus_pallet_dmp_queue::pallet::Call<T>
+   * Lookup232: cumulus_pallet_dmp_queue::pallet::Call<T>
    **/
   CumulusPalletDmpQueueCall: {
     _enum: {
@@ -2177,7 +2170,7 @@
     }
   },
   /**
-   * Lookup234: pallet_inflation::pallet::Call<T>
+   * Lookup233: pallet_inflation::pallet::Call<T>
    **/
   PalletInflationCall: {
     _enum: {
@@ -2187,7 +2180,7 @@
     }
   },
   /**
-   * Lookup235: pallet_unique::Call<T>
+   * Lookup234: pallet_unique::Call<T>
    **/
   PalletUniqueCall: {
     _enum: {
@@ -2324,7 +2317,7 @@
     }
   },
   /**
-   * Lookup240: up_data_structs::CollectionMode
+   * Lookup239: up_data_structs::CollectionMode
    **/
   UpDataStructsCollectionMode: {
     _enum: {
@@ -2334,7 +2327,7 @@
     }
   },
   /**
-   * Lookup241: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>
+   * Lookup240: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>
    **/
   UpDataStructsCreateCollectionData: {
     mode: 'UpDataStructsCollectionMode',
@@ -2349,13 +2342,13 @@
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup243: up_data_structs::AccessMode
+   * Lookup242: up_data_structs::AccessMode
    **/
   UpDataStructsAccessMode: {
     _enum: ['Normal', 'AllowList']
   },
   /**
-   * Lookup245: up_data_structs::CollectionLimits
+   * Lookup244: up_data_structs::CollectionLimits
    **/
   UpDataStructsCollectionLimits: {
     accountTokenOwnershipLimit: 'Option<u32>',
@@ -2369,7 +2362,7 @@
     transfersEnabled: 'Option<bool>'
   },
   /**
-   * Lookup247: up_data_structs::SponsoringRateLimit
+   * Lookup246: up_data_structs::SponsoringRateLimit
    **/
   UpDataStructsSponsoringRateLimit: {
     _enum: {
@@ -2378,7 +2371,7 @@
     }
   },
   /**
-   * Lookup250: up_data_structs::CollectionPermissions
+   * Lookup249: up_data_structs::CollectionPermissions
    **/
   UpDataStructsCollectionPermissions: {
     access: 'Option<UpDataStructsAccessMode>',
@@ -2386,7 +2379,7 @@
     nesting: 'Option<UpDataStructsNestingPermissions>'
   },
   /**
-   * Lookup252: up_data_structs::NestingPermissions
+   * Lookup251: up_data_structs::NestingPermissions
    **/
   UpDataStructsNestingPermissions: {
     tokenOwner: 'bool',
@@ -2394,18 +2387,18 @@
     restricted: 'Option<UpDataStructsOwnerRestrictedSet>'
   },
   /**
-   * Lookup254: up_data_structs::OwnerRestrictedSet
+   * Lookup253: up_data_structs::OwnerRestrictedSet
    **/
   UpDataStructsOwnerRestrictedSet: 'BTreeSet<u32>',
   /**
-   * Lookup259: up_data_structs::PropertyKeyPermission
+   * Lookup258: up_data_structs::PropertyKeyPermission
    **/
   UpDataStructsPropertyKeyPermission: {
     key: 'Bytes',
     permission: 'UpDataStructsPropertyPermission'
   },
   /**
-   * Lookup260: up_data_structs::PropertyPermission
+   * Lookup259: up_data_structs::PropertyPermission
    **/
   UpDataStructsPropertyPermission: {
     mutable: 'bool',
@@ -2413,14 +2406,14 @@
     tokenOwner: 'bool'
   },
   /**
-   * Lookup263: up_data_structs::Property
+   * Lookup262: up_data_structs::Property
    **/
   UpDataStructsProperty: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup266: up_data_structs::CreateItemData
+   * Lookup265: up_data_structs::CreateItemData
    **/
   UpDataStructsCreateItemData: {
     _enum: {
@@ -2430,26 +2423,26 @@
     }
   },
   /**
-   * Lookup267: up_data_structs::CreateNftData
+   * Lookup266: up_data_structs::CreateNftData
    **/
   UpDataStructsCreateNftData: {
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup268: up_data_structs::CreateFungibleData
+   * Lookup267: up_data_structs::CreateFungibleData
    **/
   UpDataStructsCreateFungibleData: {
     value: 'u128'
   },
   /**
-   * Lookup269: up_data_structs::CreateReFungibleData
+   * Lookup268: up_data_structs::CreateReFungibleData
    **/
   UpDataStructsCreateReFungibleData: {
     pieces: 'u128',
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup272: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup271: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateItemExData: {
     _enum: {
@@ -2460,14 +2453,14 @@
     }
   },
   /**
-   * Lookup274: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup273: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateNftExData: {
     properties: 'Vec<UpDataStructsProperty>',
     owner: 'PalletEvmAccountBasicCrossAccountIdRepr'
   },
   /**
-   * Lookup281: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup280: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateRefungibleExSingleOwner: {
     user: 'PalletEvmAccountBasicCrossAccountIdRepr',
@@ -2475,14 +2468,14 @@
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup283: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup282: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsCreateRefungibleExMultipleOwners: {
     users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',
     properties: 'Vec<UpDataStructsProperty>'
   },
   /**
-   * Lookup284: pallet_unique_scheduler_v2::pallet::Call<T>
+   * Lookup283: pallet_unique_scheduler_v2::pallet::Call<T>
    **/
   PalletUniqueSchedulerV2Call: {
     _enum: {
@@ -2526,7 +2519,7 @@
     }
   },
   /**
-   * Lookup287: pallet_configuration::pallet::Call<T>
+   * Lookup286: pallet_configuration::pallet::Call<T>
    **/
   PalletConfigurationCall: {
     _enum: {
@@ -2539,15 +2532,15 @@
     }
   },
   /**
-   * Lookup289: pallet_template_transaction_payment::Call<T>
+   * Lookup288: pallet_template_transaction_payment::Call<T>
    **/
   PalletTemplateTransactionPaymentCall: 'Null',
   /**
-   * Lookup290: pallet_structure::pallet::Call<T>
+   * Lookup289: pallet_structure::pallet::Call<T>
    **/
   PalletStructureCall: 'Null',
   /**
-   * Lookup291: pallet_rmrk_core::pallet::Call<T>
+   * Lookup290: pallet_rmrk_core::pallet::Call<T>
    **/
   PalletRmrkCoreCall: {
     _enum: {
@@ -2638,7 +2631,7 @@
     }
   },
   /**
-   * Lookup297: rmrk_traits::resource::ResourceTypes<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup296: rmrk_traits::resource::ResourceTypes<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceResourceTypes: {
     _enum: {
@@ -2648,7 +2641,7 @@
     }
   },
   /**
-   * Lookup299: rmrk_traits::resource::BasicResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup298: rmrk_traits::resource::BasicResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceBasicResource: {
     src: 'Option<Bytes>',
@@ -2657,7 +2650,7 @@
     thumb: 'Option<Bytes>'
   },
   /**
-   * Lookup301: rmrk_traits::resource::ComposableResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup300: rmrk_traits::resource::ComposableResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceComposableResource: {
     parts: 'Vec<u32>',
@@ -2668,7 +2661,7 @@
     thumb: 'Option<Bytes>'
   },
   /**
-   * Lookup302: rmrk_traits::resource::SlotResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup301: rmrk_traits::resource::SlotResource<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceSlotResource: {
     base: 'u32',
@@ -2679,7 +2672,7 @@
     thumb: 'Option<Bytes>'
   },
   /**
-   * Lookup305: pallet_rmrk_equip::pallet::Call<T>
+   * Lookup304: pallet_rmrk_equip::pallet::Call<T>
    **/
   PalletRmrkEquipCall: {
     _enum: {
@@ -2700,7 +2693,7 @@
     }
   },
   /**
-   * Lookup308: rmrk_traits::part::PartType<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup307: rmrk_traits::part::PartType<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartPartType: {
     _enum: {
@@ -2709,7 +2702,7 @@
     }
   },
   /**
-   * Lookup310: rmrk_traits::part::FixedPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup309: rmrk_traits::part::FixedPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartFixedPart: {
     id: 'u32',
@@ -2717,7 +2710,7 @@
     src: 'Bytes'
   },
   /**
-   * Lookup311: rmrk_traits::part::SlotPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup310: rmrk_traits::part::SlotPart<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartSlotPart: {
     id: 'u32',
@@ -2726,7 +2719,7 @@
     z: 'u32'
   },
   /**
-   * Lookup312: rmrk_traits::part::EquippableList<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup311: rmrk_traits::part::EquippableList<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPartEquippableList: {
     _enum: {
@@ -2736,7 +2729,7 @@
     }
   },
   /**
-   * Lookup314: rmrk_traits::theme::Theme<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>, S>>
+   * Lookup313: rmrk_traits::theme::Theme<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>, S>>
    **/
   RmrkTraitsTheme: {
     name: 'Bytes',
@@ -2744,14 +2737,14 @@
     inherit: 'bool'
   },
   /**
-   * Lookup316: rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup315: rmrk_traits::theme::ThemeProperty<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsThemeThemeProperty: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup318: pallet_app_promotion::pallet::Call<T>
+   * Lookup317: pallet_app_promotion::pallet::Call<T>
    **/
   PalletAppPromotionCall: {
     _enum: {
@@ -2780,7 +2773,7 @@
     }
   },
   /**
-   * Lookup319: pallet_foreign_assets::module::Call<T>
+   * Lookup318: pallet_foreign_assets::module::Call<T>
    **/
   PalletForeignAssetsModuleCall: {
     _enum: {
@@ -2797,7 +2790,7 @@
     }
   },
   /**
-   * Lookup320: pallet_evm::pallet::Call<T>
+   * Lookup319: pallet_evm::pallet::Call<T>
    **/
   PalletEvmCall: {
     _enum: {
@@ -2840,7 +2833,7 @@
     }
   },
   /**
-   * Lookup326: pallet_ethereum::pallet::Call<T>
+   * Lookup325: pallet_ethereum::pallet::Call<T>
    **/
   PalletEthereumCall: {
     _enum: {
@@ -2850,7 +2843,7 @@
     }
   },
   /**
-   * Lookup327: ethereum::transaction::TransactionV2
+   * Lookup326: ethereum::transaction::TransactionV2
    **/
   EthereumTransactionTransactionV2: {
     _enum: {
@@ -2860,7 +2853,7 @@
     }
   },
   /**
-   * Lookup328: ethereum::transaction::LegacyTransaction
+   * Lookup327: ethereum::transaction::LegacyTransaction
    **/
   EthereumTransactionLegacyTransaction: {
     nonce: 'U256',
@@ -2872,7 +2865,7 @@
     signature: 'EthereumTransactionTransactionSignature'
   },
   /**
-   * Lookup329: ethereum::transaction::TransactionAction
+   * Lookup328: ethereum::transaction::TransactionAction
    **/
   EthereumTransactionTransactionAction: {
     _enum: {
@@ -2881,7 +2874,7 @@
     }
   },
   /**
-   * Lookup330: ethereum::transaction::TransactionSignature
+   * Lookup329: ethereum::transaction::TransactionSignature
    **/
   EthereumTransactionTransactionSignature: {
     v: 'u64',
@@ -2889,7 +2882,7 @@
     s: 'H256'
   },
   /**
-   * Lookup332: ethereum::transaction::EIP2930Transaction
+   * Lookup331: ethereum::transaction::EIP2930Transaction
    **/
   EthereumTransactionEip2930Transaction: {
     chainId: 'u64',
@@ -2905,14 +2898,14 @@
     s: 'H256'
   },
   /**
-   * Lookup334: ethereum::transaction::AccessListItem
+   * Lookup333: ethereum::transaction::AccessListItem
    **/
   EthereumTransactionAccessListItem: {
     address: 'H160',
     storageKeys: 'Vec<H256>'
   },
   /**
-   * Lookup335: ethereum::transaction::EIP1559Transaction
+   * Lookup334: ethereum::transaction::EIP1559Transaction
    **/
   EthereumTransactionEip1559Transaction: {
     chainId: 'u64',
@@ -2929,7 +2922,7 @@
     s: 'H256'
   },
   /**
-   * Lookup336: pallet_evm_migration::pallet::Call<T>
+   * Lookup335: pallet_evm_migration::pallet::Call<T>
    **/
   PalletEvmMigrationCall: {
     _enum: {
@@ -2953,13 +2946,13 @@
     }
   },
   /**
-   * Lookup340: pallet_maintenance::pallet::Call<T>
+   * Lookup339: pallet_maintenance::pallet::Call<T>
    **/
   PalletMaintenanceCall: {
     _enum: ['enable', 'disable']
   },
   /**
-   * Lookup341: pallet_test_utils::pallet::Call<T>
+   * Lookup340: pallet_test_utils::pallet::Call<T>
    **/
   PalletTestUtilsCall: {
     _enum: {
@@ -2982,32 +2975,32 @@
     }
   },
   /**
-   * Lookup343: pallet_sudo::pallet::Error<T>
+   * Lookup342: pallet_sudo::pallet::Error<T>
    **/
   PalletSudoError: {
     _enum: ['RequireSudo']
   },
   /**
-   * Lookup345: orml_vesting::module::Error<T>
+   * Lookup344: orml_vesting::module::Error<T>
    **/
   OrmlVestingModuleError: {
     _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded']
   },
   /**
-   * Lookup346: orml_xtokens::module::Error<T>
+   * Lookup345: orml_xtokens::module::Error<T>
    **/
   OrmlXtokensModuleError: {
     _enum: ['AssetHasNoReserve', 'NotCrossChainTransfer', 'InvalidDest', 'NotCrossChainTransferableCurrency', 'UnweighableMessage', 'XcmExecutionFailed', 'CannotReanchor', 'InvalidAncestry', 'InvalidAsset', 'DestinationNotInvertible', 'BadVersion', 'DistinctReserveForAssetAndFee', 'ZeroFee', 'ZeroAmount', 'TooManyAssetsBeingSent', 'AssetIndexNonExistent', 'FeeNotEnough', 'NotSupportedMultiLocation', 'MinXcmFeeNotDefined']
   },
   /**
-   * Lookup349: orml_tokens::BalanceLock<Balance>
+   * Lookup348: orml_tokens::BalanceLock<Balance>
    **/
   OrmlTokensBalanceLock: {
     id: '[u8;8]',
     amount: 'u128'
   },
   /**
-   * Lookup351: orml_tokens::AccountData<Balance>
+   * Lookup350: orml_tokens::AccountData<Balance>
    **/
   OrmlTokensAccountData: {
     free: 'u128',
@@ -3015,20 +3008,20 @@
     frozen: 'u128'
   },
   /**
-   * Lookup353: orml_tokens::ReserveData<ReserveIdentifier, Balance>
+   * Lookup352: orml_tokens::ReserveData<ReserveIdentifier, Balance>
    **/
   OrmlTokensReserveData: {
     id: 'Null',
     amount: 'u128'
   },
   /**
-   * Lookup355: orml_tokens::module::Error<T>
+   * Lookup354: orml_tokens::module::Error<T>
    **/
   OrmlTokensModuleError: {
     _enum: ['BalanceTooLow', 'AmountIntoBalanceFailed', 'LiquidityRestrictions', 'MaxLocksExceeded', 'KeepAlive', 'ExistentialDeposit', 'DeadAccount', 'TooManyReserves']
   },
   /**
-   * Lookup357: cumulus_pallet_xcmp_queue::InboundChannelDetails
+   * Lookup356: cumulus_pallet_xcmp_queue::InboundChannelDetails
    **/
   CumulusPalletXcmpQueueInboundChannelDetails: {
     sender: 'u32',
@@ -3036,19 +3029,19 @@
     messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>'
   },
   /**
-   * Lookup358: cumulus_pallet_xcmp_queue::InboundState
+   * Lookup357: cumulus_pallet_xcmp_queue::InboundState
    **/
   CumulusPalletXcmpQueueInboundState: {
     _enum: ['Ok', 'Suspended']
   },
   /**
-   * Lookup361: polkadot_parachain::primitives::XcmpMessageFormat
+   * Lookup360: polkadot_parachain::primitives::XcmpMessageFormat
    **/
   PolkadotParachainPrimitivesXcmpMessageFormat: {
     _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals']
   },
   /**
-   * Lookup364: cumulus_pallet_xcmp_queue::OutboundChannelDetails
+   * Lookup363: cumulus_pallet_xcmp_queue::OutboundChannelDetails
    **/
   CumulusPalletXcmpQueueOutboundChannelDetails: {
     recipient: 'u32',
@@ -3058,13 +3051,13 @@
     lastIndex: 'u16'
   },
   /**
-   * Lookup365: cumulus_pallet_xcmp_queue::OutboundState
+   * Lookup364: cumulus_pallet_xcmp_queue::OutboundState
    **/
   CumulusPalletXcmpQueueOutboundState: {
     _enum: ['Ok', 'Suspended']
   },
   /**
-   * Lookup367: cumulus_pallet_xcmp_queue::QueueConfigData
+   * Lookup366: cumulus_pallet_xcmp_queue::QueueConfigData
    **/
   CumulusPalletXcmpQueueQueueConfigData: {
     suspendThreshold: 'u32',
@@ -3075,29 +3068,29 @@
     xcmpMaxIndividualWeight: 'SpWeightsWeightV2Weight'
   },
   /**
-   * Lookup369: cumulus_pallet_xcmp_queue::pallet::Error<T>
+   * Lookup368: cumulus_pallet_xcmp_queue::pallet::Error<T>
    **/
   CumulusPalletXcmpQueueError: {
     _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit']
   },
   /**
-   * Lookup370: pallet_xcm::pallet::Error<T>
+   * Lookup369: pallet_xcm::pallet::Error<T>
    **/
   PalletXcmError: {
     _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed']
   },
   /**
-   * Lookup371: cumulus_pallet_xcm::pallet::Error<T>
+   * Lookup370: cumulus_pallet_xcm::pallet::Error<T>
    **/
   CumulusPalletXcmError: 'Null',
   /**
-   * Lookup372: cumulus_pallet_dmp_queue::ConfigData
+   * Lookup371: cumulus_pallet_dmp_queue::ConfigData
    **/
   CumulusPalletDmpQueueConfigData: {
     maxIndividual: 'SpWeightsWeightV2Weight'
   },
   /**
-   * Lookup373: cumulus_pallet_dmp_queue::PageIndexData
+   * Lookup372: cumulus_pallet_dmp_queue::PageIndexData
    **/
   CumulusPalletDmpQueuePageIndexData: {
     beginUsed: 'u32',
@@ -3105,26 +3098,26 @@
     overweightCount: 'u64'
   },
   /**
-   * Lookup376: cumulus_pallet_dmp_queue::pallet::Error<T>
+   * Lookup375: cumulus_pallet_dmp_queue::pallet::Error<T>
    **/
   CumulusPalletDmpQueueError: {
     _enum: ['Unknown', 'OverLimit']
   },
   /**
-   * Lookup380: pallet_unique::Error<T>
+   * Lookup379: pallet_unique::Error<T>
    **/
   PalletUniqueError: {
-    _enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection']
+    _enum: ['CollectionDecimalPointLimitExceeded', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection']
   },
   /**
-   * Lookup381: pallet_unique_scheduler_v2::BlockAgenda<T>
+   * Lookup380: pallet_unique_scheduler_v2::BlockAgenda<T>
    **/
   PalletUniqueSchedulerV2BlockAgenda: {
     agenda: 'Vec<Option<PalletUniqueSchedulerV2Scheduled>>',
     freePlaces: 'u32'
   },
   /**
-   * Lookup384: pallet_unique_scheduler_v2::Scheduled<Name, pallet_unique_scheduler_v2::ScheduledCall<T>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>
+   * Lookup383: pallet_unique_scheduler_v2::Scheduled<Name, pallet_unique_scheduler_v2::ScheduledCall<T>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>
    **/
   PalletUniqueSchedulerV2Scheduled: {
     maybeId: 'Option<[u8;32]>',
@@ -3134,7 +3127,7 @@
     origin: 'OpalRuntimeOriginCaller'
   },
   /**
-   * Lookup385: pallet_unique_scheduler_v2::ScheduledCall<T>
+   * Lookup384: pallet_unique_scheduler_v2::ScheduledCall<T>
    **/
   PalletUniqueSchedulerV2ScheduledCall: {
     _enum: {
@@ -3149,7 +3142,7 @@
     }
   },
   /**
-   * Lookup387: opal_runtime::OriginCaller
+   * Lookup386: opal_runtime::OriginCaller
    **/
   OpalRuntimeOriginCaller: {
     _enum: {
@@ -3258,7 +3251,7 @@
     }
   },
   /**
-   * Lookup388: frame_support::dispatch::RawOrigin<sp_core::crypto::AccountId32>
+   * Lookup387: frame_support::dispatch::RawOrigin<sp_core::crypto::AccountId32>
    **/
   FrameSupportDispatchRawOrigin: {
     _enum: {
@@ -3268,7 +3261,7 @@
     }
   },
   /**
-   * Lookup389: pallet_xcm::pallet::Origin
+   * Lookup388: pallet_xcm::pallet::Origin
    **/
   PalletXcmOrigin: {
     _enum: {
@@ -3277,7 +3270,7 @@
     }
   },
   /**
-   * Lookup390: cumulus_pallet_xcm::pallet::Origin
+   * Lookup389: cumulus_pallet_xcm::pallet::Origin
    **/
   CumulusPalletXcmOrigin: {
     _enum: {
@@ -3286,7 +3279,7 @@
     }
   },
   /**
-   * Lookup391: pallet_ethereum::RawOrigin
+   * Lookup390: pallet_ethereum::RawOrigin
    **/
   PalletEthereumRawOrigin: {
     _enum: {
@@ -3294,17 +3287,17 @@
     }
   },
   /**
-   * Lookup392: sp_core::Void
+   * Lookup391: sp_core::Void
    **/
   SpCoreVoid: 'Null',
   /**
-   * Lookup394: pallet_unique_scheduler_v2::pallet::Error<T>
+   * Lookup393: pallet_unique_scheduler_v2::pallet::Error<T>
    **/
   PalletUniqueSchedulerV2Error: {
     _enum: ['FailedToSchedule', 'AgendaIsExhausted', 'ScheduledCallCorrupted', 'PreimageNotFound', 'TooBigScheduledCall', 'NotFound', 'TargetBlockNumberInPast', 'Named']
   },
   /**
-   * Lookup395: up_data_structs::Collection<sp_core::crypto::AccountId32>
+   * Lookup394: up_data_structs::Collection<sp_core::crypto::AccountId32>
    **/
   UpDataStructsCollection: {
     owner: 'AccountId32',
@@ -3318,7 +3311,7 @@
     flags: '[u8;1]'
   },
   /**
-   * Lookup396: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>
+   * Lookup395: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>
    **/
   UpDataStructsSponsorshipStateAccountId32: {
     _enum: {
@@ -3328,7 +3321,7 @@
     }
   },
   /**
-   * Lookup398: up_data_structs::Properties
+   * Lookup397: up_data_structs::Properties
    **/
   UpDataStructsProperties: {
     map: 'UpDataStructsPropertiesMapBoundedVec',
@@ -3336,15 +3329,15 @@
     spaceLimit: 'u32'
   },
   /**
-   * Lookup399: up_data_structs::PropertiesMap<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup398: up_data_structs::PropertiesMap<sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   UpDataStructsPropertiesMapBoundedVec: 'BTreeMap<Bytes, Bytes>',
   /**
-   * Lookup404: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>
+   * Lookup403: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>
    **/
   UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap<Bytes, UpDataStructsPropertyPermission>',
   /**
-   * Lookup411: up_data_structs::CollectionStats
+   * Lookup410: up_data_structs::CollectionStats
    **/
   UpDataStructsCollectionStats: {
     created: 'u32',
@@ -3352,18 +3345,18 @@
     alive: 'u32'
   },
   /**
-   * Lookup412: up_data_structs::TokenChild
+   * Lookup411: up_data_structs::TokenChild
    **/
   UpDataStructsTokenChild: {
     token: 'u32',
     collection: 'u32'
   },
   /**
-   * Lookup413: PhantomType::up_data_structs<T>
+   * Lookup412: PhantomType::up_data_structs<T>
    **/
   PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild);0]',
   /**
-   * Lookup415: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup414: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsTokenData: {
     properties: 'Vec<UpDataStructsProperty>',
@@ -3371,7 +3364,7 @@
     pieces: 'u128'
   },
   /**
-   * Lookup417: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>
+   * Lookup416: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>
    **/
   UpDataStructsRpcCollection: {
     owner: 'AccountId32',
@@ -3388,14 +3381,14 @@
     flags: 'UpDataStructsRpcCollectionFlags'
   },
   /**
-   * Lookup418: up_data_structs::RpcCollectionFlags
+   * Lookup417: up_data_structs::RpcCollectionFlags
    **/
   UpDataStructsRpcCollectionFlags: {
     foreign: 'bool',
     erc721metadata: 'bool'
   },
   /**
-   * Lookup419: rmrk_traits::collection::CollectionInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>
+   * Lookup418: rmrk_traits::collection::CollectionInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>
    **/
   RmrkTraitsCollectionCollectionInfo: {
     issuer: 'AccountId32',
@@ -3405,7 +3398,7 @@
     nftsCount: 'u32'
   },
   /**
-   * Lookup420: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup419: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsNftNftInfo: {
     owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',
@@ -3415,14 +3408,14 @@
     pending: 'bool'
   },
   /**
-   * Lookup422: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>
+   * Lookup421: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>
    **/
   RmrkTraitsNftRoyaltyInfo: {
     recipient: 'AccountId32',
     amount: 'Permill'
   },
   /**
-   * Lookup423: rmrk_traits::resource::ResourceInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup422: rmrk_traits::resource::ResourceInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsResourceResourceInfo: {
     id: 'u32',
@@ -3431,14 +3424,14 @@
     pendingRemoval: 'bool'
   },
   /**
-   * Lookup424: rmrk_traits::property::PropertyInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup423: rmrk_traits::property::PropertyInfo<sp_core::bounded::bounded_vec::BoundedVec<T, S>, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsPropertyPropertyInfo: {
     key: 'Bytes',
     value: 'Bytes'
   },
   /**
-   * Lookup425: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
+   * Lookup424: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, sp_core::bounded::bounded_vec::BoundedVec<T, S>>
    **/
   RmrkTraitsBaseBaseInfo: {
     issuer: 'AccountId32',
@@ -3446,92 +3439,92 @@
     symbol: 'Bytes'
   },
   /**
-   * Lookup426: rmrk_traits::nft::NftChild
+   * Lookup425: rmrk_traits::nft::NftChild
    **/
   RmrkTraitsNftNftChild: {
     collectionId: 'u32',
     nftId: 'u32'
   },
   /**
-   * Lookup428: pallet_common::pallet::Error<T>
+   * Lookup427: 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', 'UserIsNotAllowedToNest', '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', 'ConfirmSponsorshipFail', 'UserIsNotCollectionAdmin']
   },
   /**
-   * Lookup430: pallet_fungible::pallet::Error<T>
+   * Lookup429: pallet_fungible::pallet::Error<T>
    **/
   PalletFungibleError: {
     _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed', 'SettingAllowanceForAllNotAllowed']
   },
   /**
-   * Lookup431: pallet_refungible::ItemData
+   * Lookup430: pallet_refungible::ItemData
    **/
   PalletRefungibleItemData: {
     constData: 'Bytes'
   },
   /**
-   * Lookup436: pallet_refungible::pallet::Error<T>
+   * Lookup435: pallet_refungible::pallet::Error<T>
    **/
   PalletRefungibleError: {
     _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed']
   },
   /**
-   * Lookup437: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup436: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   PalletNonfungibleItemData: {
     owner: 'PalletEvmAccountBasicCrossAccountIdRepr'
   },
   /**
-   * Lookup439: up_data_structs::PropertyScope
+   * Lookup438: up_data_structs::PropertyScope
    **/
   UpDataStructsPropertyScope: {
     _enum: ['None', 'Rmrk']
   },
   /**
-   * Lookup441: pallet_nonfungible::pallet::Error<T>
+   * Lookup440: pallet_nonfungible::pallet::Error<T>
    **/
   PalletNonfungibleError: {
     _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren']
   },
   /**
-   * Lookup442: pallet_structure::pallet::Error<T>
+   * Lookup441: pallet_structure::pallet::Error<T>
    **/
   PalletStructureError: {
     _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound']
   },
   /**
-   * Lookup443: pallet_rmrk_core::pallet::Error<T>
+   * Lookup442: pallet_rmrk_core::pallet::Error<T>
    **/
   PalletRmrkCoreError: {
     _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId']
   },
   /**
-   * Lookup445: pallet_rmrk_equip::pallet::Error<T>
+   * Lookup444: pallet_rmrk_equip::pallet::Error<T>
    **/
   PalletRmrkEquipError: {
     _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart']
   },
   /**
-   * Lookup451: pallet_app_promotion::pallet::Error<T>
+   * Lookup450: pallet_app_promotion::pallet::Error<T>
    **/
   PalletAppPromotionError: {
     _enum: ['AdminNotSet', 'NoPermission', 'NotSufficientFunds', 'PendingForBlockOverflow', 'SponsorNotSet', 'IncorrectLockedBalanceOperation']
   },
   /**
-   * Lookup452: pallet_foreign_assets::module::Error<T>
+   * Lookup451: pallet_foreign_assets::module::Error<T>
    **/
   PalletForeignAssetsModuleError: {
     _enum: ['BadLocation', 'MultiLocationExisted', 'AssetIdNotExists', 'AssetIdExisted']
   },
   /**
-   * Lookup454: pallet_evm::pallet::Error<T>
+   * Lookup453: pallet_evm::pallet::Error<T>
    **/
   PalletEvmError: {
     _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce', 'GasLimitTooLow', 'GasLimitTooHigh', 'Undefined', 'Reentrancy']
   },
   /**
-   * Lookup457: fp_rpc::TransactionStatus
+   * Lookup456: fp_rpc::TransactionStatus
    **/
   FpRpcTransactionStatus: {
     transactionHash: 'H256',
@@ -3543,11 +3536,11 @@
     logsBloom: 'EthbloomBloom'
   },
   /**
-   * Lookup459: ethbloom::Bloom
+   * Lookup458: ethbloom::Bloom
    **/
   EthbloomBloom: '[u8;256]',
   /**
-   * Lookup461: ethereum::receipt::ReceiptV3
+   * Lookup460: ethereum::receipt::ReceiptV3
    **/
   EthereumReceiptReceiptV3: {
     _enum: {
@@ -3557,7 +3550,7 @@
     }
   },
   /**
-   * Lookup462: ethereum::receipt::EIP658ReceiptData
+   * Lookup461: ethereum::receipt::EIP658ReceiptData
    **/
   EthereumReceiptEip658ReceiptData: {
     statusCode: 'u8',
@@ -3566,7 +3559,7 @@
     logs: 'Vec<EthereumLog>'
   },
   /**
-   * Lookup463: ethereum::block::Block<ethereum::transaction::TransactionV2>
+   * Lookup462: ethereum::block::Block<ethereum::transaction::TransactionV2>
    **/
   EthereumBlock: {
     header: 'EthereumHeader',
@@ -3574,7 +3567,7 @@
     ommers: 'Vec<EthereumHeader>'
   },
   /**
-   * Lookup464: ethereum::header::Header
+   * Lookup463: ethereum::header::Header
    **/
   EthereumHeader: {
     parentHash: 'H256',
@@ -3594,23 +3587,23 @@
     nonce: 'EthereumTypesHashH64'
   },
   /**
-   * Lookup465: ethereum_types::hash::H64
+   * Lookup464: ethereum_types::hash::H64
    **/
   EthereumTypesHashH64: '[u8;8]',
   /**
-   * Lookup470: pallet_ethereum::pallet::Error<T>
+   * Lookup469: pallet_ethereum::pallet::Error<T>
    **/
   PalletEthereumError: {
     _enum: ['InvalidSignature', 'PreLogExists']
   },
   /**
-   * Lookup471: pallet_evm_coder_substrate::pallet::Error<T>
+   * Lookup470: pallet_evm_coder_substrate::pallet::Error<T>
    **/
   PalletEvmCoderSubstrateError: {
     _enum: ['OutOfGas', 'OutOfFund']
   },
   /**
-   * Lookup472: up_data_structs::SponsorshipState<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
+   * Lookup471: up_data_structs::SponsorshipState<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>
    **/
   UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: {
     _enum: {
@@ -3620,35 +3613,35 @@
     }
   },
   /**
-   * Lookup473: pallet_evm_contract_helpers::SponsoringModeT
+   * Lookup472: pallet_evm_contract_helpers::SponsoringModeT
    **/
   PalletEvmContractHelpersSponsoringModeT: {
     _enum: ['Disabled', 'Allowlisted', 'Generous']
   },
   /**
-   * Lookup479: pallet_evm_contract_helpers::pallet::Error<T>
+   * Lookup478: pallet_evm_contract_helpers::pallet::Error<T>
    **/
   PalletEvmContractHelpersError: {
     _enum: ['NoPermission', 'NoPendingSponsor', 'TooManyMethodsHaveSponsoredLimit']
   },
   /**
-   * Lookup480: pallet_evm_migration::pallet::Error<T>
+   * Lookup479: pallet_evm_migration::pallet::Error<T>
    **/
   PalletEvmMigrationError: {
     _enum: ['AccountNotEmpty', 'AccountIsNotMigrating', 'BadEvent']
   },
   /**
-   * Lookup481: pallet_maintenance::pallet::Error<T>
+   * Lookup480: pallet_maintenance::pallet::Error<T>
    **/
   PalletMaintenanceError: 'Null',
   /**
-   * Lookup482: pallet_test_utils::pallet::Error<T>
+   * Lookup481: pallet_test_utils::pallet::Error<T>
    **/
   PalletTestUtilsError: {
     _enum: ['TestPalletDisabled', 'TriggerRollback']
   },
   /**
-   * Lookup484: sp_runtime::MultiSignature
+   * Lookup483: sp_runtime::MultiSignature
    **/
   SpRuntimeMultiSignature: {
     _enum: {
@@ -3658,51 +3651,51 @@
     }
   },
   /**
-   * Lookup485: sp_core::ed25519::Signature
+   * Lookup484: sp_core::ed25519::Signature
    **/
   SpCoreEd25519Signature: '[u8;64]',
   /**
-   * Lookup487: sp_core::sr25519::Signature
+   * Lookup486: sp_core::sr25519::Signature
    **/
   SpCoreSr25519Signature: '[u8;64]',
   /**
-   * Lookup488: sp_core::ecdsa::Signature
+   * Lookup487: sp_core::ecdsa::Signature
    **/
   SpCoreEcdsaSignature: '[u8;65]',
   /**
-   * Lookup491: frame_system::extensions::check_spec_version::CheckSpecVersion<T>
+   * Lookup490: frame_system::extensions::check_spec_version::CheckSpecVersion<T>
    **/
   FrameSystemExtensionsCheckSpecVersion: 'Null',
   /**
-   * Lookup492: frame_system::extensions::check_tx_version::CheckTxVersion<T>
+   * Lookup491: frame_system::extensions::check_tx_version::CheckTxVersion<T>
    **/
   FrameSystemExtensionsCheckTxVersion: 'Null',
   /**
-   * Lookup493: frame_system::extensions::check_genesis::CheckGenesis<T>
+   * Lookup492: frame_system::extensions::check_genesis::CheckGenesis<T>
    **/
   FrameSystemExtensionsCheckGenesis: 'Null',
   /**
-   * Lookup496: frame_system::extensions::check_nonce::CheckNonce<T>
+   * Lookup495: frame_system::extensions::check_nonce::CheckNonce<T>
    **/
   FrameSystemExtensionsCheckNonce: 'Compact<u32>',
   /**
-   * Lookup497: frame_system::extensions::check_weight::CheckWeight<T>
+   * Lookup496: frame_system::extensions::check_weight::CheckWeight<T>
    **/
   FrameSystemExtensionsCheckWeight: 'Null',
   /**
-   * Lookup498: opal_runtime::runtime_common::maintenance::CheckMaintenance
+   * Lookup497: opal_runtime::runtime_common::maintenance::CheckMaintenance
    **/
   OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance: 'Null',
   /**
-   * Lookup499: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>
+   * Lookup498: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>
    **/
   PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact<u128>',
   /**
-   * Lookup500: opal_runtime::Runtime
+   * Lookup499: opal_runtime::Runtime
    **/
   OpalRuntimeRuntime: 'Null',
   /**
-   * Lookup501: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>
+   * Lookup500: 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
@@ -5,7 +5,7 @@
 // this is required to allow for ambient/previous definitions
 import '@polkadot/types/types/registry';
 
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletEvmMigrationEvent, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerV2BlockAgenda, PalletUniqueSchedulerV2Call, PalletUniqueSchedulerV2Error, PalletUniqueSchedulerV2Event, PalletUniqueSchedulerV2Scheduled, PalletUniqueSchedulerV2ScheduledCall, 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, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, 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, FrameSupportDispatchDispatchClass, FrameSupportDispatchDispatchInfo, FrameSupportDispatchPays, FrameSupportDispatchPerDispatchClassU32, FrameSupportDispatchPerDispatchClassWeight, FrameSupportDispatchPerDispatchClassWeightsPerClass, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportTokensMiscBalanceStatus, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckTxVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensModuleCall, OrmlTokensModuleError, OrmlTokensModuleEvent, OrmlTokensReserveData, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, OrmlXtokensModuleCall, OrmlXtokensModuleError, OrmlXtokensModuleEvent, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletEvmMigrationEvent, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletForeignAssetsModuleCall, PalletForeignAssetsModuleError, PalletForeignAssetsModuleEvent, PalletForeignAssetsNativeCurrency, PalletFungibleError, PalletInflationCall, PalletMaintenanceCall, PalletMaintenanceError, PalletMaintenanceEvent, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTestUtilsCall, PalletTestUtilsError, PalletTestUtilsEvent, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueSchedulerV2BlockAgenda, PalletUniqueSchedulerV2Call, PalletUniqueSchedulerV2Error, PalletUniqueSchedulerV2Event, PalletUniqueSchedulerV2Scheduled, PalletUniqueSchedulerV2ScheduledCall, 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, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsRpcCollectionFlags, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAsset, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
 
 declare module '@polkadot/types/types/registry' {
   interface InterfaceTypes {
@@ -162,7 +162,6 @@
     PalletTreasuryProposal: PalletTreasuryProposal;
     PalletUniqueCall: PalletUniqueCall;
     PalletUniqueError: PalletUniqueError;
-    PalletUniqueRawEvent: PalletUniqueRawEvent;
     PalletUniqueSchedulerV2BlockAgenda: PalletUniqueSchedulerV2BlockAgenda;
     PalletUniqueSchedulerV2Call: PalletUniqueSchedulerV2Call;
     PalletUniqueSchedulerV2Error: PalletUniqueSchedulerV2Error;
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -1109,41 +1109,7 @@
     readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward' | 'WeightExhausted' | 'OverweightEnqueued' | 'OverweightServiced';
   }
 
-  /** @name PalletUniqueRawEvent (89) */
-  interface PalletUniqueRawEvent extends Enum {
-    readonly isCollectionSponsorRemoved: boolean;
-    readonly asCollectionSponsorRemoved: u32;
-    readonly isCollectionAdminAdded: boolean;
-    readonly asCollectionAdminAdded: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-    readonly isCollectionOwnedChanged: boolean;
-    readonly asCollectionOwnedChanged: ITuple<[u32, AccountId32]>;
-    readonly isCollectionSponsorSet: boolean;
-    readonly asCollectionSponsorSet: ITuple<[u32, AccountId32]>;
-    readonly isSponsorshipConfirmed: boolean;
-    readonly asSponsorshipConfirmed: ITuple<[u32, AccountId32]>;
-    readonly isCollectionAdminRemoved: boolean;
-    readonly asCollectionAdminRemoved: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-    readonly isAllowListAddressRemoved: boolean;
-    readonly asAllowListAddressRemoved: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-    readonly isAllowListAddressAdded: boolean;
-    readonly asAllowListAddressAdded: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-    readonly isCollectionLimitSet: boolean;
-    readonly asCollectionLimitSet: u32;
-    readonly isCollectionPermissionSet: boolean;
-    readonly asCollectionPermissionSet: u32;
-    readonly type: 'CollectionSponsorRemoved' | 'CollectionAdminAdded' | 'CollectionOwnedChanged' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionAdminRemoved' | 'AllowListAddressRemoved' | 'AllowListAddressAdded' | 'CollectionLimitSet' | 'CollectionPermissionSet';
-  }
-
-  /** @name PalletEvmAccountBasicCrossAccountIdRepr (90) */
-  interface PalletEvmAccountBasicCrossAccountIdRepr extends Enum {
-    readonly isSubstrate: boolean;
-    readonly asSubstrate: AccountId32;
-    readonly isEthereum: boolean;
-    readonly asEthereum: H160;
-    readonly type: 'Substrate' | 'Ethereum';
-  }
-
-  /** @name PalletUniqueSchedulerV2Event (93) */
+  /** @name PalletUniqueSchedulerV2Event (89) */
   interface PalletUniqueSchedulerV2Event extends Enum {
     readonly isScheduled: boolean;
     readonly asScheduled: {
@@ -1179,7 +1145,7 @@
     readonly type: 'Scheduled' | 'Canceled' | 'Dispatched' | 'PriorityChanged' | 'CallUnavailable' | 'PermanentlyOverweight';
   }
 
-  /** @name PalletCommonEvent (96) */
+  /** @name PalletCommonEvent (92) */
   interface PalletCommonEvent extends Enum {
     readonly isCollectionCreated: boolean;
     readonly asCollectionCreated: ITuple<[u32, u8, AccountId32]>;
@@ -1205,17 +1171,46 @@
     readonly asTokenPropertyDeleted: ITuple<[u32, u32, Bytes]>;
     readonly isPropertyPermissionSet: boolean;
     readonly asPropertyPermissionSet: ITuple<[u32, Bytes]>;
-    readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'ApprovedForAll' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet';
+    readonly isAllowListAddressAdded: boolean;
+    readonly asAllowListAddressAdded: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+    readonly isAllowListAddressRemoved: boolean;
+    readonly asAllowListAddressRemoved: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+    readonly isCollectionAdminAdded: boolean;
+    readonly asCollectionAdminAdded: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+    readonly isCollectionAdminRemoved: boolean;
+    readonly asCollectionAdminRemoved: ITuple<[u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
+    readonly isCollectionLimitSet: boolean;
+    readonly asCollectionLimitSet: u32;
+    readonly isCollectionOwnerChanged: boolean;
+    readonly asCollectionOwnerChanged: ITuple<[u32, AccountId32]>;
+    readonly isCollectionPermissionSet: boolean;
+    readonly asCollectionPermissionSet: u32;
+    readonly isCollectionSponsorSet: boolean;
+    readonly asCollectionSponsorSet: ITuple<[u32, AccountId32]>;
+    readonly isSponsorshipConfirmed: boolean;
+    readonly asSponsorshipConfirmed: ITuple<[u32, AccountId32]>;
+    readonly isCollectionSponsorRemoved: boolean;
+    readonly asCollectionSponsorRemoved: u32;
+    readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'ApprovedForAll' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet' | 'AllowListAddressAdded' | 'AllowListAddressRemoved' | 'CollectionAdminAdded' | 'CollectionAdminRemoved' | 'CollectionLimitSet' | 'CollectionOwnerChanged' | 'CollectionPermissionSet' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionSponsorRemoved';
+  }
+
+  /** @name PalletEvmAccountBasicCrossAccountIdRepr (95) */
+  interface PalletEvmAccountBasicCrossAccountIdRepr extends Enum {
+    readonly isSubstrate: boolean;
+    readonly asSubstrate: AccountId32;
+    readonly isEthereum: boolean;
+    readonly asEthereum: H160;
+    readonly type: 'Substrate' | 'Ethereum';
   }
 
-  /** @name PalletStructureEvent (100) */
+  /** @name PalletStructureEvent (99) */
   interface PalletStructureEvent extends Enum {
     readonly isExecuted: boolean;
     readonly asExecuted: Result<Null, SpRuntimeDispatchError>;
     readonly type: 'Executed';
   }
 
-  /** @name PalletRmrkCoreEvent (101) */
+  /** @name PalletRmrkCoreEvent (100) */
   interface PalletRmrkCoreEvent extends Enum {
     readonly isCollectionCreated: boolean;
     readonly asCollectionCreated: {
@@ -1305,7 +1300,7 @@
     readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'IssuerChanged' | 'CollectionLocked' | 'NftMinted' | 'NftBurned' | 'NftSent' | 'NftAccepted' | 'NftRejected' | 'PropertySet' | 'ResourceAdded' | 'ResourceRemoval' | 'ResourceAccepted' | 'ResourceRemovalAccepted' | 'PrioritySet';
   }
 
-  /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (102) */
+  /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (101) */
   interface RmrkTraitsNftAccountIdOrCollectionNftTuple extends Enum {
     readonly isAccountId: boolean;
     readonly asAccountId: AccountId32;
@@ -1314,7 +1309,7 @@
     readonly type: 'AccountId' | 'CollectionAndNftTuple';
   }
 
-  /** @name PalletRmrkEquipEvent (106) */
+  /** @name PalletRmrkEquipEvent (105) */
   interface PalletRmrkEquipEvent extends Enum {
     readonly isBaseCreated: boolean;
     readonly asBaseCreated: {
@@ -1329,7 +1324,7 @@
     readonly type: 'BaseCreated' | 'EquippablesUpdated';
   }
 
-  /** @name PalletAppPromotionEvent (107) */
+  /** @name PalletAppPromotionEvent (106) */
   interface PalletAppPromotionEvent extends Enum {
     readonly isStakingRecalculation: boolean;
     readonly asStakingRecalculation: ITuple<[AccountId32, u128, u128]>;
@@ -1342,7 +1337,7 @@
     readonly type: 'StakingRecalculation' | 'Stake' | 'Unstake' | 'SetAdmin';
   }
 
-  /** @name PalletForeignAssetsModuleEvent (108) */
+  /** @name PalletForeignAssetsModuleEvent (107) */
   interface PalletForeignAssetsModuleEvent extends Enum {
     readonly isForeignAssetRegistered: boolean;
     readonly asForeignAssetRegistered: {
@@ -1369,7 +1364,7 @@
     readonly type: 'ForeignAssetRegistered' | 'ForeignAssetUpdated' | 'AssetRegistered' | 'AssetUpdated';
   }
 
-  /** @name PalletForeignAssetsModuleAssetMetadata (109) */
+  /** @name PalletForeignAssetsModuleAssetMetadata (108) */
   interface PalletForeignAssetsModuleAssetMetadata extends Struct {
     readonly name: Bytes;
     readonly symbol: Bytes;
@@ -1377,7 +1372,7 @@
     readonly minimalBalance: u128;
   }
 
-  /** @name PalletEvmEvent (110) */
+  /** @name PalletEvmEvent (109) */
   interface PalletEvmEvent extends Enum {
     readonly isLog: boolean;
     readonly asLog: {
@@ -1402,14 +1397,14 @@
     readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed';
   }
 
-  /** @name EthereumLog (111) */
+  /** @name EthereumLog (110) */
   interface EthereumLog extends Struct {
     readonly address: H160;
     readonly topics: Vec<H256>;
     readonly data: Bytes;
   }
 
-  /** @name PalletEthereumEvent (113) */
+  /** @name PalletEthereumEvent (112) */
   interface PalletEthereumEvent extends Enum {
     readonly isExecuted: boolean;
     readonly asExecuted: {
@@ -1421,7 +1416,7 @@
     readonly type: 'Executed';
   }
 
-  /** @name EvmCoreErrorExitReason (114) */
+  /** @name EvmCoreErrorExitReason (113) */
   interface EvmCoreErrorExitReason extends Enum {
     readonly isSucceed: boolean;
     readonly asSucceed: EvmCoreErrorExitSucceed;
@@ -1434,7 +1429,7 @@
     readonly type: 'Succeed' | 'Error' | 'Revert' | 'Fatal';
   }
 
-  /** @name EvmCoreErrorExitSucceed (115) */
+  /** @name EvmCoreErrorExitSucceed (114) */
   interface EvmCoreErrorExitSucceed extends Enum {
     readonly isStopped: boolean;
     readonly isReturned: boolean;
@@ -1442,7 +1437,7 @@
     readonly type: 'Stopped' | 'Returned' | 'Suicided';
   }
 
-  /** @name EvmCoreErrorExitError (116) */
+  /** @name EvmCoreErrorExitError (115) */
   interface EvmCoreErrorExitError extends Enum {
     readonly isStackUnderflow: boolean;
     readonly isStackOverflow: boolean;
@@ -1463,13 +1458,13 @@
     readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode';
   }
 
-  /** @name EvmCoreErrorExitRevert (119) */
+  /** @name EvmCoreErrorExitRevert (118) */
   interface EvmCoreErrorExitRevert extends Enum {
     readonly isReverted: boolean;
     readonly type: 'Reverted';
   }
 
-  /** @name EvmCoreErrorExitFatal (120) */
+  /** @name EvmCoreErrorExitFatal (119) */
   interface EvmCoreErrorExitFatal extends Enum {
     readonly isNotSupported: boolean;
     readonly isUnhandledInterrupt: boolean;
@@ -1480,7 +1475,7 @@
     readonly type: 'NotSupported' | 'UnhandledInterrupt' | 'CallErrorAsFatal' | 'Other';
   }
 
-  /** @name PalletEvmContractHelpersEvent (121) */
+  /** @name PalletEvmContractHelpersEvent (120) */
   interface PalletEvmContractHelpersEvent extends Enum {
     readonly isContractSponsorSet: boolean;
     readonly asContractSponsorSet: ITuple<[H160, AccountId32]>;
@@ -1491,20 +1486,20 @@
     readonly type: 'ContractSponsorSet' | 'ContractSponsorshipConfirmed' | 'ContractSponsorRemoved';
   }
 
-  /** @name PalletEvmMigrationEvent (122) */
+  /** @name PalletEvmMigrationEvent (121) */
   interface PalletEvmMigrationEvent extends Enum {
     readonly isTestEvent: boolean;
     readonly type: 'TestEvent';
   }
 
-  /** @name PalletMaintenanceEvent (123) */
+  /** @name PalletMaintenanceEvent (122) */
   interface PalletMaintenanceEvent extends Enum {
     readonly isMaintenanceEnabled: boolean;
     readonly isMaintenanceDisabled: boolean;
     readonly type: 'MaintenanceEnabled' | 'MaintenanceDisabled';
   }
 
-  /** @name PalletTestUtilsEvent (124) */
+  /** @name PalletTestUtilsEvent (123) */
   interface PalletTestUtilsEvent extends Enum {
     readonly isValueIsSet: boolean;
     readonly isShouldRollback: boolean;
@@ -1512,7 +1507,7 @@
     readonly type: 'ValueIsSet' | 'ShouldRollback' | 'BatchCompleted';
   }
 
-  /** @name FrameSystemPhase (125) */
+  /** @name FrameSystemPhase (124) */
   interface FrameSystemPhase extends Enum {
     readonly isApplyExtrinsic: boolean;
     readonly asApplyExtrinsic: u32;
@@ -1521,13 +1516,13 @@
     readonly type: 'ApplyExtrinsic' | 'Finalization' | 'Initialization';
   }
 
-  /** @name FrameSystemLastRuntimeUpgradeInfo (127) */
+  /** @name FrameSystemLastRuntimeUpgradeInfo (126) */
   interface FrameSystemLastRuntimeUpgradeInfo extends Struct {
     readonly specVersion: Compact<u32>;
     readonly specName: Text;
   }
 
-  /** @name FrameSystemCall (128) */
+  /** @name FrameSystemCall (127) */
   interface FrameSystemCall extends Enum {
     readonly isFillBlock: boolean;
     readonly asFillBlock: {
@@ -1569,21 +1564,21 @@
     readonly type: 'FillBlock' | 'Remark' | 'SetHeapPages' | 'SetCode' | 'SetCodeWithoutChecks' | 'SetStorage' | 'KillStorage' | 'KillPrefix' | 'RemarkWithEvent';
   }
 
-  /** @name FrameSystemLimitsBlockWeights (133) */
+  /** @name FrameSystemLimitsBlockWeights (132) */
   interface FrameSystemLimitsBlockWeights extends Struct {
     readonly baseBlock: SpWeightsWeightV2Weight;
     readonly maxBlock: SpWeightsWeightV2Weight;
     readonly perClass: FrameSupportDispatchPerDispatchClassWeightsPerClass;
   }
 
-  /** @name FrameSupportDispatchPerDispatchClassWeightsPerClass (134) */
+  /** @name FrameSupportDispatchPerDispatchClassWeightsPerClass (133) */
   interface FrameSupportDispatchPerDispatchClassWeightsPerClass extends Struct {
     readonly normal: FrameSystemLimitsWeightsPerClass;
     readonly operational: FrameSystemLimitsWeightsPerClass;
     readonly mandatory: FrameSystemLimitsWeightsPerClass;
   }
 
-  /** @name FrameSystemLimitsWeightsPerClass (135) */
+  /** @name FrameSystemLimitsWeightsPerClass (134) */
   interface FrameSystemLimitsWeightsPerClass extends Struct {
     readonly baseExtrinsic: SpWeightsWeightV2Weight;
     readonly maxExtrinsic: Option<SpWeightsWeightV2Weight>;
@@ -1591,25 +1586,25 @@
     readonly reserved: Option<SpWeightsWeightV2Weight>;
   }
 
-  /** @name FrameSystemLimitsBlockLength (137) */
+  /** @name FrameSystemLimitsBlockLength (136) */
   interface FrameSystemLimitsBlockLength extends Struct {
     readonly max: FrameSupportDispatchPerDispatchClassU32;
   }
 
-  /** @name FrameSupportDispatchPerDispatchClassU32 (138) */
+  /** @name FrameSupportDispatchPerDispatchClassU32 (137) */
   interface FrameSupportDispatchPerDispatchClassU32 extends Struct {
     readonly normal: u32;
     readonly operational: u32;
     readonly mandatory: u32;
   }
 
-  /** @name SpWeightsRuntimeDbWeight (139) */
+  /** @name SpWeightsRuntimeDbWeight (138) */
   interface SpWeightsRuntimeDbWeight extends Struct {
     readonly read: u64;
     readonly write: u64;
   }
 
-  /** @name SpVersionRuntimeVersion (140) */
+  /** @name SpVersionRuntimeVersion (139) */
   interface SpVersionRuntimeVersion extends Struct {
     readonly specName: Text;
     readonly implName: Text;
@@ -1621,7 +1616,7 @@
     readonly stateVersion: u8;
   }
 
-  /** @name FrameSystemError (145) */
+  /** @name FrameSystemError (144) */
   interface FrameSystemError extends Enum {
     readonly isInvalidSpecName: boolean;
     readonly isSpecVersionNeedsToIncrease: boolean;
@@ -1632,7 +1627,7 @@
     readonly type: 'InvalidSpecName' | 'SpecVersionNeedsToIncrease' | 'FailedToExtractRuntimeVersion' | 'NonDefaultComposite' | 'NonZeroRefCount' | 'CallFiltered';
   }
 
-  /** @name PolkadotPrimitivesV2PersistedValidationData (146) */
+  /** @name PolkadotPrimitivesV2PersistedValidationData (145) */
   interface PolkadotPrimitivesV2PersistedValidationData extends Struct {
     readonly parentHead: Bytes;
     readonly relayParentNumber: u32;
@@ -1640,18 +1635,18 @@
     readonly maxPovSize: u32;
   }
 
-  /** @name PolkadotPrimitivesV2UpgradeRestriction (149) */
+  /** @name PolkadotPrimitivesV2UpgradeRestriction (148) */
   interface PolkadotPrimitivesV2UpgradeRestriction extends Enum {
     readonly isPresent: boolean;
     readonly type: 'Present';
   }
 
-  /** @name SpTrieStorageProof (150) */
+  /** @name SpTrieStorageProof (149) */
   interface SpTrieStorageProof extends Struct {
     readonly trieNodes: BTreeSet<Bytes>;
   }
 
-  /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (152) */
+  /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (151) */
   interface CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot extends Struct {
     readonly dmqMqcHead: H256;
     readonly relayDispatchQueueSize: ITuple<[u32, u32]>;
@@ -1659,7 +1654,7 @@
     readonly egressChannels: Vec<ITuple<[u32, PolkadotPrimitivesV2AbridgedHrmpChannel]>>;
   }
 
-  /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (155) */
+  /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (154) */
   interface PolkadotPrimitivesV2AbridgedHrmpChannel extends Struct {
     readonly maxCapacity: u32;
     readonly maxTotalSize: u32;
@@ -1669,7 +1664,7 @@
     readonly mqcHead: Option<H256>;
   }
 
-  /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (156) */
+  /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (155) */
   interface PolkadotPrimitivesV2AbridgedHostConfiguration extends Struct {
     readonly maxCodeSize: u32;
     readonly maxHeadDataSize: u32;
@@ -1682,13 +1677,13 @@
     readonly validationUpgradeDelay: u32;
   }
 
-  /** @name PolkadotCorePrimitivesOutboundHrmpMessage (162) */
+  /** @name PolkadotCorePrimitivesOutboundHrmpMessage (161) */
   interface PolkadotCorePrimitivesOutboundHrmpMessage extends Struct {
     readonly recipient: u32;
     readonly data: Bytes;
   }
 
-  /** @name CumulusPalletParachainSystemCall (163) */
+  /** @name CumulusPalletParachainSystemCall (162) */
   interface CumulusPalletParachainSystemCall extends Enum {
     readonly isSetValidationData: boolean;
     readonly asSetValidationData: {
@@ -1709,7 +1704,7 @@
     readonly type: 'SetValidationData' | 'SudoSendUpwardMessage' | 'AuthorizeUpgrade' | 'EnactAuthorizedUpgrade';
   }
 
-  /** @name CumulusPrimitivesParachainInherentParachainInherentData (164) */
+  /** @name CumulusPrimitivesParachainInherentParachainInherentData (163) */
   interface CumulusPrimitivesParachainInherentParachainInherentData extends Struct {
     readonly validationData: PolkadotPrimitivesV2PersistedValidationData;
     readonly relayChainState: SpTrieStorageProof;
@@ -1717,19 +1712,19 @@
     readonly horizontalMessages: BTreeMap<u32, Vec<PolkadotCorePrimitivesInboundHrmpMessage>>;
   }
 
-  /** @name PolkadotCorePrimitivesInboundDownwardMessage (166) */
+  /** @name PolkadotCorePrimitivesInboundDownwardMessage (165) */
   interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct {
     readonly sentAt: u32;
     readonly msg: Bytes;
   }
 
-  /** @name PolkadotCorePrimitivesInboundHrmpMessage (169) */
+  /** @name PolkadotCorePrimitivesInboundHrmpMessage (168) */
   interface PolkadotCorePrimitivesInboundHrmpMessage extends Struct {
     readonly sentAt: u32;
     readonly data: Bytes;
   }
 
-  /** @name CumulusPalletParachainSystemError (172) */
+  /** @name CumulusPalletParachainSystemError (171) */
   interface CumulusPalletParachainSystemError extends Enum {
     readonly isOverlappingUpgrades: boolean;
     readonly isProhibitedByPolkadot: boolean;
@@ -1742,14 +1737,14 @@
     readonly type: 'OverlappingUpgrades' | 'ProhibitedByPolkadot' | 'TooBig' | 'ValidationDataNotAvailable' | 'HostConfigurationNotAvailable' | 'NotScheduled' | 'NothingAuthorized' | 'Unauthorized';
   }
 
-  /** @name PalletBalancesBalanceLock (174) */
+  /** @name PalletBalancesBalanceLock (173) */
   interface PalletBalancesBalanceLock extends Struct {
     readonly id: U8aFixed;
     readonly amount: u128;
     readonly reasons: PalletBalancesReasons;
   }
 
-  /** @name PalletBalancesReasons (175) */
+  /** @name PalletBalancesReasons (174) */
   interface PalletBalancesReasons extends Enum {
     readonly isFee: boolean;
     readonly isMisc: boolean;
@@ -1757,20 +1752,20 @@
     readonly type: 'Fee' | 'Misc' | 'All';
   }
 
-  /** @name PalletBalancesReserveData (178) */
+  /** @name PalletBalancesReserveData (177) */
   interface PalletBalancesReserveData extends Struct {
     readonly id: U8aFixed;
     readonly amount: u128;
   }
 
-  /** @name PalletBalancesReleases (180) */
+  /** @name PalletBalancesReleases (179) */
   interface PalletBalancesReleases extends Enum {
     readonly isV100: boolean;
     readonly isV200: boolean;
     readonly type: 'V100' | 'V200';
   }
 
-  /** @name PalletBalancesCall (181) */
+  /** @name PalletBalancesCall (180) */
   interface PalletBalancesCall extends Enum {
     readonly isTransfer: boolean;
     readonly asTransfer: {
@@ -1807,7 +1802,7 @@
     readonly type: 'Transfer' | 'SetBalance' | 'ForceTransfer' | 'TransferKeepAlive' | 'TransferAll' | 'ForceUnreserve';
   }
 
-  /** @name PalletBalancesError (184) */
+  /** @name PalletBalancesError (183) */
   interface PalletBalancesError extends Enum {
     readonly isVestingBalance: boolean;
     readonly isLiquidityRestrictions: boolean;
@@ -1820,7 +1815,7 @@
     readonly type: 'VestingBalance' | 'LiquidityRestrictions' | 'InsufficientBalance' | 'ExistentialDeposit' | 'KeepAlive' | 'ExistingVestingSchedule' | 'DeadAccount' | 'TooManyReserves';
   }
 
-  /** @name PalletTimestampCall (186) */
+  /** @name PalletTimestampCall (185) */
   interface PalletTimestampCall extends Enum {
     readonly isSet: boolean;
     readonly asSet: {
@@ -1829,14 +1824,14 @@
     readonly type: 'Set';
   }
 
-  /** @name PalletTransactionPaymentReleases (188) */
+  /** @name PalletTransactionPaymentReleases (187) */
   interface PalletTransactionPaymentReleases extends Enum {
     readonly isV1Ancient: boolean;
     readonly isV2: boolean;
     readonly type: 'V1Ancient' | 'V2';
   }
 
-  /** @name PalletTreasuryProposal (189) */
+  /** @name PalletTreasuryProposal (188) */
   interface PalletTreasuryProposal extends Struct {
     readonly proposer: AccountId32;
     readonly value: u128;
@@ -1844,7 +1839,7 @@
     readonly bond: u128;
   }
 
-  /** @name PalletTreasuryCall (192) */
+  /** @name PalletTreasuryCall (191) */
   interface PalletTreasuryCall extends Enum {
     readonly isProposeSpend: boolean;
     readonly asProposeSpend: {
@@ -1871,10 +1866,10 @@
     readonly type: 'ProposeSpend' | 'RejectProposal' | 'ApproveProposal' | 'Spend' | 'RemoveApproval';
   }
 
-  /** @name FrameSupportPalletId (195) */
+  /** @name FrameSupportPalletId (194) */
   interface FrameSupportPalletId extends U8aFixed {}
 
-  /** @name PalletTreasuryError (196) */
+  /** @name PalletTreasuryError (195) */
   interface PalletTreasuryError extends Enum {
     readonly isInsufficientProposersBalance: boolean;
     readonly isInvalidIndex: boolean;
@@ -1884,7 +1879,7 @@
     readonly type: 'InsufficientProposersBalance' | 'InvalidIndex' | 'TooManyApprovals' | 'InsufficientPermission' | 'ProposalNotApproved';
   }
 
-  /** @name PalletSudoCall (197) */
+  /** @name PalletSudoCall (196) */
   interface PalletSudoCall extends Enum {
     readonly isSudo: boolean;
     readonly asSudo: {
@@ -1907,7 +1902,7 @@
     readonly type: 'Sudo' | 'SudoUncheckedWeight' | 'SetKey' | 'SudoAs';
   }
 
-  /** @name OrmlVestingModuleCall (199) */
+  /** @name OrmlVestingModuleCall (198) */
   interface OrmlVestingModuleCall extends Enum {
     readonly isClaim: boolean;
     readonly isVestedTransfer: boolean;
@@ -1927,7 +1922,7 @@
     readonly type: 'Claim' | 'VestedTransfer' | 'UpdateVestingSchedules' | 'ClaimFor';
   }
 
-  /** @name OrmlXtokensModuleCall (201) */
+  /** @name OrmlXtokensModuleCall (200) */
   interface OrmlXtokensModuleCall extends Enum {
     readonly isTransfer: boolean;
     readonly asTransfer: {
@@ -1974,7 +1969,7 @@
     readonly type: 'Transfer' | 'TransferMultiasset' | 'TransferWithFee' | 'TransferMultiassetWithFee' | 'TransferMulticurrencies' | 'TransferMultiassets';
   }
 
-  /** @name XcmVersionedMultiAsset (202) */
+  /** @name XcmVersionedMultiAsset (201) */
   interface XcmVersionedMultiAsset extends Enum {
     readonly isV0: boolean;
     readonly asV0: XcmV0MultiAsset;
@@ -1983,7 +1978,7 @@
     readonly type: 'V0' | 'V1';
   }
 
-  /** @name OrmlTokensModuleCall (205) */
+  /** @name OrmlTokensModuleCall (204) */
   interface OrmlTokensModuleCall extends Enum {
     readonly isTransfer: boolean;
     readonly asTransfer: {
@@ -2020,7 +2015,7 @@
     readonly type: 'Transfer' | 'TransferAll' | 'TransferKeepAlive' | 'ForceTransfer' | 'SetBalance';
   }
 
-  /** @name CumulusPalletXcmpQueueCall (206) */
+  /** @name CumulusPalletXcmpQueueCall (205) */
   interface CumulusPalletXcmpQueueCall extends Enum {
     readonly isServiceOverweight: boolean;
     readonly asServiceOverweight: {
@@ -2056,7 +2051,7 @@
     readonly type: 'ServiceOverweight' | 'SuspendXcmExecution' | 'ResumeXcmExecution' | 'UpdateSuspendThreshold' | 'UpdateDropThreshold' | 'UpdateResumeThreshold' | 'UpdateThresholdWeight' | 'UpdateWeightRestrictDecay' | 'UpdateXcmpMaxIndividualWeight';
   }
 
-  /** @name PalletXcmCall (207) */
+  /** @name PalletXcmCall (206) */
   interface PalletXcmCall extends Enum {
     readonly isSend: boolean;
     readonly asSend: {
@@ -2118,7 +2113,7 @@
     readonly type: 'Send' | 'TeleportAssets' | 'ReserveTransferAssets' | 'Execute' | 'ForceXcmVersion' | 'ForceDefaultXcmVersion' | 'ForceSubscribeVersionNotify' | 'ForceUnsubscribeVersionNotify' | 'LimitedReserveTransferAssets' | 'LimitedTeleportAssets';
   }
 
-  /** @name XcmVersionedXcm (208) */
+  /** @name XcmVersionedXcm (207) */
   interface XcmVersionedXcm extends Enum {
     readonly isV0: boolean;
     readonly asV0: XcmV0Xcm;
@@ -2129,7 +2124,7 @@
     readonly type: 'V0' | 'V1' | 'V2';
   }
 
-  /** @name XcmV0Xcm (209) */
+  /** @name XcmV0Xcm (208) */
   interface XcmV0Xcm extends Enum {
     readonly isWithdrawAsset: boolean;
     readonly asWithdrawAsset: {
@@ -2192,7 +2187,7 @@
     readonly type: 'WithdrawAsset' | 'ReserveAssetDeposit' | 'TeleportAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom';
   }
 
-  /** @name XcmV0Order (211) */
+  /** @name XcmV0Order (210) */
   interface XcmV0Order extends Enum {
     readonly isNull: boolean;
     readonly isDepositAsset: boolean;
@@ -2240,14 +2235,14 @@
     readonly type: 'Null' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution';
   }
 
-  /** @name XcmV0Response (213) */
+  /** @name XcmV0Response (212) */
   interface XcmV0Response extends Enum {
     readonly isAssets: boolean;
     readonly asAssets: Vec<XcmV0MultiAsset>;
     readonly type: 'Assets';
   }
 
-  /** @name XcmV1Xcm (214) */
+  /** @name XcmV1Xcm (213) */
   interface XcmV1Xcm extends Enum {
     readonly isWithdrawAsset: boolean;
     readonly asWithdrawAsset: {
@@ -2316,7 +2311,7 @@
     readonly type: 'WithdrawAsset' | 'ReserveAssetDeposited' | 'ReceiveTeleportedAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom' | 'SubscribeVersion' | 'UnsubscribeVersion';
   }
 
-  /** @name XcmV1Order (216) */
+  /** @name XcmV1Order (215) */
   interface XcmV1Order extends Enum {
     readonly isNoop: boolean;
     readonly isDepositAsset: boolean;
@@ -2366,7 +2361,7 @@
     readonly type: 'Noop' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution';
   }
 
-  /** @name XcmV1Response (218) */
+  /** @name XcmV1Response (217) */
   interface XcmV1Response extends Enum {
     readonly isAssets: boolean;
     readonly asAssets: XcmV1MultiassetMultiAssets;
@@ -2375,10 +2370,10 @@
     readonly type: 'Assets' | 'Version';
   }
 
-  /** @name CumulusPalletXcmCall (232) */
+  /** @name CumulusPalletXcmCall (231) */
   type CumulusPalletXcmCall = Null;
 
-  /** @name CumulusPalletDmpQueueCall (233) */
+  /** @name CumulusPalletDmpQueueCall (232) */
   interface CumulusPalletDmpQueueCall extends Enum {
     readonly isServiceOverweight: boolean;
     readonly asServiceOverweight: {
@@ -2388,7 +2383,7 @@
     readonly type: 'ServiceOverweight';
   }
 
-  /** @name PalletInflationCall (234) */
+  /** @name PalletInflationCall (233) */
   interface PalletInflationCall extends Enum {
     readonly isStartInflation: boolean;
     readonly asStartInflation: {
@@ -2397,7 +2392,7 @@
     readonly type: 'StartInflation';
   }
 
-  /** @name PalletUniqueCall (235) */
+  /** @name PalletUniqueCall (234) */
   interface PalletUniqueCall extends Enum {
     readonly isCreateCollection: boolean;
     readonly asCreateCollection: {
@@ -2561,7 +2556,7 @@
     readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetAllowanceForAll';
   }
 
-  /** @name UpDataStructsCollectionMode (240) */
+  /** @name UpDataStructsCollectionMode (239) */
   interface UpDataStructsCollectionMode extends Enum {
     readonly isNft: boolean;
     readonly isFungible: boolean;
@@ -2570,7 +2565,7 @@
     readonly type: 'Nft' | 'Fungible' | 'ReFungible';
   }
 
-  /** @name UpDataStructsCreateCollectionData (241) */
+  /** @name UpDataStructsCreateCollectionData (240) */
   interface UpDataStructsCreateCollectionData extends Struct {
     readonly mode: UpDataStructsCollectionMode;
     readonly access: Option<UpDataStructsAccessMode>;
@@ -2584,14 +2579,14 @@
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsAccessMode (243) */
+  /** @name UpDataStructsAccessMode (242) */
   interface UpDataStructsAccessMode extends Enum {
     readonly isNormal: boolean;
     readonly isAllowList: boolean;
     readonly type: 'Normal' | 'AllowList';
   }
 
-  /** @name UpDataStructsCollectionLimits (245) */
+  /** @name UpDataStructsCollectionLimits (244) */
   interface UpDataStructsCollectionLimits extends Struct {
     readonly accountTokenOwnershipLimit: Option<u32>;
     readonly sponsoredDataSize: Option<u32>;
@@ -2604,7 +2599,7 @@
     readonly transfersEnabled: Option<bool>;
   }
 
-  /** @name UpDataStructsSponsoringRateLimit (247) */
+  /** @name UpDataStructsSponsoringRateLimit (246) */
   interface UpDataStructsSponsoringRateLimit extends Enum {
     readonly isSponsoringDisabled: boolean;
     readonly isBlocks: boolean;
@@ -2612,43 +2607,43 @@
     readonly type: 'SponsoringDisabled' | 'Blocks';
   }
 
-  /** @name UpDataStructsCollectionPermissions (250) */
+  /** @name UpDataStructsCollectionPermissions (249) */
   interface UpDataStructsCollectionPermissions extends Struct {
     readonly access: Option<UpDataStructsAccessMode>;
     readonly mintMode: Option<bool>;
     readonly nesting: Option<UpDataStructsNestingPermissions>;
   }
 
-  /** @name UpDataStructsNestingPermissions (252) */
+  /** @name UpDataStructsNestingPermissions (251) */
   interface UpDataStructsNestingPermissions extends Struct {
     readonly tokenOwner: bool;
     readonly collectionAdmin: bool;
     readonly restricted: Option<UpDataStructsOwnerRestrictedSet>;
   }
 
-  /** @name UpDataStructsOwnerRestrictedSet (254) */
+  /** @name UpDataStructsOwnerRestrictedSet (253) */
   interface UpDataStructsOwnerRestrictedSet extends BTreeSet<u32> {}
 
-  /** @name UpDataStructsPropertyKeyPermission (259) */
+  /** @name UpDataStructsPropertyKeyPermission (258) */
   interface UpDataStructsPropertyKeyPermission extends Struct {
     readonly key: Bytes;
     readonly permission: UpDataStructsPropertyPermission;
   }
 
-  /** @name UpDataStructsPropertyPermission (260) */
+  /** @name UpDataStructsPropertyPermission (259) */
   interface UpDataStructsPropertyPermission extends Struct {
     readonly mutable: bool;
     readonly collectionAdmin: bool;
     readonly tokenOwner: bool;
   }
 
-  /** @name UpDataStructsProperty (263) */
+  /** @name UpDataStructsProperty (262) */
   interface UpDataStructsProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name UpDataStructsCreateItemData (266) */
+  /** @name UpDataStructsCreateItemData (265) */
   interface UpDataStructsCreateItemData extends Enum {
     readonly isNft: boolean;
     readonly asNft: UpDataStructsCreateNftData;
@@ -2659,23 +2654,23 @@
     readonly type: 'Nft' | 'Fungible' | 'ReFungible';
   }
 
-  /** @name UpDataStructsCreateNftData (267) */
+  /** @name UpDataStructsCreateNftData (266) */
   interface UpDataStructsCreateNftData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateFungibleData (268) */
+  /** @name UpDataStructsCreateFungibleData (267) */
   interface UpDataStructsCreateFungibleData extends Struct {
     readonly value: u128;
   }
 
-  /** @name UpDataStructsCreateReFungibleData (269) */
+  /** @name UpDataStructsCreateReFungibleData (268) */
   interface UpDataStructsCreateReFungibleData extends Struct {
     readonly pieces: u128;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateItemExData (272) */
+  /** @name UpDataStructsCreateItemExData (271) */
   interface UpDataStructsCreateItemExData extends Enum {
     readonly isNft: boolean;
     readonly asNft: Vec<UpDataStructsCreateNftExData>;
@@ -2688,26 +2683,26 @@
     readonly type: 'Nft' | 'Fungible' | 'RefungibleMultipleItems' | 'RefungibleMultipleOwners';
   }
 
-  /** @name UpDataStructsCreateNftExData (274) */
+  /** @name UpDataStructsCreateNftExData (273) */
   interface UpDataStructsCreateNftExData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name UpDataStructsCreateRefungibleExSingleOwner (281) */
+  /** @name UpDataStructsCreateRefungibleExSingleOwner (280) */
   interface UpDataStructsCreateRefungibleExSingleOwner extends Struct {
     readonly user: PalletEvmAccountBasicCrossAccountIdRepr;
     readonly pieces: u128;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name UpDataStructsCreateRefungibleExMultipleOwners (283) */
+  /** @name UpDataStructsCreateRefungibleExMultipleOwners (282) */
   interface UpDataStructsCreateRefungibleExMultipleOwners extends Struct {
     readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
     readonly properties: Vec<UpDataStructsProperty>;
   }
 
-  /** @name PalletUniqueSchedulerV2Call (284) */
+  /** @name PalletUniqueSchedulerV2Call (283) */
   interface PalletUniqueSchedulerV2Call extends Enum {
     readonly isSchedule: boolean;
     readonly asSchedule: {
@@ -2756,7 +2751,7 @@
     readonly type: 'Schedule' | 'Cancel' | 'ScheduleNamed' | 'CancelNamed' | 'ScheduleAfter' | 'ScheduleNamedAfter' | 'ChangeNamedPriority';
   }
 
-  /** @name PalletConfigurationCall (287) */
+  /** @name PalletConfigurationCall (286) */
   interface PalletConfigurationCall extends Enum {
     readonly isSetWeightToFeeCoefficientOverride: boolean;
     readonly asSetWeightToFeeCoefficientOverride: {
@@ -2769,13 +2764,13 @@
     readonly type: 'SetWeightToFeeCoefficientOverride' | 'SetMinGasPriceOverride';
   }
 
-  /** @name PalletTemplateTransactionPaymentCall (289) */
+  /** @name PalletTemplateTransactionPaymentCall (288) */
   type PalletTemplateTransactionPaymentCall = Null;
 
-  /** @name PalletStructureCall (290) */
+  /** @name PalletStructureCall (289) */
   type PalletStructureCall = Null;
 
-  /** @name PalletRmrkCoreCall (291) */
+  /** @name PalletRmrkCoreCall (290) */
   interface PalletRmrkCoreCall extends Enum {
     readonly isCreateCollection: boolean;
     readonly asCreateCollection: {
@@ -2881,7 +2876,7 @@
     readonly type: 'CreateCollection' | 'DestroyCollection' | 'ChangeCollectionIssuer' | 'LockCollection' | 'MintNft' | 'BurnNft' | 'Send' | 'AcceptNft' | 'RejectNft' | 'AcceptResource' | 'AcceptResourceRemoval' | 'SetProperty' | 'SetPriority' | 'AddBasicResource' | 'AddComposableResource' | 'AddSlotResource' | 'RemoveResource';
   }
 
-  /** @name RmrkTraitsResourceResourceTypes (297) */
+  /** @name RmrkTraitsResourceResourceTypes (296) */
   interface RmrkTraitsResourceResourceTypes extends Enum {
     readonly isBasic: boolean;
     readonly asBasic: RmrkTraitsResourceBasicResource;
@@ -2892,7 +2887,7 @@
     readonly type: 'Basic' | 'Composable' | 'Slot';
   }
 
-  /** @name RmrkTraitsResourceBasicResource (299) */
+  /** @name RmrkTraitsResourceBasicResource (298) */
   interface RmrkTraitsResourceBasicResource extends Struct {
     readonly src: Option<Bytes>;
     readonly metadata: Option<Bytes>;
@@ -2900,7 +2895,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name RmrkTraitsResourceComposableResource (301) */
+  /** @name RmrkTraitsResourceComposableResource (300) */
   interface RmrkTraitsResourceComposableResource extends Struct {
     readonly parts: Vec<u32>;
     readonly base: u32;
@@ -2910,7 +2905,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name RmrkTraitsResourceSlotResource (302) */
+  /** @name RmrkTraitsResourceSlotResource (301) */
   interface RmrkTraitsResourceSlotResource extends Struct {
     readonly base: u32;
     readonly src: Option<Bytes>;
@@ -2920,7 +2915,7 @@
     readonly thumb: Option<Bytes>;
   }
 
-  /** @name PalletRmrkEquipCall (305) */
+  /** @name PalletRmrkEquipCall (304) */
   interface PalletRmrkEquipCall extends Enum {
     readonly isCreateBase: boolean;
     readonly asCreateBase: {
@@ -2942,7 +2937,7 @@
     readonly type: 'CreateBase' | 'ThemeAdd' | 'Equippable';
   }
 
-  /** @name RmrkTraitsPartPartType (308) */
+  /** @name RmrkTraitsPartPartType (307) */
   interface RmrkTraitsPartPartType extends Enum {
     readonly isFixedPart: boolean;
     readonly asFixedPart: RmrkTraitsPartFixedPart;
@@ -2951,14 +2946,14 @@
     readonly type: 'FixedPart' | 'SlotPart';
   }
 
-  /** @name RmrkTraitsPartFixedPart (310) */
+  /** @name RmrkTraitsPartFixedPart (309) */
   interface RmrkTraitsPartFixedPart extends Struct {
     readonly id: u32;
     readonly z: u32;
     readonly src: Bytes;
   }
 
-  /** @name RmrkTraitsPartSlotPart (311) */
+  /** @name RmrkTraitsPartSlotPart (310) */
   interface RmrkTraitsPartSlotPart extends Struct {
     readonly id: u32;
     readonly equippable: RmrkTraitsPartEquippableList;
@@ -2966,7 +2961,7 @@
     readonly z: u32;
   }
 
-  /** @name RmrkTraitsPartEquippableList (312) */
+  /** @name RmrkTraitsPartEquippableList (311) */
   interface RmrkTraitsPartEquippableList extends Enum {
     readonly isAll: boolean;
     readonly isEmpty: boolean;
@@ -2975,20 +2970,20 @@
     readonly type: 'All' | 'Empty' | 'Custom';
   }
 
-  /** @name RmrkTraitsTheme (314) */
+  /** @name RmrkTraitsTheme (313) */
   interface RmrkTraitsTheme extends Struct {
     readonly name: Bytes;
     readonly properties: Vec<RmrkTraitsThemeThemeProperty>;
     readonly inherit: bool;
   }
 
-  /** @name RmrkTraitsThemeThemeProperty (316) */
+  /** @name RmrkTraitsThemeThemeProperty (315) */
   interface RmrkTraitsThemeThemeProperty extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name PalletAppPromotionCall (318) */
+  /** @name PalletAppPromotionCall (317) */
   interface PalletAppPromotionCall extends Enum {
     readonly isSetAdminAddress: boolean;
     readonly asSetAdminAddress: {
@@ -3022,7 +3017,7 @@
     readonly type: 'SetAdminAddress' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers';
   }
 
-  /** @name PalletForeignAssetsModuleCall (319) */
+  /** @name PalletForeignAssetsModuleCall (318) */
   interface PalletForeignAssetsModuleCall extends Enum {
     readonly isRegisterForeignAsset: boolean;
     readonly asRegisterForeignAsset: {
@@ -3039,7 +3034,7 @@
     readonly type: 'RegisterForeignAsset' | 'UpdateForeignAsset';
   }
 
-  /** @name PalletEvmCall (320) */
+  /** @name PalletEvmCall (319) */
   interface PalletEvmCall extends Enum {
     readonly isWithdraw: boolean;
     readonly asWithdraw: {
@@ -3084,7 +3079,7 @@
     readonly type: 'Withdraw' | 'Call' | 'Create' | 'Create2';
   }
 
-  /** @name PalletEthereumCall (326) */
+  /** @name PalletEthereumCall (325) */
   interface PalletEthereumCall extends Enum {
     readonly isTransact: boolean;
     readonly asTransact: {
@@ -3093,7 +3088,7 @@
     readonly type: 'Transact';
   }
 
-  /** @name EthereumTransactionTransactionV2 (327) */
+  /** @name EthereumTransactionTransactionV2 (326) */
   interface EthereumTransactionTransactionV2 extends Enum {
     readonly isLegacy: boolean;
     readonly asLegacy: EthereumTransactionLegacyTransaction;
@@ -3104,7 +3099,7 @@
     readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
   }
 
-  /** @name EthereumTransactionLegacyTransaction (328) */
+  /** @name EthereumTransactionLegacyTransaction (327) */
   interface EthereumTransactionLegacyTransaction extends Struct {
     readonly nonce: U256;
     readonly gasPrice: U256;
@@ -3115,7 +3110,7 @@
     readonly signature: EthereumTransactionTransactionSignature;
   }
 
-  /** @name EthereumTransactionTransactionAction (329) */
+  /** @name EthereumTransactionTransactionAction (328) */
   interface EthereumTransactionTransactionAction extends Enum {
     readonly isCall: boolean;
     readonly asCall: H160;
@@ -3123,14 +3118,14 @@
     readonly type: 'Call' | 'Create';
   }
 
-  /** @name EthereumTransactionTransactionSignature (330) */
+  /** @name EthereumTransactionTransactionSignature (329) */
   interface EthereumTransactionTransactionSignature extends Struct {
     readonly v: u64;
     readonly r: H256;
     readonly s: H256;
   }
 
-  /** @name EthereumTransactionEip2930Transaction (332) */
+  /** @name EthereumTransactionEip2930Transaction (331) */
   interface EthereumTransactionEip2930Transaction extends Struct {
     readonly chainId: u64;
     readonly nonce: U256;
@@ -3145,13 +3140,13 @@
     readonly s: H256;
   }
 
-  /** @name EthereumTransactionAccessListItem (334) */
+  /** @name EthereumTransactionAccessListItem (333) */
   interface EthereumTransactionAccessListItem extends Struct {
     readonly address: H160;
     readonly storageKeys: Vec<H256>;
   }
 
-  /** @name EthereumTransactionEip1559Transaction (335) */
+  /** @name EthereumTransactionEip1559Transaction (334) */
   interface EthereumTransactionEip1559Transaction extends Struct {
     readonly chainId: u64;
     readonly nonce: U256;
@@ -3167,7 +3162,7 @@
     readonly s: H256;
   }
 
-  /** @name PalletEvmMigrationCall (336) */
+  /** @name PalletEvmMigrationCall (335) */
   interface PalletEvmMigrationCall extends Enum {
     readonly isBegin: boolean;
     readonly asBegin: {
@@ -3194,14 +3189,14 @@
     readonly type: 'Begin' | 'SetData' | 'Finish' | 'InsertEthLogs' | 'InsertEvents';
   }
 
-  /** @name PalletMaintenanceCall (340) */
+  /** @name PalletMaintenanceCall (339) */
   interface PalletMaintenanceCall extends Enum {
     readonly isEnable: boolean;
     readonly isDisable: boolean;
     readonly type: 'Enable' | 'Disable';
   }
 
-  /** @name PalletTestUtilsCall (341) */
+  /** @name PalletTestUtilsCall (340) */
   interface PalletTestUtilsCall extends Enum {
     readonly isEnable: boolean;
     readonly isSetTestValue: boolean;
@@ -3226,13 +3221,13 @@
     readonly type: 'Enable' | 'SetTestValue' | 'SetTestValueAndRollback' | 'IncTestValue' | 'SelfCancelingInc' | 'JustTakeFee' | 'BatchAll';
   }
 
-  /** @name PalletSudoError (343) */
+  /** @name PalletSudoError (342) */
   interface PalletSudoError extends Enum {
     readonly isRequireSudo: boolean;
     readonly type: 'RequireSudo';
   }
 
-  /** @name OrmlVestingModuleError (345) */
+  /** @name OrmlVestingModuleError (344) */
   interface OrmlVestingModuleError extends Enum {
     readonly isZeroVestingPeriod: boolean;
     readonly isZeroVestingPeriodCount: boolean;
@@ -3243,7 +3238,7 @@
     readonly type: 'ZeroVestingPeriod' | 'ZeroVestingPeriodCount' | 'InsufficientBalanceToLock' | 'TooManyVestingSchedules' | 'AmountLow' | 'MaxVestingSchedulesExceeded';
   }
 
-  /** @name OrmlXtokensModuleError (346) */
+  /** @name OrmlXtokensModuleError (345) */
   interface OrmlXtokensModuleError extends Enum {
     readonly isAssetHasNoReserve: boolean;
     readonly isNotCrossChainTransfer: boolean;
@@ -3267,26 +3262,26 @@
     readonly type: 'AssetHasNoReserve' | 'NotCrossChainTransfer' | 'InvalidDest' | 'NotCrossChainTransferableCurrency' | 'UnweighableMessage' | 'XcmExecutionFailed' | 'CannotReanchor' | 'InvalidAncestry' | 'InvalidAsset' | 'DestinationNotInvertible' | 'BadVersion' | 'DistinctReserveForAssetAndFee' | 'ZeroFee' | 'ZeroAmount' | 'TooManyAssetsBeingSent' | 'AssetIndexNonExistent' | 'FeeNotEnough' | 'NotSupportedMultiLocation' | 'MinXcmFeeNotDefined';
   }
 
-  /** @name OrmlTokensBalanceLock (349) */
+  /** @name OrmlTokensBalanceLock (348) */
   interface OrmlTokensBalanceLock extends Struct {
     readonly id: U8aFixed;
     readonly amount: u128;
   }
 
-  /** @name OrmlTokensAccountData (351) */
+  /** @name OrmlTokensAccountData (350) */
   interface OrmlTokensAccountData extends Struct {
     readonly free: u128;
     readonly reserved: u128;
     readonly frozen: u128;
   }
 
-  /** @name OrmlTokensReserveData (353) */
+  /** @name OrmlTokensReserveData (352) */
   interface OrmlTokensReserveData extends Struct {
     readonly id: Null;
     readonly amount: u128;
   }
 
-  /** @name OrmlTokensModuleError (355) */
+  /** @name OrmlTokensModuleError (354) */
   interface OrmlTokensModuleError extends Enum {
     readonly isBalanceTooLow: boolean;
     readonly isAmountIntoBalanceFailed: boolean;
@@ -3299,21 +3294,21 @@
     readonly type: 'BalanceTooLow' | 'AmountIntoBalanceFailed' | 'LiquidityRestrictions' | 'MaxLocksExceeded' | 'KeepAlive' | 'ExistentialDeposit' | 'DeadAccount' | 'TooManyReserves';
   }
 
-  /** @name CumulusPalletXcmpQueueInboundChannelDetails (357) */
+  /** @name CumulusPalletXcmpQueueInboundChannelDetails (356) */
   interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct {
     readonly sender: u32;
     readonly state: CumulusPalletXcmpQueueInboundState;
     readonly messageMetadata: Vec<ITuple<[u32, PolkadotParachainPrimitivesXcmpMessageFormat]>>;
   }
 
-  /** @name CumulusPalletXcmpQueueInboundState (358) */
+  /** @name CumulusPalletXcmpQueueInboundState (357) */
   interface CumulusPalletXcmpQueueInboundState extends Enum {
     readonly isOk: boolean;
     readonly isSuspended: boolean;
     readonly type: 'Ok' | 'Suspended';
   }
 
-  /** @name PolkadotParachainPrimitivesXcmpMessageFormat (361) */
+  /** @name PolkadotParachainPrimitivesXcmpMessageFormat (360) */
   interface PolkadotParachainPrimitivesXcmpMessageFormat extends Enum {
     readonly isConcatenatedVersionedXcm: boolean;
     readonly isConcatenatedEncodedBlob: boolean;
@@ -3321,7 +3316,7 @@
     readonly type: 'ConcatenatedVersionedXcm' | 'ConcatenatedEncodedBlob' | 'Signals';
   }
 
-  /** @name CumulusPalletXcmpQueueOutboundChannelDetails (364) */
+  /** @name CumulusPalletXcmpQueueOutboundChannelDetails (363) */
   interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct {
     readonly recipient: u32;
     readonly state: CumulusPalletXcmpQueueOutboundState;
@@ -3330,14 +3325,14 @@
     readonly lastIndex: u16;
   }
 
-  /** @name CumulusPalletXcmpQueueOutboundState (365) */
+  /** @name CumulusPalletXcmpQueueOutboundState (364) */
   interface CumulusPalletXcmpQueueOutboundState extends Enum {
     readonly isOk: boolean;
     readonly isSuspended: boolean;
     readonly type: 'Ok' | 'Suspended';
   }
 
-  /** @name CumulusPalletXcmpQueueQueueConfigData (367) */
+  /** @name CumulusPalletXcmpQueueQueueConfigData (366) */
   interface CumulusPalletXcmpQueueQueueConfigData extends Struct {
     readonly suspendThreshold: u32;
     readonly dropThreshold: u32;
@@ -3347,7 +3342,7 @@
     readonly xcmpMaxIndividualWeight: SpWeightsWeightV2Weight;
   }
 
-  /** @name CumulusPalletXcmpQueueError (369) */
+  /** @name CumulusPalletXcmpQueueError (368) */
   interface CumulusPalletXcmpQueueError extends Enum {
     readonly isFailedToSend: boolean;
     readonly isBadXcmOrigin: boolean;
@@ -3357,7 +3352,7 @@
     readonly type: 'FailedToSend' | 'BadXcmOrigin' | 'BadXcm' | 'BadOverweightIndex' | 'WeightOverLimit';
   }
 
-  /** @name PalletXcmError (370) */
+  /** @name PalletXcmError (369) */
   interface PalletXcmError extends Enum {
     readonly isUnreachable: boolean;
     readonly isSendFailure: boolean;
@@ -3375,44 +3370,43 @@
     readonly type: 'Unreachable' | 'SendFailure' | 'Filtered' | 'UnweighableMessage' | 'DestinationNotInvertible' | 'Empty' | 'CannotReanchor' | 'TooManyAssets' | 'InvalidOrigin' | 'BadVersion' | 'BadLocation' | 'NoSubscription' | 'AlreadySubscribed';
   }
 
-  /** @name CumulusPalletXcmError (371) */
+  /** @name CumulusPalletXcmError (370) */
   type CumulusPalletXcmError = Null;
 
-  /** @name CumulusPalletDmpQueueConfigData (372) */
+  /** @name CumulusPalletDmpQueueConfigData (371) */
   interface CumulusPalletDmpQueueConfigData extends Struct {
     readonly maxIndividual: SpWeightsWeightV2Weight;
   }
 
-  /** @name CumulusPalletDmpQueuePageIndexData (373) */
+  /** @name CumulusPalletDmpQueuePageIndexData (372) */
   interface CumulusPalletDmpQueuePageIndexData extends Struct {
     readonly beginUsed: u32;
     readonly endUsed: u32;
     readonly overweightCount: u64;
   }
 
-  /** @name CumulusPalletDmpQueueError (376) */
+  /** @name CumulusPalletDmpQueueError (375) */
   interface CumulusPalletDmpQueueError extends Enum {
     readonly isUnknown: boolean;
     readonly isOverLimit: boolean;
     readonly type: 'Unknown' | 'OverLimit';
   }
 
-  /** @name PalletUniqueError (380) */
+  /** @name PalletUniqueError (379) */
   interface PalletUniqueError extends Enum {
     readonly isCollectionDecimalPointLimitExceeded: boolean;
-    readonly isConfirmUnsetSponsorFail: boolean;
     readonly isEmptyArgument: boolean;
     readonly isRepartitionCalledOnNonRefungibleCollection: boolean;
-    readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection';
+    readonly type: 'CollectionDecimalPointLimitExceeded' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection';
   }
 
-  /** @name PalletUniqueSchedulerV2BlockAgenda (381) */
+  /** @name PalletUniqueSchedulerV2BlockAgenda (380) */
   interface PalletUniqueSchedulerV2BlockAgenda extends Struct {
     readonly agenda: Vec<Option<PalletUniqueSchedulerV2Scheduled>>;
     readonly freePlaces: u32;
   }
 
-  /** @name PalletUniqueSchedulerV2Scheduled (384) */
+  /** @name PalletUniqueSchedulerV2Scheduled (383) */
   interface PalletUniqueSchedulerV2Scheduled extends Struct {
     readonly maybeId: Option<U8aFixed>;
     readonly priority: u8;
@@ -3421,7 +3415,7 @@
     readonly origin: OpalRuntimeOriginCaller;
   }
 
-  /** @name PalletUniqueSchedulerV2ScheduledCall (385) */
+  /** @name PalletUniqueSchedulerV2ScheduledCall (384) */
   interface PalletUniqueSchedulerV2ScheduledCall extends Enum {
     readonly isInline: boolean;
     readonly asInline: Bytes;
@@ -3433,7 +3427,7 @@
     readonly type: 'Inline' | 'PreimageLookup';
   }
 
-  /** @name OpalRuntimeOriginCaller (387) */
+  /** @name OpalRuntimeOriginCaller (386) */
   interface OpalRuntimeOriginCaller extends Enum {
     readonly isSystem: boolean;
     readonly asSystem: FrameSupportDispatchRawOrigin;
@@ -3447,7 +3441,7 @@
     readonly type: 'System' | 'Void' | 'PolkadotXcm' | 'CumulusXcm' | 'Ethereum';
   }
 
-  /** @name FrameSupportDispatchRawOrigin (388) */
+  /** @name FrameSupportDispatchRawOrigin (387) */
   interface FrameSupportDispatchRawOrigin extends Enum {
     readonly isRoot: boolean;
     readonly isSigned: boolean;
@@ -3456,7 +3450,7 @@
     readonly type: 'Root' | 'Signed' | 'None';
   }
 
-  /** @name PalletXcmOrigin (389) */
+  /** @name PalletXcmOrigin (388) */
   interface PalletXcmOrigin extends Enum {
     readonly isXcm: boolean;
     readonly asXcm: XcmV1MultiLocation;
@@ -3465,7 +3459,7 @@
     readonly type: 'Xcm' | 'Response';
   }
 
-  /** @name CumulusPalletXcmOrigin (390) */
+  /** @name CumulusPalletXcmOrigin (389) */
   interface CumulusPalletXcmOrigin extends Enum {
     readonly isRelay: boolean;
     readonly isSiblingParachain: boolean;
@@ -3473,17 +3467,17 @@
     readonly type: 'Relay' | 'SiblingParachain';
   }
 
-  /** @name PalletEthereumRawOrigin (391) */
+  /** @name PalletEthereumRawOrigin (390) */
   interface PalletEthereumRawOrigin extends Enum {
     readonly isEthereumTransaction: boolean;
     readonly asEthereumTransaction: H160;
     readonly type: 'EthereumTransaction';
   }
 
-  /** @name SpCoreVoid (392) */
+  /** @name SpCoreVoid (391) */
   type SpCoreVoid = Null;
 
-  /** @name PalletUniqueSchedulerV2Error (394) */
+  /** @name PalletUniqueSchedulerV2Error (393) */
   interface PalletUniqueSchedulerV2Error extends Enum {
     readonly isFailedToSchedule: boolean;
     readonly isAgendaIsExhausted: boolean;
@@ -3496,7 +3490,7 @@
     readonly type: 'FailedToSchedule' | 'AgendaIsExhausted' | 'ScheduledCallCorrupted' | 'PreimageNotFound' | 'TooBigScheduledCall' | 'NotFound' | 'TargetBlockNumberInPast' | 'Named';
   }
 
-  /** @name UpDataStructsCollection (395) */
+  /** @name UpDataStructsCollection (394) */
   interface UpDataStructsCollection extends Struct {
     readonly owner: AccountId32;
     readonly mode: UpDataStructsCollectionMode;
@@ -3509,7 +3503,7 @@
     readonly flags: U8aFixed;
   }
 
-  /** @name UpDataStructsSponsorshipStateAccountId32 (396) */
+  /** @name UpDataStructsSponsorshipStateAccountId32 (395) */
   interface UpDataStructsSponsorshipStateAccountId32 extends Enum {
     readonly isDisabled: boolean;
     readonly isUnconfirmed: boolean;
@@ -3519,43 +3513,43 @@
     readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
   }
 
-  /** @name UpDataStructsProperties (398) */
+  /** @name UpDataStructsProperties (397) */
   interface UpDataStructsProperties extends Struct {
     readonly map: UpDataStructsPropertiesMapBoundedVec;
     readonly consumedSpace: u32;
     readonly spaceLimit: u32;
   }
 
-  /** @name UpDataStructsPropertiesMapBoundedVec (399) */
+  /** @name UpDataStructsPropertiesMapBoundedVec (398) */
   interface UpDataStructsPropertiesMapBoundedVec extends BTreeMap<Bytes, Bytes> {}
 
-  /** @name UpDataStructsPropertiesMapPropertyPermission (404) */
+  /** @name UpDataStructsPropertiesMapPropertyPermission (403) */
   interface UpDataStructsPropertiesMapPropertyPermission extends BTreeMap<Bytes, UpDataStructsPropertyPermission> {}
 
-  /** @name UpDataStructsCollectionStats (411) */
+  /** @name UpDataStructsCollectionStats (410) */
   interface UpDataStructsCollectionStats extends Struct {
     readonly created: u32;
     readonly destroyed: u32;
     readonly alive: u32;
   }
 
-  /** @name UpDataStructsTokenChild (412) */
+  /** @name UpDataStructsTokenChild (411) */
   interface UpDataStructsTokenChild extends Struct {
     readonly token: u32;
     readonly collection: u32;
   }
 
-  /** @name PhantomTypeUpDataStructs (413) */
+  /** @name PhantomTypeUpDataStructs (412) */
   interface PhantomTypeUpDataStructs extends Vec<ITuple<[UpDataStructsTokenData, UpDataStructsRpcCollection, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftNftInfo, RmrkTraitsResourceResourceInfo, RmrkTraitsPropertyPropertyInfo, RmrkTraitsBaseBaseInfo, RmrkTraitsPartPartType, RmrkTraitsTheme, RmrkTraitsNftNftChild]>> {}
 
-  /** @name UpDataStructsTokenData (415) */
+  /** @name UpDataStructsTokenData (414) */
   interface UpDataStructsTokenData extends Struct {
     readonly properties: Vec<UpDataStructsProperty>;
     readonly owner: Option<PalletEvmAccountBasicCrossAccountIdRepr>;
     readonly pieces: u128;
   }
 
-  /** @name UpDataStructsRpcCollection (417) */
+  /** @name UpDataStructsRpcCollection (416) */
   interface UpDataStructsRpcCollection extends Struct {
     readonly owner: AccountId32;
     readonly mode: UpDataStructsCollectionMode;
@@ -3571,13 +3565,13 @@
     readonly flags: UpDataStructsRpcCollectionFlags;
   }
 
-  /** @name UpDataStructsRpcCollectionFlags (418) */
+  /** @name UpDataStructsRpcCollectionFlags (417) */
   interface UpDataStructsRpcCollectionFlags extends Struct {
     readonly foreign: bool;
     readonly erc721metadata: bool;
   }
 
-  /** @name RmrkTraitsCollectionCollectionInfo (419) */
+  /** @name RmrkTraitsCollectionCollectionInfo (418) */
   interface RmrkTraitsCollectionCollectionInfo extends Struct {
     readonly issuer: AccountId32;
     readonly metadata: Bytes;
@@ -3586,7 +3580,7 @@
     readonly nftsCount: u32;
   }
 
-  /** @name RmrkTraitsNftNftInfo (420) */
+  /** @name RmrkTraitsNftNftInfo (419) */
   interface RmrkTraitsNftNftInfo extends Struct {
     readonly owner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
     readonly royalty: Option<RmrkTraitsNftRoyaltyInfo>;
@@ -3595,13 +3589,13 @@
     readonly pending: bool;
   }
 
-  /** @name RmrkTraitsNftRoyaltyInfo (422) */
+  /** @name RmrkTraitsNftRoyaltyInfo (421) */
   interface RmrkTraitsNftRoyaltyInfo extends Struct {
     readonly recipient: AccountId32;
     readonly amount: Permill;
   }
 
-  /** @name RmrkTraitsResourceResourceInfo (423) */
+  /** @name RmrkTraitsResourceResourceInfo (422) */
   interface RmrkTraitsResourceResourceInfo extends Struct {
     readonly id: u32;
     readonly resource: RmrkTraitsResourceResourceTypes;
@@ -3609,26 +3603,26 @@
     readonly pendingRemoval: bool;
   }
 
-  /** @name RmrkTraitsPropertyPropertyInfo (424) */
+  /** @name RmrkTraitsPropertyPropertyInfo (423) */
   interface RmrkTraitsPropertyPropertyInfo extends Struct {
     readonly key: Bytes;
     readonly value: Bytes;
   }
 
-  /** @name RmrkTraitsBaseBaseInfo (425) */
+  /** @name RmrkTraitsBaseBaseInfo (424) */
   interface RmrkTraitsBaseBaseInfo extends Struct {
     readonly issuer: AccountId32;
     readonly baseType: Bytes;
     readonly symbol: Bytes;
   }
 
-  /** @name RmrkTraitsNftNftChild (426) */
+  /** @name RmrkTraitsNftNftChild (425) */
   interface RmrkTraitsNftNftChild extends Struct {
     readonly collectionId: u32;
     readonly nftId: u32;
   }
 
-  /** @name PalletCommonError (428) */
+  /** @name PalletCommonError (427) */
   interface PalletCommonError extends Enum {
     readonly isCollectionNotFound: boolean;
     readonly isMustBeTokenOwner: boolean;
@@ -3664,10 +3658,12 @@
     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' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal';
+    readonly isConfirmSponsorshipFail: boolean;
+    readonly isUserIsNotCollectionAdmin: boolean;
+    readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal' | 'ConfirmSponsorshipFail' | 'UserIsNotCollectionAdmin';
   }
 
-  /** @name PalletFungibleError (430) */
+  /** @name PalletFungibleError (429) */
   interface PalletFungibleError extends Enum {
     readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isFungibleItemsHaveNoId: boolean;
@@ -3678,12 +3674,12 @@
     readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed' | 'SettingAllowanceForAllNotAllowed';
   }
 
-  /** @name PalletRefungibleItemData (431) */
+  /** @name PalletRefungibleItemData (430) */
   interface PalletRefungibleItemData extends Struct {
     readonly constData: Bytes;
   }
 
-  /** @name PalletRefungibleError (436) */
+  /** @name PalletRefungibleError (435) */
   interface PalletRefungibleError extends Enum {
     readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isWrongRefungiblePieces: boolean;
@@ -3693,19 +3689,19 @@
     readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RepartitionWhileNotOwningAllPieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
   }
 
-  /** @name PalletNonfungibleItemData (437) */
+  /** @name PalletNonfungibleItemData (436) */
   interface PalletNonfungibleItemData extends Struct {
     readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
   }
 
-  /** @name UpDataStructsPropertyScope (439) */
+  /** @name UpDataStructsPropertyScope (438) */
   interface UpDataStructsPropertyScope extends Enum {
     readonly isNone: boolean;
     readonly isRmrk: boolean;
     readonly type: 'None' | 'Rmrk';
   }
 
-  /** @name PalletNonfungibleError (441) */
+  /** @name PalletNonfungibleError (440) */
   interface PalletNonfungibleError extends Enum {
     readonly isNotNonfungibleDataUsedToMintFungibleCollectionToken: boolean;
     readonly isNonfungibleItemsHaveNoAmount: boolean;
@@ -3713,7 +3709,7 @@
     readonly type: 'NotNonfungibleDataUsedToMintFungibleCollectionToken' | 'NonfungibleItemsHaveNoAmount' | 'CantBurnNftWithChildren';
   }
 
-  /** @name PalletStructureError (442) */
+  /** @name PalletStructureError (441) */
   interface PalletStructureError extends Enum {
     readonly isOuroborosDetected: boolean;
     readonly isDepthLimit: boolean;
@@ -3722,7 +3718,7 @@
     readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound';
   }
 
-  /** @name PalletRmrkCoreError (443) */
+  /** @name PalletRmrkCoreError (442) */
   interface PalletRmrkCoreError extends Enum {
     readonly isCorruptedCollectionType: boolean;
     readonly isRmrkPropertyKeyIsTooLong: boolean;
@@ -3746,7 +3742,7 @@
     readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId';
   }
 
-  /** @name PalletRmrkEquipError (445) */
+  /** @name PalletRmrkEquipError (444) */
   interface PalletRmrkEquipError extends Enum {
     readonly isPermissionError: boolean;
     readonly isNoAvailableBaseId: boolean;
@@ -3758,7 +3754,7 @@
     readonly type: 'PermissionError' | 'NoAvailableBaseId' | 'NoAvailablePartId' | 'BaseDoesntExist' | 'NeedsDefaultThemeFirst' | 'PartDoesntExist' | 'NoEquippableOnFixedPart';
   }
 
-  /** @name PalletAppPromotionError (451) */
+  /** @name PalletAppPromotionError (450) */
   interface PalletAppPromotionError extends Enum {
     readonly isAdminNotSet: boolean;
     readonly isNoPermission: boolean;
@@ -3769,7 +3765,7 @@
     readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation';
   }
 
-  /** @name PalletForeignAssetsModuleError (452) */
+  /** @name PalletForeignAssetsModuleError (451) */
   interface PalletForeignAssetsModuleError extends Enum {
     readonly isBadLocation: boolean;
     readonly isMultiLocationExisted: boolean;
@@ -3778,7 +3774,7 @@
     readonly type: 'BadLocation' | 'MultiLocationExisted' | 'AssetIdNotExists' | 'AssetIdExisted';
   }
 
-  /** @name PalletEvmError (454) */
+  /** @name PalletEvmError (453) */
   interface PalletEvmError extends Enum {
     readonly isBalanceLow: boolean;
     readonly isFeeOverflow: boolean;
@@ -3793,7 +3789,7 @@
     readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce' | 'GasLimitTooLow' | 'GasLimitTooHigh' | 'Undefined' | 'Reentrancy';
   }
 
-  /** @name FpRpcTransactionStatus (457) */
+  /** @name FpRpcTransactionStatus (456) */
   interface FpRpcTransactionStatus extends Struct {
     readonly transactionHash: H256;
     readonly transactionIndex: u32;
@@ -3804,10 +3800,10 @@
     readonly logsBloom: EthbloomBloom;
   }
 
-  /** @name EthbloomBloom (459) */
+  /** @name EthbloomBloom (458) */
   interface EthbloomBloom extends U8aFixed {}
 
-  /** @name EthereumReceiptReceiptV3 (461) */
+  /** @name EthereumReceiptReceiptV3 (460) */
   interface EthereumReceiptReceiptV3 extends Enum {
     readonly isLegacy: boolean;
     readonly asLegacy: EthereumReceiptEip658ReceiptData;
@@ -3818,7 +3814,7 @@
     readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
   }
 
-  /** @name EthereumReceiptEip658ReceiptData (462) */
+  /** @name EthereumReceiptEip658ReceiptData (461) */
   interface EthereumReceiptEip658ReceiptData extends Struct {
     readonly statusCode: u8;
     readonly usedGas: U256;
@@ -3826,14 +3822,14 @@
     readonly logs: Vec<EthereumLog>;
   }
 
-  /** @name EthereumBlock (463) */
+  /** @name EthereumBlock (462) */
   interface EthereumBlock extends Struct {
     readonly header: EthereumHeader;
     readonly transactions: Vec<EthereumTransactionTransactionV2>;
     readonly ommers: Vec<EthereumHeader>;
   }
 
-  /** @name EthereumHeader (464) */
+  /** @name EthereumHeader (463) */
   interface EthereumHeader extends Struct {
     readonly parentHash: H256;
     readonly ommersHash: H256;
@@ -3852,24 +3848,24 @@
     readonly nonce: EthereumTypesHashH64;
   }
 
-  /** @name EthereumTypesHashH64 (465) */
+  /** @name EthereumTypesHashH64 (464) */
   interface EthereumTypesHashH64 extends U8aFixed {}
 
-  /** @name PalletEthereumError (470) */
+  /** @name PalletEthereumError (469) */
   interface PalletEthereumError extends Enum {
     readonly isInvalidSignature: boolean;
     readonly isPreLogExists: boolean;
     readonly type: 'InvalidSignature' | 'PreLogExists';
   }
 
-  /** @name PalletEvmCoderSubstrateError (471) */
+  /** @name PalletEvmCoderSubstrateError (470) */
   interface PalletEvmCoderSubstrateError extends Enum {
     readonly isOutOfGas: boolean;
     readonly isOutOfFund: boolean;
     readonly type: 'OutOfGas' | 'OutOfFund';
   }
 
-  /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (472) */
+  /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (471) */
   interface UpDataStructsSponsorshipStateBasicCrossAccountIdRepr extends Enum {
     readonly isDisabled: boolean;
     readonly isUnconfirmed: boolean;
@@ -3879,7 +3875,7 @@
     readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
   }
 
-  /** @name PalletEvmContractHelpersSponsoringModeT (473) */
+  /** @name PalletEvmContractHelpersSponsoringModeT (472) */
   interface PalletEvmContractHelpersSponsoringModeT extends Enum {
     readonly isDisabled: boolean;
     readonly isAllowlisted: boolean;
@@ -3887,7 +3883,7 @@
     readonly type: 'Disabled' | 'Allowlisted' | 'Generous';
   }
 
-  /** @name PalletEvmContractHelpersError (479) */
+  /** @name PalletEvmContractHelpersError (478) */
   interface PalletEvmContractHelpersError extends Enum {
     readonly isNoPermission: boolean;
     readonly isNoPendingSponsor: boolean;
@@ -3895,7 +3891,7 @@
     readonly type: 'NoPermission' | 'NoPendingSponsor' | 'TooManyMethodsHaveSponsoredLimit';
   }
 
-  /** @name PalletEvmMigrationError (480) */
+  /** @name PalletEvmMigrationError (479) */
   interface PalletEvmMigrationError extends Enum {
     readonly isAccountNotEmpty: boolean;
     readonly isAccountIsNotMigrating: boolean;
@@ -3903,17 +3899,17 @@
     readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating' | 'BadEvent';
   }
 
-  /** @name PalletMaintenanceError (481) */
+  /** @name PalletMaintenanceError (480) */
   type PalletMaintenanceError = Null;
 
-  /** @name PalletTestUtilsError (482) */
+  /** @name PalletTestUtilsError (481) */
   interface PalletTestUtilsError extends Enum {
     readonly isTestPalletDisabled: boolean;
     readonly isTriggerRollback: boolean;
     readonly type: 'TestPalletDisabled' | 'TriggerRollback';
   }
 
-  /** @name SpRuntimeMultiSignature (484) */
+  /** @name SpRuntimeMultiSignature (483) */
   interface SpRuntimeMultiSignature extends Enum {
     readonly isEd25519: boolean;
     readonly asEd25519: SpCoreEd25519Signature;
@@ -3924,40 +3920,40 @@
     readonly type: 'Ed25519' | 'Sr25519' | 'Ecdsa';
   }
 
-  /** @name SpCoreEd25519Signature (485) */
+  /** @name SpCoreEd25519Signature (484) */
   interface SpCoreEd25519Signature extends U8aFixed {}
 
-  /** @name SpCoreSr25519Signature (487) */
+  /** @name SpCoreSr25519Signature (486) */
   interface SpCoreSr25519Signature extends U8aFixed {}
 
-  /** @name SpCoreEcdsaSignature (488) */
+  /** @name SpCoreEcdsaSignature (487) */
   interface SpCoreEcdsaSignature extends U8aFixed {}
 
-  /** @name FrameSystemExtensionsCheckSpecVersion (491) */
+  /** @name FrameSystemExtensionsCheckSpecVersion (490) */
   type FrameSystemExtensionsCheckSpecVersion = Null;
 
-  /** @name FrameSystemExtensionsCheckTxVersion (492) */
+  /** @name FrameSystemExtensionsCheckTxVersion (491) */
   type FrameSystemExtensionsCheckTxVersion = Null;
 
-  /** @name FrameSystemExtensionsCheckGenesis (493) */
+  /** @name FrameSystemExtensionsCheckGenesis (492) */
   type FrameSystemExtensionsCheckGenesis = Null;
 
-  /** @name FrameSystemExtensionsCheckNonce (496) */
+  /** @name FrameSystemExtensionsCheckNonce (495) */
   interface FrameSystemExtensionsCheckNonce extends Compact<u32> {}
 
-  /** @name FrameSystemExtensionsCheckWeight (497) */
+  /** @name FrameSystemExtensionsCheckWeight (496) */
   type FrameSystemExtensionsCheckWeight = Null;
 
-  /** @name OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance (498) */
+  /** @name OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance (497) */
   type OpalRuntimeRuntimeCommonMaintenanceCheckMaintenance = Null;
 
-  /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (499) */
+  /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (498) */
   interface PalletTemplateTransactionPaymentChargeTransactionPayment extends Compact<u128> {}
 
-  /** @name OpalRuntimeRuntime (500) */
+  /** @name OpalRuntimeRuntime (499) */
   type OpalRuntimeRuntime = Null;
 
-  /** @name PalletEthereumFakeTransactionFinalizer (501) */
+  /** @name PalletEthereumFakeTransactionFinalizer (500) */
   type PalletEthereumFakeTransactionFinalizer = Null;
 
 } // declare module
modifiedtests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth
--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -51,7 +51,7 @@
     const adminListBeforeAddAdmin = await collection.getAdmins();
     expect(adminListBeforeAddAdmin).to.have.lengthOf(0);
 
-    await expect(collection.removeAdmin(alice, {Substrate: alice.address})).to.be.rejectedWith('common.UserIsNotAdmin');
+    await expect(collection.removeAdmin(alice, {Substrate: alice.address})).to.be.rejectedWith('common.UserIsNotCollectionAdmin');
   });
 });
 
modifiedtests/src/removeCollectionSponsor.test.tsdiffbeforeafterboth
--- a/tests/src/removeCollectionSponsor.test.ts
+++ b/tests/src/removeCollectionSponsor.test.ts
@@ -21,11 +21,12 @@
   let donor: IKeyringPair;
   let alice: IKeyringPair;
   let bob: IKeyringPair;
+  let charlie: IKeyringPair;
 
   before(async () => {
     await usingPlaygrounds(async (helper, privateKey) => {
       donor = await privateKey({filename: __filename});
-      [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
+      [alice, bob, charlie] = await helper.arrange.createAccounts([20n, 10n, 10n], donor);
     });
   });
 
@@ -69,6 +70,12 @@
     await expect(collection.removeSponsor(alice)).to.not.be.rejected;
   });
 
+  itSub('Remove sponsor for a collection with collection admin permissions', async ({helper}) => {
+    const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-1', tokenPrefix: 'RCS'});
+    await collection.setSponsor(alice, bob.address);
+    await collection.addAdmin(alice, {Substrate: charlie.address});
+    await expect(collection.removeSponsor(charlie)).not.to.be.rejected;
+  });
 });
 
 describe('(!negative test!) integration test: ext. removeCollectionSponsor():', () => {
@@ -86,13 +93,6 @@
   itSub('(!negative test!) Remove sponsor for a collection that never existed', async ({helper}) => {
     const collectionId = (1 << 32) - 1;
     await expect(helper.collection.removeSponsor(alice, collectionId)).to.be.rejectedWith(/common\.CollectionNotFound/);
-  });
-
-  itSub('(!negative test!) Remove sponsor for a collection with collection admin permissions', async ({helper}) => {
-    const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-1', tokenPrefix: 'RCS'});
-    await collection.setSponsor(alice, bob.address);
-    await collection.addAdmin(alice, {Substrate: charlie.address});
-    await expect(collection.removeSponsor(charlie)).to.be.rejectedWith(/common\.NoPermission/);
   });
 
   itSub('(!negative test!) Remove sponsor for a collection by regular user', async ({helper}) => {
@@ -112,7 +112,7 @@
     const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-4', tokenPrefix: 'RCS'});
     await collection.setSponsor(alice, bob.address);
     await collection.removeSponsor(alice);
-    await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
+    await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/common\.ConfirmSponsorshipFail/);
   });
 
   itSub('Set - confirm - remove - confirm: Sponsor cannot come back', async ({helper}) => {
@@ -120,6 +120,6 @@
     await collection.setSponsor(alice, bob.address);
     await collection.confirmSponsorship(bob);
     await collection.removeSponsor(alice);
-    await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/common\.ConfirmUnsetSponsorFail/);
+    await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/common\.ConfirmSponsorshipFail/);
   });
 });
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -933,7 +933,7 @@
       true,
     );
 
-    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionOwnedChanged');
+    return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionOwnerChanged');
   }
 
   /**