import { ContractMeta, Awaiter, Assertion } from '@libotony/sharp' import { assert } from 'chai' import { connex, wallet } from './connex-loader' import { toWei, fromWei } from './utils' const mvgTokenContract = require('../output/MVG.json') const mvgToken = new ContractMeta(mvgTokenContract.abi, mvgTokenContract.bytecode) const thor = connex.thor const vendor = connex.vendor let address = '' const zeroAddress = '0x' + '00'.repeat(20) const addrOne = wallet.list[0].address const addrTwo = wallet.list[1].address const addrThree = wallet.list[2].address describe('MVG', () => { it('deploy contract', async () => { const clause = mvgToken.deploy().asClause() const { txid } = await vendor.sign('tx').request([clause]) const receipt = await Awaiter.receipt(thor.transaction(txid), thor.ticker()) assert.isFalse(receipt.reverted, 'Should not be reverted') assert.equal(receipt.outputs[0].events.length, 2, 'Clause#0 should emit two events') assert.isTrue(!!receipt.outputs[0].contractAddress) console.log("receipt.outputs[0].contractAddress: ", receipt.outputs[0].contractAddress) address = receipt.outputs[0].contractAddress! Assertion .event(mvgToken.ABI('Transfer', 'event')) .by(address) .logs(zeroAddress, addrOne, toWei(1e11)) .equal(receipt.outputs[0].events[1]) }) describe('token basics', () => { it('account#0 balance', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('balanceOf')) .call(addrOne) Assertion .method(mvgToken.ABI('balanceOf')) .outputs(toWei(1e11)) .equal(ret) }) it('totalSupply', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('totalSupply')) .call() Assertion .method(mvgToken.ABI('totalSupply')) .outputs(toWei(1e11)) .equal(ret) }) it('name', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('name')) .call() Assertion .method(mvgToken.ABI('name')) .outputs('MVG') .equal(ret) }) it('symbol', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('symbol')) .call() Assertion .method(mvgToken.ABI('symbol')) .outputs('MVG') .equal(ret) }) it('decimals', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('decimals')) .call() Assertion .method(mvgToken.ABI('decimals')) .outputs('18') .equal(ret) }) }) describe('transfer', async () => { it('transfer - not enough amount - should revert', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('transfer')) .caller(addrTwo) .call(addrOne, toWei(100)) Assertion .revert() .with('VIP180: transfer amount exceeds balance') .equal(ret) }) it('transfer - from zero address - should revert', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('transfer')) .caller(zeroAddress) .call(addrOne, toWei(100)) Assertion .revert() .with('VIP180: transfer from the zero address') .equal(ret) }) it('transfer - to zero address - should revert', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('transfer')) .caller(addrOne) .call(zeroAddress, toWei(100)) Assertion .revert() .with('VIP180: transfer to the zero address') .equal(ret) }) }) describe('transfer and balanceOf', async () => { it('transfer should emit Transfer', async () => { const { txid } = await vendor.sign('tx') .signer(addrOne) .request([ thor.account(address) .method(mvgToken.ABI('transfer')) .asClause(addrTwo, toWei(100)) ]) const receipt = await Awaiter.receipt(thor.transaction(txid), thor.ticker()) assert.isFalse(receipt.reverted, 'Should not be reverted') assert.equal(receipt.outputs[0].events.length, 1, 'Clause#0 should emit one event') Assertion .event(mvgToken.ABI('Transfer', 'event')) .by(address) .logs(addrOne, addrTwo, toWei(100)) .equal(receipt.outputs[0].events[0]) }) it('after transfer, check addrOne balance', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('balanceOf')) .call(addrOne) Assertion .method(mvgToken.ABI('balanceOf')) .outputs(toWei(1e11 - 100)) .equal(ret) }) it('after transfer, check addrTwo balance', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('balanceOf')) .call(addrTwo) Assertion .method(mvgToken.ABI('balanceOf')) .outputs(toWei(100)) .equal(ret) }) }) describe('approve', async () => { it('approve from zero address - should revert', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('approve')) .caller(zeroAddress) .call(addrOne, toWei(100)) Assertion .revert() .with('VIP180: approve from the zero address') .equal(ret) }) it('approve - to spender-zero address should revert', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('approve')) .caller(addrOne) .call(zeroAddress, toWei(100)) Assertion .revert() .with('VIP180: approve to the zero address') .equal(ret) }) it('approve - should emit - Approval event', async () => { const { txid } = await vendor.sign('tx') .signer(addrOne) .request([ thor.account(address) .method(mvgToken.ABI('approve')) .asClause(addrTwo, toWei(100)) ]) const receipt = await Awaiter.receipt(thor.transaction(txid), thor.ticker()) assert.isFalse(receipt.reverted, 'Should not be reverted') assert.equal(receipt.outputs[0].events.length, 1, 'Clause#0 should emit one event') Assertion .event(mvgToken.ABI('Approval', 'event')) .by(address) .logs(addrOne, addrTwo, toWei(100)) .equal(receipt.outputs[0].events[0]) }) }) describe('allowance and transferFrom', async () => { it('allowance should be zero in the first time', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('allowance')) .call(addrTwo, addrOne) Assertion .method(mvgToken.ABI('allowance')) .outputs('0') .equal(ret) }) it('addrTwo should have allowance from addrOne', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('allowance')) .call(addrOne, addrTwo) Assertion .method(mvgToken.ABI('allowance')) .outputs(toWei('100')) .equal(ret) }) it('transferFrom greater amount should revert', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('transferFrom')) .caller(addrTwo) .call(addrOne, addrThree, toWei(101)) Assertion .revert() .with('VIP180: transfer amount exceeds allowance') .equal(ret) }) it('transferFrom - should emit - Transfer and Approval event', async () => { const { txid } = await vendor.sign('tx') .signer(addrTwo) .request([ thor.account(address) .method(mvgToken.ABI('transferFrom')) .asClause(addrOne, addrThree, toWei(50)) ]) const receipt = await Awaiter.receipt(thor.transaction(txid), thor.ticker()) assert.isFalse(receipt.reverted, 'Should not be reverted') assert.equal(receipt.outputs[0].events.length, 2, 'Clause#0 should emit two events') Assertion .event(mvgToken.ABI('Transfer', 'event')) .by(address) .logs(addrOne, addrThree, toWei(50)) .equal(receipt.outputs[0].events[0]) Assertion .event(mvgToken.ABI('Approval', 'event')) .by(address) .logs(addrOne, addrTwo, toWei(50)) .equal(receipt.outputs[0].events[1]) }) it('after transferFrom, check addrOne balance', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('balanceOf')) .call(addrOne) Assertion .method(mvgToken.ABI('balanceOf')) .outputs(toWei(1e11 - 100 - 50)) .equal(ret) }) it('after transferFrom, check addrThree balance', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('balanceOf')) .call(addrThree) Assertion .method(mvgToken.ABI('balanceOf')) .outputs(toWei(50)) .equal(ret) }) it('after transferFrom, check addrTwo\'s allowance from addrOne', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('allowance')) .call(addrOne, addrTwo) Assertion .method(mvgToken.ABI('allowance')) .outputs(toWei('50')) .equal(ret) }) }) describe('increaseAllowance and decreaseAllowance', async () => { it('decreaseAllowance greater than allowance should revert', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('decreaseAllowance')) .caller(addrOne) .call(addrTwo, toWei(51)) Assertion .revert() .with('VIP180: decreased allowance below zero') .equal(ret) }) it('decreaseAllowance should emit Approval event', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('decreaseAllowance')) .caller(addrOne) .call(addrTwo, toWei(10)) assert.isFalse(ret.reverted, 'Should not be reverted') assert.equal(ret.events.length, 1, 'Should emit one event') Assertion .event(mvgToken.ABI('Approval', 'event')) .by(address) .logs(addrOne, addrTwo, toWei(40)) .equal(ret.events[0]) }) it('increaseAllowance should emit Approval event', async () => { const ret = await thor.account(address) .method(mvgToken.ABI('increaseAllowance')) .caller(addrOne) .call(addrTwo, toWei(10)) assert.isFalse(ret.reverted, 'Should not be reverted') assert.equal(ret.events.length, 1, 'Should emit one event') Assertion .event(mvgToken.ABI('Approval', 'event')) .by(address) .logs(addrOne, addrTwo, toWei(60)) .equal(ret.events[0]) }) }) })