git.delta.rocks / unique-network / refs/commits / 7bcde70a2ca7

difftreelog

NFTPAR-118. Per Collection Limits

str-mv2020-12-11parent: #68e6834.patch.diff
in: master

3 files changed

modifiedREADME.mddiffbeforeafterboth
241 "ReFungible": "CreateReFungibleData"241 "ReFungible": "CreateReFungibleData"
242 }242 }
243 }243 }
244 "CollectionLimits": {
245 "AccountTokenOwnershipLimit": "u32",
246 "SponsoredDataSize": "u32",
247 "TokenLimit": "u32",
248 "SponsorTransferTimeout": "u32"
249 }
244}250}
245251
246```252```
modifiednode/src/chain_spec.rsdiffbeforeafterboth
171 sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),171 sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),
172 unconfirmed_sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),172 unconfirmed_sponsor: get_account_id_from_seed::<sr25519::Public>("Alice"),
173 const_on_chain_schema: vec![],173 const_on_chain_schema: vec![],
174 variable_on_chain_schema: vec![]174 variable_on_chain_schema: vec![],
175 limits: CollectionLimits::default()
175 },176 },
176 )],177 )],
177 nft_item_id: vec![],178 nft_item_id: vec![],
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
109 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 sender
111 pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship111 pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship
112 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}
167
168#[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,
174
175 // Timeouts for item types in passed blocks
176 pub sponsor_transfer_timeout: u32,
177}
178
179impl 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}
166188
167#[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 exceeded
348 CollectionTokenLimitExceeded,
349 /// Account token limit exceeded per collection
350 AccountTokenLimitExceeded
325 }351 }
326}352}
327353
537 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 };
541568
542 // Add new collection to map569 // Add new collection to map
1380 Ok(())1407 Ok(())
1381 }1408 }
13821409
1383 // #[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(())1418
1392 // }1419 let mut target_collection = <Collection<T>>::get(collection_id);
1393 1420 target_collection.limits = limits;
1421 <Collection<T>>::insert(collection_id, target_collection);
1422
1423 Ok(())
1424 }
1394 }1425 }
1395}1426}
13961427
14001431
1401 if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {1432 if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {
1433
1434 // check token limit and account token limit
1435 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 model
2212 // Parse call to extract collection ID and access collection sponsor2248 // Parse call to extract collection ID and access collection sponsor
2213 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)) => {
2251
2252 // check free create limit
2253 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).sponsor
2216 }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;
22192264
2220 // sponsor timeout2265 // sponsor timeout
2221 let sponsor_transfer = match _collection_mode {2266 let sponsor_transfer = match _collection_mode {
2222 CollectionMode::NFT => {2267 CollectionMode::NFT => {
2268
2269 // get correct limit
2270 let limit: u32 = if _collection_limits.sponsor_transfer_timeout > 0 {
2271 _collection_limits.sponsor_transfer_timeout
2272 } else {
2273 ChainLimit::get().nft_sponsor_transfer_timeout
2274 };
2275
2223 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 true
2233 }2286 }
2234 CollectionMode::Fungible(_) => {2287 CollectionMode::Fungible(_) => {
2288
2289 // get correct limit
2290 let limit: u32 = if _collection_limits.sponsor_transfer_timeout > 0 {
2291 _collection_limits.sponsor_transfer_timeout
2292 } else {
2293 ChainLimit::get().fungible_sponsor_transfer_timeout
2294 };
2295
2235 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(_) => {
2318
2319 // get correct limit
2320 let limit: u32 = if _collection_limits.sponsor_transfer_timeout > 0 {
2321 _collection_limits.sponsor_transfer_timeout
2322 } else {
2323 ChainLimit::get().refungible_sponsor_transfer_timeout
2324 };
2325
2257 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