difftreelog
refactor make collection limits fields optional
in: master
8 files changed
pallets/common/src/lib.rsdiffbeforeafterboth105 Ok(())105 Ok(())106 }106 }107 pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> Result<bool, DispatchError> {107 pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> Result<bool, DispatchError> {108 Ok(self.limits.owner_can_transfer && self.is_owner_or_admin(user)?)108 Ok(self.limits.owner_can_transfer() && self.is_owner_or_admin(user)?)109 }109 }110 pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> Result<bool, DispatchError> {110 pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> Result<bool, DispatchError> {111 Ok(self.limits.owner_can_transfer && self.is_owner_or_admin(user)?)111 Ok(self.limits.owner_can_transfer() && self.is_owner_or_admin(user)?)112 }112 }113 pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {113 pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {114 self.consume_sload()?;114 self.consume_sload()?;405 collection: CollectionHandle<T>,405 collection: CollectionHandle<T>,406 sender: &T::CrossAccountId,406 sender: &T::CrossAccountId,407 ) -> DispatchResult {407 ) -> DispatchResult {408 if !collection.limits.owner_can_destroy {409 fail!(Error::<T>::NoPermission);408 ensure!(410 }409 collection.limits.owner_can_destroy(),410 <Error<T>>::NoPermission,411 );411 collection.check_is_owner(&sender)?;412 collection.check_is_owner(&sender)?;412413pallets/fungible/src/lib.rsdiffbeforeafterboth157 amount: u128,157 amount: u128,158 ) -> DispatchResult {158 ) -> DispatchResult {159 ensure!(159 ensure!(160 collection.transfers_enabled,160 collection.limits.transfers_enabled(),161 <CommonError<T>>::TransferNotAllowed161 <CommonError<T>>::TransferNotAllowed,162 );162 );163163164 if collection.access == AccessMode::WhiteList {164 if collection.access == AccessMode::WhiteList {pallets/nft/src/eth/sponsoring.rsdiffbeforeafterboth43 let token_id: u32 = token_id.try_into().map_err(|_| AnyError)?;43 let token_id: u32 = token_id.try_into().map_err(|_| AnyError)?;44 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;44 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;45 let collection_limits = &collection.limits;45 let collection_limits = &collection.limits;46 let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {46 let limit =47 collection_limits.sponsor_transfer_timeout48 } else {49 NFT_SPONSOR_TRANSFER_TIMEOUT47 collection_limits.sponsor_transfer_timeout(NFT_SPONSOR_TRANSFER_TIMEOUT);50 };514852 let mut sponsor = true;49 let mut sponsor = true;53 if <NftTransferBasket<T>>::contains_key(collection_id, token_id) {50 if <NftTransferBasket<T>>::contains_key(collection_id, token_id) {74 UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {71 UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {75 let who = T::CrossAccountId::from_eth(*caller);72 let who = T::CrossAccountId::from_eth(*caller);76 let collection_limits = &collection.limits;73 let collection_limits = &collection.limits;77 let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {74 let limit = collection_limits78 collection_limits.sponsor_transfer_timeout79 } else {80 FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT75 .sponsor_transfer_timeout(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT);81 };827683 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;77 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;84 let mut sponsored = true;78 let mut sponsored = true;pallets/nft/src/lib.rsdiffbeforeafterboth37use nft_data_structs::{37use nft_data_structs::{38 MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, CUSTOM_DATA_LIMIT,38 MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, CUSTOM_DATA_LIMIT,39 VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, COLLECTION_ADMINS_LIMIT,39 VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, COLLECTION_ADMINS_LIMIT,40 OFFCHAIN_SCHEMA_LIMIT, AccessMode, Collection, CreateItemData, CollectionLimits, CollectionId,40 OFFCHAIN_SCHEMA_LIMIT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,41 NFT_SPONSOR_TRANSFER_TIMEOUT, AccessMode, Collection, CreateItemData, CollectionLimits,41 CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,42 CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,42};43};43use pallet_common::{44use pallet_common::{189 // Anyone can create a collection190 // Anyone can create a collection190 let who = ensure_signed(origin)?;191 let who = ensure_signed(origin)?;191192 let limits = CollectionLimits::<T::BlockNumber> {193 sponsored_data_size: CUSTOM_DATA_LIMIT,194 ..Default::default()195 };196192197 // Create new collection193 // Create new collection198 let new_collection = Collection::<T> {194 let new_collection = Collection::<T> {208 sponsorship: SponsorshipState::Disabled,204 sponsorship: SponsorshipState::Disabled,209 variable_on_chain_schema: Vec::new(),205 variable_on_chain_schema: Vec::new(),210 const_on_chain_schema: Vec::new(),206 const_on_chain_schema: Vec::new(),211 limits,207 limits: Default::default(),212 transfers_enabled: true,213 meta_update_permission: Default::default(),208 meta_update_permission: Default::default(),214 };209 };215210582577583 // =========578 // =========584579585 target_collection.transfers_enabled = value;580 target_collection.limits.transfers_enabled = Some(value);586 target_collection.save()581 target_collection.save()587 }582 }588583888 pub fn set_collection_limits(883 pub fn set_collection_limits(889 origin,884 origin,890 collection_id: CollectionId,885 collection_id: CollectionId,891 new_limits: CollectionLimits<T::BlockNumber>,886 new_limit: CollectionLimits,892 ) -> DispatchResult {887 ) -> DispatchResult {888 let mut new_limit = new_limit;893 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);889 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);894 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;890 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;895 target_collection.check_is_owner(&sender)?;891 target_collection.check_is_owner(&sender)?;896 let old_limits = &target_collection.limits;892 let old_limit = &target_collection.limits;897893898 // collection bounds899 ensure!(new_limits.sponsor_transfer_timeout <= MAX_SPONSOR_TIMEOUT &&894 macro_rules! limit_default {895 ($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{896 $(897 if let Some($new) = $new.$field {900 new_limits.account_token_ownership_limit.unwrap_or(0) <= MAX_TOKEN_OWNERSHIP &&898 let $old = $old.$field($($arg)?);899 let _ = $new;900 let _ = $old;901 $check902 } else {903 $new.$field = $old.$field904 }905 )*906 }};907 }908909 limit_default!(old_limit, new_limit,910 account_token_ownership_limit => ensure!(911 new_limit <= MAX_TOKEN_OWNERSHIP,912 <Error<T>>::CollectionLimitBoundsExceeded,913 ),901 new_limits.sponsored_data_size <= CUSTOM_DATA_LIMIT,914 sponsor_transfer_timeout(match target_collection.mode {915 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,916 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,917 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,918 }) => ensure!(919 new_limit <= MAX_SPONSOR_TIMEOUT,902 Error::<T>::CollectionLimitBoundsExceeded);920 <Error<T>>::CollectionLimitBoundsExceeded,903921 ),904 // token_limit check prev905 ensure!(old_limits.token_limit >= new_limits.token_limit, <CommonError<T>>::CollectionTokenLimitExceeded);922 sponsored_data_size => ensure!(923 new_limit <= CUSTOM_DATA_LIMIT,924 <Error<T>>::CollectionLimitBoundsExceeded,925 ),906 ensure!(new_limits.token_limit > 0, <CommonError<T>>::CollectionTokenLimitExceeded);926 token_limit => ensure!(907927 old_limit >= new_limit && new_limit > 0,928 <CommonError<T>>::CollectionTokenLimitExceeded929 ),908 ensure!(930 owner_can_transfer => ensure!(909 (old_limits.owner_can_transfer || !new_limits.owner_can_transfer) &&931 old_limit || !new_limit,932 <Error<T>>::OwnerPermissionsCantBeReverted,933 ),910 (old_limits.owner_can_destroy || !new_limits.owner_can_destroy),934 owner_can_destroy => ensure!(935 old_limit || !new_limit,911 Error::<T>::OwnerPermissionsCantBeReverted,936 <Error<T>>::OwnerPermissionsCantBeReverted,937 ),938 sponsored_data_rate_limit => {},939 transfers_enabled => {},912 );940 );913941914 target_collection.limits = new_limits;942 target_collection.limits = new_limit;915943916 target_collection.save()944 target_collection.save()917 }945 }pallets/nft/src/sponsorship.rsdiffbeforeafterboth282829 let limit = collection.limits.sponsor_transfer_timeout;29 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 });30 if CreateItemBasket::<T>::contains_key((collection_id, &who)) {36 if CreateItemBasket::<T>::contains_key((collection_id, &who)) {31 let last_tx_block = CreateItemBasket::<T>::get((collection_id, &who));37 let last_tx_block = CreateItemBasket::<T>::get((collection_id, &who));32 let limit_time = last_tx_block + limit.into();38 let limit_time = last_tx_block + limit.into();37 CreateItemBasket::<T>::insert((collection_id, who.clone()), block_number);43 CreateItemBasket::<T>::insert((collection_id, who.clone()), block_number);384439 // check free create limit45 // check free create limit40 if collection.limits.sponsored_data_size >= (_properties.data_size() as u32) {46 if collection.limits.sponsored_data_size() >= (_properties.data_size() as u32) {41 collection.sponsorship.sponsor().cloned()47 collection.sponsorship.sponsor().cloned()42 } else {48 } else {43 None49 None61 sponsor_transfer = match collection_mode {67 sponsor_transfer = match collection_mode {62 CollectionMode::NFT => {68 CollectionMode::NFT => {63 // get correct limit69 // get correct limit64 let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {70 let limit =65 collection_limits.sponsor_transfer_timeout66 } else {67 NFT_SPONSOR_TRANSFER_TIMEOUT71 collection_limits.sponsor_transfer_timeout(NFT_SPONSOR_TRANSFER_TIMEOUT);68 };697270 let mut sponsored = true;73 let mut sponsored = true;71 if NftTransferBasket::<T>::contains_key(collection_id, item_id) {74 if NftTransferBasket::<T>::contains_key(collection_id, item_id) {83 }86 }84 CollectionMode::Fungible(_) => {87 CollectionMode::Fungible(_) => {85 // get correct limit88 // get correct limit86 let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {89 let limit = collection_limits87 collection_limits.sponsor_transfer_timeout88 } else {89 FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT90 .sponsor_transfer_timeout(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT);90 };919192 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;92 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;93 let mut sponsored = true;93 let mut sponsored = true;106 }106 }107 CollectionMode::ReFungible => {107 CollectionMode::ReFungible => {108 // get correct limit108 // get correct limit109 let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {109 let limit = collection_limits110 collection_limits.sponsor_transfer_timeout111 } else {112 REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT110 .sponsor_transfer_timeout(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT);113 };114111115 let mut sponsored = true;112 let mut sponsored = true;116 if ReFungibleTransferBasket::<T>::contains_key(collection_id, item_id) {113 if ReFungibleTransferBasket::<T>::contains_key(collection_id, item_id) {150 // Can't sponsor fungible collection, this tx will be rejected147 // Can't sponsor fungible collection, this tx will be rejected151 // as invalid148 // as invalid152 !matches!(collection.mode, CollectionMode::Fungible(_)) &&149 !matches!(collection.mode, CollectionMode::Fungible(_)) &&153 data.len() <= collection.limits.sponsored_data_size as usize150 data.len() <= collection.limits.sponsored_data_size() as usize154 {151 {155 if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit {152 if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit() {156 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;153 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;157154158 if VariableMetaDataBasket::<T>::get(collection_id, item_id)155 if VariableMetaDataBasket::<T>::get(collection_id, item_id)159 .map(|last_block| block_number - last_block > rate_limit)156 .map(|last_block| block_number - last_block > rate_limit.into())160 .unwrap_or(true)157 .unwrap_or(true)161 {158 {162 sponsor_metadata_changes = true;159 sponsor_metadata_changes = true;pallets/nonfungible/src/lib.rsdiffbeforeafterboth164 .ok_or_else(|| <CommonError<T>>::TokenNotFound)?;164 .ok_or_else(|| <CommonError<T>>::TokenNotFound)?;165 ensure!(165 ensure!(166 &token_data.owner == sender166 &token_data.owner == sender167 || (collection.limits.owner_can_transfer167 || (collection.limits.owner_can_transfer()168 && collection.is_owner_or_admin(sender)?),168 && collection.is_owner_or_admin(sender)?),169 <CommonError<T>>::NoPermission169 <CommonError<T>>::NoPermission170 );170 );215 token: TokenId,215 token: TokenId,216 ) -> DispatchResult {216 ) -> DispatchResult {217 ensure!(217 ensure!(218 collection.transfers_enabled,218 collection.limits.transfers_enabled(),219 <CommonError<T>>::TransferNotAllowed219 <CommonError<T>>::TransferNotAllowed220 );220 );221221222 let token_data = <TokenData<T>>::get((collection.id, token))222 let token_data = <TokenData<T>>::get((collection.id, token))223 .ok_or_else(|| <CommonError<T>>::TokenNotFound)?;223 .ok_or_else(|| <CommonError<T>>::TokenNotFound)?;224 ensure!(224 ensure!(225 &token_data.owner == from225 &token_data.owner == from226 || (collection.limits.owner_can_transfer && collection.is_owner_or_admin(from)?),226 || (collection.limits.owner_can_transfer()227 && collection.is_owner_or_admin(from)?),227 <CommonError<T>>::NoPermission228 <CommonError<T>>::NoPermission228 );229 );327 .checked_add(data.len() as u32)328 .checked_add(data.len() as u32)328 .ok_or(ArithmeticError::Overflow)?;329 .ok_or(ArithmeticError::Overflow)?;329 ensure!(330 ensure!(330 tokens_minted < collection.limits.token_limit,331 tokens_minted < collection.limits.token_limit(),331 <CommonError<T>>::CollectionTokenLimitExceeded332 <CommonError<T>>::CollectionTokenLimitExceeded332 );333 );333 collection.consume_sstore()?;334 collection.consume_sstore()?;pallets/refungible/src/lib.rsdiffbeforeafterboth268 amount: u128,268 amount: u128,269 ) -> DispatchResult {269 ) -> DispatchResult {270 ensure!(270 ensure!(271 collection.transfers_enabled,271 collection.limits.transfers_enabled(),272 <CommonError<T>>::TransferNotAllowed272 <CommonError<T>>::TransferNotAllowed273 );273 );274274404 .checked_add(data.len() as u32)404 .checked_add(data.len() as u32)405 .ok_or(ArithmeticError::Overflow)?;405 .ok_or(ArithmeticError::Overflow)?;406 ensure!(406 ensure!(407 tokens_minted < collection.limits.token_limit,407 tokens_minted < collection.limits.token_limit(),408 <CommonError<T>>::CollectionTokenLimitExceeded408 <CommonError<T>>::CollectionTokenLimitExceeded409 );409 );410410primitives/nft/src/lib.rsdiffbeforeafterboth42 1042 1043};43};44pub const COLLECTION_ADMINS_LIMIT: u64 = 5;44pub const COLLECTION_ADMINS_LIMIT: u64 = 5;45pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;45pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {46pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {46 100000047 100000047} else {48} else {217 pub offchain_schema: Vec<u8>,218 pub offchain_schema: Vec<u8>,218 pub schema_version: SchemaVersion,219 pub schema_version: SchemaVersion,219 pub sponsorship: SponsorshipState<T::AccountId>,220 pub sponsorship: SponsorshipState<T::AccountId>,220 pub limits: CollectionLimits<T::BlockNumber>, // Collection private restrictions221 pub limits: CollectionLimits, // Collection private restrictions221 pub variable_on_chain_schema: Vec<u8>, //222 pub variable_on_chain_schema: Vec<u8>, //222 pub const_on_chain_schema: Vec<u8>, //223 pub const_on_chain_schema: Vec<u8>, //223 pub meta_update_permission: MetaUpdatePermission,224 pub meta_update_permission: MetaUpdatePermission,224 pub transfers_enabled: bool,225}225}226226227#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]227#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]246 pub variable_data: Vec<u8>,246 pub variable_data: Vec<u8>,247}247}248248249#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]249#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo)]250#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]250#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]251pub struct CollectionLimits<BlockNumber: Encode + Decode> {251pub struct CollectionLimits {252 pub account_token_ownership_limit: Option<u32>,252 pub account_token_ownership_limit: Option<u32>,253 pub sponsored_data_size: u32,253 pub sponsored_data_size: Option<u32>,254 /// None - setVariableMetadata is not sponsored254 /// None - setVariableMetadata is not sponsored255 /// Some(v) - setVariableMetadata is sponsored255 /// Some(v) - setVariableMetadata is sponsored256 /// if there is v block between txs256 /// if there is v block between txs257 pub sponsored_data_rate_limit: Option<BlockNumber>,257 pub sponsored_data_rate_limit: Option<u32>,258 pub token_limit: u32,258 pub token_limit: Option<u32>,259259260 // Timeouts for item types in passed blocks260 // Timeouts for item types in passed blocks261 pub sponsor_transfer_timeout: u32,261 pub sponsor_transfer_timeout: Option<u32>,262 pub owner_can_transfer: bool,262 pub owner_can_transfer: Option<bool>,263 pub owner_can_destroy: bool,263 pub owner_can_destroy: Option<bool>,264 pub transfers_enabled: Option<bool>,264}265}265266266impl<BlockNumber: Encode + Decode> CollectionLimits<BlockNumber> {267impl CollectionLimits {267 pub fn account_token_ownership_limit(&self) -> u32 {268 pub fn account_token_ownership_limit(&self) -> u32 {268 self.account_token_ownership_limit269 self.account_token_ownership_limit269 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)270 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)270 .min(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)271 .min(MAX_TOKEN_OWNERSHIP)271 }272 }273 pub fn sponsored_data_size(&self) -> u32 {274 self.sponsored_data_size275 .unwrap_or(CUSTOM_DATA_LIMIT)276 .min(CUSTOM_DATA_LIMIT)277 }278 pub fn token_limit(&self) -> u32 {279 self.token_limit280 .unwrap_or(COLLECTION_TOKEN_LIMIT)281 .min(COLLECTION_TOKEN_LIMIT)282 }283 pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {284 self.sponsor_transfer_timeout285 .unwrap_or(default)286 .min(MAX_SPONSOR_TIMEOUT)287 }288 pub fn owner_can_transfer(&self) -> bool {289 self.owner_can_transfer.unwrap_or(true)290 }291 pub fn owner_can_destroy(&self) -> bool {292 self.owner_can_destroy.unwrap_or(true)293 }294 pub fn transfers_enabled(&self) -> bool {295 self.transfers_enabled.unwrap_or(true)296 }297 pub fn sponsored_data_rate_limit(&self) -> Option<u32> {298 self.sponsored_data_rate_limit299 .map(|v| v.min(MAX_SPONSOR_TIMEOUT))300 }272}301}273274impl<BlockNumber: Encode + Decode> Default for CollectionLimits<BlockNumber> {275 fn default() -> Self {276 Self {277 account_token_ownership_limit: Some(10_000_000),278 token_limit: u32::max_value(),279 sponsored_data_size: u32::MAX,280 sponsored_data_rate_limit: None,281 sponsor_transfer_timeout: 14400,282 owner_can_transfer: true,283 owner_can_destroy: true,284 }285 }286}287302288/// BoundedVec doesn't supports serde303/// BoundedVec doesn't supports serde289#[cfg(feature = "serde1")]304#[cfg(feature = "serde1")]