difftreelog
Merge pull request #881 from UniqueNetwork/fix/collection-owner-nesting
in: master
Fix/collection owner nesting
2 files changed
pallets/nonfungible/src/lib.rsdiffbeforeafterboth1273 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 }tests/src/nesting/graphs.test.tsdiffbeforeafterboth161617import {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';202021/**21/**22 * ```dot22 * ```dot25 * 8 -> 525 * 8 -> 526 * ```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}}));313137 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]);393940 return tokens;40 return [collection, tokens];41}41}424243describe('Graphs', () => {43describe('Graphs', () => {51 });51 });525253 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);5556 await collection.setPermissions(alice, {nesting: {collectionAdmin: false, tokenOwner: true}});555756 // to self58 // [token owner] to self57 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 graph62 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/);7273 await collection.setPermissions(alice, {nesting: {collectionAdmin: true, tokenOwner: false}});7475 // [collection owner] to self76 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 graph81 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