git.delta.rocks / unique-network / refs/commits / 415353264b69

difftreelog

style reformat code

Yaroslav Bolyukin2022-05-30parent: #d048005.patch.diff
in: master

19 files changed

modifiedclient/rpc/src/lib.rsdiffbeforeafterboth
--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -30,8 +30,7 @@
 // RMRK
 use rmrk_rpc::RmrkApi as RmrkRuntimeApi;
 use up_data_structs::{
-	RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName,
-	RmrkResourceId,
+	RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName, RmrkResourceId,
 };
 
 pub use rmrk_unique_rpc::RmrkApi;
modifiednode/cli/src/service.rsdiffbeforeafterboth
--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -364,7 +364,8 @@
 			RmrkBaseInfo<AccountId>,
 			RmrkPartType,
 			RmrkTheme,
-		>*/ + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+		>*/
+		+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
 		+ sp_api::Metadata<Block>
 		+ sp_offchain::OffchainWorkerApi<Block>
 		+ cumulus_primitives_core::CollectCollationInfo<Block>,
@@ -656,7 +657,8 @@
 			RmrkBaseInfo<AccountId>,
 			RmrkPartType,
 			RmrkTheme,
-		>*/ + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+		>*/
+		+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
 		+ sp_api::Metadata<Block>
 		+ sp_offchain::OffchainWorkerApi<Block>
 		+ cumulus_primitives_core::CollectCollationInfo<Block>
@@ -800,7 +802,8 @@
 			RmrkBaseInfo<AccountId>,
 			RmrkPartType,
 			RmrkTheme,
