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

difftreelog

source

tests/src/eth/reFungibleToken.test.ts21.2 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';18import {EthUniqueHelper, expect, itEth, usingEthPlaygrounds} from './util';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 = await privateKey({filename: __filename});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 = await privateKey({filename: __filename});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);8586    const result = await contract.methods.mint(receiver).send();8788    const event = result.events.Transfer;89    const tokenId = event.returnValues.tokenId;90    expect(tokenId).to.be.equal('1');91    expect(event.address).to.be.equal(collectionAddress);92    expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');93    expect(event.returnValues.to).to.be.equal(receiver);9495    if (propertyKey && propertyValue) {96      // Set URL or suffix97      await contract.methods.setProperty(tokenId, propertyKey, Buffer.from(propertyValue)).send();98    }99100    return {contract, nextTokenId: tokenId};101  }102103  itEth('Empty tokenURI', async ({helper}) => {104    const {contract, nextTokenId} = await setup(helper, '');105    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('');106  });107108  itEth('TokenURI from url', async ({helper}) => {109    const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'URI', 'Token URI');110    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI');111  });112113  itEth('TokenURI from baseURI', async ({helper}) => {114    const {contract, nextTokenId} = await setup(helper, 'BaseURI_');115    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_');116  });117118  itEth('TokenURI from baseURI + suffix', async ({helper}) => {119    const suffix = '/some/suffix';120    const {contract, nextTokenId} = await setup(helper, 'BaseURI_', 'URISuffix', suffix);121    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix);122  });123});124125describe('Refungible: Plain calls', () => {126  let donor: IKeyringPair;127  let alice: IKeyringPair;128129  before(async function() {130    await usingEthPlaygrounds(async (helper, privateKey) => {131      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);132133      donor = await privateKey({filename: __filename});134      [alice] = await helper.arrange.createAccounts([50n], donor);135    });136  });137138  itEth('Can perform approve()', async ({helper}) => {139    const owner = await helper.eth.createAccountWithBalance(donor);140    const spender = helper.eth.createAccount();141    const collection = await helper.rft.mintCollection(alice);142    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});143144    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);145    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);146147    {148      const result = await contract.methods.approve(spender, 100).send({from: owner});149      const event = result.events.Approval;150      expect(event.address).to.be.equal(tokenAddress);151      expect(event.returnValues.owner).to.be.equal(owner);152      expect(event.returnValues.spender).to.be.equal(spender);153      expect(event.returnValues.value).to.be.equal('100');154    }155156    {157      const allowance = await contract.methods.allowance(owner, spender).call();158      expect(+allowance).to.equal(100);159    }160  });161162  itEth('Can perform transferFrom()', async ({helper}) => {163    const owner = await helper.eth.createAccountWithBalance(donor);164    const spender = await helper.eth.createAccountWithBalance(donor);165    const receiver = helper.eth.createAccount();166    const collection = await helper.rft.mintCollection(alice);167    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});168169    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);170    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);171172    await contract.methods.approve(spender, 100).send();173174    {175      const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender});176      let event = result.events.Transfer;177      expect(event.address).to.be.equal(tokenAddress);178      expect(event.returnValues.from).to.be.equal(owner);179      expect(event.returnValues.to).to.be.equal(receiver);180      expect(event.returnValues.value).to.be.equal('49');181182      event = result.events.Approval;183      expect(event.address).to.be.equal(tokenAddress);184      expect(event.returnValues.owner).to.be.equal(owner);185      expect(event.returnValues.spender).to.be.equal(spender);186      expect(event.returnValues.value).to.be.equal('51');187    }188189    {190      const balance = await contract.methods.balanceOf(receiver).call();191      expect(+balance).to.equal(49);192    }193194    {195      const balance = await contract.methods.balanceOf(owner).call();196      expect(+balance).to.equal(151);197    }198  });199200  itEth('Can perform transfer()', async ({helper}) => {201    const owner = await helper.eth.createAccountWithBalance(donor);202    const receiver = helper.eth.createAccount();203    const collection = await helper.rft.mintCollection(alice);204    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});205206    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);207    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);208209    {210      const result = await contract.methods.transfer(receiver, 50).send({from: owner});211      const event = result.events.Transfer;212      expect(event.address).to.be.equal(tokenAddress);213      expect(event.returnValues.from).to.be.equal(owner);214      expect(event.returnValues.to).to.be.equal(receiver);215      expect(event.returnValues.value).to.be.equal('50');216    }217218    {219      const balance = await contract.methods.balanceOf(owner).call();220      expect(+balance).to.equal(150);221    }222223    {224      const balance = await contract.methods.balanceOf(receiver).call();225      expect(+balance).to.equal(50);226    }227  });228229  itEth('Can perform repartition()', async ({helper}) => {230    const owner = await helper.eth.createAccountWithBalance(donor);231    const receiver = await helper.eth.createAccountWithBalance(donor);232    const collection = await helper.rft.mintCollection(alice);233    const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});234235    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);236    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);237238    await contract.methods.repartition(200).send({from: owner});239    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(200);240    await contract.methods.transfer(receiver, 110).send({from: owner});241    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(90);242    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(110);243244    await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected; // Transaction is reverted245246    await contract.methods.transfer(receiver, 90).send({from: owner});247    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(0);248    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(200);249250    await contract.methods.repartition(150).send({from: receiver});251    await expect(contract.methods.transfer(owner, 160).send({from: receiver})).to.eventually.be.rejected; // Transaction is reverted252    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(150);253  });254255  itEth('Can repartition with increased amount', async ({helper}) => {256    const owner = await helper.eth.createAccountWithBalance(donor);257    const collection = await helper.rft.mintCollection(alice);258    const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});259260    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);261    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);262263    const result = await contract.methods.repartition(200).send();264265    const event = result.events.Transfer;266    expect(event.address).to.be.equal(tokenAddress);267    expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000');268    expect(event.returnValues.to).to.be.equal(owner);269    expect(event.returnValues.value).to.be.equal('100');270  });271272  itEth('Can repartition with decreased amount', async ({helper}) => {273    const owner = await helper.eth.createAccountWithBalance(donor);274    const collection = await helper.rft.mintCollection(alice);275    const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});276277    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);278    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);279280    const result = await contract.methods.repartition(50).send();281    const event = result.events.Transfer;282    expect(event.address).to.be.equal(tokenAddress);283    expect(event.returnValues.from).to.be.equal(owner);284    expect(event.returnValues.to).to.be.equal('0x0000000000000000000000000000000000000000');285    expect(event.returnValues.value).to.be.equal('50');286  });287288  itEth('Receiving Transfer event on burning into full ownership', async ({helper}) => {289    const caller = await helper.eth.createAccountWithBalance(donor);290    const receiver = await helper.eth.createAccountWithBalance(donor);291    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Devastation', '6', '6');292    const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);293294    const result = await contract.methods.mint(caller).send();295    const tokenId = result.events.Transfer.returnValues.tokenId;296    const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId);297    const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, caller);298299    await tokenContract.methods.repartition(2).send();300    await tokenContract.methods.transfer(receiver, 1).send();301302    const events: any = [];303    contract.events.allEvents((_: any, event: any) => {304      events.push(event);305    });306    await tokenContract.methods.burnFrom(caller, 1).send();307308    if (events.length == 0) await helper.wait.newBlocks(1);309    const event = events[0];310    expect(event.address).to.be.equal(collectionAddress);311    expect(event.returnValues.from).to.be.equal('0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF');312    expect(event.returnValues.to).to.be.equal(receiver);313    expect(event.returnValues.tokenId).to.be.equal(tokenId);314  });315});316317describe('Refungible: Fees', () => {318  let donor: IKeyringPair;319  let alice: IKeyringPair;320321  before(async function() {322    await usingEthPlaygrounds(async (helper, privateKey) => {323      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);324325      donor = await privateKey({filename: __filename});326      [alice] = await helper.arrange.createAccounts([50n], donor);327    });328  });329330  itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => {331    const owner = await helper.eth.createAccountWithBalance(donor);332    const spender = helper.eth.createAccount();333    const collection = await helper.rft.mintCollection(alice);334    const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner});335336    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);337    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);338339    const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, 100).send({from: owner}));340    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));341  });342343  itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {344    const owner = await helper.eth.createAccountWithBalance(donor);345    const spender = await helper.eth.createAccountWithBalance(donor);346    const collection = await helper.rft.mintCollection(alice);347    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});348349    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);350    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);351352    await contract.methods.approve(spender, 100).send({from: owner});353354    const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender}));355    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));356  });357358  itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {359    const owner = await helper.eth.createAccountWithBalance(donor);360    const receiver = helper.eth.createAccount();361    const collection = await helper.rft.mintCollection(alice);362    const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner});363364    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId);365    const contract = helper.ethNativeContract.rftToken(tokenAddress, owner);366367    const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));368    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));369  });370});371372describe('Refungible: Substrate calls', () => {373  let donor: IKeyringPair;374  let alice: IKeyringPair;375376  before(async function() {377    await usingEthPlaygrounds(async (helper, privateKey) => {378      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);379380      donor = await privateKey({filename: __filename});381      [alice] = await helper.arrange.createAccounts([50n], donor);382    });383  });384385  itEth('Events emitted for approve()', async ({helper}) => {386    const receiver = helper.eth.createAccount();387    const collection = await helper.rft.mintCollection(alice);388    const token = await collection.mintToken(alice, 200n);389390    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);391    const contract = helper.ethNativeContract.rftToken(tokenAddress);392393    const events: any = [];394    contract.events.allEvents((_: any, event: any) => {395      events.push(event);396    });397398    expect(await token.approve(alice, {Ethereum: receiver}, 100n)).to.be.true;399    if (events.length == 0) await helper.wait.newBlocks(1);400    const event = events[0];401402    expect(event.event).to.be.equal('Approval');403    expect(event.address).to.be.equal(tokenAddress);404    expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));405    expect(event.returnValues.spender).to.be.equal(receiver);406    expect(event.returnValues.value).to.be.equal('100');407  });408409  itEth('Events emitted for transferFrom()', async ({helper}) => {410    const [bob] = await helper.arrange.createAccounts([10n], donor);411    const receiver = helper.eth.createAccount();412    const collection = await helper.rft.mintCollection(alice);413    const token = await collection.mintToken(alice, 200n);414    await token.approve(alice, {Substrate: bob.address}, 100n);415416    const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);417    const contract = helper.ethNativeContract.rftToken(tokenAddress);418419    const events: any = [];420    contract.events.allEvents((_: any, event: any) => {421      events.push(event);422    });423424    expect(await token.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver},  51n)).to.be.true;425    if (events.length == 0) await helper.wait.newBlocks(1);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;456    if (events.length == 0) await helper.wait.newBlocks(1);457    const event = events[0];458459    expect(event.event).to.be.equal('Transfer');460    expect(event.address).to.be.equal(tokenAddress);461    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));462    expect(event.returnValues.to).to.be.equal(receiver);463    expect(event.returnValues.value).to.be.equal('51');464  });465});466467describe('ERC 1633 implementation', () => {468  let donor: IKeyringPair;469470  before(async function() {471    await usingEthPlaygrounds(async (helper, privateKey) => {472      requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);473474      donor = await privateKey({filename: __filename});475    });476  });477478  itEth('Default parent token address and id', async ({helper}) => {479    const owner = await helper.eth.createAccountWithBalance(donor);480481    const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sands', '', 'GRAIN');482    const collectionContract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);483484    const result = await collectionContract.methods.mint(owner).send();485    const tokenId = result.events.Transfer.returnValues.tokenId;486487    const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId);488    const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, owner);489490    expect(await tokenContract.methods.parentToken().call()).to.be.equal(collectionAddress);491    expect(await tokenContract.methods.parentTokenId().call()).to.be.equal(tokenId);492  });493});