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

difftreelog

source

tests/src/eth/reFungibleToken.test.ts24.1 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 {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers';18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth} from './util/helpers';19import reFungibleTokenAbi from './reFungibleTokenAbi.json';2021import chai from 'chai';22import chaiAsPromised from 'chai-as-promised';23chai.use(chaiAsPromised);24const expect = chai.expect;2526describe('Refungible token: Information getting', () => {27  before(async function() {28    await requirePallets(this, [Pallets.ReFungible]);29  });3031  itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {32    const alice = privateKeyWrapper('//Alice');3334    const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;3536    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);3738    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;3940    const address = tokenIdToAddress(collectionId, tokenId);41    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});42    const totalSupply = await contract.methods.totalSupply().call();4344    expect(totalSupply).to.equal('200');45  });4647  itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => {48    const alice = privateKeyWrapper('//Alice');4950    const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;5152    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);5354    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;5556    const address = tokenIdToAddress(collectionId, tokenId);57    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});58    const balance = await contract.methods.balanceOf(caller).call();5960    expect(balance).to.equal('200');61  });6263  itWeb3('decimals', async ({api, web3, privateKeyWrapper}) => {64    const alice = privateKeyWrapper('//Alice');6566    const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;6768    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);6970    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;7172    const address = tokenIdToAddress(collectionId, tokenId);73    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});74    const decimals = await contract.methods.decimals().call();7576    expect(decimals).to.equal('0');77  });78});7980// FIXME: Need erc721 for ReFubgible.81describe('Check ERC721 token URI for ReFungible', () => {82  before(async function() {83    await requirePallets(this, [Pallets.ReFungible]);84  });8586  itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {87    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);88    const helper = evmCollectionHelpers(web3, owner);89    let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', '').send();90    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);91    const receiver = createEthAccount(web3);92    const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});93    94    const nextTokenId = await contract.methods.nextTokenId().call();95    expect(nextTokenId).to.be.equal('1');96    result = await contract.methods.mint(97      receiver,98      nextTokenId,99    ).send();100101    const events = normalizeEvents(result.events);102    const address = collectionIdToAddress(collectionId);103104    expect(events).to.be.deep.equal([105      {106        address,107        event: 'Transfer',108        args: {109          from: '0x0000000000000000000000000000000000000000',110          to: receiver,111          tokenId: nextTokenId,112        },113      },114    ]);115116    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('');117  });118119  itWeb3('TokenURI from url', async ({web3, api, privateKeyWrapper}) => {120    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);121    const helper = evmCollectionHelpers(web3, owner);122    let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();123    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);124    const receiver = createEthAccount(web3);125    const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});126    127    const nextTokenId = await contract.methods.nextTokenId().call();128    expect(nextTokenId).to.be.equal('1');129    result = await contract.methods.mint(130      receiver,131      nextTokenId,132    ).send();133    134    // Set URL135    await contract.methods.setProperty(nextTokenId, 'url', Buffer.from('Token URI')).send();136      137    const events = normalizeEvents(result.events);138    const address = collectionIdToAddress(collectionId);139140    expect(events).to.be.deep.equal([141      {142        address,143        event: 'Transfer',144        args: {145          from: '0x0000000000000000000000000000000000000000',146          to: receiver,147          tokenId: nextTokenId,148        },149      },150    ]);151152    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI');153  });154155  itWeb3('TokenURI from baseURI + tokenId', async ({web3, api, privateKeyWrapper}) => {156    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);157    const helper = evmCollectionHelpers(web3, owner);158    let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();159    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);160    const receiver = createEthAccount(web3);161    const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});162    163    const nextTokenId = await contract.methods.nextTokenId().call();164    expect(nextTokenId).to.be.equal('1');165    result = await contract.methods.mint(166      receiver,167      nextTokenId,168    ).send();169          170    const events = normalizeEvents(result.events);171    const address = collectionIdToAddress(collectionId);172173    expect(events).to.be.deep.equal([174      {175        address,176        event: 'Transfer',177        args: {178          from: '0x0000000000000000000000000000000000000000',179          to: receiver,180          tokenId: nextTokenId,181        },182      },183    ]);184185    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + nextTokenId);186  });187188  itWeb3('TokenURI from baseURI + suffix', async ({web3, api, privateKeyWrapper}) => {189    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);190    const helper = evmCollectionHelpers(web3, owner);191    let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();192    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);193    const receiver = createEthAccount(web3);194    const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});195    196    const nextTokenId = await contract.methods.nextTokenId().call();197    expect(nextTokenId).to.be.equal('1');198    result = await contract.methods.mint(199      receiver,200      nextTokenId,201    ).send();202          203    // Set suffix204    const suffix = '/some/suffix';205    await contract.methods.setProperty(nextTokenId, 'suffix', Buffer.from(suffix)).send();206207    const events = normalizeEvents(result.events);208    const address = collectionIdToAddress(collectionId);209210    expect(events).to.be.deep.equal([211      {212        address,213        event: 'Transfer',214        args: {215          from: '0x0000000000000000000000000000000000000000',216          to: receiver,217          tokenId: nextTokenId,218        },219      },220    ]);221222    expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix);223  });224});225226describe('Refungible: Plain calls', () => {227  before(async function() {228    await requirePallets(this, [Pallets.ReFungible]);229  });230231  itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {232    const alice = privateKeyWrapper('//Alice');233234    const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;235236    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);237238    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;239240    const address = tokenIdToAddress(collectionId, tokenId);241242    const spender = createEthAccount(web3);243244    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});245246    {247      const result = await contract.methods.approve(spender, 100).send({from: owner});248      const events = normalizeEvents(result.events);249250      expect(events).to.be.deep.equal([251        {252          address,253          event: 'Approval',254          args: {255            owner,256            spender,257            value: '100',258          },259        },260      ]);261    }262263    {264      const allowance = await contract.methods.allowance(owner, spender).call();265      expect(+allowance).to.equal(100);266    }267  });268269  itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => {270    const alice = privateKeyWrapper('//Alice');271272    const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;273274    const owner = createEthAccount(web3);275    await transferBalanceToEth(api, alice, owner);276277    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;278279    const spender = createEthAccount(web3);280    await transferBalanceToEth(api, alice, spender);281282    const receiver = createEthAccount(web3);283284    const address = tokenIdToAddress(collectionId, tokenId);285    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});286287    await contract.methods.approve(spender, 100).send();288289    {290      const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender});291      const events = normalizeEvents(result.events);292      expect(events).to.include.deep.members([293        {294          address,295          event: 'Transfer',296          args: {297            from: owner,298            to: receiver,299            value: '49',300          },301        },302        {303          address,304          event: 'Approval',305          args: {306            owner,307            spender,308            value: '51',309          },310        },311      ]);312    }313314    {315      const balance = await contract.methods.balanceOf(receiver).call();316      expect(+balance).to.equal(49);317    }318319    {320      const balance = await contract.methods.balanceOf(owner).call();321      expect(+balance).to.equal(151);322    }323  });324325  itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => {326    const alice = privateKeyWrapper('//Alice');327328    const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;329330    const owner = createEthAccount(web3);331    await transferBalanceToEth(api, alice, owner);332333    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;334335    const receiver = createEthAccount(web3);336    await transferBalanceToEth(api, alice, receiver);337338    const address = tokenIdToAddress(collectionId, tokenId);339    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});340341    {342      const result = await contract.methods.transfer(receiver, 50).send({from: owner});343      const events = normalizeEvents(result.events);344      expect(events).to.include.deep.members([345        {346          address,347          event: 'Transfer',348          args: {349            from: owner,350            to: receiver,351            value: '50',352          },353        },354      ]);355    }356357    {358      const balance = await contract.methods.balanceOf(owner).call();359      expect(+balance).to.equal(150);360    }361362    {363      const balance = await contract.methods.balanceOf(receiver).call();364      expect(+balance).to.equal(50);365    }366  });367368  itWeb3('Can perform repartition()', async ({web3, api, privateKeyWrapper}) => {369    const alice = privateKeyWrapper('//Alice');370371    const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;372373    const owner = createEthAccount(web3);374    await transferBalanceToEth(api, alice, owner);375376    const receiver = createEthAccount(web3);377    await transferBalanceToEth(api, alice, receiver);378379    const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;380381    const address = tokenIdToAddress(collectionId, tokenId);382    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});383384    await contract.methods.repartition(200).send({from: owner});385    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(200);386    await contract.methods.transfer(receiver, 110).send({from: owner});387    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(90);388    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(110);389    390    await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected;391392    await contract.methods.transfer(receiver, 90).send({from: owner});393    expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(0);394    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(200);395396    await contract.methods.repartition(150).send({from: receiver});397    await expect(contract.methods.transfer(owner, 160).send({from: receiver})).to.eventually.be.rejected;398    expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(150);399  });400401  itWeb3('Can repartition with increased amount', async ({web3, api, privateKeyWrapper}) => {402    const alice = privateKeyWrapper('//Alice');403404    const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;405406    const owner = createEthAccount(web3);407    await transferBalanceToEth(api, alice, owner);408409    const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;410411    const address = tokenIdToAddress(collectionId, tokenId);412    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});413414    const result = await contract.methods.repartition(200).send();415    const events = normalizeEvents(result.events);416417    expect(events).to.deep.equal([418      {419        address,420        event: 'Transfer',421        args: {422          from: '0x0000000000000000000000000000000000000000',423          to: owner,424          value: '100',425        },426      },427    ]);428  });429430  itWeb3('Can repartition with decreased amount', async ({web3, api, privateKeyWrapper}) => {431    const alice = privateKeyWrapper('//Alice');432433    const collectionId = (await createCollection(api, alice, {name: 'token name', mode: {type: 'ReFungible'}})).collectionId;434435    const owner = createEthAccount(web3);436    await transferBalanceToEth(api, alice, owner);437438    const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;439440    const address = tokenIdToAddress(collectionId, tokenId);441    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});442443    const result = await contract.methods.repartition(50).send();444    const events = normalizeEvents(result.events);445    expect(events).to.deep.equal([446      {447        address,448        event: 'Transfer',449        args: {450          from: owner,451          to: '0x0000000000000000000000000000000000000000',452          value: '50',453        },454      },455    ]);456  });457458  itWeb3('Receiving Transfer event on burning into full ownership', async ({web3, api, privateKeyWrapper}) => {459    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);460    const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);461    const helper = evmCollectionHelpers(web3, caller);462    const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();463    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);464    const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});465466    const tokenId = await contract.methods.nextTokenId().call();467    await contract.methods.mint(caller, tokenId).send();468469    const address = tokenIdToAddress(collectionId, tokenId);470471    const tokenContract =  new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});472    await tokenContract.methods.repartition(2).send();473    await tokenContract.methods.transfer(receiver, 1).send();474475    const events =  await recordEvents(contract, async () => 476      await tokenContract.methods.burnFrom(caller, 1).send());477    expect(events).to.deep.equal([478      {479        address: collectionIdAddress,480        event: 'Transfer',481        args: {482          from: '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF',483          to: receiver,484          tokenId,485        },486      },487    ]);488  });489});490491describe('Refungible: Fees', () => {492  before(async function() {493    await requirePallets(this, [Pallets.ReFungible]);494  });495496  itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {497    const alice = privateKeyWrapper('//Alice');498499    const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;500501    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);502    const spender = createEthAccount(web3);503504    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;505506    const address = tokenIdToAddress(collectionId, tokenId);507    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});508509    const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({from: owner}));510    expect(cost < BigInt(0.2 * Number(UNIQUE)));511  });512513  itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {514    const alice = privateKeyWrapper('//Alice');515516    const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;517518    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);519    const spender = await createEthAccountWithBalance(api, web3, privateKeyWrapper);520521    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;522523    const address = tokenIdToAddress(collectionId, tokenId);524    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});525526    await contract.methods.approve(spender, 100).send({from: owner});527528    const cost = await recordEthFee(api, spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender}));529    expect(cost < BigInt(0.2 * Number(UNIQUE)));530  });531532  itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {533    const alice = privateKeyWrapper('//Alice');534535    const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;536537    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);538    const receiver = createEthAccount(web3);539540    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;541542    const address = tokenIdToAddress(collectionId, tokenId);543    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});544545    const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));546    expect(cost < BigInt(0.2 * Number(UNIQUE)));547  });548});549550describe('Refungible: Substrate calls', () => {551  before(async function() {552    await requirePallets(this, [Pallets.ReFungible]);553  });554555  itWeb3('Events emitted for approve()', async ({web3, api, privateKeyWrapper}) => {556    const alice = privateKeyWrapper('//Alice');557558    const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;559560    const receiver = createEthAccount(web3);561562    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;563564    const address = tokenIdToAddress(collectionId, tokenId);565    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address);566567    const events = await recordEvents(contract, async () => {568      expect(await approve(api, collectionId, tokenId, alice, {Ethereum: receiver}, 100n)).to.be.true;569    });570571    expect(events).to.be.deep.equal([572      {573        address,574        event: 'Approval',575        args: {576          owner: subToEth(alice.address),577          spender: receiver,578          value: '100',579        },580      },581    ]);582  });583584  itWeb3('Events emitted for transferFrom()', async ({web3, api, privateKeyWrapper}) => {585    const alice = privateKeyWrapper('//Alice');586587    const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;588    const bob = privateKeyWrapper('//Bob');589590    const receiver = createEthAccount(web3);591592    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;593    expect(await approve(api, collectionId, tokenId, alice, bob.address, 100n)).to.be.true;594595    const address = tokenIdToAddress(collectionId, tokenId);596    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address);597598    const events = await recordEvents(contract, async () => {599      expect(await transferFrom(api, collectionId, tokenId, bob, alice, {Ethereum: receiver},  51n)).to.be.true;600    });601602    expect(events).to.be.deep.equal([603      {604        address,605        event: 'Transfer',606        args: {607          from: subToEth(alice.address),608          to: receiver,609          value: '51',610        },611      },612      {613        address,614        event: 'Approval',615        args: {616          owner: subToEth(alice.address),617          spender: subToEth(bob.address),618          value: '49',619        },620      },621    ]);622  });623624  itWeb3('Events emitted for transfer()', async ({web3, api, privateKeyWrapper}) => {625    const alice = privateKeyWrapper('//Alice');626627    const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;628629    const receiver = createEthAccount(web3);630631    const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;632633    const address = tokenIdToAddress(collectionId, tokenId);634    const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address);635636    const events = await recordEvents(contract, async () => {637      expect(await transfer(api, collectionId, tokenId, alice, {Ethereum: receiver},  51n)).to.be.true;638    });639640    expect(events).to.be.deep.equal([641      {642        address,643        event: 'Transfer',644        args: {645          from: subToEth(alice.address),646          to: receiver,647          value: '51',648        },649      },650    ]);651  });652});