-		>*/ + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+		>*/
+		+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
 		+ sp_api::Metadata<Block>
 		+ sp_offchain::OffchainWorkerApi<Block>
 		+ cumulus_primitives_core::CollectCollationInfo<Block>
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#![cfg_attr(not(feature = "std"), no_std)]1819extern crate alloc;2021use core::ops::{Deref, DerefMut};22use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};23use sp_std::vec::Vec;24use pallet_evm::account::CrossAccountId;25use frame_support::{26	dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, Weight, PostDispatchInfo},27	ensure,28	traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement},29	BoundedVec,30	weights::Pays,31	transactional,32};33use pallet_evm::GasWeightMapping;34use up_data_structs::{35	COLLECTION_NUMBER_LIMIT,36	Collection,37	RpcCollection,38	CollectionId,39	CreateItemData,40	MAX_TOKEN_PREFIX_LENGTH,41	COLLECTION_ADMINS_LIMIT,42	TokenId,43	CollectionStats,44	MAX_TOKEN_OWNERSHIP,45	CollectionMode,46	NFT_SPONSOR_TRANSFER_TIMEOUT,47	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,48	REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,49	MAX_SPONSOR_TIMEOUT,50	CUSTOM_DATA_LIMIT,51	CollectionLimits,52	CreateCollectionData,53	SponsorshipState,54	CreateItemExData,55	SponsoringRateLimit,56	budget::Budget,57	COLLECTION_FIELD_LIMIT,58	PhantomType,59	Property,60	Properties,61	PropertiesPermissionMap,62	PropertyKey,63	PropertyValue,64	PropertyPermission,65	PropertiesError,66	PropertyKeyPermission,67	TokenData,68	TrySetProperty,69	PropertyScope,70	// RMRK71	RmrkCollectionInfo,72	RmrkInstanceInfo,73	RmrkResourceInfo,74	RmrkPropertyInfo,75	RmrkBaseInfo,76	RmrkPartType,77	RmrkTheme,78	RmrkNftChild,79	CollectionPermissions,80	SchemaVersion,81};8283pub use pallet::*;84use sp_core::H160;85use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};86#[cfg(feature = "runtime-benchmarks")]87pub mod benchmarking;88pub mod dispatch;89pub mod erc;90pub mod eth;91pub mod weights;9293pub type SelfWeightOf<T> = <T as Config>::WeightInfo;9495#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]96pub struct CollectionHandle<T: Config> {97	pub id: CollectionId,98	collection: Collection<T::AccountId>,99	pub recorder: SubstrateRecorder<T>,100}101impl<T: Config> WithRecorder<T> for CollectionHandle<T> {102	fn recorder(&self) -> &SubstrateRecorder<T> {103		&self.recorder104	}105	fn into_recorder(self) -> SubstrateRecorder<T> {106		self.recorder107	}108}109impl<T: Config> CollectionHandle<T> {110	pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {111		<CollectionById<T>>::get(id).map(|collection| Self {112			id,113			collection,114			recorder: SubstrateRecorder::new(gas_limit),115		})116	}117118	pub fn new_with_recorder(id: CollectionId, recorder: SubstrateRecorder<T>) -> Option<Self> {119		<CollectionById<T>>::get(id).map(|collection| Self {120			id,121			collection,122			recorder,123		})124	}125126	pub fn new(id: CollectionId) -> Option<Self> {127		Self::new_with_gas_limit(id, u64::MAX)128	}129	pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {130		Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)131	}132	pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {133		self.recorder134			.consume_gas(T::GasWeightMapping::weight_to_gas(135				<T as frame_system::Config>::DbWeight::get()136					.read137					.saturating_mul(reads),138			))139	}140	pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {141		self.recorder142			.consume_gas(T::GasWeightMapping::weight_to_gas(143				<T as frame_system::Config>::DbWeight::get()144					.write145					.saturating_mul(writes),146			))147	}148	pub fn save(self) -> DispatchResult {149		<CollectionById<T>>::insert(self.id, self.collection);150		Ok(())151	}152153	pub fn set_sponsor(&mut self, sponsor: T::AccountId) {154		self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor);155	}156157	pub fn confirm_sponsorship(&mut self, sender: &T::AccountId) -> bool {158		if self.collection.sponsorship.pending_sponsor() != Some(sender) {159			return false;160		};161162		self.collection.sponsorship = SponsorshipState::Confirmed(sender.clone());163		true164	}165}166impl<T: Config> Deref for CollectionHandle<T> {167	type Target = Collection<T::AccountId>;168169	fn deref(&self) -> &Self::Target {170		&self.collection171	}172}173174impl<T: Config> DerefMut for CollectionHandle<T> {175	fn deref_mut(&mut self) -> &mut Self::Target {176		&mut self.collection177	}178}179180impl<T: Config> CollectionHandle<T> {181	pub fn check_is_owner(&self, subject: &T::CrossAccountId) -> DispatchResult {182		ensure!(*subject.as_sub() == self.owner, <Error<T>>::NoPermission);183		Ok(())184	}185	pub fn is_owner_or_admin(&self, subject: &T::CrossAccountId) -> bool {186		*subject.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, subject))187	}188	pub fn check_is_owner_or_admin(&self, subject: &T::CrossAccountId) -> DispatchResult {189		ensure!(self.is_owner_or_admin(subject), <Error<T>>::NoPermission);190		Ok(())191	}192	pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {193		self.limits.owner_can_transfer() && self.is_owner_or_admin(user)194	}195	pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> bool {196		self.limits.owner_can_transfer() && self.is_owner_or_admin(user)197	}198	pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {199		ensure!(200			<Allowlist<T>>::get((self.id, user)),201			<Error<T>>::AddressNotInAllowlist202		);203		Ok(())204	}205}206207#[frame_support::pallet]208pub mod pallet {209	use super::*;210	use pallet_evm::account;211	use dispatch::CollectionDispatch;212	use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key, traits::StorageVersion};213	use frame_system::pallet_prelude::*;214	use frame_support::traits::Currency;215	use up_data_structs::{TokenId, mapping::TokenAddressMapping};216	use scale_info::TypeInfo;217	use weights::WeightInfo;218219	#[pallet::config]220	pub trait Config:221		frame_system::Config + pallet_evm_coder_substrate::Config + TypeInfo + account::Config222	{223		type WeightInfo: WeightInfo;224		type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;225226		type Currency: Currency<Self::AccountId>;227228		#[pallet::constant]229		type CollectionCreationPrice: Get<230			<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,231		>;232		type CollectionDispatch: CollectionDispatch<Self>;233234		type TreasuryAccountId: Get<Self::AccountId>;235236		type EvmTokenAddressMapping: TokenAddressMapping<H160>;237		type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;238	}239240	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);241242	#[pallet::pallet]243	#[pallet::storage_version(STORAGE_VERSION)]244	#[pallet::generate_store(pub(super) trait Store)]245	pub struct Pallet<T>(_);246247	#[pallet::extra_constants]248	impl<T: Config> Pallet<T> {249		pub fn collection_admins_limit() -> u32 {250			COLLECTION_ADMINS_LIMIT251		}252	}253254	#[pallet::event]255	#[pallet::generate_deposit(pub fn deposit_event)]256	pub enum Event<T: Config> {257		/// New collection was created258		///259		/// # Arguments260		///261		/// * collection_id: Globally unique identifier of newly created collection.262		///263		/// * mode: [CollectionMode] converted into u8.264		///265		/// * account_id: Collection owner.266		CollectionCreated(CollectionId, u8, T::AccountId),267268		/// New collection was destroyed269		///270		/// # Arguments271		///272		/// * collection_id: Globally unique identifier of collection.273		CollectionDestroyed(CollectionId),274275		/// New item was created.276		///277		/// # Arguments278		///279		/// * collection_id: Id of the collection where item was created.280		///281		/// * item_id: Id of an item. Unique within the collection.282		///283		/// * recipient: Owner of newly created item284		///285		/// * amount: Always 1 for NFT286		ItemCreated(CollectionId, TokenId, T::CrossAccountId, u128),287288		/// Collection item was burned.289		///290		/// # Arguments291		///292		/// * collection_id.293		///294		/// * item_id: Identifier of burned NFT.295		///296		/// * owner: which user has destroyed its tokens297		///298		/// * amount: Always 1 for NFT299		ItemDestroyed(CollectionId, TokenId, T::CrossAccountId, u128),300301		/// Item was transferred302		///303		/// * collection_id: Id of collection to which item is belong304		///305		/// * item_id: Id of an item306		///307		/// * sender: Original owner of item308		///309		/// * recipient: New owner of item310		///311		/// * amount: Always 1 for NFT312		Transfer(313			CollectionId,314			TokenId,315			T::CrossAccountId,316			T::CrossAccountId,317			u128,318		),319320		/// * collection_id321		///322		/// * item_id323		///324		/// * sender325		///326		/// * spender327		///328		/// * amount329		Approved(330			CollectionId,331			TokenId,332			T::CrossAccountId,333			T::CrossAccountId,334			u128,335		),336337		CollectionPropertySet(CollectionId, PropertyKey),338339		CollectionPropertyDeleted(CollectionId, PropertyKey),340341		TokenPropertySet(CollectionId, TokenId, PropertyKey),342343		TokenPropertyDeleted(CollectionId, TokenId, PropertyKey),344345		PropertyPermissionSet(CollectionId, PropertyKey),346	}347348	#[pallet::error]349	pub enum Error<T> {350		/// This collection does not exist.351		CollectionNotFound,352		/// Sender parameter and item owner must be equal.353		MustBeTokenOwner,354		/// No permission to perform action355		NoPermission,356		/// Destroying only empty collections is allowed357		CantDestroyNotEmptyCollection,358		/// Collection is not in mint mode.359		PublicMintingNotAllowed,360		/// Address is not in allow list.361		AddressNotInAllowlist,362363		/// Collection name can not be longer than 63 char.364		CollectionNameLimitExceeded,365		/// Collection description can not be longer than 255 char.366		CollectionDescriptionLimitExceeded,367		/// Token prefix can not be longer than 15 char.368		CollectionTokenPrefixLimitExceeded,369		/// Total collections bound exceeded.370		TotalCollectionsLimitExceeded,371		/// Exceeded max admin count372		CollectionAdminCountExceeded,373		/// Collection limit bounds per collection exceeded374		CollectionLimitBoundsExceeded,375		/// Tried to enable permissions which are only permitted to be disabled376		OwnerPermissionsCantBeReverted,377		/// Collection settings not allowing items transferring378		TransferNotAllowed,379		/// Account token limit exceeded per collection380		AccountTokenLimitExceeded,381		/// Collection token limit exceeded382		CollectionTokenLimitExceeded,383		/// Metadata flag frozen384		MetadataFlagFrozen,385386		/// Item not exists.387		TokenNotFound,388		/// Item balance not enough.389		TokenValueTooLow,390		/// Requested value more than approved.391		ApprovedValueTooLow,392		/// Tried to approve more than owned393		CantApproveMoreThanOwned,394395		/// Can't transfer tokens to ethereum zero address396		AddressIsZero,397		/// Target collection doesn't supports this operation398		UnsupportedOperation,399400		/// Not sufficient founds to perform action401		NotSufficientFounds,402403		/// Collection has nesting disabled404		NestingIsDisabled,405		/// Only owner may nest tokens under this collection406		OnlyOwnerAllowedToNest,407		/// Only tokens from specific collections may nest tokens under this408		SourceCollectionIsNotAllowedToNest,409410		/// Tried to store more data than allowed in collection field411		CollectionFieldSizeExceeded,412413		/// Tried to store more property data than allowed414		NoSpaceForProperty,415416		/// Tried to store more property keys than allowed417		PropertyLimitReached,418419		/// Property key is too long420		PropertyKeyIsTooLong,421422		/// Only ASCII letters, digits, and '_', '-' are allowed423		InvalidCharacterInPropertyKey,424425		/// Empty property keys are forbidden426		EmptyPropertyKey,427	}428429	#[pallet::storage]430	pub type CreatedCollectionCount<T> = StorageValue<Value = CollectionId, QueryKind = ValueQuery>;431	#[pallet::storage]432	pub type DestroyedCollectionCount<T> =433		StorageValue<Value = CollectionId, QueryKind = ValueQuery>;434435	/// Collection info436	#[pallet::storage]437	pub type CollectionById<T> = StorageMap<438		Hasher = Blake2_128Concat,439		Key = CollectionId,440		Value = Collection<<T as frame_system::Config>::AccountId>,441		QueryKind = OptionQuery,442	>;443444	/// Collection properties445	#[pallet::storage]446	#[pallet::getter(fn collection_properties)]447	pub type CollectionProperties<T> = StorageMap<448		Hasher = Blake2_128Concat,449		Key = CollectionId,450		Value = Properties,451		QueryKind = ValueQuery,452		OnEmpty = up_data_structs::CollectionProperties,453	>;454455	#[pallet::storage]456	#[pallet::getter(fn property_permissions)]457	pub type CollectionPropertyPermissions<T> = StorageMap<458		Hasher = Blake2_128Concat,459		Key = CollectionId,460		Value = PropertiesPermissionMap,461		QueryKind = ValueQuery,462	>;463464	#[pallet::storage]465	pub type AdminAmount<T> = StorageMap<466		Hasher = Blake2_128Concat,467		Key = CollectionId,468		Value = u32,469		QueryKind = ValueQuery,470	>;471472	/// List of collection admins473	#[pallet::storage]474	pub type IsAdmin<T: Config> = StorageNMap<475		Key = (476			Key<Blake2_128Concat, CollectionId>,477			Key<Blake2_128Concat, T::CrossAccountId>,478		),479		Value = bool,480		QueryKind = ValueQuery,481	>;482483	/// Allowlisted collection users484	#[pallet::storage]485	pub type Allowlist<T: Config> = StorageNMap<486		Key = (487			Key<Blake2_128Concat, CollectionId>,488			Key<Blake2_128Concat, T::CrossAccountId>,489		),490		Value = bool,491		QueryKind = ValueQuery,492	>;493494	/// Not used by code, exists only to provide some types to metadata495	#[pallet::storage]496	pub type DummyStorageValue<T: Config> = StorageValue<497		Value = (498			CollectionStats,499			CollectionId,500			TokenId,501			PhantomType<(502				TokenData<T::CrossAccountId>,503				RpcCollection<T::AccountId>,504505				// RMRK506				RmrkCollectionInfo<T::AccountId>,507				RmrkInstanceInfo<T::AccountId>,508				RmrkResourceInfo,509				RmrkPropertyInfo,510				RmrkBaseInfo<T::AccountId>,511				RmrkPartType,512				RmrkTheme,513				RmrkNftChild,514			)>,515		),516		QueryKind = OptionQuery,517	>;518519	#[pallet::hooks]520	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {521		fn on_runtime_upgrade() -> Weight {522			if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {523				use up_data_structs::{CollectionVersion1, CollectionVersion2};524				<CollectionById<T>>::translate::<CollectionVersion1<T::AccountId>, _>(|id, v| {525					let mut props = Vec::new();526					if !v.offchain_schema.is_empty() {527						props.push(Property {528							key: b"_old_offchainSchema".to_vec().try_into().unwrap(),529							value: v.offchain_schema.clone().into_inner().try_into().expect("offchain schema too big"),530						});531					}532					if !v.variable_on_chain_schema.is_empty() {533						props.push(Property {534							key: b"_old_variableOnChainSchema".to_vec().try_into().unwrap(),535							value: v.variable_on_chain_schema.clone().into_inner().try_into().expect("offchain schema too big"),536						});537					}538					if !v.const_on_chain_schema.is_empty() {539						props.push(Property {540							key: b"_old_constOnChainSchema".to_vec().try_into().unwrap(),541							value: v.const_on_chain_schema.clone().into_inner().try_into().expect("offchain schema too big"),542						});543					}544					props.push(Property {545						key: b"_old_schemaVersion".to_vec().try_into().unwrap(),546						value: match v.schema_version {547							SchemaVersion::ImageURL => b"ImageUrl".as_slice(),548							SchemaVersion::Unique => b"Unique".as_slice(),549						}.to_vec().try_into().unwrap(),550					});551					Self::set_scoped_collection_properties(552						id,553						PropertyScope::None,554						props.into_iter(),555					).expect("existing data larger than properties");556					let mut new = CollectionVersion2::from(v.clone());557					new.permissions.access = Some(v.access);558					new.permissions.mint_mode = Some(v.mint_mode);559					Some(new)560				});561			}562563			0564		}565	}566}567568impl<T: Config> Pallet<T> {569	/// Ethereum receiver 0x0000000000000000000000000000000000000000 is reserved, and shouldn't own tokens570	pub fn ensure_correct_receiver(receiver: &T::CrossAccountId) -> DispatchResult {571		ensure!(572			&T::CrossAccountId::from_eth(H160([0; 20])) != receiver,573			<Error<T>>::AddressIsZero574		);575		Ok(())576	}577	pub fn adminlist(collection: CollectionId) -> Vec<T::CrossAccountId> {578		<IsAdmin<T>>::iter_prefix((collection,))579			.map(|(a, _)| a)580			.collect()581	}582	pub fn allowlist(collection: CollectionId) -> Vec<T::CrossAccountId> {583		<Allowlist<T>>::iter_prefix((collection,))584			.map(|(a, _)| a)585			.collect()586	}587	pub fn allowed(collection: CollectionId, user: T::CrossAccountId) -> bool {588		<Allowlist<T>>::get((collection, user))589	}590	pub fn collection_stats() -> CollectionStats {591		let created = <CreatedCollectionCount<T>>::get();592		let destroyed = <DestroyedCollectionCount<T>>::get();593		CollectionStats {594			created: created.0,595			destroyed: destroyed.0,596			alive: created.0 - destroyed.0,597		}598	}599600	pub fn effective_collection_limits(collection: CollectionId) -> Option<CollectionLimits> {601		let collection = <CollectionById<T>>::get(collection);602		if collection.is_none() {603			return None;604		}605606		let collection = collection.unwrap();607		let limits = collection.limits;608		let effective_limits = CollectionLimits {609			account_token_ownership_limit: Some(limits.account_token_ownership_limit()),610			sponsored_data_size: Some(limits.sponsored_data_size()),611			sponsored_data_rate_limit: Some(612				limits613					.sponsored_data_rate_limit614					.unwrap_or(SponsoringRateLimit::SponsoringDisabled),615			),616			token_limit: Some(limits.token_limit()),617			sponsor_transfer_timeout: Some(limits.sponsor_transfer_timeout(618				match collection.mode {619					CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,620					CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,621					CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,622				},623			)),624			sponsor_approve_timeout: Some(limits.sponsor_approve_timeout()),625			owner_can_transfer: Some(limits.owner_can_transfer()),626			owner_can_destroy: Some(limits.owner_can_destroy()),627			transfers_enabled: Some(limits.transfers_enabled()),628		};629630		Some(effective_limits)631	}632633	pub fn rpc_collection(collection: CollectionId) -> Option<RpcCollection<T::AccountId>> {634		let Collection {635			name,636			description,637			owner,638			mode,639			token_prefix,640			sponsorship,641			limits,642			permissions,643		} = <CollectionById<T>>::get(collection)?;644645		let token_property_permissions = <CollectionPropertyPermissions<T>>::get(collection)646			.into_iter()647			.map(|(key, permission)| PropertyKeyPermission {648				key,649				permission,650			})651			.collect();652653		let properties = <CollectionProperties<T>>::get(collection)654			.into_iter()655			.map(|(key, value)| Property {656				key,657				value,658			})659			.collect();660661		let permissions = CollectionPermissions {662			access: Some(permissions.access()),663			mint_mode: Some(permissions.mint_mode()),664			nesting: Some(permissions.nesting().clone()),665		};666667		Some(RpcCollection {668			name: name.into_inner(),669			description: description.into_inner(),670			owner,671			mode,672			token_prefix: token_prefix.into_inner(),673			sponsorship,674			limits,675			permissions,676			token_property_permissions,677			properties,678		})679	}680}681682macro_rules! limit_default {683	($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{684		$(685			if let Some($new) = $new.$field {686				let $old = $old.$field($($arg)?);687				let _ = $new;688				let _ = $old;689				$check690			} else {691				$new.$field = $old.$field692			}693		)*694	}};695}696macro_rules! limit_default_clone {697	($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{698		$(699			if let Some($new) = $new.$field.clone() {700				let $old = $old.$field($($arg)?);701				let _ = $new;702				let _ = $old;703				$check704			} else {705				$new.$field = $old.$field.clone()706			}707		)*708	}};709}710711impl<T: Config> Pallet<T> {712	pub fn init_collection(713		owner: T::AccountId,714		data: CreateCollectionData<T::AccountId>,715	) -> Result<CollectionId, DispatchError> {716		{717			ensure!(718				data.token_prefix.len() <= MAX_TOKEN_PREFIX_LENGTH as usize,719				Error::<T>::CollectionTokenPrefixLimitExceeded720			);721		}722723		let created_count = <CreatedCollectionCount<T>>::get()724			.0725			.checked_add(1)726			.ok_or(ArithmeticError::Overflow)?;727		let destroyed_count = <DestroyedCollectionCount<T>>::get().0;728		let id = CollectionId(created_count);729730		// bound Total number of collections731		ensure!(732			created_count - destroyed_count <= COLLECTION_NUMBER_LIMIT,733			<Error<T>>::TotalCollectionsLimitExceeded734		);735736		// =========737738		let collection = Collection {739			owner: owner.clone(),740			name: data.name,741			mode: data.mode.clone(),742			description: data.description,743			token_prefix: data.token_prefix,744			sponsorship: data745				.pending_sponsor746				.map(SponsorshipState::Unconfirmed)747				.unwrap_or_default(),748			limits: data749				.limits750				.map(|limits| Self::clamp_limits(data.mode.clone(), &Default::default(), limits))751				.unwrap_or_else(|| Ok(CollectionLimits::default()))?,752			permissions: data753				.permissions754				.map(|permissions| Self::clamp_permissions(data.mode.clone(), &Default::default(), permissions))755				.unwrap_or_else(|| Ok(CollectionPermissions::default()))?,756		};757758		let mut collection_properties = up_data_structs::CollectionProperties::get();759		collection_properties760			.try_set_from_iter(data.properties.into_iter())761			.map_err(<Error<T>>::from)?;762763		CollectionProperties::<T>::insert(id, collection_properties);764765		let mut token_props_permissions = PropertiesPermissionMap::new();766		token_props_permissions767			.try_set_from_iter(data.token_property_permissions.into_iter())768			.map_err(<Error<T>>::from)?;769770		CollectionPropertyPermissions::<T>::insert(id, token_props_permissions);771772		// Take a (non-refundable) deposit of collection creation773		{774			let mut imbalance =775				<<<T as Config>::Currency as Currency<T::AccountId>>::PositiveImbalance>::zero();776			imbalance.subsume(777				<<T as Config>::Currency as Currency<T::AccountId>>::deposit_creating(778					&T::TreasuryAccountId::get(),779					T::CollectionCreationPrice::get(),780				),781			);782			<T as Config>::Currency::settle(783				&owner,784				imbalance,785				WithdrawReasons::TRANSFER,786				ExistenceRequirement::KeepAlive,787			)788			.map_err(|_| Error::<T>::NotSufficientFounds)?;789		}790791		<CreatedCollectionCount<T>>::put(created_count);792		<Pallet<T>>::deposit_event(Event::CollectionCreated(id, data.mode.id(), owner.clone()));793		<CollectionById<T>>::insert(id, collection);794		Ok(id)795	}796797	pub fn destroy_collection(798		collection: CollectionHandle<T>,799		sender: &T::CrossAccountId,800	) -> DispatchResult {801		ensure!(802			collection.limits.owner_can_destroy(),803			<Error<T>>::NoPermission,804		);805		collection.check_is_owner(sender)?;806807		let destroyed_collections = <DestroyedCollectionCount<T>>::get()808			.0809			.checked_add(1)810			.ok_or(ArithmeticError::Overflow)?;811812		// =========813814		<DestroyedCollectionCount<T>>::put(destroyed_collections);815		<CollectionById<T>>::remove(collection.id);816		<AdminAmount<T>>::remove(collection.id);817		<IsAdmin<T>>::remove_prefix((collection.id,), None);818		<Allowlist<T>>::remove_prefix((collection.id,), None);819		<CollectionProperties<T>>::remove(collection.id);820821		<Pallet<T>>::deposit_event(Event::CollectionDestroyed(collection.id));822		Ok(())823	}824825	pub fn set_collection_property(826		collection: &CollectionHandle<T>,827		sender: &T::CrossAccountId,828		property: Property,829	) -> DispatchResult {830		collection.check_is_owner_or_admin(sender)?;831832		CollectionProperties::<T>::try_mutate(collection.id, |properties| {833			let property = property.clone();834			properties.try_set(property.key, property.value)835		})836		.map_err(<Error<T>>::from)?;837838		Self::deposit_event(Event::CollectionPropertySet(collection.id, property.key));839840		Ok(())841	}842843	pub fn set_scoped_collection_property(844		collection_id: CollectionId,845		scope: PropertyScope,846		property: Property,847	) -> DispatchResult {848		CollectionProperties::<T>::try_mutate(collection_id, |properties| {849			properties.try_scoped_set(scope, property.key, property.value)850		})851		.map_err(<Error<T>>::from)?;852853		Ok(())854	}855856	pub fn set_scoped_collection_properties(857		collection_id: CollectionId,858		scope: PropertyScope,859		properties: impl Iterator<Item = Property>,860	) -> DispatchResult {861		CollectionProperties::<T>::try_mutate(collection_id, |stored_properties| {862			stored_properties.try_scoped_set_from_iter(scope, properties)863		})864		.map_err(<Error<T>>::from)?;865866		Ok(())867	}868869	#[transactional]870	pub fn set_collection_properties(871		collection: &CollectionHandle<T>,872		sender: &T::CrossAccountId,873		properties: Vec<Property>,874	) -> DispatchResult {875		for property in properties {876			Self::set_collection_property(collection, sender, property)?;877		}878879		Ok(())880	}881882	pub fn delete_collection_property(883		collection: &CollectionHandle<T>,884		sender: &T::CrossAccountId,885		property_key: PropertyKey,886	) -> DispatchResult {887		collection.check_is_owner_or_admin(sender)?;888889		CollectionProperties::<T>::try_mutate(collection.id, |properties| {890			properties.remove(&property_key)891		})892		.map_err(<Error<T>>::from)?;893894		Self::deposit_event(Event::CollectionPropertyDeleted(895			collection.id,896			property_key,897		));898899		Ok(())900	}901902	#[transactional]903	pub fn delete_collection_properties(904		collection: &CollectionHandle<T>,905		sender: &T::CrossAccountId,906		property_keys: Vec<PropertyKey>,907	) -> DispatchResult {908		for key in property_keys {909			Self::delete_collection_property(collection, sender, key)?;910		}911912		Ok(())913	}914915	// For migrations916	pub fn set_property_permission_unchecked(917		collection: CollectionId,918		property_permission: PropertyKeyPermission,919	) -> DispatchResult {920		<CollectionPropertyPermissions<T>>::try_mutate(collection, |permissions| {921			permissions.try_set(property_permission.key, property_permission.permission)922		})923		.map_err(<Error<T>>::from)?;924		Ok(())925	}926927	pub fn set_property_permission(928		collection: &CollectionHandle<T>,929		sender: &T::CrossAccountId,930		property_permission: PropertyKeyPermission,931	) -> DispatchResult {932		collection.check_is_owner_or_admin(sender)?;933934		let all_permissions = CollectionPropertyPermissions::<T>::get(collection.id);935		let current_permission = all_permissions.get(&property_permission.key);936		if matches![937			current_permission,938			Some(PropertyPermission { mutable: false, .. })939		] {940			return Err(<Error<T>>::NoPermission.into());941		}942943		CollectionPropertyPermissions::<T>::try_mutate(collection.id, |permissions| {944			let property_permission = property_permission.clone();945			permissions.try_set(property_permission.key, property_permission.permission)946		})947		.map_err(<Error<T>>::from)?;948949		Self::deposit_event(Event::PropertyPermissionSet(950			collection.id,951			property_permission.key,952		));953954		Ok(())955	}956957	#[transactional]958	pub fn set_property_permissions(959		collection: &CollectionHandle<T>,960		sender: &T::CrossAccountId,961		property_permissions: Vec<PropertyKeyPermission>,962	) -> DispatchResult {963		for prop_pemission in property_permissions {964			Self::set_property_permission(collection, sender, prop_pemission)?;965		}966967		Ok(())968	}969970	pub fn get_collection_property(971		collection_id: CollectionId,972		key: &PropertyKey,973	) -> Option<PropertyValue> {974		Self::collection_properties(collection_id).get(key).cloned()975	}976977	pub fn bytes_keys_to_property_keys(978		keys: Vec<Vec<u8>>,979	) -> Result<Vec<PropertyKey>, DispatchError> {980		keys.into_iter()981			.map(|key| -> Result<PropertyKey, DispatchError> {982				key.try_into()983					.map_err(|_| <Error<T>>::PropertyKeyIsTooLong.into())984			})985			.collect::<Result<Vec<PropertyKey>, DispatchError>>()986	}987988	pub fn filter_collection_properties(989		collection_id: CollectionId,990		keys: Option<Vec<PropertyKey>>,991	) -> Result<Vec<Property>, DispatchError> {992		let properties = Self::collection_properties(collection_id);993994		let properties = keys995			.map(|keys| {996				keys.into_iter()997					.filter_map(|key| {998						properties.get(&key).map(|value| Property {999							key,1000							value: value.clone(),1001						})1002					})1003					.collect()1004			})1005			.unwrap_or_else(|| {1006				properties1007					.into_iter()1008					.map(|(key, value)| Property {1009						key,1010						value,1011					})1012					.collect()1013			});10141015		Ok(properties)1016	}10171018	pub fn filter_property_permissions(1019		collection_id: CollectionId,1020		keys: Option<Vec<PropertyKey>>,1021	) -> Result<Vec<PropertyKeyPermission>, DispatchError> {1022		let permissions = Self::property_permissions(collection_id);10231024		let key_permissions = keys1025			.map(|keys| {1026				keys.into_iter()1027					.filter_map(|key| {1028						permissions1029							.get(&key)1030							.map(|permission| PropertyKeyPermission {1031								key,1032								permission: permission.clone(),1033							})1034					})1035					.collect()1036			})1037			.unwrap_or_else(|| {1038				permissions1039					.into_iter()1040					.map(|(key, permission)| PropertyKeyPermission {1041						key,1042						permission,1043					})1044					.collect()1045			});10461047		Ok(key_permissions)1048	}10491050	pub fn toggle_allowlist(1051		collection: &CollectionHandle<T>,1052		sender: &T::CrossAccountId,1053		user: &T::CrossAccountId,1054		allowed: bool,1055	) -> DispatchResult {1056		collection.check_is_owner_or_admin(sender)?;10571058		// =========10591060		if allowed {1061			<Allowlist<T>>::insert((collection.id, user), true);1062		} else {1063			<Allowlist<T>>::remove((collection.id, user));1064		}10651066		Ok(())1067	}10681069	pub fn toggle_admin(1070		collection: &CollectionHandle<T>,1071		sender: &T::CrossAccountId,1072		user: &T::CrossAccountId,1073		admin: bool,1074	) -> DispatchResult {1075		collection.check_is_owner_or_admin(sender)?;10761077		let was_admin = <IsAdmin<T>>::get((collection.id, user));1078		if was_admin == admin {1079			return Ok(());1080		}1081		let amount = <AdminAmount<T>>::get(collection.id);10821083		if admin {1084			let amount = amount1085				.checked_add(1)1086				.ok_or(<Error<T>>::CollectionAdminCountExceeded)?;1087			ensure!(1088				amount <= Self::collection_admins_limit(),1089				<Error<T>>::CollectionAdminCountExceeded,1090			);10911092			// =========10931094			<AdminAmount<T>>::insert(collection.id, amount);1095			<IsAdmin<T>>::insert((collection.id, user), true);1096		} else {1097			<AdminAmount<T>>::insert(collection.id, amount.saturating_sub(1));1098			<IsAdmin<T>>::remove((collection.id, user));1099		}11001101		Ok(())1102	}11031104	pub fn clamp_limits(1105		mode: CollectionMode,1106		old_limit: &CollectionLimits,1107		mut new_limit: CollectionLimits,1108	) -> Result<CollectionLimits, DispatchError> {1109		limit_default!(old_limit, new_limit,1110			account_token_ownership_limit => ensure!(1111				new_limit <= MAX_TOKEN_OWNERSHIP,1112				<Error<T>>::CollectionLimitBoundsExceeded,1113			),1114			sponsored_data_size => ensure!(1115				new_limit <= CUSTOM_DATA_LIMIT,1116				<Error<T>>::CollectionLimitBoundsExceeded,1117			),11181119			sponsored_data_rate_limit => {},1120			token_limit => ensure!(1121				old_limit >= new_limit && new_limit > 0,1122				<Error<T>>::CollectionTokenLimitExceeded1123			),11241125			sponsor_transfer_timeout(match mode {1126				CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,1127				CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1128				CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1129			}) => ensure!(1130				new_limit <= MAX_SPONSOR_TIMEOUT,1131				<Error<T>>::CollectionLimitBoundsExceeded,1132			),1133			sponsor_approve_timeout => {},1134			owner_can_transfer => ensure!(1135				old_limit || !new_limit,1136				<Error<T>>::OwnerPermissionsCantBeReverted,1137			),1138			owner_can_destroy => ensure!(1139				old_limit || !new_limit,1140				<Error<T>>::OwnerPermissionsCantBeReverted,1141			),1142			transfers_enabled => {},1143		);1144		Ok(new_limit)1145	}1146	pub fn clamp_permissions(1147		mode: CollectionMode,1148		old_limit: &CollectionPermissions,1149		mut new_limit: CollectionPermissions,1150	) -> Result<CollectionPermissions, DispatchError> {1151		limit_default_clone!(old_limit, new_limit,1152			access => {},1153			mint_mode => {},1154			nesting => {},1155		);1156		Ok(new_limit)1157	}1158}11591160#[macro_export]1161macro_rules! unsupported {1162	() => {1163		Err(<Error<T>>::UnsupportedOperation.into())1164	};1165}11661167/// Worst cases1168pub trait CommonWeightInfo<CrossAccountId> {1169	fn create_item() -> Weight;1170	fn create_multiple_items(amount: &[CreateItemData]) -> Weight;1171	fn create_multiple_items_ex(cost: &CreateItemExData<CrossAccountId>) -> Weight;1172	fn burn_item() -> Weight;1173	fn set_collection_properties(amount: u32) -> Weight;1174	fn delete_collection_properties(amount: u32) -> Weight;1175	fn set_token_properties(amount: u32) -> Weight;1176	fn delete_token_properties(amount: u32) -> Weight;1177	fn set_property_permissions(amount: u32) -> Weight;1178	fn transfer() -> Weight;1179	fn approve() -> Weight;1180	fn transfer_from() -> Weight;1181	fn burn_from() -> Weight;1182}11831184pub trait CommonCollectionOperations<T: Config> {1185	fn create_item(1186		&self,1187		sender: T::CrossAccountId,1188		to: T::CrossAccountId,1189		data: CreateItemData,1190		nesting_budget: &dyn Budget,1191	) -> DispatchResultWithPostInfo;1192	fn create_multiple_items(1193		&self,1194		sender: T::CrossAccountId,1195		to: T::CrossAccountId,1196		data: Vec<CreateItemData>,1197		nesting_budget: &dyn Budget,1198	) -> DispatchResultWithPostInfo;1199	fn create_multiple_items_ex(1200		&self,1201		sender: T::CrossAccountId,1202		data: CreateItemExData<T::CrossAccountId>,1203		nesting_budget: &dyn Budget,1204	) -> DispatchResultWithPostInfo;1205	fn burn_item(1206		&self,1207		sender: T::CrossAccountId,1208		token: TokenId,1209		amount: u128,1210	) -> DispatchResultWithPostInfo;1211	fn set_collection_properties(1212		&self,1213		sender: T::CrossAccountId,1214		properties: Vec<Property>,1215	) -> DispatchResultWithPostInfo;1216	fn delete_collection_properties(1217		&self,1218		sender: &T::CrossAccountId,1219		property_keys: Vec<PropertyKey>,1220	) -> DispatchResultWithPostInfo;1221	fn set_token_properties(1222		&self,1223		sender: T::CrossAccountId,1224		token_id: TokenId,1225		property: Vec<Property>,1226	) -> DispatchResultWithPostInfo;1227	fn delete_token_properties(1228		&self,1229		sender: T::CrossAccountId,1230		token_id: TokenId,1231		property_keys: Vec<PropertyKey>,1232	) -> DispatchResultWithPostInfo;1233	fn set_property_permissions(1234		&self,1235		sender: &T::CrossAccountId,1236		property_permissions: Vec<PropertyKeyPermission>,1237	) -> DispatchResultWithPostInfo;1238	fn transfer(1239		&self,1240		sender: T::CrossAccountId,1241		to: T::CrossAccountId,1242		token: TokenId,1243		amount: u128,1244		nesting_budget: &dyn Budget,1245	) -> DispatchResultWithPostInfo;1246	fn approve(1247		&self,1248		sender: T::CrossAccountId,1249		spender: T::CrossAccountId,1250		token: TokenId,1251		amount: u128,1252	) -> DispatchResultWithPostInfo;1253	fn transfer_from(1254		&self,1255		sender: T::CrossAccountId,1256		from: T::CrossAccountId,1257		to: T::CrossAccountId,1258		token: TokenId,1259		amount: u128,1260		nesting_budget: &dyn Budget,1261	) -> DispatchResultWithPostInfo;1262	fn burn_from(1263		&self,1264		sender: T::CrossAccountId,1265		from: T::CrossAccountId,1266		token: TokenId,1267		amount: u128,1268		nesting_budget: &dyn Budget,1269	) -> DispatchResultWithPostInfo;12701271	fn check_nesting(1272		&self,1273		sender: T::CrossAccountId,1274		from: (CollectionId, TokenId),1275		under: TokenId,1276		budget: &dyn Budget,1277	) -> DispatchResult;12781279	fn nest(1280		&self,1281		under: TokenId,1282		to_nest: (CollectionId, TokenId)1283	);12841285	fn unnest(1286		&self,1287		under: TokenId,1288		to_nest: (CollectionId, TokenId)1289	);12901291	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;1292	fn collection_tokens(&self) -> Vec<TokenId>;1293	fn token_exists(&self, token: TokenId) -> bool;1294	fn last_token_id(&self) -> TokenId;12951296	fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;1297	fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue>;1298	fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property>;1299	/// Amount of unique collection tokens1300	fn total_supply(&self) -> u32;1301	/// Amount of different tokens account has (Applicable to nonfungible/refungible)1302	fn account_balance(&self, account: T::CrossAccountId) -> u32;1303	/// Amount of specific token account have (Applicable to fungible/refungible)1304	fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;1305	fn allowance(1306		&self,1307		sender: T::CrossAccountId,1308		spender: T::CrossAccountId,1309		token: TokenId,1310	) -> u128;1311}13121313// Flexible enough for implementing CommonCollectionOperations1314pub fn with_weight(res: DispatchResult, weight: Weight) -> DispatchResultWithPostInfo {1315	let post_info = PostDispatchInfo {1316		actual_weight: Some(weight),1317		pays_fee: Pays::Yes,1318	};1319	match res {1320		Ok(()) => Ok(post_info),1321		Err(error) => Err(DispatchErrorWithPostInfo { post_info, error }),1322	}1323}13241325impl<T: Config> From<PropertiesError> for Error<T> {1326	fn from(error: PropertiesError) -> Self {1327		match error {1328			PropertiesError::NoSpaceForProperty => Self::NoSpaceForProperty,1329			PropertiesError::PropertyLimitReached => Self::PropertyLimitReached,1330			PropertiesError::InvalidCharacterInPropertyKey => Self::InvalidCharacterInPropertyKey,1331			PropertiesError::PropertyKeyIsTooLong => Self::PropertyKeyIsTooLong,1332			PropertiesError::EmptyPropertyKey => Self::EmptyPropertyKey,1333		}1334	}1335}
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#![cfg_attr(not(feature = "std"), no_std)]1819extern crate alloc;2021use core::ops::{Deref, DerefMut};22use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};23use sp_std::vec::Vec;24use pallet_evm::account::CrossAccountId;25use frame_support::{26	dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, Weight, PostDispatchInfo},27	ensure,28	traits::{Imbalance, Get, Currency, WithdrawReasons, ExistenceRequirement},29	BoundedVec,30	weights::Pays,31	transactional,32};33use pallet_evm::GasWeightMapping;34use up_data_structs::{35	COLLECTION_NUMBER_LIMIT,36	Collection,37	RpcCollection,38	CollectionId,39	CreateItemData,40	MAX_TOKEN_PREFIX_LENGTH,41	COLLECTION_ADMINS_LIMIT,42	TokenId,43	CollectionStats,44	MAX_TOKEN_OWNERSHIP,45	CollectionMode,46	NFT_SPONSOR_TRANSFER_TIMEOUT,47	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,48	REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,49	MAX_SPONSOR_TIMEOUT,50	CUSTOM_DATA_LIMIT,51	CollectionLimits,52	CreateCollectionData,53	SponsorshipState,54	CreateItemExData,55	SponsoringRateLimit,56	budget::Budget,57	COLLECTION_FIELD_LIMIT,58	PhantomType,59	Property,60	Properties,61	PropertiesPermissionMap,62	PropertyKey,63	PropertyValue,64	PropertyPermission,65	PropertiesError,66	PropertyKeyPermission,67	TokenData,68	TrySetProperty,69	PropertyScope,70	// RMRK71	RmrkCollectionInfo,72	RmrkInstanceInfo,73	RmrkResourceInfo,74	RmrkPropertyInfo,75	RmrkBaseInfo,76	RmrkPartType,77	RmrkTheme,78	RmrkNftChild,79	CollectionPermissions,80	SchemaVersion,81};8283pub use pallet::*;84use sp_core::H160;85use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};86#[cfg(feature = "runtime-benchmarks")]87pub mod benchmarking;88pub mod dispatch;89pub mod erc;90pub mod eth;91pub mod weights;9293pub type SelfWeightOf<T> = <T as Config>::WeightInfo;9495#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]96pub struct CollectionHandle<T: Config> {97	pub id: CollectionId,98	collection: Collection<T::AccountId>,99	pub recorder: SubstrateRecorder<T>,100}101impl<T: Config> WithRecorder<T> for CollectionHandle<T> {102	fn recorder(&self) -> &SubstrateRecorder<T> {103		&self.recorder104	}105	fn into_recorder(self) -> SubstrateRecorder<T> {106		self.recorder107	}108}109impl<T: Config> CollectionHandle<T> {110	pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {111		<CollectionById<T>>::get(id).map(|collection| Self {112			id,113			collection,114			recorder: SubstrateRecorder::new(gas_limit),115		})116	}117118	pub fn new_with_recorder(id: CollectionId, recorder: SubstrateRecorder<T>) -> Option<Self> {119		<CollectionById<T>>::get(id).map(|collection| Self {120			id,121			collection,122			recorder,123		})124	}125126	pub fn new(id: CollectionId) -> Option<Self> {127		Self::new_with_gas_limit(id, u64::MAX)128	}129	pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {130		Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)131	}132	pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {133		self.recorder134			.consume_gas(T::GasWeightMapping::weight_to_gas(135				<T as frame_system::Config>::DbWeight::get()136					.read137					.saturating_mul(reads),138			))139	}140	pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {141		self.recorder142			.consume_gas(T::GasWeightMapping::weight_to_gas(143				<T as frame_system::Config>::DbWeight::get()144					.write145					.saturating_mul(writes),146			))147	}148	pub fn save(self) -> DispatchResult {149		<CollectionById<T>>::insert(self.id, self.collection);150		Ok(())151	}152153	pub fn set_sponsor(&mut self, sponsor: T::AccountId) {154		self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor);155	}156157	pub fn confirm_sponsorship(&mut self, sender: &T::AccountId) -> bool {158		if self.collection.sponsorship.pending_sponsor() != Some(sender) {159			return false;160		};161162		self.collection.sponsorship = SponsorshipState::Confirmed(sender.clone());163		true164	}165}166impl<T: Config> Deref for CollectionHandle<T> {167	type Target = Collection<T::AccountId>;168169	fn deref(&self) -> &Self::Target {170		&self.collection171	}172}173174impl<T: Config> DerefMut for CollectionHandle<T> {175	fn deref_mut(&mut self) -> &mut Self::Target {176		&mut self.collection177	}178}179180impl<T: Config> CollectionHandle<T> {181	pub fn check_is_owner(&self, subject: &T::CrossAccountId) -> DispatchResult {182		ensure!(*subject.as_sub() == self.owner, <Error<T>>::NoPermission);183		Ok(())184	}185	pub fn is_owner_or_admin(&self, subject: &T::CrossAccountId) -> bool {186		*subject.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, subject))187	}188	pub fn check_is_owner_or_admin(&self, subject: &T::CrossAccountId) -> DispatchResult {189		ensure!(self.is_owner_or_admin(subject), <Error<T>>::NoPermission);190		Ok(())191	}192	pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {193		self.limits.owner_can_transfer() && self.is_owner_or_admin(user)194	}195	pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> bool {196		self.limits.owner_can_transfer() && self.is_owner_or_admin(user)197	}198	pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {199		ensure!(200			<Allowlist<T>>::get((self.id, user)),201			<Error<T>>::AddressNotInAllowlist202		);203		Ok(())204	}205}206207#[frame_support::pallet]208pub mod pallet {209	use super::*;210	use pallet_evm::account;211	use dispatch::CollectionDispatch;212	use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key, traits::StorageVersion};213	use frame_system::pallet_prelude::*;214	use frame_support::traits::Currency;215	use up_data_structs::{TokenId, mapping::TokenAddressMapping};216	use scale_info::TypeInfo;217	use weights::WeightInfo;218219	#[pallet::config]220	pub trait Config:221		frame_system::Config + pallet_evm_coder_substrate::Config + TypeInfo + account::Config222	{223		type WeightInfo: WeightInfo;224		type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;225226		type Currency: Currency<Self::AccountId>;227228		#[pallet::constant]229		type CollectionCreationPrice: Get<230			<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,231		>;232		type CollectionDispatch: CollectionDispatch<Self>;233234		type TreasuryAccountId: Get<Self::AccountId>;235236		type EvmTokenAddressMapping: TokenAddressMapping<H160>;237		type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;238	}239240	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);241242	#[pallet::pallet]243	#[pallet::storage_version(STORAGE_VERSION)]244	#[pallet::generate_store(pub(super) trait Store)]245	pub struct Pallet<T>(_);246247	#[pallet::extra_constants]248	impl<T: Config> Pallet<T> {249		pub fn collection_admins_limit() -> u32 {250			COLLECTION_ADMINS_LIMIT251		}252	}253254	#[pallet::event]255	#[pallet::generate_deposit(pub fn deposit_event)]256	pub enum Event<T: Config> {257		/// New collection was created258		///259		/// # Arguments260		///261		/// * collection_id: Globally unique identifier of newly created collection.262		///263		/// * mode: [CollectionMode] converted into u8.264		///265		/// * account_id: Collection owner.266		CollectionCreated(CollectionId, u8, T::AccountId),267268		/// New collection was destroyed269		///270		/// # Arguments271		///272		/// * collection_id: Globally unique identifier of collection.273		CollectionDestroyed(CollectionId),274275		/// New item was created.276		///277		/// # Arguments278		///279		/// * collection_id: Id of the collection where item was created.280		///281		/// * item_id: Id of an item. Unique within the collection.282		///283		/// * recipient: Owner of newly created item284		///285		/// * amount: Always 1 for NFT286		ItemCreated(CollectionId, TokenId, T::CrossAccountId, u128),287288		/// Collection item was burned.289		///290		/// # Arguments291		///292		/// * collection_id.293		///294		/// * item_id: Identifier of burned NFT.295		///296		/// * owner: which user has destroyed its tokens297		///298		/// * amount: Always 1 for NFT299		ItemDestroyed(CollectionId, TokenId, T::CrossAccountId, u128),300301		/// Item was transferred302		///303		/// * collection_id: Id of collection to which item is belong304		///305		/// * item_id: Id of an item306		///307		/// * sender: Original owner of item308		///309		/// * recipient: New owner of item310		///311		/// * amount: Always 1 for NFT312		Transfer(313			CollectionId,314			TokenId,315			T::CrossAccountId,316			T::CrossAccountId,317			u128,318		),319320		/// * collection_id321		///322		/// * item_id323		///324		/// * sender325		///326		/// * spender327		///328		/// * amount329		Approved(330			CollectionId,331			TokenId,332			T::CrossAccountId,333			T::CrossAccountId,334			u128,335		),336337		CollectionPropertySet(CollectionId, PropertyKey),338339		CollectionPropertyDeleted(CollectionId, PropertyKey),340341		TokenPropertySet(CollectionId, TokenId, PropertyKey),342343		TokenPropertyDeleted(CollectionId, TokenId, PropertyKey),344345		PropertyPermissionSet(CollectionId, PropertyKey),346	}347348	#[pallet::error]349	pub enum Error<T> {350		/// This collection does not exist.351		CollectionNotFound,352		/// Sender parameter and item owner must be equal.353		MustBeTokenOwner,354		/// No permission to perform action355		NoPermission,356		/// Destroying only empty collections is allowed357		CantDestroyNotEmptyCollection,358		/// Collection is not in mint mode.359		PublicMintingNotAllowed,360		/// Address is not in allow list.361		AddressNotInAllowlist,362363		/// Collection name can not be longer than 63 char.364		CollectionNameLimitExceeded,365		/// Collection description can not be longer than 255 char.366		CollectionDescriptionLimitExceeded,367		/// Token prefix can not be longer than 15 char.368		CollectionTokenPrefixLimitExceeded,369		/// Total collections bound exceeded.370		TotalCollectionsLimitExceeded,371		/// Exceeded max admin count372		CollectionAdminCountExceeded,373		/// Collection limit bounds per collection exceeded374		CollectionLimitBoundsExceeded,375		/// Tried to enable permissions which are only permitted to be disabled376		OwnerPermissionsCantBeReverted,377		/// Collection settings not allowing items transferring378		TransferNotAllowed,379		/// Account token limit exceeded per collection380		AccountTokenLimitExceeded,381		/// Collection token limit exceeded382		CollectionTokenLimitExceeded,383		/// Metadata flag frozen384		MetadataFlagFrozen,385386		/// Item not exists.387		TokenNotFound,388		/// Item balance not enough.389		TokenValueTooLow,390		/// Requested value more than approved.391		ApprovedValueTooLow,392		/// Tried to approve more than owned393		CantApproveMoreThanOwned,394395		/// Can't transfer tokens to ethereum zero address396		AddressIsZero,397		/// Target collection doesn't supports this operation398		UnsupportedOperation,399400		/// Not sufficient founds to perform action401		NotSufficientFounds,402403		/// Collection has nesting disabled404		NestingIsDisabled,405		/// Only owner may nest tokens under this collection406		OnlyOwnerAllowedToNest,407		/// Only tokens from specific collections may nest tokens under this408		SourceCollectionIsNotAllowedToNest,409410		/// Tried to store more data than allowed in collection field411		CollectionFieldSizeExceeded,412413		/// Tried to store more property data than allowed414		NoSpaceForProperty,415416		/// Tried to store more property keys than allowed417		PropertyLimitReached,418419		/// Property key is too long420		PropertyKeyIsTooLong,421422		/// Only ASCII letters, digits, and '_', '-' are allowed423		InvalidCharacterInPropertyKey,424425		/// Empty property keys are forbidden426		EmptyPropertyKey,427	}428429	#[pallet::storage]430	pub type CreatedCollectionCount<T> = StorageValue<Value = CollectionId, QueryKind = ValueQuery>;431	#[pallet::storage]432	pub type DestroyedCollectionCount<T> =433		StorageValue<Value = CollectionId, QueryKind = ValueQuery>;434435	/// Collection info436	#[pallet::storage]437	pub type CollectionById<T> = StorageMap<438		Hasher = Blake2_128Concat,439		Key = CollectionId,440		Value = Collection<<T as frame_system::Config>::AccountId>,441		QueryKind = OptionQuery,442	>;443444	/// Collection properties445	#[pallet::storage]446	#[pallet::getter(fn collection_properties)]447	pub type CollectionProperties<T> = StorageMap<448		Hasher = Blake2_128Concat,449		Key = CollectionId,450		Value = Properties,451		QueryKind = ValueQuery,452		OnEmpty = up_data_structs::CollectionProperties,453	>;454455	#[pallet::storage]456	#[pallet::getter(fn property_permissions)]457	pub type CollectionPropertyPermissions<T> = StorageMap<458		Hasher = Blake2_128Concat,459		Key = CollectionId,460		Value = PropertiesPermissionMap,461		QueryKind = ValueQuery,462	>;463464	#[pallet::storage]465	pub type AdminAmount<T> = StorageMap<466		Hasher = Blake2_128Concat,467		Key = CollectionId,468		Value = u32,469		QueryKind = ValueQuery,470	>;471472	/// List of collection admins473	#[pallet::storage]474	pub type IsAdmin<T: Config> = StorageNMap<475		Key = (476			Key<Blake2_128Concat, CollectionId>,477			Key<Blake2_128Concat, T::CrossAccountId>,478		),479		Value = bool,480		QueryKind = ValueQuery,481	>;482483	/// Allowlisted collection users484	#[pallet::storage]485	pub type Allowlist<T: Config> = StorageNMap<486		Key = (487			Key<Blake2_128Concat, CollectionId>,488			Key<Blake2_128Concat, T::CrossAccountId>,489		),490		Value = bool,491		QueryKind = ValueQuery,492	>;493494	/// Not used by code, exists only to provide some types to metadata495	#[pallet::storage]496	pub type DummyStorageValue<T: Config> = StorageValue<497		Value = (498			CollectionStats,499			CollectionId,500			TokenId,501			PhantomType<(502				TokenData<T::CrossAccountId>,503				RpcCollection<T::AccountId>,504				// RMRK505				RmrkCollectionInfo<T::AccountId>,506				RmrkInstanceInfo<T::AccountId>,507				RmrkResourceInfo,508				RmrkPropertyInfo,509				RmrkBaseInfo<T::AccountId>,510				RmrkPartType,511				RmrkTheme,512				RmrkNftChild,513			)>,514		),515		QueryKind = OptionQuery,516	>;517518	#[pallet::hooks]519	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {520		fn on_runtime_upgrade() -> Weight {521			if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {522				use up_data_structs::{CollectionVersion1, CollectionVersion2};523				<CollectionById<T>>::translate::<CollectionVersion1<T::AccountId>, _>(|id, v| {524					let mut props = Vec::new();525					if !v.offchain_schema.is_empty() {526						props.push(Property {527							key: b"_old_offchainSchema".to_vec().try_into().unwrap(),528							value: v529								.offchain_schema530								.clone()531								.into_inner()532								.try_into()533								.expect("offchain schema too big"),534						});535					}536					if !v.variable_on_chain_schema.is_empty() {537						props.push(Property {538							key: b"_old_variableOnChainSchema".to_vec().try_into().unwrap(),539							value: v540								.variable_on_chain_schema541								.clone()542								.into_inner()543								.try_into()544								.expect("offchain schema too big"),545						});546					}547					if !v.const_on_chain_schema.is_empty() {548						props.push(Property {549							key: b"_old_constOnChainSchema".to_vec().try_into().unwrap(),550							value: v551								.const_on_chain_schema552								.clone()553								.into_inner()554								.try_into()555								.expect("offchain schema too big"),556						});557					}558					props.push(Property {559						key: b"_old_schemaVersion".to_vec().try_into().unwrap(),560						value: match v.schema_version {561							SchemaVersion::ImageURL => b"ImageUrl".as_slice(),562							SchemaVersion::Unique => b"Unique".as_slice(),563						}564						.to_vec()565						.try_into()566						.unwrap(),567					});568					Self::set_scoped_collection_properties(569						id,570						PropertyScope::None,571						props.into_iter(),572					)573					.expect("existing data larger than properties");574					let mut new = CollectionVersion2::from(v.clone());575					new.permissions.access = Some(v.access);576					new.permissions.mint_mode = Some(v.mint_mode);577					Some(new)578				});579			}580581			0582		}583	}584}585586impl<T: Config> Pallet<T> {587	/// Ethereum receiver 0x0000000000000000000000000000000000000000 is reserved, and shouldn't own tokens588	pub fn ensure_correct_receiver(receiver: &T::CrossAccountId) -> DispatchResult {589		ensure!(590			&T::CrossAccountId::from_eth(H160([0; 20])) != receiver,591			<Error<T>>::AddressIsZero592		);593		Ok(())594	}595	pub fn adminlist(collection: CollectionId) -> Vec<T::CrossAccountId> {596		<IsAdmin<T>>::iter_prefix((collection,))597			.map(|(a, _)| a)598			.collect()599	}600	pub fn allowlist(collection: CollectionId) -> Vec<T::CrossAccountId> {601		<Allowlist<T>>::iter_prefix((collection,))602			.map(|(a, _)| a)603			.collect()604	}605	pub fn allowed(collection: CollectionId, user: T::CrossAccountId) -> bool {606		<Allowlist<T>>::get((collection, user))607	}608	pub fn collection_stats() -> CollectionStats {609		let created = <CreatedCollectionCount<T>>::get();610		let destroyed = <DestroyedCollectionCount<T>>::get();611		CollectionStats {612			created: created.0,613			destroyed: destroyed.0,614			alive: created.0 - destroyed.0,615		}616	}617618	pub fn effective_collection_limits(collection: CollectionId) -> Option<CollectionLimits> {619		let collection = <CollectionById<T>>::get(collection);620		if collection.is_none() {621			return None;622		}623624		let collection = collection.unwrap();625		let limits = collection.limits;626		let effective_limits = CollectionLimits {627			account_token_ownership_limit: Some(limits.account_token_ownership_limit()),628			sponsored_data_size: Some(limits.sponsored_data_size()),629			sponsored_data_rate_limit: Some(630				limits631					.sponsored_data_rate_limit632					.unwrap_or(SponsoringRateLimit::SponsoringDisabled),633			),634			token_limit: Some(limits.token_limit()),635			sponsor_transfer_timeout: Some(limits.sponsor_transfer_timeout(636				match collection.mode {637					CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,638					CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,639					CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,640				},641			)),642			sponsor_approve_timeout: Some(limits.sponsor_approve_timeout()),643			owner_can_transfer: Some(limits.owner_can_transfer()),644			owner_can_destroy: Some(limits.owner_can_destroy()),645			transfers_enabled: Some(limits.transfers_enabled()),646		};647648		Some(effective_limits)649	}650651	pub fn rpc_collection(collection: CollectionId) -> Option<RpcCollection<T::AccountId>> {652		let Collection {653			name,654			description,655			owner,656			mode,657			token_prefix,658			sponsorship,659			limits,660			permissions,661		} = <CollectionById<T>>::get(collection)?;662663		let token_property_permissions = <CollectionPropertyPermissions<T>>::get(collection)664			.into_iter()665			.map(|(key, permission)| PropertyKeyPermission { key, permission })666			.collect();667668		let properties = <CollectionProperties<T>>::get(collection)669			.into_iter()670			.map(|(key, value)| Property { key, value })671			.collect();672673		let permissions = CollectionPermissions {674			access: Some(permissions.access()),675			mint_mode: Some(permissions.mint_mode()),676			nesting: Some(permissions.nesting().clone()),677		};678679		Some(RpcCollection {680			name: name.into_inner(),681			description: description.into_inner(),682			owner,683			mode,684			token_prefix: token_prefix.into_inner(),685			sponsorship,686			limits,687			permissions,688			token_property_permissions,689			properties,690		})691	}692}693694macro_rules! limit_default {695	($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{696		$(697			if let Some($new) = $new.$field {698				let $old = $old.$field($($arg)?);699				let _ = $new;700				let _ = $old;701				$check702			} else {703				$new.$field = $old.$field704			}705		)*706	}};707}708macro_rules! limit_default_clone {709	($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{710		$(711			if let Some($new) = $new.$field.clone() {712				let $old = $old.$field($($arg)?);713				let _ = $new;714				let _ = $old;715				$check716			} else {717				$new.$field = $old.$field.clone()718			}719		)*720	}};721}722723impl<T: Config> Pallet<T> {724	pub fn init_collection(725		owner: T::AccountId,726		data: CreateCollectionData<T::AccountId>,727	) -> Result<CollectionId, DispatchError> {728		{729			ensure!(730				data.token_prefix.len() <= MAX_TOKEN_PREFIX_LENGTH as usize,731				Error::<T>::CollectionTokenPrefixLimitExceeded732			);733		}734735		let created_count = <CreatedCollectionCount<T>>::get()736			.0737			.checked_add(1)738			.ok_or(ArithmeticError::Overflow)?;739		let destroyed_count = <DestroyedCollectionCount<T>>::get().0;740		let id = CollectionId(created_count);741742		// bound Total number of collections743		ensure!(744			created_count - destroyed_count <= COLLECTION_NUMBER_LIMIT,745			<Error<T>>::TotalCollectionsLimitExceeded746		);747748		// =========749750		let collection = Collection {751			owner: owner.clone(),752			name: data.name,753			mode: data.mode.clone(),754			description: data.description,755			token_prefix: data.token_prefix,756			sponsorship: data757				.pending_sponsor758				.map(SponsorshipState::Unconfirmed)759				.unwrap_or_default(),760			limits: data761				.limits762				.map(|limits| Self::clamp_limits(data.mode.clone(), &Default::default(), limits))763				.unwrap_or_else(|| Ok(CollectionLimits::default()))?,764			permissions: data765				.permissions766				.map(|permissions| {767					Self::clamp_permissions(data.mode.clone(), &Default::default(), permissions)768				})769				.unwrap_or_else(|| Ok(CollectionPermissions::default()))?,770		};771772		let mut collection_properties = up_data_structs::CollectionProperties::get();773		collection_properties774			.try_set_from_iter(data.properties.into_iter())775			.map_err(<Error<T>>::from)?;776777		CollectionProperties::<T>::insert(id, collection_properties);778779		let mut token_props_permissions = PropertiesPermissionMap::new();780		token_props_permissions781			.try_set_from_iter(data.token_property_permissions.into_iter())782			.map_err(<Error<T>>::from)?;783784		CollectionPropertyPermissions::<T>::insert(id, token_props_permissions);785786		// Take a (non-refundable) deposit of collection creation787		{788			let mut imbalance =789				<<<T as Config>::Currency as Currency<T::AccountId>>::PositiveImbalance>::zero();790			imbalance.subsume(791				<<T as Config>::Currency as Currency<T::AccountId>>::deposit_creating(792					&T::TreasuryAccountId::get(),793					T::CollectionCreationPrice::get(),794				),795			);796			<T as Config>::Currency::settle(797				&owner,798				imbalance,799				WithdrawReasons::TRANSFER,800				ExistenceRequirement::KeepAlive,801			)802			.map_err(|_| Error::<T>::NotSufficientFounds)?;803		}804805		<CreatedCollectionCount<T>>::put(created_count);806		<Pallet<T>>::deposit_event(Event::CollectionCreated(id, data.mode.id(), owner.clone()));807		<CollectionById<T>>::insert(id, collection);808		Ok(id)809	}810811	pub fn destroy_collection(812		collection: CollectionHandle<T>,813		sender: &T::CrossAccountId,814	) -> DispatchResult {815		ensure!(816			collection.limits.owner_can_destroy(),817			<Error<T>>::NoPermission,818		);819		collection.check_is_owner(sender)?;820821		let destroyed_collections = <DestroyedCollectionCount<T>>::get()822			.0823			.checked_add(1)824			.ok_or(ArithmeticError::Overflow)?;825826		// =========827828		<DestroyedCollectionCount<T>>::put(destroyed_collections);829		<CollectionById<T>>::remove(collection.id);830		<AdminAmount<T>>::remove(collection.id);831		<IsAdmin<T>>::remove_prefix((collection.id,), None);832		<Allowlist<T>>::remove_prefix((collection.id,), None);833		<CollectionProperties<T>>::remove(collection.id);834835		<Pallet<T>>::deposit_event(Event::CollectionDestroyed(collection.id));836		Ok(())837	}838839	pub fn set_collection_property(840		collection: &CollectionHandle<T>,841		sender: &T::CrossAccountId,842		property: Property,843	) -> DispatchResult {844		collection.check_is_owner_or_admin(sender)?;845846		CollectionProperties::<T>::try_mutate(collection.id, |properties| {847			let property = property.clone();848			properties.try_set(property.key, property.value)849		})850		.map_err(<Error<T>>::from)?;851852		Self::deposit_event(Event::CollectionPropertySet(collection.id, property.key));853854		Ok(())855	}856857	pub fn set_scoped_collection_property(858		collection_id: CollectionId,859		scope: PropertyScope,860		property: Property,861	) -> DispatchResult {862		CollectionProperties::<T>::try_mutate(collection_id, |properties| {863			properties.try_scoped_set(scope, property.key, property.value)864		})865		.map_err(<Error<T>>::from)?;866867		Ok(())868	}869870	pub fn set_scoped_collection_properties(871		collection_id: CollectionId,872		scope: PropertyScope,873		properties: impl Iterator<Item = Property>,874	) -> DispatchResult {875		CollectionProperties::<T>::try_mutate(collection_id, |stored_properties| {876			stored_properties.try_scoped_set_from_iter(scope, properties)877		})878		.map_err(<Error<T>>::from)?;879880		Ok(())881	}882883	#[transactional]884	pub fn set_collection_properties(885		collection: &CollectionHandle<T>,886		sender: &T::CrossAccountId,887		properties: Vec<Property>,888	) -> DispatchResult {889		for property in properties {890			Self::set_collection_property(collection, sender, property)?;891		}892893		Ok(())894	}895896	pub fn delete_collection_property(897		collection: &CollectionHandle<T>,898		sender: &T::CrossAccountId,899		property_key: PropertyKey,900	) -> DispatchResult {901		collection.check_is_owner_or_admin(sender)?;902903		CollectionProperties::<T>::try_mutate(collection.id, |properties| {904			properties.remove(&property_key)905		})906		.map_err(<Error<T>>::from)?;907908		Self::deposit_event(Event::CollectionPropertyDeleted(909			collection.id,910			property_key,911		));912913		Ok(())914	}915916	#[transactional]917	pub fn delete_collection_properties(918		collection: &CollectionHandle<T>,919		sender: &T::CrossAccountId,920		property_keys: Vec<PropertyKey>,921	) -> DispatchResult {922		for key in property_keys {923			Self::delete_collection_property(collection, sender, key)?;924		}925926		Ok(())927	}928929	// For migrations930	pub fn set_property_permission_unchecked(931		collection: CollectionId,932		property_permission: PropertyKeyPermission,933	) -> DispatchResult {934		<CollectionPropertyPermissions<T>>::try_mutate(collection, |permissions| {935			permissions.try_set(property_permission.key, property_permission.permission)936		})937		.map_err(<Error<T>>::from)?;938		Ok(())939	}940941	pub fn set_property_permission(942		collection: &CollectionHandle<T>,943		sender: &T::CrossAccountId,944		property_permission: PropertyKeyPermission,945	) -> DispatchResult {946		collection.check_is_owner_or_admin(sender)?;947948		let all_permissions = CollectionPropertyPermissions::<T>::get(collection.id);949		let current_permission = all_permissions.get(&property_permission.key);950		if matches![951			current_permission,952			Some(PropertyPermission { mutable: false, .. })953		] {954			return Err(<Error<T>>::NoPermission.into());955		}956957		CollectionPropertyPermissions::<T>::try_mutate(collection.id, |permissions| {958			let property_permission = property_permission.clone();959			permissions.try_set(property_permission.key, property_permission.permission)960		})961		.map_err(<Error<T>>::from)?;962963		Self::deposit_event(Event::PropertyPermissionSet(964			collection.id,965			property_permission.key,966		));967968		Ok(())969	}970971	#[transactional]972	pub fn set_property_permissions(973		collection: &CollectionHandle<T>,974		sender: &T::CrossAccountId,975		property_permissions: Vec<PropertyKeyPermission>,976	) -> DispatchResult {977		for prop_pemission in property_permissions {978			Self::set_property_permission(collection, sender, prop_pemission)?;979		}980981		Ok(())982	}983984	pub fn get_collection_property(985		collection_id: CollectionId,986		key: &PropertyKey,987	) -> Option<PropertyValue> {988		Self::collection_properties(collection_id).get(key).cloned()989	}990991	pub fn bytes_keys_to_property_keys(992		keys: Vec<Vec<u8>>,993	) -> Result<Vec<PropertyKey>, DispatchError> {994		keys.into_iter()995			.map(|key| -> Result<PropertyKey, DispatchError> {996				key.try_into()997					.map_err(|_| <Error<T>>::PropertyKeyIsTooLong.into())998			})999			.collect::<Result<Vec<PropertyKey>, DispatchError>>()1000	}10011002	pub fn filter_collection_properties(1003		collection_id: CollectionId,1004		keys: Option<Vec<PropertyKey>>,1005	) -> Result<Vec<Property>, DispatchError> {1006		let properties = Self::collection_properties(collection_id);10071008		let properties = keys1009			.map(|keys| {1010				keys.into_iter()1011					.filter_map(|key| {1012						properties.get(&key).map(|value| Property {1013							key,1014							value: value.clone(),1015						})1016					})1017					.collect()1018			})1019			.unwrap_or_else(|| {1020				properties1021					.into_iter()1022					.map(|(key, value)| Property { key, value })1023					.collect()1024			});10251026		Ok(properties)1027	}10281029	pub fn filter_property_permissions(1030		collection_id: CollectionId,1031		keys: Option<Vec<PropertyKey>>,1032	) -> Result<Vec<PropertyKeyPermission>, DispatchError> {1033		let permissions = Self::property_permissions(collection_id);10341035		let key_permissions = keys1036			.map(|keys| {1037				keys.into_iter()1038					.filter_map(|key| {1039						permissions1040							.get(&key)1041							.map(|permission| PropertyKeyPermission {1042								key,1043								permission: permission.clone(),1044							})1045					})1046					.collect()1047			})1048			.unwrap_or_else(|| {1049				permissions1050					.into_iter()1051					.map(|(key, permission)| PropertyKeyPermission { key, permission })1052					.collect()1053			});10541055		Ok(key_permissions)1056	}10571058	pub fn toggle_allowlist(1059		collection: &CollectionHandle<T>,1060		sender: &T::CrossAccountId,1061		user: &T::CrossAccountId,1062		allowed: bool,1063	) -> DispatchResult {1064		collection.check_is_owner_or_admin(sender)?;10651066		// =========10671068		if allowed {1069			<Allowlist<T>>::insert((collection.id, user), true);1070		} else {1071			<Allowlist<T>>::remove((collection.id, user));1072		}10731074		Ok(())1075	}10761077	pub fn toggle_admin(1078		collection: &CollectionHandle<T>,1079		sender: &T::CrossAccountId,1080		user: &T::CrossAccountId,1081		admin: bool,1082	) -> DispatchResult {1083		collection.check_is_owner_or_admin(sender)?;10841085		let was_admin = <IsAdmin<T>>::get((collection.id, user));1086		if was_admin == admin {1087			return Ok(());1088		}1089		let amount = <AdminAmount<T>>::get(collection.id);10901091		if admin {1092			let amount = amount1093				.checked_add(1)1094				.ok_or(<Error<T>>::CollectionAdminCountExceeded)?;1095			ensure!(1096				amount <= Self::collection_admins_limit(),1097				<Error<T>>::CollectionAdminCountExceeded,1098			);10991100			// =========11011102			<AdminAmount<T>>::insert(collection.id, amount);1103			<IsAdmin<T>>::insert((collection.id, user), true);1104		} else {1105			<AdminAmount<T>>::insert(collection.id, amount.saturating_sub(1));1106			<IsAdmin<T>>::remove((collection.id, user));1107		}11081109		Ok(())1110	}11111112	pub fn clamp_limits(1113		mode: CollectionMode,1114		old_limit: &CollectionLimits,1115		mut new_limit: CollectionLimits,1116	) -> Result<CollectionLimits, DispatchError> {1117		limit_default!(old_limit, new_limit,1118			account_token_ownership_limit => ensure!(1119				new_limit <= MAX_TOKEN_OWNERSHIP,1120				<Error<T>>::CollectionLimitBoundsExceeded,1121			),1122			sponsored_data_size => ensure!(1123				new_limit <= CUSTOM_DATA_LIMIT,1124				<Error<T>>::CollectionLimitBoundsExceeded,1125			),11261127			sponsored_data_rate_limit => {},1128			token_limit => ensure!(1129				old_limit >= new_limit && new_limit > 0,1130				<Error<T>>::CollectionTokenLimitExceeded1131			),11321133			sponsor_transfer_timeout(match mode {1134				CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,1135				CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1136				CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1137			}) => ensure!(1138				new_limit <= MAX_SPONSOR_TIMEOUT,1139				<Error<T>>::CollectionLimitBoundsExceeded,1140			),1141			sponsor_approve_timeout => {},1142			owner_can_transfer => ensure!(1143				old_limit || !new_limit,1144				<Error<T>>::OwnerPermissionsCantBeReverted,1145			),1146			owner_can_destroy => ensure!(1147				old_limit || !new_limit,1148				<Error<T>>::OwnerPermissionsCantBeReverted,1149			),1150			transfers_enabled => {},1151		);1152		Ok(new_limit)1153	}1154	pub fn clamp_permissions(1155		mode: CollectionMode,1156		old_limit: &CollectionPermissions,1157		mut new_limit: CollectionPermissions,1158	) -> Result<CollectionPermissions, DispatchError> {1159		limit_default_clone!(old_limit, new_limit,1160			access => {},1161			mint_mode => {},1162			nesting => {},1163		);1164		Ok(new_limit)1165	}1166}11671168#[macro_export]1169macro_rules! unsupported {1170	() => {1171		Err(<Error<T>>::UnsupportedOperation.into())1172	};1173}11741175/// Worst cases1176pub trait CommonWeightInfo<CrossAccountId> {1177	fn create_item() -> Weight;1178	fn create_multiple_items(amount: &[CreateItemData]) -> Weight;1179	fn create_multiple_items_ex(cost: &CreateItemExData<CrossAccountId>) -> Weight;1180	fn burn_item() -> Weight;1181	fn set_collection_properties(amount: u32) -> Weight;1182	fn delete_collection_properties(amount: u32) -> Weight;1183	fn set_token_properties(amount: u32) -> Weight;1184	fn delete_token_properties(amount: u32) -> Weight;1185	fn set_property_permissions(amount: u32) -> Weight;1186	fn transfer() -> Weight;1187	fn approve() -> Weight;1188	fn transfer_from() -> Weight;1189	fn burn_from() -> Weight;1190}11911192pub trait CommonCollectionOperations<T: Config> {1193	fn create_item(1194		&self,1195		sender: T::CrossAccountId,1196		to: T::CrossAccountId,1197		data: CreateItemData,1198		nesting_budget: &dyn Budget,1199	) -> DispatchResultWithPostInfo;1200	fn create_multiple_items(1201		&self,1202		sender: T::CrossAccountId,1203		to: T::CrossAccountId,1204		data: Vec<CreateItemData>,1205		nesting_budget: &dyn Budget,1206	) -> DispatchResultWithPostInfo;1207	fn create_multiple_items_ex(1208		&self,1209		sender: T::CrossAccountId,1210		data: CreateItemExData<T::CrossAccountId>,1211		nesting_budget: &dyn Budget,1212	) -> DispatchResultWithPostInfo;1213	fn burn_item(1214		&self,1215		sender: T::CrossAccountId,1216		token: TokenId,1217		amount: u128,1218	) -> DispatchResultWithPostInfo;1219	fn set_collection_properties(1220		&self,1221		sender: T::CrossAccountId,1222		properties: Vec<Property>,1223	) -> DispatchResultWithPostInfo;1224	fn delete_collection_properties(1225		&self,1226		sender: &T::CrossAccountId,1227		property_keys: Vec<PropertyKey>,1228	) -> DispatchResultWithPostInfo;1229	fn set_token_properties(1230		&self,1231		sender: T::CrossAccountId,1232		token_id: TokenId,1233		property: Vec<Property>,1234	) -> DispatchResultWithPostInfo;1235	fn delete_token_properties(1236		&self,1237		sender: T::CrossAccountId,1238		token_id: TokenId,1239		property_keys: Vec<PropertyKey>,1240	) -> DispatchResultWithPostInfo;1241	fn set_property_permissions(1242		&self,1243		sender: &T::CrossAccountId,1244		property_permissions: Vec<PropertyKeyPermission>,1245	) -> DispatchResultWithPostInfo;1246	fn transfer(1247		&self,1248		sender: T::CrossAccountId,1249		to: T::CrossAccountId,1250		token: TokenId,1251		amount: u128,1252		nesting_budget: &dyn Budget,1253	) -> DispatchResultWithPostInfo;1254	fn approve(1255		&self,1256		sender: T::CrossAccountId,1257		spender: T::CrossAccountId,1258		token: TokenId,1259		amount: u128,1260	) -> DispatchResultWithPostInfo;1261	fn transfer_from(1262		&self,1263		sender: T::CrossAccountId,1264		from: T::CrossAccountId,1265		to: T::CrossAccountId,1266		token: TokenId,1267		amount: u128,1268		nesting_budget: &dyn Budget,1269	) -> DispatchResultWithPostInfo;1270	fn burn_from(1271		&self,1272		sender: T::CrossAccountId,1273		from: T::CrossAccountId,1274		token: TokenId,1275		amount: u128,1276		nesting_budget: &dyn Budget,1277	) -> DispatchResultWithPostInfo;12781279	fn check_nesting(1280		&self,1281		sender: T::CrossAccountId,1282		from: (CollectionId, TokenId),1283		under: TokenId,1284		budget: &dyn Budget,1285	) -> DispatchResult;12861287	fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId));12881289	fn unnest(&self, under: TokenId, to_nest: (CollectionId, TokenId));12901291	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;1292	fn collection_tokens(&self) -> Vec<TokenId>;1293	fn token_exists(&self, token: TokenId) -> bool;1294	fn last_token_id(&self) -> TokenId;12951296	fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;1297	fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue>;1298	fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property>;1299	/// Amount of unique collection tokens1300	fn total_supply(&self) -> u32;1301	/// Amount of different tokens account has (Applicable to nonfungible/refungible)1302	fn account_balance(&self, account: T::CrossAccountId) -> u32;1303	/// Amount of specific token account have (Applicable to fungible/refungible)1304	fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;1305	fn allowance(1306		&self,1307		sender: T::CrossAccountId,1308		spender: T::CrossAccountId,1309		token: TokenId,1310	) -> u128;1311}13121313// Flexible enough for implementing CommonCollectionOperations1314pub fn with_weight(res: DispatchResult, weight: Weight) -> DispatchResultWithPostInfo {1315	let post_info = PostDispatchInfo {1316		actual_weight: Some(weight),1317		pays_fee: Pays::Yes,1318	};1319	match res {1320		Ok(()) => Ok(post_info),1321		Err(error) => Err(DispatchErrorWithPostInfo { post_info, error }),1322	}1323}13241325impl<T: Config> From<PropertiesError> for Error<T> {1326	fn from(error: PropertiesError) -> Self {1327		match error {1328			PropertiesError::NoSpaceForProperty => Self::NoSpaceForProperty,1329			PropertiesError::PropertyLimitReached => Self::PropertyLimitReached,1330			PropertiesError::InvalidCharacterInPropertyKey => Self::InvalidCharacterInPropertyKey,1331			PropertiesError::PropertyKeyIsTooLong => Self::PropertyKeyIsTooLong,1332			PropertiesError::EmptyPropertyKey => Self::EmptyPropertyKey,1333		}1334	}1335}
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -298,17 +298,9 @@
 		fail!(<Error<T>>::FungibleDisallowsNesting)
 	}
 
