git.delta.rocks / unique-network / refs/commits / 0ef2a332f919

difftreelog

source

js-packages/tests/eth/nesting/nest.test.ts16.0 KiBsourcehistory
1import type {IKeyringPair} from '@polkadot/types/types';2import {Contract} from 'web3-eth-contract';34import {itEth, usingEthPlaygrounds, expect} from '../util/index.js';5import {EthUniqueHelper} from '../util/playgrounds/unique.dev.js';67const createNestingCollection = async (8  helper: EthUniqueHelper,9  owner: string,10  mergeDeprecated = false,11): Promise<{ collectionId: number, collectionAddress: string, contract: Contract }> => {12  const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');1314  const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, mergeDeprecated);15  await contract.methods.setCollectionNesting([true, false, []]).send({from: owner});1617  return {collectionId, collectionAddress, contract};18};192021describe('EVM nesting tests group', () => {22  let donor: IKeyringPair;2324  before(async function() {25    await usingEthPlaygrounds(async (_, privateKey) => {26      donor = await privateKey({url: import.meta.url});27    });28  });2930  describe('Integration Test: EVM Nesting', () => {31    itEth('NFT: allows an Owner to nest/unnest their token', async ({helper}) => {32      const owner = await helper.eth.createAccountWithBalance(donor);33      const {collectionId, contract} = await createNestingCollection(helper, owner);3435      // Create a token to be nested to36      const mintingTargetNFTTokenIdResult = await contract.methods.mint(owner).send({from: owner});37      const targetNFTTokenId = mintingTargetNFTTokenIdResult.events.Transfer.returnValues.tokenId;38      const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetNFTTokenId);3940      // Create a nested token41      const mintingFirstTokenIdResult = await contract.methods.mint(targetNftTokenAddress).send({from: owner});42      const firstTokenId = mintingFirstTokenIdResult.events.Transfer.returnValues.tokenId;43      expect(await contract.methods.ownerOf(firstTokenId).call()).to.be.equal(targetNftTokenAddress);4445      // Create a token to be nested and nest46      const mintingSecondTokenIdResult = await contract.methods.mint(owner).send({from: owner});47      const secondTokenId = mintingSecondTokenIdResult.events.Transfer.returnValues.tokenId;4849      await contract.methods.transfer(targetNftTokenAddress, secondTokenId).send({from: owner});50      expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(targetNftTokenAddress);5152      // Unnest token back53      await contract.methods.transferFrom(targetNftTokenAddress, owner, secondTokenId).send({from: owner});54      expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(owner);55    });5657    itEth('NFT: collectionNesting()', async ({helper}) => {58      const owner = await helper.eth.createAccountWithBalance(donor);59      const {collectionAddress: unnestedCollectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');60      const unnestedContract = await helper.ethNativeContract.collection(unnestedCollectionAddress, 'nft', owner);61      expect(await unnestedContract.methods.collectionNesting().call({from: owner})).to.be.like([false, false, []]);6263      const {contract} = await createNestingCollection(helper, owner);64      expect(await contract.methods.collectionNesting().call({from: owner})).to.be.like([true, false, []]);65      await contract.methods.setCollectionNesting([true, false, [unnestedCollectionAddress]]).send({from: owner});66      expect(await contract.methods.collectionNesting().call({from: owner})).to.be.like([true, false, [unnestedCollectionAddress]]);67      await contract.methods.setCollectionNesting([false, true, [unnestedCollectionAddress]]).send({from: owner});68      expect(await contract.methods.collectionNesting().call({from: owner})).to.be.like([false, true, [unnestedCollectionAddress]]);69      await contract.methods.setCollectionNesting([false, false, []]).send({from: owner});70      expect(await contract.methods.collectionNesting().call({from: owner})).to.be.like([false, false, []]);71    });7273    // Sof-deprecated74    itEth('NFT: collectionNestingRestrictedCollectionIds() & collectionNestingPermissions', async ({helper}) => {75      const owner = await helper.eth.createAccountWithBalance(donor);76      const {collectionId: unnestedCollsectionId, collectionAddress: unnsetedCollectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');77      const unnestedContract = await helper.ethNativeContract.collection(unnsetedCollectionAddress, 'nft', owner, true);78      expect(await unnestedContract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([false, []]);7980      const {contract} = await createNestingCollection(helper, owner, true);81      expect(await contract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([true, []]);82      await contract.methods['setCollectionNesting(bool,address[])'](true, [unnsetedCollectionAddress]).send({from: owner});83      expect(await contract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([true, [unnestedCollsectionId.toString()]]);84      expect(await contract.methods.collectionNestingPermissions().call({from: owner})).to.be.like([['1', false], ['0', true]]);85      await contract.methods['setCollectionNesting(bool)'](false).send({from: owner});86      expect(await contract.methods.collectionNestingPermissions().call({from: owner})).to.be.like([['1', false], ['0', false]]);87    });8889    itEth('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {90      const owner = await helper.eth.createAccountWithBalance(donor);9192      const {collectionId: collectionIdA, contract: contractA} = await createNestingCollection(helper, owner);93      const {contract: contractB} = await createNestingCollection(helper, owner);94      await contractA.methods.setCollectionNesting([true, false, [contractA.options.address, contractB.options.address]]).send({from: owner});9596      // Create a token to nest into97      const mintingtargetNftTokenIdResult = await contractA.methods.mint(owner).send({from: owner});98      const targetNftTokenId = mintingtargetNftTokenIdResult.events.Transfer.returnValues.tokenId;99      const nftTokenAddressA1 = helper.ethAddress.fromTokenId(collectionIdA, targetNftTokenId);100101      // Create a token for nesting in the same collection as the target102      const mintingTokenIdAResult = await contractA.methods.mint(owner).send({from: owner});103      const nftTokenIdA = mintingTokenIdAResult.events.Transfer.returnValues.tokenId;104105      // Create a token for nesting in a different collection106      const mintingTokenIdBResult = await contractB.methods.mint(owner).send({from: owner});107      const nftTokenIdB = mintingTokenIdBResult.events.Transfer.returnValues.tokenId;108109      // Nest110      await contractA.methods.transfer(nftTokenAddressA1, nftTokenIdA).send({from: owner});111      expect(await contractA.methods.ownerOf(nftTokenIdA).call()).to.be.equal(nftTokenAddressA1);112113      await contractB.methods.transfer(nftTokenAddressA1, nftTokenIdB).send({from: owner});114      expect(await contractB.methods.ownerOf(nftTokenIdB).call()).to.be.equal(nftTokenAddressA1);115    });116  });117118  describe('Negative Test: EVM Nesting', () => {119    itEth('NFT: disallows to nest token if nesting is disabled', async ({helper}) => {120      const owner = await helper.eth.createAccountWithBalance(donor);121122      const {collectionId, contract} = await createNestingCollection(helper, owner);123      await contract.methods.setCollectionNesting([false, false, []]).send({from: owner});124125      // Create a token to nest into126      const mintingTargetTokenIdResult = await contract.methods.mint(owner).send({from: owner});127      const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;128      const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetTokenId);129130      // Create a token to nest131      const mintingNftTokenIdResult = await contract.methods.mint(owner).send({from: owner});132      const nftTokenId = mintingNftTokenIdResult.events.Transfer.returnValues.tokenId;133134      // Try to nest135      await expect(contract.methods136        .transfer(targetNftTokenAddress, nftTokenId)137        .call({from: owner})).to.be.rejectedWith('UserIsNotAllowedToNest');138    });139140    itEth('NFT: disallows a non-Owner to nest someone else\'s token', async ({helper}) => {141      const owner = await helper.eth.createAccountWithBalance(donor);142      const malignant = await helper.eth.createAccountWithBalance(donor);143144      const {collectionId, contract} = await createNestingCollection(helper, owner);145146      // Mint a token147      const mintingTargetTokenIdResult = await contract.methods.mint(owner).send({from: owner});148      const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;149      const targetTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetTokenId);150151      // Mint a token belonging to a different account152      const mintingTokenIdResult = await contract.methods.mint(malignant).send({from: owner});153      const tokenId = mintingTokenIdResult.events.Transfer.returnValues.tokenId;154155      // Try to nest one token in another as a non-owner account156      await expect(contract.methods157        .transfer(targetTokenAddress, tokenId)158        .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');159    });160161    itEth('NFT: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async ({helper}) => {162      const owner = await helper.eth.createAccountWithBalance(donor);163      const malignant = await helper.eth.createAccountWithBalance(donor);164165      const {collectionId: collectionIdA, contract: contractA} = await createNestingCollection(helper, owner);166      const {contract: contractB} = await createNestingCollection(helper, owner);167168      await contractA.methods.setCollectionNesting([true, false, [contractA.options.address, contractB.options.address]]).send({from: owner});169170      // Create a token in one collection171      const mintingTokenIdAResult = await contractA.methods.mint(owner).send({from: owner});172      const nftTokenIdA = mintingTokenIdAResult.events.Transfer.returnValues.tokenId;173      const nftTokenAddressA = helper.ethAddress.fromTokenId(collectionIdA, nftTokenIdA);174175      // Create a token in another collection176      const mintingTokenIdBResult = await contractB.methods.mint(malignant).send({from: owner});177      const nftTokenIdB = mintingTokenIdBResult.events.Transfer.returnValues.tokenId;178179      // Try to drag someone else's token into the other collection and nest180      await expect(contractB.methods181        .transfer(nftTokenAddressA, nftTokenIdB)182        .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');183    });184185    itEth('NFT: disallows to nest token in an unlisted collection', async ({helper}) => {186      const owner = await helper.eth.createAccountWithBalance(donor);187188      const {collectionId: collectionIdA, contract: contractA} = await createNestingCollection(helper, owner);189      const {contract: contractB} = await createNestingCollection(helper, owner);190191      await contractA.methods.setCollectionNesting([true, false, [contractA.options.address]]).send({from: owner});192193      // Create a token in one collection194      const mintingTokenIdAResult = await contractA.methods.mint(owner).send({from: owner});195      const nftTokenIdA = mintingTokenIdAResult.events.Transfer.returnValues.tokenId;196      const nftTokenAddressA = helper.ethAddress.fromTokenId(collectionIdA, nftTokenIdA);197198      // Create a token in another collection199      const mintingTokenIdBResult = await contractB.methods.mint(owner).send({from: owner});200      const nftTokenIdB = mintingTokenIdBResult.events.Transfer.returnValues.tokenId;201202203      // Try to nest into a token in the other collection, disallowed in the first204      await expect(contractB.methods205        .transfer(nftTokenAddressA, nftTokenIdB)206        .call()).to.be.rejectedWith('SourceCollectionIsNotAllowedToNest');207    });208  });209210  describe('Fungible', () => {211    async function createFungibleCollection(helper: EthUniqueHelper, owner: string, mode: 'ft' | 'native ft') {212      if(mode === 'ft') {213        const {collectionAddress} = await helper.eth.createFungibleCollection(owner, '', 18, '', '');214        const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner);215        await contract.methods.mint(owner, 100n).send({from: owner});216        return {collectionAddress, contract};217      }218219      // native ft220      const collectionAddress = helper.ethAddress.fromCollectionId(0);221      const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner);222      return {collectionAddress, contract};223    }224225    [226      {mode: 'ft' as const},227      {mode: 'native ft' as const},228    ].map(testCase => {229      itEth(`Allow nest [${testCase.mode}]`, async ({helper}) => {230        const owner = await helper.eth.createAccountWithBalance(donor);231        const {collectionId: targetCollectionId, contract: targetContract} = await createNestingCollection(helper, owner);232        const {contract: ftContract} = await createFungibleCollection(helper, owner, testCase.mode);233234        const mintingTargetTokenIdResult = await targetContract.methods.mint(owner).send({from: owner});235        const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;236        const targetTokenAddress = helper.ethAddress.fromTokenId(targetCollectionId, targetTokenId);237238        await ftContract.methods.transfer(targetTokenAddress, 10n).send({from: owner});239        expect(await ftContract.methods.balanceOf(targetTokenAddress).call({from: owner})).to.be.equal('10');240      });241    });242243    [244      {mode: 'ft' as const},245      {mode: 'native ft' as const},246    ].map(testCase => {247      itEth(`Allow partial/full unnest [${testCase.mode}]`, async ({helper}) => {248        const owner = await helper.eth.createAccountWithBalance(donor);249        const {collectionId: targetCollectionId, contract: targetContract} = await createNestingCollection(helper, owner);250        const {contract: ftContract} = await createFungibleCollection(helper, owner, testCase.mode);251252        const mintingTargetTokenIdResult = await targetContract.methods.mint(owner).send({from: owner});253        const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;254        const targetTokenAddress = helper.ethAddress.fromTokenId(targetCollectionId, targetTokenId);255256        await ftContract.methods.transfer(targetTokenAddress, 10n).send({from: owner});257258        await ftContract.methods.transferFrom(targetTokenAddress, owner, 5n).send({from: owner});259        expect(await ftContract.methods.balanceOf(targetTokenAddress).call({from: owner})).to.be.equal('5');260261        await ftContract.methods.transferFrom(targetTokenAddress, owner, 5n).send({from: owner});262        expect(await ftContract.methods.balanceOf(targetTokenAddress).call({from: owner})).to.be.equal('0');263      });264    });265266    [267      {mode: 'ft' as const},268      {mode: 'native ft' as const},269    ].map(testCase => {270      itEth(`Disallow nest into collection without nesting permission [${testCase.mode}] (except for native fungible collection)`, async ({helper}) => {271        const owner = await helper.eth.createAccountWithBalance(donor);272        const {collectionId: targetCollectionId, contract: targetContract} = await createNestingCollection(helper, owner);273        await targetContract.methods.setCollectionNesting([false, false, []]).send({from: owner});274275        const {contract: ftContract} = await createFungibleCollection(helper, owner, testCase.mode);276277        const mintingTargetTokenIdResult = await targetContract.methods.mint(owner).send({from: owner});278        const targetTokenId = mintingTargetTokenIdResult.events.Transfer.returnValues.tokenId;279        const targetTokenAddress = helper.ethAddress.fromTokenId(targetCollectionId, targetTokenId);280281        if(testCase.mode === 'ft') {282          await expect(ftContract.methods.transfer(targetTokenAddress, 10n).call({from: owner})).to.be.rejectedWith('UserIsNotAllowedToNest');283        } else {284          await expect(ftContract.methods.transfer(targetTokenAddress, 10n).call({from: owner})).to.be.not.rejected;285        }286      });287    });288  });289});