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

difftreelog

refactor(interface) remove outdated benchmarks

Yaroslav Bolyukin2021-10-22parent: #d54d8c2.patch.diff
in: master

3 files changed

modifiedpallets/nft/src/benchmarking.rsdiffbeforeafterboth
--- a/pallets/nft/src/benchmarking.rs
+++ b/pallets/nft/src/benchmarking.rs
@@ -7,35 +7,10 @@
 use nft_data_structs::*;
 use core::convert::TryInto;
 use sp_runtime::DispatchError;
+use pallet_common::benchmarking::{create_data, create_u16_data};
 
 const SEED: u32 = 1;
-
-fn create_data(size: usize) -> Vec<u8> {
-	(0..size).map(|v| (v & 0xff) as u8).collect()
-}
-fn create_u16_data(size: usize) -> Vec<u16> {
-	(0..size).map(|v| (v & 0xffff) as u16).collect()
-}
-
-fn default_nft_data() -> CreateItemData {
-	CreateItemData::NFT(CreateNftData {
-		const_data: create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(),
-		variable_data: create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(),
-	})
-}
 
-fn default_fungible_data() -> CreateItemData {
-	CreateItemData::Fungible(CreateFungibleData { value: 1000 })
-}
-
-fn default_re_fungible_data() -> CreateItemData {
-	CreateItemData::ReFungible(CreateReFungibleData {
-		const_data: create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(),
-		variable_data: create_data(CUSTOM_DATA_LIMIT as usize).try_into().unwrap(),
-		pieces: 1000,
-	})
-}
-
 fn create_collection_helper<T: Config>(
 	owner: T::AccountId,
 	mode: CollectionMode,
@@ -55,20 +30,10 @@
 		token_prefix,
 		mode,
 	)?;
-	Ok(CreatedCollectionCount::get())
+	Ok(<pallet_common::CreatedCollectionCount<T>>::get())
 }
 fn create_nft_collection<T: Config>(owner: T::AccountId) -> Result<CollectionId, DispatchError> {
 	create_collection_helper::<T>(owner, CollectionMode::NFT)
-}
-fn create_fungible_collection<T: Config>(
-	owner: T::AccountId,
-) -> Result<CollectionId, DispatchError> {
-	create_collection_helper::<T>(owner, CollectionMode::Fungible(0))
-}
-fn create_refungible_collection<T: Config>(
-	owner: T::AccountId,
-) -> Result<CollectionId, DispatchError> {
-	create_collection_helper::<T>(owner, CollectionMode::ReFungible)
 }
 
 benchmarks! {
@@ -82,7 +47,7 @@
 		T::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get());
 	}: _(RawOrigin::Signed(caller.clone()), col_name.clone(), col_desc.clone(), token_prefix.clone(), mode)
 	verify {
-		assert_eq!(<Pallet<T>>::collection_id(2).unwrap().owner, caller);
+		assert_eq!(<pallet_common::CollectionById<T>>::get(CollectionId(1)).unwrap().owner, caller);
 	}
 
 	destroy_collection {
@@ -129,7 +94,7 @@
 		let caller: T::AccountId = account("caller", 0, SEED);
 		let collection = create_nft_collection::<T>(caller.clone())?;
 		let new_admin: T::AccountId = account("admin", 0, SEED);
-		<Pallet<T>>::add_collection_admin(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(new_admin.clone()))?;
+		<Pallet<T>>::add_collection_admin(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(new_admin.clone()))?;
 	}: _(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(new_admin))
 
 	set_collection_sponsor {
@@ -140,152 +105,21 @@
 	confirm_sponsorship {
 		let caller: T::AccountId = account("caller", 0, SEED);
 		let collection = create_nft_collection::<T>(caller.clone())?;
-		<Pallet<T>>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone())?;
+		<Pallet<T>>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), collection, caller.clone())?;
 	}: _(RawOrigin::Signed(caller.clone()), collection)
 
 	remove_collection_sponsor {
 		let caller: T::AccountId = account("caller", 0, SEED);
 		let collection = create_nft_collection::<T>(caller.clone())?;
-		<Pallet<T>>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), 2, caller.clone())?;
-		<Pallet<T>>::confirm_sponsorship(RawOrigin::Signed(caller.clone()).into(), 2)?;
+		<Pallet<T>>::set_collection_sponsor(RawOrigin::Signed(caller.clone()).into(), collection, caller.clone())?;
+		<Pallet<T>>::confirm_sponsorship(RawOrigin::Signed(caller.clone()).into(), collection)?;
 	}: _(RawOrigin::Signed(caller.clone()), collection)
-
-	// nft item
-	create_item_nft {
-		let b in 0..(CUSTOM_DATA_LIMIT * 2);
-
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let data = CreateItemData::NFT(CreateNftData {
-			const_data: create_data(b.min(CUSTOM_DATA_LIMIT) as usize).try_into().unwrap(),
-			variable_data: create_data(b.saturating_sub(CUSTOM_DATA_LIMIT) as usize).try_into().unwrap(),
-		});
-	}: create_item(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
-
-	create_multiple_items_nft {
-		// TODO: Take item data size into account. As create_item_nft bench shows, this parameter has no effect on execution time,
-		// but it may if we increase CUSTOM_DATA_LIMIT
-		let b in 1..1000;
-
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let data = (0..b).map(|_| default_nft_data()).collect();
-	}: create_multiple_items(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
 
-	// fungible item
-	create_item_fungible {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_fungible_collection::<T>(caller.clone())?;
-		let data = CreateItemData::Fungible(CreateFungibleData {
-			value: 1000,
-		});
-	}: create_item(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
-
-	create_multiple_items_fungible {
-		let b in 1..1000;
-
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_fungible_collection::<T>(caller.clone())?;
-		let data = (0..b).map(|_| default_fungible_data()).collect();
-	}: create_multiple_items(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
-
-	// refungible item
-	create_item_refungible {
-		let b in 0..(CUSTOM_DATA_LIMIT * 2);
-
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_refungible_collection::<T>(caller.clone())?;
-		let data = CreateItemData::ReFungible(CreateReFungibleData {
-			const_data: create_data(b.min(CUSTOM_DATA_LIMIT) as usize).try_into().unwrap(),
-			variable_data: create_data(b.saturating_sub(CUSTOM_DATA_LIMIT) as usize).try_into().unwrap(),
-			pieces: 1000,
-		});
-	}: create_item(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
-
-	create_multiple_items_refungible {
-		// TODO: Take item data size into account. As create_item_nft bench shows, this parameter has no effect on execution time,
-		// but it may if we increase CUSTOM_DATA_LIMIT
-		let b in 1..1000;
-
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_refungible_collection::<T>(caller.clone())?;
-		let data = (0..b).map(|_| default_re_fungible_data()).collect();
-	}: create_multiple_items(RawOrigin::Signed(caller.clone()), collection, T::CrossAccountId::from_sub(caller.clone()), data)
-
-	burn_item_nft {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let data = default_nft_data();
-		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(caller.clone()), data)?;
-	}: burn_item(RawOrigin::Signed(caller.clone()), collection, 1, 1)
-
-	transfer_nft {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let recipient: T::AccountId = account("recipient", 0, SEED);
-		let data = default_nft_data();
-		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(caller.clone()), data)?;
-	}: transfer(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), collection, 1, 1)
-
-	transfer_fungible {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_fungible_collection::<T>(caller.clone())?;
-		let recipient: T::AccountId = account("recipient", 0, SEED);
-		let data = default_fungible_data();
-		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(caller.clone()), data)?;
-	}: transfer(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), collection, 1, 1)
-
-	transfer_refungible {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_refungible_collection::<T>(caller.clone())?;
-		let recipient: T::AccountId = account("recipient", 0, SEED);
-		let data = default_re_fungible_data();
-		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), collection, T::CrossAccountId::from_sub(caller.clone()), data)?;
-	}: transfer(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), collection, 1, 1)
-
 	set_transfers_enabled_flag {
 		let caller: T::AccountId = account("caller", 0, SEED);
 		let collection = create_nft_collection::<T>(caller.clone())?;
 	}: _(RawOrigin::Signed(caller.clone()), collection, false)
-
-	approve_nft {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let recipient: T::AccountId = account("recipient", 0, SEED);
-		let data = default_nft_data();
-		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(caller.clone()), data)?;
-	}: approve(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), collection, 1, 1)
 