-	fn nest(
-		&self,
-		_under: TokenId,
-		_to_nest: (CollectionId, TokenId)
-	) {}
+	fn nest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}
 
-	fn unnest(
-		&self,
-		_under: TokenId,
-		_to_nest: (CollectionId, TokenId)
-	) {}
+	fn unnest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}
 
 	fn collection_tokens(&self) -> Vec<TokenId> {
 		vec![TokenId::default()]
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -184,11 +184,7 @@
 
 		if balance == 0 {
 			<Balance<T>>::remove((collection.id, owner));
-			<PalletStructure<T>>::unnest_if_nested(
-				owner,
-				collection.id,
-				TokenId::default()
-			);
+			<PalletStructure<T>>::unnest_if_nested(owner, collection.id, TokenId::default());
 		} else {
 			<Balance<T>>::insert((collection.id, owner), balance);
 		}
@@ -249,18 +245,14 @@
 			to,
 			collection.id,
 			TokenId::default(),
-			nesting_budget
+			nesting_budget,
 		)?;
 
 		if let Some(balance_to) = balance_to {
 			// from != to
 			if balance_from == 0 {
 				<Balance<T>>::remove((collection.id, from));
-				<PalletStructure<T>>::unnest_if_nested(
-					from,
-					collection.id,
-					TokenId::default()
-				);
+				<PalletStructure<T>>::unnest_if_nested(from, collection.id, TokenId::default());
 			} else {
 				<Balance<T>>::insert((collection.id, from), balance_from);
 			}
@@ -333,7 +325,11 @@
 		<TotalSupply<T>>::insert(collection.id, total_supply);
 		for (user, amount) in balances {
 			<Balance<T>>::insert((collection.id, &user), amount);
-			<PalletStructure<T>>::nest_if_sent_to_token_unchecked(&user, collection.id, TokenId::default());
+			<PalletStructure<T>>::nest_if_sent_to_token_unchecked(
+				&user,
+				collection.id,
+				TokenId::default(),
+			);
 			<PalletEvm<T>>::deposit_log(
 				ERC20Events::Transfer {
 					from: H160::default(),
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -22,7 +22,7 @@
 	PropertyKeyPermission, PropertyValue,
 };
 use pallet_common::{
-	CommonCollectionOperations, CommonWeightInfo, with_weight, weights::WeightInfo as _
+	CommonCollectionOperations, CommonWeightInfo, with_weight, weights::WeightInfo as _,
 };
 use sp_runtime::DispatchError;
 use sp_std::vec::Vec;
@@ -353,19 +353,11 @@
 		<Pallet<T>>::check_nesting(self, sender, from, under, budget)
 	}
 
-	fn nest(
-		&self,
-		under: TokenId,
-		to_nest: (CollectionId, TokenId)
-	) {
+	fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId)) {
 		<Pallet<T>>::nest((self.id, under), to_nest);
 	}
 
-	fn unnest(
-		&self,
-		under: TokenId,
-		to_unnest: (CollectionId, TokenId)
-	) {
+	fn unnest(&self, under: TokenId, to_unnest: (CollectionId, TokenId)) {
 		<Pallet<T>>::unnest((self.id, under), to_unnest);
 	}
 
@@ -415,10 +407,7 @@
 		.unwrap_or_else(|| {
 			properties
 				.into_iter()
-				.map(|(key, value)| Property {
-					key,
-					value,
-				})
+				.map(|(key, value)| Property { key, value })
 				.collect()
 		})
 	}
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -426,11 +426,10 @@
 	Ok(a)
 }
 
