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

difftreelog

source

tests/src/eth/reFungibleToken.test.ts21.0 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/>.1617import {Pallets, requirePalletsOrSkip} from '../util/playgrounds';18import {EthUniqueHelper, expect, itEth, usingEthPlaygrounds} from './util/playgrounds';19import {IKeyringPair} from '@polkadot/types/types';20import {Contract} from 'web3-eth-contract';212223describe('Refungible token: Information getting', () => {24  let donor: IKeyringPair;25  let alice: IKeyringPair;2627  before(async function() {28    await usingEthPlaygrounds(async (helper, privateKey) => {29      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);3031      donor = privateKey('//Alice');32      [alice] = await helper.arrange.createAccounts([20n], donor);33    });34  });3536  itEth('totalSupply', async ({helper}) => {37    const caller = await helper.eth.createAccountWithBalance(donor);38    const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'});39    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller});4041    const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller);42    const totalSupply = await contract.methods.totalSupply().call();43    expect(totalSupply).to.equal('200');44  });4546  itEth('balanceOf', async ({helper}) => {47    const caller = await helper.eth.createAccountWithBalance(donor);48    const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'});49    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller});5051    const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller);52    const balance = await contract.methods.balanceOf(caller).call();53    expect(balance).to.equal('200');54  });5556  itEth('decimals', async ({helper}) => {57    const caller = await helper.eth.createAccountWithBalance(donor);58    const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'});59    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller});6061    const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller);62    const decimals = await contract.methods.decimals().call();63    expect(decimals).to.equal('0');64  });65});6667// FIXME: Need erc721 for ReFubgible.68describe('Check ERC721 token URI for ReFungible', () => {69  let donor: IKeyringPair;7071  before(async function() {72    await usingEthPlaygrounds(async (helper, privateKey) => {73      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);7475      donor = privateKey('//Alice');76    });77  });7879  async function setup(helper: EthUniqueHelper, baseUri: string, propertyKey?: string, propertyValue?: string): Promise<{contract: Contract, nextTokenId: string}> {80    const owner = await helper.eth.createAccountWithBalance(donor);81    const receiver = helper.eth.createAccount();8283    const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'Mint collection', 'a', 'b', baseUri);84    const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);85    86    const nextTokenId = await contract.methods.nextTokenId().call();87    expect(nextTokenId).to.be.equal('1');88    const result = await contract.methods.mint(89      receiver,90      nextTokenId,91    ).send();9293    if (propertyKey && propertyValue) {94      // Set URL or suffix95      await contract.methods.setProperty(nextTokenId, propertyKey, Buffer.from(propertyValue)).send();96    }9798    const event = result.events.Transfer;99    expect(event.address).to.be.equal(collectionAddress);100    expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');101    expect(event.returnValues.to).to.be.equal(receiver);102    expect(event.returnValues.tokenId).to.be.equal(nextTokenId);103104    return {contract, nextTokenId};105  }106107  itEth('Empty tokenURI', async ({helper}) => {108    const {contract, nextTokenId} = await setup(helper, '');109    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('');110  });111112  itEth('TokenURI from url', async ({helper}) => {113    const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'URI', 'Token URI');114    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI');115  });116117  itEth('TokenURI from baseURI', async ({helper}) => {118    const {contract, nextTokenId} = await setup(helper, 'BaseURI_');119    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_');120  });121122  itEth('TokenURI from baseURI + suffix', async ({helper}) => {123    const suffix = '/some/suffix';124    const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'URISuffix', suffix);125    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix);126  });127});128129describe('Refungible: Plain calls', () => {130  let donor: IKeyringPair;131  let alice: IKeyringPair;132133  before(async function() {134    await usingEthPlaygrounds(async (helper, privateKey) => {135      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);136137      donor = privateKey('//Alice');138      [alice] = await helper.arrange.createAccounts([50n], donor);139    });140  });141142  itEth('Can perform approve()', async ({helper}) => {143    const owner = await helper.eth.createAccountWithBalance(donor);144    const spender = helper.eth.createAccount();145    const collection = await helper.rft.mintCollection(alice);146    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});147148    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);149    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);150151    {152      const result = await contract.methods.approve(spender, 100).send({from: owner});153      const event = result.events.Approval;154      expect(event.address).to.be.equal(tokenAddress);155      expect(event.returnValues.owner).to.be.equal(owner);156      expect(event.returnValues.spender).to.be.equal(spender);157      expect(event.returnValues.value).to.be.equal('100');158    }159160    {161      const allowance = await contract.methods.allowance(owner, spender).call();162      expect(+allowance).to.equal(100);163    }164  });165166  itEth('Can perform transferFrom()', async ({helper}) => {167    const owner = await helper.eth.createAccountWithBalance(donor);168    const spender = await helper.eth.createAccountWithBalance(donor);169    const receiver = helper.eth.createAccount();170    const collection = await helper.rft.mintCollection(alice);171    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});172173    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);174    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);175176    await contract.methods.approve(spender, 100).send();177178    {179      const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender});180      let event = result.events.Transfer;181      expect(event.address).to.be.equal(tokenAddress);182      expect(event.returnValues.from).to.be.equal(owner);183      expect(event.returnValues.to).to.be.equal(receiver);184      expect(event.returnValues.value).to.be.equal('49');185186      event = result.events.Approval;187      expect(event.address).to.be.equal(tokenAddress);188      expect(event.returnValues.owner).to.be.equal(owner);189      expect(event.returnValues.spender).to.be.equal(spender);190      expect(event.returnValues.value).to.be.equal('51');191    }192193    {194      const balance = await contract.methods.balanceOf(receiver).call();195      expect(+balance).to.equal(49);196    }197198    {199      const balance = await contract.methods.balanceOf(owner).call();200      expect(+balance).to.equal(151);201    }202  });203204  itEth('Can perform transfer()', async ({helper}) => {205    const owner = await helper.eth.createAccountWithBalance(donor);206    const receiver = helper.eth.createAccount();207    const collection = await helper.rft.mintCollection(alice);208    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});209210    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);211    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);212213    {214      const result = await contract.methods.transfer(receiver, 50).send({from: owner});215      const event = result.events.Transfer;216      expect(event.address).to.be.equal(tokenAddress);217      expect(event.returnValues.from).to.be.equal(owner);218      expect(event.returnValues.to).to.be.equal(receiver);219      expect(event.returnValues.value).to.be.equal('50');220    }221222    {223      const balance = await contract.methods.balanceOf(owner).call();224      expect(+balance).to.equal(150);225    }226227    {228      const balance = await contract.methods.balanceOf(receiver).call();229      expect(+balance).to.equal(50);230    }231  });232233  itEth('Can perform repartition()', async ({helper}) => {234    const owner = await helper.eth.createAccountWithBalance(donor);235    const receiver = await helper.eth.createAccountWithBalance(donor);236    const collection = await helper.rft.mintCollection(alice);237    const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});238239    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);240    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);241242    await contract.methods.repartition(200).send({from: owner});243    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(200);244    await contract.methods.transfer(receiver, 110).send({from: owner});245    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(90);246    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(110);247248    await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected; // Transaction is reverted249250    await contract.methods.transfer(receiver, 90).send({from: owner});251    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(0);252    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(200);253254    await contract.methods.repartition(150).send({from: receiver});255    await expect(contract.methods.transfer(owner, 160).send({from: receiver})).to.eventually.be.rejected; // Transaction is reverted256    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(150);257  });258259  itEth('Can repartition with increased amount', async ({helper}) => {260    const owner = await helper.eth.createAccountWithBalance(donor);261    const collection = await helper.rft.mintCollection(alice);262    const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});263264    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);265    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);266267    const result = await contract.methods.repartition(200).send();268269    const event = result.events.Transfer;270    expect(event.address).to.be.equal(tokenAddress);271    expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');272    expect(event.returnValues.to).to.be.equal(owner);273    expect(event.returnValues.value).to.be.equal('100');274  });275276  itEth('Can repartition with decreased amount', async ({helper}) => {277    const owner = await helper.eth.createAccountWithBalance(donor);278    const collection = await helper.rft.mintCollection(alice);279    const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});280281    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);282    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);283284    const result = await contract.methods.repartition(50).send();285    const event = result.events.Transfer;286    expect(event.address).to.be.equal(tokenAddress);287    expect(event.returnValues.from).to.be.equal(owner);288    expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000');289    expect(event.returnValues.value).to.be.equal('50');290  });291292  itEth('Receiving Transfer event on burning into full ownership', async ({helper}) => {293    const caller = await helper.eth.createAccountWithBalance(donor);294    const receiver = await helper.eth.createAccountWithBalance(donor);295    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Devastation', '6', '6');296    const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);297298    const tokenId = await contract.methods.nextTokenId().call();299    await contract.methods.mint(caller, tokenId).send();300    const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId);301    const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, caller);302303    await tokenContract.methods.repartition(2).send();304    await tokenContract.methods.transfer(receiver, 1).send();305306    const events: any = [];307    contract.events.allEvents((_: any, event: any) => {308      events.push(event);309    });310    await tokenContract.methods.burnFrom(caller, 1).send();311312    const event = events[0];313    expect(event.address).to.be.equal(collectionAddress);314    expect(event.returnValues.from).to.be.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');315    expect(event.returnValues.to).to.be.equal(receiver);316    expect(event.returnValues.tokenId).to.be.equal(tokenId);317  });318});319320describe('Refungible: Fees', () => {321  let donor: IKeyringPair;322  let alice: IKeyringPair;323324  before(async function() {325    await usingEthPlaygrounds(async (helper, privateKey) => {326      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);327328      donor = privateKey('//Alice');329      [alice] = await helper.arrange.createAccounts([50n], donor);330    });331  });332333  itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => {334    const owner = await helper.eth.createAccountWithBalance(donor);335    const spender = helper.eth.createAccount();336    const collection = await helper.rft.mintCollection(alice);337    const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});338339    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);340    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);341342    const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, 100).send({from: owner}));343    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));344  });345346  itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {347    const owner = await helper.eth.createAccountWithBalance(donor);348    const spender = await helper.eth.createAccountWithBalance(donor);349    const collection = await helper.rft.mintCollection(alice);350    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});351352    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);353    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);354355    await contract.methods.approve(spender, 100).send({from: owner});356357    const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender}));358    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));359  });360361  itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {362    const owner = await helper.eth.createAccountWithBalance(donor);363    const receiver = helper.eth.createAccount();364    const collection = await helper.rft.mintCollection(alice);365    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});366367    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);368    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);369370    const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));371    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));372  });373});374375describe('Refungible: Substrate calls', () => {376  let donor: IKeyringPair;377  let alice: IKeyringPair;378379  before(async function() {380    await usingEthPlaygrounds(async (helper, privateKey) => {381      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);382383      donor = privateKey('//Alice');384      [alice] = await helper.arrange.createAccounts([50n], donor);385    });386  });387388  itEth('Events emitted for approve()', async ({helper}) => {389    const receiver = helper.eth.createAccount();390    const collection = await helper.rft.mintCollection(alice);391    const token = await collection.mintToken(alice, 200n);392393    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);394    const contract = helper.ethNativeContract.rftToken(tokenAddress);395396    const events: any = [];397    contract.events.allEvents((_: any, event: any) => {398      events.push(event);399    });400    expect(await token.approve(alice, {Ethereum: receiver}, 100n)).to.be.true;401402    const event = events[0];403    expect(event.event).to.be.equal('Approval');404    expect(event.address).to.be.equal(tokenAddress);405    expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));406    expect(event.returnValues.spender).to.be.equal(receiver);407    expect(event.returnValues.value).to.be.equal('100');408  });409410  itEth('Events emitted for transferFrom()', async ({helper}) => {411    const [bob] = await helper.arrange.createAccounts([10n], donor);412    const receiver = helper.eth.createAccount();413    const collection = await helper.rft.mintCollection(alice);414    const token = await collection.mintToken(alice, 200n);415    await token.approve(alice, {Substrate: bob.address}, 100n);416417    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);418    const contract = helper.ethNativeContract.rftToken(tokenAddress);419420    const events: any = [];421    contract.events.allEvents((_: any, event: any) => {422      events.push(event);423    });424425    expect(await token.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver},  51n)).to.be.true;426427    let event = events[0];428    expect(event.event).to.be.equal('Transfer');429    expect(event.address).to.be.equal(tokenAddress);430    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));431    expect(event.returnValues.to).to.be.equal(receiver);432    expect(event.returnValues.value).to.be.equal('51');433434    event = events[1];435    expect(event.event).to.be.equal('Approval');436    expect(event.address).to.be.equal(tokenAddress);437    expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));438    expect(event.returnValues.spender).to.be.equal(helper.address.substrateToEth(bob.address));439    expect(event.returnValues.value).to.be.equal('49');440  });441442  itEth('Events emitted for transfer()', async ({helper}) => {443    const receiver = helper.eth.createAccount();444    const collection = await helper.rft.mintCollection(alice);445    const token = await collection.mintToken(alice, 200n);446447    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);448    const contract = helper.ethNativeContract.rftToken(tokenAddress);449450    const events: any = [];451    contract.events.allEvents((_: any, event: any) => {452      events.push(event);453    });454455    expect(await token.transfer(alice, {Ethereum: receiver},  51n)).to.be.true;456457    const event = events[0];458    expect(event.event).to.be.equal('Transfer');459    expect(event.address).to.be.equal(tokenAddress);460    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));461    expect(event.returnValues.to).to.be.equal(receiver);462    expect(event.returnValues.value).to.be.equal('51');463  });464});465466describe('ERC 1633 implementation', () => {467  let donor: IKeyringPair;468469  before(async function() {470    await usingEthPlaygrounds(async (helper, privateKey) => {471      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);472473      donor = privateKey('//Alice');474    });475  });476477  itEth('Default parent token address and id', async ({helper}) => {478    const owner = await helper.eth.createAccountWithBalance(donor);479480    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sands', '', 'GRAIN');481    const collectionContract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);482    483    const tokenId = await collectionContract.methods.nextTokenId().call();484    await collectionContract.methods.mint(owner, tokenId).send();485    const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId);486    const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, owner);487488    expect(await tokenContract.methods.parentToken().call()).to.be.equal(collectionAddress);489    expect(await tokenContract.methods.parentTokenId().call()).to.be.equal(tokenId);490  });491});