difftreelog
NFTPAR-118. Per Collection Limits
in: master
3 files changed
README.mddiffbeforeafterboth--- a/README.md
+++ b/README.md
@@ -241,6 +241,12 @@
"ReFungible": "CreateReFungibleData"
}
}
+ "CollectionLimits": {
+ "AccountTokenOwnershipLimit": "u32",
+ "SponsoredDataSize": "u32",
+ "TokenLimit": "u32",
+ "SponsorTransferTimeout": "u32"
+ }
}
```
\ No newline at end of file
node/src/chain_spec.rsdiffbeforeafterboth--- a/node/src/chain_spec.rs
+++ b/node/src/chain_spec.rs
@@ -171,7 +171,8 @@
sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),
unconfirmed_sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),
const_on_chain_schema: vec![],
- variable_on_chain_schema: vec![]
+ variable_on_chain_schema: vec![],
+ limits: CollectionLimits::default()
},
)],
nft_item_id: vec![],
pallets/nft/src/lib.rsdiffbeforeafterboth109 pub offchain_schema: Vec<u8>,109 pub offchain_schema: Vec<u8>,110 pub sponsor: AccountId, // Who pays fees. If set to default address, the fees are applied to the transaction sender110 pub sponsor: AccountId, // Who pays fees. If set to default address, the fees are applied to the transaction sender111 pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship111 pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship112 pub limits: CollectionLimits, // Collection private restrictions 112 pub variable_on_chain_schema: Vec<u8>, //113 pub variable_on_chain_schema: Vec<u8>, //113 pub const_on_chain_schema: Vec<u8>, //114 pub const_on_chain_schema: Vec<u8>, //114}115}164 pub start_block: BlockNumber,165 pub start_block: BlockNumber,165}166}167168#[derive(Encode, Decode, Debug, Clone, PartialEq)]169#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]170pub struct CollectionLimits {171 pub account_token_ownership_limit: u32,172 pub sponsored_data_size: u32,173 pub token_limit: u32,174175 // Timeouts for item types in passed blocks176 pub sponsor_transfer_timeout: u32,177}178179impl Default for CollectionLimits {180 fn default() -> CollectionLimits {181 CollectionLimits { 182 account_token_ownership_limit: 0, 183 token_limit: 0,184 sponsored_data_size: 0, 185 sponsor_transfer_timeout: 0 }186 }187}166188167#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]189#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]168#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]190#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]321 /// Unexpected collection type.343 /// Unexpected collection type.322 UnexpectedCollectionType,344 UnexpectedCollectionType,323 /// Can't store metadata in fungible tokens.345 /// Can't store metadata in fungible tokens.324 CantStoreMetadataInFungibleTokens346 CantStoreMetadataInFungibleTokens,347 /// Collection token limit exceeded348 CollectionTokenLimitExceeded,349 /// Account token limit exceeded per collection350 AccountTokenLimitExceeded325 }351 }326}352}327353537 unconfirmed_sponsor: T::AccountId::default(),563 unconfirmed_sponsor: T::AccountId::default(),538 variable_on_chain_schema: Vec::new(),564 variable_on_chain_schema: Vec::new(),539 const_on_chain_schema: Vec::new(),565 const_on_chain_schema: Vec::new(),566 limits: CollectionLimits::default(),540 };567 };541568542 // Add new collection to map569 // Add new collection to map1380 Ok(())1407 Ok(())1381 }1408 }138214091383 // #[cfg(feature = "runtime-benchmarks")]1410 #[weight = 0]1384 // #[weight = 0]1411 pub fn set_collection_limits(1385 // pub fn add_contract_sponsoring_debug(1412 origin,1386 // origin,1413 collection_id: u64,1387 // contract_address: T::AccountId, 1414 limits: CollectionLimits,1388 // owner: T::AccountId) -> DispatchResult {1415 ) -> DispatchResult {1389 // let sender = ensure_signed(origin)?;1416 let sender = ensure_signed(origin)?;1390 // <ContractOwner<T>>::insert(contract_address.clone(), owner);1417 Self::check_owner_permissions(collection_id, sender.clone())?;1391 // Ok(())14181392 // }1419 let mut target_collection = <Collection<T>>::get(collection_id);1393 1420 target_collection.limits = limits;1421 <Collection<T>>::insert(collection_id, target_collection);14221423 Ok(())1424 } 1394 }1425 }1395}1426}13961427140014311401 if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {1432 if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {14331434 // check token limit and account token limit1435 let total_items: u64 = ItemListIndex::get(collection_id);1436 let account_items: u32 = <AddressTokens<T>>::get(collection_id, sender.clone()).len() as u32;1437 ensure!(collection.limits.token_limit as u64 > total_items, Error::<T>::CollectionTokenLimitExceeded);1438 ensure!(collection.limits.account_token_ownership_limit > account_items, Error::<T>::AccountTokenLimitExceeded);1402 ensure!(collection.mint_mode == true, Error::<T>::PublicMintingNotAllowed);1439 ensure!(collection.mint_mode == true, Error::<T>::PublicMintingNotAllowed);1403 Self::check_white_list(collection_id, owner)?;1440 Self::check_white_list(collection_id, owner)?;1404 Self::check_white_list(collection_id, sender)?;1441 Self::check_white_list(collection_id, sender)?;2211 // Determine who is paying transaction fee based on ecnomic model2247 // Determine who is paying transaction fee based on ecnomic model2212 // Parse call to extract collection ID and access collection sponsor2248 // Parse call to extract collection ID and access collection sponsor2213 let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {2249 let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {2214 Some(Call::create_item(collection_id, _properties, _owner)) => {2250 Some(Call::create_item(collection_id, _owner, _properties)) => {22512252 // check free create limit2253 if <Collection<T>>::get(collection_id).limits.sponsored_data_size >= (_properties.len() as u32)2254 {2215 <Collection<T>>::get(collection_id).sponsor2255 <Collection<T>>::get(collection_id).sponsor2216 }2256 } else {2257 T::AccountId::default()2258 }2259 }2217 Some(Call::transfer(_new_owner, collection_id, _item_id, _value)) => {2260 Some(Call::transfer(_new_owner, collection_id, _item_id, _value)) => {2261 2262 let _collection_limits = <Collection<T>>::get(collection_id).limits;2218 let _collection_mode = <Collection<T>>::get(collection_id).mode;2263 let _collection_mode = <Collection<T>>::get(collection_id).mode;221922642220 // sponsor timeout2265 // sponsor timeout2221 let sponsor_transfer = match _collection_mode {2266 let sponsor_transfer = match _collection_mode {2222 CollectionMode::NFT => {2267 CollectionMode::NFT => {22682269 // get correct limit2270 let limit: u32 = if _collection_limits.sponsor_transfer_timeout > 0 {2271 _collection_limits.sponsor_transfer_timeout2272 } else {2273 ChainLimit::get().nft_sponsor_transfer_timeout2274 };22752223 let basket = <NftTransferBasket<T>>::get(collection_id, _item_id);2276 let basket = <NftTransferBasket<T>>::get(collection_id, _item_id);2224 let block_number = <system::Module<T>>::block_number() as T::BlockNumber;2277 let block_number = <system::Module<T>>::block_number() as T::BlockNumber;2225 let limit_time = basket + ChainLimit::get().nft_sponsor_transfer_timeout.into();2278 let limit_time = basket + limit.into();2226 if block_number >= limit_time {2279 if block_number >= limit_time {2227 <NftTransferBasket<T>>::insert(collection_id, _item_id, block_number);2280 <NftTransferBasket<T>>::insert(collection_id, _item_id, block_number);2228 true2281 true2233 }2286 }2234 CollectionMode::Fungible(_) => {2287 CollectionMode::Fungible(_) => {22882289 // get correct limit2290 let limit: u32 = if _collection_limits.sponsor_transfer_timeout > 0 {2291 _collection_limits.sponsor_transfer_timeout2292 } else {2293 ChainLimit::get().fungible_sponsor_transfer_timeout2294 };22952235 let mut basket = <FungibleTransferBasket<T>>::get(collection_id, _item_id);2296 let mut basket = <FungibleTransferBasket<T>>::get(collection_id, _item_id);2236 let block_number = <system::Module<T>>::block_number() as T::BlockNumber;2297 let block_number = <system::Module<T>>::block_number() as T::BlockNumber;2237 if basket.iter().any(|i| i.address == _new_owner.clone())2298 if basket.iter().any(|i| i.address == _new_owner.clone())2238 {2299 {2239 let item = basket.iter_mut().find(|i| i.address == _new_owner.clone()).unwrap().clone();2300 let item = basket.iter_mut().find(|i| i.address == _new_owner.clone()).unwrap().clone();2240 let limit_time = item.start_block + ChainLimit::get().fungible_sponsor_transfer_timeout.into();2301 let limit_time = item.start_block + limit.into();2241 if block_number >= limit_time {2302 if block_number >= limit_time {2242 basket.retain(|x| x.address == item.address);2303 basket.retain(|x| x.address == item.address);2243 basket.push(BasketItem { start_block: block_number, address: _new_owner.clone() });2304 basket.push(BasketItem { start_block: block_number, address: _new_owner.clone() });2255 }2316 }2256 CollectionMode::ReFungible(_) => {2317 CollectionMode::ReFungible(_) => {23182319 // get correct limit2320 let limit: u32 = if _collection_limits.sponsor_transfer_timeout > 0 {2321 _collection_limits.sponsor_transfer_timeout2322 } else {2323 ChainLimit::get().refungible_sponsor_transfer_timeout2324 };23252257 let basket = <ReFungibleTransferBasket<T>>::get(collection_id, _item_id);2326 let basket = <ReFungibleTransferBasket<T>>::get(collection_id, _item_id);2258 let block_number = <system::Module<T>>::block_number() as T::BlockNumber;2327 let block_number = <system::Module<T>>::block_number() as T::BlockNumber;2259 let limit_time = basket + ChainLimit::get().nft_sponsor_transfer_timeout.into();2328 let limit_time = basket + limit.into();2260 if block_number >= limit_time {2329 if block_number >= limit_time {2261 <ReFungibleTransferBasket<T>>::insert(collection_id, _item_id, block_number);2330 <ReFungibleTransferBasket<T>>::insert(collection_id, _item_id, block_number);2262 true2331 true