-fn has_token_permission<T: Config>(
-	collection_id: CollectionId,
-	key: &PropertyKey,
-) -> bool {
-	if let Ok(token_property_permissions) = CollectionPropertyPermissions::<T>::try_get(collection_id) {
+fn has_token_permission<T: Config>(collection_id: CollectionId, key: &PropertyKey) -> bool {
+	if let Ok(token_property_permissions) =
+		CollectionPropertyPermissions::<T>::try_get(collection_id)
+	{
 		return token_property_permissions.contains_key(key);
 	}
 
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -164,31 +164,44 @@
 		fn on_runtime_upgrade() -> Weight {
 			if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {
 				let mut had_consts = BTreeSet::new();
-				<TokenData<T>>::translate::<ItemDataVersion1<T::CrossAccountId>, _>(|(collection, token), v| {
-					let mut props = vec![];
-					if !v.const_data.is_empty() {
-						props.push(Property {
-							key: b"_old_constData".to_vec().try_into().unwrap(),
-							value: v.const_data.clone().into_inner().try_into().expect("const too long"),
-						});
-						had_consts.insert(collection);
-					}
-					if !v.variable_data.is_empty() {
-						props.push(Property {
-							key: b"_old_variableData".to_vec().try_into().unwrap(),
-							value: v.variable_data.clone().into_inner().try_into().expect("variable too long"),
-						})
-					}
-					if !props.is_empty() {
-						Self::set_scoped_token_properties(
-							collection,
-							token,
-							PropertyScope::None,
-							props.into_iter(),
-						).expect("existing token data exceeds property storage");
-					}
-					Some(<ItemDataVersion2<T::CrossAccountId>>::from(v))
-				});
+				<TokenData<T>>::translate::<ItemDataVersion1<T::CrossAccountId>, _>(
+					|(collection, token), v| {
+						let mut props = vec![];
+						if !v.const_data.is_empty() {
+							props.push(Property {
+								key: b"_old_constData".to_vec().try_into().unwrap(),
+								value: v
+									.const_data
+									.clone()
+									.into_inner()
+									.try_into()
+									.expect("const too long"),
+							});
+							had_consts.insert(collection);
+						}
+						if !v.variable_data.is_empty() {
+							props.push(Property {
+								key: b"_old_variableData".to_vec().try_into().unwrap(),
+								value: v
+									.variable_data
+									.clone()
+									.into_inner()
+									.try_into()
+									.expect("variable too long"),
+							})
+						}
+						if !props.is_empty() {
+							Self::set_scoped_token_properties(
+								collection,
+								token,
+								PropertyScope::None,
+								props.into_iter(),
+							)
+							.expect("existing token data exceeds property storage");
+						}
+						Some(<ItemDataVersion2<T::CrossAccountId>>::from(v))
+					},
+				);
 				for collection in had_consts {
 					<PalletCommon<T>>::set_property_permission_unchecked(
 						collection,
@@ -199,8 +212,9 @@
 								collection_admin: true,
 								token_owner: false,
 							},
-						}
-					).expect("failed to configure permission");
+						},
+					)
+					.expect("failed to configure permission");
 				}
 			}
 