-	// Nft
-	transfer_from_nft {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let recipient: T::AccountId = account("recipient", 0, SEED);
-		let data = default_nft_data();
-		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(caller.clone()), data)?;
-		<Pallet<T>>::approve(RawOrigin::Signed(caller.clone()).into(), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)?;
-	}: transfer_from(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)
-
-	// Fungible
-	transfer_from_fungible {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_fungible_collection::<T>(caller.clone())?;
-		let recipient: T::AccountId = account("recipient", 0, SEED);
-		let data = default_fungible_data();
-		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(caller.clone()), data)?;
-		<Pallet<T>>::approve(RawOrigin::Signed(caller.clone()).into(), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)?;
-	}: transfer_from(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)
-
-	// ReFungible
-	transfer_from_refungible {
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_refungible_collection::<T>(caller.clone())?;
-		let recipient: T::AccountId = account("recipient", 0, SEED);
-		let data = default_re_fungible_data();
-		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(caller.clone()), data)?;
-		<Pallet<T>>::approve(RawOrigin::Signed(caller.clone()).into(), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)?;
-	}: transfer_from(RawOrigin::Signed(caller.clone()), T::CrossAccountId::from_sub(caller.clone()), T::CrossAccountId::from_sub(recipient.clone()), 2, 1, 1)
-
 	set_offchain_schema {
 		let b in 0..OFFCHAIN_SCHEMA_LIMIT;
 
@@ -308,29 +142,19 @@
 		let caller: T::AccountId = account("caller", 0, SEED);
 		let collection = create_nft_collection::<T>(caller.clone())?;
 		let data = create_data(b as usize);
-	}: set_variable_on_chain_schema(RawOrigin::Signed(caller.clone()), 2, data)
-
-	set_variable_meta_data_nft {
-		let b in 0..CUSTOM_DATA_LIMIT;
-
-		let caller: T::AccountId = account("caller", 0, SEED);
-		let collection = create_nft_collection::<T>(caller.clone())?;
-		let data = default_nft_data();
-		<Pallet<T>>::create_item(RawOrigin::Signed(caller.clone()).into(), 2, T::CrossAccountId::from_sub(caller.clone()), data)?;
-		let data = create_data(b as usize);
-	}: set_variable_meta_data(RawOrigin::Signed(caller.clone()), collection, 1, data)
+	}: set_variable_on_chain_schema(RawOrigin::Signed(caller.clone()), collection, data)
 
 	set_schema_version {
 		let caller: T::AccountId = account("caller", 0, SEED);
 		let collection = create_nft_collection::<T>(caller.clone())?;
-	}: set_schema_version(RawOrigin::Signed(caller.clone()), 2, SchemaVersion::Unique)
+	}: set_schema_version(RawOrigin::Signed(caller.clone()), collection, SchemaVersion::Unique)
 
 	set_collection_limits{
 		let caller: T::AccountId = account("caller", 0, SEED);
 		let collection = create_nft_collection::<T>(caller.clone())?;
 
 		let cl = CollectionLimits {
-			account_token_ownership_limit: 0,
+			account_token_ownership_limit: Some(0),
 			sponsored_data_size: 0,
 			token_limit: 1,
 			sponsor_transfer_timeout: 0,
@@ -338,5 +162,10 @@
 			owner_can_transfer: true,
 			sponsored_data_rate_limit: None,
 		};
-	}: set_collection_limits(RawOrigin::Signed(caller.clone()), 2, cl)
+	}: set_collection_limits(RawOrigin::Signed(caller.clone()), collection, cl)
+
+	set_meta_update_permission_flag {
+		let caller: T::AccountId = account("caller", 0, SEED);
+		let collection = create_nft_collection::<T>(caller.clone())?;
+	}: _(RawOrigin::Signed(caller.clone()), collection, MetaUpdatePermission::Admin)
 }
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
before · pallets/nft/src/lib.rs
1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56#![recursion_limit = "1024"]7#![cfg_attr(not(feature = "std"), no_std)]8#![allow(9	clippy::too_many_arguments,10	clippy::unnecessary_mut_passed,11	clippy::unused_unit12)]1314extern crate alloc;1516pub use serde::{Serialize, Deserialize};1718pub use frame_support::{19	construct_runtime, decl_module, decl_storage, decl_error,20	dispatch::DispatchResult,21	ensure, fail, parameter_types,22	traits::{23		ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness,24		IsSubType, WithdrawReasons,25	},26	weights::{27		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},28		DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,29		WeightToFeePolynomial, DispatchClass,30	},31	StorageValue, transactional,32	pallet_prelude::DispatchResultWithPostInfo,33};34use frame_system::{self as system, ensure_signed};35use sp_runtime::{sp_std::prelude::Vec};36use nft_data_structs::{37	MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, CUSTOM_DATA_LIMIT,38	VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, COLLECTION_ADMINS_LIMIT,39	OFFCHAIN_SCHEMA_LIMIT, AccessMode, Collection, CreateItemData, CollectionLimits, CollectionId,40	CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,41};42use pallet_common::{43	account::CrossAccountId, CollectionHandle, IsAdmin, Pallet as PalletCommon,44	Error as CommonError, CommonWeightInfo, Allowlist,45};46use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle};47use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};48use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};4950#[cfg(test)]51mod mock;5253#[cfg(test)]54mod tests;5556mod eth;57mod sponsorship;58pub use sponsorship::NftSponsorshipHandler;59pub use eth::sponsoring::NftEthSponsorshipHandler;6061pub use eth::NftErcSupport;6263pub mod common;64use common::CommonWeights;65pub mod dispatch;66use dispatch::dispatch_call;6768#[cfg(feature = "runtime-benchmarks")]69mod benchmarking;70pub mod weights;71use weights::WeightInfo;7273decl_error! {74	/// Error for non-fungible-token module.75	pub enum Error for Module<T: Config> {76		/// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.77		CollectionDecimalPointLimitExceeded,78		/// This address is not set as sponsor, use setCollectionSponsor first.79		ConfirmUnsetSponsorFail,80		/// Length of items properties must be greater than 0.81		EmptyArgument,82		/// Collection limit bounds per collection exceeded83		CollectionLimitBoundsExceeded,84		/// Tried to enable permissions which are only permitted to be disabled85		OwnerPermissionsCantBeReverted,86	}87}88pub trait Config:89	system::Config90	+ pallet_evm_coder_substrate::Config91	+ pallet_common::Config92	+ pallet_nonfungible::Config93	+ pallet_refungible::Config94	+ pallet_fungible::Config95	+ Sized96{97	/// Weight information for extrinsics in this pallet.98	type WeightInfo: WeightInfo;99}100101type SelfWeightOf<T> = <T as Config>::WeightInfo;102103trait WeightInfoHelpers: WeightInfo {104	fn transfer() -> Weight {105		Self::transfer_nft()106			.max(Self::transfer_fungible())107			.max(Self::transfer_refungible())108	}109	fn transfer_from() -> Weight {110		Self::transfer_from_nft()111			.max(Self::transfer_from_fungible())112			.max(Self::transfer_from_refungible())113	}114	fn approve() -> Weight {115		// TODO: refungible, fungible116		Self::approve_nft()117	}118	fn set_variable_meta_data(data: u32) -> Weight {119		// TODO: refungible120		Self::set_variable_meta_data_nft(data)121	}122	fn create_item(data: u32) -> Weight {123		Self::create_item_nft(data)124			.max(Self::create_item_fungible())125			.max(Self::create_item_refungible(data))126	}127	fn create_multiple_items(amount: u32) -> Weight {128		Self::create_multiple_items_nft(amount)129			.max(Self::create_multiple_items_fungible(amount))130			.max(Self::create_multiple_items_refungible(amount))131	}132}133impl<T: WeightInfo> WeightInfoHelpers for T {}134135// # Used definitions136//137// ## User control levels138//139// chain-controlled - key is uncontrolled by user140//                    i.e autoincrementing index141//                    can use non-cryptographic hash142// real - key is controlled by user143//        but it is hard to generate enough colliding values, i.e owner of signed txs144//        can use non-cryptographic hash145// controlled - key is completly controlled by users146//              i.e maps with mutable keys147//              should use cryptographic hash148//149// ## User control level downgrade reasons150//151// ?1 - chain-controlled -> controlled152//      collections/tokens can be destroyed, resulting in massive holes153// ?2 - chain-controlled -> controlled154//      same as ?1, but can be only added, resulting in easier exploitation155// ?3 - real -> controlled156//      no confirmation required, so addresses can be easily generated157decl_storage! {158	trait Store for Module<T: Config> as Nft {159160		//#region Private members161		/// Used for migrations162		ChainVersion: u64;163		//#endregion164165		//#region Tokens transfer rate limit baskets166		/// (Collection id (controlled?2), who created (real))167		/// TODO: Off chain worker should remove from this map when collection gets removed168		pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => T::BlockNumber;169		/// Collection id (controlled?2), token id (controlled?2)170		pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => T::BlockNumber;171		/// Collection id (controlled?2), owning user (real)172		pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => T::BlockNumber;173		/// Collection id (controlled?2), token id (controlled?2)174		pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => T::BlockNumber;175		//#endregion176177		/// Variable metadata sponsoring178		/// Collection id (controlled?2), token id (controlled?2)179		pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber> = None;180	}181}182183decl_module! {184	pub struct Module<T: Config> for enum Call185	where186		origin: T::Origin187	{188		const CollectionAdminsLimit: u64 = COLLECTION_ADMINS_LIMIT;189		type Error = Error<T>;190191		fn on_initialize(_now: T::BlockNumber) -> Weight {192			0193		}194195		/// This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner and admin of the collection are set to the address that signed the transaction. Both addresses can be changed later.196		///197		/// # Permissions198		///199		/// * Anyone.200		///201		/// # Arguments202		///203		/// * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.204		///205		/// * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.206		///207		/// * token_prefix: UTF-8 string with token prefix.208		///209		/// * mode: [CollectionMode] collection type and type dependent data.210		// returns collection ID211		#[weight = <SelfWeightOf<T>>::create_collection()]212		#[transactional]213		pub fn create_collection(origin,214								 collection_name: Vec<u16>,215								 collection_description: Vec<u16>,216								 token_prefix: Vec<u8>,217								 mode: CollectionMode) -> DispatchResult {218219			// Anyone can create a collection220			let who = ensure_signed(origin)?;221222			let limits = CollectionLimits::<T::BlockNumber> {223				sponsored_data_size: CUSTOM_DATA_LIMIT,224				..Default::default()225			};226227			// Create new collection228			let new_collection = Collection::<T> {229				owner: who.clone(),230				name: collection_name,231				mode: mode.clone(),232				mint_mode: false,233				access: AccessMode::Normal,234				description: collection_description,235				token_prefix,236				offchain_schema: Vec::new(),237				schema_version: SchemaVersion::ImageURL,238				sponsorship: SponsorshipState::Disabled,239				variable_on_chain_schema: Vec::new(),240				const_on_chain_schema: Vec::new(),241				limits,242				transfers_enabled: true,243				meta_update_permission: Default::default(),244			};245246			let _id = match mode {247				CollectionMode::NFT => {PalletNonfungible::init_collection(new_collection)?},248				CollectionMode::Fungible(decimal_points) => {249					// check params250					ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);251					PalletFungible::init_collection(new_collection)?252				}253				CollectionMode::ReFungible => {254					PalletRefungible::init_collection(new_collection)?255				}256			};257258			Ok(())259		}260261		/// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.262		///263		/// # Permissions264		///265		/// * Collection Owner.266		///267		/// # Arguments268		///269		/// * collection_id: collection to destroy.270		#[weight = <SelfWeightOf<T>>::destroy_collection()]271		#[transactional]272		pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {273			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);274275			let collection = <CollectionHandle<T>>::try_get(collection_id)?;276			collection.check_is_owner(&sender)?;277278			// =========279280			match collection.mode {281				CollectionMode::ReFungible => PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?,282				CollectionMode::Fungible(_) => PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?,283				CollectionMode::NFT => PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?,284			}285286			<NftTransferBasket<T>>::remove_prefix(collection_id, None);287			<FungibleTransferBasket<T>>::remove_prefix(collection_id, None);288			<ReFungibleTransferBasket<T>>::remove_prefix(collection_id, None);289290			<VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);291292			Ok(())293		}294295		/// Add an address to white list.296		///297		/// # Permissions298		///299		/// * Collection Owner300		/// * Collection Admin301		///302		/// # Arguments303		///304		/// * collection_id.305		///306		/// * address.307		#[weight = <SelfWeightOf<T>>::add_to_white_list()]308		#[transactional]309		pub fn add_to_white_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{310311			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);312			let collection = <CollectionHandle<T>>::try_get(collection_id)?;313314			<PalletCommon<T>>::toggle_allowlist(315				&collection,316				&sender,317				&address,318				true,319			)?;320321			Ok(())322		}323324		/// Remove an address from white list.325		///326		/// # Permissions327		///328		/// * Collection Owner329		/// * Collection Admin330		///331		/// # Arguments332		///333		/// * collection_id.334		///335		/// * address.336		#[weight = <SelfWeightOf<T>>::remove_from_white_list()]337		#[transactional]338		pub fn remove_from_white_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{339340			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);341			let collection = <CollectionHandle<T>>::try_get(collection_id)?;342343			<PalletCommon<T>>::toggle_allowlist(344				&collection,345				&sender,346				&address,347				false,348			)?;349350			Ok(())351		}352353		/// Toggle between normal and white list access for the methods with access for `Anyone`.354		///355		/// # Permissions356		///357		/// * Collection Owner.358		///359		/// # Arguments360		///361		/// * collection_id.362		///363		/// * mode: [AccessMode]364		#[weight = <SelfWeightOf<T>>::set_public_access_mode()]365		#[transactional]366		pub fn set_public_access_mode(origin, collection_id: CollectionId, mode: AccessMode) -> DispatchResult367		{368			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);369370			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;371			target_collection.check_is_owner(&sender)?;372373			target_collection.access = mode;374			target_collection.save()375		}376377		/// Allows Anyone to create tokens if:378		/// * White List is enabled, and379		/// * Address is added to white list, and380		/// * This method was called with True parameter381		///382		/// # Permissions383		/// * Collection Owner384		///385		/// # Arguments386		///387		/// * collection_id.388		///389		/// * mint_permission: Boolean parameter. If True, allows minting to Anyone with conditions above.390		#[weight = <SelfWeightOf<T>>::set_mint_permission()]391		#[transactional]392		pub fn set_mint_permission(origin, collection_id: CollectionId, mint_permission: bool) -> DispatchResult393		{394			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);395396			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;397			target_collection.check_is_owner(&sender)?;398399			target_collection.mint_mode = mint_permission;400			target_collection.save()401		}402403		/// Change the owner of the collection.404		///405		/// # Permissions406		///407		/// * Collection Owner.408		///409		/// # Arguments410		///411		/// * collection_id.412		///413		/// * new_owner.414		#[weight = <SelfWeightOf<T>>::change_collection_owner()]415		#[transactional]416		pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {417418			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);419420			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;421			target_collection.check_is_owner(&sender)?;422423			target_collection.owner = new_owner;424			target_collection.save()425		}426427		/// Adds an admin of the Collection.428		/// NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.429		///430		/// # Permissions431		///432		/// * Collection Owner.433		/// * Collection Admin.434		///435		/// # Arguments436		///437		/// * collection_id: ID of the Collection to add admin for.438		///439		/// * new_admin_id: Address of new admin to add.440		#[weight = <SelfWeightOf<T>>::add_collection_admin()]441		#[transactional]442		pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {443			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);444445			let collection = <CollectionHandle<T>>::try_get(collection_id)?;446			collection.check_is_owner_or_admin(&sender)?;447448			<IsAdmin<T>>::insert((collection_id, new_admin_id.as_sub()), true);449			Ok(())450		}451452		/// Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.453		///454		/// # Permissions455		///456		/// * Collection Owner.457		/// * Collection Admin.458		///459		/// # Arguments460		///461		/// * collection_id: ID of the Collection to remove admin for.462		///463		/// * account_id: Address of admin to remove.464		#[weight = <SelfWeightOf<T>>::remove_collection_admin()]465		#[transactional]466		pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {467			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);468469			let collection = <CollectionHandle<T>>::try_get(collection_id)?;470			collection.check_is_owner_or_admin(&sender)?;471472			<IsAdmin<T>>::remove((collection_id, account_id.as_sub()));473			Ok(())474		}475476		/// # Permissions477		///478		/// * Collection Owner479		///480		/// # Arguments481		///482		/// * collection_id.483		///484		/// * new_sponsor.485		#[weight = <SelfWeightOf<T>>::set_collection_sponsor()]486		#[transactional]487		pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {488			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);489490			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;491			target_collection.check_is_owner_or_admin(&sender)?;492493			target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor);494			target_collection.save()495		}496497		/// # Permissions498		///499		/// * Sponsor.500		///501		/// # Arguments502		///503		/// * collection_id.504		#[weight = <SelfWeightOf<T>>::confirm_sponsorship()]505		#[transactional]506		pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {507			let sender = ensure_signed(origin)?;508509			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;510			ensure!(511				target_collection.sponsorship.pending_sponsor() == Some(&sender),512				Error::<T>::ConfirmUnsetSponsorFail513			);514515			target_collection.sponsorship = SponsorshipState::Confirmed(sender);516			target_collection.save()517		}518519		/// Switch back to pay-per-own-transaction model.520		///521		/// # Permissions522		///523		/// * Collection owner.524		///525		/// # Arguments526		///527		/// * collection_id.528		#[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]529		#[transactional]530		pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {531			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);532533			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;534			target_collection.check_is_owner(&sender)?;535536			target_collection.sponsorship = SponsorshipState::Disabled;537			target_collection.save()538		}539540		/// This method creates a concrete instance of NFT Collection created with CreateCollection method.541		///542		/// # Permissions543		///544		/// * Collection Owner.545		/// * Collection Admin.546		/// * Anyone if547		///     * White List is enabled, and548		///     * Address is added to white list, and549		///     * MintPermission is enabled (see SetMintPermission method)550		///551		/// # Arguments552		///553		/// * collection_id: ID of the collection.554		///555		/// * owner: Address, initial owner of the NFT.556		///557		/// * data: Token data to store on chain.558		#[weight = <CommonWeights<T>>::create_item()]559		#[transactional]560		pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {561			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);562563			dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data))564		}565566		/// This method creates multiple items in a collection created with CreateCollection method.567		///568		/// # Permissions569		///570		/// * Collection Owner.571		/// * Collection Admin.572		/// * Anyone if573		///     * White List is enabled, and574		///     * Address is added to white list, and575		///     * MintPermission is enabled (see SetMintPermission method)576		///577		/// # Arguments578		///579		/// * collection_id: ID of the collection.580		///581		/// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].582		///583		/// * owner: Address, initial owner of the NFT.584		#[weight = <CommonWeights<T>>::create_multiple_items(items_data.len() as u32)]585		#[transactional]586		pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {587			ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);588			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);589590			dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data))591		}592593		// TODO! transaction weight594595		/// Set transfers_enabled value for particular collection596		///597		/// # Permissions598		///599		/// * Collection Owner.600		///601		/// # Arguments602		///603		/// * collection_id: ID of the collection.604		///605		/// * value: New flag value.606		#[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]607		#[transactional]608		pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {609			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);610			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;611			target_collection.check_is_owner(&sender)?;612613			// =========614615			target_collection.transfers_enabled = value;616			target_collection.save()617		}618619		/// Destroys a concrete instance of NFT.620		///621		/// # Permissions622		///623		/// * Collection Owner.624		/// * Collection Admin.625		/// * Current NFT Owner.626		///627		/// # Arguments628		///629		/// * collection_id: ID of the collection.630		///631		/// * item_id: ID of NFT to burn.632		#[weight = <CommonWeights<T>>::burn_item()]633		#[transactional]634		pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {635			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);636637			dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))638		}639640		/// Change ownership of the token.641		///642		/// # Permissions643		///644		/// * Collection Owner645		/// * Collection Admin646		/// * Current NFT owner647		///648		/// # Arguments649		///650		/// * recipient: Address of token recipient.651		///652		/// * collection_id.653		///654		/// * item_id: ID of the item655		///     * Non-Fungible Mode: Required.656		///     * Fungible Mode: Ignored.657		///     * Re-Fungible Mode: Required.658		///659		/// * value: Amount to transfer.660		///     * Non-Fungible Mode: Ignored661		///     * Fungible Mode: Must specify transferred amount662		///     * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)663		#[weight = <CommonWeights<T>>::transfer()]664		#[transactional]665		pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {666			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);667668			dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value))669		}670671		/// Set, change, or remove approved address to transfer the ownership of the NFT.672		///673		/// # Permissions674		///675		/// * Collection Owner676		/// * Collection Admin677		/// * Current NFT owner678		///679		/// # Arguments680		///681		/// * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).682		///683		/// * collection_id.684		///685		/// * item_id: ID of the item.686		#[weight = <CommonWeights<T>>::approve()]687		#[transactional]688		pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {689			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);690691			dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))692		}693694		/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.695		///696		/// # Permissions697		/// * Collection Owner698		/// * Collection Admin699		/// * Current NFT owner700		/// * Address approved by current NFT owner701		///702		/// # Arguments703		///704		/// * from: Address that owns token.705		///706		/// * recipient: Address of token recipient.707		///708		/// * collection_id.709		///710		/// * item_id: ID of the item.711		///712		/// * value: Amount to transfer.713		#[weight = <CommonWeights<T>>::transfer_from()]714		#[transactional]715		pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {716			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);717718			dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value))719		}720721		/// Set off-chain data schema.722		///723		/// # Permissions724		///725		/// * Collection Owner726		/// * Collection Admin727		///728		/// # Arguments729		///730		/// * collection_id.731		///732		/// * schema: String representing the offchain data schema.733		#[weight = <CommonWeights<T>>::set_variable_metadata(data.len() as u32)]734		#[transactional]735		pub fn set_variable_meta_data (736			origin,737			collection_id: CollectionId,738			item_id: TokenId,739			data: Vec<u8>740		) -> DispatchResultWithPostInfo {741			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);742743			dispatch_call::<T, _>(collection_id, |d| d.set_variable_metadata(sender, item_id, data))744		}745746		/// Set meta_update_permission value for particular collection747		///748		/// # Permissions749		///750		/// * Collection Owner.751		///752		/// # Arguments753		///754		/// * collection_id: ID of the collection.755		///756		/// * value: New flag value.757		#[weight = <SelfWeightOf<T>>::set_variable_meta_data(0)]758		#[transactional]759		pub fn set_meta_update_permission_flag(origin, collection_id: CollectionId, value: MetaUpdatePermission) -> DispatchResult {760			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);761			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;762763			ensure!(764				target_collection.meta_update_permission != MetaUpdatePermission::None,765				<CommonError<T>>::MetadataFlagFrozen,766			);767			target_collection.check_is_owner(&sender)?;768769			target_collection.meta_update_permission = value;770771			target_collection.save()772		}773774		/// Set schema standard775		/// ImageURL776		/// Unique777		///778		/// # Permissions779		///780		/// * Collection Owner781		/// * Collection Admin782		///783		/// # Arguments784		///785		/// * collection_id.786		///787		/// * schema: SchemaVersion: enum788		#[weight = <SelfWeightOf<T>>::set_schema_version()]789		#[transactional]790		pub fn set_schema_version(791			origin,792			collection_id: CollectionId,793			version: SchemaVersion794		) -> DispatchResult {795			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);796			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;797			target_collection.check_is_owner_or_admin(&sender)?;798			target_collection.schema_version = version;799			target_collection.save()800		}801802		/// Set off-chain data schema.803		///804		/// # Permissions805		///806		/// * Collection Owner807		/// * Collection Admin808		///809		/// # Arguments810		///811		/// * collection_id.812		///813		/// * schema: String representing the offchain data schema.814		#[weight = <SelfWeightOf<T>>::set_offchain_schema(schema.len() as u32)]815		#[transactional]816		pub fn set_offchain_schema(817			origin,818			collection_id: CollectionId,819			schema: Vec<u8>820		) -> DispatchResult {821			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);822			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;823			target_collection.check_is_owner_or_admin(&sender)?;824825			// check schema limit826			ensure!(schema.len() as u32 <= OFFCHAIN_SCHEMA_LIMIT, "");827828			target_collection.offchain_schema = schema;829			target_collection.save()830		}831832		/// Set const on-chain data schema.833		///834		/// # Permissions835		///836		/// * Collection Owner837		/// * Collection Admin838		///839		/// # Arguments840		///841		/// * collection_id.842		///843		/// * schema: String representing the const on-chain data schema.844		#[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]845		#[transactional]846		pub fn set_const_on_chain_schema (847			origin,848			collection_id: CollectionId,849			schema: Vec<u8>850		) -> DispatchResult {851			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);852			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;853			target_collection.check_is_owner_or_admin(&sender)?;854855			// check schema limit856			ensure!(schema.len() as u32 <= CONST_ON_CHAIN_SCHEMA_LIMIT, "");857858			target_collection.const_on_chain_schema = schema;859			target_collection.save()860		}861862		/// Set variable on-chain data schema.863		///864		/// # Permissions865		///866		/// * Collection Owner867		/// * Collection Admin868		///869		/// # Arguments870		///871		/// * collection_id.872		///873		/// * schema: String representing the variable on-chain data schema.874		#[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]875		#[transactional]876		pub fn set_variable_on_chain_schema (877			origin,878			collection_id: CollectionId,879			schema: Vec<u8>880		) -> DispatchResult {881			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);882			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;883			target_collection.check_is_owner_or_admin(&sender)?;884885			// check schema limit886			ensure!(schema.len() as u32 <= VARIABLE_ON_CHAIN_SCHEMA_LIMIT, "");887888			target_collection.variable_on_chain_schema = schema;889			target_collection.save()890		}891892		#[weight = <SelfWeightOf<T>>::set_collection_limits()]893		#[transactional]894		pub fn set_collection_limits(895			origin,896			collection_id: CollectionId,897			new_limits: CollectionLimits<T::BlockNumber>,898		) -> DispatchResult {899			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);900			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;901			target_collection.check_is_owner(&sender)?;902			let old_limits = &target_collection.limits;903904			// collection bounds905			ensure!(new_limits.sponsor_transfer_timeout <= MAX_SPONSOR_TIMEOUT &&906				new_limits.account_token_ownership_limit.unwrap_or(0) <= MAX_TOKEN_OWNERSHIP &&907				new_limits.sponsored_data_size <= CUSTOM_DATA_LIMIT,908				Error::<T>::CollectionLimitBoundsExceeded);909910			// token_limit   check  prev911			ensure!(old_limits.token_limit >= new_limits.token_limit, <CommonError<T>>::CollectionTokenLimitExceeded);912			ensure!(new_limits.token_limit > 0, <CommonError<T>>::CollectionTokenLimitExceeded);913914			ensure!(915				(old_limits.owner_can_transfer || !new_limits.owner_can_transfer) &&916				(old_limits.owner_can_destroy || !new_limits.owner_can_destroy),917				Error::<T>::OwnerPermissionsCantBeReverted,918			);919920			target_collection.limits = new_limits;921922			target_collection.save()923		}924	}925}926927// TODO: limit returned entries?928impl<T: Config> Pallet<T> {929	pub fn adminlist(collection: CollectionId) -> Vec<T::AccountId> {930		<IsAdmin<T>>::iter_prefix((collection,))931			.map(|(a, _)| a)932			.collect()933	}934	pub fn allowlist(collection: CollectionId) -> Vec<T::AccountId> {935		<Allowlist<T>>::iter_prefix((collection,))936			.map(|(a, _)| a)937			.collect()938	}939}
after · pallets/nft/src/lib.rs
1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56#![recursion_limit = "1024"]7#![cfg_attr(not(feature = "std"), no_std)]8#![allow(9	clippy::too_many_arguments,10	clippy::unnecessary_mut_passed,11	clippy::unused_unit12)]1314extern crate alloc;1516pub use serde::{Serialize, Deserialize};1718pub use frame_support::{19	construct_runtime, decl_module, decl_storage, decl_error,20	dispatch::DispatchResult,21	ensure, fail, parameter_types,22	traits::{23		ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness,24		IsSubType, WithdrawReasons,25	},26	weights::{27		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},28		DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,29		WeightToFeePolynomial, DispatchClass,30	},31	StorageValue, transactional,32	pallet_prelude::DispatchResultWithPostInfo,33};34use frame_system::{self as system, ensure_signed};35use sp_runtime::{sp_std::prelude::Vec};36use nft_data_structs::{37	MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, CUSTOM_DATA_LIMIT,38	VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, COLLECTION_ADMINS_LIMIT,39	OFFCHAIN_SCHEMA_LIMIT, AccessMode, Collection, CreateItemData, CollectionLimits, CollectionId,40	CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,41};42use pallet_common::{43	account::CrossAccountId, CollectionHandle, IsAdmin, Pallet as PalletCommon,44	Error as CommonError, CommonWeightInfo, Allowlist,45};46use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle};47use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};48use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};4950#[cfg(test)]51mod mock;5253#[cfg(test)]54mod tests;5556mod eth;57mod sponsorship;58pub use sponsorship::NftSponsorshipHandler;59pub use eth::sponsoring::NftEthSponsorshipHandler;6061pub use eth::NftErcSupport;6263pub mod common;64use common::CommonWeights;65pub mod dispatch;66use dispatch::dispatch_call;6768#[cfg(feature = "runtime-benchmarks")]69mod benchmarking;70pub mod weights;71use weights::WeightInfo;7273decl_error! {74	/// Error for non-fungible-token module.75	pub enum Error for Module<T: Config> {76		/// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.77		CollectionDecimalPointLimitExceeded,78		/// This address is not set as sponsor, use setCollectionSponsor first.79		ConfirmUnsetSponsorFail,80		/// Length of items properties must be greater than 0.81		EmptyArgument,82		/// Collection limit bounds per collection exceeded83		CollectionLimitBoundsExceeded,84		/// Tried to enable permissions which are only permitted to be disabled85		OwnerPermissionsCantBeReverted,86	}87}88pub trait Config:89	system::Config90	+ pallet_evm_coder_substrate::Config91	+ pallet_common::Config92	+ pallet_nonfungible::Config93	+ pallet_refungible::Config94	+ pallet_fungible::Config95	+ Sized96{97	/// Weight information for extrinsics in this pallet.98	type WeightInfo: WeightInfo;99}100101type SelfWeightOf<T> = <T as Config>::WeightInfo;102103// # Used definitions104//105// ## User control levels106//107// chain-controlled - key is uncontrolled by user108//                    i.e autoincrementing index109//                    can use non-cryptographic hash110// real - key is controlled by user111//        but it is hard to generate enough colliding values, i.e owner of signed txs112//        can use non-cryptographic hash113// controlled - key is completly controlled by users114//              i.e maps with mutable keys115//              should use cryptographic hash116//117// ## User control level downgrade reasons118//119// ?1 - chain-controlled -> controlled120//      collections/tokens can be destroyed, resulting in massive holes121// ?2 - chain-controlled -> controlled122//      same as ?1, but can be only added, resulting in easier exploitation123// ?3 - real -> controlled124//      no confirmation required, so addresses can be easily generated125decl_storage! {126	trait Store for Module<T: Config> as Nft {127128		//#region Private members129		/// Used for migrations130		ChainVersion: u64;131		//#endregion132133		//#region Tokens transfer rate limit baskets134		/// (Collection id (controlled?2), who created (real))135		/// TODO: Off chain worker should remove from this map when collection gets removed136		pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => T::BlockNumber;137		/// Collection id (controlled?2), token id (controlled?2)138		pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => T::BlockNumber;139		/// Collection id (controlled?2), owning user (real)140		pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => T::BlockNumber;141		/// Collection id (controlled?2), token id (controlled?2)142		pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => T::BlockNumber;143		//#endregion144145		/// Variable metadata sponsoring146		/// Collection id (controlled?2), token id (controlled?2)147		pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber> = None;148	}149}150151decl_module! {152	pub struct Module<T: Config> for enum Call153	where154		origin: T::Origin155	{156		const CollectionAdminsLimit: u64 = COLLECTION_ADMINS_LIMIT;157		type Error = Error<T>;158159		fn on_initialize(_now: T::BlockNumber) -> Weight {160			0161		}162163		/// This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner and admin of the collection are set to the address that signed the transaction. Both addresses can be changed later.164		///165		/// # Permissions166		///167		/// * Anyone.168		///169		/// # Arguments170		///171		/// * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.172		///173		/// * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.174		///175		/// * token_prefix: UTF-8 string with token prefix.176		///177		/// * mode: [CollectionMode] collection type and type dependent data.178		// returns collection ID179		#[weight = <SelfWeightOf<T>>::create_collection()]180		#[transactional]181		pub fn create_collection(origin,182								 collection_name: Vec<u16>,183								 collection_description: Vec<u16>,184								 token_prefix: Vec<u8>,185								 mode: CollectionMode) -> DispatchResult {186187			// Anyone can create a collection188			let who = ensure_signed(origin)?;189190			let limits = CollectionLimits::<T::BlockNumber> {191				sponsored_data_size: CUSTOM_DATA_LIMIT,192				..Default::default()193			};194195			// Create new collection196			let new_collection = Collection::<T> {197				owner: who.clone(),198				name: collection_name,199				mode: mode.clone(),200				mint_mode: false,201				access: AccessMode::Normal,202				description: collection_description,203				token_prefix,204				offchain_schema: Vec::new(),205				schema_version: SchemaVersion::ImageURL,206				sponsorship: SponsorshipState::Disabled,207				variable_on_chain_schema: Vec::new(),208				const_on_chain_schema: Vec::new(),209				limits,210				transfers_enabled: true,211				meta_update_permission: Default::default(),212			};213214			let _id = match mode {215				CollectionMode::NFT => {PalletNonfungible::init_collection(new_collection)?},216				CollectionMode::Fungible(decimal_points) => {217					// check params218					ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);219					PalletFungible::init_collection(new_collection)?220				}221				CollectionMode::ReFungible => {222					PalletRefungible::init_collection(new_collection)?223				}224			};225226			Ok(())227		}228229		/// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.230		///231		/// # Permissions232		///233		/// * Collection Owner.234		///235		/// # Arguments236		///237		/// * collection_id: collection to destroy.238		#[weight = <SelfWeightOf<T>>::destroy_collection()]239		#[transactional]240		pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {241			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);242243			let collection = <CollectionHandle<T>>::try_get(collection_id)?;244			collection.check_is_owner(&sender)?;245246			// =========247248			match collection.mode {249				CollectionMode::ReFungible => PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?,250				CollectionMode::Fungible(_) => PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?,251				CollectionMode::NFT => PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?,252			}253254			<NftTransferBasket<T>>::remove_prefix(collection_id, None);255			<FungibleTransferBasket<T>>::remove_prefix(collection_id, None);256			<ReFungibleTransferBasket<T>>::remove_prefix(collection_id, None);257258			<VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);259260			Ok(())261		}262263		/// Add an address to white list.264		///265		/// # Permissions266		///267		/// * Collection Owner268		/// * Collection Admin269		///270		/// # Arguments271		///272		/// * collection_id.273		///274		/// * address.275		#[weight = <SelfWeightOf<T>>::add_to_white_list()]276		#[transactional]277		pub fn add_to_white_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{278279			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);280			let collection = <CollectionHandle<T>>::try_get(collection_id)?;281282			<PalletCommon<T>>::toggle_allowlist(283				&collection,284				&sender,285				&address,286				true,287			)?;288289			Ok(())290		}291292		/// Remove an address from white list.293		///294		/// # Permissions295		///296		/// * Collection Owner297		/// * Collection Admin298		///299		/// # Arguments300		///301		/// * collection_id.302		///303		/// * address.304		#[weight = <SelfWeightOf<T>>::remove_from_white_list()]305		#[transactional]306		pub fn remove_from_white_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{307308			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);309			let collection = <CollectionHandle<T>>::try_get(collection_id)?;310311			<PalletCommon<T>>::toggle_allowlist(312				&collection,313				&sender,314				&address,315				false,316			)?;317318			Ok(())319		}320321		/// Toggle between normal and white list access for the methods with access for `Anyone`.322		///323		/// # Permissions324		///325		/// * Collection Owner.326		///327		/// # Arguments328		///329		/// * collection_id.330		///331		/// * mode: [AccessMode]332		#[weight = <SelfWeightOf<T>>::set_public_access_mode()]333		#[transactional]334		pub fn set_public_access_mode(origin, collection_id: CollectionId, mode: AccessMode) -> DispatchResult335		{336			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);337338			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;339			target_collection.check_is_owner(&sender)?;340341			target_collection.access = mode;342			target_collection.save()343		}344345		/// Allows Anyone to create tokens if:346		/// * White List is enabled, and347		/// * Address is added to white list, and348		/// * This method was called with True parameter349		///350		/// # Permissions351		/// * Collection Owner352		///353		/// # Arguments354		///355		/// * collection_id.356		///357		/// * mint_permission: Boolean parameter. If True, allows minting to Anyone with conditions above.358		#[weight = <SelfWeightOf<T>>::set_mint_permission()]359		#[transactional]360		pub fn set_mint_permission(origin, collection_id: CollectionId, mint_permission: bool) -> DispatchResult361		{362			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);363364			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;365			target_collection.check_is_owner(&sender)?;366367			target_collection.mint_mode = mint_permission;368			target_collection.save()369		}370371		/// Change the owner of the collection.372		///373		/// # Permissions374		///375		/// * Collection Owner.376		///377		/// # Arguments378		///379		/// * collection_id.380		///381		/// * new_owner.382		#[weight = <SelfWeightOf<T>>::change_collection_owner()]383		#[transactional]384		pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {385386			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);387388			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;389			target_collection.check_is_owner(&sender)?;390391			target_collection.owner = new_owner;392			target_collection.save()393		}394395		/// Adds an admin of the Collection.396		/// NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.397		///398		/// # Permissions399		///400		/// * Collection Owner.401		/// * Collection Admin.402		///403		/// # Arguments404		///405		/// * collection_id: ID of the Collection to add admin for.406		///407		/// * new_admin_id: Address of new admin to add.408		#[weight = <SelfWeightOf<T>>::add_collection_admin()]409		#[transactional]410		pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {411			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);412413			let collection = <CollectionHandle<T>>::try_get(collection_id)?;414			collection.check_is_owner_or_admin(&sender)?;415416			<IsAdmin<T>>::insert((collection_id, new_admin_id.as_sub()), true);417			Ok(())418		}419420		/// Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.421		///422		/// # Permissions423		///424		/// * Collection Owner.425		/// * Collection Admin.426		///427		/// # Arguments428		///429		/// * collection_id: ID of the Collection to remove admin for.430		///431		/// * account_id: Address of admin to remove.432		#[weight = <SelfWeightOf<T>>::remove_collection_admin()]433		#[transactional]434		pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {435			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);436437			let collection = <CollectionHandle<T>>::try_get(collection_id)?;438			collection.check_is_owner_or_admin(&sender)?;439440			<IsAdmin<T>>::remove((collection_id, account_id.as_sub()));441			Ok(())442		}443444		/// # Permissions445		///446		/// * Collection Owner447		///448		/// # Arguments449		///450		/// * collection_id.451		///452		/// * new_sponsor.453		#[weight = <SelfWeightOf<T>>::set_collection_sponsor()]454		#[transactional]455		pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {456			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);457458			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;459			target_collection.check_is_owner_or_admin(&sender)?;460461			target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor);462			target_collection.save()463		}464465		/// # Permissions466		///467		/// * Sponsor.468		///469		/// # Arguments470		///471		/// * collection_id.472		#[weight = <SelfWeightOf<T>>::confirm_sponsorship()]473		#[transactional]474		pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {475			let sender = ensure_signed(origin)?;476477			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;478			ensure!(479				target_collection.sponsorship.pending_sponsor() == Some(&sender),480				Error::<T>::ConfirmUnsetSponsorFail481			);482483			target_collection.sponsorship = SponsorshipState::Confirmed(sender);484			target_collection.save()485		}486487		/// Switch back to pay-per-own-transaction model.488		///489		/// # Permissions490		///491		/// * Collection owner.492		///493		/// # Arguments494		///495		/// * collection_id.496		#[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]497		#[transactional]498		pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {499			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);500501			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;502			target_collection.check_is_owner(&sender)?;503504			target_collection.sponsorship = SponsorshipState::Disabled;505			target_collection.save()506		}507508		/// This method creates a concrete instance of NFT Collection created with CreateCollection method.509		///510		/// # Permissions511		///512		/// * Collection Owner.513		/// * Collection Admin.514		/// * Anyone if515		///     * White List is enabled, and516		///     * Address is added to white list, and517		///     * MintPermission is enabled (see SetMintPermission method)518		///519		/// # Arguments520		///521		/// * collection_id: ID of the collection.522		///523		/// * owner: Address, initial owner of the NFT.524		///525		/// * data: Token data to store on chain.526		#[weight = <CommonWeights<T>>::create_item()]527		#[transactional]528		pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {529			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);530531			dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data))532		}533534		/// This method creates multiple items in a collection created with CreateCollection method.535		///536		/// # Permissions537		///538		/// * Collection Owner.539		/// * Collection Admin.540		/// * Anyone if541		///     * White List is enabled, and542		///     * Address is added to white list, and543		///     * MintPermission is enabled (see SetMintPermission method)544		///545		/// # Arguments546		///547		/// * collection_id: ID of the collection.548		///549		/// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].550		///551		/// * owner: Address, initial owner of the NFT.552		#[weight = <CommonWeights<T>>::create_multiple_items(items_data.len() as u32)]553		#[transactional]554		pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {555			ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);556			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);557558			dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data))559		}560561		// TODO! transaction weight562563		/// Set transfers_enabled value for particular collection564		///565		/// # Permissions566		///567		/// * Collection Owner.568		///569		/// # Arguments570		///571		/// * collection_id: ID of the collection.572		///573		/// * value: New flag value.574		#[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]575		#[transactional]576		pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {577			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);578			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;579			target_collection.check_is_owner(&sender)?;580581			// =========582583			target_collection.transfers_enabled = value;584			target_collection.save()585		}586587		/// Destroys a concrete instance of NFT.588		///589		/// # Permissions590		///591		/// * Collection Owner.592		/// * Collection Admin.593		/// * Current NFT Owner.594		///595		/// # Arguments596		///597		/// * collection_id: ID of the collection.598		///599		/// * item_id: ID of NFT to burn.600		#[weight = <CommonWeights<T>>::burn_item()]601		#[transactional]602		pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {603			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);604605			dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))606		}607608		/// Change ownership of the token.609		///610		/// # Permissions611		///612		/// * Collection Owner613		/// * Collection Admin614		/// * Current NFT owner615		///616		/// # Arguments617		///618		/// * recipient: Address of token recipient.619		///620		/// * collection_id.621		///622		/// * item_id: ID of the item623		///     * Non-Fungible Mode: Required.624		///     * Fungible Mode: Ignored.625		///     * Re-Fungible Mode: Required.626		///627		/// * value: Amount to transfer.628		///     * Non-Fungible Mode: Ignored629		///     * Fungible Mode: Must specify transferred amount630		///     * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)631		#[weight = <CommonWeights<T>>::transfer()]632		#[transactional]633		pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {634			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);635636			dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value))637		}638639		/// Set, change, or remove approved address to transfer the ownership of the NFT.640		///641		/// # Permissions642		///643		/// * Collection Owner644		/// * Collection Admin645		/// * Current NFT owner646		///647		/// # Arguments648		///649		/// * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).650		///651		/// * collection_id.652		///653		/// * item_id: ID of the item.654		#[weight = <CommonWeights<T>>::approve()]655		#[transactional]656		pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {657			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);658659			dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))660		}661662		/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.663		///664		/// # Permissions665		/// * Collection Owner666		/// * Collection Admin667		/// * Current NFT owner668		/// * Address approved by current NFT owner669		///670		/// # Arguments671		///672		/// * from: Address that owns token.673		///674		/// * recipient: Address of token recipient.675		///676		/// * collection_id.677		///678		/// * item_id: ID of the item.679		///680		/// * value: Amount to transfer.681		#[weight = <CommonWeights<T>>::transfer_from()]682		#[transactional]683		pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {684			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);685686			dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value))687		}688689		/// Set off-chain data schema.690		///691		/// # Permissions692		///693		/// * Collection Owner694		/// * Collection Admin695		///696		/// # Arguments697		///698		/// * collection_id.699		///700		/// * schema: String representing the offchain data schema.701		#[weight = <CommonWeights<T>>::set_variable_metadata(data.len() as u32)]702		#[transactional]703		pub fn set_variable_meta_data (704			origin,705			collection_id: CollectionId,706			item_id: TokenId,707			data: Vec<u8>708		) -> DispatchResultWithPostInfo {709			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);710711			dispatch_call::<T, _>(collection_id, |d| d.set_variable_metadata(sender, item_id, data))712		}713714		/// Set meta_update_permission value for particular collection715		///716		/// # Permissions717		///718		/// * Collection Owner.719		///720		/// # Arguments721		///722		/// * collection_id: ID of the collection.723		///724		/// * value: New flag value.725		#[weight = <SelfWeightOf<T>>::set_meta_update_permission_flag()]726		#[transactional]727		pub fn set_meta_update_permission_flag(origin, collection_id: CollectionId, value: MetaUpdatePermission) -> DispatchResult {728			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);729			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;730731			ensure!(732				target_collection.meta_update_permission != MetaUpdatePermission::None,733				<CommonError<T>>::MetadataFlagFrozen,734			);735			target_collection.check_is_owner(&sender)?;736737			target_collection.meta_update_permission = value;738739			target_collection.save()740		}741742		/// Set schema standard743		/// ImageURL744		/// Unique745		///746		/// # Permissions747		///748		/// * Collection Owner749		/// * Collection Admin750		///751		/// # Arguments752		///753		/// * collection_id.754		///755		/// * schema: SchemaVersion: enum756		#[weight = <SelfWeightOf<T>>::set_schema_version()]757		#[transactional]758		pub fn set_schema_version(759			origin,760			collection_id: CollectionId,761			version: SchemaVersion762		) -> DispatchResult {763			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);764			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;765			target_collection.check_is_owner_or_admin(&sender)?;766			target_collection.schema_version = version;767			target_collection.save()768		}769770		/// Set off-chain data schema.771		///772		/// # Permissions773		///774		/// * Collection Owner775		/// * Collection Admin776		///777		/// # Arguments778		///779		/// * collection_id.780		///781		/// * schema: String representing the offchain data schema.782		#[weight = <SelfWeightOf<T>>::set_offchain_schema(schema.len() as u32)]783		#[transactional]784		pub fn set_offchain_schema(785			origin,786			collection_id: CollectionId,787			schema: Vec<u8>788		) -> DispatchResult {789			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);790			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;791			target_collection.check_is_owner_or_admin(&sender)?;792793			// check schema limit794			ensure!(schema.len() as u32 <= OFFCHAIN_SCHEMA_LIMIT, "");795796			target_collection.offchain_schema = schema;797			target_collection.save()798		}799800		/// Set const on-chain data schema.801		///802		/// # Permissions803		///804		/// * Collection Owner805		/// * Collection Admin806		///807		/// # Arguments808		///809		/// * collection_id.810		///811		/// * schema: String representing the const on-chain data schema.812		#[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]813		#[transactional]814		pub fn set_const_on_chain_schema (815			origin,816			collection_id: CollectionId,817			schema: Vec<u8>818		) -> DispatchResult {819			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);820			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;821			target_collection.check_is_owner_or_admin(&sender)?;822823			// check schema limit824			ensure!(schema.len() as u32 <= CONST_ON_CHAIN_SCHEMA_LIMIT, "");825826			target_collection.const_on_chain_schema = schema;827			target_collection.save()828		}829830		/// Set variable on-chain data schema.831		///832		/// # Permissions833		///834		/// * Collection Owner835		/// * Collection Admin836		///837		/// # Arguments838		///839		/// * collection_id.840		///841		/// * schema: String representing the variable on-chain data schema.842		#[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]843		#[transactional]844		pub fn set_variable_on_chain_schema (845			origin,846			collection_id: CollectionId,847			schema: Vec<u8>848		) -> DispatchResult {849			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);850			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;851			target_collection.check_is_owner_or_admin(&sender)?;852853			// check schema limit854			ensure!(schema.len() as u32 <= VARIABLE_ON_CHAIN_SCHEMA_LIMIT, "");855856			target_collection.variable_on_chain_schema = schema;857			target_collection.save()858		}859860		#[weight = <SelfWeightOf<T>>::set_collection_limits()]861		#[transactional]862		pub fn set_collection_limits(863			origin,864			collection_id: CollectionId,865			new_limits: CollectionLimits<T::BlockNumber>,866		) -> DispatchResult {867			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);868			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;869			target_collection.check_is_owner(&sender)?;870			let old_limits = &target_collection.limits;871872			// collection bounds873			ensure!(new_limits.sponsor_transfer_timeout <= MAX_SPONSOR_TIMEOUT &&874				new_limits.account_token_ownership_limit.unwrap_or(0) <= MAX_TOKEN_OWNERSHIP &&875				new_limits.sponsored_data_size <= CUSTOM_DATA_LIMIT,876				Error::<T>::CollectionLimitBoundsExceeded);877878			// token_limit   check  prev879			ensure!(old_limits.token_limit >= new_limits.token_limit, <CommonError<T>>::CollectionTokenLimitExceeded);880			ensure!(new_limits.token_limit > 0, <CommonError<T>>::CollectionTokenLimitExceeded);881882			ensure!(883				(old_limits.owner_can_transfer || !new_limits.owner_can_transfer) &&884				(old_limits.owner_can_destroy || !new_limits.owner_can_destroy),885				Error::<T>::OwnerPermissionsCantBeReverted,886			);887888			target_collection.limits = new_limits;889890			target_collection.save()891		}892	}893}894895// TODO: limit returned entries?896impl<T: Config> Pallet<T> {897	pub fn adminlist(collection: CollectionId) -> Vec<T::AccountId> {898		<IsAdmin<T>>::iter_prefix((collection,))899			.map(|(a, _)| a)900			.collect()901	}902	pub fn allowlist(collection: CollectionId) -> Vec<T::AccountId> {903		<Allowlist<T>>::iter_prefix((collection,))904			.map(|(a, _)| a)905			.collect()906	}907}
modifiedpallets/nft/src/weights.rsdiffbeforeafterboth
--- a/pallets/nft/src/weights.rs
+++ b/pallets/nft/src/weights.rs
@@ -2,8 +2,8 @@
 
 //! Autogenerated weights for pallet_nft
 //!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
