git.delta.rocks / unique-network / refs/commits / 8bbc6aebf29e

difftreelog

Merge pull request #197 from UniqueNetwork/feature/CORE-167

kozyrevdev2021-10-04parents: #511eef6 #854f33e.patch.diff
in: master
Limits logic fixed. Tests added

5 files changed

modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
306 /// Amount of collections destroyed, used for total amount tracking with306 /// Amount of collections destroyed, used for total amount tracking with
307 /// CreatedCollectionCount307 /// CreatedCollectionCount
308 DestroyedCollectionCount: u32;308 DestroyedCollectionCount: u32;
309 /// Total amount of account owned tokens (NFTs + RFTs + unique fungibles)
310 /// Account id (real)
311 pub AccountItemCount get(fn account_item_count): map hasher(twox_64_concat) T::AccountId => u32;
312 //#endregion309 //#endregion
313310
314 //#region Basic collections311 //#region Basic collections
1125 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1122 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
11261123
1127 let collection = Self::get_collection(collection_id)?;1124 let collection = Self::get_collection(collection_id)?;
1125 Self::meta_update_check(&sender, &collection, item_id)?;
11281126
1129 Self::set_variable_meta_data_internal(&sender, &collection, item_id, data)?;1127 Self::set_variable_meta_data_internal(&sender, &collection, item_id, data)?;
11301128
1648 let account_items: u32 =1646 let account_items: u32 =
1649 <AddressTokens<T>>::get(collection_id, recipient.as_sub()).len() as u32;1647 <AddressTokens<T>>::get(collection_id, recipient.as_sub()).len() as u32;
1648
1649 // zero limit means collection limit is disabled
1650 // otherwise get lower value
1651 let limit = if collection.limits.account_token_ownership_limit == 0
1652 || collection.limits.account_token_ownership_limit > ACCOUNT_TOKEN_OWNERSHIP_LIMIT
1653 {
1654 ACCOUNT_TOKEN_OWNERSHIP_LIMIT
1655 } else {
1656 collection.limits.account_token_ownership_limit
1657 };
1658
1650 ensure!(1659 ensure!(limit > account_items, Error::<T>::AccountTokenLimitExceeded);
1651 collection.limits.account_token_ownership_limit > account_items,
1652 Error::<T>::AccountTokenLimitExceeded
1653 );
16541660
1675 .checked_add(amount)1681 .checked_add(amount)
1676 .ok_or(Error::<T>::AccountTokenLimitExceeded)?;1682 .ok_or(Error::<T>::AccountTokenLimitExceeded)?;
1683
1684 // zero limit means collection limit is disabled
1685 // otherwise get lower value
1686 let account_token_limit = if collection.limits.account_token_ownership_limit == 0
1687 || collection.limits.account_token_ownership_limit > ACCOUNT_TOKEN_OWNERSHIP_LIMIT
1688 {
1689 ACCOUNT_TOKEN_OWNERSHIP_LIMIT
1690 } else {
1691 collection.limits.account_token_ownership_limit
1692 };
1693
1677 ensure!(1694 ensure!(
1678 collection.limits.token_limit >= total_items,1695 collection.limits.token_limit >= total_items,
1679 Error::<T>::CollectionTokenLimitExceeded1696 Error::<T>::CollectionTokenLimitExceeded
1680 );1697 );
1681 ensure!(1698 ensure!(
1682 collection.limits.account_token_ownership_limit >= account_items,1699 account_token_limit >= account_items,
1683 Error::<T>::AccountTokenLimitExceeded1700 Error::<T>::AccountTokenLimitExceeded
1684 );1701 );
16851702
2409 item_index: TokenId,2426 item_index: TokenId,
2410 owner: &T::CrossAccountId,2427 owner: &T::CrossAccountId,
2411 ) -> DispatchResult {2428 ) -> DispatchResult {
2412 // add to account limit
2413 collection.consume_sload()?;
2414 if <AccountItemCount<T>>::contains_key(owner.as_sub()) {
2415 // bound Owned tokens by a single address
2416 collection.consume_sload()?;
2417 let count = <AccountItemCount<T>>::get(owner.as_sub());
2418 ensure!(
2419 count < ACCOUNT_TOKEN_OWNERSHIP_LIMIT,
2420 Error::<T>::AddressOwnershipLimitExceeded
2421 );
2422
2423 collection.consume_sstore()?;
2424 <AccountItemCount<T>>::insert(
2425 owner.as_sub(),
2426 count.checked_add(1).ok_or(Error::<T>::NumOverflow)?,
2427 );
2428 } else {
2429 collection.consume_sstore()?;
2430 <AccountItemCount<T>>::insert(owner.as_sub(), 1);
2431 }
2432
2433 collection.consume_sload()?;2429 collection.consume_sload()?;
2434 let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());2430 let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());
2435 if list_exists {2431 if list_exists {
2436 collection.consume_sload()?;2432 collection.consume_sload()?;
2437 let mut list = <AddressTokens<T>>::get(collection.id, owner.as_sub());2433 let mut list = <AddressTokens<T>>::get(collection.id, owner.as_sub());
2434
2435 // bound Owned tokens by a single address in collection
2436 let account_items: u32 = list.len() as u32;
2437 ensure!(
2438 account_items < ACCOUNT_TOKEN_OWNERSHIP_LIMIT,
2439 Error::<T>::AddressOwnershipLimitExceeded
2440 );
2441
2438 let item_contains = list.contains(&item_index.clone());2442 let item_contains = list.contains(&item_index.clone());
24392443
2457 item_index: TokenId,2461 item_index: TokenId,
2458 owner: &T::CrossAccountId,2462 owner: &T::CrossAccountId,
2459 ) -> DispatchResult {2463 ) -> DispatchResult {
2460 // update counter
2461 collection.consume_sload()?;
2462 collection.consume_sstore()?;
2463 <AccountItemCount<T>>::insert(
2464 owner.as_sub(),
2465 <AccountItemCount<T>>::get(owner.as_sub())
2466 .checked_sub(1)
2467 .ok_or(Error::<T>::NumOverflow)?,
2468 );
2469
2470 collection.consume_sload()?;2464 collection.consume_sload()?;
2471 let list_exists = <AddressTokens<T>>::contains_key(collection.id, owner.as_sub());2465 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) {
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
1789 let data = default_nft_data();1789 let data = default_nft_data();
1790 assert_noop!(1790 assert_noop!(
1791 TemplateModule::create_item(origin1, 1, account(1), data.into()),1791 TemplateModule::create_item(origin1, 1, account(1), data.into()),
1792 Error::<Test>::AddressOwnershipLimitExceeded1792 Error::<Test>::AccountTokenLimitExceeded
1793 );1793 );
1794 });1794 });
1795}1795}
2016 let data = default_nft_data();2016 let data = default_nft_data();
2017 create_test_item(1, &data.into());2017 create_test_item(1, &data.into());
20182018
2019 TemplateModule::set_meta_update_permission_flag(2019 assert_ok!(TemplateModule::set_meta_update_permission_flag(
2020 origin1.clone(),2020 origin1.clone(),
2021 collection_id,2021 collection_id,
2022 MetaUpdatePermission::ItemOwner,2022 MetaUpdatePermission::ItemOwner,
2023 );2023 ));
20242024
2025 let variable_data = b"ten chars.".to_vec();2025 let variable_data = b"ten chars.".to_vec();
2026 assert_ok!(TemplateModule::set_variable_meta_data(2026 assert_ok!(TemplateModule::set_variable_meta_data(
2040}2040}
20412041
2042#[test]2042#[test]
2043fn set_variable_meta_data_on_nft_with_item_owner_permission_flag_neg() {2043fn set_variable_meta_data_on_nft_with_item_owner_permission_flag_neg() {
2044 new_test_ext().execute_with(|| {2044 new_test_ext().execute_with(|| {
2045 // default_limits();2045 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);
20462046
2047 let collection_id = create_test_collection_for_owner(&CollectionMode::NFT, 2, 1);2047 let origin1 = Origin::signed(1);
20482048
2049 let origin1 = Origin::signed(1);2049 assert_ok!(TemplateModule::set_mint_permission(
2050 let origin2 = Origin::signed(2);2050 origin1.clone(),
20512051 collection_id,
2052 assert_ok!(TemplateModule::set_mint_permission(2052 true
2053 origin2.clone(),2053 ));
2054 collection_id,2054 assert_ok!(TemplateModule::add_to_white_list(
2055 true2055 origin1.clone(),
2056 ));2056 collection_id,
2057 assert_ok!(TemplateModule::add_to_white_list(2057 account(1)
2058 origin2.clone(),2058 ));
2059 collection_id,2059
2060 account(1)2060 let data = default_nft_data();
2061 ));2061 create_test_item(1, &data.into());
20622062
2063 let data = default_nft_data();2063 assert_ok!(TemplateModule::set_meta_update_permission_flag(
2064 create_test_item(1, &data.into());2064 origin1.clone(),
20652065 collection_id,
2066 assert_ok!(TemplateModule::set_meta_update_permission_flag(2066 MetaUpdatePermission::ItemOwner,
2067 origin2.clone(),2067 ));
2068 collection_id,2068
2069 MetaUpdatePermission::ItemOwner,2069 let variable_data = b"1234567890123".to_vec();
2070 ));2070 assert_noop!(
20712071 TemplateModule::set_variable_meta_data(
2072 let variable_data = b"ten chars.++".to_vec();2072 origin1,
2073 assert_noop!(2073 collection_id,
2074 TemplateModule::set_variable_meta_data(2074 1,
2075 origin2,2075 variable_data.clone()
2076 collection_id,2076 ),
2077 1,2077 Error::<Test>::TokenVariableDataLimitExceeded
2078 variable_data.clone()2078 );
2079 ),2079 })
2080 Error::<Test>::TokenVariableDataLimitExceeded2080}
2081 );
20822081
2083 #[test]2082#[test]
2084 fn collection_transfer_flag_works() {2083fn collection_transfer_flag_works() {
2141 MetaUpdatePermission::Admin,2140 MetaUpdatePermission::Admin,
2142 ));2141 ));
21432142
2144 let variable_data = b"test set_variable_meta_data method.".to_vec();2143 let variable_data = b"test.".to_vec();
2145 assert_ok!(TemplateModule::set_variable_meta_data(2144 assert_ok!(TemplateModule::set_variable_meta_data(
2146 origin1,2145 origin1,
2147 collection_id,2146 collection_id,
2188 MetaUpdatePermission::Admin,2187 MetaUpdatePermission::Admin,
2189 ));2188 ));
21902189
2191 let variable_data = b"test set_variable_meta_data method.".to_vec();2190 let variable_data = b"test.".to_vec();
2192 assert_noop!(2191 assert_noop!(
2193 TemplateModule::set_variable_meta_data(2192 TemplateModule::set_variable_meta_data(
2194 origin1,2193 origin1,
2243 MetaUpdatePermission::None,2242 MetaUpdatePermission::None,
2244 ));2243 ));
22452244
2246 let variable_data = b"test set_variable_meta_data method.".to_vec();2245 let variable_data = b"test.".to_vec();
2247 assert_noop!(2246 assert_noop!(
2248 TemplateModule::set_variable_meta_data(2247 TemplateModule::set_variable_meta_data(
2249 origin1.clone(),2248 origin1.clone(),
2285 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);2284 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
2286 });2285 });
2287 }2286}
2288 });
2289}
22902287
addedtests/src/limits.test.tsdiffbeforeafterboth