@@ -263,7 +277,7 @@
 		collection_id: CollectionId,
 		token_id: TokenId,
 		scope: PropertyScope,
-		properties: impl Iterator<Item=Property>,
+		properties: impl Iterator<Item = Property>,
 	) -> DispatchResult {
 		TokenProperties::<T>::try_mutate((collection_id, token_id), |stored_properties| {
 			stored_properties.try_scoped_set_from_iter(scope, properties)
@@ -347,11 +361,7 @@
 			<AccountBalance<T>>::insert((collection.id, token_data.owner.clone()), balance);
 		}
 
-		<PalletStructure<T>>::unnest_if_nested(
-			&token_data.owner,
-			collection.id,
-			token
-		);
+		<PalletStructure<T>>::unnest_if_nested(&token_data.owner, collection.id, token);
 
 		<Owned<T>>::remove((collection.id, &token_data.owner, token));
 		<TokensBurnt<T>>::insert(collection.id, burnt);
@@ -589,16 +599,12 @@
 			to,
 			collection.id,
 			token,
-			nesting_budget
+			nesting_budget,
 		)?;
 
 		// =========
 
-		<PalletStructure<T>>::unnest_if_nested(
-			from,
-			collection.id,
-			token
-		);
+		<PalletStructure<T>>::unnest_if_nested(from, collection.id, token);
 
 		<TokenData<T>>::insert(
 			(collection.id, token),
@@ -709,7 +715,11 @@
 					},
 				);
 
-				<PalletStructure<T>>::nest_if_sent_to_token_unchecked(&data.owner, collection.id, TokenId(token));
+				<PalletStructure<T>>::nest_if_sent_to_token_unchecked(
+					&data.owner,
+					collection.id,
+					TokenId(token),
+				);
 
 				if let Err(e) = Self::set_token_properties(
 					collection,
@@ -958,31 +968,24 @@
 		Ok(())
 	}
 
-	fn nest(
-		under: (CollectionId, TokenId),
-		to_nest: (CollectionId, TokenId),
-	) {
-		<TokenChildren<T>>::insert(
-			(under.0, under.1, (to_nest.0, to_nest.1)),
-			true
-		);
+	fn nest(under: (CollectionId, TokenId), to_nest: (CollectionId, TokenId)) {
+		<TokenChildren<T>>::insert((under.0, under.1, (to_nest.0, to_nest.1)), true);
 	}
 
-	fn unnest(
-		under: (CollectionId, TokenId),
-		to_unnest: (CollectionId, TokenId),
-	) {
-		<TokenChildren<T>>::remove(
-			(under.0, under.1, to_unnest)
-		);
+	fn unnest(under: (CollectionId, TokenId), to_unnest: (CollectionId, TokenId)) {
+		<TokenChildren<T>>::remove((under.0, under.1, to_unnest));
 	}
 
 	fn collection_has_tokens(collection_id: CollectionId) -> bool {
-		<TokenData<T>>::iter_prefix((collection_id,)).next().is_some()
+		<TokenData<T>>::iter_prefix((collection_id,))
+			.next()
+			.is_some()
 	}
 
 	fn token_has_children(collection_id: CollectionId, token_id: TokenId) -> bool {
-		<TokenChildren<T>>::iter_prefix((collection_id, token_id)).next().is_some()
+		<TokenChildren<T>>::iter_prefix((collection_id, token_id))
+			.next()
+			.is_some()
 	}
 
 	/// Delegated to `create_multiple_items`
modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -21,7 +21,9 @@
 use sp_runtime::{DispatchError, Permill, traits::StaticLookup};
 use sp_std::vec::Vec;
 use up_data_structs::*;
-use pallet_common::{Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations};
+use pallet_common::{
+	Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,
+};
 use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};
 use pallet_evm::account::CrossAccountId;
 use core::convert::AsRef;
@@ -38,18 +40,17 @@
 
 #[frame_support::pallet]
 pub mod pallet {
-    use super::*;
-    use pallet_evm::account;
+	use super::*;
+	use pallet_evm::account;
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config
-                    + pallet_common::Config
-                    + pallet_nonfungible::Config
-                    + account::Config {
+	pub trait Config:
+		frame_system::Config + pallet_common::Config + pallet_nonfungible::Config + account::Config
+	{
 		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
 	}
 
-    #[pallet::storage]
+	#[pallet::storage]
 	#[pallet::getter(fn collection_index)]
 	pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;
 
@@ -60,33 +61,33 @@
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
-        CollectionCreated {
+		CollectionCreated {
 			issuer: T::AccountId,
 			collection_id: RmrkCollectionId,
 		},
-        CollectionDestroyed {
+		CollectionDestroyed {
 			issuer: T::AccountId,
 			collection_id: RmrkCollectionId,
 		},
-        IssuerChanged {
+		IssuerChanged {
 			old_issuer: T::AccountId,
 			new_issuer: T::AccountId,
 			collection_id: RmrkCollectionId,
 		},
-        CollectionLocked {
+		CollectionLocked {
 			issuer: T::AccountId,
 			collection_id: RmrkCollectionId,
 		},
-        NftMinted {
+		NftMinted {
 			owner: T::AccountId,
 			collection_id: RmrkCollectionId,
 			nft_id: RmrkNftId,
 		},
-        NFTBurned {
+		NFTBurned {
 			owner: T::AccountId,
 			nft_id: RmrkNftId,
 		},
-        PropertySet {
+		PropertySet {
 			collection_id: RmrkCollectionId,
 			maybe_nft_id: Option<RmrkNftId>,
 			key: RmrkKeyString,
@@ -96,24 +97,24 @@
 
 	#[pallet::error]
 	pub enum Error<T> {
-        /* Unique-specific events */
-        CorruptedCollectionType,
-        NftTypeEncodeError,
-        RmrkPropertyKeyIsTooLong,
-        RmrkPropertyValueIsTooLong,
+		/* Unique-specific events */
+		CorruptedCollectionType,
+		NftTypeEncodeError,
+		RmrkPropertyKeyIsTooLong,
+		RmrkPropertyValueIsTooLong,
 
-        /* RMRK compatible events */
-        CollectionNotEmpty,
-        NoAvailableCollectionId,
-        NoAvailableNftId,
-        CollectionUnknown,
-        NoPermission,
-        CollectionFullOrLocked,
+		/* RMRK compatible events */
+		CollectionNotEmpty,
+		NoAvailableCollectionId,
+		NoAvailableNftId,
+		CollectionUnknown,
+		NoPermission,
+		CollectionFullOrLocked,
 	}
 
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
-        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn create_collection(
 			origin: OriginFor<T>,
@@ -121,127 +122,141 @@
 			max: Option<u32>,
 			symbol: RmrkCollectionSymbol,
 		) -> DispatchResult {
-            let sender = ensure_signed(origin)?;
+			let sender = ensure_signed(origin)?;
 
-            let limits = CollectionLimits {
-                owner_can_transfer: Some(false),
-                token_limit: max,
-                ..Default::default()
-            };
+			let limits = CollectionLimits {
+				owner_can_transfer: Some(false),
+				token_limit: max,
+				..Default::default()
+			};
 
-            let data = CreateCollectionData {
-                limits: Some(limits),
-                token_prefix: symbol.into_inner()
-                    .try_into()
-                    .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
-                ..Default::default()
-            };
+			let data = CreateCollectionData {
+				limits: Some(limits),
+				token_prefix: symbol
+					.into_inner()
+					.try_into()
+					.map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
+				..Default::default()
+			};
 
-            let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);
+			let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);
 
-            if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
-                return Err(<Error<T>>::NoAvailableCollectionId.into());
-            }
+			if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
+				return Err(<Error<T>>::NoAvailableCollectionId.into());
+			}
 
-            let collection_id = collection_id_res?;
+			let collection_id = collection_id_res?;
 
-            <PalletCommon<T>>::set_scoped_collection_properties(
-                collection_id,
-                PropertyScope::Rmrk,
-                [
-                    Self::rmrk_property(Metadata, &metadata)?,
-                    Self::rmrk_property(CollectionType, &misc::CollectionType::Regular)?,
-                ].into_iter()
-            )?;
+			<PalletCommon<T>>::set_scoped_collection_properties(
+				collection_id,
+				PropertyScope::Rmrk,
+				[
+					Self::rmrk_property(Metadata, &metadata)?,
+					Self::rmrk_property(CollectionType, &misc::CollectionType::Regular)?,
+				]
+				.into_iter(),
+			)?;
 
-            <CollectionIndex<T>>::mutate(|n| *n += 1);
+			<CollectionIndex<T>>::mutate(|n| *n += 1);
 
-            Self::deposit_event(Event::CollectionCreated {
-                issuer: sender,
-                collection_id: collection_id.0
-            });
+			Self::deposit_event(Event::CollectionCreated {
+				issuer: sender,
+				collection_id: collection_id.0,
+			});
 
-            Ok(())
-        }
+			Ok(())
+		}
 
-        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn destroy_collection(
 			origin: OriginFor<T>,
 			collection_id: RmrkCollectionId,
 		) -> DispatchResult {
-            let sender = ensure_signed(origin)?;
-            let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+			let sender = ensure_signed(origin)?;
+			let cross_sender = T::CrossAccountId::from_sub(sender.clone());
 
-            let unique_collection_id = collection_id.into();
+			let unique_collection_id = collection_id.into();
 
-            let collection = Self::get_typed_nft_collection(unique_collection_id, misc::CollectionType::Regular)?;
+			let collection = Self::get_typed_nft_collection(
+				unique_collection_id,
+				misc::CollectionType::Regular,
+			)?;
 
-            ensure!(collection.total_supply() == 0, <Error<T>>::CollectionNotEmpty);
+			ensure!(
+				collection.total_supply() == 0,
+				<Error<T>>::CollectionNotEmpty
+			);
 
-            <PalletNft<T>>::destroy_collection(collection, &cross_sender)
-                .map_err(Self::map_common_err_to_proxy)?;
+			<PalletNft<T>>::destroy_collection(collection, &cross_sender)
+				.map_err(Self::map_common_err_to_proxy)?;
 
-            Self::deposit_event(Event::CollectionDestroyed { issuer: sender, collection_id });
+			Self::deposit_event(Event::CollectionDestroyed {
+				issuer: sender,
+				collection_id,
+			});
 
-            Ok(())
-        }
+			Ok(())
+		}
 
-        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn change_collection_issuer(
 			origin: OriginFor<T>,
 			collection_id: RmrkCollectionId,
 			new_issuer: <T::Lookup as StaticLookup>::Source,
 		) -> DispatchResult {
-            let sender = ensure_signed(origin)?;
+			let sender = ensure_signed(origin)?;
 
-            let new_issuer = T::Lookup::lookup(new_issuer)?;
+			let new_issuer = T::Lookup::lookup(new_issuer)?;
 
-            Self::change_collection_owner(
-                collection_id.into(),
-                misc::CollectionType::Regular,
-                sender.clone(),
-                new_issuer.clone()
-            )?;
+			Self::change_collection_owner(
+				collection_id.into(),
+				misc::CollectionType::Regular,
+				sender.clone(),
+				new_issuer.clone(),
+			)?;
 
-            Self::deposit_event(Event::IssuerChanged {
+			Self::deposit_event(Event::IssuerChanged {
 				old_issuer: sender,
 				new_issuer,
 				collection_id,
 			});
 
-            Ok(())
-        }
+			Ok(())
+		}
 
-        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn lock_collection(
 			origin: OriginFor<T>,
 			collection_id: RmrkCollectionId,
 		) -> DispatchResult {
-            let sender = ensure_signed(origin)?;
-            let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+			let sender = ensure_signed(origin)?;
+			let cross_sender = T::CrossAccountId::from_sub(sender.clone());
 
-            let collection = Self::get_typed_nft_collection(
-                collection_id.into(),
-                misc::CollectionType::Regular
-            )?;
+			let collection = Self::get_typed_nft_collection(
+				collection_id.into(),
+				misc::CollectionType::Regular,
+			)?;
 
-            Self::check_collection_owner(&collection, &cross_sender)?;
+			Self::check_collection_owner(&collection, &cross_sender)?;
 
-            let token_count = collection.total_supply();
+			let token_count = collection.total_supply();
 
-            let mut collection = collection.into_inner();
-            collection.limits.token_limit = Some(token_count);
-            collection.save()?;
+			let mut collection = collection.into_inner();
+			collection.limits.token_limit = Some(token_count);
+			collection.save()?;
 
-			Self::deposit_event(Event::CollectionLocked { issuer: sender, collection_id });
+			Self::deposit_event(Event::CollectionLocked {
+				issuer: sender,
+				collection_id,
+			});
 
-            Ok(())
-        }
+			Ok(())
+		}
 
-        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn mint_nft(
 			origin: OriginFor<T>,
@@ -251,47 +266,49 @@
 			royalty_amount: Option<Permill>,
 			metadata: RmrkString,
 		) -> DispatchResult {
-            let sender = ensure_signed(origin)?;
-            let sender = T::CrossAccountId::from_sub(sender);
-            let cross_owner = T::CrossAccountId::from_sub(owner.clone());
+			let sender = ensure_signed(origin)?;
+			let sender = T::CrossAccountId::from_sub(sender);
+			let cross_owner = T::CrossAccountId::from_sub(owner.clone());
 
-            let royalty_info = royalty_amount.map(|amount| rmrk::RoyaltyInfo {
-                recipient: recipient.unwrap_or_else(|| owner.clone()),
-                amount
-            });
+			let royalty_info = royalty_amount.map(|amount| rmrk::RoyaltyInfo {
+				recipient: recipient.unwrap_or_else(|| owner.clone()),
+				amount,
+			});
 
-            let collection = Self::get_typed_nft_collection(
-                collection_id.into(),
-                misc::CollectionType::Regular,
-            )?;
+			let collection = Self::get_typed_nft_collection(
+				collection_id.into(),
+				misc::CollectionType::Regular,
+			)?;
 
-            let nft_id = Self::create_nft(
-                &sender,
-                &cross_owner,
-                &collection,
-                NftType::Regular,
-                [
-                    Self::rmrk_property(RoyaltyInfo, &royalty_info)?,
-                    Self::rmrk_property(Metadata, &metadata)?,
-                    Self::rmrk_property(Equipped, &false)?,
-                    Self::rmrk_property(ResourceCollection, &None::<CollectionId>)?,
-                    Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,
-                ].into_iter()
-            ).map_err(|err| match err {
-                DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),
-                err => Self::map_common_err_to_proxy(err)
-            })?;
+			let nft_id = Self::create_nft(
+				&sender,
+				&cross_owner,
+				&collection,
+				NftType::Regular,
+				[
+					Self::rmrk_property(RoyaltyInfo, &royalty_info)?,
+					Self::rmrk_property(Metadata, &metadata)?,
+					Self::rmrk_property(Equipped, &false)?,
+					Self::rmrk_property(ResourceCollection, &None::<CollectionId>)?,
+					Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,
+				]
+				.into_iter(),
+			)
+			.map_err(|err| match err {
+				DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),
+				err => Self::map_common_err_to_proxy(err),
+			})?;
 
-            Self::deposit_event(Event::NftMinted {
-                owner,
-                collection_id,
-                nft_id: nft_id.0
-            });
+			Self::deposit_event(Event::NftMinted {
+				owner,
+				collection_id,
+				nft_id: nft_id.0,
+			});
 
-            Ok(())
-        }
+			Ok(())
+		}
 
-        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn burn_nft(
 			origin: OriginFor<T>,
@@ -299,21 +316,24 @@
 			nft_id: RmrkNftId,
 		) -> DispatchResult {
 			let sender = ensure_signed(origin)?;
-            let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+			let cross_sender = T::CrossAccountId::from_sub(sender.clone());
 
-            Self::destroy_nft(
-                cross_sender,
-                collection_id.into(),
-                misc::CollectionType::Regular,
-                nft_id.into()
-            )?;
+			Self::destroy_nft(
+				cross_sender,
+				collection_id.into(),
+				misc::CollectionType::Regular,
+				nft_id.into(),
+			)?;
 
-            Self::deposit_event(Event::NFTBurned { owner: sender, nft_id });
+			Self::deposit_event(Event::NFTBurned {
+				owner: sender,
+				nft_id,
+			});
 
-            Ok(())
-        }
+			Ok(())
+		}
 
-        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
 		#[transactional]
 		pub fn set_property(
 			origin: OriginFor<T>,
@@ -322,323 +342,346 @@
 			key: RmrkKeyString,
 			value: RmrkValueString,
 		) -> DispatchResult {
-            let sender = ensure_signed(origin)?;
-            let sender = T::CrossAccountId::from_sub(sender);
+			let sender = ensure_signed(origin)?;
+			let sender = T::CrossAccountId::from_sub(sender);
 
-            let collection_id: CollectionId = rmrk_collection_id.into();
+			let collection_id: CollectionId = rmrk_collection_id.into();
 
-            match maybe_nft_id {
-                Some(nft_id) => {
-                    let token_id: TokenId = nft_id.into();
+			match maybe_nft_id {
+				Some(nft_id) => {
+					let token_id: TokenId = nft_id.into();
 
-                    Self::ensure_nft_owner(collection_id, token_id, &sender)?;
-                    Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;
+					Self::ensure_nft_owner(collection_id, token_id, &sender)?;
+					Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;
 
-                    <PalletNft<T>>::set_scoped_token_property(
-                        collection_id,
-                        token_id,
-                        PropertyScope::Rmrk,
-                        Self::rmrk_property(UserProperty(key.as_slice()), &value)?
-                    )?;
-                },
-                None => {
-                    let collection = Self::get_typed_nft_collection(
-                        collection_id,
-                        misc::CollectionType::Regular
-                    )?;
+					<PalletNft<T>>::set_scoped_token_property(
+						collection_id,
+						token_id,
+						PropertyScope::Rmrk,
+						Self::rmrk_property(UserProperty(key.as_slice()), &value)?,
+					)?;
+				}
+				None => {
+					let collection = Self::get_typed_nft_collection(
+						collection_id,
+						misc::CollectionType::Regular,
+					)?;
 
-                    Self::check_collection_owner(&collection, &sender)?;
+					Self::check_collection_owner(&collection, &sender)?;
 
-                    <PalletCommon<T>>::set_scoped_collection_property(
-                        collection_id,
-                        PropertyScope::Rmrk,
-                        Self::rmrk_property(UserProperty(key.as_slice()), &value)?
-                    )?;
-                }
-            }
+					<PalletCommon<T>>::set_scoped_collection_property(
+						collection_id,
+						PropertyScope::Rmrk,
+						Self::rmrk_property(UserProperty(key.as_slice()), &value)?,
+					)?;
+				}
+			}
 
-            Self::deposit_event(
-                Event::PropertySet {
-                    collection_id: rmrk_collection_id,
-                    maybe_nft_id,
-                    key,
-                    value
-                }
-            );
+			Self::deposit_event(Event::PropertySet {
+				collection_id: rmrk_collection_id,
+				maybe_nft_id,
+				key,
+				value,
+			});
 
-            Ok(())
-        }
+			Ok(())
+		}
 	}
 }
 
 impl<T: Config> Pallet<T> {
-    pub fn rmrk_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {
-        let key = rmrk_key.to_key::<T>()?;
+	pub fn rmrk_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {
+		let key = rmrk_key.to_key::<T>()?;
 
-        let scoped_key = PropertyScope::Rmrk.apply(key)
-            .map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;
+		let scoped_key = PropertyScope::Rmrk
+			.apply(key)
+			.map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;
 
-        Ok(scoped_key)
-    }
+		Ok(scoped_key)
+	}
 
-    pub fn rmrk_property<E: Encode>(rmrk_key: RmrkProperty, value: &E) -> Result<Property, DispatchError> {
-        let key = rmrk_key.to_key::<T>()?;
+	pub fn rmrk_property<E: Encode>(
+		rmrk_key: RmrkProperty,
+		value: &E,
+	) -> Result<Property, DispatchError> {
+		let key = rmrk_key.to_key::<T>()?;
 
-        let value = value.encode()
-            .try_into()
-            .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;
+		let value = value
+			.encode()
+			.try_into()
+			.map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;
 
-        let property = Property {
-            key,
-            value,
-        };
+		let property = Property { key, value };
 
-        Ok(property)
-    }
+		Ok(property)
+	}
 
-    pub fn create_nft(
-        sender: &T::CrossAccountId,
-        owner: &T::CrossAccountId,
-        collection: &NonfungibleHandle<T>,
-        nft_type: NftType,
-        properties: impl Iterator<Item=Property>
-    ) -> Result<TokenId, DispatchError> {
-        todo!("store nft type");
-        let data = CreateNftExData {
-            properties: BoundedVec::default(),
-            owner: owner.clone(),
-        };
+	pub fn create_nft(
+		sender: &T::CrossAccountId,
+		owner: &T::CrossAccountId,
+		collection: &NonfungibleHandle<T>,
+		nft_type: NftType,
+		properties: impl Iterator<Item = Property>,
+	) -> Result<TokenId, DispatchError> {
+		todo!("store nft type");
+		let data = CreateNftExData {
+			properties: BoundedVec::default(),
+			owner: owner.clone(),
+		};
 
-        let budget = budget::Value::new(2);
+		let budget = budget::Value::new(2);
 
-        <PalletNft<T>>::create_item(
-            collection,
-            sender,
-            data,
-            &budget,
-        )?;
+		<PalletNft<T>>::create_item(collection, sender, data, &budget)?;
 
-        let nft_id = <PalletNft<T>>::current_token_id(collection.id);
+		let nft_id = <PalletNft<T>>::current_token_id(collection.id);
 
-        <PalletNft<T>>::set_scoped_token_properties(
-            collection.id,
-            nft_id,
-            PropertyScope::Rmrk,
-            properties
-        )?;
+		<PalletNft<T>>::set_scoped_token_properties(
+			collection.id,
+			nft_id,
+			PropertyScope::Rmrk,
+			properties,
+		)?;
 
-        Ok(nft_id)
-    }
+		Ok(nft_id)
+	}
 
-    fn destroy_nft(
-        sender: T::CrossAccountId,
-        collection_id: CollectionId,
-        collection_type: misc::CollectionType,
-        token_id: TokenId
-    ) -> DispatchResult {
-        let collection = Self::get_typed_nft_collection(
-            collection_id,
-            collection_type
-        )?;
+	fn destroy_nft(
+		sender: T::CrossAccountId,
+		collection_id: CollectionId,
+		collection_type: misc::CollectionType,
+		token_id: TokenId,
+	) -> DispatchResult {
+		let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;
 
-        <PalletNft<T>>::burn(&collection, &sender, token_id)
-            .map_err(Self::map_common_err_to_proxy)?;
+		<PalletNft<T>>::burn(&collection, &sender, token_id)
+			.map_err(Self::map_common_err_to_proxy)?;
 
-        Ok(())
-    }
+		Ok(())
+	}
 
-    fn change_collection_owner(
-        collection_id: CollectionId,
-        collection_type: misc::CollectionType,
-        sender: T::AccountId,
-        new_owner: T::AccountId,
-    ) -> DispatchResult {
-        let collection = Self::get_typed_nft_collection(
-            collection_id,
-            collection_type
-        )?;
-        Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;
+	fn change_collection_owner(
+		collection_id: CollectionId,
+		collection_type: misc::CollectionType,
+		sender: T::AccountId,
+		new_owner: T::AccountId,
+	) -> DispatchResult {
+		let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;
+		Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;
 
-        let mut collection = collection.into_inner();
+		let mut collection = collection.into_inner();
 
-        collection.owner = new_owner;
-        collection.save()
-    }
+		collection.owner = new_owner;
+		collection.save()
+	}
 
-    fn check_collection_owner(collection: &NonfungibleHandle<T>, account: &T::CrossAccountId) -> DispatchResult {
-        collection.check_is_owner(account)
-            .map_err(Self::map_common_err_to_proxy)
-    }
+	fn check_collection_owner(
+		collection: &NonfungibleHandle<T>,
+		account: &T::CrossAccountId,
+	) -> DispatchResult {
+		collection
+			.check_is_owner(account)
+			.map_err(Self::map_common_err_to_proxy)
+	}
 
-    pub fn last_collection_idx() -> RmrkCollectionId {
-        <CollectionIndex<T>>::get()
-    }
+	pub fn last_collection_idx() -> RmrkCollectionId {
+		<CollectionIndex<T>>::get()
+	}
 
-    pub fn get_nft_collection(collection_id: CollectionId) -> Result<NonfungibleHandle<T>, DispatchError> {
-        let collection = <CollectionHandle<T>>::try_get(collection_id)
-            .map_err(|_| <Error<T>>::CollectionUnknown)?;
+	pub fn get_nft_collection(
+		collection_id: CollectionId,
+	) -> Result<NonfungibleHandle<T>, DispatchError> {
+		let collection = <CollectionHandle<T>>::try_get(collection_id)
+			.map_err(|_| <Error<T>>::CollectionUnknown)?;
 
-        match collection.mode {
-            CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),
-            _ => Err(<Error<T>>::CollectionUnknown.into())
-        }
-    }
+		match collection.mode {
+			CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),
+			_ => Err(<Error<T>>::CollectionUnknown.into()),
+		}
+	}
 
