git.delta.rocks / unique-network / refs/commits / 3563d095a013

difftreelog

Merge pull request #881 from UniqueNetwork/fix/collection-owner-nesting

Yaroslav Bolyukin2023-02-11parents: #7467766 #4a2e26d.patch.diff
in: master
Fix/collection owner nesting

2 files changed

modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
1273 Some(from),1273 Some(from),
1274 nesting_budget,1274 nesting_budget,
1275 )? {1275 )? {
1276 // Pass, token existence is checked in `check_indirectly_owned`1276 // Pass, token existence and ouroboros checks are done in `check_indirectly_owned`
1277 } else if nesting.collection_admin && handle.is_owner_or_admin(&sender) {1277 } else if nesting.collection_admin && handle.is_owner_or_admin(&sender) {
1278 ensure!(1278 // token existence and ouroboros checks are done in `get_checked_topmost_owner`
1279 <TokenData<T>>::contains_key((handle.id, under)),1279 let _ = <PalletStructure<T>>::get_checked_topmost_owner(
1280 handle.id,
1281 under,
1282 Some(from),
1283 nesting_budget,
1284 )?
1280 <CommonError<T>>::TokenNotFound1285 .ok_or(<CommonError<T>>::TokenNotFound)?;
1281 );
1282 } else {1286 } else {
1283 fail!(<CommonError<T>>::UserIsNotAllowedToNest);1287 fail!(<CommonError<T>>::UserIsNotAllowedToNest);
1284 }1288 }
modifiedtests/src/nesting/graphs.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/graphs.test.ts
+++ b/tests/src/nesting/graphs.test.ts
@@ -16,7 +16,7 @@
 
 import {IKeyringPair} from '@polkadot/types/types';
 import {expect, itSub, usingPlaygrounds} from '../util';
-import {UniqueHelper, UniqueNFToken} from '../util/playgrounds/unique';
+import {UniqueHelper, UniqueNFTCollection, UniqueNFToken} from '../util/playgrounds/unique';
 
 /**
  * ```dot
@@ -25,7 +25,7 @@
  * 8 -> 5
  * ```
  */
-async function buildComplexObjectGraph(helper: UniqueHelper, sender: IKeyringPair): Promise<UniqueNFToken[]> {
+async function buildComplexObjectGraph(helper: UniqueHelper, sender: IKeyringPair): Promise<[UniqueNFTCollection,UniqueNFToken[]]> {
   const collection = await helper.nft.mintCollection(sender, {permissions: {nesting: {tokenOwner: true}}});
   const tokens = await collection.mintMultipleTokens(sender, Array(8).fill({owner: {Substrate: sender.address}}));
 
@@ -37,7 +37,7 @@
   await tokens[2].nest(sender, tokens[1]);
   await tokens[1].nest(sender, tokens[0]);
 
-  return tokens;
+  return [collection, tokens];
 }
 
 describe('Graphs', () => {
@@ -51,21 +51,36 @@
   });
 
   itSub('Ouroboros can\'t be created in a complex graph', async ({helper}) => {
-    const tokens = await buildComplexObjectGraph(helper, alice);
+    const [collection, tokens] = await buildComplexObjectGraph(helper, alice);
+
+    await collection.setPermissions(alice, {nesting: {collectionAdmin: false, tokenOwner: true}});
 
-    // to self
+    // [token owner] to self
     await expect(
       tokens[0].nest(alice, tokens[0]),
-      'first transaction',
+      '[token owner] self-nesting is forbidden',
     ).to.be.rejectedWith(/structure\.OuroborosDetected/);
-    // to nested part of graph
+    // [token owner] to nested part of graph
     await expect(
       tokens[0].nest(alice, tokens[4]),
-      'second transaction',
+      '[token owner] cannot nest the root node into an internal node',
     ).to.be.rejectedWith(/structure\.OuroborosDetected/);
     await expect(
       tokens[1].transferFrom(alice, tokens[0].nestingAccount(), tokens[7].nestingAccount()),
-      'third transaction',
+      '[token owner] cannot nest higher internal node into lower internal node',
+    ).to.be.rejectedWith(/structure\.OuroborosDetected/);
+
+    await collection.setPermissions(alice, {nesting: {collectionAdmin: true, tokenOwner: false}});
+
+    // [collection owner] to self
+    await expect(
+      tokens[0].nest(alice, tokens[0]),
+      '[collection owner] self-nesting is forbidden',
+    ).to.be.rejectedWith(/structure\.OuroborosDetected/);
+    // [collection owner] to nested part of graph
+    await expect(
+      tokens[0].nest(alice, tokens[4]),
+      '[collection owner] cannot nest the root node into an internal node',
     ).to.be.rejectedWith(/structure\.OuroborosDetected/);
   });
 });