-//! DATE: 2021-08-31, STEPS: `[50, ]`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2021-10-21, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
 //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128
 
 // Executed Command:
@@ -43,202 +43,141 @@
 	fn set_collection_sponsor() -> Weight;
 	fn confirm_sponsorship() -> Weight;
 	fn remove_collection_sponsor() -> Weight;
-	fn create_item_nft(b: u32, ) -> Weight;
-	fn create_multiple_items_nft(b: u32, ) -> Weight;
-	fn create_item_fungible() -> Weight;
-	fn create_multiple_items_fungible(b: u32, ) -> Weight;
-	fn create_item_refungible(b: u32, ) -> Weight;
-	fn create_multiple_items_refungible(b: u32, ) -> Weight;
-	fn burn_item_nft() -> Weight;
-	fn transfer_nft() -> Weight;
-	fn transfer_fungible() -> Weight;
-	fn transfer_refungible() -> Weight;
 	fn set_transfers_enabled_flag() -> Weight;
-	fn approve_nft() -> Weight;
-	fn transfer_from_nft() -> Weight;
-	fn transfer_from_fungible() -> Weight;
-	fn transfer_from_refungible() -> Weight;
 	fn set_offchain_schema(b: u32, ) -> Weight;
 	fn set_const_on_chain_schema(b: u32, ) -> Weight;
 	fn set_variable_on_chain_schema(b: u32, ) -> Weight;
