git.delta.rocks / unique-network / refs/commits / 37762c5cf403

difftreelog

rename: WhiteList to AllowList

Igor Kozyrev2021-11-16parent: #2eb1073.patch.diff
in: master

1 file changed

modifiedtests/src/eth/marketplace/marketplace.test.tsdiffbeforeafterboth
before · tests/src/eth/marketplace/marketplace.test.ts
1import {readFile} from 'fs/promises';2import {getBalanceSingle, transferBalanceExpectSuccess} from '../../substrate/get-balance';3import privateKey from '../../substrate/privateKey';4import {addToWhiteListExpectSuccess, confirmSponsorshipExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, getTokenOwner, setCollectionSponsorExpectSuccess, transferExpectSuccess, transferFromExpectSuccess} from '../../util/helpers';5import {collectionIdToAddress, contractHelpers, createEthAccountWithBalance, executeEthTxOnSub, GAS_ARGS, itWeb3, subToEth, subToEthLowercase} from '../util/helpers';6import {evmToAddress} from '@polkadot/util-crypto';7import nonFungibleAbi from '../nonFungibleAbi.json';8import fungibleAbi from '../fungibleAbi.json';9import {expect} from 'chai';1011const PRICE = 2000n;1213describe.only('Matcher contract usage', () => {14  itWeb3('With UNQ', async ({api, web3}) => {15    const matcherOwner = await createEthAccountWithBalance(api, web3);16    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {17      from: matcherOwner,18      ...GAS_ARGS,19    });20    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments:[matcherOwner]}).send({from: matcherOwner});21    const helpers = contractHelpers(web3, matcherOwner);22    await helpers.methods.toggleSponsoring(matcher.options.address, true).send({from: matcherOwner});23    await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});2425    const alice = privateKey('//Alice');26    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});27    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});28    await setCollectionSponsorExpectSuccess(collectionId, alice.address);29    await confirmSponsorshipExpectSuccess(collectionId);3031    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(alice.address), true).send({from: matcherOwner});32    await addToWhiteListExpectSuccess(alice, collectionId, evmToAddress(subToEth(alice.address)));3334    const seller = privateKey('//Bob');35    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(seller.address), true).send({from: matcherOwner});36    await addToWhiteListExpectSuccess(alice, collectionId, evmToAddress(subToEth(seller.address)));3738    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);3940    // To transfer item to matcher it first needs to be transfered to EVM account of bob41    await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});4243    // Token is owned by seller initially44    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});4546    // Ask47    {48      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));49      await executeEthTxOnSub(api, seller, matcher, m => m.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, tokenId));50    }5152    // Token is transferred to matcher53    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});5455    // Buy56    {57      const sellerBalanceBeforePurchase = await getBalanceSingle(api, seller.address);58      // There is two functions named 'buy', so we should provide full signature59      await executeEthTxOnSub(api, alice, matcher, m => m['buy(address,uint256)'](evmCollection.options.address, tokenId), {value: PRICE});60      expect(await getBalanceSingle(api, seller.address) - sellerBalanceBeforePurchase === PRICE);61    }6263    // Token is transferred to evm account of alice64    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(alice.address)});656667    // Transfer token to substrate side of alice68    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: subToEth(alice.address)}, {Substrate: alice.address});6970    // Token is transferred to substrate account of alice, seller received funds71    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Substrate: alice.address});72  });7374  // selling for custom tokens excluded from release75  itWeb3.skip('With custom ERC20', async ({api, web3}) => {76    const matcherOwner = await createEthAccountWithBalance(api, web3);77    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {78      from: matcherOwner,79      ...GAS_ARGS,80    });81    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments: [matcherOwner]}).send({from: matcherOwner});8283    const alice = privateKey('//Alice');84    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});85    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});8687    const fungibleId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});88    const evmFungible = new web3.eth.Contract(fungibleAbi as any, collectionIdToAddress(fungibleId), {from: matcherOwner, ...GAS_ARGS});89    await createFungibleItemExpectSuccess(alice, fungibleId, {Value: PRICE}, {Ethereum: subToEth(alice.address)});9091    const seller = privateKey('//Bob');9293    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);9495    // To transfer item to matcher it first needs to be transfered to EVM account of bob96    await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});97    // Fees will be paid from EVM account, so we should have some balance here98    await transferBalanceExpectSuccess(api, seller, evmToAddress(subToEth(seller.address)), 10n ** 18n);99    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), 10n ** 18n);100101    // Token is owned by seller initially102    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});103104    // Ask105    {106      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));107      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, evmFungible.options.address, evmCollection.options.address, tokenId, 1));108    }109110    // Token is transferred to matcher111    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});112113    // Buy114    {115      const sellerBalanceBeforePurchase = BigInt(await evmFungible.methods.balanceOf(subToEth(seller.address)).call());116      const buyerBalanceBeforePurchase = BigInt(await evmFungible.methods.balanceOf(subToEth(alice.address)).call());117118      await executeEthTxOnSub(api, alice, evmFungible, m => m.approve(matcher.options.address, PRICE));119      // There is two functions named 'buy', so we should provide full signature120      await executeEthTxOnSub(api, alice, matcher, m =>121        m['buy(address,uint256,address,uint256)'](evmCollection.options.address, tokenId, evmFungible.options.address, PRICE));122123      // Approved price is removed from buyer balance, and added to seller124      expect(BigInt(await evmFungible.methods.balanceOf(subToEth(seller.address)).call()) - sellerBalanceBeforePurchase === PRICE);125      expect(buyerBalanceBeforePurchase - BigInt(await evmFungible.methods.balanceOf(subToEth(alice.address)).call()) === PRICE);126    }127128    // Token is transferred to evm account of alice129    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(alice.address)});130131132    // Transfer token to substrate side of alice133    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: subToEth(alice.address)}, {Substrate: alice.address});134135    // Token is transferred to substrate account of alice136    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Substrate: alice.address});137  });138139  itWeb3('With escrow', async ({api, web3}) => {140    const matcherOwner = await createEthAccountWithBalance(api, web3);141    const escrow = await createEthAccountWithBalance(api, web3);142    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {143      from: matcherOwner,144      ...GAS_ARGS,145    });146    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments: [matcherOwner]}).send({from: matcherOwner});147    await matcher.methods.setEscrow(escrow).send({from: matcherOwner});148    const helpers = contractHelpers(web3, matcherOwner);149    await helpers.methods.toggleSponsoring(matcher.options.address, true).send({from: matcherOwner});150    await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});151152    const alice = privateKey('//Alice');153    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});154    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});155    await setCollectionSponsorExpectSuccess(collectionId, alice.address);156    await confirmSponsorshipExpectSuccess(collectionId);157158    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(alice.address), true).send({from: matcherOwner});159    await addToWhiteListExpectSuccess(alice, collectionId, evmToAddress(subToEth(alice.address)));160161    const seller = privateKey('//Bob');162    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(seller.address), true).send({from: matcherOwner});163    await addToWhiteListExpectSuccess(alice, collectionId, evmToAddress(subToEth(seller.address)));164165    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);166167    // To transfer item to matcher it first needs to be transfered to EVM account of bob168    await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});169170    // Token is owned by seller initially171    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});172173    // Ask174    {175      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));176      await executeEthTxOnSub(api, seller, matcher, m => m.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, tokenId));177    }178179    // Token is transferred to matcher180    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});181182    // Give buyer KSM183    await matcher.methods.depositKSM(PRICE, subToEth(alice.address)).send({from: escrow});184185    // Buy186    {187      expect(await matcher.methods.balanceKSM(subToEth(seller.address)).call()).to.be.equal('0');188      expect(await matcher.methods.balanceKSM(subToEth(alice.address)).call()).to.be.equal(PRICE.toString());189190      await executeEthTxOnSub(api, alice, matcher, m => m.buyKSM(evmCollection.options.address, tokenId, subToEth(alice.address), subToEth(alice.address)));191192      // Price is removed from buyer balance, and added to seller193      expect(await matcher.methods.balanceKSM(subToEth(alice.address)).call()).to.be.equal('0');194      expect(await matcher.methods.balanceKSM(subToEth(seller.address)).call()).to.be.equal(PRICE.toString());195    }196197    // Token is transferred to evm account of alice198    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(alice.address)});199200    // Transfer token to substrate side of alice201    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: subToEth(alice.address)}, {Substrate: alice.address});202203    // Token is transferred to substrate account of alice, seller received funds204    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Substrate: alice.address});205  });206});
after · tests/src/eth/marketplace/marketplace.test.ts
1import {readFile} from 'fs/promises';2import {getBalanceSingle, transferBalanceExpectSuccess} from '../../substrate/get-balance';3import privateKey from '../../substrate/privateKey';4import {addToAllowListExpectSuccess, confirmSponsorshipExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, getTokenOwner, setCollectionSponsorExpectSuccess, transferExpectSuccess, transferFromExpectSuccess} from '../../util/helpers';5import {collectionIdToAddress, contractHelpers, createEthAccountWithBalance, executeEthTxOnSub, GAS_ARGS, itWeb3, subToEth, subToEthLowercase} from '../util/helpers';6import {evmToAddress} from '@polkadot/util-crypto';7import nonFungibleAbi from '../nonFungibleAbi.json';8import fungibleAbi from '../fungibleAbi.json';9import {expect} from 'chai';1011const PRICE = 2000n;1213describe.only('Matcher contract usage', () => {14  itWeb3('With UNQ', async ({api, web3}) => {15    const matcherOwner = await createEthAccountWithBalance(api, web3);16    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {17      from: matcherOwner,18      ...GAS_ARGS,19    });20    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments:[matcherOwner]}).send({from: matcherOwner});21    const helpers = contractHelpers(web3, matcherOwner);22    await helpers.methods.toggleSponsoring(matcher.options.address, true).send({from: matcherOwner});23    await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});2425    const alice = privateKey('//Alice');26    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});27    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});28    await setCollectionSponsorExpectSuccess(collectionId, alice.address);29    await confirmSponsorshipExpectSuccess(collectionId);3031    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(alice.address), true).send({from: matcherOwner});32    await addAllowListExpectSuccess(alice, collectionId, evmToAddress(subToEth(alice.address)));3334    const seller = privateKey('//Bob');35    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(seller.address), true).send({from: matcherOwner});36    await addToAllowListExpectSuccess(alice, collectionId, evmToAddress(subToEth(seller.address)));3738    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);3940    // To transfer item to matcher it first needs to be transfered to EVM account of bob41    await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});4243    // Token is owned by seller initially44    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});4546    // Ask47    {48      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));49      await executeEthTxOnSub(api, seller, matcher, m => m.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, tokenId));50    }5152    // Token is transferred to matcher53    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});5455    // Buy56    {57      const sellerBalanceBeforePurchase = await getBalanceSingle(api, seller.address);58      // There is two functions named 'buy', so we should provide full signature59      await executeEthTxOnSub(api, alice, matcher, m => m['buy(address,uint256)'](evmCollection.options.address, tokenId), {value: PRICE});60      expect(await getBalanceSingle(api, seller.address) - sellerBalanceBeforePurchase === PRICE);61    }6263    // Token is transferred to evm account of alice64    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(alice.address)});656667    // Transfer token to substrate side of alice68    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: subToEth(alice.address)}, {Substrate: alice.address});6970    // Token is transferred to substrate account of alice, seller received funds71    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Substrate: alice.address});72  });7374  // selling for custom tokens excluded from release75  itWeb3.skip('With custom ERC20', async ({api, web3}) => {76    const matcherOwner = await createEthAccountWithBalance(api, web3);77    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {78      from: matcherOwner,79      ...GAS_ARGS,80    });81    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments: [matcherOwner]}).send({from: matcherOwner});8283    const alice = privateKey('//Alice');84    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});85    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});8687    const fungibleId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});88    const evmFungible = new web3.eth.Contract(fungibleAbi as any, collectionIdToAddress(fungibleId), {from: matcherOwner, ...GAS_ARGS});89    await createFungibleItemExpectSuccess(alice, fungibleId, {Value: PRICE}, {Ethereum: subToEth(alice.address)});9091    const seller = privateKey('//Bob');9293    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);9495    // To transfer item to matcher it first needs to be transfered to EVM account of bob96    await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});97    // Fees will be paid from EVM account, so we should have some balance here98    await transferBalanceExpectSuccess(api, seller, evmToAddress(subToEth(seller.address)), 10n ** 18n);99    await transferBalanceExpectSuccess(api, alice, evmToAddress(subToEth(alice.address)), 10n ** 18n);100101    // Token is owned by seller initially102    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});103104    // Ask105    {106      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));107      await executeEthTxOnSub(api, seller, matcher, m => m.setAsk(PRICE, evmFungible.options.address, evmCollection.options.address, tokenId, 1));108    }109110    // Token is transferred to matcher111    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});112113    // Buy114    {115      const sellerBalanceBeforePurchase = BigInt(await evmFungible.methods.balanceOf(subToEth(seller.address)).call());116      const buyerBalanceBeforePurchase = BigInt(await evmFungible.methods.balanceOf(subToEth(alice.address)).call());117118      await executeEthTxOnSub(api, alice, evmFungible, m => m.approve(matcher.options.address, PRICE));119      // There is two functions named 'buy', so we should provide full signature120      await executeEthTxOnSub(api, alice, matcher, m =>121        m['buy(address,uint256,address,uint256)'](evmCollection.options.address, tokenId, evmFungible.options.address, PRICE));122123      // Approved price is removed from buyer balance, and added to seller124      expect(BigInt(await evmFungible.methods.balanceOf(subToEth(seller.address)).call()) - sellerBalanceBeforePurchase === PRICE);125      expect(buyerBalanceBeforePurchase - BigInt(await evmFungible.methods.balanceOf(subToEth(alice.address)).call()) === PRICE);126    }127128    // Token is transferred to evm account of alice129    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(alice.address)});130131132    // Transfer token to substrate side of alice133    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: subToEth(alice.address)}, {Substrate: alice.address});134135    // Token is transferred to substrate account of alice136    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Substrate: alice.address});137  });138139  itWeb3('With escrow', async ({api, web3}) => {140    const matcherOwner = await createEthAccountWithBalance(api, web3);141    const escrow = await createEthAccountWithBalance(api, web3);142    const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {143      from: matcherOwner,144      ...GAS_ARGS,145    });146    const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments: [matcherOwner]}).send({from: matcherOwner});147    await matcher.methods.setEscrow(escrow).send({from: matcherOwner});148    const helpers = contractHelpers(web3, matcherOwner);149    await helpers.methods.toggleSponsoring(matcher.options.address, true).send({from: matcherOwner});150    await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});151152    const alice = privateKey('//Alice');153    const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});154    const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});155    await setCollectionSponsorExpectSuccess(collectionId, alice.address);156    await confirmSponsorshipExpectSuccess(collectionId);157158    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(alice.address), true).send({from: matcherOwner});159    await addToAllowListExpectSuccess(alice, collectionId, evmToAddress(subToEth(alice.address)));160161    const seller = privateKey('//Bob');162    await helpers.methods.toggleAllowed(matcher.options.address, subToEth(seller.address), true).send({from: matcherOwner});163    await addToAllowListExpectSuccess(alice, collectionId, evmToAddress(subToEth(seller.address)));164165    const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);166167    // To transfer item to matcher it first needs to be transfered to EVM account of bob168    await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});169170    // Token is owned by seller initially171    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});172173    // Ask174    {175      await executeEthTxOnSub(api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));176      await executeEthTxOnSub(api, seller, matcher, m => m.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, tokenId));177    }178179    // Token is transferred to matcher180    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});181182    // Give buyer KSM183    await matcher.methods.depositKSM(PRICE, subToEth(alice.address)).send({from: escrow});184185    // Buy186    {187      expect(await matcher.methods.balanceKSM(subToEth(seller.address)).call()).to.be.equal('0');188      expect(await matcher.methods.balanceKSM(subToEth(alice.address)).call()).to.be.equal(PRICE.toString());189190      await executeEthTxOnSub(api, alice, matcher, m => m.buyKSM(evmCollection.options.address, tokenId, subToEth(alice.address), subToEth(alice.address)));191192      // Price is removed from buyer balance, and added to seller193      expect(await matcher.methods.balanceKSM(subToEth(alice.address)).call()).to.be.equal('0');194      expect(await matcher.methods.balanceKSM(subToEth(seller.address)).call()).to.be.equal(PRICE.toString());195    }196197    // Token is transferred to evm account of alice198    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(alice.address)});199200    // Transfer token to substrate side of alice201    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: subToEth(alice.address)}, {Substrate: alice.address});202203    // Token is transferred to substrate account of alice, seller received funds204    expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Substrate: alice.address});205  });206});