no changes

modifiedtests/src/util/helpers.tsdiffbeforeafterboth
810 });810 });
811}811}
812
813export async function
814getFreeBalance(account: IKeyringPair) : Promise<BigNumber>
815{
816 let balance = new BigNumber(0) ;
817 await usingApi(async (api) => {
818 balance = new BigNumber((await api.query.system.account(account.address)).data.free.toString());
819 });
820
821 return balance;
822}
812823
813export async function824export async function
814scheduleTransferExpectSuccess(825scheduleTransferExpectSuccess(
884 if (type === 'ReFungible') {895 if (type === 'ReFungible') {
885 const nftItemData =896 const nftItemData =
886 (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON() as unknown as IReFungibleTokenDataType;897 (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON() as unknown as IReFungibleTokenDataType;
898 const expectedOwner = toSubstrateAddress(to);
899 const ownerIndex = nftItemData.Owner.findIndex(v => toSubstrateAddress(v.Owner as any as string) == expectedOwner);
900 expect(ownerIndex).to.not.equal(-1);
887 expect(nftItemData.Owner[0].Owner).to.be.deep.equal(to);901 expect(nftItemData.Owner[ownerIndex].Owner).to.be.deep.equal(normalizeAccountId(to));
888 expect(nftItemData.Owner[0].Fraction.toString()).to.be.equal(value.toString());902 expect(nftItemData.Owner[ownerIndex].Fraction).to.be.greaterThanOrEqual(value as number);
889 }903 }
890 });904 });
891}905}