git.delta.rocks / unique-network / refs/commits / e4eea6c1f0ba

difftreelog

source

js-packages/tests/eth/fractionalizer/fractionalizer.test.ts23.9 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161718import {readFile} from 'fs/promises';1920import type {IKeyringPair} from '@polkadot/types/types';21import {evmToAddress} from '@polkadot/util-crypto';2223import {Contract} from 'web3-eth-contract';2425import {usingEthPlaygrounds, expect, itEth} from '../util/index.js';26import {EthUniqueHelper} from '../util/playgrounds/unique.dev.js';27import type {CompiledContract} from '../util/playgrounds/types.js';28import {requirePalletsOrSkip, Pallets, makeNames} from '@unique/test-utils/util.js';2930const {dirname} = makeNames(import.meta.url);3132let compiledFractionalizer: CompiledContract;3334const compileContract = async (helper: EthUniqueHelper): Promise<CompiledContract> => {35  if(!compiledFractionalizer) {36    compiledFractionalizer = await helper.ethContract.compile('Fractionalizer', (await readFile(`${dirname}/Fractionalizer.sol`)).toString(), [37      {solPath: 'api/CollectionHelpers.sol', fsPath: `${dirname}/../api/CollectionHelpers.sol`},38      {solPath: 'api/ContractHelpers.sol', fsPath: `${dirname}/../api/ContractHelpers.sol`},39      {solPath: 'api/UniqueRefungibleToken.sol', fsPath: `${dirname}/../api/UniqueRefungibleToken.sol`},40      {solPath: 'api/UniqueRefungible.sol', fsPath: `${dirname}/../api/UniqueRefungible.sol`},41      {solPath: 'api/UniqueNFT.sol', fsPath: `${dirname}/../api/UniqueNFT.sol`},42    ]);43  }44  return compiledFractionalizer;45};464748const deployContract = async (helper: EthUniqueHelper, owner: string): Promise<Contract> => {49  const compiled = await compileContract(helper);50  return await helper.ethContract.deployByAbi(owner, compiled.abi, compiled.object);51};525354const initContract = async (helper: EthUniqueHelper, owner: string): Promise<{contract: Contract, rftCollectionAddress: string}> => {55  const fractionalizer = await deployContract(helper, owner);56  const amount = 10n * helper.balance.getOneTokenNominal();57  const web3 = helper.getWeb3();58  await web3.eth.sendTransaction({from: owner, to: fractionalizer.options.address, value: `${amount}`, gas: helper.eth.DEFAULT_GAS});59  const result = await fractionalizer.methods.createAndSetRFTCollection('A', 'B', 'C').send({value: Number(2n * helper.balance.getOneTokenNominal())});60  const rftCollectionAddress = result.events.RFTCollectionSet.returnValues._collection;61  return {contract: fractionalizer, rftCollectionAddress};62};6364const mintRFTToken = async (helper: EthUniqueHelper, owner: string, fractionalizer: Contract, amount: bigint): Promise<{65  nftCollectionAddress: string, nftTokenId: number, rftTokenAddress: string66}> => {67  const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');68  const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);69  const mintResult = await nftContract.methods.mint(owner).send({from: owner});70  const nftTokenId = mintResult.events.Transfer.returnValues.tokenId;7172  await fractionalizer.methods.setNftCollectionIsAllowed(nftCollection.collectionAddress, true).send({from: owner});73  await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send({from: owner});74  const result = await fractionalizer.methods.nft2rft(nftCollection.collectionAddress, nftTokenId, amount).send({from: owner});75  const {_collection, _tokenId, _rftToken} = result.events.Fractionalized.returnValues;76  return {77    nftCollectionAddress: _collection,78    nftTokenId: _tokenId,79    rftTokenAddress: _rftToken,80  };81};828384describe('Fractionalizer contract usage', () => {85  let donor: IKeyringPair;8687  before(async function() {88    await usingEthPlaygrounds(async (helper: EthUniqueHelper, privateKey) => {89      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);90      donor = await privateKey({url: import.meta.url});91    });92  });9394  itEth('Set RFT collection', async ({helper}) => {95    const owner = await helper.eth.createAccountWithBalance(donor);96    const fractionalizer = await deployContract(helper, owner);97    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');98    const rftContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);99100    const fractionalizerAddressCross = helper.ethCrossAccount.fromAddress(fractionalizer.options.address);101    await rftContract.methods.addCollectionAdminCross(fractionalizerAddressCross).send({from: owner});102    const result = await fractionalizer.methods.setRFTCollection(rftCollection.collectionAddress).send({from: owner});103    expect(result.events).to.be.like({104      RFTCollectionSet: {105        returnValues: {106          _collection: rftCollection.collectionAddress,107        },108      },109    });110  });111112  itEth('Mint RFT collection', async ({helper}) => {113    const owner = await helper.eth.createAccountWithBalance(donor);114    const fractionalizer = await deployContract(helper, owner);115    await helper.balance.transferToSubstrate(donor, evmToAddress(fractionalizer.options.address), 10n * helper.balance.getOneTokenNominal());116117    const result = await fractionalizer.methods.createAndSetRFTCollection('A', 'B', 'C').send({from: owner, value: Number(2n * helper.balance.getOneTokenNominal())});118    expect(result.events).to.be.like({119      RFTCollectionSet: {},120    });121    expect(result.events.RFTCollectionSet.returnValues._collection).to.be.ok;122  });123124  itEth('Set Allowlist', async ({helper}) => {125    const owner = await helper.eth.createAccountWithBalance(donor);126    const {contract: fractionalizer} = await initContract(helper, owner);127    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');128129    const result1 = await fractionalizer.methods.setNftCollectionIsAllowed(nftCollection.collectionAddress, true).send({from: owner});130    expect(result1.events).to.be.like({131      AllowListSet: {132        returnValues: {133          _collection: nftCollection.collectionAddress,134          _status: true,135        },136      },137    });138    const result2 = await fractionalizer.methods.setNftCollectionIsAllowed(nftCollection.collectionAddress, false).send({from: owner});139    expect(result2.events).to.be.like({140      AllowListSet: {141        returnValues: {142          _collection: nftCollection.collectionAddress,143          _status: false,144        },145      },146    });147  });148149  itEth('NFT to RFT', async ({helper}) => {150    const owner = await helper.eth.createAccountWithBalance(donor);151152    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');153    const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);154    const mintResult = await nftContract.methods.mint(owner).send({from: owner});155    const nftTokenId = mintResult.events.Transfer.returnValues.tokenId;156157    const {contract: fractionalizer} = await initContract(helper, owner);158159    await fractionalizer.methods.setNftCollectionIsAllowed(nftCollection.collectionAddress, true).send({from: owner});160    await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send({from: owner});161    const result = await fractionalizer.methods.nft2rft(nftCollection.collectionAddress, nftTokenId, 100).send({from: owner});162    expect(result.events).to.be.like({163      Fractionalized: {164        returnValues: {165          _collection: nftCollection.collectionAddress,166          _tokenId: nftTokenId,167          _amount: '100',168        },169      },170    });171    const rftTokenAddress = result.events.Fractionalized.returnValues._rftToken;172173    // FIXME: should work without the caller174    const rftTokenContract = helper.ethNativeContract.rftToken(rftTokenAddress);175    expect(await rftTokenContract.methods.balanceOf(owner).call()).to.equal('100');176  });177178  itEth('RFT to NFT', async ({helper}) => {179    const owner = await helper.eth.createAccountWithBalance(donor);180181    const {contract: fractionalizer, rftCollectionAddress} = await initContract(helper, owner);182    const {rftTokenAddress, nftCollectionAddress, nftTokenId} = await mintRFTToken(helper, owner, fractionalizer, 100n);183184    const {collectionId, tokenId} = helper.ethAddress.extractTokenId(rftTokenAddress);185    const refungibleAddress = helper.ethAddress.fromCollectionId(collectionId);186    expect(rftCollectionAddress).to.be.equal(refungibleAddress);187    const refungibleTokenContract = await helper.ethNativeContract.rftToken(rftTokenAddress, owner);188    await refungibleTokenContract.methods.approve(fractionalizer.options.address, 100).send({from: owner});189    const result = await fractionalizer.methods.rft2nft(refungibleAddress, tokenId).send({from: owner});190    expect(result.events).to.be.like({191      Defractionalized: {192        returnValues: {193          _rftToken: rftTokenAddress,194          _nftCollection: nftCollectionAddress,195          _nftTokenId: nftTokenId,196        },197      },198    });199  });200201  itEth('Test fractionalizer NFT <-> RFT mapping ', async ({helper}) => {202    const owner = await helper.eth.createAccountWithBalance(donor);203204    const {contract: fractionalizer, rftCollectionAddress} = await initContract(helper, owner);205    const {rftTokenAddress, nftCollectionAddress, nftTokenId} = await mintRFTToken(helper, owner, fractionalizer, 100n);206207    const {collectionId, tokenId} = helper.ethAddress.extractTokenId(rftTokenAddress);208    const refungibleAddress = helper.ethAddress.fromCollectionId(collectionId);209    expect(rftCollectionAddress).to.be.equal(refungibleAddress);210    const refungibleTokenContract = await helper.ethNativeContract.rftToken(rftTokenAddress, owner);211    await refungibleTokenContract.methods.approve(fractionalizer.options.address, 100).send({from: owner});212213    const rft2nft = await fractionalizer.methods.rft2nftMapping(rftTokenAddress).call();214    expect(rft2nft).to.be.like({215      _collection: nftCollectionAddress,216      _tokenId: nftTokenId,217    });218219    const nft2rft = await fractionalizer.methods.nft2rftMapping(nftCollectionAddress, nftTokenId).call();220    expect(nft2rft).to.be.eq(tokenId.toString());221  });222});223224225226describe('Negative Integration Tests for fractionalizer', () => {227  let donor: IKeyringPair;228229  before(async function() {230    await usingEthPlaygrounds(async (helper: EthUniqueHelper, privateKey) => {231      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);232      donor = await privateKey({url: import.meta.url});233    });234  });235236  itEth('call setRFTCollection twice', async ({helper}) => {237    const owner = await helper.eth.createAccountWithBalance(donor);238    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');239    const refungibleContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);240241    const fractionalizer = await deployContract(helper, owner);242    const fractionalizerAddressCross = helper.ethCrossAccount.fromAddress(fractionalizer.options.address);243    await refungibleContract.methods.addCollectionAdminCross(fractionalizerAddressCross).send({from: owner});244    await fractionalizer.methods.setRFTCollection(rftCollection.collectionAddress).send({from: owner});245246    await expect(fractionalizer.methods.setRFTCollection(rftCollection.collectionAddress).call())247      .to.be.rejectedWith(/RFT collection is already set$/g);248  });249250  itEth('call setRFTCollection with NFT collection', async ({helper}) => {251    const owner = await helper.eth.createAccountWithBalance(donor);252    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');253    const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);254255    const fractionalizer = await deployContract(helper, owner);256    const fractionalizerAddressCross = helper.ethCrossAccount.fromAddress(fractionalizer.options.address);257    await nftContract.methods.addCollectionAdminCross(fractionalizerAddressCross).send({from: owner});258259    await expect(fractionalizer.methods.setRFTCollection(nftCollection.collectionAddress).call())260      .to.be.rejectedWith(/Wrong collection type. Collection is not refungible.$/g);261  });262263  itEth('call setRFTCollection while not collection admin', async ({helper}) => {264    const owner = await helper.eth.createAccountWithBalance(donor);265    const fractionalizer = await deployContract(helper, owner);266    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');267268    await expect(fractionalizer.methods.setRFTCollection(rftCollection.collectionAddress).call())269      .to.be.rejectedWith(/Fractionalizer contract should be an admin of the collection$/g);270  });271272  itEth('call setRFTCollection after createAndSetRFTCollection', async ({helper}) => {273    const owner = await helper.eth.createAccountWithBalance(donor);274    const fractionalizer = await deployContract(helper, owner);275    await helper.balance.transferToSubstrate(donor, evmToAddress(fractionalizer.options.address), 10n * helper.balance.getOneTokenNominal());276277    const result = await fractionalizer.methods.createAndSetRFTCollection('A', 'B', 'C').send({from: owner, value: Number(2n * helper.balance.getOneTokenNominal())});278    const collectionIdAddress = result.events.RFTCollectionSet.returnValues._collection;279280    await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).call())281      .to.be.rejectedWith(/RFT collection is already set$/g);282  });283284  itEth('call nft2rft without setting RFT collection for contract', async ({helper}) => {285    const owner = await helper.eth.createAccountWithBalance(donor);286287    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');288    const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);289    const mintResult = await nftContract.methods.mint(owner).send({from: owner});290    const nftTokenId = mintResult.events.Transfer.returnValues.tokenId;291292    const fractionalizer = await deployContract(helper, owner);293294    await expect(fractionalizer.methods.nft2rft(nftCollection.collectionAddress, nftTokenId, 100).call())295      .to.be.rejectedWith(/RFT collection is not set$/g);296  });297298  itEth('call nft2rft while not owner of NFT token', async ({helper}) => {299    const owner = await helper.eth.createAccountWithBalance(donor);300    const nftOwner = await helper.eth.createAccountWithBalance(donor);301302    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');303    const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);304    const mintResult = await nftContract.methods.mint(owner).send({from: owner});305    const nftTokenId = mintResult.events.Transfer.returnValues.tokenId;306    await nftContract.methods.transfer(nftOwner, 1).send({from: owner});307308309    const {contract: fractionalizer} = await initContract(helper, owner);310    await fractionalizer.methods.setNftCollectionIsAllowed(nftCollection.collectionAddress, true).send({from: owner});311312    await expect(fractionalizer.methods.nft2rft(nftCollection.collectionAddress, nftTokenId, 100).call({from: owner}))313      .to.be.rejectedWith(/Only token owner could fractionalize it$/g);314  });315316  itEth('call nft2rft while not in list of allowed accounts', async ({helper}) => {317    const owner = await helper.eth.createAccountWithBalance(donor);318319    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');320    const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);321    const mintResult = await nftContract.methods.mint(owner).send({from: owner});322    const nftTokenId = mintResult.events.Transfer.returnValues.tokenId;323324    const {contract: fractionalizer} = await initContract(helper, owner);325326    await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send({from: owner});327    await expect(fractionalizer.methods.nft2rft(nftCollection.collectionAddress, nftTokenId, 100).call())328      .to.be.rejectedWith(/Fractionalization of this collection is not allowed by admin$/g);329  });330331  itEth('call nft2rft while fractionalizer doesnt have approval for nft token', async ({helper}) => {332    const owner = await helper.eth.createAccountWithBalance(donor);333334    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');335    const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);336    const mintResult = await nftContract.methods.mint(owner).send({from: owner});337    const nftTokenId = mintResult.events.Transfer.returnValues.tokenId;338339    const {contract: fractionalizer} = await initContract(helper, owner);340341    await fractionalizer.methods.setNftCollectionIsAllowed(nftCollection.collectionAddress, true).send({from: owner});342    await expect(fractionalizer.methods.nft2rft(nftCollection.collectionAddress, nftTokenId, 100).call())343      .to.be.rejectedWith(/ApprovedValueTooLow$/g);344  });345346  itEth('call rft2nft without setting RFT collection for contract', async ({helper}) => {347    const owner = await helper.eth.createAccountWithBalance(donor);348349    const fractionalizer = await deployContract(helper, owner);350    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');351    const refungibleContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);352    const mintResult = await refungibleContract.methods.mint(owner).send({from: owner});353    const rftTokenId = mintResult.events.Transfer.returnValues.tokenId;354355    await expect(fractionalizer.methods.rft2nft(rftCollection.collectionAddress, rftTokenId).call({from: owner}))356      .to.be.rejectedWith(/RFT collection is not set$/g);357  });358359  itEth('call rft2nft for RFT token that is not from configured RFT collection', async ({helper}) => {360    const owner = await helper.eth.createAccountWithBalance(donor);361362    const {contract: fractionalizer} = await initContract(helper, owner);363    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');364    const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);365    const mintResult = await refungibleContract.methods.mint(owner).send({from: owner});366    const rftTokenId = mintResult.events.Transfer.returnValues.tokenId;367368    await expect(fractionalizer.methods.rft2nft(rftCollection.collectionAddress, rftTokenId).call())369      .to.be.rejectedWith(/Wrong RFT collection$/g);370  });371372  itEth('call rft2nft for RFT token that was not minted by fractionalizer contract', async ({helper}) => {373    const owner = await helper.eth.createAccountWithBalance(donor);374    const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');375    const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);376377    const fractionalizer = await deployContract(helper, owner);378379    const fractionalizerAddressCross = helper.ethCrossAccount.fromAddress(fractionalizer.options.address);380    await refungibleContract.methods.addCollectionAdminCross(fractionalizerAddressCross).send({from: owner});381    await fractionalizer.methods.setRFTCollection(rftCollection.collectionAddress).send({from: owner});382383    const mintResult = await refungibleContract.methods.mint(owner).send({from: owner});384    const rftTokenId = mintResult.events.Transfer.returnValues.tokenId;385386    await expect(fractionalizer.methods.rft2nft(rftCollection.collectionAddress, rftTokenId).call())387      .to.be.rejectedWith(/No corresponding NFT token found$/g);388  });389390  itEth('call rft2nft without owning all RFT pieces', async ({helper}) => {391    const owner = await helper.eth.createAccountWithBalance(donor);392    const receiver = await helper.eth.createAccountWithBalance(donor);393394    const {contract: fractionalizer, rftCollectionAddress} = await initContract(helper, owner);395    const {rftTokenAddress} = await mintRFTToken(helper, owner, fractionalizer, 100n);396397    const {tokenId} = helper.ethAddress.extractTokenId(rftTokenAddress);398    const refungibleTokenContract = helper.ethNativeContract.rftToken(rftTokenAddress, owner);399    await refungibleTokenContract.methods.transfer(receiver, 50).send({from: owner});400    await refungibleTokenContract.methods.approve(fractionalizer.options.address, 50).send({from: receiver});401    await expect(fractionalizer.methods.rft2nft(rftCollectionAddress, tokenId).call({from: receiver}))402      .to.be.rejectedWith(/Not all pieces are owned by the caller$/g);403  });404405  itEth('send QTZ/UNQ to contract from non owner', async ({helper}) => {406    const owner = await helper.eth.createAccountWithBalance(donor);407    const payer = await helper.eth.createAccountWithBalance(donor);408409    const fractionalizer = await deployContract(helper, owner);410    const amount = 10n * helper.balance.getOneTokenNominal();411    const web3 = helper.getWeb3();412    await expect(web3.eth.sendTransaction({from: payer, to: fractionalizer.options.address, value: `${amount}`, gas: helper.eth.DEFAULT_GAS})).to.be.rejected;413  });414415  itEth('fractionalize NFT with NFT transfers disallowed', async ({helper}) => {416    const nftCollection = await helper.nft.mintCollection(donor, {name: 'A', description: 'B', tokenPrefix: 'C'});417418    const owner = await helper.eth.createAccountWithBalance(donor);419    const nftToken = await nftCollection.mintToken(donor, {Ethereum: owner});420    await helper.executeExtrinsic(donor, 'api.tx.unique.setTransfersEnabledFlag', [nftCollection.collectionId, false], true);421    const nftCollectionAddress = helper.ethAddress.fromCollectionId(nftCollection.collectionId);422    const {contract: fractionalizer} = await initContract(helper, owner);423    await fractionalizer.methods.setNftCollectionIsAllowed(nftCollectionAddress, true).send({from: owner});424425    const nftContract = await helper.ethNativeContract.collection(nftCollectionAddress, 'nft', owner);426    await nftContract.methods.approve(fractionalizer.options.address, nftToken.tokenId).send({from: owner});427    await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftToken.tokenId, 100).call())428      .to.be.rejectedWith(/TransferNotAllowed$/g);429  });430431  itEth('fractionalize NFT with RFT transfers disallowed', async ({helper}) => {432    const owner = await helper.eth.createAccountWithBalance(donor);433434    const rftCollection = await helper.rft.mintCollection(donor, {name: 'A', description: 'B', tokenPrefix: 'C'});435    const rftCollectionAddress = helper.ethAddress.fromCollectionId(rftCollection.collectionId);436    const fractionalizer = await deployContract(helper, owner);437    await rftCollection.addAdmin(donor, {Ethereum: fractionalizer.options.address});438439    await fractionalizer.methods.setRFTCollection(rftCollectionAddress).send({from: owner});440    await helper.executeExtrinsic(donor, 'api.tx.unique.setTransfersEnabledFlag', [rftCollection.collectionId, false], true);441442    const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');443    const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);444    const mintResult = await nftContract.methods.mint(owner).send({from: owner});445    const nftTokenId = mintResult.events.Transfer.returnValues.tokenId;446447    await fractionalizer.methods.setNftCollectionIsAllowed(nftCollection.collectionAddress, true).send({from: owner});448    await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send({from: owner});449450    await expect(fractionalizer.methods.nft2rft(nftCollection.collectionAddress, nftTokenId, 100n).call())451      .to.be.rejectedWith(/TransferNotAllowed$/g);452  });453});