From 60b3f3e6dd39afe12884a17f9d978dd604a138b5 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Sun, 25 Jun 2017 14:50:11 -0700 Subject: Implement EtherTokenWrapper and tests, with deposit and withdraw methods --- test/ether_token_wrapper_test.ts | 99 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 test/ether_token_wrapper_test.ts (limited to 'test') diff --git a/test/ether_token_wrapper_test.ts b/test/ether_token_wrapper_test.ts new file mode 100644 index 000000000..730b85497 --- /dev/null +++ b/test/ether_token_wrapper_test.ts @@ -0,0 +1,99 @@ +import 'mocha'; +import * as chai from 'chai'; +import {chaiSetup} from './utils/chai_setup'; +import * as Web3 from 'web3'; +import * as BigNumber from 'bignumber.js'; +import promisify = require('es6-promisify'); +import {web3Factory} from './utils/web3_factory'; +import {ZeroEx, ZeroExError, Token} from '../src'; +import {BlockchainLifecycle} from './utils/blockchain_lifecycle'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(); + +describe.only('EtherTokenWrapper', () => { + let web3: Web3; + let zeroEx: ZeroEx; + let userAddresses: string[]; + let addressWithETH: string; + let wethContractAddress: string; + let depositETHAmount: BigNumber.BigNumber; + let depositWeiAmount: BigNumber.BigNumber; + let decimalPlaces: number; + before(async () => { + web3 = web3Factory.create(); + zeroEx = new ZeroEx(web3.currentProvider); + userAddresses = await promisify(web3.eth.getAccounts)(); + addressWithETH = userAddresses[0]; + wethContractAddress = await zeroEx.etherToken.getContractAddressAsync(); + depositETHAmount = new BigNumber(5); + depositWeiAmount = (zeroEx as any)._web3Wrapper.toWei(depositETHAmount); + decimalPlaces = 7; + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + describe('#depositAsync', () => { + it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => { + const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); + expect(preETHBalance).to.be.bignumber.gt(0); + expect(preWETHBalance).to.be.bignumber.equal(0); + + await zeroEx.etherToken.depositAsync(depositWeiAmount, addressWithETH); + + const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); + + expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(depositWeiAmount); + const remainingETH = preETHBalance.minus(depositETHAmount); + return expect(postETHBalance.round(decimalPlaces)).to.be.bignumber.equal(remainingETH); + }); + it('should throw if user has insufficient ETH balance for deposit', async () => { + const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + + const overETHBalance = preETHBalance.add(5); + const overETHBalanceinWei = (zeroEx as any)._web3Wrapper.toWei(overETHBalance); + + return expect( + zeroEx.etherToken.depositAsync(overETHBalanceinWei, addressWithETH), + ).to.be.rejectedWith(ZeroExError.INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT); + }); + }); + describe('#withdrawAsync', () => { + it('should successfully withdraw ETH in return for Wrapped ETH tokens', async () => { + const ETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + + await zeroEx.etherToken.depositAsync(depositWeiAmount, addressWithETH); + + const expectedPreETHBalance = ETHBalance.minus(depositETHAmount); + const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); + expect(preETHBalance.round(decimalPlaces)).to.be.bignumber.equal(expectedPreETHBalance); + expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount); + + await zeroEx.etherToken.withdrawAsync(depositWeiAmount, addressWithETH); + + const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); + + expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(0); + const expectedETHBalance = preETHBalance.add(depositETHAmount).round(decimalPlaces); + return expect(postETHBalance.round(decimalPlaces)).to.be.bignumber.equal(expectedETHBalance); + }); + it('should throw if user has insufficient WETH balance for withdrawl', async () => { + const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); + expect(preWETHBalance).to.be.bignumber.equal(0); + + const overWETHBalance = preWETHBalance.add(999999999); + + return expect( + zeroEx.etherToken.withdrawAsync(overWETHBalance, addressWithETH), + ).to.be.rejectedWith(ZeroExError.INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWL); + }); + }); +}); -- cgit v1.2.3 From 0f413febd3cf2798a9be1149b1ef7ddd3550f7d0 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Mon, 26 Jun 2017 10:30:09 -0700 Subject: Fix typo --- test/ether_token_wrapper_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/ether_token_wrapper_test.ts b/test/ether_token_wrapper_test.ts index 730b85497..60fe00925 100644 --- a/test/ether_token_wrapper_test.ts +++ b/test/ether_token_wrapper_test.ts @@ -93,7 +93,7 @@ describe.only('EtherTokenWrapper', () => { return expect( zeroEx.etherToken.withdrawAsync(overWETHBalance, addressWithETH), - ).to.be.rejectedWith(ZeroExError.INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWL); + ).to.be.rejectedWith(ZeroExError.INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL); }); }); }); -- cgit v1.2.3 From 41098c6a35cc483b30ddc0566ca18c98b1548364 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Mon, 26 Jun 2017 11:20:16 -0700 Subject: refactor getBalanceInEthAsync to getBalanceInWeiAsync and change the test assertions to check if the discrepancy between the existing ETH balance and expected balance is small enough to simply be the gas cost used by the transaction. --- test/ether_token_wrapper_test.ts | 43 +++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'test') diff --git a/test/ether_token_wrapper_test.ts b/test/ether_token_wrapper_test.ts index 60fe00925..ebce81e97 100644 --- a/test/ether_token_wrapper_test.ts +++ b/test/ether_token_wrapper_test.ts @@ -12,13 +12,18 @@ chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(); -describe.only('EtherTokenWrapper', () => { +// Since the address depositing/withdrawing ETH/WETH also needs to pay gas costs for the transaction, +// a small amount of ETH will be used to pay this gas cost. We therefore check that the difference between +// the expected balance and actual balance (given the amount of ETH deposited), only deviates by the amount +// required to pay gas costs. +const MAX_REASONABLE_GAS_COST_IN_WEI = 62237; + +describe('EtherTokenWrapper', () => { let web3: Web3; let zeroEx: ZeroEx; let userAddresses: string[]; let addressWithETH: string; let wethContractAddress: string; - let depositETHAmount: BigNumber.BigNumber; let depositWeiAmount: BigNumber.BigNumber; let decimalPlaces: number; before(async () => { @@ -27,8 +32,7 @@ describe.only('EtherTokenWrapper', () => { userAddresses = await promisify(web3.eth.getAccounts)(); addressWithETH = userAddresses[0]; wethContractAddress = await zeroEx.etherToken.getContractAddressAsync(); - depositETHAmount = new BigNumber(5); - depositWeiAmount = (zeroEx as any)._web3Wrapper.toWei(depositETHAmount); + depositWeiAmount = (zeroEx as any)._web3Wrapper.toWei(new BigNumber(5)); decimalPlaces = 7; }); beforeEach(async () => { @@ -39,25 +43,26 @@ describe.only('EtherTokenWrapper', () => { }); describe('#depositAsync', () => { it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => { - const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); expect(preETHBalance).to.be.bignumber.gt(0); expect(preWETHBalance).to.be.bignumber.equal(0); await zeroEx.etherToken.depositAsync(depositWeiAmount, addressWithETH); - const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + const postETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(depositWeiAmount); - const remainingETH = preETHBalance.minus(depositETHAmount); - return expect(postETHBalance.round(decimalPlaces)).to.be.bignumber.equal(remainingETH); + const remainingETHInWei = preETHBalance.minus(depositWeiAmount); + const gasCost = remainingETHInWei.minus(postETHBalanceInWei); + expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI); }); it('should throw if user has insufficient ETH balance for deposit', async () => { - const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); - const overETHBalance = preETHBalance.add(5); - const overETHBalanceinWei = (zeroEx as any)._web3Wrapper.toWei(overETHBalance); + const extraETHBalance = (zeroEx as any)._web3Wrapper.toWei(5, 'ether'); + const overETHBalanceinWei = preETHBalance.add(extraETHBalance); return expect( zeroEx.etherToken.depositAsync(overETHBalanceinWei, addressWithETH), @@ -66,24 +71,26 @@ describe.only('EtherTokenWrapper', () => { }); describe('#withdrawAsync', () => { it('should successfully withdraw ETH in return for Wrapped ETH tokens', async () => { - const ETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + const ETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); await zeroEx.etherToken.depositAsync(depositWeiAmount, addressWithETH); - const expectedPreETHBalance = ETHBalance.minus(depositETHAmount); - const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + const expectedPreETHBalance = ETHBalanceInWei.minus(depositWeiAmount); + const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); - expect(preETHBalance.round(decimalPlaces)).to.be.bignumber.equal(expectedPreETHBalance); + let gasCost = expectedPreETHBalance.minus(preETHBalance); + expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI); expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount); await zeroEx.etherToken.withdrawAsync(depositWeiAmount, addressWithETH); - const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInEthAsync(addressWithETH); + const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(0); - const expectedETHBalance = preETHBalance.add(depositETHAmount).round(decimalPlaces); - return expect(postETHBalance.round(decimalPlaces)).to.be.bignumber.equal(expectedETHBalance); + const expectedETHBalance = preETHBalance.add(depositWeiAmount).round(decimalPlaces); + gasCost = expectedETHBalance.minus(postETHBalance); + expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI); }); it('should throw if user has insufficient WETH balance for withdrawl', async () => { const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); -- cgit v1.2.3