-    pub fn collection_exists(collection_id: CollectionId) -> bool {
-        <CollectionHandle<T>>::try_get(collection_id).is_ok()
-    }
+	pub fn collection_exists(collection_id: CollectionId) -> bool {
+		<CollectionHandle<T>>::try_get(collection_id).is_ok()
+	}
 
-    pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {
-        <TokenData<T>>::contains_key((collection_id, nft_id))
-    }
+	pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {
+		<TokenData<T>>::contains_key((collection_id, nft_id))
+	}
 
-    pub fn get_collection_property(collection_id: CollectionId, key: RmrkProperty) -> Result<PropertyValue, DispatchError> {
-        let collection_property = <PalletCommon<T>>::collection_properties(collection_id)
-            .get(&Self::rmrk_property_key(key)?)
-            .ok_or(<Error<T>>::CollectionUnknown)?
-            .clone();
+	pub fn get_collection_property(
+		collection_id: CollectionId,
+		key: RmrkProperty,
+	) -> Result<PropertyValue, DispatchError> {
+		let collection_property = <PalletCommon<T>>::collection_properties(collection_id)
+			.get(&Self::rmrk_property_key(key)?)
+			.ok_or(<Error<T>>::CollectionUnknown)?
+			.clone();
 
-        Ok(collection_property)
-    }
+		Ok(collection_property)
+	}
 
-    pub fn get_collection_type(collection_id: CollectionId) -> Result<misc::CollectionType, DispatchError> {
-        let value = Self::get_collection_property(collection_id, CollectionType)?;
+	pub fn get_collection_type(
+		collection_id: CollectionId,
+	) -> Result<misc::CollectionType, DispatchError> {
+		let value = Self::get_collection_property(collection_id, CollectionType)?;
 
-        let mut value = value.as_slice();
+		let mut value = value.as_slice();
 
-        misc::CollectionType::decode(&mut value)
-            .map_err(|_| <Error<T>>::CorruptedCollectionType.into())
-    }
+		misc::CollectionType::decode(&mut value)
+			.map_err(|_| <Error<T>>::CorruptedCollectionType.into())
+	}
 
-    pub fn ensure_collection_type(collection_id: CollectionId, collection_type: misc::CollectionType) -> DispatchResult {
-        let actual_type = Self::get_collection_type(collection_id)?;
-        ensure!(actual_type == collection_type, <CommonError<T>>::NoPermission);
+	pub fn ensure_collection_type(
+		collection_id: CollectionId,
+		collection_type: misc::CollectionType,
+	) -> DispatchResult {
+		let actual_type = Self::get_collection_type(collection_id)?;
+		ensure!(
+			actual_type == collection_type,
+			<CommonError<T>>::NoPermission
+		);
 
-        Ok(())
-    }
+		Ok(())
+	}
 
-    pub fn get_nft_property(collection_id: CollectionId, nft_id: TokenId, key: RmrkProperty) -> Result<PropertyValue, DispatchError> {
-        let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))
-            .get(&Self::rmrk_property_key(key)?)
-            .ok_or(<Error<T>>::NoAvailableNftId)?
-            .clone();
+	pub fn get_nft_property(
+		collection_id: CollectionId,
+		nft_id: TokenId,
+		key: RmrkProperty,
+	) -> Result<PropertyValue, DispatchError> {
+		let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))
+			.get(&Self::rmrk_property_key(key)?)
+			.ok_or(<Error<T>>::NoAvailableNftId)?
+			.clone();
 
-        Ok(nft_property)
-    }
+		Ok(nft_property)
+	}
 
-    pub fn get_nft_type(_collection_id: CollectionId, _token_id: TokenId) -> Result<NftType, DispatchError> {
-        todo!("should get it from properties?")
-    }
+	pub fn get_nft_type(
+		_collection_id: CollectionId,
+		_token_id: TokenId,
+	) -> Result<NftType, DispatchError> {
+		todo!("should get it from properties?")
+	}
 
-    pub fn ensure_nft_type(collection_id: CollectionId, token_id: TokenId, nft_type: NftType) -> DispatchResult {
-        let actual_type = Self::get_nft_type(collection_id, token_id)?;
-        ensure!(actual_type == nft_type, <Error<T>>::NoPermission);
+	pub fn ensure_nft_type(
+		collection_id: CollectionId,
+		token_id: TokenId,
+		nft_type: NftType,
+	) -> DispatchResult {
+		let actual_type = Self::get_nft_type(collection_id, token_id)?;
+		ensure!(actual_type == nft_type, <Error<T>>::NoPermission);
 
-        Ok(())
-    }
+		Ok(())
+	}
 
-    pub fn ensure_nft_owner(
-        collection_id: CollectionId,
-        token_id: TokenId,
-        possible_owner: &T::CrossAccountId
-    ) -> DispatchResult {
-        let token_data = <TokenData<T>>::get((collection_id, token_id))
-            .ok_or(<Error<T>>::NoAvailableNftId)?;
+	pub fn ensure_nft_owner(
+		collection_id: CollectionId,
+		token_id: TokenId,
+		possible_owner: &T::CrossAccountId,
+	) -> DispatchResult {
+		let token_data =
+			<TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;
 
-        ensure!(token_data.owner == *possible_owner, <Error<T>>::NoPermission);
+		ensure!(
+			token_data.owner == *possible_owner,
+			<Error<T>>::NoPermission
+		);
 
-        Ok(())
-    }
+		Ok(())
+	}
 
-    pub fn filter_user_properties<Key, Value, R, Mapper>(
-        collection_id: CollectionId,
-        token_id: Option<TokenId>,
-        filter_keys: Option<Vec<RmrkPropertyKey>>,
-        mapper: Mapper,
-    ) -> Result<Vec<R>, DispatchError>
-    where
-        Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
-        Value: Decode + Default,
-        Mapper: Fn(Key, Value) -> R
-    {
-        filter_keys.map(|keys| {
-            let properties = keys.into_iter()
-                .filter_map(|key| {
-                    let key: Key = key.try_into().ok()?;
+	pub fn filter_user_properties<Key, Value, R, Mapper>(
+		collection_id: CollectionId,
+		token_id: Option<TokenId>,
+		filter_keys: Option<Vec<RmrkPropertyKey>>,
+		mapper: Mapper,
+	) -> Result<Vec<R>, DispatchError>
+	where
+		Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
+		Value: Decode + Default,
+		Mapper: Fn(Key, Value) -> R,
+	{
+		filter_keys
+			.map(|keys| {
+				let properties = keys
+					.into_iter()
+					.filter_map(|key| {
+						let key: Key = key.try_into().ok()?;
 
-                    let value = match token_id {
-                        Some(token_id) => Self::get_nft_property(
-                            collection_id,
-                            token_id,
-                            UserProperty(key.as_ref())
-                        ),
-                        None => Self::get_collection_property(
-                            collection_id,
-                            UserProperty(key.as_ref())
-                        )
-                    }.ok()?.decode_or_default();
+						let value = match token_id {
+							Some(token_id) => Self::get_nft_property(
+								collection_id,
+								token_id,
+								UserProperty(key.as_ref()),
+							),
+							None => Self::get_collection_property(
+								collection_id,
+								UserProperty(key.as_ref()),
+							),
+						}
+						.ok()?
+						.decode_or_default();
 
-                    Some(mapper(key, value))
-                })
-                .collect();
+						Some(mapper(key, value))
+					})
+					.collect();
 
-            Ok(properties)
-        }).unwrap_or_else(|| {
-            let properties = Self::iterate_user_properties(collection_id, token_id, mapper)?
-                .collect();
+				Ok(properties)
+			})
+			.unwrap_or_else(|| {
+				let properties =
+					Self::iterate_user_properties(collection_id, token_id, mapper)?.collect();
 
-            Ok(properties)
-        })
-    }
+				Ok(properties)
+			})
+	}
 
-    pub fn iterate_user_properties<Key, Value, R, Mapper>(
-        collection_id: CollectionId,
-        token_id: Option<TokenId>,
-        mapper: Mapper,
-    ) -> Result<impl Iterator<Item=R>, DispatchError>
-    where
-        Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
-        Value: Decode + Default,
-        Mapper: Fn(Key, Value) -> R
-    {
-        let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;
+	pub fn iterate_user_properties<Key, Value, R, Mapper>(
+		collection_id: CollectionId,
+		token_id: Option<TokenId>,
+		mapper: Mapper,
+	) -> Result<impl Iterator<Item = R>, DispatchError>
+	where
+		Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
+		Value: Decode + Default,
+		Mapper: Fn(Key, Value) -> R,
+	{
+		let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;
 
-        let properties = match token_id {
-            Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),
-            None => <PalletCommon<T>>::collection_properties(collection_id)
-        };
+		let properties = match token_id {
+			Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),
+			None => <PalletCommon<T>>::collection_properties(collection_id),
+		};
 
-        let properties = properties
-            .into_iter()
-            .filter_map(move |(key, value)| {
-                let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;
+		let properties = properties.into_iter().filter_map(move |(key, value)| {
+			let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;
 
-                let key: Key = key.to_vec().try_into().ok()?;
-                let value: Value = value.decode_or_default();
+			let key: Key = key.to_vec().try_into().ok()?;
+			let value: Value = value.decode_or_default();
 
-                Some(mapper(key, value))
-            });
+			Some(mapper(key, value))
+		});
 
-        Ok(properties)
-    }
+		Ok(properties)
+	}
 
-    pub fn get_typed_nft_collection(
-        collection_id: CollectionId,
-        collection_type: misc::CollectionType
-    ) -> Result<NonfungibleHandle<T>, DispatchError> {
-        Self::ensure_collection_type(collection_id, collection_type)?;
+	pub fn get_typed_nft_collection(
+		collection_id: CollectionId,
+		collection_type: misc::CollectionType,
+	) -> Result<NonfungibleHandle<T>, DispatchError> {
+		Self::ensure_collection_type(collection_id, collection_type)?;
 
-        Self::get_nft_collection(collection_id)
-    }
+		Self::get_nft_collection(collection_id)
+	}
 
-    fn map_common_err_to_proxy(err: DispatchError) -> DispatchError {
-        map_common_err_to_proxy! {
-            match err {
-                NoPermission => NoPermission,
-                CollectionTokenLimitExceeded => CollectionFullOrLocked,
-                PublicMintingNotAllowed => NoPermission,
-                TokenNotFound => NoAvailableNftId
-            }
-        }
-    }
+	fn map_common_err_to_proxy(err: DispatchError) -> DispatchError {
+		map_common_err_to_proxy! {
+			match err {
+				NoPermission => NoPermission,
+				CollectionTokenLimitExceeded => CollectionFullOrLocked,
+				PublicMintingNotAllowed => NoPermission,
+				TokenNotFound => NoAvailableNftId
+			}
+		}
+	}
 }
modifiedpallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/src/misc.rs
+++ b/pallets/proxy-rmrk-core/src/misc.rs
@@ -15,41 +15,42 @@
 }
 
 pub trait RmrkDecode<T: Decode + Default, S> {
-    fn decode_or_default(&self) -> T;
+	fn decode_or_default(&self) -> T;
 }
 
 impl<T: Decode + Default, S> RmrkDecode<T, S> for BoundedVec<u8, S> {
-    fn decode_or_default(&self) -> T {
-        let mut value = self.as_slice();
+	fn decode_or_default(&self) -> T {
+		let mut value = self.as_slice();
 
-        T::decode(&mut value).unwrap_or_default()
-    }
+		T::decode(&mut value).unwrap_or_default()
+	}
 }
 
 pub trait RmrkRebind<T, S> {
-    fn rebind(&self) -> BoundedVec<u8, S>;
+	fn rebind(&self) -> BoundedVec<u8, S>;
 }
 
-impl<T, S> RmrkRebind<T, S> for BoundedVec<u8, T> where BoundedVec<u8, S>: TryFrom<Vec<u8>> {
-    fn rebind(&self) -> BoundedVec<u8, S> {
-        BoundedVec::<u8, S>::try_from(
-            self.clone().into_inner()
-        ).unwrap_or_default()
-    }
+impl<T, S> RmrkRebind<T, S> for BoundedVec<u8, T>
+where
+	BoundedVec<u8, S>: TryFrom<Vec<u8>>,
+{
+	fn rebind(&self) -> BoundedVec<u8, S> {
+		BoundedVec::<u8, S>::try_from(self.clone().into_inner()).unwrap_or_default()
+	}
 }
 
 #[derive(Encode, Decode, PartialEq, Eq)]
 pub enum CollectionType {
-    Regular,
-    Resource,
-    Base,
+	Regular,
+	Resource,
+	Base,
 }
 
 #[derive(Encode, Decode, PartialEq, Eq)]
 pub enum NftType {
-    Regular,
-    Resource,
-    FixedPart,
-    SlotPart,
-    Theme
+	Regular,
+	Resource,
+	FixedPart,
+	SlotPart,
+	Theme,
 }
modifiedpallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/src/property.rs
+++ b/pallets/proxy-rmrk-core/src/property.rs
@@ -2,38 +2,38 @@
 use core::convert::AsRef;
 
 pub enum RmrkProperty<'r> {
-    Metadata,
-    CollectionType,
-    RoyaltyInfo,
-    Equipped,
-    ResourceCollection,
-    ResourcePriorities,
-    ResourceType,
-    PendingResourceAccept,
-    PendingResourceRemoval,
-    Parts,
-    Base,
-    Src,
-    Slot,
-    License,
-    Thumb,
-    EquippedNft,
-    BaseType,
-    ExternalPartId,
-    EquippableList,
-    ZIndex,
-    ThemeName,
-    ThemeInherit,
-    UserProperty(&'r [u8]),
+	Metadata,
+	CollectionType,
+	RoyaltyInfo,
+	Equipped,
+	ResourceCollection,
+	ResourcePriorities,
+	ResourceType,
+	PendingResourceAccept,
+	PendingResourceRemoval,
+	Parts,
+	Base,
+	Src,
+	Slot,
+	License,
+	Thumb,
+	EquippedNft,
+	BaseType,
+	ExternalPartId,
+	EquippableList,
+	ZIndex,
+	ThemeName,
+	ThemeInherit,
+	UserProperty(&'r [u8]),
 }
 
 impl<'r> RmrkProperty<'r> {
-    pub fn to_key<T: Config>(self) -> Result<PropertyKey, Error<T>> {
-        fn get_bytes<T: AsRef<[u8]>>(container: &T) -> &[u8] {
-            container.as_ref()
-        }
+	pub fn to_key<T: Config>(self) -> Result<PropertyKey, Error<T>> {
+		fn get_bytes<T: AsRef<[u8]>>(container: &T) -> &[u8] {
+			container.as_ref()
+		}
 
-        macro_rules! key {
+		macro_rules! key {
             ($($component:expr),+) => {
                 PropertyKey::try_from([$(key!(@ &$component)),+].concat())
                     .map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)
@@ -44,30 +44,30 @@
             };
         }
 
-        match self {
-            Self::Metadata => key!("metadata"),
-            Self::CollectionType => key!("collection-type"),
-            Self::RoyaltyInfo => key!("royalty-info"),
-            Self::Equipped => key!("equipped"),
-            Self::ResourceCollection => key!("resource-collection"),
-            Self::ResourcePriorities => key!("resource-priorities"),
-            Self::ResourceType => key!("resource-type"),
-            Self::PendingResourceAccept => key!("pending-accept"),
-            Self::PendingResourceRemoval => key!("pending-removal"),
-            Self::Parts => key!("parts"),
-            Self::Base => key!("base"),
-            Self::Src => key!("src"),
-            Self::Slot => key!("slot"),
-            Self::License => key!("license"),
-            Self::Thumb => key!("thumb"),
-            Self::EquippedNft => key!("equipped-nft"),
-            Self::BaseType => key!("base-type"),
-            Self::ExternalPartId => key!("ext-part-id"),
-            Self::EquippableList => key!("equippable-list"),
-            Self::ZIndex => key!("z-index"),
-            Self::ThemeName => key!("theme-name"),
-            Self::ThemeInherit => key!("theme-inherit"),
-            Self::UserProperty(name) => key!("userprop-", name),
-        }
-    }
+		match self {
+			Self::Metadata => key!("metadata"),
+			Self::CollectionType => key!("collection-type"),
+			Self::RoyaltyInfo => key!("royalty-info"),
+			Self::Equipped => key!("equipped"),
+			Self::ResourceCollection => key!("resource-collection"),
+			Self::ResourcePriorities => key!("resource-priorities"),
+			Self::ResourceType => key!("resource-type"),
+			Self::PendingResourceAccept => key!("pending-accept"),
+			Self::PendingResourceRemoval => key!("pending-removal"),
+			Self::Parts => key!("parts"),
+			Self::Base => key!("base"),
+			Self::Src => key!("src"),
+			Self::Slot => key!("slot"),
+			Self::License => key!("license"),
+			Self::Thumb => key!("thumb"),
+			Self::EquippedNft => key!("equipped-nft"),
+			Self::BaseType => key!("base-type"),
+			Self::ExternalPartId => key!("ext-part-id"),
+			Self::EquippableList => key!("equippable-list"),
+			Self::ZIndex => key!("z-index"),
+			Self::ThemeName => key!("theme-name"),
+			Self::ThemeInherit => key!("theme-inherit"),
+			Self::UserProperty(name) => key!("userprop-", name),
+		}
+	}
 }
modifiedpallets/proxy-rmrk-equip/src/lib.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-equip/src/lib.rs
+++ b/pallets/proxy-rmrk-equip/src/lib.rs
@@ -21,7 +21,11 @@
 use sp_runtime::DispatchError;
 use up_data_structs::*;
 use pallet_common::{Pallet as PalletCommon, Error as CommonError};
-use pallet_rmrk_core::{Pallet as PalletCore, misc::{self, *}, property::RmrkProperty::*};
+use pallet_rmrk_core::{
+	Pallet as PalletCore,
+	misc::{self, *},
+	property::RmrkProperty::*,
+};
 use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle};
 use pallet_evm::account::CrossAccountId;
 
@@ -29,212 +33,206 @@
 
 #[frame_support::pallet]
 pub mod pallet {
-    use super::*;
+	use super::*;
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config
-                    + pallet_rmrk_core::Config {
+	pub trait Config: frame_system::Config + pallet_rmrk_core::Config {
 		type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
 	}
 
-    #[pallet::storage]
+	#[pallet::storage]
 	#[pallet::getter(fn internal_part_id)]
-	pub type InernalPartId<T: Config> = StorageDoubleMap<
-        _,
-        Twox64Concat,
-        CollectionId,
-        Twox64Concat,
-        RmrkPartId,
-        TokenId
-    >;
+	pub type InernalPartId<T: Config> =
+		StorageDoubleMap<_, Twox64Concat, CollectionId, Twox64Concat, RmrkPartId, TokenId>;
 
-    #[pallet::storage]
+	#[pallet::storage]
 	#[pallet::getter(fn base_has_default_theme)]
-    pub type BaseHasDefaultTheme<T: Config> = StorageMap<
-        _,
-        Twox64Concat,
-        CollectionId,
-        bool,
-        ValueQuery
-    >;
+	pub type BaseHasDefaultTheme<T: Config> =
+		StorageMap<_, Twox64Concat, CollectionId, bool, ValueQuery>;
 
-    #[pallet::pallet]
+	#[pallet::pallet]
 	#[pallet::generate_store(pub(super) trait Store)]
 	pub struct Pallet<T>(_);
 
 	#[pallet::event]
 	#[pallet::generate_deposit(pub(super) fn deposit_event)]
 	pub enum Event<T: Config> {
-        BaseCreated {
+		BaseCreated {
 			issuer: T::AccountId,
 			base_id: RmrkBaseId,
 		},
-    }
+	}
 
-    #[pallet::error]
+	#[pallet::error]
 	pub enum Error<T> {
-        PermissionError,
-        NoAvailableBaseId,
-        NoAvailablePartId,
-        BaseDoesntExist,
-        NeedsDefaultThemeFirst,
-    }
+		PermissionError,
+		NoAvailableBaseId,
+		NoAvailablePartId,
+		BaseDoesntExist,
+		NeedsDefaultThemeFirst,
+	}
 
-    #[pallet::call]
+	#[pallet::call]
 	impl<T: Config> Pallet<T> {
-        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
-        #[transactional]
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[transactional]
 		pub fn create_base(
 			origin: OriginFor<T>,
 			base_type: RmrkString,
 			symbol: RmrkString,
 			parts: BoundedVec<RmrkPartType, RmrkPartsLimit>,
 		) -> DispatchResult {
-            let sender = ensure_signed(origin)?;
-            let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+			let sender = ensure_signed(origin)?;
+			let cross_sender = T::CrossAccountId::from_sub(sender.clone());
 
-            let data = CreateCollectionData {
-                limits: None,
-                token_prefix: symbol.into_inner()
-                    .try_into()
-                    .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
-                ..Default::default()
-            };
+			let data = CreateCollectionData {
+				limits: None,
+				token_prefix: symbol
+					.into_inner()
+					.try_into()
+					.map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
+				..Default::default()
+			};
 
-            let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);
+			let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);
 
-            if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
-                return Err(<Error<T>>::NoAvailableBaseId.into());
-            }
+			if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
+				return Err(<Error<T>>::NoAvailableBaseId.into());
+			}
 
-            let collection_id = collection_id_res?;
+			let collection_id = collection_id_res?;
 
-            <PalletCommon<T>>::set_scoped_collection_properties(
-                collection_id,
-                PropertyScope::Rmrk,
-                [
-                    <PalletCore<T>>::rmrk_property(CollectionType, &misc::CollectionType::Base)?,
-                    <PalletCore<T>>::rmrk_property(BaseType, &base_type)?,
-                ].into_iter()
-            )?;
+			<PalletCommon<T>>::set_scoped_collection_properties(
+				collection_id,
+				PropertyScope::Rmrk,
+				[
+					<PalletCore<T>>::rmrk_property(CollectionType, &misc::CollectionType::Base)?,
+					<PalletCore<T>>::rmrk_property(BaseType, &base_type)?,
+				]
+				.into_iter(),
+			)?;
 
-            let collection = <PalletCore<T>>::get_nft_collection(collection_id)?;
+			let collection = <PalletCore<T>>::get_nft_collection(collection_id)?;
 
-            for part in parts {
-                let part_id = part.id();
-                let part_token_id = Self::create_part(
-                    &cross_sender,
-                    &collection,
-                    part
-                )?;
+			for part in parts {
+				let part_id = part.id();
+				let part_token_id = Self::create_part(&cross_sender, &collection, part)?;
 
-                <InernalPartId<T>>::insert(collection_id, part_id, part_token_id);
+				<InernalPartId<T>>::insert(collection_id, part_id, part_token_id);
 
-                <PalletNft<T>>::set_scoped_token_property(
-                    collection_id,
-                    part_token_id,
-                    PropertyScope::Rmrk,
-                    <PalletCore<T>>::rmrk_property(ExternalPartId, &part_id)?
-                )?;
-            }
+				<PalletNft<T>>::set_scoped_token_property(
+					collection_id,
+					part_token_id,
+					PropertyScope::Rmrk,
+					<PalletCore<T>>::rmrk_property(ExternalPartId, &part_id)?,
+				)?;
+			}
 
-            Self::deposit_event(Event::BaseCreated { issuer: sender, base_id: collection_id.0 });
+			Self::deposit_event(Event::BaseCreated {
+				issuer: sender,
+				base_id: collection_id.0,
+			});
 
-            Ok(())
-        }
+			Ok(())
+		}
 
-        #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
-        #[transactional]
+		#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+		#[transactional]
 		pub fn theme_add(
 			origin: OriginFor<T>,
 			base_id: RmrkBaseId,
 			theme: RmrkTheme,
 		) -> DispatchResult {
-            let sender = ensure_signed(origin)?;
+			let sender = ensure_signed(origin)?;
 
-            let sender = T::CrossAccountId::from_sub(sender);
-            let owner = &sender;
+			let sender = T::CrossAccountId::from_sub(sender);
+			let owner = &sender;
 
-            let collection_id: CollectionId = base_id.into();
+			let collection_id: CollectionId = base_id.into();
 
-            let collection = <PalletCore<T>>::get_typed_nft_collection(
-                collection_id,
-                misc::CollectionType::Base
-            ).map_err(|_| <Error<T>>::BaseDoesntExist)?;
+			let collection = <PalletCore<T>>::get_typed_nft_collection(
+				collection_id,
+				misc::CollectionType::Base,
+			)
+			.map_err(|_| <Error<T>>::BaseDoesntExist)?;
 
-            if theme.name.as_slice() == b"default" {
-                <BaseHasDefaultTheme<T>>::insert(collection_id, true);
-            } else if !Self::base_has_default_theme(collection_id) {
-                return Err(<Error<T>>::NeedsDefaultThemeFirst.into());
-            }
+			if theme.name.as_slice() == b"default" {
+				<BaseHasDefaultTheme<T>>::insert(collection_id, true);
+			} else if !Self::base_has_default_theme(collection_id) {
+				return Err(<Error<T>>::NeedsDefaultThemeFirst.into());
+			}
 
-            let token_id = <PalletCore<T>>::create_nft(
-                &sender,
-                owner,
-                &collection,
-                NftType::Theme,
-                [
-                    <PalletCore<T>>::rmrk_property(ThemeName, &theme.name)?,
-                    <PalletCore<T>>::rmrk_property(ThemeInherit, &theme.inherit)?
-                ].into_iter()
-            ).map_err(|_| <Error<T>>::PermissionError)?;
+			let token_id = <PalletCore<T>>::create_nft(
+				&sender,
+				owner,
+				&collection,
+				NftType::Theme,
+				[
+					<PalletCore<T>>::rmrk_property(ThemeName, &theme.name)?,
+					<PalletCore<T>>::rmrk_property(ThemeInherit, &theme.inherit)?,
+				]
+				.into_iter(),
+			)
+			.map_err(|_| <Error<T>>::PermissionError)?;
 
-            for property in theme.properties {
-                <PalletNft<T>>::set_scoped_token_property(
-                    collection_id,
-                    token_id,
-                    PropertyScope::Rmrk,
-                    <PalletCore<T>>::rmrk_property(
-                        UserProperty(property.key.as_slice()),
-                        &property.value
-                    )?
-                )?;
-            }
+			for property in theme.properties {
+				<PalletNft<T>>::set_scoped_token_property(
+					collection_id,
+					token_id,
+					PropertyScope::Rmrk,
+					<PalletCore<T>>::rmrk_property(
+						UserProperty(property.key.as_slice()),
+						&property.value,
+					)?,
+				)?;
+			}
 
-            Ok(())
-        }
-    }
+			Ok(())
+		}
+	}
 }
 
 impl<T: Config> Pallet<T> {
-    fn create_part(
-        sender: &T::CrossAccountId,
-        collection: &NonfungibleHandle<T>,
-        part: RmrkPartType
-    ) -> Result<TokenId, DispatchError> {
-        let owner = sender;
+	fn create_part(
+		sender: &T::CrossAccountId,
+		collection: &NonfungibleHandle<T>,
+		part: RmrkPartType,
+	) -> Result<TokenId, DispatchError> {
+		let owner = sender;
 
-        let src = part.src();
-        let z_index = part.z_index();
+		let src = part.src();
+		let z_index = part.z_index();
 
-        let nft_type = match part {
-            RmrkPartType::FixedPart(_) => NftType::FixedPart,
-            RmrkPartType::SlotPart(_) => NftType::SlotPart,
-        };
+		let nft_type = match part {
+			RmrkPartType::FixedPart(_) => NftType::FixedPart,
+			RmrkPartType::SlotPart(_) => NftType::SlotPart,
+		};
 
-        let token_id = <PalletCore<T>>::create_nft(
-            sender,
-            owner,
-            collection,
-            nft_type,
-            [
-                <PalletCore<T>>::rmrk_property(Src, &src)?,
-                <PalletCore<T>>::rmrk_property(ZIndex, &z_index)?
-            ].into_iter()
-        ).map_err(|err| match err {
-            DispatchError::Arithmetic(_) => <Error<T>>::NoAvailablePartId.into(),
-            err => err
-        })?;
+		let token_id = <PalletCore<T>>::create_nft(
+			sender,
+			owner,
+			collection,
+			nft_type,
+			[
+				<PalletCore<T>>::rmrk_property(Src, &src)?,
+				<PalletCore<T>>::rmrk_property(ZIndex, &z_index)?,
+			]
+			.into_iter(),
+		)
+		.map_err(|err| match err {
+			DispatchError::Arithmetic(_) => <Error<T>>::NoAvailablePartId.into(),
+			err => err,
+		})?;
 
-        if let RmrkPartType::SlotPart(part) = part {
-            <PalletNft<T>>::set_scoped_token_property(
-                collection.id,
-                token_id,
-                PropertyScope::Rmrk,
-                <PalletCore<T>>::rmrk_property(EquippableList, &part.equippable)?
-            )?;
-        }
+		if let RmrkPartType::SlotPart(part) = part {
+			<PalletNft<T>>::set_scoped_token_property(
+				collection.id,
+				token_id,
+				PropertyScope::Rmrk,
+				<PalletCore<T>>::rmrk_property(EquippableList, &part.equippable)?,
+			)?;
+		}
 
-        Ok(token_id)
-    }
+		Ok(token_id)
+	}
 }
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -313,17 +313,9 @@
 		fail!(<Error<T>>::RefungibleDisallowsNesting)
 	}
 
-	fn nest(
-		&self,
-		_under: TokenId,
-		_to_nest: (CollectionId, TokenId)
-	) {}
+	fn nest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}
 
-	fn unnest(
-		&self,
-		_under: TokenId,
-		_to_nest: (CollectionId, TokenId)
-	) {}
+	fn unnest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}
 
 	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {
 		<Owned<T>>::iter_prefix((self.id, account))
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -22,9 +22,7 @@
 	CreateCollectionData, CreateRefungibleExData, mapping::TokenAddressMapping, budget::Budget,
 };
 use pallet_evm::account::CrossAccountId;
-use pallet_common::{
-	Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,
-};
+use pallet_common::{Error as CommonError, Event as CommonEvent, Pallet as PalletCommon};
 use pallet_structure::Pallet as PalletStructure;
 use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
 use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
