difftreelog
Fix collection limits
in: master
3 files changed
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -383,7 +383,7 @@
/// Collection limit bounds per collection exceeded
CollectionLimitBoundsExceeded,
/// Tried to enable permissions which are only permitted to be disabled
- OwnerPermissionsCantBeReturned,
+ OwnerPermissionsCantBeReverted,
/// Schema data size limit bound exceeded
SchemaDataLimitExceeded,
/// Maximum refungibility exceeded
@@ -626,7 +626,7 @@
let sender = ensure_signed(origin)?;
Self::check_owner_permissions(collection_id, sender)?;
- let mut target_collection = <Collection<T>>::get(collection_id);
+ let target_collection = <Collection<T>>::get(collection_id);
if !target_collection.limits.owner_can_destroy {
fail!(Error::<T>::NoPermission);
}
@@ -1532,31 +1532,32 @@
pub fn set_collection_limits(
origin,
collection_id: u32,
- limits: CollectionLimits,
+ new_limits: CollectionLimits,
) -> DispatchResult {
let sender = ensure_signed(origin)?;
Self::check_owner_permissions(collection_id, sender.clone())?;
let mut target_collection = <Collection<T>>::get(collection_id);
+ let old_limits = target_collection.limits;
let chain_limits = ChainLimit::get();
- let climits = target_collection.limits;
// collection bounds
- ensure!(limits.sponsor_transfer_timeout <= MAX_SPONSOR_TIMEOUT &&
- limits.account_token_ownership_limit <= MAX_TOKEN_OWNERSHIP,
+ ensure!(new_limits.sponsor_transfer_timeout <= MAX_SPONSOR_TIMEOUT &&
+ new_limits.account_token_ownership_limit <= MAX_TOKEN_OWNERSHIP &&
+ new_limits.sponsored_data_size <= chain_limits.custom_data_limit &&
+ new_limits.sponsored_mint_size <= chain_limits.custom_data_limit,
Error::<T>::CollectionLimitBoundsExceeded);
// token_limit check prev
- ensure!(climits.token_limit > limits.token_limit &&
- limits.token_limit <= chain_limits.account_token_ownership_limit,
- Error::<T>::AccountTokenLimitExceeded);
+ ensure!(old_limits.token_limit >= new_limits.token_limit, Error::<T>::CollectionTokenLimitExceeded);
+ ensure!(new_limits.token_limit > 0, Error::<T>::CollectionTokenLimitExceeded);
ensure!(
- (climits.owner_can_transfer || !limits.owner_can_transfer) &&
- (climits.owner_can_destroy || !limits.owner_can_destroy),
- Error::<T>::OwnerPermissionsCantBeReturned,
+ (old_limits.owner_can_transfer || !new_limits.owner_can_transfer) &&
+ (old_limits.owner_can_destroy || !new_limits.owner_can_destroy),
+ Error::<T>::OwnerPermissionsCantBeReverted,
);
- target_collection.limits = limits;
+ target_collection.limits = new_limits;
<Collection<T>>::insert(collection_id, target_collection);
Ok(())
tests/src/setCollectionLimits.test.tsdiffbeforeafterboth1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56// https://unique-network.readthedocs.io/en/latest/jsapi.html#setchainlimits7import { ApiPromise, Keyring } from '@polkadot/api';8import { IKeyringPair } from '@polkadot/types/types';9import chai from 'chai';10import chaiAsPromised from 'chai-as-promised';11import usingApi, {submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';12import { ICollectionInterface } from './types';13import {14 createCollectionExpectSuccess, getCreatedCollectionCount,15 getCreateItemResult,16 getDetailedCollectionInfo,17 setCollectionLimitsExpectFailure,18 setCollectionLimitsExpectSuccess,19} from './util/helpers';2021chai.use(chaiAsPromised);22const expect = chai.expect;2324let alice: IKeyringPair;25let bob: IKeyringPair;26let collectionIdForTesting: number;2728const accountTokenOwnershipLimit = 0;29const sponsoredDataSize = 0;30const sponsoredMintSize = 0;31const tokenLimit = 0;3233describe('hooks', () => {34 before(async () => {35 await usingApi(async () => {36 const keyring = new Keyring({ type: 'sr25519' });37 alice = keyring.addFromUri('//Alice');38 });39 });40 it('choose or create collection for testing', async () => {41 await usingApi(async () => {42 collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});43 });44 });45});4647describe('setCollectionLimits positive', () => {48 let tx;49 before(async () => {50 await usingApi(async () => {51 const keyring = new Keyring({ type: 'sr25519' });52 alice = keyring.addFromUri('//Alice');53 });54 });55 it('execute setCollectionLimits with predefined params ', async () => {56 await usingApi(async (api: ApiPromise) => {57 tx = api.tx.nft.setCollectionLimits(58 collectionIdForTesting,59 {60 accountTokenOwnershipLimit,61 sponsoredDataSize,62 sponsoredMintSize,63 tokenLimit,64 },65 );66 const events = await submitTransactionAsync(alice, tx);67 const result = getCreateItemResult(events);68 // tslint:disable-next-line:no-unused-expression69 expect(result.success).to.be.true;70 });71 });72 it('get collection limits defined in previous test', async () => {73 await usingApi(async (api: ApiPromise) => {74 const collectionInfo = await getDetailedCollectionInfo(api, collectionIdForTesting) as ICollectionInterface;75 expect(collectionInfo.Limits.AccountTokenOwnershipLimit.toNumber()).to.be.equal(accountTokenOwnershipLimit);76 expect(collectionInfo.Limits.SponsoredMintSize.toNumber()).to.be.equal(sponsoredMintSize);77 expect(collectionInfo.Limits.TokenLimit.toNumber()).to.be.equal(tokenLimit);78 expect(collectionInfo.Limits.SponsorTimeout.toNumber()).to.be.equal(sponsoredDataSize);79 });80 });81});8283describe('setCollectionLimits negative', () => {84 let tx;85 before(async () => {86 await usingApi(async () => {87 const keyring = new Keyring({ type: 'sr25519' });88 alice = keyring.addFromUri('//Alice');89 bob = keyring.addFromUri('//Bob');90 });91 });92 it('execute setCollectionLimits for not exists collection', async () => {93 await usingApi(async (api: ApiPromise) => {94 const collectionCount = await getCreatedCollectionCount(api);95 const nonExistedCollectionId = collectionCount + 1;96 tx = api.tx.nft.setCollectionLimits(97 nonExistedCollectionId,98 {99 accountTokenOwnershipLimit,100 sponsoredDataSize,101 sponsoredMintSize,102 tokenLimit,103 },104 );105 await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;106 });107 });108 it('execute setCollectionLimits from user who is not owner of this collection', async () => {109 await usingApi(async (api: ApiPromise) => {110 tx = api.tx.nft.setCollectionLimits(111 collectionIdForTesting,112 {113 accountTokenOwnershipLimit,114 sponsoredDataSize,115 sponsoredMintSize,116 tokenLimit,117 },118 );119 await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;120 });121 });122 it('execute setCollectionLimits with incorrect limits', async () => {123 await usingApi(async (api: ApiPromise) => {124 tx = api.tx.nft.setCollectionLimits(125 collectionIdForTesting,126 {127 accountTokenOwnershipLimit: 'awdawd',128 sponsorTransferTimeout: 'awd',129 sponsoredDataSize: '12312312312312312',130 tokenLimit: '-100',131 },132 );133 await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;134 });135 });136137 it('fails when trying to enable OwnerCanTransfer after it was disabled', async () => {138 const collectionId = await createCollectionExpectSuccess();139 await setCollectionLimitsExpectSuccess(alice, collectionId, { OwnerCanTransfer: false });140 await setCollectionLimitsExpectFailure(alice, collectionId, { OwnerCanTransfer: true });141 });142143 it('fails when trying to enable OwnerCanDestroy after it was disabled', async () => {144 const collectionId = await createCollectionExpectSuccess();145 await setCollectionLimitsExpectSuccess(alice, collectionId, { OwnerCanDestroy: false });146 await setCollectionLimitsExpectFailure(alice, collectionId, { OwnerCanDestroy: true });147 });148});1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56// https://unique-network.readthedocs.io/en/latest/jsapi.html#setchainlimits7import { ApiPromise, Keyring } from '@polkadot/api';8import { IKeyringPair } from '@polkadot/types/types';9import chai from 'chai';10import chaiAsPromised from 'chai-as-promised';11import usingApi, {submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';12import { ICollectionInterface } from './types';13import {14 createCollectionExpectSuccess, getCreatedCollectionCount,15 getCreateItemResult,16 getDetailedCollectionInfo,17 setCollectionLimitsExpectFailure,18 setCollectionLimitsExpectSuccess,19} from './util/helpers';2021chai.use(chaiAsPromised);22const expect = chai.expect;2324let alice: IKeyringPair;25let bob: IKeyringPair;26let collectionIdForTesting: number;2728const accountTokenOwnershipLimit = 0;29const sponsoredDataSize = 0;30const sponsoredMintSize = 0;31const sponsorTimeout = 1;32const tokenLimit = 1;3334describe('setCollectionLimits positive', () => {35 let tx;36 before(async () => {37 await usingApi(async () => {38 const keyring = new Keyring({ type: 'sr25519' });39 alice = keyring.addFromUri('//Alice');40 collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});41 });42 });43 it('execute setCollectionLimits with predefined params ', async () => {44 await usingApi(async (api: ApiPromise) => {45 tx = api.tx.nft.setCollectionLimits(46 collectionIdForTesting,47 {48 AccountTokenOwnershipLimit: accountTokenOwnershipLimit,49 SponsoredMintSize: sponsoredDataSize,50 TokenLimit: tokenLimit,51 SponsorTimeout: sponsorTimeout,52 OwnerCanTransfer: true,53 OwnerCanDestroy: true54 },55 );56 const events = await submitTransactionAsync(alice, tx);57 const result = getCreateItemResult(events);5859 // get collection limits defined previously60 const collectionInfo = await getDetailedCollectionInfo(api, collectionIdForTesting) as ICollectionInterface;6162 // tslint:disable-next-line:no-unused-expression63 expect(result.success).to.be.true;64 expect(collectionInfo.Limits.AccountTokenOwnershipLimit.toNumber()).to.be.equal(accountTokenOwnershipLimit);65 expect(collectionInfo.Limits.SponsoredMintSize.toNumber()).to.be.equal(sponsoredDataSize);66 expect(collectionInfo.Limits.TokenLimit.toNumber()).to.be.equal(tokenLimit);67 expect(collectionInfo.Limits.SponsorTimeout.toNumber()).to.be.equal(sponsorTimeout);68 expect(collectionInfo.Limits.OwnerCanTransfer.valueOf()).to.be.true;69 expect(collectionInfo.Limits.OwnerCanDestroy.valueOf()).to.be.true;70 });71 });72});7374describe('setCollectionLimits negative', () => {75 let tx;76 before(async () => {77 await usingApi(async () => {78 const keyring = new Keyring({ type: 'sr25519' });79 alice = keyring.addFromUri('//Alice');80 bob = keyring.addFromUri('//Bob');81 collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});82 });83 });84 it('execute setCollectionLimits for not exists collection', async () => {85 await usingApi(async (api: ApiPromise) => {86 const collectionCount = await getCreatedCollectionCount(api);87 const nonExistedCollectionId = collectionCount + 1;88 tx = api.tx.nft.setCollectionLimits(89 nonExistedCollectionId,90 {91 accountTokenOwnershipLimit,92 sponsoredDataSize,93 sponsoredMintSize,94 tokenLimit,95 },96 );97 await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;98 });99 });100 it('execute setCollectionLimits from user who is not owner of this collection', async () => {101 await usingApi(async (api: ApiPromise) => {102 tx = api.tx.nft.setCollectionLimits(103 collectionIdForTesting,104 {105 accountTokenOwnershipLimit,106 sponsoredDataSize,107 sponsoredMintSize,108 tokenLimit,109 },110 );111 await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;112 });113 });114 it('execute setCollectionLimits with incorrect limits', async () => {115 await usingApi(async (api: ApiPromise) => {116 tx = api.tx.nft.setCollectionLimits(117 collectionIdForTesting,118 {119 accountTokenOwnershipLimit: 'awdawd',120 sponsorTransferTimeout: 'awd',121 sponsoredDataSize: '12312312312312312',122 tokenLimit: '-100',123 },124 );125 await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;126 });127 });128129 it('fails when trying to enable OwnerCanTransfer after it was disabled', async () => {130 const collectionId = await createCollectionExpectSuccess();131 await setCollectionLimitsExpectSuccess(alice, collectionId, { 132 AccountTokenOwnershipLimit: accountTokenOwnershipLimit,133 SponsoredMintSize: sponsoredDataSize,134 TokenLimit: tokenLimit,135 SponsorTimeout: sponsorTimeout,136 OwnerCanTransfer: false,137 OwnerCanDestroy: true138 });139 await setCollectionLimitsExpectFailure(alice, collectionId, { 140 AccountTokenOwnershipLimit: accountTokenOwnershipLimit,141 SponsoredMintSize: sponsoredDataSize,142 TokenLimit: tokenLimit,143 SponsorTimeout: sponsorTimeout,144 OwnerCanTransfer: true,145 OwnerCanDestroy: true146 });147 });148149 it('fails when trying to enable OwnerCanDestroy after it was disabled', async () => {150 const collectionId = await createCollectionExpectSuccess();151 await setCollectionLimitsExpectSuccess(alice, collectionId, {152 AccountTokenOwnershipLimit: accountTokenOwnershipLimit,153 SponsoredMintSize: sponsoredDataSize,154 TokenLimit: tokenLimit,155 SponsorTimeout: sponsorTimeout,156 OwnerCanTransfer: true,157 OwnerCanDestroy: false158 });159 await setCollectionLimitsExpectFailure(alice, collectionId, { 160 AccountTokenOwnershipLimit: accountTokenOwnershipLimit,161 SponsoredMintSize: sponsoredDataSize,162 TokenLimit: tokenLimit,163 SponsorTimeout: sponsorTimeout,164 OwnerCanTransfer: true,165 OwnerCanDestroy: true166 });167 });168});tests/src/types.tsdiffbeforeafterboth--- a/tests/src/types.ts
+++ b/tests/src/types.ts
@@ -17,6 +17,8 @@
SponsoredMintSize: BN;
TokenLimit: BN;
SponsorTimeout: BN;
+ OwnerCanTransfer: boolean;
+ OwnerCanDestroy: boolean;
};
MintMode: boolean;
Mode: {