difftreelog
Nesting tests refactoring WIP
in: master
5 files changed
tests/src/nesting/nest.test.tsdiffbeforeafterboth--- a/tests/src/nesting/nest.test.ts
+++ b/tests/src/nesting/nest.test.ts
@@ -72,153 +72,6 @@
});
});
- itSub('Admin (NFT): allows an Admin to nest a token', async ({helper}) => {
- const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {collectionAdmin: true}}});
- await collection.addAdmin(alice, {Substrate: bob.address});
- const targetToken = await collection.mintToken(alice, {Substrate: charlie.address});
-
- // Create an immediately nested token
- const nestedToken = await collection.mintToken(bob, targetToken.nestingAccount());
- expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
- expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
-
- // Create a token to be nested and nest
- const newToken = await collection.mintToken(bob);
- await newToken.nest(bob, targetToken);
- expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
- expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
- });
-
- itSub('Admin (NFT): Admin and Token Owner can operate together', async ({helper}) => {
- const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {collectionAdmin: true, tokenOwner: true}}});
- await collection.addAdmin(alice, {Substrate: bob.address});
- const targetToken = await collection.mintToken(alice, {Substrate: charlie.address});
-
- // Create an immediately nested token by an administrator
- const nestedToken = await collection.mintToken(bob, targetToken.nestingAccount());
- expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
- expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
-
- // Create a token to be nested and nest
- const newToken = await collection.mintToken(alice, {Substrate: charlie.address});
- await newToken.nest(charlie, targetToken);
- expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
- expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
- });
-
- itSub('Admin (NFT): allows an Admin to nest a token (Restricted nesting)', async ({helper}) => {
- const collectionA = await helper.nft.mintCollection(alice);
- await collectionA.addAdmin(alice, {Substrate: bob.address});
- const collectionB = await helper.nft.mintCollection(alice);
- await collectionB.addAdmin(alice, {Substrate: bob.address});
- await collectionA.setPermissions(alice, {nesting: {collectionAdmin: true, restricted:[collectionB.collectionId]}});
- const targetToken = await collectionA.mintToken(alice, {Substrate: charlie.address});
-
- // Create an immediately nested token
- const nestedToken = await collectionB.mintToken(bob, targetToken.nestingAccount());
- expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
- expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
-
- // Create a token to be nested and nest
- const newToken = await collectionB.mintToken(bob);
- await newToken.nest(bob, targetToken);
- expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
- expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
- });
-
- // ---------- Non-Fungible ----------
-
- itSub('NFT: allows an Owner to nest/unnest their token', async ({helper}) => {
- const collection = await helper.nft.mintCollection(alice, {permissions: {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true}}});
- await collection.addToAllowList(alice, {Substrate: charlie.address});
- const targetToken = await collection.mintToken(charlie);
- await collection.addToAllowList(alice, targetToken.nestingAccount());
-
- // Create an immediately nested token
- const nestedToken = await collection.mintToken(charlie, targetToken.nestingAccount());
- expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
- expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
-
- // Create a token to be nested and nest
- const newToken = await collection.mintToken(charlie);
- await newToken.nest(charlie, targetToken);
- expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
- expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
- });
-
- itSub('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {
- const collectionA = await helper.nft.mintCollection(alice);
- const collectionB = await helper.nft.mintCollection(alice);
- //await collectionB.addAdmin(alice, {Substrate: bob.address});
- const targetToken = await collectionA.mintToken(alice, {Substrate: charlie.address});
-
- await collectionA.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true, restricted:[collectionB.collectionId]}});
- await collectionA.addToAllowList(alice, {Substrate: charlie.address});
- await collectionA.addToAllowList(alice, targetToken.nestingAccount());
-
- await collectionB.setPermissions(alice, {access: 'AllowList', mintMode: true});
- await collectionB.addToAllowList(alice, {Substrate: charlie.address});
- await collectionB.addToAllowList(alice, targetToken.nestingAccount());
-
- // Create an immediately nested token
- const nestedToken = await collectionB.mintToken(charlie, targetToken.nestingAccount());
- expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
- expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
-
- // Create a token to be nested and nest
- const newToken = await collectionB.mintToken(charlie);
- await newToken.nest(charlie, targetToken);
- expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
- expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
- });
-
- // ---------- Fungible ----------
-
- itSub('Fungible: allows an Owner to nest/unnest their token', async ({helper}) => {
- const collectionNFT = await helper.nft.mintCollection(alice, {permissions: {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true}}});
- const collectionFT = await helper.ft.mintCollection(alice);
- const targetToken = await collectionNFT.mintToken(alice, {Substrate: charlie.address});
-
- await collectionNFT.addToAllowList(alice, {Substrate: charlie.address});
- await collectionNFT.addToAllowList(alice, targetToken.nestingAccount());
-
- await collectionFT.setPermissions(alice, {access: 'AllowList', mintMode: true});
- await collectionFT.addToAllowList(alice, {Substrate: charlie.address});
- await collectionFT.addToAllowList(alice, targetToken.nestingAccount());
-
- // Create an immediately nested token
- await collectionFT.mint(charlie, 5n, targetToken.nestingAccount());
- expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(5n);
-
- // Create a token to be nested and nest
- await collectionFT.mint(charlie, 5n);
- await collectionFT.transfer(charlie, targetToken.nestingAccount(), 2n);
- expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(7n);
- });
-
- itSub('Fungible: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {
- const collectionNFT = await helper.nft.mintCollection(alice);
- const collectionFT = await helper.ft.mintCollection(alice);
- const targetToken = await collectionNFT.mintToken(alice, {Substrate: charlie.address});
-
- await collectionNFT.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true, restricted:[collectionFT.collectionId]}});
- await collectionNFT.addToAllowList(alice, {Substrate: charlie.address});
- await collectionNFT.addToAllowList(alice, targetToken.nestingAccount());
-
- await collectionFT.setPermissions(alice, {access: 'AllowList', mintMode: true});
- await collectionFT.addToAllowList(alice, {Substrate: charlie.address});
- await collectionFT.addToAllowList(alice, targetToken.nestingAccount());
-
- // Create an immediately nested token
- await collectionFT.mint(charlie, 5n, targetToken.nestingAccount());
- expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(5n);
-
- // Create a token to be nested and nest
- await collectionFT.mint(charlie, 5n);
- await collectionFT.transfer(charlie, targetToken.nestingAccount(), 2n);
- expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(7n);
- });
-
itSub.ifWithPallets('ReFungible: getTopmostOwner works correctly with Nesting', [Pallets.ReFungible], async({helper}) => {
const collectionNFT = await helper.nft.mintCollection(alice, {
permissions: {
@@ -261,28 +114,8 @@
const donor = await privateKey({filename: __filename});
[alice, bob] = await helper.arrange.createAccounts([100n, 50n], donor);
});
- });
-
- itSub('Disallows excessive token nesting', async ({helper}) => {
- const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
- let token = await collection.mintToken(alice);
-
- const maxNestingLevel = 5;
-
- // Create a nested-token matryoshka
- for (let i = 0; i < maxNestingLevel; i++) {
- token = await collection.mintToken(alice, token.nestingAccount());
- }
-
- // The nesting depth is limited by `maxNestingLevel`
- await expect(collection.mintToken(alice, token.nestingAccount()))
- .to.be.rejectedWith(/structure\.DepthLimit/);
- expect(await token.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});
- expect(await token.getChildren()).to.be.length(0);
});
- // ---------- Admin ------------
-
itSub('Admin (NFT): disallows an Admin to operate nesting when only TokenOwner is allowed', async ({helper}) => {
const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
await collection.addAdmin(alice, {Substrate: bob.address});
@@ -302,21 +135,21 @@
});
itSub('Admin (NFT): disallows a Token Owner to operate nesting when only Admin is allowed', async ({helper}) => {
- const collection = await helper.nft.mintCollection(alice, {permissions: {access: 'AllowList', mintMode: true, nesting: {collectionAdmin: true}}});
- const targetToken = await collection.mintToken(alice, {Substrate: bob.address});
- await collection.addToAllowList(alice, {Substrate: bob.address});
- await collection.addToAllowList(alice, targetToken.nestingAccount());
+ const collectionAlice = await helper.nft.mintCollection(alice, {permissions: {access: 'AllowList', mintMode: true, nesting: {collectionAdmin: true}}});
+ const targetTokenBob = await collectionAlice.mintToken(alice, {Substrate: bob.address});
+ await collectionAlice.addToAllowList(alice, {Substrate: bob.address});
+ await collectionAlice.addToAllowList(alice, targetTokenBob.nestingAccount());
// Try to create a nested token as token owner when it's disallowed
- await expect(collection.mintToken(bob, targetToken.nestingAccount()))
+ await expect(collectionAlice.mintToken(bob, targetTokenBob.nestingAccount()))
.to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
// Try to create a token to be nested and nest
- const newToken = await collection.mintToken(bob);
- await expect(newToken.nest(bob, targetToken))
+ const newToken = await collectionAlice.mintToken(bob);
+ await expect(newToken.nest(bob, targetTokenBob))
.to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
- expect(await targetToken.getChildren()).to.be.length(0);
+ expect(await targetTokenBob.getChildren()).to.be.length(0);
expect(await newToken.getOwner()).to.be.deep.equal({Substrate: bob.address});
});
@@ -341,113 +174,7 @@
expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});
expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
});
-
- itSub('Admin (NFT): disallows an Admin to nest a token from an unlisted collection (Restricted nesting)', async ({helper}) => {
- const collectionA = await helper.nft.mintCollection(alice);
- const collectionB = await helper.nft.mintCollection(alice);
- await collectionA.setPermissions(alice, {nesting: {collectionAdmin: true, restricted: [collectionA.collectionId]}});
- const targetToken = await collectionA.mintToken(alice);
-
- // Try to create a nested token from another collection
- await expect(collectionB.mintToken(alice, targetToken.nestingAccount()))
- .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
-
- // Create a token in another collection yet to be nested and try to nest
- const newToken = await collectionB.mintToken(alice);
- await expect(newToken.nest(alice, targetToken))
- .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
-
- expect(await targetToken.getChildren()).to.be.length(0);
- expect(await newToken.getOwner()).to.be.deep.equal({Substrate: alice.address});
- });
-
- // ---------- Non-Fungible ----------
-
- itSub('NFT: disallows to nest token if nesting is disabled', async ({helper}) => {
- // Collection is implicitly not allowed nesting at creation
- const collection = await helper.nft.mintCollection(alice);
- const targetToken = await collection.mintToken(alice);
-
- // Try to create a nested token as token owner when it's disallowed
- await expect(collection.mintToken(alice, targetToken.nestingAccount()))
- .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
-
- // Try to create a token to be nested and nest
- const newToken = await collection.mintToken(alice);
- await expect(newToken.nest(alice, targetToken))
- .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
-
- expect(await targetToken.getChildren()).to.be.length(0);
- expect(await newToken.getOwner()).to.be.deep.equal({Substrate: alice.address});
- });
-
- itSub('NFT: disallows a non-Owner to nest someone else\'s token', async ({helper}) => {
- const collection = await helper.nft.mintCollection(alice);
- const targetToken = await collection.mintToken(alice);
-
- await collection.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true}});
- await collection.addToAllowList(alice, {Substrate: bob.address});
- await collection.addToAllowList(alice, targetToken.nestingAccount());
- // Try to create a token to be nested and nest
- const newToken = await collection.mintToken(alice);
- await expect(newToken.nest(bob, targetToken)).to.be.rejectedWith(/common\.NoPermission/);
-
- expect(await targetToken.getChildren()).to.be.length(0);
- expect(await newToken.getOwner()).to.be.deep.equal({Substrate: alice.address});
- });
-
- itSub('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async ({helper}) => {
- const collection = await helper.nft.mintCollection(alice);
- const targetToken = await collection.mintToken(alice);
-
- await collection.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true}});
- await collection.addToAllowList(alice, {Substrate: bob.address});
- await collection.addToAllowList(alice, targetToken.nestingAccount());
-
- const collectionB = await helper.nft.mintCollection(alice, {permissions: {access: 'AllowList', mintMode: true}});
- await collectionB.addToAllowList(alice, {Substrate: bob.address});
- await collectionB.addToAllowList(alice, targetToken.nestingAccount());
-
- // Try to create a token to be nested and nest
- const newToken = await collectionB.mintToken(alice);
- await expect(newToken.nest(bob, targetToken)).to.be.rejectedWith(/common\.NoPermission/);
-
- expect(await targetToken.getChildren()).to.be.length(0);
- expect(await newToken.getOwner()).to.be.deep.equal({Substrate: alice.address});
- });
-
- itSub('NFT: disallows to nest token in an unlisted collection', async ({helper}) => {
- // Create collection with restricted nesting -- even self is not allowed
- const collection = await helper.nft.mintCollection(alice, {permissions: {access: 'AllowList', mintMode: true, nesting: {tokenOwner: true, restricted: []}}});
- const targetToken = await collection.mintToken(alice, {Substrate: bob.address});
-
- await collection.addToAllowList(alice, {Substrate: bob.address});
- await collection.addToAllowList(alice, targetToken.nestingAccount());
-
- // Try to mint in own collection after allowlisting the accounts
- await expect(collection.mintToken(bob, targetToken.nestingAccount()))
- .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
- });
-
- // ---------- Fungible ----------
-
- itSub('Fungible: disallows to nest token if nesting is disabled', async ({helper}) => {
- const collectionNFT = await helper.nft.mintCollection(alice);
- const collectionFT = await helper.ft.mintCollection(alice);
- const targetToken = await collectionNFT.mintToken(alice);
-
- // Try to create an immediately nested token
- await expect(collectionFT.mint(alice, 5n, targetToken.nestingAccount()))
- .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
-
- // Try to create a token to be nested and nest
- await collectionFT.mint(alice, 5n);
- await expect(collectionFT.transfer(alice, targetToken.nestingAccount(), 2n))
- .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
- expect(await collectionFT.getBalance({Substrate: alice.address})).to.be.equal(5n);
- });
-
itSub('Fungible: disallows a non-Owner to unnest someone else\'s token', async ({helper}) => {
const collectionNFT = await helper.nft.mintCollection(alice, {permissions: {nesting: {collectionAdmin: true, tokenOwner: true}}});
const collectionFT = await helper.ft.mintCollection(alice);
@@ -477,22 +204,5 @@
.to.be.rejectedWith(/common\.ApprovedValueTooLow/);
expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(5n);
});
-
- itSub('Fungible: disallows to nest token in an unlisted collection', async ({helper}) => {
- const collectionNFT = await helper.nft.mintCollection(alice, {permissions: {nesting: {collectionAdmin: true, tokenOwner: true, restricted: []}}});
- const collectionFT = await helper.ft.mintCollection(alice);
- const targetToken = await collectionNFT.mintToken(alice);
- // Try to mint an immediately nested token
- await expect(collectionFT.mint(alice, 5n, targetToken.nestingAccount()))
- .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
-
- // Mint a token and try to nest it
- await collectionFT.mint(alice, 5n);
- await expect(collectionFT.transfer(alice, targetToken.nestingAccount(), 1n))
- .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
-
- expect(await collectionFT.getBalance(targetToken.nestingAccount())).to.be.equal(0n);
- expect(await collectionFT.getBalance({Substrate: alice.address})).to.be.equal(5n);
- });
});
tests/src/sub/nesting/admin.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/sub/nesting/admin.test.ts
@@ -0,0 +1,87 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+import {IKeyringPair} from '@polkadot/types/types';
+import {expect, itSub, Pallets, usingPlaygrounds} from '../../util';
+
+describe('Collection admin', () => {
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+ let charlie: IKeyringPair;
+
+ before(async () => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = await privateKey({filename: __filename});
+ [alice, bob, charlie] = await helper.arrange.createAccounts([200n, 10n, 10n], donor);
+ });
+ });
+
+ [
+ {restricted: true},
+ {restricted: false},
+ ].map(testCase => {
+ itSub(`can nest tokens if "collectionAdmin" permission set ${testCase.restricted ? ', in restricted mode' : ''}`, async ({helper}) => {
+ const collectionA = await helper.nft.mintCollection(alice);
+ await collectionA.addAdmin(alice, {Substrate: bob.address});
+ const collectionB = await helper.nft.mintCollection(alice);
+ await collectionB.addAdmin(alice, {Substrate: bob.address});
+ // Collection has permission for collectionAdmin to nest:
+ await collectionA.setPermissions(alice, {nesting:
+ {collectionAdmin: true, restricted: testCase.restricted ? [collectionA.collectionId, collectionB.collectionId] : null},
+ });
+ // Token for nesting in from collectionA:
+ const targetTokenA = await collectionA.mintToken(alice, {Substrate: charlie.address});
+
+ // 1. Create an immediately nested tokens:
+ // 1.1 From own collection:
+ const nestedTokenA = await collectionA.mintToken(bob, targetTokenA.nestingAccount());
+ // 1.2 From different collection:
+ const nestedTokenB = await collectionB.mintToken(bob, targetTokenA.nestingAccount());
+ expect(await nestedTokenA.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
+ expect(await nestedTokenA.getOwner()).to.be.deep.equal(targetTokenA.nestingAccount().toLowerCase());
+ expect(await nestedTokenB.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
+ expect(await nestedTokenB.getOwner()).to.be.deep.equal(targetTokenA.nestingAccount().toLowerCase());
+
+ // 2. Create a token to be nested and nest:
+ const newNestedTokenA = await collectionA.mintToken(bob);
+ const newNestedTokenB = await collectionB.mintToken(bob);
+ // 2.1 From own collection:
+ await newNestedTokenA.nest(bob, targetTokenA);
+ // 2.2 From different collection:
+ await newNestedTokenB.nest(bob, targetTokenA);
+ expect(await newNestedTokenB.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
+ expect(await newNestedTokenB.getOwner()).to.be.deep.equal(targetTokenA.nestingAccount().toLowerCase());
+ });
+ });
+
+ itSub('can operate together with token owner if "collectionAdmin" and "tokenOwner" permissions set', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {collectionAdmin: true, tokenOwner: true}}});
+ await collection.addAdmin(alice, {Substrate: bob.address});
+ const targetToken = await collection.mintToken(alice, {Substrate: charlie.address});
+
+ // Admin can create an immediately nested token:
+ const nestedToken = await collection.mintToken(bob, targetToken.nestingAccount());
+ expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
+ expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
+
+ // Owner can create and and nest:
+ const newToken = await collection.mintToken(alice, {Substrate: charlie.address});
+ await newToken.nest(charlie, targetToken);
+ expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});
+ expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
+ });
+});
+
tests/src/sub/nesting/common.test.tsdiffbeforeafterboth--- a/tests/src/sub/nesting/common.test.ts
+++ b/tests/src/sub/nesting/common.test.ts
@@ -19,61 +19,77 @@
import {UniqueNFTCollection, UniqueRFTCollection} from '../../util/playgrounds/unique';
let alice: IKeyringPair;
+let bob: IKeyringPair;
before(async () => {
await usingPlaygrounds(async (helper, privateKey) => {
const donor = await privateKey({filename: __filename});
- [alice] = await helper.arrange.createAccounts([100n], donor);
+ [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);
});
});
[
- {mode: 'nft' as const, requiredPallets: []},
- {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'nft' as const, restrictedMode: true, requiredPallets: []},
+ {mode: 'nft' as const, restrictedMode: false, requiredPallets: []},
+ {mode: 'rft' as const, restrictedMode: true, requiredPallets: [Pallets.ReFungible]},
+ {mode: 'rft' as const, restrictedMode: false, requiredPallets: [Pallets.ReFungible]},
].map(testCase => {
- itSub.ifWithPallets(`Owner can nest ${testCase.mode.toUpperCase()} in NFT`, testCase.requiredPallets, async ({helper}) => {
- // Only NFT allows nesting, permissions should be set:
- const aliceNFTCollection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
- const targetToken = await aliceNFTCollection.mintToken(alice);
+ itSub.ifWithPallets(`Token owner can nest ${testCase.mode.toUpperCase()} in NFT if "tokenOwner" permission set ${testCase.restrictedMode ? 'in restricted mode': ''}`, testCase.requiredPallets, async ({helper}) => {
+ // Only NFT can be target for nesting in
+ const targetNFTCollection = await helper.nft.mintCollection(alice);
+ const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});
- const collectionForNesting = await helper[testCase.mode].mintCollection(alice);
+ const collectionForNesting = await helper[testCase.mode].mintCollection(bob);
+ // permissions should be set:
+ await targetNFTCollection.setPermissions(alice, {
+ nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},
+ });
- // 1. Alice can immediately create nested token:
+ // 1. Bob can immediately create nested token:
const nestedToken1 = testCase.mode === 'nft'
- ? await (collectionForNesting as UniqueNFTCollection).mintToken(alice, targetToken.nestingAccount())
- : await (collectionForNesting as UniqueRFTCollection).mintToken(alice, 10n, targetToken.nestingAccount());
- expect(await nestedToken1.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});
- expect(await nestedToken1.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
+ ? await (collectionForNesting as UniqueNFTCollection).mintToken(bob, targetTokenBob.nestingAccount())
+ : await (collectionForNesting as UniqueRFTCollection).mintToken(bob, 10n, targetTokenBob.nestingAccount());
+ expect(await nestedToken1.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});
+ expect(await nestedToken1.getOwner()).to.be.deep.equal(targetTokenBob.nestingAccount().toLowerCase());
- // 2. Alice can mint and nest token:
- const nestedToken2 = await collectionForNesting.mintToken(alice);
- await nestedToken2.nest(alice, targetToken);
- expect(await nestedToken2.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});
- expect(await nestedToken2.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase());
+ // 2. Bob can mint and nest token:
+ const nestedToken2 = await collectionForNesting.mintToken(bob);
+ await nestedToken2.nest(bob, targetTokenBob);
+ expect(await nestedToken2.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});
+ expect(await nestedToken2.getOwner()).to.be.deep.equal(targetTokenBob.nestingAccount().toLowerCase());
});
});
-itSub('Owner can nest FT in NFT', async ({helper}) => {
- // Only NFT allows nesting, permissions should be set:
- const aliceNFTCollection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
- const targetToken = await aliceNFTCollection.mintToken(alice);
+[
+ {restrictedMode: true},
+ {restrictedMode: false},
+].map(testCase => {
+ itSub(`Token owner can nest FT in NFT if "tokenOwner" permission set ${testCase.restrictedMode ? 'in restricted mode': ''}`, async ({helper}) => {
+ // Only NFT allows nesting, permissions should be set:
+ const targetNFTCollection = await helper.nft.mintCollection(alice);
+ const targetTokenBob = await targetNFTCollection.mintToken(alice, {Substrate: bob.address});
- const collectionForNesting = await helper.ft.mintCollection(alice);
+ const collectionForNesting = await helper.ft.mintCollection(bob);
+ // permissions should be set:
+ await targetNFTCollection.setPermissions(alice, {
+ nesting: {tokenOwner: true, restricted: testCase.restrictedMode ? [collectionForNesting.collectionId] : null},
+ });
- // 1. Alice can immediately create nested tokens:
- await collectionForNesting.mint(alice, 100n, targetToken.nestingAccount());
- expect(await collectionForNesting.getTop10Owners()).deep.eq([targetToken.nestingAccount().toLowerCase()]);
- expect(await collectionForNesting.getBalance(targetToken.nestingAccount())).eq(100n);
+ // 1. Alice can immediately create nested tokens:
+ await collectionForNesting.mint(bob, 100n, targetTokenBob.nestingAccount());
+ expect(await collectionForNesting.getTop10Owners()).deep.eq([targetTokenBob.nestingAccount().toLowerCase()]);
+ expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(100n);
- // 2. Alice can mint and nest token:
- await collectionForNesting.mint(alice, 100n);
- await collectionForNesting.transfer(alice, targetToken.nestingAccount(), 50n);
- expect(await collectionForNesting.getBalance(targetToken.nestingAccount())).eq(150n);
+ // 2. Alice can mint and nest token:
+ await collectionForNesting.mint(bob, 100n);
+ await collectionForNesting.transfer(bob, targetTokenBob.nestingAccount(), 50n);
+ expect(await collectionForNesting.getBalance(targetTokenBob.nestingAccount())).eq(150n);
+ });
});
-itSub.ifWithPallets('Owner can transferFrom nested tokens', [Pallets.ReFungible], async ({helper}) => {
+itSub.ifWithPallets('Owner can unnest tokens using transferFrom', [Pallets.ReFungible], async ({helper}) => {
const collectionToNest = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});
const tokenA = await collectionToNest.mintToken(alice);
const tokenB = await collectionToNest.mintToken(alice);
tests/src/sub/nesting/negative.test.tsdiffbeforeafterboth1// 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';20import {itEth} from '../../eth/util';2122let alice: IKeyringPair;2324before(async () => {25 await usingPlaygrounds(async (helper, privateKey) => {26 const donor = await privateKey({filename: __filename});27 [alice] = await helper.arrange.createAccounts([50n], donor);28 });29});3031[32 {mode: 'nft' as const, requiredPallets: []},33 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},34].map(testCase => {35 itSub.ifWithPallets(`Owner cannot nest ${testCase.mode.toUpperCase()} if nesting not allowed`, testCase.requiredPallets, async ({helper}) => {36 // Create default collection, permissions are not set:37 const aliceNFTCollection = await helper.nft.mintCollection(alice);38 const targetToken = await aliceNFTCollection.mintToken(alice);3940 const collectionForNesting = await helper[testCase.mode].mintCollection(alice);4142 // 1. Alice cannot create immediately nested tokens:43 const nestingTx = testCase.mode === 'nft'44 ? (collectionForNesting as UniqueNFTCollection).mintToken(alice, targetToken.nestingAccount())45 : (collectionForNesting as UniqueRFTCollection).mintToken(alice, 10n, targetToken.nestingAccount());46 await expect(nestingTx).to.be.rejectedWith('common.UserIsNotAllowedToNest');4748 // 2. Alice cannot mint and nest token:49 const nestedToken2 = await collectionForNesting.mintToken(alice);50 await expect(nestedToken2.nest(alice, targetToken)).to.be.rejectedWith('common.UserIsNotAllowedToNest');51 });52});5354itSub('Owner cannot nest FT if nesting not allowed', async ({helper}) => {55 // Create default collection, permissions are not set:56 const aliceNFTCollection = await helper.nft.mintCollection(alice);57 const targetToken = await aliceNFTCollection.mintToken(alice);5859 const collectionForNesting = await helper.ft.mintCollection(alice);6061 // 1. Alice cannot create immediately nested tokens:62 await expect(collectionForNesting.mint(alice, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest');6364 // 2. Alice can mint and nest token:65 await collectionForNesting.mint(alice, 100n);66 await expect(collectionForNesting.transfer(alice, targetToken.nestingAccount(), 50n)).to.be.rejectedWith('common.UserIsNotAllowedToNest');67});6869itSub.ifWithPallets('Cannot nest in non existing token', [Pallets.ReFungible], async ({helper}) => {70 const collection = await helper.nft.mintCollection(alice);71 // To avoid UserIsNotAllowedToNest error72 await helper.collection.setPermissions(alice, collection.collectionId, {nesting: {collectionAdmin: true}});7374 // The list of non-existing tokens:75 const tokenFromNonExistingCollection = helper.nft.getTokenObject(9999999, 1);76 const tokenBurnt = await collection.mintToken(alice);77 await tokenBurnt.burn(alice);78 const tokenNotMintedYet = helper.nft.getTokenObject(collection.collectionId, 2);7980 // The list of collections to nest tokens from:81 const nftCollectionForNesting = await helper.nft.mintCollection(alice);82 const rftCollectionForNesting = await helper.rft.mintCollection(alice);83 const ftCollectionForNesting = await helper.ft.mintCollection(alice);8485 const testCases = [86 {token: tokenFromNonExistingCollection, error: 'CollectionNotFound'},87 {token: tokenBurnt, error: 'TokenNotFound'},88 {token: tokenNotMintedYet, error: 'TokenNotFound'},89 ];9091 for(const testCase of testCases) {92 // 1. Alice cannot create nested token to non-existing token93 await expect(nftCollectionForNesting.mintToken(alice, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);94 await expect(rftCollectionForNesting.mintToken(alice, 10n, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);95 await expect(ftCollectionForNesting.mint(alice, 10n, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);9697 // 2. Alice cannot mint and nest token:98 const nft = await nftCollectionForNesting.mintToken(alice);99 const rft = await rftCollectionForNesting.mintToken(alice, 100n);100 const _ft = await ftCollectionForNesting.mint(alice, 100n);101 await expect(nft.transfer(alice, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);102 await expect(rft.transfer(alice, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);103 await expect(ftCollectionForNesting.transfer(alice, testCase.token.nestingAccount(), 50n)).to.be.rejectedWith(testCase.error);104 }105});106107itEth.ifWithPallets('Cannot nest to collection address', [Pallets.ReFungible], async({helper}) => {108 const existingCollection = await helper.nft.mintCollection(alice);109 const existingCollectionAddress = helper.ethAddress.fromCollectionId(existingCollection.collectionId);110 const futureCollectionAddress = helper.ethAddress.fromCollectionId(99999999);111112 const nftCollectionForNesting = await helper.nft.mintCollection(alice);113114 // 1. Alice cannot create nested token to collection address115 await expect(nftCollectionForNesting.mintToken(alice, {Ethereum: existingCollectionAddress})).to.be.rejectedWith('CantNestTokenUnderCollection');116 await expect(nftCollectionForNesting.mintToken(alice, {Ethereum: futureCollectionAddress})).to.be.rejectedWith('CantNestTokenUnderCollection');117118 // 2. Alice cannot mint and nest token to collection address:119 const nft = await nftCollectionForNesting.mintToken(alice);120 await expect(nft.transfer(alice, {Ethereum: existingCollectionAddress})).to.be.rejectedWith('CantNestTokenUnderCollection');121 await expect(nft.transfer(alice, {Ethereum: futureCollectionAddress})).to.be.rejectedWith('CantNestTokenUnderCollection');122});123124itEth.ifWithPallets('Cannot nest in RFT or FT', [Pallets.ReFungible], async ({helper}) => {125 // Create default collection, permissions are not set:126 const rftCollection = await helper.rft.mintCollection(alice);127 const ftCollection = await helper.ft.mintCollection(alice);128129 const rftToken = await rftCollection.mintToken(alice);130 const _ftToken = await ftCollection.mint(alice, 100n);131132 const collectionForNesting = await helper.nft.mintCollection(alice);133134 // 1. Alice cannot create immediately nested tokens:135 await expect(collectionForNesting.mintToken(alice, rftToken.nestingAccount())).to.be.rejectedWith('refungible.RefungibleDisallowsNesting');136 await expect(collectionForNesting.mintToken(alice, {Ethereum: helper.ethAddress.fromTokenId(ftCollection.collectionId, 0)})).to.be.rejectedWith('fungible.FungibleDisallowsNesting');137138 // 2. Alice cannot mint and nest token:139 const nestedToken2 = await collectionForNesting.mintToken(alice);140 await expect(nestedToken2.nest(alice, rftToken)).to.be.rejectedWith('refungible.RefungibleDisallowsNesting');141 await expect(ftCollection.transfer(alice, {Ethereum: helper.ethAddress.fromTokenId(ftCollection.collectionId, 0)})).to.be.rejectedWith('fungible.FungibleDisallowsNesting');142});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 {UniqueFTCollection, UniqueNFTCollection, UniqueNFToken, UniqueRFTCollection, UniqueRFToken} from '../../util/playgrounds/unique';20import {itEth} from '../../eth/util';2122let alice: IKeyringPair;23let bob: IKeyringPair;2425before(async () => {26 await usingPlaygrounds(async (helper, privateKey) => {27 const donor = await privateKey({filename: __filename});28 [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);29 });30});3132[33 {mode: 'nft' as const, requiredPallets: []},34 {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]},35].map(testCase => {36 itSub.ifWithPallets(`Owner cannot nest ${testCase.mode.toUpperCase()} if nesting is disabled`, testCase.requiredPallets, async ({helper}) => {37 // Create default collection, permissions are not set:38 const aliceNFTCollection = await helper.nft.mintCollection(alice);39 const targetToken = await aliceNFTCollection.mintToken(alice);4041 const collectionForNesting = await helper[testCase.mode].mintCollection(alice);4243 // 1. Alice cannot create immediately nested tokens:44 const nestingTx = testCase.mode === 'nft'45 ? (collectionForNesting as UniqueNFTCollection).mintToken(alice, targetToken.nestingAccount())46 : (collectionForNesting as UniqueRFTCollection).mintToken(alice, 10n, targetToken.nestingAccount());47 await expect(nestingTx).to.be.rejectedWith('common.UserIsNotAllowedToNest');4849 // 2. Alice cannot mint and nest token:50 const nestedToken2 = await collectionForNesting.mintToken(alice);51 await expect(nestedToken2.nest(alice, targetToken)).to.be.rejectedWith('common.UserIsNotAllowedToNest');52 });53});5455itSub('Owner cannot nest FT if nesting is disabled', async ({helper}) => {56 // Create default collection, permissions are not set:57 const aliceNFTCollection = await helper.nft.mintCollection(alice);58 const targetToken = await aliceNFTCollection.mintToken(alice);5960 const collectionForNesting = await helper.ft.mintCollection(alice);6162 // 1. Alice cannot create immediately nested tokens:63 await expect(collectionForNesting.mint(alice, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest');6465 // 2. Alice can mint and nest token:66 await collectionForNesting.mint(alice, 100n);67 await expect(collectionForNesting.transfer(alice, targetToken.nestingAccount(), 50n)).to.be.rejectedWith('common.UserIsNotAllowedToNest');68});6970[71 {mode: 'nft' as const},72 {mode: 'rft' as const},73 {mode: 'ft' as const},74].map(testCase => {75 itSub(`Non-owner and non-admin cannot nest ${testCase.mode.toUpperCase()} in someone else's tokens`, async ({helper}) => {76 const targetCollection = await helper.nft.mintCollection(alice, {permissions:77 {nesting: {tokenOwner: true, collectionAdmin: true}},78 });79 const targetToken = await targetCollection.mintToken(alice);8081 const nestedCollectionBob = await helper[testCase.mode].mintCollection(bob);8283 let nestedTokenBob: UniqueNFToken | UniqueRFToken;84 switch (testCase.mode) {85 case 'nft': nestedTokenBob = await (nestedCollectionBob as UniqueNFTCollection).mintToken(bob); break;86 case 'rft': nestedTokenBob = await (nestedCollectionBob as UniqueRFTCollection).mintToken(bob, 100n); break;87 case 'ft': await (nestedCollectionBob as UniqueFTCollection).mint(bob, 100n); break;88 }8990 // Bob non-owner of targetToken and non admin of targetCollection, so91 // 1. cannot mint nested token:92 switch (testCase.mode) {93 case 'nft': await expect((nestedCollectionBob as UniqueNFTCollection).mintToken(bob, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;94 case 'rft': await expect((nestedCollectionBob as UniqueRFTCollection).mintToken(bob, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;95 case 'ft': await expect((nestedCollectionBob as UniqueFTCollection).mint(bob, 100n, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;96 }9798 // 2. cannot nest existing token:99 switch (testCase.mode) {100 case 'nft':101 case 'rft': await expect(nestedTokenBob!.transfer(bob, targetToken.nestingAccount())).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;102 case 'ft': await expect((nestedCollectionBob as UniqueFTCollection).transfer(bob, targetToken.nestingAccount(), 100n)).to.be.rejectedWith('common.UserIsNotAllowedToNest'); break;103 }104 });105});106107[108 {mode: 'nft' as const, nesting: {tokenOwner: true, collectionAdmin: false}},109 {mode: 'nft' as const, nesting: {tokenOwner: false, collectionAdmin: true}},110].map(testCase => {111 itSub(`${testCase.nesting.tokenOwner'Admin''Token owner'} cannot nest when only ${testCase.nesting.tokenOwner'tokenOwner''collectionAdmin'} is allowed`, async ({helper}) => {112 // Create collection with tokenOwner or create collection with collectionAdmin permission:113 const targetCollection = await helper.nft.mintCollection(alice, {permissions: {nesting: testCase.nesting}});114 const targetTokenAlice = await targetCollection.mintToken(alice);115 await targetCollection.addAdmin(alice, {Substrate: bob.address});116117 const nestedCollectionAlice = await helper[testCase.mode].mintCollection(alice);118 const nestedCollectionBob = await helper[testCase.mode].mintCollection(bob);119 // if nesting permissions restricted for token owner – minter is bob (admin),120 // if collectionAdmin – alice (owner)121122 // FIXME: nesting allowed only for admin but token owner can nest anyway:123 testCase.nesting.tokenOwner124 ? await expect(nestedCollectionBob.mintToken(bob, targetTokenAlice.nestingAccount())).to.be.rejectedWith(/common\.UserIsNotAllowedToNest/)125 : await expect(nestedCollectionAlice.mintToken(alice, targetTokenAlice.nestingAccount())).to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);126 });127});128129itSub.ifWithPallets('Cannot nest in non existing token', [Pallets.ReFungible], async ({helper}) => {130 const collection = await helper.nft.mintCollection(alice);131 // To avoid UserIsNotAllowedToNest error132 await helper.collection.setPermissions(alice, collection.collectionId, {nesting: {collectionAdmin: true}});133134 // The list of non-existing tokens:135 const tokenFromNonExistingCollection = helper.nft.getTokenObject(9999999, 1);136 const tokenBurnt = await collection.mintToken(alice);137 await tokenBurnt.burn(alice);138 const tokenNotMintedYet = helper.nft.getTokenObject(collection.collectionId, 2);139140 // The list of collections to nest tokens from:141 const nftCollectionForNesting = await helper.nft.mintCollection(alice);142 const rftCollectionForNesting = await helper.rft.mintCollection(alice);143 const ftCollectionForNesting = await helper.ft.mintCollection(alice);144145 const testCases = [146 {token: tokenFromNonExistingCollection, error: 'CollectionNotFound'},147 {token: tokenBurnt, error: 'TokenNotFound'},148 {token: tokenNotMintedYet, error: 'TokenNotFound'},149 ];150151 for(const testCase of testCases) {152 // 1. Alice cannot create nested token to non-existing token153 await expect(nftCollectionForNesting.mintToken(alice, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);154 await expect(rftCollectionForNesting.mintToken(alice, 10n, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);155 await expect(ftCollectionForNesting.mint(alice, 10n, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);156157 // 2. Alice cannot mint and nest token:158 const nft = await nftCollectionForNesting.mintToken(alice);159 const rft = await rftCollectionForNesting.mintToken(alice, 100n);160 const _ft = await ftCollectionForNesting.mint(alice, 100n);161 await expect(nft.transfer(alice, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);162 await expect(rft.transfer(alice, testCase.token.nestingAccount())).to.be.rejectedWith(testCase.error);163 await expect(ftCollectionForNesting.transfer(alice, testCase.token.nestingAccount(), 50n)).to.be.rejectedWith(testCase.error);164 }165});166167itEth.ifWithPallets('Cannot nest in collection address', [Pallets.ReFungible], async({helper}) => {168 const existingCollection = await helper.nft.mintCollection(alice);169 const existingCollectionAddress = helper.ethAddress.fromCollectionId(existingCollection.collectionId);170 const futureCollectionAddress = helper.ethAddress.fromCollectionId(99999999);171172 const nftCollectionForNesting = await helper.nft.mintCollection(alice);173174 // 1. Alice cannot create nested token to collection address175 await expect(nftCollectionForNesting.mintToken(alice, {Ethereum: existingCollectionAddress})).to.be.rejectedWith('CantNestTokenUnderCollection');176 await expect(nftCollectionForNesting.mintToken(alice, {Ethereum: futureCollectionAddress})).to.be.rejectedWith('CantNestTokenUnderCollection');177178 // 2. Alice cannot mint and nest token to collection address:179 const nft = await nftCollectionForNesting.mintToken(alice);180 await expect(nft.transfer(alice, {Ethereum: existingCollectionAddress})).to.be.rejectedWith('CantNestTokenUnderCollection');181 await expect(nft.transfer(alice, {Ethereum: futureCollectionAddress})).to.be.rejectedWith('CantNestTokenUnderCollection');182});183184itEth.ifWithPallets('Cannot nest in RFT or FT', [Pallets.ReFungible], async ({helper}) => {185 // Create default collection, permissions are not set:186 const rftCollection = await helper.rft.mintCollection(alice);187 const ftCollection = await helper.ft.mintCollection(alice);188189 const rftToken = await rftCollection.mintToken(alice);190 const _ftToken = await ftCollection.mint(alice, 100n);191192 const collectionForNesting = await helper.nft.mintCollection(alice);193194 // 1. Alice cannot create immediately nested tokens:195 await expect(collectionForNesting.mintToken(alice, rftToken.nestingAccount())).to.be.rejectedWith('refungible.RefungibleDisallowsNesting');196 await expect(collectionForNesting.mintToken(alice, {Ethereum: helper.ethAddress.fromTokenId(ftCollection.collectionId, 0)})).to.be.rejectedWith('fungible.FungibleDisallowsNesting');197198 // 2. Alice cannot mint and nest token:199 const nestedToken2 = await collectionForNesting.mintToken(alice);200 await expect(nestedToken2.nest(alice, rftToken)).to.be.rejectedWith('refungible.RefungibleDisallowsNesting');201 await expect(ftCollection.transfer(alice, {Ethereum: helper.ethAddress.fromTokenId(ftCollection.collectionId, 0)})).to.be.rejectedWith('fungible.FungibleDisallowsNesting');202});203204itSub('Cannot nest in restricted collection if collection is not in the list', async ({helper}) => {205 const {collectionId: allowedCollectionId} = await helper.nft.mintCollection(alice);206 const notAllowedCollectionNFT = await helper.nft.mintCollection(alice);207 const notAllowedCollectionRFT = await helper.rft.mintCollection(alice);208 const notAllowedCollectionFT = await helper.ft.mintCollection(alice);209210 // Collection restricted to allowedCollectionId211 const restrictedCollectionA = await helper.nft.mintCollection(alice, {permissions:212 {nesting: {tokenOwner: true, restricted: [allowedCollectionId]}},213 });214 // Create collection with restricted nesting -- even self is not allowed215 const restrictedCollectionB = await helper.nft.mintCollection(alice, {permissions:216 {nesting: {tokenOwner: true, restricted: []}},217 });218219 const targetTokenA = await restrictedCollectionA.mintToken(alice);220 const targetTokenB = await restrictedCollectionB.mintToken(alice);221222 // 1. Cannot mint in own collection after allowlisting the accounts:223 await expect(restrictedCollectionA.mintToken(alice, targetTokenA.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);224 await expect(restrictedCollectionB.mintToken(alice, targetTokenB.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);225226 // 2. Cannot mint from notAllowedCollection:227 await expect(notAllowedCollectionNFT.mintToken(alice, targetTokenA.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);228 await expect(notAllowedCollectionNFT.mintToken(alice, targetTokenB.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);229 await expect(notAllowedCollectionRFT.mintToken(alice, 100n, targetTokenA.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);230 await expect(notAllowedCollectionRFT.mintToken(alice, 100n, targetTokenB.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);231 await expect(notAllowedCollectionFT.mint(alice, 100n, targetTokenA.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);232 await expect(notAllowedCollectionFT.mint(alice, 100n, targetTokenB.nestingAccount())).to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);233});234235itSub('Cannot create nesting chains greater than 5', async ({helper}) => {236 const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}});237 let token = await collection.mintToken(alice);238239 const maxNestingLevel = 5;240241 // Create a nested-token matryoshka242 for (let i = 0; i < maxNestingLevel; i++) {243 token = await collection.mintToken(alice, token.nestingAccount());244 }245246 // The nesting depth is limited by `maxNestingLevel`247 // 1. Cannot mint:248 await expect(collection.mintToken(alice, token.nestingAccount()))249 .to.be.rejectedWith(/structure\.DepthLimit/);250 // 2. Cannot transfer:251 const anotherToken = await collection.mintToken(alice);252 await expect(anotherToken.transfer(alice, token.nestingAccount()))253 .to.be.rejectedWith(/structure\.DepthLimit/);254 // 3. Cannot nest FT pieces:255 const ftCollection = await helper.ft.mintCollection(alice);256 await expect(ftCollection.mint(alice, 100n, token.nestingAccount()))257 .to.be.rejectedWith(/structure\.DepthLimit/);258259 expect(await token.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});260 expect(await token.getChildren()).to.has.length(0);261});tests/src/sub/refungible/nesting.test.tsdiffbeforeafterboth--- a/tests/src/sub/refungible/nesting.test.ts
+++ b/tests/src/sub/refungible/nesting.test.ts
@@ -116,22 +116,6 @@
});
});
- itSub('cannot nest token if nesting is disabled', async ({helper}) => {
- const collectionNFT = await helper.nft.mintCollection(alice);
- const collectionRFT = await helper.rft.mintCollection(alice);
- const targetToken = await collectionNFT.mintToken(alice);
-
- // Try to create an immediately nested token
- await expect(collectionRFT.mintToken(alice, 5n, targetToken.nestingAccount()))
- .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
-
- // Try to create a token to be nested and nest
- const token = await collectionRFT.mintToken(alice, 5n);
- await expect(token.transfer(alice, targetToken.nestingAccount(), 2n))
- .to.be.rejectedWith(/common\.UserIsNotAllowedToNest/);
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(5n);
- });
-
[
{restrictedMode: true},
{restrictedMode: false},
@@ -160,21 +144,5 @@
.to.be.rejectedWith(/common\.ApprovedValueTooLow/);
expect(await newToken.getBalance(targetToken.nestingAccount())).to.be.equal(1n);
});
- });
-
- itSub('ReFungible: disallows to nest token to an unlisted collection', async ({helper}) => {
- const collectionNFT = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true, restricted: []}}});
- const collectionRFT = await helper.rft.mintCollection(alice);
- const targetToken = await collectionNFT.mintToken(alice);
-
- // Try to create an immediately nested token
- await expect(collectionRFT.mintToken(alice, 5n, targetToken.nestingAccount()))
- .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
-
- // Try to create a token to be nested and nest
- const token = await collectionRFT.mintToken(alice, 5n);
- await expect(token.transfer(alice, targetToken.nestingAccount(), 2n))
- .to.be.rejectedWith(/common\.SourceCollectionIsNotAllowedToNest/);
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(5n);
});
});