git.delta.rocks / unique-network / refs/commits / 2c6fa32b7608

difftreelog

fix remove native ft from childrens

Trubnikov Sergey2023-05-23parent: #95338e2.patch.diff
in: master

4 files changed

modifiedpallets/balances-adapter/src/common.rsdiffbeforeafterboth
--- a/pallets/balances-adapter/src/common.rs
+++ b/pallets/balances-adapter/src/common.rs
@@ -85,7 +85,7 @@
 	}
 }
 
-/// Implementation of `CommonCollectionOperations` for `FungibleHandle`. It wraps FungibleHandle Pallete
+/// Implementation of `CommonCollectionOperations` for `FungibleHandle`. It wraps FungibleHandle Pallet
 /// methods and adds weight info.
 impl<T: Config> CommonCollectionOperations<T> for NativeFungibleHandle<T> {
 	fn create_item(
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -1347,37 +1347,18 @@
 	}
 
 	fn token_has_children(collection_id: CollectionId, token_id: TokenId) -> bool {
-		let address = T::CrossTokenAddressMapping::token_to_address(collection_id, token_id);
-		let balance = <pallet_balances::Pallet<T>>::free_balance(address.as_sub());
-
-		balance > T::Balance::default()
-			|| <TokenChildren<T>>::iter_prefix((collection_id, token_id))
-				.next()
-				.is_some()
+		<TokenChildren<T>>::iter_prefix((collection_id, token_id))
+			.next()
+			.is_some()
 	}
 
 	pub fn token_children_ids(collection_id: CollectionId, token_id: TokenId) -> Vec<TokenChild> {
-		let mut tokens: Vec<_> = vec![];
-
-		let address = T::CrossTokenAddressMapping::token_to_address(collection_id, token_id);
-		let balance = <pallet_balances::Pallet<T>>::free_balance(address.as_sub());
-		if balance > T::Balance::default() {
-			tokens.push(TokenChild {
-				token: TokenId(0),
-				collection: pallet_common::NATIVE_FUNGIBLE_COLLECTION_ID,
+		<TokenChildren<T>>::iter_prefix((collection_id, token_id))
+			.map(|((child_collection_id, child_id), _)| TokenChild {
+				collection: child_collection_id,
+				token: child_id,
 			})
-		}
-
-		tokens.extend(
-			<TokenChildren<T>>::iter_prefix((collection_id, token_id)).map(
-				|((child_collection_id, child_id), _)| TokenChild {
-					collection: child_collection_id,
-					token: child_id,
-				},
-			),
-		);
-
-		tokens
+			.collect()
 	}
 
 	/// Mint single NFT token.
modifiedtests/src/sub/nesting/common.test.tsdiffbeforeafterboth
before · tests/src/sub/nesting/common.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {IKeyringPair} from '@polkadot/types/types';18import {expect, itSub, Pallets, usingPlaygrounds} from '../../util';19import {UniqueNFTCollection, UniqueRFTCollection} from '../../util/playgrounds/unique';2021let alice: IKeyringPair;22let bob: IKeyringPair;2324describe('Common nesting tests', () => {25  before(async () => {26    await usingPlaygrounds(async (helper, privateKey) => {27      const donor = await privateKey({url: import.meta.url});28      [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);29    });30  });3132  [33    {mode: 'nft' as const, restrictedMode: true, requiredPallets: []},34    {mode: 'nft' as const, restrictedMode: false, requiredPallets: []},35    {mode: 'rft' as const, restrictedMode: true, requiredPallets: [Pallets.ReFungible]},36    {mode: 'rft' as const, restrictedMode: false, requiredPallets: [Pallets.ReFungible]},37  ].map(testCase => {38    itSub.ifWithPallets(`Token owner can nest ${testCase.mode.toUpperCase()} in NFT if "tokenOwner" permission set ${testCase.restrictedMode ? 'in restricted mode': ''}`, testCase.requiredPallets, async ({helper}) => {39      // Only NFT can be target for nesting in40      const targetNFTCollection = await helper.nft.mintCollection(alice);41      const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});4243      const collectionForNesting = await helper[testCase.mode].mintCollection(bob);44      // permissions should be set:45      await targetNFTCollection.setPermissions(alice, {46        nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},47      });4849      // 1. Bob can immediately create nested token:50      const nestedToken1 = testCase.mode === 'nft'51        ? await (collectionForNesting as UniqueNFTCollection).mintToken(bob, targetTokenBob.nestingAccount())52        : await (collectionForNesting as UniqueRFTCollection).mintToken(bob, 10n, targetTokenBob.nestingAccount());53      expect(await nestedToken1.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});54      expect(await nestedToken1.getOwner()).to.be.deep.equal(targetTokenBob.nestingAccount().toLowerCase());5556      // 2. Bob can mint and nest token:57      const nestedToken2 = await collectionForNesting.mintToken(bob);58      await nestedToken2.nest(bob, targetTokenBob);59      expect(await nestedToken2.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});60      expect(await nestedToken2.getOwner()).to.be.deep.equal(targetTokenBob.nestingAccount().toLowerCase());61    });62  });636465  [66    {restrictedMode: true},67    {restrictedMode: false},68  ].map(testCase => {69    itSub(`Token owner can nest FT in NFT if "tokenOwner" permission set  ${testCase.restrictedMode ? 'in restricted mode': ''}`, async ({helper}) => {70      // Only NFT allows nesting, permissions should be set:71      const targetNFTCollection = await helper.nft.mintCollection(alice);72      const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});7374      const collectionForNesting = await helper.ft.mintCollection(bob);75      // permissions should be set:76      await targetNFTCollection.setPermissions(alice, {77        nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},78      });7980      // 1. Alice can immediately create nested tokens:81      await collectionForNesting.mint(bob, 100n, targetTokenBob.nestingAccount());82      expect(await collectionForNesting.getTop10Owners()).deep.eq([targetTokenBob.nestingAccount().toLowerCase()]);83      expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(100n);8485      // 2. Alice can mint and nest token:86      await collectionForNesting.mint(bob, 100n);87      await collectionForNesting.transfer(bob, targetTokenBob.nestingAccount(), 50n);88      expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(150n);89      expect(await targetTokenBob.getChildren()).to.be.deep.equal([{collectionId: collectionForNesting.collectionId, tokenId: 0}]);90    });91  });9293  [94    {restrictedMode: true},95    {restrictedMode: false},96  ].map(testCase => {97    itSub(`Token owner can nest Native FT in NFT if "tokenOwner" permission set  ${testCase.restrictedMode ? 'in restricted mode': ''}`, async ({helper}) => {98      // Only NFT allows nesting, permissions should be set:99      const targetNFTCollection = await helper.nft.mintCollection(alice);100      const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});101      expect(await targetTokenBob.getChildren()).to.be.empty;102103      const collectionForNesting = helper.ft.getCollectionObject(0);104      // permissions should be set:105      await targetNFTCollection.setPermissions(alice, {106        nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},107      });108109      // Bob can nest Native FT into their NFT:110      await collectionForNesting.transfer(bob, targetTokenBob.nestingAccount(), 50n);111      expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(50n);112      expect(await targetTokenBob.getChildren()).to.be.deep.equal([{collectionId: 0, tokenId: 0}]);113    });114  });115116117  itSub.ifWithPallets('Owner can unnest tokens using transferFrom', [Pallets.ReFungible], async ({helper}) => {118    const collectionToNest = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});119    const tokenA = await collectionToNest.mintToken(alice);120    const tokenB = await collectionToNest.mintToken(alice);121122    // Create a nested token123    const nftCollectionToBeNested = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});124    const rftCollectionToBeNested = await helper.rft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});125    const ftCollectionToBeNested = await helper.ft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});126    const nativeFtCollectionToBeNested = helper.ft.getCollectionObject(0);127128    const nestedNFT = await nftCollectionToBeNested.mintToken(alice, tokenA.nestingAccount());129    const nestedRFT = await rftCollectionToBeNested.mintToken(alice, 100n, tokenA.nestingAccount());130    const _nestedFT = await ftCollectionToBeNested.mint(alice, 100n, tokenA.nestingAccount());131    await nativeFtCollectionToBeNested.transfer(alice, tokenA.nestingAccount(), 100n);132    expect(await nestedNFT.getOwner()).to.be.deep.equal(tokenA.nestingAccount().toLowerCase());133    expect(await nestedRFT.getOwner()).to.be.deep.equal(tokenA.nestingAccount().toLowerCase());134    expect(await ftCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(100n);135    expect(await nativeFtCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(100n);136137    expect(await tokenA.getChildren()).to.be.length(4);138    expect(await tokenB.getChildren()).to.be.length(0);139140    // Transfer the nested token to another token141    await nestedNFT.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount());142    await nestedRFT.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);143    await ftCollectionToBeNested.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);144    await nativeFtCollectionToBeNested.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);145146    expect(await nestedNFT.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});147    expect(await nestedNFT.getOwner()).to.be.deep.equal(tokenB.nestingAccount().toLowerCase());148149    expect(await nestedRFT.getBalance(tokenB.nestingAccount())).to.equal(25n);150    expect(await nestedRFT.getBalance(tokenA.nestingAccount())).to.equal(75n);151152    expect(await ftCollectionToBeNested.getBalance(tokenB.nestingAccount())).to.equal(25n);153    expect(await ftCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(75n);154155    expect(await nativeFtCollectionToBeNested.getBalance(tokenB.nestingAccount())).to.equal(25n);156    expect(await nativeFtCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(75n);157158    // RFT, FT, and native FT159    expect(await tokenA.getChildren()).to.be.length(3);160    // NFT, RFT, FT, and native FT161    expect(await tokenB.getChildren()).to.be.length(4);162  });163});
after · tests/src/sub/nesting/common.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {IKeyringPair} from '@polkadot/types/types';18import {expect, itSub, Pallets, usingPlaygrounds} from '../../util';19import {UniqueNFTCollection, UniqueRFTCollection} from '../../util/playgrounds/unique';2021let alice: IKeyringPair;22let bob: IKeyringPair;2324describe('Common nesting tests', () => {25  before(async () => {26    await usingPlaygrounds(async (helper, privateKey) => {27      const donor = await privateKey({url: import.meta.url});28      [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);29    });30  });3132  [33    {mode: 'nft' as const, restrictedMode: true, requiredPallets: []},34    {mode: 'nft' as const, restrictedMode: false, requiredPallets: []},35    {mode: 'rft' as const, restrictedMode: true, requiredPallets: [Pallets.ReFungible]},36    {mode: 'rft' as const, restrictedMode: false, requiredPallets: [Pallets.ReFungible]},37  ].map(testCase => {38    itSub.ifWithPallets(`Token owner can nest ${testCase.mode.toUpperCase()} in NFT if "tokenOwner" permission set ${testCase.restrictedMode ? 'in restricted mode': ''}`, testCase.requiredPallets, async ({helper}) => {39      // Only NFT can be target for nesting in40      const targetNFTCollection = await helper.nft.mintCollection(alice);41      const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});4243      const collectionForNesting = await helper[testCase.mode].mintCollection(bob);44      // permissions should be set:45      await targetNFTCollection.setPermissions(alice, {46        nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},47      });4849      // 1. Bob can immediately create nested token:50      const nestedToken1 = testCase.mode === 'nft'51        ? await (collectionForNesting as UniqueNFTCollection).mintToken(bob, targetTokenBob.nestingAccount())52        : await (collectionForNesting as UniqueRFTCollection).mintToken(bob, 10n, targetTokenBob.nestingAccount());53      expect(await nestedToken1.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});54      expect(await nestedToken1.getOwner()).to.be.deep.equal(targetTokenBob.nestingAccount().toLowerCase());5556      // 2. Bob can mint and nest token:57      const nestedToken2 = await collectionForNesting.mintToken(bob);58      await nestedToken2.nest(bob, targetTokenBob);59      expect(await nestedToken2.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});60      expect(await nestedToken2.getOwner()).to.be.deep.equal(targetTokenBob.nestingAccount().toLowerCase());61    });62  });636465  [66    {restrictedMode: true},67    {restrictedMode: false},68  ].map(testCase => {69    itSub(`Token owner can nest FT in NFT if "tokenOwner" permission set  ${testCase.restrictedMode ? 'in restricted mode': ''}`, async ({helper}) => {70      // Only NFT allows nesting, permissions should be set:71      const targetNFTCollection = await helper.nft.mintCollection(alice);72      const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});7374      const collectionForNesting = await helper.ft.mintCollection(bob);75      // permissions should be set:76      await targetNFTCollection.setPermissions(alice, {77        nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},78      });7980      // 1. Alice can immediately create nested tokens:81      await collectionForNesting.mint(bob, 100n, targetTokenBob.nestingAccount());82      expect(await collectionForNesting.getTop10Owners()).deep.eq([targetTokenBob.nestingAccount().toLowerCase()]);83      expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(100n);8485      // 2. Alice can mint and nest token:86      await collectionForNesting.mint(bob, 100n);87      await collectionForNesting.transfer(bob, targetTokenBob.nestingAccount(), 50n);88      expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(150n);89      expect(await targetTokenBob.getChildren()).to.be.deep.equal([{collectionId: collectionForNesting.collectionId, tokenId: 0}]);90    });91  });9293  [94    {restrictedMode: true},95    {restrictedMode: false},96  ].map(testCase => {97    itSub(`Token owner can nest Native FT in NFT if "tokenOwner" permission set  ${testCase.restrictedMode ? 'in restricted mode': ''}`, async ({helper}) => {98      // Only NFT allows nesting, permissions should be set:99      const targetNFTCollection = await helper.nft.mintCollection(alice);100      const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});101      expect(await targetTokenBob.getChildren()).to.be.empty;102103      const collectionForNesting = helper.ft.getCollectionObject(0);104      // permissions should be set:105      await targetNFTCollection.setPermissions(alice, {106        nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},107      });108109      // Bob can nest Native FT into their NFT:110      await collectionForNesting.transfer(bob, targetTokenBob.nestingAccount(), 50n);111      expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(50n);112      // Native FT should't be visible in NFT children:113      expect(await targetTokenBob.getChildren()).to.be.deep.equal([]);114    });115  });116117118  itSub.ifWithPallets('Owner can unnest tokens using transferFrom', [Pallets.ReFungible], async ({helper}) => {119    const collectionToNest = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});120    const tokenA = await collectionToNest.mintToken(alice);121    const tokenB = await collectionToNest.mintToken(alice);122123    // Create a nested token124    const nftCollectionToBeNested = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});125    const rftCollectionToBeNested = await helper.rft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});126    const ftCollectionToBeNested = await helper.ft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});127    const nativeFtCollectionToBeNested = helper.ft.getCollectionObject(0);128129    const nestedNFT = await nftCollectionToBeNested.mintToken(alice, tokenA.nestingAccount());130    const nestedRFT = await rftCollectionToBeNested.mintToken(alice, 100n, tokenA.nestingAccount());131    const _nestedFT = await ftCollectionToBeNested.mint(alice, 100n, tokenA.nestingAccount());132    await nativeFtCollectionToBeNested.transfer(alice, tokenA.nestingAccount(), 100n);133    expect(await nestedNFT.getOwner()).to.be.deep.equal(tokenA.nestingAccount().toLowerCase());134    expect(await nestedRFT.getOwner()).to.be.deep.equal(tokenA.nestingAccount().toLowerCase());135    expect(await ftCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(100n);136    expect(await nativeFtCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(100n);137138    expect(await tokenA.getChildren()).to.be.length(3);139    expect(await tokenB.getChildren()).to.be.length(0);140141    // Transfer the nested token to another token142    await nestedNFT.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount());143    await nestedRFT.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);144    await ftCollectionToBeNested.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);145    await nativeFtCollectionToBeNested.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount(), 25n);146147    expect(await nestedNFT.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});148    expect(await nestedNFT.getOwner()).to.be.deep.equal(tokenB.nestingAccount().toLowerCase());149150    expect(await nestedRFT.getBalance(tokenB.nestingAccount())).to.equal(25n);151    expect(await nestedRFT.getBalance(tokenA.nestingAccount())).to.equal(75n);152153    expect(await ftCollectionToBeNested.getBalance(tokenB.nestingAccount())).to.equal(25n);154    expect(await ftCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(75n);155156    expect(await nativeFtCollectionToBeNested.getBalance(tokenB.nestingAccount())).to.equal(25n);157    expect(await nativeFtCollectionToBeNested.getBalance(tokenA.nestingAccount())).to.equal(75n);158159    // RFT, FT, and without native FT160    expect(await tokenA.getChildren()).to.be.length(2);161    // NFT, RFT, FT, and without native FT162    expect(await tokenB.getChildren()).to.be.length(3);163  });164});
modifiedtests/src/sub/nesting/e2e.test.tsdiffbeforeafterboth
--- a/tests/src/sub/nesting/e2e.test.ts
+++ b/tests/src/sub/nesting/e2e.test.ts
@@ -80,25 +80,22 @@
       {tokenId: tokenA.tokenId, collectionId: collectionA.collectionId},
       {tokenId: 0, collectionId: collectionB.collectionId},
       {tokenId: tokenC.tokenId, collectionId: collectionC.collectionId},
-      {tokenId: 0, collectionId: collectionNative.collectionId},
-    ]).and.has.length(4);
+    ]).and.has.length(3);
 
     // Burn all nested pieces
     await tokenC.burnFrom(alice, targetToken.nestingAccount(), 2n);
     expect(await targetToken.getChildren()).to.have.deep.members([
       {tokenId: tokenA.tokenId, collectionId: collectionA.collectionId},
       {tokenId: 0, collectionId: collectionB.collectionId},
-      {tokenId: 0, collectionId: collectionNative.collectionId},
     ])
-      .and.has.length(3);
+      .and.has.length(2);
 
     // Move part of the fungible token inside token A deeper in the nesting tree
     await collectionB.transferFrom(alice, targetToken.nestingAccount(), tokenA.nestingAccount(), 1n);
     expect(await targetToken.getChildren()).to.be.have.deep.members([
       {tokenId: tokenA.tokenId, collectionId: collectionA.collectionId},
       {tokenId: 0, collectionId: collectionB.collectionId},
-      {tokenId: 0, collectionId: collectionNative.collectionId},
-    ]).and.has.length(3);
+    ]).and.has.length(2);
     // Nested token also has children now:
     expect(await tokenA.getChildren()).to.have.deep.members([
       {tokenId: 0, collectionId: collectionB.collectionId},
@@ -108,8 +105,7 @@
     await collectionB.transferFrom(alice, targetToken.nestingAccount(), tokenA.nestingAccount(), 1n);
     expect(await targetToken.getChildren()).to.have.deep.members([
       {tokenId: tokenA.tokenId, collectionId: collectionA.collectionId},
-      {tokenId: 0, collectionId: collectionNative.collectionId},
-    ]).and.has.length(2);
+    ]).and.has.length(1);
     expect(await tokenA.getChildren()).to.have.deep.members([
       {tokenId: 0, collectionId: collectionB.collectionId},
     ]).and.has.length(1);