@@ -230,7 +228,9 @@
 	}
 
 	fn collection_has_tokens(collection_id: CollectionId) -> bool {
-		<TokenData<T>>::iter_prefix((collection_id,)).next().is_some()
+		<TokenData<T>>::iter_prefix((collection_id,))
+			.next()
+			.is_some()
 	}
 
 	pub fn burn_token(collection: &RefungibleHandle<T>, token_id: TokenId) -> DispatchResult {
@@ -388,18 +388,14 @@
 			to,
 			collection.id,
 			token,
-			nesting_budget
+			nesting_budget,
 		)?;
 
 		if let Some(balance_to) = balance_to {
 			// from != to
 			if balance_from == 0 {
 				<Balance<T>>::remove((collection.id, token, from));
-				<PalletStructure<T>>::unnest_if_nested(
-					from,
-					collection.id,
-					token
-				);
+				<PalletStructure<T>>::unnest_if_nested(from, collection.id, token);
 			} else {
 				<Balance<T>>::insert((collection.id, token, from), balance_from);
 			}
@@ -497,7 +493,6 @@
 		for (i, token) in data.iter().enumerate() {
 			let token_id = TokenId(first_token_id + i as u32 + 1);
 			for (to, _) in token.users.iter() {
-
 				<PalletStructure<T>>::check_nesting(
 					sender.clone(),
 					to,
@@ -531,7 +526,11 @@
 				}
 				<Balance<T>>::insert((collection.id, token_id, &user), amount);
 				<Owned<T>>::insert((collection.id, &user, TokenId(token_id)), true);
-				<PalletStructure<T>>::nest_if_sent_to_token_unchecked(&user, collection.id, TokenId(token_id));
+				<PalletStructure<T>>::nest_if_sent_to_token_unchecked(
+					&user,
+					collection.id,
+					TokenId(token_id),
+				);
 
 				// TODO: ERC20 transfer event
 				<PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(
modifiedpallets/structure/src/lib.rsdiffbeforeafterboth
--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -189,17 +189,11 @@
 		under: &T::CrossAccountId,
 		collection_id: CollectionId,
 		token_id: TokenId,
-		nesting_budget: &dyn Budget
+		nesting_budget: &dyn Budget,
 	) -> DispatchResult {
-		Self::try_exec_if_owner_is_valid_nft(
-			under,
-			|d, parent_id| d.check_nesting(
-				from,
-				(collection_id, token_id),
-				parent_id,
-				nesting_budget
-			)
-		)
+		Self::try_exec_if_owner_is_valid_nft(under, |d, parent_id| {
+			d.check_nesting(from, (collection_id, token_id), parent_id, nesting_budget)
+		})
 	}
 
 	pub fn nest_if_sent_to_token(
@@ -207,69 +201,51 @@
 		under: &T::CrossAccountId,
 		collection_id: CollectionId,
 		token_id: TokenId,
-		nesting_budget: &dyn Budget
+		nesting_budget: &dyn Budget,
 	) -> DispatchResult {
-		Self::try_exec_if_owner_is_valid_nft(
-			under,
-			|d, parent_id| {
-				d.check_nesting(
-					from,
-					(collection_id, token_id),
-					parent_id,
-					nesting_budget
-				)?;
+		Self::try_exec_if_owner_is_valid_nft(under, |d, parent_id| {
+			d.check_nesting(from, (collection_id, token_id), parent_id, nesting_budget)?;
 
-				d.nest(parent_id, (collection_id, token_id));
+			d.nest(parent_id, (collection_id, token_id));
 
-				Ok(())
-			}
-		)
+			Ok(())
+		})
 	}
 
 	pub fn nest_if_sent_to_token_unchecked(
 		owner: &T::CrossAccountId,
 		collection_id: CollectionId,
-		token_id: TokenId
+		token_id: TokenId,
 	) {
-		Self::exec_if_owner_is_valid_nft(
-			owner,
-			|d, parent_id| d.nest(
-				parent_id,
-				(collection_id, token_id)
-			)
-		);
+		Self::exec_if_owner_is_valid_nft(owner, |d, parent_id| {
+			d.nest(parent_id, (collection_id, token_id))
+		});
 	}
 
 	pub fn unnest_if_nested(
 		owner: &T::CrossAccountId,
 		collection_id: CollectionId,
-		token_id: TokenId
+		token_id: TokenId,
 	) {
-		Self::exec_if_owner_is_valid_nft(
-			owner,
-			|d, parent_id| d.unnest(
-			parent_id,
-			(collection_id, token_id)
-			)
-		);
+		Self::exec_if_owner_is_valid_nft(owner, |d, parent_id| {
+			d.unnest(parent_id, (collection_id, token_id))
+		});
 	}
 
 	fn exec_if_owner_is_valid_nft(
 		account: &T::CrossAccountId,
-		action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId)
+		action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId),
 	) {
-		Self::try_exec_if_owner_is_valid_nft(
-			account,
-			|d, id| {
-				action(d, id);
-				Ok(())
-			}
-		).unwrap();
+		Self::try_exec_if_owner_is_valid_nft(account, |d, id| {
+			action(d, id);
+			Ok(())
+		})
+		.unwrap();
 	}
 
 	fn try_exec_if_owner_is_valid_nft(
 		account: &T::CrossAccountId,
-		action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId) -> DispatchResult
+		action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId) -> DispatchResult,
 	) -> DispatchResult {
 		let account = T::CrossTokenAddressMapping::address_to_token(account);
 
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -37,11 +37,10 @@
 use frame_system::{self as system, ensure_signed};
 use sp_runtime::{sp_std::prelude::Vec};
 use up_data_structs::{
-	MAX_COLLECTION_NAME_LENGTH,
-	MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, AccessMode, CreateItemData,
-	CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId, SponsorshipState,
-	CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,
-	PropertyKeyPermission,
+	MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,
+	AccessMode, CreateItemData, CollectionLimits, CollectionPermissions, CollectionId,
+	CollectionMode, TokenId, SponsorshipState, CreateCollectionData, CreateItemExData, budget,
+	Property, PropertyKey, PropertyKeyPermission,
 };
 use pallet_evm::account::CrossAccountId;
 use pallet_common::{
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -49,7 +49,8 @@
 	},
 	NftChild as RmrkNftChild, AccountIdOrCollectionNftTuple as RmrkAccountIdOrCollectionNftTuple,
 	FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart, EquippableList as RmrkEquippableList,
-	BasicResource as RmrkBasicResource, ComposableResource as RmrkComposableResource, SlotResource as RmrkSlotResource,
+	BasicResource as RmrkBasicResource, ComposableResource as RmrkComposableResource,
+	SlotResource as RmrkSlotResource,
 };
 
 mod bounded;
@@ -361,8 +362,7 @@
 pub type CollectionPropertiesPermissionsVec =
 	BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;
 
-pub type CollectionPropertiesVec =
-	BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;
+pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;
 
 /// All fields are wrapped in `Option`s, where None means chain default
 // When adding/removing fields from this struct - don't forget to also update clamp_limits
@@ -790,8 +790,8 @@
 	>::IntoIter;
 
 	fn into_iter(self) -> Self::IntoIter {
-        self.0.into_iter()
-    }
+		self.0.into_iter()
+	}
 }
 
 impl<Value> TrySetProperty for PropertiesMap<Value> {
@@ -853,8 +853,8 @@
 	type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;
 
 	fn into_iter(self) -> Self::IntoIter {
-        self.map.into_iter()
-    }
+		self.map.into_iter()
+	}
 }
 
 impl TrySetProperty for Properties {
@@ -932,11 +932,7 @@
 pub type RmrkCollectionInfo<AccountId> =
 	CollectionInfo<RmrkString, RmrkCollectionSymbol, AccountId>;
 pub type RmrkInstanceInfo<AccountId> = NftInfo<AccountId, Permill, RmrkString>;
-pub type RmrkResourceInfo = ResourceInfo<
-	RmrkBoundedResource,
-	RmrkString,
-	RmrkBoundedParts,
->;
+pub type RmrkResourceInfo = ResourceInfo<RmrkBoundedResource, RmrkString, RmrkBoundedParts>;
 pub type RmrkPropertyInfo = PropertyInfo<RmrkKeyString, RmrkValueString>;
 pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;
 pub type RmrkPartType =
modifiedprimitives/data-structs/src/rmrk.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/rmrk.rs
+++ b/primitives/data-structs/src/rmrk.rs
@@ -20,37 +20,37 @@
 
 #[cfg(feature = "std")]
 mod serialize {
-    use core::convert::AsRef;
-    use serde::ser::{self, Serialize};
+	use core::convert::AsRef;
+	use serde::ser::{self, Serialize};
 
-    pub mod vec {
-        use super::*;
+	pub mod vec {
+		use super::*;
 
-        pub fn serialize<D, V, C>(value: &C, serializer: D) -> Result<D::Ok, D::Error>
-        where
-            D: ser::Serializer,
-            V: Serialize,
-            C: AsRef<[V]>,
-        {
-            value.as_ref().serialize(serializer)
-        }
-    }
+		pub fn serialize<D, V, C>(value: &C, serializer: D) -> Result<D::Ok, D::Error>
+		where
+			D: ser::Serializer,
+			V: Serialize,
+			C: AsRef<[V]>,
+		{
+			value.as_ref().serialize(serializer)
+		}
+	}
 
-    pub mod opt_vec {
-        use super::*;
+	pub mod opt_vec {
+		use super::*;
 
-        pub fn serialize<D, V, C>(value: &Option<C>, serializer: D) -> Result<D::Ok, D::Error>
-        where
-            D: ser::Serializer,
-            V: Serialize,
-            C: AsRef<[V]>,
-        {
-            match value {
-                Some(value) => super::vec::serialize(value, serializer),
-                None => serializer.serialize_none()
-            }
-        }
-    }
+		pub fn serialize<D, V, C>(value: &Option<C>, serializer: D) -> Result<D::Ok, D::Error>
+		where
+			D: ser::Serializer,
+			V: Serialize,
+			C: AsRef<[V]>,
+		{
+			match value {
+				Some(value) => super::vec::serialize(value, serializer),
+				None => serializer.serialize_none(),
+			}
+		}
+	}
 }
 
 /// Collection info.
@@ -58,13 +58,11 @@
 #[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
 #[cfg_attr(
 	feature = "std",
-	serde(
-		bound = r#"
+	serde(bound = r#"
 			AccountId: Serialize,
 			BoundedString: AsRef<[u8]>,
 			BoundedSymbol: AsRef<[u8]>
-		"#
-	)
+		"#)
 )]
 pub struct CollectionInfo<BoundedString, BoundedSymbol, AccountId> {
 	/// Current bidder and bid price.
@@ -91,9 +89,9 @@
 #[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
 pub struct RoyaltyInfo<AccountId, RoyaltyAmount> {
 	/// Recipient (AccountId) of the royalty
-    pub recipient: AccountId,
+	pub recipient: AccountId,
 	/// Amount (Permill) of the royalty
-    pub amount: RoyaltyAmount,
+	pub amount: RoyaltyAmount,
 }
 
 /// Nft info.
@@ -101,13 +99,11 @@
 #[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
 #[cfg_attr(
 	feature = "std",
-	serde(
-		bound = r#"
+	serde(bound = r#"
 			AccountId: Serialize,
 			RoyaltyAmount: Serialize,
 			BoundedString: AsRef<[u8]>
-		"#
-	)
+		"#)
 )]
 pub struct NftInfo<AccountId, RoyaltyAmount, BoundedString> {
 	/// The owner of the NFT, can be either an Account or a tuple (CollectionId, NftId)
@@ -129,22 +125,19 @@
 #[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]
 pub struct NftChild {
 	pub collection_id: CollectionId,
-	pub nft_id: NftId
+	pub nft_id: NftId,
 }
 
 #[cfg_attr(feature = "std", derive(Serialize))]
 #[derive(Encode, Decode, PartialEq, TypeInfo)]
 #[cfg_attr(
 	feature = "std",
-	serde(
-		bound = r#"
+	serde(bound = r#"
 			BoundedKey: AsRef<[u8]>,
 			BoundedValue: AsRef<[u8]>
-		"#
-	)
+		"#)
 )]
-pub struct PropertyInfo<BoundedKey, BoundedValue>
-{
+pub struct PropertyInfo<BoundedKey, BoundedValue> {
 	/// Key of the property
 	#[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
 	pub key: BoundedKey,
@@ -156,10 +149,7 @@
 
 #[derive(Encode, Decode, Default, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
 #[cfg_attr(feature = "std", derive(Serialize))]
-#[cfg_attr(
-	feature = "std",
-	serde(bound = "BoundedString: AsRef<[u8]>")
-)]
+#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
 pub struct BasicResource<BoundedString> {
 	/// If the resource is Media, the base property is absent. Media src should be a URI like an
 	/// IPFS hash.
@@ -188,12 +178,10 @@
 #[cfg_attr(feature = "std", derive(Serialize))]
 #[cfg_attr(
 	feature = "std",
-	serde(
-		bound = r#"
+	serde(bound = r#"
 			BoundedString: AsRef<[u8]>,
 			BoundedParts: AsRef<[PartId]>
-		"#
-	)
+		"#)
 )]
 pub struct ComposableResource<BoundedString, BoundedParts> {
 	/// If a resource is composed, it will have an array of parts that compose it
@@ -235,10 +223,7 @@
 
 #[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
 #[cfg_attr(feature = "std", derive(Serialize))]
-#[cfg_attr(
-	feature = "std",
-	serde(bound = "BoundedString: AsRef<[u8]>")
-)]
+#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
 pub struct SlotResource<BoundedString> {
 	/// A Base is uniquely identified by the combination of the word `base`, its minting block
 	/// number, and user provided symbol during Base creation, glued by dashes `-`, e.g.
@@ -279,14 +264,12 @@
 #[cfg_attr(feature = "std", derive(Serialize))]
 #[cfg_attr(
 	feature = "std",
-	serde(
-		bound = r#"
+	serde(bound = r#"
 			BoundedString: AsRef<[u8]>,
 			BoundedParts: AsRef<[PartId]>
-		"#
-	)
+		"#)
 )]
-#[derivative(Default(bound=""))]
+#[derivative(Default(bound = ""))]
 pub enum ResourceTypes<BoundedString: Default, BoundedParts> {
 	#[derivative(Default)]
 	Basic(BasicResource<BoundedString>),
@@ -294,18 +277,15 @@
 	Slot(SlotResource<BoundedString>),
 }
 
-
 #[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
 #[cfg_attr(feature = "std", derive(Serialize))]
 #[cfg_attr(
 	feature = "std",
-	serde(
-		bound = r#"
+	serde(bound = r#"
 			BoundedResource: AsRef<[u8]>,
 			BoundedString: AsRef<[u8]>,
 			BoundedParts: AsRef<[PartId]>
-		"#
-	)
+		"#)
 )]
 pub struct ResourceInfo<BoundedResource, BoundedString: Default, BoundedParts> {
 	/// id is a 5-character string of reasonable uniqueness.
@@ -328,12 +308,10 @@
 #[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
 #[cfg_attr(
 	feature = "std",
-	serde(
-		bound = r#"
+	serde(bound = r#"
 			AccountId: Serialize,
 			BoundedString: AsRef<[u8]>
-		"#
-	)
+		"#)
 )]
 pub struct BaseInfo<AccountId, BoundedString> {
 	/// Original creator of the Base
@@ -350,10 +328,7 @@
 
 #[cfg_attr(feature = "std", derive(Serialize))]
 #[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]
-#[cfg_attr(
-	feature = "std",
-	serde(bound = "BoundedString: AsRef<[u8]>")
-)]
+#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
 pub struct FixedPart<BoundedString> {
 	pub id: PartId,
 	pub z: ZIndex,
@@ -368,29 +343,24 @@
 	feature = "std",
 	serde(bound = "BoundedCollectionList: AsRef<[CollectionId]>")
 )]
-#[derivative(Default(bound=""))]
+#[derivative(Default(bound = ""))]
 pub enum EquippableList<BoundedCollectionList> {
 	All,
 
 	#[derivative(Default)]
 	Empty,
 
-	Custom(
-		#[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
-		BoundedCollectionList
-	),
+	Custom(#[cfg_attr(feature = "std", serde(with = "serialize::vec"))] BoundedCollectionList),
 }
 
 #[cfg_attr(feature = "std", derive(Serialize))]
 #[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]
 #[cfg_attr(
 	feature = "std",
-	serde(
-		bound = r#"
+	serde(bound = r#"
 			BoundedString: AsRef<[u8]>,
 			BoundedCollectionList: AsRef<[CollectionId]>
-		"#
-	)
+		"#)
 )]
 pub struct SlotPart<BoundedString, BoundedCollectionList> {
 	pub id: PartId,
@@ -406,12 +376,10 @@
 #[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]
 #[cfg_attr(
 	feature = "std",
-	serde(
-		bound = r#"
+	serde(bound = r#"
 			BoundedString: AsRef<[u8]>,
 			BoundedCollectionList: AsRef<[CollectionId]>
-		"#
-	)
+		"#)
 )]
 pub enum PartType<BoundedString, BoundedCollectionList> {
 	FixedPart(FixedPart<BoundedString>),
@@ -422,21 +390,21 @@
 	pub fn id(&self) -> PartId {
 		match self {
 			Self::FixedPart(part) => part.id,
-			Self::SlotPart(part) => part.id
+			Self::SlotPart(part) => part.id,
 		}
 	}
 
 	pub fn src(&self) -> &BoundedString {
 		match self {
 			Self::FixedPart(part) => &part.src,
-			Self::SlotPart(part) => &part.src
+			Self::SlotPart(part) => &part.src,
 		}
 	}
 
 	pub fn z_index(&self) -> ZIndex {
 		match self {
 			Self::FixedPart(part) => part.z,
-			Self::SlotPart(part) => part.z
+			Self::SlotPart(part) => part.z,
 		}
 	}
 }
@@ -445,12 +413,10 @@
 #[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq)]
 #[cfg_attr(
 	feature = "std",
-	serde(
-		bound = r#"
+	serde(bound = r#"
 			BoundedString: AsRef<[u8]>,
 			PropertyList: AsRef<[ThemeProperty<BoundedString>]>,
-		"#
-	)
+		"#)
 )]
 pub struct Theme<BoundedString, PropertyList> {
 	/// Name of the theme
@@ -466,10 +432,7 @@
 
 #[cfg_attr(feature = "std", derive(Eq, Serialize))]
 #[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq)]
-#[cfg_attr(
-	feature = "std",
-	serde(bound = "BoundedString: AsRef<[u8]>")
-)]
+#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
 pub struct ThemeProperty<BoundedString> {
 	/// Key of the property
 	#[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
modifiedruntime/tests/src/tests.rsdiffbeforeafterboth
--- a/runtime/tests/src/tests.rs
+++ b/runtime/tests/src/tests.rs
@@ -19,9 +19,9 @@
 use up_data_structs::{
 	COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,
 	CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, TokenId,
-	MAX_TOKEN_OWNERSHIP, CreateCollectionData, CollectionMode,
-	AccessMode, CollectionPermissions, PropertyKeyPermission, PropertyPermission,
-	Property, CollectionPropertiesVec, CollectionPropertiesPermissionsVec,
+	MAX_TOKEN_OWNERSHIP, CreateCollectionData, CollectionMode, AccessMode, CollectionPermissions,
+	PropertyKeyPermission, PropertyPermission, Property, CollectionPropertiesVec,
+	CollectionPropertiesPermissionsVec,
 };
 use frame_support::{assert_noop, assert_ok, assert_err};
 use sp_std::convert::TryInto;
@@ -47,12 +47,12 @@
 
 fn default_nft_data() -> CreateNftData {
 	CreateNftData {
-		properties: vec![
-			Property {
-				key: b"test-prop".to_vec().try_into().unwrap(),
-				value: b"test-nft-prop".to_vec().try_into().unwrap(),
-			},
-		].try_into().unwrap(),
+		properties: vec![Property {
+			key: b"test-prop".to_vec().try_into().unwrap(),
+			value: b"test-nft-prop".to_vec().try_into().unwrap(),
+		}]
+		.try_into()
+		.unwrap(),
 	}
 }
 
@@ -77,22 +77,23 @@
 	let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
 	let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
 	let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
-	let token_property_permissions: CollectionPropertiesPermissionsVec = vec![
-		PropertyKeyPermission {
+	let token_property_permissions: CollectionPropertiesPermissionsVec =
+		vec![PropertyKeyPermission {
 			key: b"test-prop".to_vec().try_into().unwrap(),
 			permission: PropertyPermission {
 				mutable: true,
 				collection_admin: false,
 				token_owner: true,
 			},
-		},
-	].try_into().unwrap();
-	let properties: CollectionPropertiesVec = vec![
-		Property {
-			key: b"test-collection-prop".to_vec().try_into().unwrap(),
-			value: b"test-collection-value".to_vec().try_into().unwrap(),
-		}
-	].try_into().unwrap();
+		}]
+		.try_into()
+		.unwrap();
+	let properties: CollectionPropertiesVec = vec![Property {
+		key: b"test-collection-prop".to_vec().try_into().unwrap(),
+		value: b"test-collection-value".to_vec().try_into().unwrap(),
+	}]
+	.try_into()
+	.unwrap();
 
 	let data: CreateCollectionData<u64> = CreateCollectionData {
 		name: col_name1.try_into().unwrap(),
@@ -150,30 +151,21 @@
 fn get_collection_property_permissions(collection_id: CollectionId) -> Vec<PropertyKeyPermission> {
 	<pallet_common::Pallet<Test>>::property_permissions(collection_id)
 		.into_iter()
-		.map(|(key, permission)| PropertyKeyPermission {
-			key,
-			permission,
-		})
+		.map(|(key, permission)| PropertyKeyPermission { key, permission })
 		.collect()
 }
 
 fn get_collection_properties(collection_id: CollectionId) -> Vec<Property> {
 	<pallet_common::Pallet<Test>>::collection_properties(collection_id)
 		.into_iter()
-		.map(|(key, value)| Property {
-			key,
-			value,
-		})
+		.map(|(key, value)| Property { key, value })
 		.collect()
 }
 
 fn get_token_properties(collection_id: CollectionId, token_id: TokenId) -> Vec<Property> {
 	<pallet_nonfungible::Pallet<Test>>::token_properties((collection_id, token_id))
 		.into_iter()
-		.map(|(key, value)| Property {
-			key,
-			value,
-		})
+		.map(|(key, value)| Property { key, value })
 		.collect()
 }