1import {IKeyringPair} from '@polkadot/types/types';2import {Contract} from 'web3-eth-contract';34import {itEth, EthUniqueHelper, usingEthPlaygrounds, expect} from '../util/playgrounds';56const createNestingCollection = async (7 helper: EthUniqueHelper,8 owner: string,9): Promise<{ collectionId: number, collectionAddress: string, contract: Contract }> => {10 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');1112 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);13 await contract.methods.setCollectionNesting(true).send({from: owner});1415 return {collectionId, collectionAddress, contract};16};171819describe('EVM nesting tests group', () => {20 let donor: IKeyringPair;2122 before(async function() {23 await usingEthPlaygrounds(async (_, privateKey) => {24 donor = privateKey('//Alice');25 });26 });2728 describe('Integration Test: EVM Nesting', () => {29 itEth('NFT: allows an Owner to nest/unnest their token', async ({helper}) => {30 const owner = await helper.eth.createAccountWithBalance(donor);31 const {collectionId, contract} = await createNestingCollection(helper, owner);32 33 34 const targetNFTTokenId = await contract.methods.nextTokenId().call();35 await contract.methods.mint(36 owner,37 targetNFTTokenId,38 ).send({from: owner});39 40 const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetNFTTokenId);41 42 43 const firstTokenId = await contract.methods.nextTokenId().call();44 await contract.methods.mint(45 targetNftTokenAddress,46 firstTokenId,47 ).send({from: owner});48 49 expect(await contract.methods.ownerOf(firstTokenId).call()).to.be.equal(targetNftTokenAddress);50 51 52 const secondTokenId = await contract.methods.nextTokenId().call();53 await contract.methods.mint(54 owner,55 secondTokenId,56 ).send({from: owner});57 58 await contract.methods.transfer(targetNftTokenAddress, secondTokenId).send({from: owner});59 60 expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(targetNftTokenAddress);61 62 63 await contract.methods.transferFrom(targetNftTokenAddress, owner, secondTokenId).send({from: owner});64 expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(owner);65 });66 67 itEth('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {68 const owner = await helper.eth.createAccountWithBalance(donor);69 70 const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);71 const {collectionAddress: collectionAddressB, contract: contractB} = await createNestingCollection(helper, owner);72 await contractA.methods.setCollectionNesting(true, [collectionAddressA, collectionAddressB]).send({from: owner});73 74 75 const targetNftTokenId = await contractA.methods.nextTokenId().call();76 await contractA.methods.mint(77 owner,78 targetNftTokenId,79 ).send({from: owner});80 const nftTokenAddressA1 = helper.ethAddress.fromTokenId(collectionIdA, targetNftTokenId);81 82 83 const nftTokenIdA = await contractA.methods.nextTokenId().call();84 await contractA.methods.mint(85 owner,86 nftTokenIdA,87 ).send({from: owner});88 89 90 const nftTokenIdB = await contractB.methods.nextTokenId().call();91 await contractB.methods.mint(92 owner,93 nftTokenIdB,94 ).send({from: owner});95 96 97 await contractA.methods.transfer(nftTokenAddressA1, nftTokenIdA).send({from: owner});98 expect(await contractA.methods.ownerOf(nftTokenIdA).call()).to.be.equal(nftTokenAddressA1);99 100 await contractB.methods.transfer(nftTokenAddressA1, nftTokenIdB).send({from: owner});101 expect(await contractB.methods.ownerOf(nftTokenIdB).call()).to.be.equal(nftTokenAddressA1);102 });103 });104105 describe('Negative Test: EVM Nesting', async() => {106 itEth('NFT: disallows to nest token if nesting is disabled', async ({helper}) => {107 const owner = await helper.eth.createAccountWithBalance(donor);108 109 const {collectionId, contract} = await createNestingCollection(helper, owner);110 await contract.methods.setCollectionNesting(false).send({from: owner});111 112 113 const targetNftTokenId = await contract.methods.nextTokenId().call();114 await contract.methods.mint(115 owner,116 targetNftTokenId,117 ).send({from: owner});118 119 const targetNftTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetNftTokenId);120 121 122 const nftTokenId = await contract.methods.nextTokenId().call();123 await contract.methods.mint(124 owner,125 nftTokenId,126 ).send({from: owner});127 128 129 await expect(contract.methods130 .transfer(targetNftTokenAddress, nftTokenId)131 .call({from: owner})).to.be.rejectedWith('UserIsNotAllowedToNest');132 });133 134 itEth('NFT: disallows a non-Owner to nest someone else\'s token', async ({helper}) => {135 const owner = await helper.eth.createAccountWithBalance(donor);136 const malignant = await helper.eth.createAccountWithBalance(donor);137 138 const {collectionId, contract} = await createNestingCollection(helper, owner);139 140 141 const targetTokenId = await contract.methods.nextTokenId().call();142 await contract.methods.mint(143 owner,144 targetTokenId,145 ).send({from: owner});146 const targetTokenAddress = helper.ethAddress.fromTokenId(collectionId, targetTokenId);147 148 149 const tokenId = await contract.methods.nextTokenId().call();150 await contract.methods.mint(151 malignant,152 tokenId,153 ).send({from: owner});154 155 156 await expect(contract.methods157 .transfer(targetTokenAddress, tokenId)158 .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');159 });160 161 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);164 165 const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);166 const {collectionAddress: collectionAddressB, contract: contractB} = await createNestingCollection(helper, owner);167 168 await contractA.methods.setCollectionNesting(true, [collectionAddressA, collectionAddressB]).send({from: owner});169 170 171 const nftTokenIdA = await contractA.methods.nextTokenId().call();172 await contractA.methods.mint(173 owner,174 nftTokenIdA,175 ).send({from: owner});176 const nftTokenAddressA = helper.ethAddress.fromTokenId(collectionIdA, nftTokenIdA);177 178 179 const nftTokenIdB = await contractB.methods.nextTokenId().call();180 await contractB.methods.mint(181 malignant,182 nftTokenIdB,183 ).send({from: owner});184 185 186 await expect(contractB.methods187 .transfer(nftTokenAddressA, nftTokenIdB)188 .call({from: malignant})).to.be.rejectedWith('UserIsNotAllowedToNest');189 });190 191 itEth('NFT: disallows to nest token in an unlisted collection', async ({helper}) => {192 const owner = await helper.eth.createAccountWithBalance(donor);193 194 const {collectionId: collectionIdA, collectionAddress: collectionAddressA, contract: contractA} = await createNestingCollection(helper, owner);195 const {contract: contractB} = await createNestingCollection(helper, owner);196 197 await contractA.methods.setCollectionNesting(true, [collectionAddressA]).send({from: owner});198 199 200 const nftTokenIdA = await contractA.methods.nextTokenId().call();201 await contractA.methods.mint(202 owner,203 nftTokenIdA,204 ).send({from: owner});205 const nftTokenAddressA = helper.ethAddress.fromTokenId(collectionIdA, nftTokenIdA);206 207 208 const nftTokenIdB = await contractB.methods.nextTokenId().call();209 await contractB.methods.mint(210 owner,211 nftTokenIdB,212 ).send({from: owner});213 214 215 await expect(contractB.methods216 .transfer(nftTokenAddressA, nftTokenIdB)217 .call()).to.be.rejectedWith('SourceCollectionIsNotAllowedToNest');218 });219 });220});