difftreelog
Merge pull request #125 from usetech-llc/fix/NFTPAR-367_createMultipleItems_overflow_checks
in: master
Fix bulk mint exceeds collection token limit
2 files changed
pallets/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);
tests/src/createMultipleItems.test.tsdiffbeforeafterboth11import {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';161817chai.use(chaiAsPromised);19chai.use(chaiAsPromised);93 });95 });94 });96 });9798 it('Can mint amount of items equals to collection limits', async () => {99 await usingApi(async (api) => {100 const alice = privateKey('//Alice');101102 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});9611797describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {118describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {176 });197 });177 });198 });199200 it('Fails when minting tokens exceeds collectionLimits amount', async () => {201 await usingApi(async (api) => {202 const alice = privateKey('//Alice');203204 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