git.delta.rocks / unique-network / refs/commits / 8ccb2682a57d

difftreelog

refactor make collection limits fields optional

Yaroslav Bolyukin2021-11-04parent: #579977f.patch.diff
in: master

8 files changed

modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -105,10 +105,10 @@
 		Ok(())
 	}
 	pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> Result<bool, DispatchError> {
-		Ok(self.limits.owner_can_transfer && self.is_owner_or_admin(user)?)
+		Ok(self.limits.owner_can_transfer() && self.is_owner_or_admin(user)?)
 	}
 	pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> Result<bool, DispatchError> {
-		Ok(self.limits.owner_can_transfer && self.is_owner_or_admin(user)?)
+		Ok(self.limits.owner_can_transfer() && self.is_owner_or_admin(user)?)
 	}
 	pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {
 		self.consume_sload()?;
@@ -405,9 +405,10 @@
 		collection: CollectionHandle<T>,
 		sender: &T::CrossAccountId,
 	) -> DispatchResult {
-		if !collection.limits.owner_can_destroy {
-			fail!(Error::<T>::NoPermission);
-		}
+		ensure!(
+			collection.limits.owner_can_destroy(),
+			<Error<T>>::NoPermission,
+		);
 		collection.check_is_owner(&sender)?;
 
 		let destroyed_collections = <DestroyedCollectionCount<T>>::get()
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -157,8 +157,8 @@
 		amount: u128,
 	) -> DispatchResult {
 		ensure!(
-			collection.transfers_enabled,
-			<CommonError<T>>::TransferNotAllowed
+			collection.limits.transfers_enabled(),
+			<CommonError<T>>::TransferNotAllowed,
 		);
 
 		if collection.access == AccessMode::WhiteList {
modifiedpallets/nft/src/eth/sponsoring.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/sponsoring.rs
+++ b/pallets/nft/src/eth/sponsoring.rs
@@ -43,11 +43,8 @@
 					let token_id: u32 = token_id.try_into().map_err(|_| AnyError)?;
 					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
 					let collection_limits = &collection.limits;
-					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
-						collection_limits.sponsor_transfer_timeout
-					} else {
-						NFT_SPONSOR_TRANSFER_TIMEOUT
-					};
+					let limit =
+						collection_limits.sponsor_transfer_timeout(NFT_SPONSOR_TRANSFER_TIMEOUT);
 
 					let mut sponsor = true;
 					if <NftTransferBasket<T>>::contains_key(collection_id, token_id) {
@@ -74,11 +71,8 @@
 				UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
 					let who = T::CrossAccountId::from_eth(*caller);
 					let collection_limits = &collection.limits;
-					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
-						collection_limits.sponsor_transfer_timeout
-					} else {
-						FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
-					};
+					let limit = collection_limits
+						.sponsor_transfer_timeout(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT);
 
 					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
 					let mut sponsored = true;
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -37,8 +37,9 @@
 use nft_data_structs::{
 	MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, CUSTOM_DATA_LIMIT,
 	VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, COLLECTION_ADMINS_LIMIT,
-	OFFCHAIN_SCHEMA_LIMIT, AccessMode, Collection, CreateItemData, CollectionLimits, CollectionId,
-	CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,
+	OFFCHAIN_SCHEMA_LIMIT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+	NFT_SPONSOR_TRANSFER_TIMEOUT, AccessMode, Collection, CreateItemData, CollectionLimits,
+	CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,
 };
 use pallet_common::{
 	account::CrossAccountId, CollectionHandle, IsAdmin, Pallet as PalletCommon,
@@ -188,11 +189,6 @@
 
 			// Anyone can create a collection
 			let who = ensure_signed(origin)?;
-
-			let limits = CollectionLimits::<T::BlockNumber> {
-				sponsored_data_size: CUSTOM_DATA_LIMIT,
-				..Default::default()
-			};
 
 			// Create new collection
 			let new_collection = Collection::<T> {
@@ -208,8 +204,7 @@
 				sponsorship: SponsorshipState::Disabled,
 				variable_on_chain_schema: Vec::new(),
 				const_on_chain_schema: Vec::new(),
-				limits,
-				transfers_enabled: true,
+				limits: Default::default(),
 				meta_update_permission: Default::default(),
 			};
 
@@ -582,7 +577,7 @@
 
 			// =========
 
-			target_collection.transfers_enabled = value;
+			target_collection.limits.transfers_enabled = Some(value);
 			target_collection.save()
 		}
 
@@ -888,30 +883,63 @@
 		pub fn set_collection_limits(
 			origin,
 			collection_id: CollectionId,
-			new_limits: CollectionLimits<T::BlockNumber>,
+			new_limit: CollectionLimits,
 		) -> DispatchResult {
+			let mut new_limit = new_limit;
 			let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
 			let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
 			target_collection.check_is_owner(&sender)?;
-			let old_limits = &target_collection.limits;
+			let old_limit = &target_collection.limits;
 
-			// collection bounds
-			ensure!(new_limits.sponsor_transfer_timeout <= MAX_SPONSOR_TIMEOUT &&
-				new_limits.account_token_ownership_limit.unwrap_or(0) <= MAX_TOKEN_OWNERSHIP &&
-				new_limits.sponsored_data_size <= CUSTOM_DATA_LIMIT,
-				Error::<T>::CollectionLimitBoundsExceeded);
+			macro_rules! limit_default {
+				($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{
+					$(
+						if let Some($new) = $new.$field {
+							let $old = $old.$field($($arg)?);
+							let _ = $new;
+							let _ = $old;
+							$check
+						} else {
+							$new.$field = $old.$field
+						}
+					)*
+				}};
+			}
 
-			// token_limit   check  prev
-			ensure!(old_limits.token_limit >= new_limits.token_limit, <CommonError<T>>::CollectionTokenLimitExceeded);
-			ensure!(new_limits.token_limit > 0, <CommonError<T>>::CollectionTokenLimitExceeded);
-
-			ensure!(
-				(old_limits.owner_can_transfer || !new_limits.owner_can_transfer) &&
-				(old_limits.owner_can_destroy || !new_limits.owner_can_destroy),
-				Error::<T>::OwnerPermissionsCantBeReverted,
+			limit_default!(old_limit, new_limit,
+				account_token_ownership_limit => ensure!(
+					new_limit <= MAX_TOKEN_OWNERSHIP,
+					<Error<T>>::CollectionLimitBoundsExceeded,
+				),
+				sponsor_transfer_timeout(match target_collection.mode {
+					CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
+					CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+					CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+				}) => ensure!(
+					new_limit <= MAX_SPONSOR_TIMEOUT,
+					<Error<T>>::CollectionLimitBoundsExceeded,
+				),
+				sponsored_data_size => ensure!(
+					new_limit <= CUSTOM_DATA_LIMIT,
+					<Error<T>>::CollectionLimitBoundsExceeded,
+				),
+				token_limit => ensure!(
+					old_limit >= new_limit && new_limit > 0,
+					<CommonError<T>>::CollectionTokenLimitExceeded
+				),
+				owner_can_transfer => ensure!(
+					old_limit || !new_limit,
+					<Error<T>>::OwnerPermissionsCantBeReverted,
+				),
+				owner_can_destroy => ensure!(
+					old_limit || !new_limit,
+					<Error<T>>::OwnerPermissionsCantBeReverted,
+				),
+				sponsored_data_rate_limit => {},
+				transfers_enabled => {},
 			);
 
-			target_collection.limits = new_limits;
+			target_collection.limits = new_limit;
 
 			target_collection.save()
 		}
modifiedpallets/nft/src/sponsorship.rsdiffbeforeafterboth
before · pallets/nft/src/sponsorship.rs
1use crate::{2	Config, Call, CreateItemBasket, VariableMetaDataBasket, ReFungibleTransferBasket,3	FungibleTransferBasket, NftTransferBasket, CreateItemData, CollectionMode,4};5use core::marker::PhantomData;6use up_sponsorship::SponsorshipHandler;7use frame_support::{8	traits::{IsSubType},9	storage::{StorageMap, StorageDoubleMap},10};11use nft_data_structs::{12	TokenId, CollectionId, NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,13	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,14};15use pallet_common::{CollectionById};1617pub struct NftSponsorshipHandler<T>(PhantomData<T>);18impl<T: Config> NftSponsorshipHandler<T> {19	pub fn withdraw_create_item(20		who: &T::AccountId,21		collection_id: &CollectionId,22		_properties: &CreateItemData,23	) -> Option<T::AccountId> {24		let collection = CollectionById::<T>::get(collection_id)?;2526		// sponsor timeout27		let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;2829		let limit = collection.limits.sponsor_transfer_timeout;30		if CreateItemBasket::<T>::contains_key((collection_id, &who)) {31			let last_tx_block = CreateItemBasket::<T>::get((collection_id, &who));32			let limit_time = last_tx_block + limit.into();33			if block_number <= limit_time {34				return None;35			}36		}37		CreateItemBasket::<T>::insert((collection_id, who.clone()), block_number);3839		// check free create limit40		if collection.limits.sponsored_data_size >= (_properties.data_size() as u32) {41			collection.sponsorship.sponsor().cloned()42		} else {43			None44		}45	}4647	pub fn withdraw_transfer(48		who: &T::AccountId,49		collection_id: &CollectionId,50		item_id: &TokenId,51	) -> Option<T::AccountId> {52		let collection = CollectionById::<T>::get(collection_id)?;5354		let mut sponsor_transfer = false;55		if collection.sponsorship.confirmed() {56			let collection_limits = collection.limits.clone();57			let collection_mode = collection.mode.clone();5859			// sponsor timeout60			let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;61			sponsor_transfer = match collection_mode {62				CollectionMode::NFT => {63					// get correct limit64					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {65						collection_limits.sponsor_transfer_timeout66					} else {67						NFT_SPONSOR_TRANSFER_TIMEOUT68					};6970					let mut sponsored = true;71					if NftTransferBasket::<T>::contains_key(collection_id, item_id) {72						let last_tx_block = NftTransferBasket::<T>::get(collection_id, item_id);73						let limit_time = last_tx_block + limit.into();74						if block_number <= limit_time {75							sponsored = false;76						}77					}78					if sponsored {79						NftTransferBasket::<T>::insert(collection_id, item_id, block_number);80					}8182					sponsored83				}84				CollectionMode::Fungible(_) => {85					// get correct limit86					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {87						collection_limits.sponsor_transfer_timeout88					} else {89						FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT90					};9192					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;93					let mut sponsored = true;94					if FungibleTransferBasket::<T>::contains_key(collection_id, who) {95						let last_tx_block = FungibleTransferBasket::<T>::get(collection_id, who);96						let limit_time = last_tx_block + limit.into();97						if block_number <= limit_time {98							sponsored = false;99						}100					}101					if sponsored {102						FungibleTransferBasket::<T>::insert(collection_id, who, block_number);103					}104105					sponsored106				}107				CollectionMode::ReFungible => {108					// get correct limit109					let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {110						collection_limits.sponsor_transfer_timeout111					} else {112						REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT113					};114115					let mut sponsored = true;116					if ReFungibleTransferBasket::<T>::contains_key(collection_id, item_id) {117						let last_tx_block =118							ReFungibleTransferBasket::<T>::get(collection_id, item_id);119						let limit_time = last_tx_block + limit.into();120						if block_number <= limit_time {121							sponsored = false;122						}123					}124					if sponsored {125						ReFungibleTransferBasket::<T>::insert(collection_id, item_id, block_number);126					}127128					sponsored129				}130			};131		}132133		if !sponsor_transfer {134			None135		} else {136			collection.sponsorship.sponsor().cloned()137		}138	}139140	pub fn withdraw_set_variable_meta_data(141		collection_id: &CollectionId,142		item_id: &TokenId,143		data: &[u8],144	) -> Option<T::AccountId> {145		let mut sponsor_metadata_changes = false;146147		let collection = CollectionById::<T>::get(collection_id)?;148149		if collection.sponsorship.confirmed() &&150			// Can't sponsor fungible collection, this tx will be rejected151			// as invalid152			!matches!(collection.mode, CollectionMode::Fungible(_)) &&153			data.len() <= collection.limits.sponsored_data_size as usize154		{155			if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit {156				let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;157158				if VariableMetaDataBasket::<T>::get(collection_id, item_id)159					.map(|last_block| block_number - last_block > rate_limit)160					.unwrap_or(true)161				{162					sponsor_metadata_changes = true;163					VariableMetaDataBasket::<T>::insert(collection_id, item_id, block_number);164				}165			}166		}167168		if !sponsor_metadata_changes {169			None170		} else {171			collection.sponsorship.sponsor().cloned()172		}173	}174}175176impl<T, C> SponsorshipHandler<T::AccountId, C> for NftSponsorshipHandler<T>177where178	T: Config,179	C: IsSubType<Call<T>>,180{181	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {182		match IsSubType::<Call<T>>::is_sub_type(call)? {183			Call::create_item {184				collection_id,185				data,186				..187			} => Self::withdraw_create_item(who, collection_id, data),188			Call::transfer {189				collection_id,190				item_id,191				..192			} => Self::withdraw_transfer(who, collection_id, item_id),193			Call::set_variable_meta_data {194				collection_id,195				item_id,196				data,197			} => Self::withdraw_set_variable_meta_data(collection_id, item_id, data),198			_ => None,199		}200	}201}
after · pallets/nft/src/sponsorship.rs
1use crate::{2	Config, Call, CreateItemBasket, VariableMetaDataBasket, ReFungibleTransferBasket,3	FungibleTransferBasket, NftTransferBasket, CreateItemData, CollectionMode,4};5use core::marker::PhantomData;6use up_sponsorship::SponsorshipHandler;7use frame_support::{8	traits::{IsSubType},9	storage::{StorageMap, StorageDoubleMap},10};11use nft_data_structs::{12	TokenId, CollectionId, NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,13	FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,14};15use pallet_common::{CollectionById};1617pub struct NftSponsorshipHandler<T>(PhantomData<T>);18impl<T: Config> NftSponsorshipHandler<T> {19	pub fn withdraw_create_item(20		who: &T::AccountId,21		collection_id: &CollectionId,22		_properties: &CreateItemData,23	) -> Option<T::AccountId> {24		let collection = CollectionById::<T>::get(collection_id)?;2526		// sponsor timeout27		let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;2829		let limit = collection30			.limits31			.sponsor_transfer_timeout(match _properties {32				CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,33				CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,34				CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,35			});36		if CreateItemBasket::<T>::contains_key((collection_id, &who)) {37			let last_tx_block = CreateItemBasket::<T>::get((collection_id, &who));38			let limit_time = last_tx_block + limit.into();39			if block_number <= limit_time {40				return None;41			}42		}43		CreateItemBasket::<T>::insert((collection_id, who.clone()), block_number);4445		// check free create limit46		if collection.limits.sponsored_data_size() >= (_properties.data_size() as u32) {47			collection.sponsorship.sponsor().cloned()48		} else {49			None50		}51	}5253	pub fn withdraw_transfer(54		who: &T::AccountId,55		collection_id: &CollectionId,56		item_id: &TokenId,57	) -> Option<T::AccountId> {58		let collection = CollectionById::<T>::get(collection_id)?;5960		let mut sponsor_transfer = false;61		if collection.sponsorship.confirmed() {62			let collection_limits = collection.limits.clone();63			let collection_mode = collection.mode.clone();6465			// sponsor timeout66			let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;67			sponsor_transfer = match collection_mode {68				CollectionMode::NFT => {69					// get correct limit70					let limit =71						collection_limits.sponsor_transfer_timeout(NFT_SPONSOR_TRANSFER_TIMEOUT);7273					let mut sponsored = true;74					if NftTransferBasket::<T>::contains_key(collection_id, item_id) {75						let last_tx_block = NftTransferBasket::<T>::get(collection_id, item_id);76						let limit_time = last_tx_block + limit.into();77						if block_number <= limit_time {78							sponsored = false;79						}80					}81					if sponsored {82						NftTransferBasket::<T>::insert(collection_id, item_id, block_number);83					}8485					sponsored86				}87				CollectionMode::Fungible(_) => {88					// get correct limit89					let limit = collection_limits90						.sponsor_transfer_timeout(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT);9192					let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;93					let mut sponsored = true;94					if FungibleTransferBasket::<T>::contains_key(collection_id, who) {95						let last_tx_block = FungibleTransferBasket::<T>::get(collection_id, who);96						let limit_time = last_tx_block + limit.into();97						if block_number <= limit_time {98							sponsored = false;99						}100					}101					if sponsored {102						FungibleTransferBasket::<T>::insert(collection_id, who, block_number);103					}104105					sponsored106				}107				CollectionMode::ReFungible => {108					// get correct limit109					let limit = collection_limits110						.sponsor_transfer_timeout(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT);111112					let mut sponsored = true;113					if ReFungibleTransferBasket::<T>::contains_key(collection_id, item_id) {114						let last_tx_block =115							ReFungibleTransferBasket::<T>::get(collection_id, item_id);116						let limit_time = last_tx_block + limit.into();117						if block_number <= limit_time {118							sponsored = false;119						}120					}121					if sponsored {122						ReFungibleTransferBasket::<T>::insert(collection_id, item_id, block_number);123					}124125					sponsored126				}127			};128		}129130		if !sponsor_transfer {131			None132		} else {133			collection.sponsorship.sponsor().cloned()134		}135	}136137	pub fn withdraw_set_variable_meta_data(138		collection_id: &CollectionId,139		item_id: &TokenId,140		data: &[u8],141	) -> Option<T::AccountId> {142		let mut sponsor_metadata_changes = false;143144		let collection = CollectionById::<T>::get(collection_id)?;145146		if collection.sponsorship.confirmed() &&147			// Can't sponsor fungible collection, this tx will be rejected148			// as invalid149			!matches!(collection.mode, CollectionMode::Fungible(_)) &&150			data.len() <= collection.limits.sponsored_data_size() as usize151		{152			if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit() {153				let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;154155				if VariableMetaDataBasket::<T>::get(collection_id, item_id)156					.map(|last_block| block_number - last_block > rate_limit.into())157					.unwrap_or(true)158				{159					sponsor_metadata_changes = true;160					VariableMetaDataBasket::<T>::insert(collection_id, item_id, block_number);161				}162			}163		}164165		if !sponsor_metadata_changes {166			None167		} else {168			collection.sponsorship.sponsor().cloned()169		}170	}171}172173impl<T, C> SponsorshipHandler<T::AccountId, C> for NftSponsorshipHandler<T>174where175	T: Config,176	C: IsSubType<Call<T>>,177{178	fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {179		match IsSubType::<Call<T>>::is_sub_type(call)? {180			Call::create_item {181				collection_id,182				data,183				..184			} => Self::withdraw_create_item(who, collection_id, data),185			Call::transfer {186				collection_id,187				item_id,188				..189			} => Self::withdraw_transfer(who, collection_id, item_id),190			Call::set_variable_meta_data {191				collection_id,192				item_id,193				data,194			} => Self::withdraw_set_variable_meta_data(collection_id, item_id, data),195			_ => None,196		}197	}198}
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -164,7 +164,7 @@
 			.ok_or_else(|| <CommonError<T>>::TokenNotFound)?;
 		ensure!(
 			&token_data.owner == sender
-				|| (collection.limits.owner_can_transfer
+				|| (collection.limits.owner_can_transfer()
 					&& collection.is_owner_or_admin(sender)?),
 			<CommonError<T>>::NoPermission
 		);
@@ -215,7 +215,7 @@
 		token: TokenId,
 	) -> DispatchResult {
 		ensure!(
-			collection.transfers_enabled,
+			collection.limits.transfers_enabled(),
 			<CommonError<T>>::TransferNotAllowed
 		);
 
@@ -223,7 +223,8 @@
 			.ok_or_else(|| <CommonError<T>>::TokenNotFound)?;
 		ensure!(
 			&token_data.owner == from
-				|| (collection.limits.owner_can_transfer && collection.is_owner_or_admin(from)?),
+				|| (collection.limits.owner_can_transfer()
+					&& collection.is_owner_or_admin(from)?),
 			<CommonError<T>>::NoPermission
 		);
 
@@ -327,7 +328,7 @@
 			.checked_add(data.len() as u32)
 			.ok_or(ArithmeticError::Overflow)?;
 		ensure!(
-			tokens_minted < collection.limits.token_limit,
+			tokens_minted < collection.limits.token_limit(),
 			<CommonError<T>>::CollectionTokenLimitExceeded
 		);
 		collection.consume_sstore()?;
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -268,7 +268,7 @@
 		amount: u128,
 	) -> DispatchResult {
 		ensure!(
-			collection.transfers_enabled,
+			collection.limits.transfers_enabled(),
 			<CommonError<T>>::TransferNotAllowed
 		);
 
@@ -404,7 +404,7 @@
 			.checked_add(data.len() as u32)
 			.ok_or(ArithmeticError::Overflow)?;
 		ensure!(
-			tokens_minted < collection.limits.token_limit,
+			tokens_minted < collection.limits.token_limit(),
 			<CommonError<T>>::CollectionTokenLimitExceeded
 		);
 
modifiedprimitives/nft/src/lib.rsdiffbeforeafterboth
--- a/primitives/nft/src/lib.rs
+++ b/primitives/nft/src/lib.rs
@@ -42,6 +42,7 @@
 	10
 };
 pub const COLLECTION_ADMINS_LIMIT: u64 = 5;
+pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;
 pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {
 	1000000
 } else {
@@ -217,11 +218,10 @@
 	pub offchain_schema: Vec<u8>,
 	pub schema_version: SchemaVersion,
 	pub sponsorship: SponsorshipState<T::AccountId>,
-	pub limits: CollectionLimits<T::BlockNumber>, // Collection private restrictions
-	pub variable_on_chain_schema: Vec<u8>,        //
-	pub const_on_chain_schema: Vec<u8>,           //
+	pub limits: CollectionLimits,          // Collection private restrictions
+	pub variable_on_chain_schema: Vec<u8>, //
+	pub const_on_chain_schema: Vec<u8>,    //
 	pub meta_update_permission: MetaUpdatePermission,
-	pub transfers_enabled: bool,
 }
 
 #[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
@@ -246,42 +246,57 @@
 	pub variable_data: Vec<u8>,
 }
 
-#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
+#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo)]
 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
-pub struct CollectionLimits<BlockNumber: Encode + Decode> {
+pub struct CollectionLimits {
 	pub account_token_ownership_limit: Option<u32>,
-	pub sponsored_data_size: u32,
+	pub sponsored_data_size: Option<u32>,
 	/// None - setVariableMetadata is not sponsored
 	/// Some(v) - setVariableMetadata is sponsored
 	///           if there is v block between txs
-	pub sponsored_data_rate_limit: Option<BlockNumber>,
-	pub token_limit: u32,
+	pub sponsored_data_rate_limit: Option<u32>,
+	pub token_limit: Option<u32>,
 
 	// Timeouts for item types in passed blocks
-	pub sponsor_transfer_timeout: u32,
-	pub owner_can_transfer: bool,
-	pub owner_can_destroy: bool,
+	pub sponsor_transfer_timeout: Option<u32>,
+	pub owner_can_transfer: Option<bool>,
+	pub owner_can_destroy: Option<bool>,
+	pub transfers_enabled: Option<bool>,
 }
 
-impl<BlockNumber: Encode + Decode> CollectionLimits<BlockNumber> {
+impl CollectionLimits {
 	pub fn account_token_ownership_limit(&self) -> u32 {
 		self.account_token_ownership_limit
 			.unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)
-			.min(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)
+			.min(MAX_TOKEN_OWNERSHIP)
 	}
-}
-
-impl<BlockNumber: Encode + Decode> Default for CollectionLimits<BlockNumber> {
-	fn default() -> Self {
-		Self {
-			account_token_ownership_limit: Some(10_000_000),
-			token_limit: u32::max_value(),
-			sponsored_data_size: u32::MAX,
-			sponsored_data_rate_limit: None,
-			sponsor_transfer_timeout: 14400,
-			owner_can_transfer: true,
-			owner_can_destroy: true,
-		}
+	pub fn sponsored_data_size(&self) -> u32 {
+		self.sponsored_data_size
+			.unwrap_or(CUSTOM_DATA_LIMIT)
+			.min(CUSTOM_DATA_LIMIT)
+	}
+	pub fn token_limit(&self) -> u32 {
+		self.token_limit
+			.unwrap_or(COLLECTION_TOKEN_LIMIT)
+			.min(COLLECTION_TOKEN_LIMIT)
+	}
+	pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {
+		self.sponsor_transfer_timeout
+			.unwrap_or(default)
+			.min(MAX_SPONSOR_TIMEOUT)
+	}
+	pub fn owner_can_transfer(&self) -> bool {
+		self.owner_can_transfer.unwrap_or(true)
+	}
+	pub fn owner_can_destroy(&self) -> bool {
+		self.owner_can_destroy.unwrap_or(true)
+	}
+	pub fn transfers_enabled(&self) -> bool {
+		self.transfers_enabled.unwrap_or(true)
+	}
+	pub fn sponsored_data_rate_limit(&self) -> Option<u32> {
+		self.sponsored_data_rate_limit
+			.map(|v| v.min(MAX_SPONSOR_TIMEOUT))
 	}
 }