-	fn set_variable_meta_data_nft(b: u32, ) -> Weight;
 	fn set_schema_version() -> Weight;
 	fn set_collection_limits() -> Weight;
+	fn set_meta_update_permission_flag() -> Weight;
 }
 
 /// Weights for pallet_nft using the Substrate node and recommended hardware.
 pub struct SubstrateWeight<T>(PhantomData<T>);
 impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+	// Storage: Common CreatedCollectionCount (r:1 w:1)
+	// Storage: Common DestroyedCollectionCount (r:1 w:0)
+	// Storage: System Account (r:2 w:2)
+	// Storage: Common CollectionById (r:0 w:1)
 	fn create_collection() -> Weight {
-		(25_851_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(8 as Weight))
-			.saturating_add(T::DbWeight::get().writes(6 as Weight))
+		(23_803_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(4 as Weight))
+			.saturating_add(T::DbWeight::get().writes(4 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
+	// Storage: Common DestroyedCollectionCount (r:1 w:1)
+	// Storage: Nonfungible TokensMinted (r:0 w:1)
+	// Storage: Nonfungible TokensBurnt (r:0 w:1)
 	fn destroy_collection() -> Weight {
-		(28_737_000 as Weight)
+		(27_831_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(2 as Weight))
 			.saturating_add(T::DbWeight::get().writes(4 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common Allowlist (r:0 w:1)
 	fn add_to_white_list() -> Weight {
-		(6_237_000 as Weight)
+		(6_629_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common Allowlist (r:0 w:1)
 	fn remove_from_white_list() -> Weight {
-		(6_252_000 as Weight)
+		(6_596_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_public_access_mode() -> Weight {
-		(6_691_000 as Weight)
+		(6_338_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_mint_permission() -> Weight {
-		(6_630_000 as Weight)
+		(6_383_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn change_collection_owner() -> Weight {
-		(6_521_000 as Weight)
+		(6_493_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common IsAdmin (r:0 w:1)
 	fn add_collection_admin() -> Weight {
-		(8_057_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+		(6_850_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common IsAdmin (r:0 w:1)
 	fn remove_collection_admin() -> Weight {
-		(8_307_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+		(6_615_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_collection_sponsor() -> Weight {
-		(6_484_000 as Weight)
+		(6_430_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn confirm_sponsorship() -> Weight {
-		(6_530_000 as Weight)
+		(6_125_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn remove_collection_sponsor() -> Weight {
-		(6_733_000 as Weight)
+		(6_236_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
-	fn create_item_nft(_b: u32, ) -> Weight {
-		(167_909_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(11 as Weight))
-			.saturating_add(T::DbWeight::get().writes(8 as Weight))
-	}
-	fn create_multiple_items_nft(b: u32, ) -> Weight {
-		(336_830_000 as Weight)
-			// Standard Error: 42_000
-			.saturating_add((11_627_000 as Weight).saturating_mul(b as Weight))
-			.saturating_add(T::DbWeight::get().reads(11 as Weight))
-			.saturating_add(T::DbWeight::get().writes(7 as Weight))
-			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
-	}
-	fn create_item_fungible() -> Weight {
-		(24_123_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(9 as Weight))
-			.saturating_add(T::DbWeight::get().writes(4 as Weight))
-	}
-	fn create_multiple_items_fungible(b: u32, ) -> Weight {
-		(48_227_000 as Weight)
-			// Standard Error: 13_000
-			.saturating_add((2_918_000 as Weight).saturating_mul(b as Weight))
-			.saturating_add(T::DbWeight::get().reads(9 as Weight))
-			.saturating_add(T::DbWeight::get().writes(4 as Weight))
-	}
-	fn create_item_refungible(_b: u32, ) -> Weight {
-		(26_293_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(9 as Weight))
-			.saturating_add(T::DbWeight::get().writes(7 as Weight))
-	}
-	fn create_multiple_items_refungible(b: u32, ) -> Weight {
-		(0 as Weight)
-			// Standard Error: 16_000
-			.saturating_add((8_374_000 as Weight).saturating_mul(b as Weight))
-			.saturating_add(T::DbWeight::get().reads(9 as Weight))
-			.saturating_add(T::DbWeight::get().writes(6 as Weight))
-			.saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
-	}
-	fn burn_item_nft() -> Weight {
-		(32_237_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(9 as Weight))
-			.saturating_add(T::DbWeight::get().writes(7 as Weight))
-	}
-	fn transfer_nft() -> Weight {
-		(192_578_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(14 as Weight))
-			.saturating_add(T::DbWeight::get().writes(10 as Weight))
-	}
-	fn transfer_fungible() -> Weight {
-		(170_749_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(11 as Weight))
-			.saturating_add(T::DbWeight::get().writes(7 as Weight))
-	}
-	fn transfer_refungible() -> Weight {
-		(35_949_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(10 as Weight))
-			.saturating_add(T::DbWeight::get().writes(7 as Weight))
-	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_transfers_enabled_flag() -> Weight {
-		(6_376_000 as Weight)
+		(6_500_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
-	fn approve_nft() -> Weight {
-		(169_825_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(9 as Weight))
-			.saturating_add(T::DbWeight::get().writes(4 as Weight))
-	}
-	fn transfer_from_nft() -> Weight {
-		(197_912_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(15 as Weight))
-			.saturating_add(T::DbWeight::get().writes(11 as Weight))
-	}
-	fn transfer_from_fungible() -> Weight {
-		(183_789_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(12 as Weight))
-			.saturating_add(T::DbWeight::get().writes(8 as Weight))
-	}
-	fn transfer_from_refungible() -> Weight {
-		(37_149_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(11 as Weight))
-			.saturating_add(T::DbWeight::get().writes(8 as Weight))
-	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_offchain_schema(_b: u32, ) -> Weight {
-		(6_435_000 as Weight)
+		(6_538_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_const_on_chain_schema(_b: u32, ) -> Weight {
-		(6_646_000 as Weight)
+		(6_542_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
-	fn set_variable_on_chain_schema(_b: u32, ) -> Weight {
-		(6_542_000 as Weight)
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_variable_on_chain_schema(b: u32, ) -> Weight {
+		(6_092_000 as Weight)
+			// Standard Error: 0
+			.saturating_add((2_000 as Weight).saturating_mul(b as Weight))
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
-	fn set_variable_meta_data_nft(_b: u32, ) -> Weight {
-		(14_697_000 as Weight)
-			.saturating_add(T::DbWeight::get().reads(2 as Weight))
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_schema_version() -> Weight {
+		(6_470_000 as Weight)
+			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
-	fn set_schema_version() -> Weight {
-		(6_566_000 as Weight)
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_collection_limits() -> Weight {
+		(6_841_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
-	fn set_collection_limits() -> Weight {
-		(6_349_000 as Weight)
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_meta_update_permission_flag() -> Weight {
+		(6_278_000 as Weight)
 			.saturating_add(T::DbWeight::get().reads(1 as Weight))
 			.saturating_add(T::DbWeight::get().writes(1 as Weight))
 	}
@@ -246,178 +185,129 @@
 
 // For backwards compatibility and tests
 impl WeightInfo for () {
+	// Storage: Common CreatedCollectionCount (r:1 w:1)
+	// Storage: Common DestroyedCollectionCount (r:1 w:0)
+	// Storage: System Account (r:2 w:2)
+	// Storage: Common CollectionById (r:0 w:1)
 	fn create_collection() -> Weight {
-		(25_851_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(8 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(6 as Weight))
+		(23_803_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(4 as Weight))
+			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
+	// Storage: Common DestroyedCollectionCount (r:1 w:1)
+	// Storage: Nonfungible TokensMinted (r:0 w:1)
+	// Storage: Nonfungible TokensBurnt (r:0 w:1)
 	fn destroy_collection() -> Weight {
-		(28_737_000 as Weight)
+		(27_831_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common Allowlist (r:0 w:1)
 	fn add_to_white_list() -> Weight {
-		(6_237_000 as Weight)
+		(6_629_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common Allowlist (r:0 w:1)
 	fn remove_from_white_list() -> Weight {
-		(6_252_000 as Weight)
+		(6_596_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_public_access_mode() -> Weight {
-		(6_691_000 as Weight)
+		(6_338_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_mint_permission() -> Weight {
-		(6_630_000 as Weight)
+		(6_383_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn change_collection_owner() -> Weight {
-		(6_521_000 as Weight)
+		(6_493_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common IsAdmin (r:0 w:1)
 	fn add_collection_admin() -> Weight {
-		(8_057_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+		(6_850_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:0)
+	// Storage: Common IsAdmin (r:0 w:1)
 	fn remove_collection_admin() -> Weight {
-		(8_307_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+		(6_615_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_collection_sponsor() -> Weight {
-		(6_484_000 as Weight)
+		(6_430_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn confirm_sponsorship() -> Weight {
-		(6_530_000 as Weight)
+		(6_125_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn remove_collection_sponsor() -> Weight {
-		(6_733_000 as Weight)
+		(6_236_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
-	fn create_item_nft(b: u32, ) -> Weight {
-		(167_180_000 as Weight)
-			// Standard Error: 1_000
-			.saturating_add((10_000 as Weight).saturating_mul(b as Weight))
-			.saturating_add(RocksDbWeight::get().reads(11 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(8 as Weight))
-	}
-	fn create_multiple_items_nft(b: u32, ) -> Weight {
-		(336_830_000 as Weight)
-			// Standard Error: 42_000
-			.saturating_add((11_627_000 as Weight).saturating_mul(b as Weight))
-			.saturating_add(RocksDbWeight::get().reads(11 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
-			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
-	}
-	fn create_item_fungible() -> Weight {
-		(24_123_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
-	}
-	fn create_multiple_items_fungible(b: u32, ) -> Weight {
-		(13_217_000 as Weight)
-			// Standard Error: 4_000
-			.saturating_add((2_971_000 as Weight).saturating_mul(b as Weight))
-			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
-	}
-	fn create_item_refungible(_b: u32, ) -> Weight {
-		(26_293_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
-	}
-	fn create_multiple_items_refungible(b: u32, ) -> Weight {
-		(0 as Weight)
-			// Standard Error: 16_000
-			.saturating_add((8_374_000 as Weight).saturating_mul(b as Weight))
-			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(6 as Weight))
-			.saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight)))
-	}
-	fn burn_item_nft() -> Weight {
-		(32_237_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
-	}
-	fn transfer_nft() -> Weight {
-		(192_578_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(14 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(10 as Weight))
-	}
-	fn transfer_fungible() -> Weight {
-		(170_749_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(11 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
-	}
-	fn transfer_refungible() -> Weight {
-		(35_949_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(10 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(7 as Weight))
-	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_transfers_enabled_flag() -> Weight {
-		(6_376_000 as Weight)
+		(6_500_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
-	fn approve_nft() -> Weight {
-		(169_825_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(9 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(4 as Weight))
-	}
-	fn transfer_from_nft() -> Weight {
-		(197_912_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(15 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(11 as Weight))
-	}
-	fn transfer_from_fungible() -> Weight {
-		(183_789_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(12 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(8 as Weight))
-	}
-	fn transfer_from_refungible() -> Weight {
-		(37_149_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(11 as Weight))
-			.saturating_add(RocksDbWeight::get().writes(8 as Weight))
-	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_offchain_schema(_b: u32, ) -> Weight {
-		(6_435_000 as Weight)
+		(6_538_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
+	// Storage: Common CollectionById (r:1 w:1)
 	fn set_const_on_chain_schema(_b: u32, ) -> Weight {
-		(6_646_000 as Weight)
+		(6_542_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
-	fn set_variable_on_chain_schema(_b: u32, ) -> Weight {
-		(6_542_000 as Weight)
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_variable_on_chain_schema(b: u32, ) -> Weight {
+		(6_092_000 as Weight)
+			// Standard Error: 0
+			.saturating_add((2_000 as Weight).saturating_mul(b as Weight))
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
-	fn set_variable_meta_data_nft(_b: u32, ) -> Weight {
-		(14_697_000 as Weight)
-			.saturating_add(RocksDbWeight::get().reads(2 as Weight))
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_schema_version() -> Weight {
+		(6_470_000 as Weight)
+			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
-	fn set_schema_version() -> Weight {
-		(6_566_000 as Weight)
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_collection_limits() -> Weight {
+		(6_841_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}
-	fn set_collection_limits() -> Weight {
-		(6_349_000 as Weight)
+	// Storage: Common CollectionById (r:1 w:1)
+	fn set_meta_update_permission_flag() -> Weight {
+		(6_278_000 as Weight)
 			.saturating_add(RocksDbWeight::get().reads(1 as Weight))
 			.saturating_add(RocksDbWeight::get().writes(1 as Weight))
 	}