git.delta.rocks / unique-network / refs/commits / 07649f272b8b

difftreelog

Merge pull request #125 from usetech-llc/fix/NFTPAR-367_createMultipleItems_overflow_checks

usetech-llc2021-03-14parents: #447a9ec #a5cb42a.patch.diff
in: master
Fix bulk mint exceeds collection token limit

2 files changed

modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -967,7 +967,7 @@
 
             let target_collection = <Collection<T>>::get(collection_id);
 
-            Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?;
+            Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner, 1)?;
             Self::validate_create_item_args(&target_collection, &data)?;
             Self::create_item_no_validation(collection_id, owner, data)?;
 
@@ -1003,7 +1003,7 @@
             Self::collection_exists(collection_id)?;
             let target_collection = <Collection<T>>::get(collection_id);
 
-            Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?;
+            Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner, items_data.len() as u32)?;
 
             for data in &items_data {
                 Self::validate_create_item_args(&target_collection, data)?;
@@ -1638,13 +1638,17 @@
         Ok(())
     }
 
-    fn can_create_items_in_collection(collection_id: CollectionId, collection: &CollectionType<T::AccountId>, sender: &T::AccountId, owner: &T::AccountId) -> DispatchResult {
+    fn can_create_items_in_collection(collection_id: CollectionId, collection: &CollectionType<T::AccountId>, sender: &T::AccountId, owner: &T::AccountId, amount: u32) -> DispatchResult {
 
         // check token limit and account token limit
-        let total_items: u32 = ItemListIndex::get(collection_id);
-        let account_items: u32 = <AddressTokens<T>>::get(collection_id, owner).len() as u32;
-        ensure!(collection.limits.token_limit > total_items,  Error::<T>::CollectionTokenLimitExceeded);
-        ensure!(collection.limits.account_token_ownership_limit > account_items,  Error::<T>::AccountTokenLimitExceeded);
+        let total_items: u32 = ItemListIndex::get(collection_id)
+            .checked_add(amount)
+            .ok_or(Error::<T>::CollectionTokenLimitExceeded)?;
+        let account_items: u32 = (<AddressTokens<T>>::get(collection_id, owner).len() as u32)
+            .checked_add(amount)
+            .ok_or(Error::<T>::AccountTokenLimitExceeded)?;
+        ensure!(collection.limits.token_limit >= total_items,  Error::<T>::CollectionTokenLimitExceeded);
+        ensure!(collection.limits.account_token_ownership_limit >= account_items,  Error::<T>::AccountTokenLimitExceeded);
 
         if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {
             ensure!(collection.mint_mode == true, Error::<T>::PublicMintingNotAllowed);
modifiedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
11import {11import {
12 createCollectionExpectSuccess,12 createCollectionExpectSuccess,
13 destroyCollectionExpectSuccess,13 destroyCollectionExpectSuccess,
14 getGenericResult,
14 IReFungibleTokenDataType,15 IReFungibleTokenDataType,
16 setCollectionLimitsExpectSuccess,
15} from './util/helpers';17} from './util/helpers';
1618
17chai.use(chaiAsPromised);19chai.use(chaiAsPromised);
93 });95 });
94 });96 });
97
98 it('Can mint amount of items equals to collection limits', async () => {
99 await usingApi(async (api) => {
100 const alice = privateKey('//Alice');
101
102 const collectionId = await createCollectionExpectSuccess();
103 await setCollectionLimitsExpectSuccess(alice, collectionId, {
104 TokenLimit: 2,
105 });
106 const args = [
107 { nft: ['A', 'A'] },
108 { nft: ['B', 'B'] },
109 ];
110 const createMultipleItemsTx = api.tx.nft.createMultipleItems(collectionId, alice.address, args);
111 const events = await submitTransactionAsync(alice, createMultipleItemsTx);
112 const result = getGenericResult(events);
113 expect(result.success).to.be.true;
114 });
115 });
95});116});
96117
97describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {118describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {
176 });197 });
177 });198 });
199
200 it('Fails when minting tokens exceeds collectionLimits amount', async () => {
201 await usingApi(async (api) => {
202 const alice = privateKey('//Alice');
203
204 const collectionId = await createCollectionExpectSuccess();
205 await setCollectionLimitsExpectSuccess(alice, collectionId, {
206 TokenLimit: 1,
207 });
208 const args = [
209 { nft: ['A', 'A'] },
210 { nft: ['B', 'B'] },
211 ];
212 const createMultipleItemsTx = api.tx.nft.createMultipleItems(collectionId, alice.address, args);
213 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
214 });
215 });
178});216});
179217