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

difftreelog

source

tests/src/eth/fungible.test.ts19.8 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 {expect, itEth, usingEthPlaygrounds} from './util';18import {IKeyringPair} from '@polkadot/types/types';1920describe('Fungible: Information getting', () => {21  let donor: IKeyringPair;22  let alice: IKeyringPair;2324  before(async function() {25    await usingEthPlaygrounds(async (helper, privateKey) => {26      donor = await privateKey({filename: __filename});27      [alice] = await helper.arrange.createAccounts([20n], donor);28    });29  });3031  itEth('totalSupply', async ({helper}) => {32    const caller = await helper.eth.createAccountWithBalance(donor);33    const collection = await helper.ft.mintCollection(alice);34    await collection.mint(alice, 200n);3536    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller);37    const totalSupply = await contract.methods.totalSupply().call();38    expect(totalSupply).to.equal('200');39  });4041  itEth('balanceOf', async ({helper}) => {42    const caller = await helper.eth.createAccountWithBalance(donor);43    const collection = await helper.ft.mintCollection(alice);44    await collection.mint(alice, 200n, {Ethereum: caller});4546    const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller);47    const balance = await contract.methods.balanceOf(caller).call();48    expect(balance).to.equal('200');49  });50});5152describe('Fungible: Plain calls', () => {53  let donor: IKeyringPair;54  let alice: IKeyringPair;5556  before(async function() {57    await usingEthPlaygrounds(async (helper, privateKey) => {58      donor = await privateKey({filename: __filename});59      [alice] = await helper.arrange.createAccounts([20n], donor);60    });61  });6263  itEth('Can perform mint()', async ({helper}) => {64    const owner = await helper.eth.createAccountWithBalance(donor);65    const receiver = helper.eth.createAccount();66    const collection = await helper.ft.mintCollection(alice);67    await collection.addAdmin(alice, {Ethereum: owner});6869    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);70    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);7172    const result = await contract.methods.mint(receiver, 100).send();73    74    const event = result.events.Transfer;75    expect(event.address).to.equal(collectionAddress);76    expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');77    expect(event.returnValues.to).to.equal(receiver);78    expect(event.returnValues.value).to.equal('100');79  });8081  itEth('Can perform mintBulk()', async ({helper}) => {82    const owner = await helper.eth.createAccountWithBalance(donor);83    const bulkSize = 3;84    const receivers = [...new Array(bulkSize)].map(() => helper.eth.createAccount());85    const collection = await helper.ft.mintCollection(alice);86    await collection.addAdmin(alice, {Ethereum: owner});8788    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);89    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);9091    const result = await contract.methods.mintBulk(Array.from({length: bulkSize}, (_, i) => (92      [receivers[i], (i + 1) * 10]93    ))).send();94    const events = result.events.Transfer.sort((a: any, b: any) => +a.returnValues.value - b.returnValues.value);95    for (let i = 0; i < bulkSize; i++) {96      const event = events[i];97      expect(event.address).to.equal(collectionAddress);98      expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000');99      expect(event.returnValues.to).to.equal(receivers[i]);100      expect(event.returnValues.value).to.equal(String(10 * (i + 1)));101    }102  });103104  itEth('Can perform burn()', async ({helper}) => {105    const owner = await helper.eth.createAccountWithBalance(donor);106    const receiver = await helper.eth.createAccountWithBalance(donor);107    const collection = await helper.ft.mintCollection(alice);108    await collection.addAdmin(alice, {Ethereum: owner});109110    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);111    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);112    await contract.methods.mint(receiver, 100).send();113114    const result = await contract.methods.burnFrom(receiver, 49).send({from: receiver});115    116    const event = result.events.Transfer;117    expect(event.address).to.equal(collectionAddress);118    expect(event.returnValues.from).to.equal(receiver);119    expect(event.returnValues.to).to.equal('0x0000000000000000000000000000000000000000');120    expect(event.returnValues.value).to.equal('49');121122    const balance = await contract.methods.balanceOf(receiver).call();123    expect(balance).to.equal('51');124  });125126  itEth('Can perform approve()', async ({helper}) => {127    const owner = await helper.eth.createAccountWithBalance(donor);128    const spender = helper.eth.createAccount();129    const collection = await helper.ft.mintCollection(alice);130    await collection.mint(alice, 200n, {Ethereum: owner});131132    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);133    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);134135    {136      const result = await contract.methods.approve(spender, 100).send({from: owner});137138      const event = result.events.Approval;139      expect(event.address).to.be.equal(collectionAddress);140      expect(event.returnValues.owner).to.be.equal(owner);141      expect(event.returnValues.spender).to.be.equal(spender);142      expect(event.returnValues.value).to.be.equal('100');143    }144145    {146      const allowance = await contract.methods.allowance(owner, spender).call();147      expect(+allowance).to.equal(100);148    }149  });150151  itEth('Can perform burnFromCross()', async ({helper}) => {152    const sender = await helper.eth.createAccountWithBalance(donor, 100n);153154    const collection = await helper.ft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);155156    await collection.mint(alice, 200n, {Substrate: alice.address});157    await collection.approveTokens(alice, {Ethereum: sender}, 100n);158159    const address = helper.ethAddress.fromCollectionId(collection.collectionId);160    const contract = helper.ethNativeContract.collection(address, 'ft');161162    const fromBalanceBefore = await collection.getBalance({Substrate: alice.address});163    164    const ownerCross = helper.ethCrossAccount.fromKeyringPair(alice);165    const result = await contract.methods.burnFromCross(ownerCross, 49).send({from: sender});166    const events = result.events;167168    expect(events).to.be.like({169      Transfer: {170        address: helper.ethAddress.fromCollectionId(collection.collectionId),171        event: 'Transfer',172        returnValues: {173          from: helper.address.substrateToEth(alice.address),174          to: '0x0000000000000000000000000000000000000000',175          value: '49',176        },177      },178      Approval: {179        address: helper.ethAddress.fromCollectionId(collection.collectionId),180        returnValues: {181          owner: helper.address.substrateToEth(alice.address),182          spender: sender,183          value: '51',184        },185        event: 'Approval',186      },187    });188189    const fromBalanceAfter = await collection.getBalance({Substrate: alice.address});190    expect(fromBalanceBefore - fromBalanceAfter).to.be.eq(49n);191  });192193  itEth('Can perform transferFrom()', async ({helper}) => {194    const owner = await helper.eth.createAccountWithBalance(donor);195    const spender = await helper.eth.createAccountWithBalance(donor);196    const receiver = helper.eth.createAccount();197    const collection = await helper.ft.mintCollection(alice);198    await collection.mint(alice, 200n, {Ethereum: owner});199200    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);201    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);202203    await contract.methods.approve(spender, 100).send();204205    {206      const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender});207      208      let event = result.events.Transfer;209      expect(event.address).to.be.equal(collectionAddress);210      expect(event.returnValues.from).to.be.equal(owner);211      expect(event.returnValues.to).to.be.equal(receiver);212      expect(event.returnValues.value).to.be.equal('49');213214      event = result.events.Approval;215      expect(event.address).to.be.equal(collectionAddress);216      expect(event.returnValues.owner).to.be.equal(owner);217      expect(event.returnValues.spender).to.be.equal(spender);218      expect(event.returnValues.value).to.be.equal('51');219    }220221    {222      const balance = await contract.methods.balanceOf(receiver).call();223      expect(+balance).to.equal(49);224    }225226    {227      const balance = await contract.methods.balanceOf(owner).call();228      expect(+balance).to.equal(151);229    }230  });231232  itEth('Can perform transfer()', async ({helper}) => {233    const owner = await helper.eth.createAccountWithBalance(donor);234    const receiver = await helper.eth.createAccountWithBalance(donor);235    const collection = await helper.ft.mintCollection(alice);236    await collection.mint(alice, 200n, {Ethereum: owner});237238    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);239    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);240241    {242      const result = await contract.methods.transfer(receiver, 50).send({from: owner});243      244      const event = result.events.Transfer;245      expect(event.address).to.be.equal(collectionAddress);246      expect(event.returnValues.from).to.be.equal(owner);247      expect(event.returnValues.to).to.be.equal(receiver);248      expect(event.returnValues.value).to.be.equal('50');249    }250251    {252      const balance = await contract.methods.balanceOf(owner).call();253      expect(+balance).to.equal(150);254    }255256    {257      const balance = await contract.methods.balanceOf(receiver).call();258      expect(+balance).to.equal(50);259    }260  });261262  itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {263    const sender = await helper.eth.createAccountWithBalance(donor, 100n);264265    const collection = await helper.ft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);266267    const receiver = helper.eth.createAccount();268269    await collection.mint(alice, 200n, {Substrate: alice.address});270    await collection.approveTokens(alice, {Ethereum: sender}, 100n);271272    const address = helper.ethAddress.fromCollectionId(collection.collectionId);273    const contract = helper.ethNativeContract.collection(address, 'ft');274275    const from = helper.ethCrossAccount.fromKeyringPair(alice);276    const to = helper.ethCrossAccount.fromAddress(receiver);277278    const fromBalanceBefore = await collection.getBalance({Substrate: alice.address});279    const toBalanceBefore = await collection.getBalance({Ethereum: receiver});280    281    const result = await contract.methods.transferFromCross(from, to, 51).send({from: sender});282283    expect(result.events).to.be.like({284      Transfer: {285        address,286        event: 'Transfer',287        returnValues: {288          from: helper.address.substrateToEth(alice.address),289          to: receiver,290          value: '51',291        },292      },293      Approval: {294        address,295        event: 'Approval',296        returnValues: {297          owner: helper.address.substrateToEth(alice.address),298          spender: sender,299          value: '49',300        },301      }});302303    const fromBalanceAfter = await collection.getBalance({Substrate: alice.address});304    expect(fromBalanceBefore - fromBalanceAfter).to.be.eq(51n);305    const toBalanceAfter = await collection.getBalance({Ethereum: receiver});306    expect(toBalanceAfter - toBalanceBefore).to.be.eq(51n);307  });308});309310describe('Fungible: Fees', () => {311  let donor: IKeyringPair;312  let alice: IKeyringPair;313314  before(async function() {315    await usingEthPlaygrounds(async (helper, privateKey) => {316      donor = await privateKey({filename: __filename});317      [alice] = await helper.arrange.createAccounts([20n], donor);318    });319  });320  321  itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => {322    const owner = await helper.eth.createAccountWithBalance(donor);323    const spender = helper.eth.createAccount();324    const collection = await helper.ft.mintCollection(alice);325    await collection.mint(alice, 200n, {Ethereum: owner});326327    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);328    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);329330    const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, 100).send({from: owner}));331    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));332  });333334  itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {335    const owner = await helper.eth.createAccountWithBalance(donor);336    const spender = await helper.eth.createAccountWithBalance(donor);337    const collection = await helper.ft.mintCollection(alice);338    await collection.mint(alice, 200n, {Ethereum: owner});339340    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);341    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);342343    await contract.methods.approve(spender, 100).send({from: owner});344345    const cost = await helper.eth.recordCallFee(spender, () => contract.methods.transferFrom(owner, spender, 100).send({from: spender}));346    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));347  });348349  itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {350    const owner = await helper.eth.createAccountWithBalance(donor);351    const receiver = helper.eth.createAccount();352    const collection = await helper.ft.mintCollection(alice);353    await collection.mint(alice, 200n, {Ethereum: owner});354355    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);356    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);357358    const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));359    expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));360  });361});362363describe('Fungible: Substrate calls', () => {364  let donor: IKeyringPair;365  let alice: IKeyringPair;366367  before(async function() {368    await usingEthPlaygrounds(async (helper, privateKey) => {369      donor = await privateKey({filename: __filename});370      [alice] = await helper.arrange.createAccounts([20n], donor);371    });372  });373374  itEth('Events emitted for approve()', async ({helper}) => {375    const receiver = helper.eth.createAccount();376    const collection = await helper.ft.mintCollection(alice);377    await collection.mint(alice, 200n);378379    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);380    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft');381382    const events: any = [];383    contract.events.allEvents((_: any, event: any) => {384      events.push(event);385    });386    387    await collection.approveTokens(alice, {Ethereum: receiver}, 100n);388    if (events.length == 0) await helper.wait.newBlocks(1);389    const event = events[0];390391    expect(event.event).to.be.equal('Approval');392    expect(event.address).to.be.equal(collectionAddress);393    expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));394    expect(event.returnValues.spender).to.be.equal(receiver);395    expect(event.returnValues.value).to.be.equal('100');396  });397398  itEth('Events emitted for transferFrom()', async ({helper}) => {399    const [bob] = await helper.arrange.createAccounts([10n], donor);400    const receiver = helper.eth.createAccount();401    const collection = await helper.ft.mintCollection(alice);402    await collection.mint(alice, 200n);403    await collection.approveTokens(alice, {Substrate: bob.address}, 100n);404405    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);406    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft');407408    const events: any = [];409    contract.events.allEvents((_: any, event: any) => {410      events.push(event);411    });412413    await collection.transferFrom(bob, {Substrate: alice.address}, {Ethereum: receiver}, 51n);414    if (events.length == 0) await helper.wait.newBlocks(1);415    let event = events[0];416417    expect(event.event).to.be.equal('Transfer');418    expect(event.address).to.be.equal(collectionAddress);419    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));420    expect(event.returnValues.to).to.be.equal(receiver);421    expect(event.returnValues.value).to.be.equal('51');422423    event = events[1];424    expect(event.event).to.be.equal('Approval');425    expect(event.address).to.be.equal(collectionAddress);426    expect(event.returnValues.owner).to.be.equal(helper.address.substrateToEth(alice.address));427    expect(event.returnValues.spender).to.be.equal(helper.address.substrateToEth(bob.address));428    expect(event.returnValues.value).to.be.equal('49');429  });430431  itEth('Events emitted for transfer()', async ({helper}) => {432    const receiver = helper.eth.createAccount();433    const collection = await helper.ft.mintCollection(alice);434    await collection.mint(alice, 200n);435436    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);437    const contract = helper.ethNativeContract.collection(collectionAddress, 'ft');438439    const events: any = [];440    contract.events.allEvents((_: any, event: any) => {441      events.push(event);442    });443    444    await collection.transfer(alice, {Ethereum:receiver}, 51n);445    if (events.length == 0) await helper.wait.newBlocks(1);446    const event = events[0];447448    expect(event.event).to.be.equal('Transfer');449    expect(event.address).to.be.equal(collectionAddress);450    expect(event.returnValues.from).to.be.equal(helper.address.substrateToEth(alice.address));451    expect(event.returnValues.to).to.be.equal(receiver);452    expect(event.returnValues.value).to.be.equal('51');453  });454455  itEth('Events emitted for transferFromCross()', async ({helper, privateKey}) => {456    const sender = await helper.eth.createAccountWithBalance(donor, 100n);457458    const collection = await helper.ft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);459460    const receiver = helper.eth.createAccount();461462    await collection.mint(alice, 200n, {Substrate: alice.address});463    await collection.approveTokens(alice, {Ethereum: sender}, 100n);464465    const address = helper.ethAddress.fromCollectionId(collection.collectionId);466    const contract = helper.ethNativeContract.collection(address, 'ft');467468    const from = helper.ethCrossAccount.fromKeyringPair(alice);469    const to = helper.ethCrossAccount.fromAddress(receiver);470    471    const result = await contract.methods.transferFromCross(from, to, 51).send({from: sender});472473    expect(result.events).to.be.like({474      Transfer: {475        address,476        event: 'Transfer',477        returnValues: {478          from: helper.address.substrateToEth(alice.address),479          to: receiver,480          value: '51',481        },482      },483      Approval: {484        address,485        event: 'Approval',486        returnValues: {487          owner: helper.address.substrateToEth(alice.address),488          spender: sender,489          value: '49',490        },491      }});492  });493});