git.delta.rocks / unique-network / refs/commits / 836070f4956b

difftreelog

Limits logic fixed. Tests added

str-mv2021-09-08parent: #abfdac1.patch.diff
in: master

4 files changed

modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
302 /// Amount of collections destroyed, used for total amount tracking with302 /// Amount of collections destroyed, used for total amount tracking with
303 /// CreatedCollectionCount303 /// CreatedCollectionCount
304 DestroyedCollectionCount: u32;304 DestroyedCollectionCount: u32;
305 /// Total amount of account owned tokens (NFTs + RFTs + unique fungibles)
306 /// Account id (real)
307 pub AccountItemCount get(fn account_item_count): map hasher(twox_64_concat) T::AccountId => u32;
308 //#endregion305 //#endregion
309306
310 //#region Basic collections307 //#region Basic collections
1596 let account_items: u32 =1593 let account_items: u32 =
1597 <AddressTokens<T>>::get(collection_id, recipient.as_sub()).len() as u32;1594 <AddressTokens<T>>::get(collection_id, recipient.as_sub()).len() as u32;
1595
1596 // zero limit means collection limit is disabled
1597 // otherwise get lower value
1598 let limit = if collection.limits.account_token_ownership_limit == 0
1599 || collection.limits.account_token_ownership_limit > ACCOUNT_TOKEN_OWNERSHIP_LIMIT
1600 {
1601 ACCOUNT_TOKEN_OWNERSHIP_LIMIT
1602 } else {
1603 collection.limits.account_token_ownership_limit
1604 };
1605
1598 ensure!(1606 ensure!(limit > account_items, Error::<T>::AccountTokenLimitExceeded);
1599 collection.limits.account_token_ownership_limit > account_items,
1600 Error::<T>::AccountTokenLimitExceeded
1601 );
16021607
1623 .checked_add(amount)1628 .checked_add(amount)
1624 .ok_or(Error::<T>::AccountTokenLimitExceeded)?;1629 .ok_or(Error::<T>::AccountTokenLimitExceeded)?;
1630
1631 // zero limit means collection limit is disabled
1632 // otherwise get lower value
1633 let account_token_limit = if collection.limits.account_token_ownership_limit == 0
1634 || collection.limits.account_token_ownership_limit > ACCOUNT_TOKEN_OWNERSHIP_LIMIT
1635 {
1636 ACCOUNT_TOKEN_OWNERSHIP_LIMIT
1637 } else {
1638 collection.limits.account_token_ownership_limit
1639 };
1640
1625 ensure!(1641 ensure!(
1626 collection.limits.token_limit >= total_items,1642 collection.limits.token_limit >= total_items,
1627 Error::<T>::CollectionTokenLimitExceeded1643 Error::<T>::CollectionTokenLimitExceeded
1628 );1644 );
1629 ensure!(1645 ensure!(
1630 collection.limits.account_token_ownership_limit >= account_items,1646 account_token_limit >= account_items,
1631 Error::<T>::AccountTokenLimitExceeded1647 Error::<T>::AccountTokenLimitExceeded
1632 );1648 );
16331649
2362 item_index: TokenId,2378 item_index: TokenId,
2363 owner: &T::CrossAccountId,2379 owner: &T::CrossAccountId,
2364 ) -> DispatchResult {2380 ) -> DispatchResult {
2365 // add to account limit
2366 collection.consume_sload()?;
2367 if <AccountItemCount<T>>::contains_key(owner.as_sub()) {
2368 // bound Owned tokens by a single address
2369 collection.consume_sload()?;
2370 let count = <AccountItemCount<T>>::get(owner.as_sub());
2371 ensure!(
2372 count < ACCOUNT_TOKEN_OWNERSHIP_LIMIT,
2373 Error::<T>::AddressOwnershipLimitExceeded
2374 );
2375
2376 collection.consume_sstore()?;
2377 <AccountItemCount<T>>::insert(
2378 owner.as_sub(),
2379 count.checked_add(1).ok_or(Error::<T>::NumOverflow)?,
2380 );
2381 } else {
2382 collection.consume_sstore()?;
2383 <AccountItemCount<T>>::insert(owner.as_sub(), 1);
2384 }
2385
2386 collection.consume_sload()?;2381 collection.consume_sload()?;
2387 let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());2382 let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());
2388 if list_exists {2383 if list_exists {
2389 collection.consume_sload()?;2384 collection.consume_sload()?;
2390 let mut list = <AddressTokens<T>>::get(collection.id, owner.as_sub());2385 let mut list = <AddressTokens<T>>::get(collection.id, owner.as_sub());
2386
2387 // bound Owned tokens by a single address in collection
2388 let account_items: u32 = list.len() as u32;
2389 ensure!(
2390 account_items < ACCOUNT_TOKEN_OWNERSHIP_LIMIT,
2391 Error::<T>::AddressOwnershipLimitExceeded
2392 );
2393
2391 let item_contains = list.contains(&item_index.clone());2394 let item_contains = list.contains(&item_index.clone());
23922395
2410 item_index: TokenId,2413 item_index: TokenId,
2411 owner: &T::CrossAccountId,2414 owner: &T::CrossAccountId,
2412 ) -> DispatchResult {2415 ) -> DispatchResult {
2413 // update counter
2414 collection.consume_sload()?;
2415 collection.consume_sstore()?;
2416 <AccountItemCount<T>>::insert(
2417 owner.as_sub(),
2418 <AccountItemCount<T>>::get(owner.as_sub())
2419 .checked_sub(1)
2420 .ok_or(Error::<T>::NumOverflow)?,
2421 );
2422
2423 collection.consume_sload()?;2416 collection.consume_sload()?;
2424 let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());2417 let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());
modifiedpallets/nft/src/sponsorship.rsdiffbeforeafterboth
61 sponsor_transfer = match collection_mode {61 sponsor_transfer = match collection_mode {
62 CollectionMode::NFT => {62 CollectionMode::NFT => {
63 // get correct limit63 // get correct limit
64 let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {64 let limit: u32 = if collection_limits.sponsor_transfer_timeout != 0 {
65 if collection_limits.sponsor_transfer_timeout > NFT_SPONSOR_TRANSFER_TIMEOUT
66 {
65 collection_limits.sponsor_transfer_timeout67 collection_limits.sponsor_transfer_timeout
66 } else {68 } else {
67 NFT_SPONSOR_TRANSFER_TIMEOUT69 NFT_SPONSOR_TRANSFER_TIMEOUT
68 };70 }
71 } else {
72 0
73 };
6974
70 let mut sponsored = true;75 let mut sponsored = true;
71 if NftTransferBasket::<T>::contains_key(collection_id, item_id) {76 if NftTransferBasket::<T>::contains_key(collection_id, item_id) {
83 }88 }
84 CollectionMode::Fungible(_) => {89 CollectionMode::Fungible(_) => {
85 // get correct limit90 // get correct limit
86 let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {91 let limit: u32 = if collection_limits.sponsor_transfer_timeout != 0 {
92 if collection_limits.sponsor_transfer_timeout
93 > FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
94 {
87 collection_limits.sponsor_transfer_timeout95 collection_limits.sponsor_transfer_timeout
88 } else {96 } else {
89 FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT97 FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
90 };98 }
9199 } else {
92 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;100 0
101 };
102
93 let mut sponsored = true;103 let mut sponsored = true;
94 if FungibleTransferBasket::<T>::contains_key(collection_id, who) {104 if FungibleTransferBasket::<T>::contains_key(collection_id, who) {
106 }116 }
107 CollectionMode::ReFungible => {117 CollectionMode::ReFungible => {
108 // get correct limit118 // get correct limit
109 let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {119 let limit: u32 = if collection_limits.sponsor_transfer_timeout != 0 {
120 if collection_limits.sponsor_transfer_timeout
121 > REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
122 {
110 collection_limits.sponsor_transfer_timeout123 collection_limits.sponsor_transfer_timeout
111 } else {124 } else {
112 REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT125 REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT
113 };126 }
127 } else {
128 0
129 };
114130
115 let mut sponsored = true;131 let mut sponsored = true;
116 if ReFungibleTransferBasket::<T>::contains_key(collection_id, item_id) {132 if ReFungibleTransferBasket::<T>::contains_key(collection_id, item_id) {
addedtests/src/limits.test.tsdiffbeforeafterboth

no changes

modifiedtests/src/util/helpers.tsdiffbeforeafterboth
796 });796 });
797}797}
798
799export async function
800getFreeBalance(account: IKeyringPair) : Promise<BigNumber>
801{
802 let balance = new BigNumber(0) ;
803 await usingApi(async (api) => {
804 balance = new BigNumber((await api.query.system.account(account.address)).data.free.toString());
805 });
806
807 return balance;
808}
798809
799export async function810export async function
800scheduleTransferExpectSuccess(811scheduleTransferExpectSuccess(
870 if (type === 'ReFungible') {881 if (type === 'ReFungible') {
871 const nftItemData =882 const nftItemData =
872 (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON() as unknown as IReFungibleTokenDataType;883 (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON() as unknown as IReFungibleTokenDataType;
884 const expectedOwner = toSubstrateAddress(to);
885 const ownerIndex = nftItemData.Owner.findIndex(v => toSubstrateAddress(v.Owner as any as string) == expectedOwner);
886 expect(ownerIndex).to.not.equal(-1);
873 expect(nftItemData.Owner[0].Owner).to.be.deep.equal(to);887 expect(nftItemData.Owner[ownerIndex].Owner).to.be.deep.equal(normalizeAccountId(to));
874 expect(nftItemData.Owner[0].Fraction.toString()).to.be.equal(value.toString());888 expect(nftItemData.Owner[ownerIndex].Fraction).to.be.greaterThanOrEqual(value as number);
875 }889 }
876 });890 });
877}891}
1173 return normalizeAccountId((await api.query.nft.nftItemList(collectionId, tokenId) as any).toJSON().Owner);1187 return normalizeAccountId((await api.query.nft.nftItemList(collectionId, tokenId) as any).toJSON().Owner);
1174}1188}
1189
1190export async function waitNewBlocks(blocksCount = 1): Promise<void> {
1191 await usingApi(async (api) => {
1192 const promise = new Promise<void>(async (resolve) => {
1193
1194 const unsubscribe = await api.rpc.chain.subscribeNewHeads(() => {
1195 if (blocksCount > 0) {
1196 blocksCount--;
1197 } else {
1198 unsubscribe();
1199 resolve();
1200 }
1201 });
1202 });
1203 return promise;
1204 });
1205}
1206