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
1616
17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';
18import {expect, itSub, usingPlaygrounds} from '../util';18import {expect, itSub, usingPlaygrounds} from '../util';
19import {UniqueHelper, UniqueNFToken} from '../util/playgrounds/unique';19import {UniqueHelper, UniqueNFTCollection, UniqueNFToken} from '../util/playgrounds/unique';
2020
21/**21/**
22 * ```dot22 * ```dot
25 * 8 -> 525 * 8 -> 5
26 * ```26 * ```
27 */27 */
28async function buildComplexObjectGraph(helper: UniqueHelper, sender: IKeyringPair): Promise<UniqueNFToken[]> {28async function buildComplexObjectGraph(helper: UniqueHelper, sender: IKeyringPair): Promise<[UniqueNFTCollection,UniqueNFToken[]]> {
29 const collection = await helper.nft.mintCollection(sender, {permissions: {nesting: {tokenOwner: true}}});29 const collection = await helper.nft.mintCollection(sender, {permissions: {nesting: {tokenOwner: true}}});
30 const tokens = await collection.mintMultipleTokens(sender, Array(8).fill({owner: {Substrate: sender.address}}));30 const tokens = await collection.mintMultipleTokens(sender, Array(8).fill({owner: {Substrate: sender.address}}));
3131
37 await tokens[2].nest(sender, tokens[1]);37 await tokens[2].nest(sender, tokens[1]);
38 await tokens[1].nest(sender, tokens[0]);38 await tokens[1].nest(sender, tokens[0]);
3939
40 return tokens;40 return [collection, tokens];
41}41}
4242
43describe('Graphs', () => {43describe('Graphs', () => {
51 });51 });
5252
53 itSub('Ouroboros can\'t be created in a complex graph', async ({helper}) => {53 itSub('Ouroboros can\'t be created in a complex graph', async ({helper}) => {
54 const tokens = await buildComplexObjectGraph(helper, alice);54 const [collection, tokens] = await buildComplexObjectGraph(helper, alice);
55
56 await collection.setPermissions(alice, {nesting: {collectionAdmin: false, tokenOwner: true}});
5557
56 // to self58 // [token owner] to self
57 await expect(59 await expect(
58 tokens[0].nest(alice, tokens[0]),60 tokens[0].nest(alice, tokens[0]),
59 'first transaction',61 '[token owner] self-nesting is forbidden',
60 ).to.be.rejectedWith(/structure\.OuroborosDetected/);62 ).to.be.rejectedWith(/structure\.OuroborosDetected/);
61 // to nested part of graph63 // [token owner] to nested part of graph
62 await expect(64 await expect(
63 tokens[0].nest(alice, tokens[4]),65 tokens[0].nest(alice, tokens[4]),
64 'second transaction',66 '[token owner] cannot nest the root node into an internal node',
65 ).to.be.rejectedWith(/structure\.OuroborosDetected/);67 ).to.be.rejectedWith(/structure\.OuroborosDetected/);
66 await expect(68 await expect(
67 tokens[1].transferFrom(alice, tokens[0].nestingAccount(), tokens[7].nestingAccount()),69 tokens[1].transferFrom(alice, tokens[0].nestingAccount(), tokens[7].nestingAccount()),
68 'third transaction',70 '[token owner] cannot nest higher internal node into lower internal node',
69 ).to.be.rejectedWith(/structure\.OuroborosDetected/);71 ).to.be.rejectedWith(/structure\.OuroborosDetected/);
72
73 await collection.setPermissions(alice, {nesting: {collectionAdmin: true, tokenOwner: false}});
74
75 // [collection owner] to self
76 await expect(
77 tokens[0].nest(alice, tokens[0]),
78 '[collection owner] self-nesting is forbidden',
79 ).to.be.rejectedWith(/structure\.OuroborosDetected/);
80 // [collection owner] to nested part of graph
81 await expect(
82 tokens[0].nest(alice, tokens[4]),
83 '[collection owner] cannot nest the root node into an internal node',
84 ).to.be.rejectedWith(/structure\.OuroborosDetected/);
70 });85 });
71});86});
7287