From 7d59faa65069f11bf873215d531637fa0a732232 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 1 Dec 2017 16:47:38 -0800 Subject: Add updated ERC20 implementation, update WETH --- packages/contracts/contracts/base/ERC20Token.sol | 50 +++++++++++++++++++ .../contracts/contracts/deprecated/EtherToken.sol | 56 ++++++++++++++++++++++ packages/contracts/contracts/tokens/EtherToken.sol | 6 ++- 3 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 packages/contracts/contracts/base/ERC20Token.sol create mode 100644 packages/contracts/contracts/deprecated/EtherToken.sol (limited to 'packages') diff --git a/packages/contracts/contracts/base/ERC20Token.sol b/packages/contracts/contracts/base/ERC20Token.sol new file mode 100644 index 000000000..765cd7274 --- /dev/null +++ b/packages/contracts/contracts/base/ERC20Token.sol @@ -0,0 +1,50 @@ +pragma solidity 0.4.11; + +import "./Token.sol"; + +contract ERC20Token is Token { + + uint constant MAX_UINT = 2**256 - 1; + + function transfer(address _to, uint _value) returns (bool) { + require(balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]); + balances[msg.sender] -= _value; + balances[_to] += _value; + Transfer(msg.sender, _to, _value); + return true; + } + + /// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance. See https://github.com/ethereum/EIPs/issues/717 + /// @param _from Address to transfer from. + /// @param _to Address to transfer to. + /// @param _value Amount to transfer. + /// @return Success of transfer. + function transferFrom(address _from, address _to, uint _value) returns (bool) { + require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value >= balances[_to]); + balances[_to] += _value; + balances[_from] -= _value; + if (allowance < MAX_UINT) { + allowed[_from][msg.sender] -= _value; + } + Transfer(_from, _to, _value); + return true; + } + + function balanceOf(address _owner) constant returns (uint) { + return balances[_owner]; + } + + function approve(address _spender, uint _value) returns (bool) { + allowed[msg.sender][_spender] = _value; + Approval(msg.sender, _spender, _value); + return true; + } + + function allowance(address _owner, address _spender) constant returns (uint) { + return allowed[_owner][_spender]; + } + + mapping (address => uint) balances; + mapping (address => mapping (address => uint)) allowed; + uint public totalSupply; +} \ No newline at end of file diff --git a/packages/contracts/contracts/deprecated/EtherToken.sol b/packages/contracts/contracts/deprecated/EtherToken.sol new file mode 100644 index 000000000..68148e095 --- /dev/null +++ b/packages/contracts/contracts/deprecated/EtherToken.sol @@ -0,0 +1,56 @@ +/* + + Copyright 2017 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity 0.4.11; + +import "./UnlimitedAllowanceToken.sol"; +import "./../base/SafeMath.sol"; + +contract EtherToken is UnlimitedAllowanceToken, SafeMath { + + string constant public name = "Ether Token"; + string constant public symbol = "WETH"; + uint8 constant public decimals = 18; + + /// @dev Fallback to calling deposit when ether is sent directly to contract. + function() + public + payable + { + deposit(); + } + + /// @dev Buys tokens with Ether, exchanging them 1:1. + function deposit() + public + payable + { + balances[msg.sender] = safeAdd(balances[msg.sender], msg.value); + totalSupply = safeAdd(totalSupply, msg.value); + } + + /// @dev Sells tokens in exchange for Ether, exchanging them 1:1. + /// @param amount Number of tokens to sell. + function withdraw(uint amount) + public + { + balances[msg.sender] = safeSub(balances[msg.sender], amount); + totalSupply = safeSub(totalSupply, amount); + require(msg.sender.send(amount)); + } +} diff --git a/packages/contracts/contracts/tokens/EtherToken.sol b/packages/contracts/contracts/tokens/EtherToken.sol index 68148e095..5c0f0e536 100644 --- a/packages/contracts/contracts/tokens/EtherToken.sol +++ b/packages/contracts/contracts/tokens/EtherToken.sol @@ -18,10 +18,10 @@ pragma solidity 0.4.11; -import "./UnlimitedAllowanceToken.sol"; +import "./ERC20Token.sol"; import "./../base/SafeMath.sol"; -contract EtherToken is UnlimitedAllowanceToken, SafeMath { +contract EtherToken is ERC20Token, SafeMath { string constant public name = "Ether Token"; string constant public symbol = "WETH"; @@ -42,6 +42,7 @@ contract EtherToken is UnlimitedAllowanceToken, SafeMath { { balances[msg.sender] = safeAdd(balances[msg.sender], msg.value); totalSupply = safeAdd(totalSupply, msg.value); + Transfer(address(0), msg.sender, msg.value); } /// @dev Sells tokens in exchange for Ether, exchanging them 1:1. @@ -52,5 +53,6 @@ contract EtherToken is UnlimitedAllowanceToken, SafeMath { balances[msg.sender] = safeSub(balances[msg.sender], amount); totalSupply = safeSub(totalSupply, amount); require(msg.sender.send(amount)); + Tranfer(msg.sender, address(0), msg.value); } } -- cgit v1.2.3 From 7008e882c0508939da117cd90fe06e7006b85300 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 4 Dec 2017 13:25:01 -0800 Subject: Add version to new EtherToken, fix typos --- packages/contracts/contracts/base/ERC20Token.sol | 3 +- .../contracts/contracts/deprecated/EtherToken.sol | 2 +- packages/contracts/contracts/tokens/EtherToken.sol | 58 ---------- .../contracts/contracts/tokens/EtherToken_v2.sol | 58 ++++++++++ packages/contracts/test/ts/ether_token_v2.ts | 118 +++++++++++++++++++++ packages/contracts/util/artifacts.ts | 2 + 6 files changed, 181 insertions(+), 60 deletions(-) delete mode 100644 packages/contracts/contracts/tokens/EtherToken.sol create mode 100644 packages/contracts/contracts/tokens/EtherToken_v2.sol create mode 100644 packages/contracts/test/ts/ether_token_v2.ts (limited to 'packages') diff --git a/packages/contracts/contracts/base/ERC20Token.sol b/packages/contracts/contracts/base/ERC20Token.sol index 765cd7274..f0117894d 100644 --- a/packages/contracts/contracts/base/ERC20Token.sol +++ b/packages/contracts/contracts/base/ERC20Token.sol @@ -20,7 +20,8 @@ contract ERC20Token is Token { /// @param _value Amount to transfer. /// @return Success of transfer. function transferFrom(address _from, address _to, uint _value) returns (bool) { - require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value >= balances[_to]); + uint allowance = allowed[_from][msg.sender]; + require(balances[_from] >= _value && allowance >= _value && balances[_to] + _value >= balances[_to]); balances[_to] += _value; balances[_from] -= _value; if (allowance < MAX_UINT) { diff --git a/packages/contracts/contracts/deprecated/EtherToken.sol b/packages/contracts/contracts/deprecated/EtherToken.sol index 68148e095..566782e35 100644 --- a/packages/contracts/contracts/deprecated/EtherToken.sol +++ b/packages/contracts/contracts/deprecated/EtherToken.sol @@ -18,7 +18,7 @@ pragma solidity 0.4.11; -import "./UnlimitedAllowanceToken.sol"; +import "./../tokens/UnlimitedAllowanceToken.sol"; import "./../base/SafeMath.sol"; contract EtherToken is UnlimitedAllowanceToken, SafeMath { diff --git a/packages/contracts/contracts/tokens/EtherToken.sol b/packages/contracts/contracts/tokens/EtherToken.sol deleted file mode 100644 index 5c0f0e536..000000000 --- a/packages/contracts/contracts/tokens/EtherToken.sol +++ /dev/null @@ -1,58 +0,0 @@ -/* - - Copyright 2017 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity 0.4.11; - -import "./ERC20Token.sol"; -import "./../base/SafeMath.sol"; - -contract EtherToken is ERC20Token, SafeMath { - - string constant public name = "Ether Token"; - string constant public symbol = "WETH"; - uint8 constant public decimals = 18; - - /// @dev Fallback to calling deposit when ether is sent directly to contract. - function() - public - payable - { - deposit(); - } - - /// @dev Buys tokens with Ether, exchanging them 1:1. - function deposit() - public - payable - { - balances[msg.sender] = safeAdd(balances[msg.sender], msg.value); - totalSupply = safeAdd(totalSupply, msg.value); - Transfer(address(0), msg.sender, msg.value); - } - - /// @dev Sells tokens in exchange for Ether, exchanging them 1:1. - /// @param amount Number of tokens to sell. - function withdraw(uint amount) - public - { - balances[msg.sender] = safeSub(balances[msg.sender], amount); - totalSupply = safeSub(totalSupply, amount); - require(msg.sender.send(amount)); - Tranfer(msg.sender, address(0), msg.value); - } -} diff --git a/packages/contracts/contracts/tokens/EtherToken_v2.sol b/packages/contracts/contracts/tokens/EtherToken_v2.sol new file mode 100644 index 000000000..a75a2aa7c --- /dev/null +++ b/packages/contracts/contracts/tokens/EtherToken_v2.sol @@ -0,0 +1,58 @@ +/* + + Copyright 2017 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity 0.4.11; + +import "./../base/ERC20Token.sol"; +import "./../base/SafeMath.sol"; + +contract EtherToken_v2 is ERC20Token, SafeMath { + + string constant public name = "Ether Token"; + string constant public symbol = "WETH"; + uint8 constant public decimals = 18; + + /// @dev Fallback to calling deposit when ether is sent directly to contract. + function() + public + payable + { + deposit(); + } + + /// @dev Buys tokens with Ether, exchanging them 1:1. + function deposit() + public + payable + { + balances[msg.sender] = safeAdd(balances[msg.sender], msg.value); + totalSupply = safeAdd(totalSupply, msg.value); + Transfer(address(0), msg.sender, msg.value); + } + + /// @dev Sells tokens in exchange for Ether, exchanging them 1:1. + /// @param amount Number of tokens to sell. + function withdraw(uint amount) + public + { + balances[msg.sender] = safeSub(balances[msg.sender], amount); + totalSupply = safeSub(totalSupply, amount); + require(msg.sender.send(amount)); + Transfer(msg.sender, address(0), amount); + } +} diff --git a/packages/contracts/test/ts/ether_token_v2.ts b/packages/contracts/test/ts/ether_token_v2.ts new file mode 100644 index 000000000..857371578 --- /dev/null +++ b/packages/contracts/test/ts/ether_token_v2.ts @@ -0,0 +1,118 @@ +import {ZeroEx, ZeroExError} from '0x.js'; +import {BigNumber} from 'bignumber.js'; +import * as chai from 'chai'; +import promisify = require('es6-promisify'); +import Web3 = require('web3'); + +import {Artifacts} from '../../util/artifacts'; + +import {chaiSetup} from './utils/chai_setup'; + +const {EtherToken} = new Artifacts(artifacts); + +chaiSetup.configure(); +const expect = chai.expect; + +// In order to benefit from type-safety, we re-assign the global web3 instance injected by Truffle +// with type `any` to a variable of type `Web3`. +const web3: Web3 = (global as any).web3; + +contract('EtherToken', (accounts: string[]) => { + const account = accounts[0]; + const gasPrice = ZeroEx.toBaseUnitAmount(new BigNumber(20), 9); + let zeroEx: ZeroEx; + let etherTokenAddress: string; + before(async () => { + etherTokenAddress = EtherToken.address; + zeroEx = new ZeroEx(web3.currentProvider, { + gasPrice, + etherTokenContractAddress: etherTokenAddress, + }); + }); + + const sendTransactionAsync = promisify(web3.eth.sendTransaction); + const getEthBalanceAsync = async (owner: string) => { + const balanceStr = await promisify(web3.eth.getBalance)(owner); + const balance = new BigNumber(balanceStr); + return balance; + }; + + describe('deposit', () => { + it('should throw if caller attempts to deposit more Ether than caller balance', async () => { + const initEthBalance = await getEthBalanceAsync(account); + const ethToDeposit = initEthBalance.plus(1); + + return expect(zeroEx.etherToken.depositAsync(ethToDeposit, account)) + .to.be.rejectedWith(ZeroExError.InsufficientEthBalanceForDeposit); + }); + + it('should convert deposited Ether to wrapped Ether tokens', async () => { + const initEthBalance = await getEthBalanceAsync(account); + const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + + const ethToDeposit = new BigNumber(web3.toWei(1, 'ether')); + + const txHash = await zeroEx.etherToken.depositAsync(ethToDeposit, account); + const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); + + const ethSpentOnGas = gasPrice.times(receipt.gasUsed); + const finalEthBalance = await getEthBalanceAsync(account); + const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + + expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas))); + expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit)); + }); + }); + + describe('withdraw', () => { + it('should throw if caller attempts to withdraw greater than caller balance', async () => { + const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + const ethTokensToWithdraw = initEthTokenBalance.plus(1); + + return expect(zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account)) + .to.be.rejectedWith(ZeroExError.InsufficientWEthBalanceForWithdrawal); + }); + + it('should convert ether tokens to ether with sufficient balance', async () => { + const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + const initEthBalance = await getEthBalanceAsync(account); + const ethTokensToWithdraw = initEthTokenBalance; + expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0); + const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account); + const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); + + const ethSpentOnGas = gasPrice.times(receipt.gasUsed); + const finalEthBalance = await getEthBalanceAsync(account); + const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + + expect(finalEthBalance).to.be.bignumber + .equal(initEthBalance.plus(ethTokensToWithdraw.minus(ethSpentOnGas))); + expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.minus(ethTokensToWithdraw)); + }); + }); + + describe('fallback', () => { + it('should convert sent ether to ether tokens', async () => { + const initEthBalance = await getEthBalanceAsync(account); + const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + + const ethToDeposit = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18); + + const txHash = await sendTransactionAsync({ + from: account, + to: etherTokenAddress, + value: ethToDeposit, + gasPrice, + }); + + const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); + + const ethSpentOnGas = gasPrice.times(receipt.gasUsed); + const finalEthBalance = await getEthBalanceAsync(account); + const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + + expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas))); + expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit)); + }); + }); +}); diff --git a/packages/contracts/util/artifacts.ts b/packages/contracts/util/artifacts.ts index b15c9216f..12321ac66 100644 --- a/packages/contracts/util/artifacts.ts +++ b/packages/contracts/util/artifacts.ts @@ -7,6 +7,7 @@ export class Artifacts { public ZRXToken: any; public DummyToken: any; public EtherToken: any; + public EtherToken_v2: any; public MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: any; public MaliciousToken: any; constructor(artifacts: any) { @@ -18,6 +19,7 @@ export class Artifacts { this.ZRXToken = artifacts.require('ZRXToken'); this.DummyToken = artifacts.require('DummyToken'); this.EtherToken = artifacts.require('EtherToken'); + this.EtherToken_v2 = artifacts.require('EtherToken_v2'); this.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress = artifacts.require( 'MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress'); this.MaliciousToken = artifacts.require('MaliciousToken'); -- cgit v1.2.3 From e6862e973983d478b7683425983f18b4680dd238 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 4 Dec 2017 16:58:15 -0800 Subject: Fix errors with new testrpc version --- packages/contracts/test/ts/exchange/core.ts | 26 ++++++++++---------- packages/contracts/test/ts/exchange/wrapper.ts | 8 +++---- .../contracts/test/ts/multi_sig_with_time_lock.ts | 6 ++--- ...i_sig_with_time_lock_except_remove_auth_addr.ts | 10 ++++---- packages/contracts/test/ts/token_registry.ts | 28 +++++++++++----------- .../contracts/test/ts/token_transfer_proxy/auth.ts | 8 +++---- .../test/ts/token_transfer_proxy/transfer_from.ts | 2 +- packages/contracts/util/constants.ts | 1 + 8 files changed, 45 insertions(+), 44 deletions(-) (limited to 'packages') diff --git a/packages/contracts/test/ts/exchange/core.ts b/packages/contracts/test/ts/exchange/core.ts index daf46ca37..e4aa74c32 100644 --- a/packages/contracts/test/ts/exchange/core.ts +++ b/packages/contracts/test/ts/exchange/core.ts @@ -422,7 +422,7 @@ contract('Exchange', (accounts: string[]) => { takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), }); - return expect(exWrapper.fillOrderAsync(order, taker)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(exWrapper.fillOrderAsync(order, taker)).to.be.rejectedWith(constants.REVERT); }); it('should throw if signature is invalid', async () => { @@ -432,7 +432,7 @@ contract('Exchange', (accounts: string[]) => { order.params.r = ethUtil.bufferToHex(ethUtil.sha3('invalidR')); order.params.s = ethUtil.bufferToHex(ethUtil.sha3('invalidS')); - return expect(exWrapper.fillOrderAsync(order, taker)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(exWrapper.fillOrderAsync(order, taker)).to.be.rejectedWith(constants.REVERT); }); it('should throw if makerTokenAmount is 0', async () => { @@ -440,7 +440,7 @@ contract('Exchange', (accounts: string[]) => { makerTokenAmount: new BigNumber(0), }); - return expect(exWrapper.fillOrderAsync(order, taker)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(exWrapper.fillOrderAsync(order, taker)).to.be.rejectedWith(constants.REVERT); }); it('should throw if takerTokenAmount is 0', async () => { @@ -448,14 +448,14 @@ contract('Exchange', (accounts: string[]) => { takerTokenAmount: new BigNumber(0), }); - return expect(exWrapper.fillOrderAsync(order, taker)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(exWrapper.fillOrderAsync(order, taker)).to.be.rejectedWith(constants.REVERT); }); it('should throw if fillTakerTokenAmount is 0', async () => { order = await orderFactory.newSignedOrderAsync(); return expect(exWrapper.fillOrderAsync(order, taker, {fillTakerTokenAmount: new BigNumber(0)})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should not change balances if maker balances are too low to fill order and \ @@ -478,7 +478,7 @@ contract('Exchange', (accounts: string[]) => { }); return expect(exWrapper.fillOrderAsync(order, taker, {shouldThrowOnInsufficientBalanceOrAllowance: true})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should not change balances if taker balances are too low to fill order and \ @@ -501,7 +501,7 @@ contract('Exchange', (accounts: string[]) => { }); return expect(exWrapper.fillOrderAsync(order, taker, {shouldThrowOnInsufficientBalanceOrAllowance: true})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should not change balances if maker allowances are too low to fill order and \ @@ -520,7 +520,7 @@ contract('Exchange', (accounts: string[]) => { async () => { await rep.approve(TokenTransferProxy.address, 0, {from: maker}); expect(exWrapper.fillOrderAsync(order, taker, {shouldThrowOnInsufficientBalanceOrAllowance: true})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); await rep.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, {from: maker}); }); @@ -540,7 +540,7 @@ contract('Exchange', (accounts: string[]) => { async () => { await dgd.approve(TokenTransferProxy.address, 0, {from: taker}); expect(exWrapper.fillOrderAsync(order, taker, {shouldThrowOnInsufficientBalanceOrAllowance: true})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); await dgd.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, {from: taker}); }); @@ -651,7 +651,7 @@ contract('Exchange', (accounts: string[]) => { }); it('should throw if not sent by maker', async () => { - return expect(exWrapper.cancelOrderAsync(order, taker)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(exWrapper.cancelOrderAsync(order, taker)).to.be.rejectedWith(constants.REVERT); }); it('should throw if makerTokenAmount is 0', async () => { @@ -659,7 +659,7 @@ contract('Exchange', (accounts: string[]) => { makerTokenAmount: new BigNumber(0), }); - return expect(exWrapper.cancelOrderAsync(order, maker)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(exWrapper.cancelOrderAsync(order, maker)).to.be.rejectedWith(constants.REVERT); }); it('should throw if takerTokenAmount is 0', async () => { @@ -667,14 +667,14 @@ contract('Exchange', (accounts: string[]) => { takerTokenAmount: new BigNumber(0), }); - return expect(exWrapper.cancelOrderAsync(order, maker)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(exWrapper.cancelOrderAsync(order, maker)).to.be.rejectedWith(constants.REVERT); }); it('should throw if cancelTakerTokenAmount is 0', async () => { order = await orderFactory.newSignedOrderAsync(); return expect(exWrapper.cancelOrderAsync(order, maker, {cancelTakerTokenAmount: new BigNumber(0)})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should be able to cancel a full order', async () => { diff --git a/packages/contracts/test/ts/exchange/wrapper.ts b/packages/contracts/test/ts/exchange/wrapper.ts index c40d60104..3097f6887 100644 --- a/packages/contracts/test/ts/exchange/wrapper.ts +++ b/packages/contracts/test/ts/exchange/wrapper.ts @@ -133,7 +133,7 @@ contract('Exchange', (accounts: string[]) => { }); return expect(exWrapper.fillOrKillOrderAsync(order, taker)) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should throw if entire fillTakerTokenAmount not filled', async () => { @@ -143,7 +143,7 @@ contract('Exchange', (accounts: string[]) => { await exWrapper.fillOrderAsync(order, from, {fillTakerTokenAmount: order.params.takerTokenAmount.div(2)}); return expect(exWrapper.fillOrKillOrderAsync(order, taker)) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); }); @@ -237,7 +237,7 @@ contract('Exchange', (accounts: string[]) => { await exWrapper.fillOrKillOrderAsync(orders[0], taker); return expect(exWrapper.batchFillOrKillOrdersAsync(orders, taker, {fillTakerTokenAmounts})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); }); @@ -302,7 +302,7 @@ contract('Exchange', (accounts: string[]) => { return expect( exWrapper.fillOrdersUpToAsync( orders, taker, {fillTakerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18)}), - ).to.be.rejectedWith(constants.INVALID_OPCODE); + ).to.be.rejectedWith(constants.REVERT); }); }); diff --git a/packages/contracts/test/ts/multi_sig_with_time_lock.ts b/packages/contracts/test/ts/multi_sig_with_time_lock.ts index 6dd4dc3b2..84eb21b4a 100644 --- a/packages/contracts/test/ts/multi_sig_with_time_lock.ts +++ b/packages/contracts/test/ts/multi_sig_with_time_lock.ts @@ -44,7 +44,7 @@ contract('MultiSigWalletWithTimeLock', (accounts: string[]) => { describe('changeTimeLock', () => { it('should throw when not called by wallet', async () => { return expect(multiSig.changeTimeLock(SECONDS_TIME_LOCKED, {from: owners[0]})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should throw without enough confirmations', async () => { @@ -58,7 +58,7 @@ contract('MultiSigWalletWithTimeLock', (accounts: string[]) => { const subRes = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); txId = subRes.logs[0].args.transactionId.toNumber(); - return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.REVERT); }); it('should set confirmation time with enough confirmations', async () => { @@ -97,7 +97,7 @@ contract('MultiSigWalletWithTimeLock', (accounts: string[]) => { const confRes = await multiSig.confirmTransaction(txId, {from: owners[1]}); expect(confRes.logs).to.have.length(2); - return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.REVERT); }); it('should execute if it has enough confirmations and is past the time lock', async () => { diff --git a/packages/contracts/test/ts/multi_sig_with_time_lock_except_remove_auth_addr.ts b/packages/contracts/test/ts/multi_sig_with_time_lock_except_remove_auth_addr.ts index 97ccac2bd..6f7aaa6cd 100644 --- a/packages/contracts/test/ts/multi_sig_with_time_lock_except_remove_auth_addr.ts +++ b/packages/contracts/test/ts/multi_sig_with_time_lock_except_remove_auth_addr.ts @@ -44,7 +44,7 @@ contract('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', (accounts: s it('should throw if data is not for removeAuthorizedAddress', async () => { const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]); return expect(multiSig.isFunctionRemoveAuthorizedAddress.call(data)) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should return true if data is for removeAuthorizedAddress', async () => { @@ -64,7 +64,7 @@ contract('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', (accounts: s const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); const txId = res.logs[0].args.transactionId.toString(); - return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT); }); it('should throw if tx destination is not the tokenTransferProxy', async () => { @@ -81,7 +81,7 @@ contract('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', (accounts: s const isConfirmed = await multiSig.isConfirmed.call(txId); expect(isConfirmed).to.be.true(); - return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT); }); it('should throw if tx data is not for removeAuthorizedAddress', async () => { @@ -96,7 +96,7 @@ contract('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', (accounts: s const isConfirmed = await multiSig.isConfirmed.call(txId); expect(isConfirmed).to.be.true(); - return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT); }); it('should execute removeAuthorizedAddress for valid tokenTransferProxy if fully confirmed', async () => { @@ -131,7 +131,7 @@ contract('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', (accounts: s const tx = await multiSig.transactions.call(txId); const isExecuted = tx[3]; expect(isExecuted).to.be.true(); - return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT); }); }); }); diff --git a/packages/contracts/test/ts/token_registry.ts b/packages/contracts/test/ts/token_registry.ts index ed0bbf55b..36f3edcfc 100644 --- a/packages/contracts/test/ts/token_registry.ts +++ b/packages/contracts/test/ts/token_registry.ts @@ -58,7 +58,7 @@ contract('TokenRegistry', (accounts: string[]) => { describe('addToken', () => { it('should throw when not called by owner', async () => { - return expect(tokenRegWrapper.addTokenAsync(token1, notOwner)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(tokenRegWrapper.addTokenAsync(token1, notOwner)).to.be.rejectedWith(constants.REVERT); }); it('should add token metadata when called by owner', async () => { @@ -70,11 +70,11 @@ contract('TokenRegistry', (accounts: string[]) => { it('should throw if token already exists', async () => { await tokenRegWrapper.addTokenAsync(token1, owner); - return expect(tokenRegWrapper.addTokenAsync(token1, owner)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(tokenRegWrapper.addTokenAsync(token1, owner)).to.be.rejectedWith(constants.REVERT); }); it('should throw if token address is null', async () => { - return expect(tokenRegWrapper.addTokenAsync(nullToken, owner)).to.be.rejectedWith(constants.INVALID_OPCODE); + return expect(tokenRegWrapper.addTokenAsync(nullToken, owner)).to.be.rejectedWith(constants.REVERT); }); it('should throw if name already exists', async () => { @@ -82,7 +82,7 @@ contract('TokenRegistry', (accounts: string[]) => { const duplicateNameToken = _.assign({}, token2, {name: token1.name}); return expect(tokenRegWrapper.addTokenAsync(duplicateNameToken, owner)) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should throw if symbol already exists', async () => { @@ -90,7 +90,7 @@ contract('TokenRegistry', (accounts: string[]) => { const duplicateSymbolToken = _.assign({}, token2, {symbol: token1.symbol}); return expect(tokenRegWrapper.addTokenAsync(duplicateSymbolToken, owner)) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); }); @@ -116,7 +116,7 @@ contract('TokenRegistry', (accounts: string[]) => { describe('setTokenName', () => { it('should throw when not called by owner', async () => { return expect(tokenReg.setTokenName(token1.address, token2.name, {from: notOwner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should change the token name when called by owner', async () => { @@ -137,19 +137,19 @@ contract('TokenRegistry', (accounts: string[]) => { await tokenRegWrapper.addTokenAsync(token2, owner); return expect(tokenReg.setTokenName(token1.address, token2.name, {from: owner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should throw if token does not exist', async () => { return expect(tokenReg.setTokenName(nullToken.address, token2.name, {from: owner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); }); describe('setTokenSymbol', () => { it('should throw when not called by owner', async () => { return expect(tokenReg.setTokenSymbol(token1.address, token2.symbol, {from: notOwner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should change the token symbol when called by owner', async () => { @@ -170,12 +170,12 @@ contract('TokenRegistry', (accounts: string[]) => { await tokenRegWrapper.addTokenAsync(token2, owner); return expect(tokenReg.setTokenSymbol(token1.address, token2.symbol, {from: owner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should throw if token does not exist', async () => { return expect(tokenReg.setTokenSymbol(nullToken.address, token2.symbol, {from: owner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); }); @@ -183,7 +183,7 @@ contract('TokenRegistry', (accounts: string[]) => { it('should throw if not called by owner', async () => { const index = 0; return expect(tokenReg.removeToken(token1.address, index, {from: notOwner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should remove token metadata when called by owner', async () => { @@ -197,14 +197,14 @@ contract('TokenRegistry', (accounts: string[]) => { it('should throw if token does not exist', async () => { const index = 0; return expect(tokenReg.removeToken(nullToken.address, index, {from: owner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should throw if token at given index does not match address', async () => { await tokenRegWrapper.addTokenAsync(token2, owner); const incorrectIndex = 0; return expect(tokenReg.removeToken(token2.address, incorrectIndex, {from: owner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); }); diff --git a/packages/contracts/test/ts/token_transfer_proxy/auth.ts b/packages/contracts/test/ts/token_transfer_proxy/auth.ts index 785fbc016..7c0a3d231 100644 --- a/packages/contracts/test/ts/token_transfer_proxy/auth.ts +++ b/packages/contracts/test/ts/token_transfer_proxy/auth.ts @@ -23,7 +23,7 @@ contract('TokenTransferProxy', (accounts: string[]) => { describe('addAuthorizedAddress', () => { it('should throw if not called by owner', async () => { return expect(tokenTransferProxy.addAuthorizedAddress(notOwner, {from: notOwner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should allow owner to add an authorized address', async () => { @@ -36,14 +36,14 @@ contract('TokenTransferProxy', (accounts: string[]) => { it('should throw if owner attempts to authorize a duplicate address', async () => { return expect(tokenTransferProxy.addAuthorizedAddress(authorized, {from: owner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); }); describe('removeAuthorizedAddress', () => { it('should throw if not called by owner', async () => { return expect(tokenTransferProxy.removeAuthorizedAddress(authorized, {from: notOwner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should allow owner to remove an authorized address', async () => { @@ -57,7 +57,7 @@ contract('TokenTransferProxy', (accounts: string[]) => { it('should throw if owner attempts to remove an address that is not authorized', async () => { return expect(tokenTransferProxy.removeAuthorizedAddress(notAuthorized, {from: owner})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); }); diff --git a/packages/contracts/test/ts/token_transfer_proxy/transfer_from.ts b/packages/contracts/test/ts/token_transfer_proxy/transfer_from.ts index 6e0bfdc1a..8b40bfb1e 100644 --- a/packages/contracts/test/ts/token_transfer_proxy/transfer_from.ts +++ b/packages/contracts/test/ts/token_transfer_proxy/transfer_from.ts @@ -46,7 +46,7 @@ contract('TokenTransferProxy', (accounts: string[]) => { describe('transferFrom', () => { it('should throw when called by an unauthorized address', async () => { expect(tokenTransferProxy.transferFrom(rep.address, accounts[0], accounts[1], 1000, {from: notAuthorized})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should allow an authorized address to transfer', async () => { diff --git a/packages/contracts/util/constants.ts b/packages/contracts/util/constants.ts index 5beebc68c..733ad2312 100644 --- a/packages/contracts/util/constants.ts +++ b/packages/contracts/util/constants.ts @@ -1,4 +1,5 @@ export const constants = { NULL_BYTES: '0x', INVALID_OPCODE: 'invalid opcode', + REVERT: 'revert', }; -- cgit v1.2.3 From b58bf8259db7378b841e6695d99580027b4e2969 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 5 Dec 2017 12:45:08 -0800 Subject: Add tests for ERC20Token and EtherToken_v2 --- packages/contracts/contracts/base/ERC20Token.sol | 51 --------- packages/contracts/contracts/test/Mintable.sol | 4 +- packages/contracts/contracts/tokens/ERC20Token.sol | 51 +++++++++ .../contracts/contracts/tokens/EtherToken_v2.sol | 2 +- .../migrations/2_deploy_independent_contracts.ts | 9 +- packages/contracts/package.json | 1 - packages/contracts/test/ts/erc20Token.ts | 123 +++++++++++++++++++++ packages/contracts/test/ts/ether_token_v2.ts | 52 ++++++++- packages/contracts/util/artifacts.ts | 4 +- 9 files changed, 233 insertions(+), 64 deletions(-) delete mode 100644 packages/contracts/contracts/base/ERC20Token.sol create mode 100644 packages/contracts/contracts/tokens/ERC20Token.sol create mode 100644 packages/contracts/test/ts/erc20Token.ts (limited to 'packages') diff --git a/packages/contracts/contracts/base/ERC20Token.sol b/packages/contracts/contracts/base/ERC20Token.sol deleted file mode 100644 index f0117894d..000000000 --- a/packages/contracts/contracts/base/ERC20Token.sol +++ /dev/null @@ -1,51 +0,0 @@ -pragma solidity 0.4.11; - -import "./Token.sol"; - -contract ERC20Token is Token { - - uint constant MAX_UINT = 2**256 - 1; - - function transfer(address _to, uint _value) returns (bool) { - require(balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]); - balances[msg.sender] -= _value; - balances[_to] += _value; - Transfer(msg.sender, _to, _value); - return true; - } - - /// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance. See https://github.com/ethereum/EIPs/issues/717 - /// @param _from Address to transfer from. - /// @param _to Address to transfer to. - /// @param _value Amount to transfer. - /// @return Success of transfer. - function transferFrom(address _from, address _to, uint _value) returns (bool) { - uint allowance = allowed[_from][msg.sender]; - require(balances[_from] >= _value && allowance >= _value && balances[_to] + _value >= balances[_to]); - balances[_to] += _value; - balances[_from] -= _value; - if (allowance < MAX_UINT) { - allowed[_from][msg.sender] -= _value; - } - Transfer(_from, _to, _value); - return true; - } - - function balanceOf(address _owner) constant returns (uint) { - return balances[_owner]; - } - - function approve(address _spender, uint _value) returns (bool) { - allowed[msg.sender][_spender] = _value; - Approval(msg.sender, _spender, _value); - return true; - } - - function allowance(address _owner, address _spender) constant returns (uint) { - return allowed[_owner][_spender]; - } - - mapping (address => uint) balances; - mapping (address => mapping (address => uint)) allowed; - uint public totalSupply; -} \ No newline at end of file diff --git a/packages/contracts/contracts/test/Mintable.sol b/packages/contracts/contracts/test/Mintable.sol index c0438f304..257dca705 100644 --- a/packages/contracts/contracts/test/Mintable.sol +++ b/packages/contracts/contracts/test/Mintable.sol @@ -1,13 +1,13 @@ pragma solidity 0.4.11; -import "./../tokens/UnlimitedAllowanceToken.sol"; +import "./../tokens/ERC20Token.sol"; import "./../base/SafeMath.sol"; /* * Mintable * Base contract that creates a mintable UnlimitedAllowanceToken */ -contract Mintable is UnlimitedAllowanceToken, SafeMath { +contract Mintable is ERC20Token, SafeMath { function mint(uint _value) { require(_value <= 100000000000000000000); balances[msg.sender] = safeAdd(_value, balances[msg.sender]); diff --git a/packages/contracts/contracts/tokens/ERC20Token.sol b/packages/contracts/contracts/tokens/ERC20Token.sol new file mode 100644 index 000000000..8db58c707 --- /dev/null +++ b/packages/contracts/contracts/tokens/ERC20Token.sol @@ -0,0 +1,51 @@ +pragma solidity 0.4.11; + +import "./../base/Token.sol"; + +contract ERC20Token is Token { + + uint constant MAX_UINT = 2**256 - 1; + + function transfer(address _to, uint _value) returns (bool) { + require(balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]); + balances[msg.sender] -= _value; + balances[_to] += _value; + Transfer(msg.sender, _to, _value); + return true; + } + + /// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance. See https://github.com/ethereum/EIPs/issues/717 + /// @param _from Address to transfer from. + /// @param _to Address to transfer to. + /// @param _value Amount to transfer. + /// @return Success of transfer. + function transferFrom(address _from, address _to, uint _value) returns (bool) { + uint allowance = allowed[_from][msg.sender]; + require(balances[_from] >= _value && allowance >= _value && balances[_to] + _value >= balances[_to]); + balances[_to] += _value; + balances[_from] -= _value; + if (allowance < MAX_UINT) { + allowed[_from][msg.sender] -= _value; + } + Transfer(_from, _to, _value); + return true; + } + + function balanceOf(address _owner) constant returns (uint) { + return balances[_owner]; + } + + function approve(address _spender, uint _value) returns (bool) { + allowed[msg.sender][_spender] = _value; + Approval(msg.sender, _spender, _value); + return true; + } + + function allowance(address _owner, address _spender) constant returns (uint) { + return allowed[_owner][_spender]; + } + + mapping (address => uint) balances; + mapping (address => mapping (address => uint)) allowed; + uint public totalSupply; +} \ No newline at end of file diff --git a/packages/contracts/contracts/tokens/EtherToken_v2.sol b/packages/contracts/contracts/tokens/EtherToken_v2.sol index a75a2aa7c..0c7acf8a0 100644 --- a/packages/contracts/contracts/tokens/EtherToken_v2.sol +++ b/packages/contracts/contracts/tokens/EtherToken_v2.sol @@ -18,7 +18,7 @@ pragma solidity 0.4.11; -import "./../base/ERC20Token.sol"; +import "./../tokens/ERC20Token.sol"; import "./../base/SafeMath.sol"; contract EtherToken_v2 is ERC20Token, SafeMath { diff --git a/packages/contracts/migrations/2_deploy_independent_contracts.ts b/packages/contracts/migrations/2_deploy_independent_contracts.ts index 878860eb6..db9fc370d 100644 --- a/packages/contracts/migrations/2_deploy_independent_contracts.ts +++ b/packages/contracts/migrations/2_deploy_independent_contracts.ts @@ -4,6 +4,7 @@ const { MultiSigWalletWithTimeLock, TokenTransferProxy, EtherToken, + EtherTokenV2, TokenRegistry, } = new Artifacts(artifacts); @@ -28,11 +29,13 @@ module.exports = (deployer: any, network: string, accounts: string[]) => { deployer.deploy(MultiSigWalletWithTimeLock, config.owners, config.confirmationsRequired, config.secondsRequired) .then(() => { - return deployer.deploy(TokenTransferProxy); + return deployer.deploy(TokenTransferProxy); }).then(() => { - return deployer.deploy(TokenRegistry); + return deployer.deploy(TokenRegistry); }).then(() => { - return deployer.deploy(EtherToken); + return deployer.deploy(EtherToken); + }).then(() => { + return deployer.deploy(EtherTokenV2); }); } else { deployer.deploy([ diff --git a/packages/contracts/package.json b/packages/contracts/package.json index d2f30933a..46bf4f731 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -31,7 +31,6 @@ "@0xproject/tslint-config": "^0.2.1", "@0xproject/types": "^0.1.0", "@types/bluebird": "^3.5.3", - "@types/isomorphic-fetch": "^0.0.34", "@types/lodash": "^4.14.86", "@types/node": "^8.0.53", "@types/request-promise-native": "^1.0.2", diff --git a/packages/contracts/test/ts/erc20Token.ts b/packages/contracts/test/ts/erc20Token.ts new file mode 100644 index 000000000..e2282cbf3 --- /dev/null +++ b/packages/contracts/test/ts/erc20Token.ts @@ -0,0 +1,123 @@ +import {ZeroEx} from '0x.js'; +import {BigNumber} from 'bignumber.js'; +import * as chai from 'chai'; +import * as Web3 from 'web3'; + +import {Artifacts} from '../../util/artifacts'; +import {constants} from '../../util/constants'; +import {ContractInstance} from '../../util/types'; + +import {chaiSetup} from './utils/chai_setup'; + +const {DummyToken} = new Artifacts(artifacts); +const web3: Web3 = (global as any).web3; +chaiSetup.configure(); +const expect = chai.expect; + +contract('ERC20Token', (accounts: string[]) => { + const zeroEx = new ZeroEx(web3.currentProvider); + const owner = accounts[0]; + const spender = accounts[1]; + + const MAX_MINT_VALUE = new BigNumber(100000000000000000000); + let tokenAddress: string; + let token: ContractInstance; + + beforeEach(async () => { + token = await DummyToken.new({from: owner}); + await token.mint(MAX_MINT_VALUE, {from: owner}); + tokenAddress = token.address; + }); + + describe('transfer', () => { + it('should throw if owner has insufficient balance', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = ownerBalance.plus(1); + return expect(token.transfer.call(owner, spender, amountToTransfer, {from: spender})) + .to.be.rejectedWith(constants.REVERT); + }); + + it('should transfer balance from sender to receiver', async () => { + const receiver = spender; + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = new BigNumber(1); + await zeroEx.token.transferAsync(tokenAddress, owner, receiver, amountToTransfer); + const finalOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const finalReceiverBalance = await zeroEx.token.getBalanceAsync(tokenAddress, receiver); + + const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer); + const expectedFinalReceiverBalance = amountToTransfer; + expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance); + expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance); + }); + + it('should return true on a 0 value transfer', async () => { + const didReturnTrue = await token.transfer.call(spender, 0, {from: owner}); + expect(didReturnTrue).to.be.true(); + }); + }); + + describe('transferFrom', () => { + it('should throw if owner has insufficient balance', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = ownerBalance.plus(1); + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer); + return expect(token.transferFrom.call(owner, spender, amountToTransfer, {from: spender})) + .to.be.rejectedWith(constants.REVERT); + }); + + it('should throw if spender has insufficient allowance', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = ownerBalance; + + const spenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; + expect(spenderAllowanceIsInsufficient).to.be.true(); + + return expect(token.transferFrom.call(owner, spender, amountToTransfer, {from: spender})) + .to.be.rejectedWith(constants.REVERT); + }); + + it('should return true on a 0 value transfer', async () => { + const amountToTransfer = 0; + const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); + expect(didReturnTrue).to.be.true(); + }); + + it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + + const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); + }); + + it('should transfer the correct balances if spender has sufficient allowance', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = initOwnerBalance; + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + + const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender); + + expect(newOwnerBalance).to.be.bignumber.equal(0); + expect(newSpenderBalance).to.be.bignumber.equal(initOwnerBalance); + }); + + it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = initOwnerBalance; + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + + const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + expect(newSpenderAllowance).to.be.bignumber.equal(0); + }); + }); +}); diff --git a/packages/contracts/test/ts/ether_token_v2.ts b/packages/contracts/test/ts/ether_token_v2.ts index 857371578..0c352b522 100644 --- a/packages/contracts/test/ts/ether_token_v2.ts +++ b/packages/contracts/test/ts/ether_token_v2.ts @@ -8,7 +8,7 @@ import {Artifacts} from '../../util/artifacts'; import {chaiSetup} from './utils/chai_setup'; -const {EtherToken} = new Artifacts(artifacts); +const {EtherTokenV2} = new Artifacts(artifacts); chaiSetup.configure(); const expect = chai.expect; @@ -17,13 +17,14 @@ const expect = chai.expect; // with type `any` to a variable of type `Web3`. const web3: Web3 = (global as any).web3; -contract('EtherToken', (accounts: string[]) => { +contract('EtherTokenV2', (accounts: string[]) => { const account = accounts[0]; const gasPrice = ZeroEx.toBaseUnitAmount(new BigNumber(20), 9); let zeroEx: ZeroEx; let etherTokenAddress: string; - before(async () => { - etherTokenAddress = EtherToken.address; + beforeEach(async () => { + const etherToken = await EtherTokenV2.new(); + etherTokenAddress = etherToken.address; zeroEx = new ZeroEx(web3.currentProvider, { gasPrice, etherTokenContractAddress: etherTokenAddress, @@ -62,9 +63,32 @@ contract('EtherToken', (accounts: string[]) => { expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas))); expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit)); }); + + it('should log 1 event with correct arguments', async () => { + const ethToDeposit = new BigNumber(web3.toWei(1, 'ether')); + + const txHash = await zeroEx.etherToken.depositAsync(ethToDeposit, account); + const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); + + const logs = receipt.logs; + expect(logs.length).to.equal(1); + + const expectedFrom = ZeroEx.NULL_ADDRESS; + const expectedTo = account; + const expectedValue = ethToDeposit; + const logArgs = logs[0].args; + expect(logArgs._from).to.equal(expectedFrom); + expect(logArgs._to).to.equal(expectedTo); + expect(logArgs._value).to.be.bignumber.equal(ethToDeposit); + }); }); describe('withdraw', () => { + beforeEach(async () => { + const ethToDeposit = new BigNumber(web3.toWei(1, 'ether')); + await zeroEx.etherToken.depositAsync(ethToDeposit, account); + }); + it('should throw if caller attempts to withdraw greater than caller balance', async () => { const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); const ethTokensToWithdraw = initEthTokenBalance.plus(1); @@ -89,6 +113,26 @@ contract('EtherToken', (accounts: string[]) => { .equal(initEthBalance.plus(ethTokensToWithdraw.minus(ethSpentOnGas))); expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.minus(ethTokensToWithdraw)); }); + + it('should log 1 event with correct arguments', async () => { + const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); + const initEthBalance = await getEthBalanceAsync(account); + const ethTokensToWithdraw = initEthTokenBalance; + expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0); + const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account); + const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); + + const logs = receipt.logs; + expect(logs.length).to.equal(1); + + const expectedFrom = account; + const expectedTo = ZeroEx.NULL_ADDRESS; + const expectedValue = ethTokensToWithdraw; + const logArgs = logs[0].args; + expect(logArgs._from).to.equal(expectedFrom); + expect(logArgs._to).to.equal(expectedTo); + expect(logArgs._value).to.be.bignumber.equal(ethTokensToWithdraw); + }); }); describe('fallback', () => { diff --git a/packages/contracts/util/artifacts.ts b/packages/contracts/util/artifacts.ts index 12321ac66..cb06739af 100644 --- a/packages/contracts/util/artifacts.ts +++ b/packages/contracts/util/artifacts.ts @@ -7,7 +7,7 @@ export class Artifacts { public ZRXToken: any; public DummyToken: any; public EtherToken: any; - public EtherToken_v2: any; + public EtherTokenV2: any; public MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: any; public MaliciousToken: any; constructor(artifacts: any) { @@ -19,7 +19,7 @@ export class Artifacts { this.ZRXToken = artifacts.require('ZRXToken'); this.DummyToken = artifacts.require('DummyToken'); this.EtherToken = artifacts.require('EtherToken'); - this.EtherToken_v2 = artifacts.require('EtherToken_v2'); + this.EtherTokenV2 = artifacts.require('EtherToken_v2'); this.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress = artifacts.require( 'MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress'); this.MaliciousToken = artifacts.require('MaliciousToken'); -- cgit v1.2.3 From 548fda8dbaadc4827137d4b90753b306fdfd554b Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Wed, 6 Dec 2017 20:46:53 -0800 Subject: Add updated contracts, reorganize contract file structure --- packages/contracts/contracts/Exchange.sol | 6 +- .../contracts/MultiSigWalletWithTimeLock.sol | 132 -------- ...etWithTimeLockExceptRemoveAuthorizedAddress.sol | 82 ----- packages/contracts/contracts/TokenRegistry.sol | 4 +- .../contracts/contracts/TokenTransferProxy.sol | 6 +- .../contracts/contracts/base/MultiSigWallet.sol | 365 --------------------- packages/contracts/contracts/base/Ownable.sol | 27 -- packages/contracts/contracts/base/SafeMath.sol | 41 --- .../contracts/contracts/base/StandardToken.sol | 44 --- packages/contracts/contracts/base/Token.sol | 38 --- .../contracts/contracts/deprecated/EtherToken.sol | 56 ---- .../contracts/multisig/MultiSigWallet.sol | 365 +++++++++++++++++++++ .../multisig/MultiSigWalletWithTimeLock.sol | 132 ++++++++ ...etWithTimeLockExceptRemoveAuthorizedAddress.sol | 82 +++++ packages/contracts/contracts/test/DummyToken.sol | 8 +- .../contracts/contracts/test/DummyToken_v2.sol | 37 +++ .../contracts/contracts/test/MaliciousToken.sol | 8 +- packages/contracts/contracts/test/Mintable.sol | 12 +- packages/contracts/contracts/test/Mintable_v2.sol | 18 + packages/contracts/contracts/tokens/ERC20Token.sol | 39 ++- packages/contracts/contracts/tokens/EtherToken.sol | 56 ++++ .../contracts/contracts/tokens/EtherToken_v2.sol | 8 +- .../contracts/contracts/tokens/StandardToken.sol | 44 +++ packages/contracts/contracts/tokens/Token.sol | 38 +++ packages/contracts/contracts/tokens/Token_v2.sol | 38 +++ .../contracts/tokens/UnlimitedAllowanceToken.sol | 4 +- packages/contracts/contracts/tokens/ZRXToken.sol | 2 +- packages/contracts/package.json | 2 +- packages/contracts/test/ts/erc20Token.ts | 6 +- packages/contracts/test/ts/exchange/core.ts | 2 +- packages/contracts/util/artifacts.ts | 2 + 31 files changed, 877 insertions(+), 827 deletions(-) delete mode 100644 packages/contracts/contracts/MultiSigWalletWithTimeLock.sol delete mode 100644 packages/contracts/contracts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol delete mode 100644 packages/contracts/contracts/base/MultiSigWallet.sol delete mode 100644 packages/contracts/contracts/base/Ownable.sol delete mode 100644 packages/contracts/contracts/base/SafeMath.sol delete mode 100644 packages/contracts/contracts/base/StandardToken.sol delete mode 100644 packages/contracts/contracts/base/Token.sol delete mode 100644 packages/contracts/contracts/deprecated/EtherToken.sol create mode 100644 packages/contracts/contracts/multisig/MultiSigWallet.sol create mode 100644 packages/contracts/contracts/multisig/MultiSigWalletWithTimeLock.sol create mode 100644 packages/contracts/contracts/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol create mode 100644 packages/contracts/contracts/test/DummyToken_v2.sol create mode 100644 packages/contracts/contracts/test/Mintable_v2.sol create mode 100644 packages/contracts/contracts/tokens/EtherToken.sol create mode 100644 packages/contracts/contracts/tokens/StandardToken.sol create mode 100644 packages/contracts/contracts/tokens/Token.sol create mode 100644 packages/contracts/contracts/tokens/Token_v2.sol (limited to 'packages') diff --git a/packages/contracts/contracts/Exchange.sol b/packages/contracts/contracts/Exchange.sol index 02deee967..2f734fb20 100644 --- a/packages/contracts/contracts/Exchange.sol +++ b/packages/contracts/contracts/Exchange.sol @@ -16,11 +16,11 @@ */ -pragma solidity 0.4.11; +pragma solidity ^0.4.11; import "./TokenTransferProxy.sol"; -import "./base/Token.sol"; -import "./base/SafeMath.sol"; +import "./tokens/Token.sol"; +import "./lib/SafeMath.sol"; /// @title Exchange - Facilitates exchange of ERC20 tokens. /// @author Amir Bandeali - , Will Warren - diff --git a/packages/contracts/contracts/MultiSigWalletWithTimeLock.sol b/packages/contracts/contracts/MultiSigWalletWithTimeLock.sol deleted file mode 100644 index 70123e6b6..000000000 --- a/packages/contracts/contracts/MultiSigWalletWithTimeLock.sol +++ /dev/null @@ -1,132 +0,0 @@ -/* - - Copyright 2017 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity 0.4.11; - -import "./base/MultiSigWallet.sol"; - -/// @title Multisignature wallet with time lock- Allows multiple parties to execute a transaction after a time lock has passed. -/// @author Amir Bandeali - -contract MultiSigWalletWithTimeLock is MultiSigWallet { - - event ConfirmationTimeSet(uint indexed transactionId, uint confirmationTime); - event TimeLockChange(uint secondsTimeLocked); - - uint public secondsTimeLocked; - - mapping (uint => uint) public confirmationTimes; - - modifier notFullyConfirmed(uint transactionId) { - require(!isConfirmed(transactionId)); - _; - } - - modifier fullyConfirmed(uint transactionId) { - require(isConfirmed(transactionId)); - _; - } - - modifier pastTimeLock(uint transactionId) { - require(block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked); - _; - } - - /* - * Public functions - */ - - /// @dev Contract constructor sets initial owners, required number of confirmations, and time lock. - /// @param _owners List of initial owners. - /// @param _required Number of required confirmations. - /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. - function MultiSigWalletWithTimeLock(address[] _owners, uint _required, uint _secondsTimeLocked) - public - MultiSigWallet(_owners, _required) - { - secondsTimeLocked = _secondsTimeLocked; - } - - /// @dev Changes the duration of the time lock for transactions. - /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. - function changeTimeLock(uint _secondsTimeLocked) - public - onlyWallet - { - secondsTimeLocked = _secondsTimeLocked; - TimeLockChange(_secondsTimeLocked); - } - - /// @dev Allows an owner to confirm a transaction. - /// @param transactionId Transaction ID. - function confirmTransaction(uint transactionId) - public - ownerExists(msg.sender) - transactionExists(transactionId) - notConfirmed(transactionId, msg.sender) - notFullyConfirmed(transactionId) - { - confirmations[transactionId][msg.sender] = true; - Confirmation(msg.sender, transactionId); - if (isConfirmed(transactionId)) { - setConfirmationTime(transactionId, block.timestamp); - } - } - - /// @dev Allows an owner to revoke a confirmation for a transaction. - /// @param transactionId Transaction ID. - function revokeConfirmation(uint transactionId) - public - ownerExists(msg.sender) - confirmed(transactionId, msg.sender) - notExecuted(transactionId) - notFullyConfirmed(transactionId) - { - confirmations[transactionId][msg.sender] = false; - Revocation(msg.sender, transactionId); - } - - /// @dev Allows anyone to execute a confirmed transaction. - /// @param transactionId Transaction ID. - function executeTransaction(uint transactionId) - public - notExecuted(transactionId) - fullyConfirmed(transactionId) - pastTimeLock(transactionId) - { - Transaction storage tx = transactions[transactionId]; - tx.executed = true; - if (tx.destination.call.value(tx.value)(tx.data)) - Execution(transactionId); - else { - ExecutionFailure(transactionId); - tx.executed = false; - } - } - - /* - * Internal functions - */ - - /// @dev Sets the time of when a submission first passed. - function setConfirmationTime(uint transactionId, uint confirmationTime) - internal - { - confirmationTimes[transactionId] = confirmationTime; - ConfirmationTimeSet(transactionId, confirmationTime); - } -} diff --git a/packages/contracts/contracts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol b/packages/contracts/contracts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol deleted file mode 100644 index 15fdb1d07..000000000 --- a/packages/contracts/contracts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol +++ /dev/null @@ -1,82 +0,0 @@ -/* - - Copyright 2017 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity 0.4.11; - -import "./MultiSigWalletWithTimeLock.sol"; - -contract MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress is MultiSigWalletWithTimeLock { - - address public TOKEN_TRANSFER_PROXY_CONTRACT; - - modifier validRemoveAuthorizedAddressTx(uint transactionId) { - Transaction storage tx = transactions[transactionId]; - require(tx.destination == TOKEN_TRANSFER_PROXY_CONTRACT); - require(isFunctionRemoveAuthorizedAddress(tx.data)); - _; - } - - /// @dev Contract constructor sets initial owners, required number of confirmations, time lock, and tokenTransferProxy address. - /// @param _owners List of initial owners. - /// @param _required Number of required confirmations. - /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. - /// @param _tokenTransferProxy Address of TokenTransferProxy contract. - function MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress( - address[] _owners, - uint _required, - uint _secondsTimeLocked, - address _tokenTransferProxy) - public - MultiSigWalletWithTimeLock(_owners, _required, _secondsTimeLocked) - { - TOKEN_TRANSFER_PROXY_CONTRACT = _tokenTransferProxy; - } - - /// @dev Allows execution of removeAuthorizedAddress without time lock. - /// @param transactionId Transaction ID. - function executeRemoveAuthorizedAddress(uint transactionId) - public - notExecuted(transactionId) - fullyConfirmed(transactionId) - validRemoveAuthorizedAddressTx(transactionId) - { - Transaction storage tx = transactions[transactionId]; - tx.executed = true; - if (tx.destination.call.value(tx.value)(tx.data)) - Execution(transactionId); - else { - ExecutionFailure(transactionId); - tx.executed = false; - } - } - - /// @dev Compares first 4 bytes of byte array to removeAuthorizedAddress function signature. - /// @param data Transaction data. - /// @return Successful if data is a call to removeAuthorizedAddress. - function isFunctionRemoveAuthorizedAddress(bytes data) - public - constant - returns (bool) - { - bytes4 removeAuthorizedAddressSignature = bytes4(sha3("removeAuthorizedAddress(address)")); - for (uint i = 0; i < 4; i++) { - require(data[i] == removeAuthorizedAddressSignature[i]); - } - return true; - } -} diff --git a/packages/contracts/contracts/TokenRegistry.sol b/packages/contracts/contracts/TokenRegistry.sol index d370f8cfe..c76eaea9d 100644 --- a/packages/contracts/contracts/TokenRegistry.sol +++ b/packages/contracts/contracts/TokenRegistry.sol @@ -16,9 +16,9 @@ */ -pragma solidity 0.4.11; +pragma solidity ^0.4.11; -import "./base/Ownable.sol"; +import "./lib/Ownable.sol"; /// @title Token Registry - Stores metadata associated with ERC20 tokens. See ERC22 https://github.com/ethereum/EIPs/issues/22 /// @author Amir Bandeali - , Will Warren - diff --git a/packages/contracts/contracts/TokenTransferProxy.sol b/packages/contracts/contracts/TokenTransferProxy.sol index 23b0b9e6d..81ada804d 100644 --- a/packages/contracts/contracts/TokenTransferProxy.sol +++ b/packages/contracts/contracts/TokenTransferProxy.sol @@ -16,10 +16,10 @@ */ -pragma solidity 0.4.11; +pragma solidity ^0.4.11; -import "./base/Token.sol"; -import "./base/Ownable.sol"; +import "./tokens/Token.sol"; +import "./lib/Ownable.sol"; /// @title TokenTransferProxy - Transfers tokens on behalf of contracts that have been approved via decentralized governance. /// @author Amir Bandeali - , Will Warren - diff --git a/packages/contracts/contracts/base/MultiSigWallet.sol b/packages/contracts/contracts/base/MultiSigWallet.sol deleted file mode 100644 index 7531224ea..000000000 --- a/packages/contracts/contracts/base/MultiSigWallet.sol +++ /dev/null @@ -1,365 +0,0 @@ -pragma solidity 0.4.11; - -/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution. -/// @author Stefan George - -contract MultiSigWallet { - - uint constant public MAX_OWNER_COUNT = 50; - - event Confirmation(address indexed sender, uint indexed transactionId); - event Revocation(address indexed sender, uint indexed transactionId); - event Submission(uint indexed transactionId); - event Execution(uint indexed transactionId); - event ExecutionFailure(uint indexed transactionId); - event Deposit(address indexed sender, uint value); - event OwnerAddition(address indexed owner); - event OwnerRemoval(address indexed owner); - event RequirementChange(uint required); - - mapping (uint => Transaction) public transactions; - mapping (uint => mapping (address => bool)) public confirmations; - mapping (address => bool) public isOwner; - address[] public owners; - uint public required; - uint public transactionCount; - - struct Transaction { - address destination; - uint value; - bytes data; - bool executed; - } - - modifier onlyWallet() { - if (msg.sender != address(this)) - throw; - _; - } - - modifier ownerDoesNotExist(address owner) { - if (isOwner[owner]) - throw; - _; - } - - modifier ownerExists(address owner) { - if (!isOwner[owner]) - throw; - _; - } - - modifier transactionExists(uint transactionId) { - if (transactions[transactionId].destination == 0) - throw; - _; - } - - modifier confirmed(uint transactionId, address owner) { - if (!confirmations[transactionId][owner]) - throw; - _; - } - - modifier notConfirmed(uint transactionId, address owner) { - if (confirmations[transactionId][owner]) - throw; - _; - } - - modifier notExecuted(uint transactionId) { - if (transactions[transactionId].executed) - throw; - _; - } - - modifier notNull(address _address) { - if (_address == 0) - throw; - _; - } - - modifier validRequirement(uint ownerCount, uint _required) { - if ( ownerCount > MAX_OWNER_COUNT - || _required > ownerCount - || _required == 0 - || ownerCount == 0) - throw; - _; - } - - /// @dev Fallback function allows to deposit ether. - function() - payable - { - if (msg.value > 0) - Deposit(msg.sender, msg.value); - } - - /* - * Public functions - */ - /// @dev Contract constructor sets initial owners and required number of confirmations. - /// @param _owners List of initial owners. - /// @param _required Number of required confirmations. - function MultiSigWallet(address[] _owners, uint _required) - public - validRequirement(_owners.length, _required) - { - for (uint i=0; i<_owners.length; i++) { - if (isOwner[_owners[i]] || _owners[i] == 0) - throw; - isOwner[_owners[i]] = true; - } - owners = _owners; - required = _required; - } - - /// @dev Allows to add a new owner. Transaction has to be sent by wallet. - /// @param owner Address of new owner. - function addOwner(address owner) - public - onlyWallet - ownerDoesNotExist(owner) - notNull(owner) - validRequirement(owners.length + 1, required) - { - isOwner[owner] = true; - owners.push(owner); - OwnerAddition(owner); - } - - /// @dev Allows to remove an owner. Transaction has to be sent by wallet. - /// @param owner Address of owner. - function removeOwner(address owner) - public - onlyWallet - ownerExists(owner) - { - isOwner[owner] = false; - for (uint i=0; i owners.length) - changeRequirement(owners.length); - OwnerRemoval(owner); - } - - /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet. - /// @param owner Address of owner to be replaced. - /// @param owner Address of new owner. - function replaceOwner(address owner, address newOwner) - public - onlyWallet - ownerExists(owner) - ownerDoesNotExist(newOwner) - { - for (uint i=0; i= a); - return c; - } - - function max64(uint64 a, uint64 b) internal constant returns (uint64) { - return a >= b ? a : b; - } - - function min64(uint64 a, uint64 b) internal constant returns (uint64) { - return a < b ? a : b; - } - - function max256(uint256 a, uint256 b) internal constant returns (uint256) { - return a >= b ? a : b; - } - - function min256(uint256 a, uint256 b) internal constant returns (uint256) { - return a < b ? a : b; - } -} diff --git a/packages/contracts/contracts/base/StandardToken.sol b/packages/contracts/contracts/base/StandardToken.sol deleted file mode 100644 index e0719d89a..000000000 --- a/packages/contracts/contracts/base/StandardToken.sol +++ /dev/null @@ -1,44 +0,0 @@ -pragma solidity 0.4.11; - -import "./Token.sol"; - -contract StandardToken is Token { - - function transfer(address _to, uint _value) returns (bool) { - //Default assumes totalSupply can't be over max (2^256 - 1). - if (balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]) { - balances[msg.sender] -= _value; - balances[_to] += _value; - Transfer(msg.sender, _to, _value); - return true; - } else { return false; } - } - - function transferFrom(address _from, address _to, uint _value) returns (bool) { - if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value >= balances[_to]) { - balances[_to] += _value; - balances[_from] -= _value; - allowed[_from][msg.sender] -= _value; - Transfer(_from, _to, _value); - return true; - } else { return false; } - } - - function balanceOf(address _owner) constant returns (uint) { - return balances[_owner]; - } - - function approve(address _spender, uint _value) returns (bool) { - allowed[msg.sender][_spender] = _value; - Approval(msg.sender, _spender, _value); - return true; - } - - function allowance(address _owner, address _spender) constant returns (uint) { - return allowed[_owner][_spender]; - } - - mapping (address => uint) balances; - mapping (address => mapping (address => uint)) allowed; - uint public totalSupply; -} diff --git a/packages/contracts/contracts/base/Token.sol b/packages/contracts/contracts/base/Token.sol deleted file mode 100644 index c6a55c2c0..000000000 --- a/packages/contracts/contracts/base/Token.sol +++ /dev/null @@ -1,38 +0,0 @@ -pragma solidity 0.4.11; - -contract Token { - - /// @return total amount of tokens - function totalSupply() constant returns (uint supply) {} - - /// @param _owner The address from which the balance will be retrieved - /// @return The balance - function balanceOf(address _owner) constant returns (uint balance) {} - - /// @notice send `_value` token to `_to` from `msg.sender` - /// @param _to The address of the recipient - /// @param _value The amount of token to be transferred - /// @return Whether the transfer was successful or not - function transfer(address _to, uint _value) returns (bool success) {} - - /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` - /// @param _from The address of the sender - /// @param _to The address of the recipient - /// @param _value The amount of token to be transferred - /// @return Whether the transfer was successful or not - function transferFrom(address _from, address _to, uint _value) returns (bool success) {} - - /// @notice `msg.sender` approves `_addr` to spend `_value` tokens - /// @param _spender The address of the account able to transfer the tokens - /// @param _value The amount of wei to be approved for transfer - /// @return Whether the approval was successful or not - function approve(address _spender, uint _value) returns (bool success) {} - - /// @param _owner The address of the account owning tokens - /// @param _spender The address of the account able to transfer the tokens - /// @return Amount of remaining tokens allowed to spent - function allowance(address _owner, address _spender) constant returns (uint remaining) {} - - event Transfer(address indexed _from, address indexed _to, uint _value); - event Approval(address indexed _owner, address indexed _spender, uint _value); -} diff --git a/packages/contracts/contracts/deprecated/EtherToken.sol b/packages/contracts/contracts/deprecated/EtherToken.sol deleted file mode 100644 index 566782e35..000000000 --- a/packages/contracts/contracts/deprecated/EtherToken.sol +++ /dev/null @@ -1,56 +0,0 @@ -/* - - Copyright 2017 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity 0.4.11; - -import "./../tokens/UnlimitedAllowanceToken.sol"; -import "./../base/SafeMath.sol"; - -contract EtherToken is UnlimitedAllowanceToken, SafeMath { - - string constant public name = "Ether Token"; - string constant public symbol = "WETH"; - uint8 constant public decimals = 18; - - /// @dev Fallback to calling deposit when ether is sent directly to contract. - function() - public - payable - { - deposit(); - } - - /// @dev Buys tokens with Ether, exchanging them 1:1. - function deposit() - public - payable - { - balances[msg.sender] = safeAdd(balances[msg.sender], msg.value); - totalSupply = safeAdd(totalSupply, msg.value); - } - - /// @dev Sells tokens in exchange for Ether, exchanging them 1:1. - /// @param amount Number of tokens to sell. - function withdraw(uint amount) - public - { - balances[msg.sender] = safeSub(balances[msg.sender], amount); - totalSupply = safeSub(totalSupply, amount); - require(msg.sender.send(amount)); - } -} diff --git a/packages/contracts/contracts/multisig/MultiSigWallet.sol b/packages/contracts/contracts/multisig/MultiSigWallet.sol new file mode 100644 index 000000000..68f70fe83 --- /dev/null +++ b/packages/contracts/contracts/multisig/MultiSigWallet.sol @@ -0,0 +1,365 @@ +pragma solidity ^0.4.11; + +/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution. +/// @author Stefan George - +contract MultiSigWallet { + + uint constant public MAX_OWNER_COUNT = 50; + + event Confirmation(address indexed sender, uint indexed transactionId); + event Revocation(address indexed sender, uint indexed transactionId); + event Submission(uint indexed transactionId); + event Execution(uint indexed transactionId); + event ExecutionFailure(uint indexed transactionId); + event Deposit(address indexed sender, uint value); + event OwnerAddition(address indexed owner); + event OwnerRemoval(address indexed owner); + event RequirementChange(uint required); + + mapping (uint => Transaction) public transactions; + mapping (uint => mapping (address => bool)) public confirmations; + mapping (address => bool) public isOwner; + address[] public owners; + uint public required; + uint public transactionCount; + + struct Transaction { + address destination; + uint value; + bytes data; + bool executed; + } + + modifier onlyWallet() { + if (msg.sender != address(this)) + throw; + _; + } + + modifier ownerDoesNotExist(address owner) { + if (isOwner[owner]) + throw; + _; + } + + modifier ownerExists(address owner) { + if (!isOwner[owner]) + throw; + _; + } + + modifier transactionExists(uint transactionId) { + if (transactions[transactionId].destination == 0) + throw; + _; + } + + modifier confirmed(uint transactionId, address owner) { + if (!confirmations[transactionId][owner]) + throw; + _; + } + + modifier notConfirmed(uint transactionId, address owner) { + if (confirmations[transactionId][owner]) + throw; + _; + } + + modifier notExecuted(uint transactionId) { + if (transactions[transactionId].executed) + throw; + _; + } + + modifier notNull(address _address) { + if (_address == 0) + throw; + _; + } + + modifier validRequirement(uint ownerCount, uint _required) { + if ( ownerCount > MAX_OWNER_COUNT + || _required > ownerCount + || _required == 0 + || ownerCount == 0) + throw; + _; + } + + /// @dev Fallback function allows to deposit ether. + function() + payable + { + if (msg.value > 0) + Deposit(msg.sender, msg.value); + } + + /* + * Public functions + */ + /// @dev Contract constructor sets initial owners and required number of confirmations. + /// @param _owners List of initial owners. + /// @param _required Number of required confirmations. + function MultiSigWallet(address[] _owners, uint _required) + public + validRequirement(_owners.length, _required) + { + for (uint i=0; i<_owners.length; i++) { + if (isOwner[_owners[i]] || _owners[i] == 0) + throw; + isOwner[_owners[i]] = true; + } + owners = _owners; + required = _required; + } + + /// @dev Allows to add a new owner. Transaction has to be sent by wallet. + /// @param owner Address of new owner. + function addOwner(address owner) + public + onlyWallet + ownerDoesNotExist(owner) + notNull(owner) + validRequirement(owners.length + 1, required) + { + isOwner[owner] = true; + owners.push(owner); + OwnerAddition(owner); + } + + /// @dev Allows to remove an owner. Transaction has to be sent by wallet. + /// @param owner Address of owner. + function removeOwner(address owner) + public + onlyWallet + ownerExists(owner) + { + isOwner[owner] = false; + for (uint i=0; i owners.length) + changeRequirement(owners.length); + OwnerRemoval(owner); + } + + /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet. + /// @param owner Address of owner to be replaced. + /// @param owner Address of new owner. + function replaceOwner(address owner, address newOwner) + public + onlyWallet + ownerExists(owner) + ownerDoesNotExist(newOwner) + { + for (uint i=0; i +contract MultiSigWalletWithTimeLock is MultiSigWallet { + + event ConfirmationTimeSet(uint indexed transactionId, uint confirmationTime); + event TimeLockChange(uint secondsTimeLocked); + + uint public secondsTimeLocked; + + mapping (uint => uint) public confirmationTimes; + + modifier notFullyConfirmed(uint transactionId) { + require(!isConfirmed(transactionId)); + _; + } + + modifier fullyConfirmed(uint transactionId) { + require(isConfirmed(transactionId)); + _; + } + + modifier pastTimeLock(uint transactionId) { + require(block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked); + _; + } + + /* + * Public functions + */ + + /// @dev Contract constructor sets initial owners, required number of confirmations, and time lock. + /// @param _owners List of initial owners. + /// @param _required Number of required confirmations. + /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. + function MultiSigWalletWithTimeLock(address[] _owners, uint _required, uint _secondsTimeLocked) + public + MultiSigWallet(_owners, _required) + { + secondsTimeLocked = _secondsTimeLocked; + } + + /// @dev Changes the duration of the time lock for transactions. + /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. + function changeTimeLock(uint _secondsTimeLocked) + public + onlyWallet + { + secondsTimeLocked = _secondsTimeLocked; + TimeLockChange(_secondsTimeLocked); + } + + /// @dev Allows an owner to confirm a transaction. + /// @param transactionId Transaction ID. + function confirmTransaction(uint transactionId) + public + ownerExists(msg.sender) + transactionExists(transactionId) + notConfirmed(transactionId, msg.sender) + notFullyConfirmed(transactionId) + { + confirmations[transactionId][msg.sender] = true; + Confirmation(msg.sender, transactionId); + if (isConfirmed(transactionId)) { + setConfirmationTime(transactionId, block.timestamp); + } + } + + /// @dev Allows an owner to revoke a confirmation for a transaction. + /// @param transactionId Transaction ID. + function revokeConfirmation(uint transactionId) + public + ownerExists(msg.sender) + confirmed(transactionId, msg.sender) + notExecuted(transactionId) + notFullyConfirmed(transactionId) + { + confirmations[transactionId][msg.sender] = false; + Revocation(msg.sender, transactionId); + } + + /// @dev Allows anyone to execute a confirmed transaction. + /// @param transactionId Transaction ID. + function executeTransaction(uint transactionId) + public + notExecuted(transactionId) + fullyConfirmed(transactionId) + pastTimeLock(transactionId) + { + Transaction storage tx = transactions[transactionId]; + tx.executed = true; + if (tx.destination.call.value(tx.value)(tx.data)) + Execution(transactionId); + else { + ExecutionFailure(transactionId); + tx.executed = false; + } + } + + /* + * Internal functions + */ + + /// @dev Sets the time of when a submission first passed. + function setConfirmationTime(uint transactionId, uint confirmationTime) + internal + { + confirmationTimes[transactionId] = confirmationTime; + ConfirmationTimeSet(transactionId, confirmationTime); + } +} diff --git a/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol b/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol new file mode 100644 index 000000000..5c1620808 --- /dev/null +++ b/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol @@ -0,0 +1,82 @@ +/* + + Copyright 2017 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.11; + +import "./MultiSigWalletWithTimeLock.sol"; + +contract MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress is MultiSigWalletWithTimeLock { + + address public TOKEN_TRANSFER_PROXY_CONTRACT; + + modifier validRemoveAuthorizedAddressTx(uint transactionId) { + Transaction storage tx = transactions[transactionId]; + require(tx.destination == TOKEN_TRANSFER_PROXY_CONTRACT); + require(isFunctionRemoveAuthorizedAddress(tx.data)); + _; + } + + /// @dev Contract constructor sets initial owners, required number of confirmations, time lock, and tokenTransferProxy address. + /// @param _owners List of initial owners. + /// @param _required Number of required confirmations. + /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. + /// @param _tokenTransferProxy Address of TokenTransferProxy contract. + function MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress( + address[] _owners, + uint _required, + uint _secondsTimeLocked, + address _tokenTransferProxy) + public + MultiSigWalletWithTimeLock(_owners, _required, _secondsTimeLocked) + { + TOKEN_TRANSFER_PROXY_CONTRACT = _tokenTransferProxy; + } + + /// @dev Allows execution of removeAuthorizedAddress without time lock. + /// @param transactionId Transaction ID. + function executeRemoveAuthorizedAddress(uint transactionId) + public + notExecuted(transactionId) + fullyConfirmed(transactionId) + validRemoveAuthorizedAddressTx(transactionId) + { + Transaction storage tx = transactions[transactionId]; + tx.executed = true; + if (tx.destination.call.value(tx.value)(tx.data)) + Execution(transactionId); + else { + ExecutionFailure(transactionId); + tx.executed = false; + } + } + + /// @dev Compares first 4 bytes of byte array to removeAuthorizedAddress function signature. + /// @param data Transaction data. + /// @return Successful if data is a call to removeAuthorizedAddress. + function isFunctionRemoveAuthorizedAddress(bytes data) + public + constant + returns (bool) + { + bytes4 removeAuthorizedAddressSignature = bytes4(sha3("removeAuthorizedAddress(address)")); + for (uint i = 0; i < 4; i++) { + require(data[i] == removeAuthorizedAddressSignature[i]); + } + return true; + } +} diff --git a/packages/contracts/contracts/test/DummyToken.sol b/packages/contracts/contracts/test/DummyToken.sol index 414c17b2a..cf8c27201 100644 --- a/packages/contracts/contracts/test/DummyToken.sol +++ b/packages/contracts/contracts/test/DummyToken.sol @@ -1,7 +1,7 @@ -pragma solidity 0.4.11; +pragma solidity ^0.4.11; import "./Mintable.sol"; -import "./../base/Ownable.sol"; +import "./../lib/Ownable.sol"; contract DummyToken is Mintable, Ownable { string public name; @@ -21,7 +21,9 @@ contract DummyToken is Mintable, Ownable { balances[msg.sender] = _totalSupply; } - function setBalance(address _target, uint _value) onlyOwner { + function setBalance(address _target, uint _value) + onlyOwner + { uint currBalance = balanceOf(_target); if (_value < currBalance) { totalSupply = safeSub(totalSupply, safeSub(currBalance, _value)); diff --git a/packages/contracts/contracts/test/DummyToken_v2.sol b/packages/contracts/contracts/test/DummyToken_v2.sol new file mode 100644 index 000000000..24c604369 --- /dev/null +++ b/packages/contracts/contracts/test/DummyToken_v2.sol @@ -0,0 +1,37 @@ +pragma solidity 0.4.18; + +import "./Mintable_v2.sol"; +import "./../lib/Ownable_v2.sol"; + +contract DummyToken_v2 is Mintable_v2, Ownable_v2 { + string public name; + string public symbol; + uint public decimals; + + function DummyToken( + string _name, + string _symbol, + uint _decimals, + uint _totalSupply) + public + { + name = _name; + symbol = _symbol; + decimals = _decimals; + totalSupply = _totalSupply; + balances[msg.sender] = _totalSupply; + } + + function setBalance(address _target, uint _value) + public + onlyOwner + { + uint currBalance = balanceOf(_target); + if (_value < currBalance) { + totalSupply = safeSub(totalSupply, safeSub(currBalance, _value)); + } else { + totalSupply = safeAdd(totalSupply, safeSub(_value, currBalance)); + } + balances[_target] = _value; + } +} diff --git a/packages/contracts/contracts/test/MaliciousToken.sol b/packages/contracts/contracts/test/MaliciousToken.sol index 3c1a53612..9e1322984 100644 --- a/packages/contracts/contracts/test/MaliciousToken.sol +++ b/packages/contracts/contracts/test/MaliciousToken.sol @@ -1,11 +1,13 @@ -pragma solidity 0.4.11; +pragma solidity ^0.4.11; -import "./../base/StandardToken.sol"; +import "./../tokens/StandardToken.sol"; contract MaliciousToken is StandardToken { uint8 stateToUpdate = 1; // Not null so that change only requires 5000 gas - function updateState() internal { + function updateState() + internal + { stateToUpdate++; } diff --git a/packages/contracts/contracts/test/Mintable.sol b/packages/contracts/contracts/test/Mintable.sol index 257dca705..34c9eb858 100644 --- a/packages/contracts/contracts/test/Mintable.sol +++ b/packages/contracts/contracts/test/Mintable.sol @@ -1,14 +1,16 @@ -pragma solidity 0.4.11; +pragma solidity ^0.4.11; -import "./../tokens/ERC20Token.sol"; -import "./../base/SafeMath.sol"; +import "./../tokens/UnlimitedAllowanceToken.sol"; +import "./../lib/SafeMath.sol"; /* * Mintable * Base contract that creates a mintable UnlimitedAllowanceToken */ -contract Mintable is ERC20Token, SafeMath { - function mint(uint _value) { +contract Mintable is UnlimitedAllowanceToken, SafeMath { + function mint(uint _value) + public + { require(_value <= 100000000000000000000); balances[msg.sender] = safeAdd(_value, balances[msg.sender]); totalSupply = safeAdd(totalSupply, _value); diff --git a/packages/contracts/contracts/test/Mintable_v2.sol b/packages/contracts/contracts/test/Mintable_v2.sol new file mode 100644 index 000000000..95e2fcfe3 --- /dev/null +++ b/packages/contracts/contracts/test/Mintable_v2.sol @@ -0,0 +1,18 @@ +pragma solidity 0.4.18; + +import "./../tokens/ERC20Token.sol"; +import "./../lib/SafeMath_v2.sol"; + +/* + * Mintable + * Base contract that creates a mintable UnlimitedAllowanceToken + */ +contract Mintable_v2 is ERC20Token, SafeMath_v2 { + function mint(uint _value) + public + { + require(_value <= 100000000000000000000); + balances[msg.sender] = safeAdd(_value, balances[msg.sender]); + totalSupply = safeAdd(totalSupply, _value); + } +} diff --git a/packages/contracts/contracts/tokens/ERC20Token.sol b/packages/contracts/contracts/tokens/ERC20Token.sol index 8db58c707..4596331c1 100644 --- a/packages/contracts/contracts/tokens/ERC20Token.sol +++ b/packages/contracts/contracts/tokens/ERC20Token.sol @@ -1,12 +1,15 @@ -pragma solidity 0.4.11; +pragma solidity ^0.4.18; -import "./../base/Token.sol"; +import "./Token_v2.sol"; -contract ERC20Token is Token { +contract ERC20Token is Token_v2 { uint constant MAX_UINT = 2**256 - 1; - function transfer(address _to, uint _value) returns (bool) { + function transfer(address _to, uint _value) + public + returns (bool) + { require(balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]); balances[msg.sender] -= _value; balances[_to] += _value; @@ -19,7 +22,10 @@ contract ERC20Token is Token { /// @param _to Address to transfer to. /// @param _value Amount to transfer. /// @return Success of transfer. - function transferFrom(address _from, address _to, uint _value) returns (bool) { + function transferFrom(address _from, address _to, uint _value) + public + returns (bool) + { uint allowance = allowed[_from][msg.sender]; require(balances[_from] >= _value && allowance >= _value && balances[_to] + _value >= balances[_to]); balances[_to] += _value; @@ -31,17 +37,28 @@ contract ERC20Token is Token { return true; } - function balanceOf(address _owner) constant returns (uint) { - return balances[_owner]; - } - - function approve(address _spender, uint _value) returns (bool) { + function approve(address _spender, uint _value) + public + returns (bool) + { allowed[msg.sender][_spender] = _value; Approval(msg.sender, _spender, _value); return true; } - function allowance(address _owner, address _spender) constant returns (uint) { + function balanceOf(address _owner) + public + view + returns (uint) + { + return balances[_owner]; + } + + function allowance(address _owner, address _spender) + public + view + returns (uint) + { return allowed[_owner][_spender]; } diff --git a/packages/contracts/contracts/tokens/EtherToken.sol b/packages/contracts/contracts/tokens/EtherToken.sol new file mode 100644 index 000000000..900b95337 --- /dev/null +++ b/packages/contracts/contracts/tokens/EtherToken.sol @@ -0,0 +1,56 @@ +/* + + Copyright 2017 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.4.11; + +import ".//UnlimitedAllowanceToken.sol"; +import "./../lib/SafeMath.sol"; + +contract EtherToken is UnlimitedAllowanceToken, SafeMath { + + string constant public name = "Ether Token"; + string constant public symbol = "WETH"; + uint8 constant public decimals = 18; + + /// @dev Fallback to calling deposit when ether is sent directly to contract. + function() + public + payable + { + deposit(); + } + + /// @dev Buys tokens with Ether, exchanging them 1:1. + function deposit() + public + payable + { + balances[msg.sender] = safeAdd(balances[msg.sender], msg.value); + totalSupply = safeAdd(totalSupply, msg.value); + } + + /// @dev Sells tokens in exchange for Ether, exchanging them 1:1. + /// @param amount Number of tokens to sell. + function withdraw(uint amount) + public + { + balances[msg.sender] = safeSub(balances[msg.sender], amount); + totalSupply = safeSub(totalSupply, amount); + require(msg.sender.send(amount)); + } +} diff --git a/packages/contracts/contracts/tokens/EtherToken_v2.sol b/packages/contracts/contracts/tokens/EtherToken_v2.sol index 0c7acf8a0..fe6b64266 100644 --- a/packages/contracts/contracts/tokens/EtherToken_v2.sol +++ b/packages/contracts/contracts/tokens/EtherToken_v2.sol @@ -16,12 +16,12 @@ */ -pragma solidity 0.4.11; +pragma solidity 0.4.18; -import "./../tokens/ERC20Token.sol"; -import "./../base/SafeMath.sol"; +import "./ERC20Token.sol"; +import "./../lib/SafeMath_v2.sol"; -contract EtherToken_v2 is ERC20Token, SafeMath { +contract EtherToken_v2 is ERC20Token, SafeMath_v2 { string constant public name = "Ether Token"; string constant public symbol = "WETH"; diff --git a/packages/contracts/contracts/tokens/StandardToken.sol b/packages/contracts/contracts/tokens/StandardToken.sol new file mode 100644 index 000000000..0e5c33a3a --- /dev/null +++ b/packages/contracts/contracts/tokens/StandardToken.sol @@ -0,0 +1,44 @@ +pragma solidity ^0.4.11; + +import "./Token.sol"; + +contract StandardToken is Token { + + function transfer(address _to, uint _value) returns (bool) { + //Default assumes totalSupply can't be over max (2^256 - 1). + if (balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]) { + balances[msg.sender] -= _value; + balances[_to] += _value; + Transfer(msg.sender, _to, _value); + return true; + } else { return false; } + } + + function transferFrom(address _from, address _to, uint _value) returns (bool) { + if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value >= balances[_to]) { + balances[_to] += _value; + balances[_from] -= _value; + allowed[_from][msg.sender] -= _value; + Transfer(_from, _to, _value); + return true; + } else { return false; } + } + + function balanceOf(address _owner) constant returns (uint) { + return balances[_owner]; + } + + function approve(address _spender, uint _value) returns (bool) { + allowed[msg.sender][_spender] = _value; + Approval(msg.sender, _spender, _value); + return true; + } + + function allowance(address _owner, address _spender) constant returns (uint) { + return allowed[_owner][_spender]; + } + + mapping (address => uint) balances; + mapping (address => mapping (address => uint)) allowed; + uint public totalSupply; +} diff --git a/packages/contracts/contracts/tokens/Token.sol b/packages/contracts/contracts/tokens/Token.sol new file mode 100644 index 000000000..10c6c41c1 --- /dev/null +++ b/packages/contracts/contracts/tokens/Token.sol @@ -0,0 +1,38 @@ +pragma solidity ^0.4.11; + +contract Token { + + /// @return total amount of tokens + function totalSupply() constant returns (uint supply) {} + + /// @param _owner The address from which the balance will be retrieved + /// @return The balance + function balanceOf(address _owner) constant returns (uint balance) {} + + /// @notice send `_value` token to `_to` from `msg.sender` + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + /// @return Whether the transfer was successful or not + function transfer(address _to, uint _value) returns (bool success) {} + + /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` + /// @param _from The address of the sender + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + /// @return Whether the transfer was successful or not + function transferFrom(address _from, address _to, uint _value) returns (bool success) {} + + /// @notice `msg.sender` approves `_addr` to spend `_value` tokens + /// @param _spender The address of the account able to transfer the tokens + /// @param _value The amount of wei to be approved for transfer + /// @return Whether the approval was successful or not + function approve(address _spender, uint _value) returns (bool success) {} + + /// @param _owner The address of the account owning tokens + /// @param _spender The address of the account able to transfer the tokens + /// @return Amount of remaining tokens allowed to spent + function allowance(address _owner, address _spender) constant returns (uint remaining) {} + + event Transfer(address indexed _from, address indexed _to, uint _value); + event Approval(address indexed _owner, address indexed _spender, uint _value); +} \ No newline at end of file diff --git a/packages/contracts/contracts/tokens/Token_v2.sol b/packages/contracts/contracts/tokens/Token_v2.sol new file mode 100644 index 000000000..bd46dec2b --- /dev/null +++ b/packages/contracts/contracts/tokens/Token_v2.sol @@ -0,0 +1,38 @@ +pragma solidity 0.4.18; + +contract Token_v2 { + + /// @return total amount of tokens + function totalSupply() public view returns (uint) {} + + /// @notice send `_value` token to `_to` from `msg.sender` + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + /// @return Whether the transfer was successful or not + function transfer(address _to, uint _value) public returns (bool) {} + + /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` + /// @param _from The address of the sender + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + /// @return Whether the transfer was successful or not + function transferFrom(address _from, address _to, uint _value) public returns (bool) {} + + /// @notice `msg.sender` approves `_addr` to spend `_value` tokens + /// @param _spender The address of the account able to transfer the tokens + /// @param _value The amount of wei to be approved for transfer + /// @return Whether the approval was successful or not + function approve(address _spender, uint _value) public returns (bool) {} + + /// @param _owner The address from which the balance will be retrieved + /// @return The balance + function balanceOf(address _owner) public view returns (uint) {} + + /// @param _owner The address of the account owning tokens + /// @param _spender The address of the account able to transfer the tokens + /// @return Amount of remaining tokens allowed to spent + function allowance(address _owner, address _spender) public view returns (uint) {} + + event Transfer(address indexed _from, address indexed _to, uint _value); + event Approval(address indexed _owner, address indexed _spender, uint _value); +} diff --git a/packages/contracts/contracts/tokens/UnlimitedAllowanceToken.sol b/packages/contracts/contracts/tokens/UnlimitedAllowanceToken.sol index 40e01b360..035993990 100644 --- a/packages/contracts/contracts/tokens/UnlimitedAllowanceToken.sol +++ b/packages/contracts/contracts/tokens/UnlimitedAllowanceToken.sol @@ -16,9 +16,9 @@ */ -pragma solidity 0.4.11; +pragma solidity ^0.4.11; -import "./../base/StandardToken.sol"; +import "./StandardToken.sol"; contract UnlimitedAllowanceToken is StandardToken { diff --git a/packages/contracts/contracts/tokens/ZRXToken.sol b/packages/contracts/contracts/tokens/ZRXToken.sol index c8b9c08ab..9456d1649 100644 --- a/packages/contracts/contracts/tokens/ZRXToken.sol +++ b/packages/contracts/contracts/tokens/ZRXToken.sol @@ -16,7 +16,7 @@ */ -pragma solidity 0.4.11; +pragma solidity ^0.4.11; import "./UnlimitedAllowanceToken.sol"; diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 46bf4f731..3c5dfe890 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -44,7 +44,7 @@ "dirty-chai": "^2.0.1", "mocha": "^4.0.1", "solc": "^0.4.18", - "truffle": "3.4.3", + "truffle": "^4.0.1", "tslint": "5.8.0", "types-bn": "^0.0.1", "types-ethereumjs-util": "0xProject/types-ethereumjs-util", diff --git a/packages/contracts/test/ts/erc20Token.ts b/packages/contracts/test/ts/erc20Token.ts index e2282cbf3..9aa93180b 100644 --- a/packages/contracts/test/ts/erc20Token.ts +++ b/packages/contracts/test/ts/erc20Token.ts @@ -9,7 +9,7 @@ import {ContractInstance} from '../../util/types'; import {chaiSetup} from './utils/chai_setup'; -const {DummyToken} = new Artifacts(artifacts); +const {DummyTokenV2} = new Artifacts(artifacts); const web3: Web3 = (global as any).web3; chaiSetup.configure(); const expect = chai.expect; @@ -24,7 +24,7 @@ contract('ERC20Token', (accounts: string[]) => { let token: ContractInstance; beforeEach(async () => { - token = await DummyToken.new({from: owner}); + token = await DummyTokenV2.new({from: owner}); await token.mint(MAX_MINT_VALUE, {from: owner}); tokenAddress = token.address; }); @@ -33,7 +33,7 @@ contract('ERC20Token', (accounts: string[]) => { it('should throw if owner has insufficient balance', async () => { const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); const amountToTransfer = ownerBalance.plus(1); - return expect(token.transfer.call(owner, spender, amountToTransfer, {from: spender})) + return expect(token.transfer.call(spender, amountToTransfer, {from: owner})) .to.be.rejectedWith(constants.REVERT); }); diff --git a/packages/contracts/test/ts/exchange/core.ts b/packages/contracts/test/ts/exchange/core.ts index e4aa74c32..7f632c6e6 100644 --- a/packages/contracts/test/ts/exchange/core.ts +++ b/packages/contracts/test/ts/exchange/core.ts @@ -610,7 +610,7 @@ contract('Exchange', (accounts: string[]) => { }); return expect(exWrapper.fillOrderAsync(order, taker, {shouldThrowOnInsufficientBalanceOrAllowance: false})) - .to.be.rejectedWith(constants.INVALID_OPCODE); + .to.be.rejectedWith(constants.REVERT); }); it('should not change balances if an order is expired', async () => { diff --git a/packages/contracts/util/artifacts.ts b/packages/contracts/util/artifacts.ts index cb06739af..6b05df78c 100644 --- a/packages/contracts/util/artifacts.ts +++ b/packages/contracts/util/artifacts.ts @@ -6,6 +6,7 @@ export class Artifacts { public Exchange: any; public ZRXToken: any; public DummyToken: any; + public DummyTokenV2: any; public EtherToken: any; public EtherTokenV2: any; public MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: any; @@ -18,6 +19,7 @@ export class Artifacts { this.Exchange = artifacts.require('Exchange'); this.ZRXToken = artifacts.require('ZRXToken'); this.DummyToken = artifacts.require('DummyToken'); + this.DummyTokenV2 = artifacts.require('DummyToken_v2'); this.EtherToken = artifacts.require('EtherToken'); this.EtherTokenV2 = artifacts.require('EtherToken_v2'); this.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress = artifacts.require( -- cgit v1.2.3 From 2cc410e61f75a43ce36416b7d15f897d6e7fc92c Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Thu, 7 Dec 2017 00:45:41 -0800 Subject: Update 0x.js version, fix build errors --- packages/contracts/package.json | 2 +- packages/contracts/test/ts/erc20Token.ts | 5 ++++- packages/contracts/test/ts/ether_token.ts | 7 +++++-- packages/contracts/test/ts/ether_token_v2.ts | 10 ++++++---- packages/contracts/test/ts/exchange/core.ts | 1 + packages/contracts/test/ts/unlimitedAllowanceToken.ts | 6 +++++- packages/contracts/test/ts/zrxToken.ts | 6 ++++-- packages/contracts/util/constants.ts | 1 + 8 files changed, 27 insertions(+), 11 deletions(-) (limited to 'packages') diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 3c5dfe890..31c69e8d5 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -53,7 +53,7 @@ "yargs": "^10.0.3" }, "dependencies": { - "0x.js": "^0.22.6", + "0x.js": "^0.27.1", "@0xproject/json-schemas": "^0.6.10", "@0xproject/utils": "^0.1.0", "@0xproject/web3-wrapper": "^0.1.0", diff --git a/packages/contracts/test/ts/erc20Token.ts b/packages/contracts/test/ts/erc20Token.ts index 9aa93180b..1edcfcbbd 100644 --- a/packages/contracts/test/ts/erc20Token.ts +++ b/packages/contracts/test/ts/erc20Token.ts @@ -15,7 +15,10 @@ chaiSetup.configure(); const expect = chai.expect; contract('ERC20Token', (accounts: string[]) => { - const zeroEx = new ZeroEx(web3.currentProvider); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + }; + const zeroEx = new ZeroEx(web3.currentProvider, config); const owner = accounts[0]; const spender = accounts[1]; diff --git a/packages/contracts/test/ts/ether_token.ts b/packages/contracts/test/ts/ether_token.ts index dbb4d2ee6..79c618ec2 100644 --- a/packages/contracts/test/ts/ether_token.ts +++ b/packages/contracts/test/ts/ether_token.ts @@ -5,6 +5,7 @@ import * as chai from 'chai'; import Web3 = require('web3'); import {Artifacts} from '../../util/artifacts'; +import {constants} from '../../util/constants'; import {chaiSetup} from './utils/chai_setup'; @@ -22,11 +23,13 @@ contract('EtherToken', (accounts: string[]) => { const gasPrice = ZeroEx.toBaseUnitAmount(new BigNumber(20), 9); let zeroEx: ZeroEx; let etherTokenAddress: string; + before(async () => { etherTokenAddress = EtherToken.address; zeroEx = new ZeroEx(web3.currentProvider, { - gasPrice, - etherTokenContractAddress: etherTokenAddress, + gasPrice, + etherTokenContractAddress: etherTokenAddress, + networkId: constants.TESTRPC_NETWORK_ID, }); }); diff --git a/packages/contracts/test/ts/ether_token_v2.ts b/packages/contracts/test/ts/ether_token_v2.ts index 0c352b522..4931eb798 100644 --- a/packages/contracts/test/ts/ether_token_v2.ts +++ b/packages/contracts/test/ts/ether_token_v2.ts @@ -5,6 +5,7 @@ import promisify = require('es6-promisify'); import Web3 = require('web3'); import {Artifacts} from '../../util/artifacts'; +import {constants} from '../../util/constants'; import {chaiSetup} from './utils/chai_setup'; @@ -26,8 +27,9 @@ contract('EtherTokenV2', (accounts: string[]) => { const etherToken = await EtherTokenV2.new(); etherTokenAddress = etherToken.address; zeroEx = new ZeroEx(web3.currentProvider, { - gasPrice, - etherTokenContractAddress: etherTokenAddress, + gasPrice, + etherTokenContractAddress: etherTokenAddress, + networkId: constants.TESTRPC_NETWORK_ID, }); }); @@ -76,7 +78,7 @@ contract('EtherTokenV2', (accounts: string[]) => { const expectedFrom = ZeroEx.NULL_ADDRESS; const expectedTo = account; const expectedValue = ethToDeposit; - const logArgs = logs[0].args; + const logArgs = (logs[0] as any).args; expect(logArgs._from).to.equal(expectedFrom); expect(logArgs._to).to.equal(expectedTo); expect(logArgs._value).to.be.bignumber.equal(ethToDeposit); @@ -128,7 +130,7 @@ contract('EtherTokenV2', (accounts: string[]) => { const expectedFrom = account; const expectedTo = ZeroEx.NULL_ADDRESS; const expectedValue = ethTokensToWithdraw; - const logArgs = logs[0].args; + const logArgs = (logs[0] as any).args; expect(logArgs._from).to.equal(expectedFrom); expect(logArgs._to).to.equal(expectedTo); expect(logArgs._value).to.be.bignumber.equal(ethTokensToWithdraw); diff --git a/packages/contracts/test/ts/exchange/core.ts b/packages/contracts/test/ts/exchange/core.ts index 7f632c6e6..641084937 100644 --- a/packages/contracts/test/ts/exchange/core.ts +++ b/packages/contracts/test/ts/exchange/core.ts @@ -59,6 +59,7 @@ contract('Exchange', (accounts: string[]) => { exWrapper = new ExchangeWrapper(exchange); zeroEx = new ZeroEx(web3.currentProvider, { exchangeContractAddress: exchange.address, + networkId: constants.TESTRPC_NETWORK_ID, }); const [repAddress, dgdAddress, zrxAddress] = await Promise.all([ diff --git a/packages/contracts/test/ts/unlimitedAllowanceToken.ts b/packages/contracts/test/ts/unlimitedAllowanceToken.ts index ca3fcd7d2..3b4d2db77 100644 --- a/packages/contracts/test/ts/unlimitedAllowanceToken.ts +++ b/packages/contracts/test/ts/unlimitedAllowanceToken.ts @@ -4,6 +4,7 @@ import * as chai from 'chai'; import * as Web3 from 'web3'; import {Artifacts} from '../../util/artifacts'; +import {constants} from '../../util/constants'; import {ContractInstance} from '../../util/types'; import {chaiSetup} from './utils/chai_setup'; @@ -14,7 +15,10 @@ chaiSetup.configure(); const expect = chai.expect; contract('UnlimitedAllowanceToken', (accounts: string[]) => { - const zeroEx = new ZeroEx(web3.currentProvider); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + }; + const zeroEx = new ZeroEx(web3.currentProvider, config); const owner = accounts[0]; const spender = accounts[1]; diff --git a/packages/contracts/test/ts/zrxToken.ts b/packages/contracts/test/ts/zrxToken.ts index 471ee93f2..1c9655402 100644 --- a/packages/contracts/test/ts/zrxToken.ts +++ b/packages/contracts/test/ts/zrxToken.ts @@ -4,6 +4,7 @@ import * as chai from 'chai'; import Web3 = require('web3'); import {Artifacts} from '../../util/artifacts'; +import {constants} from '../../util/constants'; import {ContractInstance} from '../../util/types'; import {chaiSetup} from './utils/chai_setup'; @@ -25,9 +26,10 @@ contract('ZRXToken', (accounts: string[]) => { beforeEach(async () => { zeroEx = new ZeroEx(web3.currentProvider, { - exchangeContractAddress: Exchange.address, + exchangeContractAddress: Exchange.address, + networkId: constants.TESTRPC_NETWORK_ID, }); - zrxAddress = await zeroEx.exchange.getZRXTokenAddressAsync(); + zrxAddress = zeroEx.exchange.getZRXTokenAddress(); zrx = await ZRXToken.at(zrxAddress); MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; }); diff --git a/packages/contracts/util/constants.ts b/packages/contracts/util/constants.ts index 733ad2312..c28a18e27 100644 --- a/packages/contracts/util/constants.ts +++ b/packages/contracts/util/constants.ts @@ -2,4 +2,5 @@ export const constants = { NULL_BYTES: '0x', INVALID_OPCODE: 'invalid opcode', REVERT: 'revert', + TESTRPC_NETWORK_ID: 50, }; -- cgit v1.2.3 From 8b29f6f18de0af62cb1737a3b6d4cc188b764b97 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Thu, 7 Dec 2017 10:22:08 -0800 Subject: Fix typo, change variable name to be consistent --- packages/contracts/contracts/tokens/EtherToken.sol | 2 +- packages/contracts/contracts/tokens/EtherToken_v2.sol | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'packages') diff --git a/packages/contracts/contracts/tokens/EtherToken.sol b/packages/contracts/contracts/tokens/EtherToken.sol index 900b95337..daef97d8f 100644 --- a/packages/contracts/contracts/tokens/EtherToken.sol +++ b/packages/contracts/contracts/tokens/EtherToken.sol @@ -18,7 +18,7 @@ pragma solidity ^0.4.11; -import ".//UnlimitedAllowanceToken.sol"; +import "./UnlimitedAllowanceToken.sol"; import "./../lib/SafeMath.sol"; contract EtherToken is UnlimitedAllowanceToken, SafeMath { diff --git a/packages/contracts/contracts/tokens/EtherToken_v2.sol b/packages/contracts/contracts/tokens/EtherToken_v2.sol index fe6b64266..d56d54432 100644 --- a/packages/contracts/contracts/tokens/EtherToken_v2.sol +++ b/packages/contracts/contracts/tokens/EtherToken_v2.sol @@ -47,12 +47,12 @@ contract EtherToken_v2 is ERC20Token, SafeMath_v2 { /// @dev Sells tokens in exchange for Ether, exchanging them 1:1. /// @param amount Number of tokens to sell. - function withdraw(uint amount) + function withdraw(uint _value) public { - balances[msg.sender] = safeSub(balances[msg.sender], amount); - totalSupply = safeSub(totalSupply, amount); - require(msg.sender.send(amount)); - Transfer(msg.sender, address(0), amount); + balances[msg.sender] = safeSub(balances[msg.sender], _value); + totalSupply = safeSub(totalSupply, _value); + require(msg.sender.send(_value)); + Transfer(msg.sender, address(0), _value); } } -- cgit v1.2.3 From 6f2cb661638f86bae7a000f69cca1a6ba32a7087 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 11 Dec 2017 13:19:13 -0800 Subject: Refactor unlimited allowance logic out of ERC20Token --- .../contracts/contracts/test/DummyToken_v2.sol | 2 +- packages/contracts/contracts/test/Mintable_v2.sol | 4 +- packages/contracts/contracts/tokens/ERC20Token.sol | 16 +- .../contracts/contracts/tokens/EtherToken_v2.sol | 6 +- .../tokens/UnlimitedAllowanceToken_v2.sol | 46 ++++++ packages/contracts/test/ts/erc20Token.ts | 126 --------------- .../contracts/test/ts/unlimitedAllowanceToken.ts | 119 --------------- .../contracts/test/ts/unlimited_allowance_token.ts | 119 +++++++++++++++ .../test/ts/unlimited_allowance_token_v2.ts | 126 +++++++++++++++ packages/contracts/test/ts/zrxToken.ts | 170 --------------------- packages/contracts/test/ts/zrx_token.ts | 170 +++++++++++++++++++++ 11 files changed, 470 insertions(+), 434 deletions(-) create mode 100644 packages/contracts/contracts/tokens/UnlimitedAllowanceToken_v2.sol delete mode 100644 packages/contracts/test/ts/erc20Token.ts delete mode 100644 packages/contracts/test/ts/unlimitedAllowanceToken.ts create mode 100644 packages/contracts/test/ts/unlimited_allowance_token.ts create mode 100644 packages/contracts/test/ts/unlimited_allowance_token_v2.ts delete mode 100644 packages/contracts/test/ts/zrxToken.ts create mode 100644 packages/contracts/test/ts/zrx_token.ts (limited to 'packages') diff --git a/packages/contracts/contracts/test/DummyToken_v2.sol b/packages/contracts/contracts/test/DummyToken_v2.sol index 24c604369..e3392bf64 100644 --- a/packages/contracts/contracts/test/DummyToken_v2.sol +++ b/packages/contracts/contracts/test/DummyToken_v2.sol @@ -8,7 +8,7 @@ contract DummyToken_v2 is Mintable_v2, Ownable_v2 { string public symbol; uint public decimals; - function DummyToken( + function DummyToken_v2( string _name, string _symbol, uint _decimals, diff --git a/packages/contracts/contracts/test/Mintable_v2.sol b/packages/contracts/contracts/test/Mintable_v2.sol index 95e2fcfe3..a2605791f 100644 --- a/packages/contracts/contracts/test/Mintable_v2.sol +++ b/packages/contracts/contracts/test/Mintable_v2.sol @@ -1,13 +1,13 @@ pragma solidity 0.4.18; -import "./../tokens/ERC20Token.sol"; +import "./../tokens/UnlimitedAllowanceToken_v2.sol"; import "./../lib/SafeMath_v2.sol"; /* * Mintable * Base contract that creates a mintable UnlimitedAllowanceToken */ -contract Mintable_v2 is ERC20Token, SafeMath_v2 { +contract Mintable_v2 is UnlimitedAllowanceToken_v2, SafeMath_v2 { function mint(uint _value) public { diff --git a/packages/contracts/contracts/tokens/ERC20Token.sol b/packages/contracts/contracts/tokens/ERC20Token.sol index 4596331c1..5ec81032f 100644 --- a/packages/contracts/contracts/tokens/ERC20Token.sol +++ b/packages/contracts/contracts/tokens/ERC20Token.sol @@ -1,11 +1,9 @@ -pragma solidity ^0.4.18; +pragma solidity 0.4.18; import "./Token_v2.sol"; contract ERC20Token is Token_v2 { - uint constant MAX_UINT = 2**256 - 1; - function transfer(address _to, uint _value) public returns (bool) @@ -17,22 +15,14 @@ contract ERC20Token is Token_v2 { return true; } - /// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance. See https://github.com/ethereum/EIPs/issues/717 - /// @param _from Address to transfer from. - /// @param _to Address to transfer to. - /// @param _value Amount to transfer. - /// @return Success of transfer. function transferFrom(address _from, address _to, uint _value) public returns (bool) { - uint allowance = allowed[_from][msg.sender]; - require(balances[_from] >= _value && allowance >= _value && balances[_to] + _value >= balances[_to]); + require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value >= balances[_to]); balances[_to] += _value; balances[_from] -= _value; - if (allowance < MAX_UINT) { - allowed[_from][msg.sender] -= _value; - } + allowed[_from][msg.sender] -= _value; Transfer(_from, _to, _value); return true; } diff --git a/packages/contracts/contracts/tokens/EtherToken_v2.sol b/packages/contracts/contracts/tokens/EtherToken_v2.sol index d56d54432..a501013e4 100644 --- a/packages/contracts/contracts/tokens/EtherToken_v2.sol +++ b/packages/contracts/contracts/tokens/EtherToken_v2.sol @@ -18,10 +18,10 @@ pragma solidity 0.4.18; -import "./ERC20Token.sol"; +import "./UnlimitedAllowanceToken_v2.sol"; import "./../lib/SafeMath_v2.sol"; -contract EtherToken_v2 is ERC20Token, SafeMath_v2 { +contract EtherToken_v2 is UnlimitedAllowanceToken_v2, SafeMath_v2 { string constant public name = "Ether Token"; string constant public symbol = "WETH"; @@ -46,7 +46,7 @@ contract EtherToken_v2 is ERC20Token, SafeMath_v2 { } /// @dev Sells tokens in exchange for Ether, exchanging them 1:1. - /// @param amount Number of tokens to sell. + /// @param _value Number of tokens to sell. function withdraw(uint _value) public { diff --git a/packages/contracts/contracts/tokens/UnlimitedAllowanceToken_v2.sol b/packages/contracts/contracts/tokens/UnlimitedAllowanceToken_v2.sol new file mode 100644 index 000000000..2da54fee2 --- /dev/null +++ b/packages/contracts/contracts/tokens/UnlimitedAllowanceToken_v2.sol @@ -0,0 +1,46 @@ +/* + + Copyright 2017 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity 0.4.18; + +import "./ERC20Token.sol"; + +contract UnlimitedAllowanceToken_v2 is ERC20Token { + + uint constant MAX_UINT = 2**256 - 1; + + /// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance. See https://github.com/ethereum/EIPs/issues/717 + /// @param _from Address to transfer from. + /// @param _to Address to transfer to. + /// @param _value Amount to transfer. + /// @return Success of transfer. + function transferFrom(address _from, address _to, uint _value) + public + returns (bool) + { + uint allowance = allowed[_from][msg.sender]; + require(balances[_from] >= _value && allowance >= _value && balances[_to] + _value >= balances[_to]); + balances[_to] += _value; + balances[_from] -= _value; + if (allowance < MAX_UINT) { + allowed[_from][msg.sender] -= _value; + } + Transfer(_from, _to, _value); + return true; + } +} diff --git a/packages/contracts/test/ts/erc20Token.ts b/packages/contracts/test/ts/erc20Token.ts deleted file mode 100644 index 1edcfcbbd..000000000 --- a/packages/contracts/test/ts/erc20Token.ts +++ /dev/null @@ -1,126 +0,0 @@ -import {ZeroEx} from '0x.js'; -import {BigNumber} from 'bignumber.js'; -import * as chai from 'chai'; -import * as Web3 from 'web3'; - -import {Artifacts} from '../../util/artifacts'; -import {constants} from '../../util/constants'; -import {ContractInstance} from '../../util/types'; - -import {chaiSetup} from './utils/chai_setup'; - -const {DummyTokenV2} = new Artifacts(artifacts); -const web3: Web3 = (global as any).web3; -chaiSetup.configure(); -const expect = chai.expect; - -contract('ERC20Token', (accounts: string[]) => { - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; - const zeroEx = new ZeroEx(web3.currentProvider, config); - const owner = accounts[0]; - const spender = accounts[1]; - - const MAX_MINT_VALUE = new BigNumber(100000000000000000000); - let tokenAddress: string; - let token: ContractInstance; - - beforeEach(async () => { - token = await DummyTokenV2.new({from: owner}); - await token.mint(MAX_MINT_VALUE, {from: owner}); - tokenAddress = token.address; - }); - - describe('transfer', () => { - it('should throw if owner has insufficient balance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = ownerBalance.plus(1); - return expect(token.transfer.call(spender, amountToTransfer, {from: owner})) - .to.be.rejectedWith(constants.REVERT); - }); - - it('should transfer balance from sender to receiver', async () => { - const receiver = spender; - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = new BigNumber(1); - await zeroEx.token.transferAsync(tokenAddress, owner, receiver, amountToTransfer); - const finalOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const finalReceiverBalance = await zeroEx.token.getBalanceAsync(tokenAddress, receiver); - - const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer); - const expectedFinalReceiverBalance = amountToTransfer; - expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance); - expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance); - }); - - it('should return true on a 0 value transfer', async () => { - const didReturnTrue = await token.transfer.call(spender, 0, {from: owner}); - expect(didReturnTrue).to.be.true(); - }); - }); - - describe('transferFrom', () => { - it('should throw if owner has insufficient balance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = ownerBalance.plus(1); - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer); - return expect(token.transferFrom.call(owner, spender, amountToTransfer, {from: spender})) - .to.be.rejectedWith(constants.REVERT); - }); - - it('should throw if spender has insufficient allowance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = ownerBalance; - - const spenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); - const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; - expect(spenderAllowanceIsInsufficient).to.be.true(); - - return expect(token.transferFrom.call(owner, spender, amountToTransfer, {from: spender})) - .to.be.rejectedWith(constants.REVERT); - }); - - it('should return true on a 0 value transfer', async () => { - const amountToTransfer = 0; - const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); - expect(didReturnTrue).to.be.true(); - }); - - it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = initOwnerBalance; - const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); - - const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); - expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); - }); - - it('should transfer the correct balances if spender has sufficient allowance', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = initOwnerBalance; - const initSpenderAllowance = initOwnerBalance; - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); - - const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender); - - expect(newOwnerBalance).to.be.bignumber.equal(0); - expect(newSpenderBalance).to.be.bignumber.equal(initOwnerBalance); - }); - - it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = initOwnerBalance; - const initSpenderAllowance = initOwnerBalance; - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); - - const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); - expect(newSpenderAllowance).to.be.bignumber.equal(0); - }); - }); -}); diff --git a/packages/contracts/test/ts/unlimitedAllowanceToken.ts b/packages/contracts/test/ts/unlimitedAllowanceToken.ts deleted file mode 100644 index 3b4d2db77..000000000 --- a/packages/contracts/test/ts/unlimitedAllowanceToken.ts +++ /dev/null @@ -1,119 +0,0 @@ -import {ZeroEx} from '0x.js'; -import {BigNumber} from 'bignumber.js'; -import * as chai from 'chai'; -import * as Web3 from 'web3'; - -import {Artifacts} from '../../util/artifacts'; -import {constants} from '../../util/constants'; -import {ContractInstance} from '../../util/types'; - -import {chaiSetup} from './utils/chai_setup'; - -const {DummyToken} = new Artifacts(artifacts); -const web3: Web3 = (global as any).web3; -chaiSetup.configure(); -const expect = chai.expect; - -contract('UnlimitedAllowanceToken', (accounts: string[]) => { - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; - const zeroEx = new ZeroEx(web3.currentProvider, config); - const owner = accounts[0]; - const spender = accounts[1]; - - const MAX_MINT_VALUE = new BigNumber(100000000000000000000); - let tokenAddress: string; - let token: ContractInstance; - - beforeEach(async () => { - token = await DummyToken.new({from: owner}); - await token.mint(MAX_MINT_VALUE, {from: owner}); - tokenAddress = token.address; - }); - - describe('transfer', () => { - it('should transfer balance from sender to receiver', async () => { - const receiver = spender; - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = new BigNumber(1); - await zeroEx.token.transferAsync(tokenAddress, owner, receiver, amountToTransfer); - const finalOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const finalReceiverBalance = await zeroEx.token.getBalanceAsync(tokenAddress, receiver); - - const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer); - const expectedFinalReceiverBalance = amountToTransfer; - expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance); - expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance); - }); - - it('should return true on a 0 value transfer', async () => { - const didReturnTrue = await token.transfer.call(spender, 0, {from: owner}); - expect(didReturnTrue).to.be.true(); - }); - }); - - describe('transferFrom', () => { - it('should return false if owner has insufficient balance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = ownerBalance.plus(1); - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer); - const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); - expect(didReturnTrue).to.be.false(); - }); - - it('should return false if spender has insufficient allowance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = ownerBalance; - - const spenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); - const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; - expect(spenderAllowanceIsInsufficient).to.be.true(); - - const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); - expect(didReturnTrue).to.be.false(); - }); - - it('should return true on a 0 value transfer', async () => { - const amountToTransfer = 0; - const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); - expect(didReturnTrue).to.be.true(); - }); - - it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = initOwnerBalance; - const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); - - const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); - expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); - }); - - it('should transfer the correct balances if spender has sufficient allowance', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = initOwnerBalance; - const initSpenderAllowance = initOwnerBalance; - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); - - const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender); - - expect(newOwnerBalance).to.be.bignumber.equal(0); - expect(newSpenderBalance).to.be.bignumber.equal(initOwnerBalance); - }); - - it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); - const amountToTransfer = initOwnerBalance; - const initSpenderAllowance = initOwnerBalance; - await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); - - const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); - expect(newSpenderAllowance).to.be.bignumber.equal(0); - }); - }); -}); diff --git a/packages/contracts/test/ts/unlimited_allowance_token.ts b/packages/contracts/test/ts/unlimited_allowance_token.ts new file mode 100644 index 000000000..3b4d2db77 --- /dev/null +++ b/packages/contracts/test/ts/unlimited_allowance_token.ts @@ -0,0 +1,119 @@ +import {ZeroEx} from '0x.js'; +import {BigNumber} from 'bignumber.js'; +import * as chai from 'chai'; +import * as Web3 from 'web3'; + +import {Artifacts} from '../../util/artifacts'; +import {constants} from '../../util/constants'; +import {ContractInstance} from '../../util/types'; + +import {chaiSetup} from './utils/chai_setup'; + +const {DummyToken} = new Artifacts(artifacts); +const web3: Web3 = (global as any).web3; +chaiSetup.configure(); +const expect = chai.expect; + +contract('UnlimitedAllowanceToken', (accounts: string[]) => { + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + }; + const zeroEx = new ZeroEx(web3.currentProvider, config); + const owner = accounts[0]; + const spender = accounts[1]; + + const MAX_MINT_VALUE = new BigNumber(100000000000000000000); + let tokenAddress: string; + let token: ContractInstance; + + beforeEach(async () => { + token = await DummyToken.new({from: owner}); + await token.mint(MAX_MINT_VALUE, {from: owner}); + tokenAddress = token.address; + }); + + describe('transfer', () => { + it('should transfer balance from sender to receiver', async () => { + const receiver = spender; + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = new BigNumber(1); + await zeroEx.token.transferAsync(tokenAddress, owner, receiver, amountToTransfer); + const finalOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const finalReceiverBalance = await zeroEx.token.getBalanceAsync(tokenAddress, receiver); + + const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer); + const expectedFinalReceiverBalance = amountToTransfer; + expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance); + expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance); + }); + + it('should return true on a 0 value transfer', async () => { + const didReturnTrue = await token.transfer.call(spender, 0, {from: owner}); + expect(didReturnTrue).to.be.true(); + }); + }); + + describe('transferFrom', () => { + it('should return false if owner has insufficient balance', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = ownerBalance.plus(1); + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer); + const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); + expect(didReturnTrue).to.be.false(); + }); + + it('should return false if spender has insufficient allowance', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = ownerBalance; + + const spenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; + expect(spenderAllowanceIsInsufficient).to.be.true(); + + const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); + expect(didReturnTrue).to.be.false(); + }); + + it('should return true on a 0 value transfer', async () => { + const amountToTransfer = 0; + const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); + expect(didReturnTrue).to.be.true(); + }); + + it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + + const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); + }); + + it('should transfer the correct balances if spender has sufficient allowance', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = initOwnerBalance; + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + + const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender); + + expect(newOwnerBalance).to.be.bignumber.equal(0); + expect(newSpenderBalance).to.be.bignumber.equal(initOwnerBalance); + }); + + it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = initOwnerBalance; + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + + const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + expect(newSpenderAllowance).to.be.bignumber.equal(0); + }); + }); +}); diff --git a/packages/contracts/test/ts/unlimited_allowance_token_v2.ts b/packages/contracts/test/ts/unlimited_allowance_token_v2.ts new file mode 100644 index 000000000..73e12f00c --- /dev/null +++ b/packages/contracts/test/ts/unlimited_allowance_token_v2.ts @@ -0,0 +1,126 @@ +import {ZeroEx} from '0x.js'; +import {BigNumber} from 'bignumber.js'; +import * as chai from 'chai'; +import * as Web3 from 'web3'; + +import {Artifacts} from '../../util/artifacts'; +import {constants} from '../../util/constants'; +import {ContractInstance} from '../../util/types'; + +import {chaiSetup} from './utils/chai_setup'; + +const {DummyTokenV2} = new Artifacts(artifacts); +const web3: Web3 = (global as any).web3; +chaiSetup.configure(); +const expect = chai.expect; + +contract('UnlimitedAllowanceTokenV2', (accounts: string[]) => { + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + }; + const zeroEx = new ZeroEx(web3.currentProvider, config); + const owner = accounts[0]; + const spender = accounts[1]; + + const MAX_MINT_VALUE = new BigNumber(100000000000000000000); + let tokenAddress: string; + let token: ContractInstance; + + beforeEach(async () => { + token = await DummyTokenV2.new({from: owner}); + await token.mint(MAX_MINT_VALUE, {from: owner}); + tokenAddress = token.address; + }); + + describe('transfer', () => { + it('should throw if owner has insufficient balance', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = ownerBalance.plus(1); + return expect(token.transfer.call(spender, amountToTransfer, {from: owner})) + .to.be.rejectedWith(constants.REVERT); + }); + + it('should transfer balance from sender to receiver', async () => { + const receiver = spender; + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = new BigNumber(1); + await zeroEx.token.transferAsync(tokenAddress, owner, receiver, amountToTransfer); + const finalOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const finalReceiverBalance = await zeroEx.token.getBalanceAsync(tokenAddress, receiver); + + const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer); + const expectedFinalReceiverBalance = amountToTransfer; + expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance); + expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance); + }); + + it('should return true on a 0 value transfer', async () => { + const didReturnTrue = await token.transfer.call(spender, 0, {from: owner}); + expect(didReturnTrue).to.be.true(); + }); + }); + + describe('transferFrom', () => { + it('should throw if owner has insufficient balance', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = ownerBalance.plus(1); + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer); + return expect(token.transferFrom.call(owner, spender, amountToTransfer, {from: spender})) + .to.be.rejectedWith(constants.REVERT); + }); + + it('should throw if spender has insufficient allowance', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = ownerBalance; + + const spenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; + expect(spenderAllowanceIsInsufficient).to.be.true(); + + return expect(token.transferFrom.call(owner, spender, amountToTransfer, {from: spender})) + .to.be.rejectedWith(constants.REVERT); + }); + + it('should return true on a 0 value transfer', async () => { + const amountToTransfer = 0; + const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); + expect(didReturnTrue).to.be.true(); + }); + + it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + + const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); + }); + + it('should transfer the correct balances if spender has sufficient allowance', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = initOwnerBalance; + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + + const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender); + + expect(newOwnerBalance).to.be.bignumber.equal(0); + expect(newSpenderBalance).to.be.bignumber.equal(initOwnerBalance); + }); + + it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = initOwnerBalance; + await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + + const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); + expect(newSpenderAllowance).to.be.bignumber.equal(0); + }); + }); +}); diff --git a/packages/contracts/test/ts/zrxToken.ts b/packages/contracts/test/ts/zrxToken.ts deleted file mode 100644 index 1c9655402..000000000 --- a/packages/contracts/test/ts/zrxToken.ts +++ /dev/null @@ -1,170 +0,0 @@ -import {ZeroEx} from '0x.js'; -import {BigNumber} from 'bignumber.js'; -import * as chai from 'chai'; -import Web3 = require('web3'); - -import {Artifacts} from '../../util/artifacts'; -import {constants} from '../../util/constants'; -import {ContractInstance} from '../../util/types'; - -import {chaiSetup} from './utils/chai_setup'; - -chaiSetup.configure(); -const expect = chai.expect; -const {Exchange, ZRXToken} = new Artifacts(artifacts); -const web3: Web3 = (global as any).web3; - -contract('ZRXToken', (accounts: string[]) => { - const owner = accounts[0]; - const spender = accounts[1]; - let zeroEx: ZeroEx; - - let MAX_UINT: BigNumber; - - let zrx: ContractInstance; - let zrxAddress: string; - - beforeEach(async () => { - zeroEx = new ZeroEx(web3.currentProvider, { - exchangeContractAddress: Exchange.address, - networkId: constants.TESTRPC_NETWORK_ID, - }); - zrxAddress = zeroEx.exchange.getZRXTokenAddress(); - zrx = await ZRXToken.at(zrxAddress); - MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; - }); - - describe('constants', () => { - it('should have 18 decimals', async () => { - const decimals = new BigNumber(await zrx.decimals.call()); - const expectedDecimals = 18; - expect(decimals).to.be.bignumber.equal(expectedDecimals); - }); - - it('should have a total supply of 1 billion tokens', async () => { - const totalSupply = new BigNumber(await zrx.totalSupply.call()); - const expectedTotalSupply = 1000000000; - expect(ZeroEx.toUnitAmount(totalSupply, 18)).to.be.bignumber.equal(expectedTotalSupply); - }); - - it('should be named 0x Protocol Token', async () => { - const name = await zrx.name.call(); - const expectedName = '0x Protocol Token'; - expect(name).to.be.equal(expectedName); - }); - - it('should have the symbol ZRX', async () => { - const symbol = await zrx.symbol.call(); - const expectedSymbol = 'ZRX'; - expect(symbol).to.be.equal(expectedSymbol); - }); - }); - - describe('constructor', () => { - it('should initialize owner balance to totalSupply', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const totalSupply = new BigNumber(await zrx.totalSupply.call()); - expect(totalSupply).to.be.bignumber.equal(ownerBalance); - }); - }); - - describe('transfer', () => { - it('should transfer balance from sender to receiver', async () => { - const receiver = spender; - const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const amountToTransfer = new BigNumber(1); - const txHash = await zeroEx.token.transferAsync(zrxAddress, owner, receiver, amountToTransfer); - await zeroEx.awaitTransactionMinedAsync(txHash); - const finalOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const finalReceiverBalance = await zeroEx.token.getBalanceAsync(zrxAddress, receiver); - - const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer); - const expectedFinalReceiverBalance = amountToTransfer; - expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance); - expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance); - }); - - it('should return true on a 0 value transfer', async () => { - const didReturnTrue = await zrx.transfer.call(spender, 0, {from: owner}); - expect(didReturnTrue).to.be.true(); - }); - }); - - describe('transferFrom', () => { - it('should return false if owner has insufficient balance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const amountToTransfer = ownerBalance.plus(1); - let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer); - await zeroEx.awaitTransactionMinedAsync(txHash); - const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); - expect(didReturnTrue).to.be.false(); - // Reset allowance - txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, new BigNumber(0)); - await zeroEx.awaitTransactionMinedAsync(txHash); - }); - - it('should return false if spender has insufficient allowance', async () => { - const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const amountToTransfer = ownerBalance; - - const spenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); - const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; - expect(spenderAllowanceIsInsufficient).to.be.true(); - - const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); - expect(didReturnTrue).to.be.false(); - }); - - it('should return true on a 0 value transfer', async () => { - const amountToTransfer = 0; - const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); - expect(didReturnTrue).to.be.true(); - }); - - it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const amountToTransfer = initOwnerBalance; - const initSpenderAllowance = MAX_UINT; - let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); - await zeroEx.awaitTransactionMinedAsync(txHash); - txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer); - await zeroEx.awaitTransactionMinedAsync(txHash); - - const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); - expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); - // Restore balance - txHash = await zeroEx.token.transferAsync(zrxAddress, spender, owner, amountToTransfer); - await zeroEx.awaitTransactionMinedAsync(txHash); - }); - - it('should transfer the correct balances if spender has sufficient allowance', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const initSpenderBalance = await zeroEx.token.getBalanceAsync(zrxAddress, spender); - const amountToTransfer = initOwnerBalance; - const initSpenderAllowance = initOwnerBalance; - let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); - await zeroEx.awaitTransactionMinedAsync(txHash); - txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer); - await zeroEx.awaitTransactionMinedAsync(txHash); - - const newOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const newSpenderBalance = await zeroEx.token.getBalanceAsync(zrxAddress, spender); - - expect(newOwnerBalance).to.be.bignumber.equal(0); - expect(newSpenderBalance).to.be.bignumber.equal(initSpenderBalance.plus(initOwnerBalance)); - }); - - it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => { - const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); - const amountToTransfer = initOwnerBalance; - const initSpenderAllowance = initOwnerBalance; - let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); - await zeroEx.awaitTransactionMinedAsync(txHash); - txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer); - await zeroEx.awaitTransactionMinedAsync(txHash); - - const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); - expect(newSpenderAllowance).to.be.bignumber.equal(0); - }); - }); -}); diff --git a/packages/contracts/test/ts/zrx_token.ts b/packages/contracts/test/ts/zrx_token.ts new file mode 100644 index 000000000..1c9655402 --- /dev/null +++ b/packages/contracts/test/ts/zrx_token.ts @@ -0,0 +1,170 @@ +import {ZeroEx} from '0x.js'; +import {BigNumber} from 'bignumber.js'; +import * as chai from 'chai'; +import Web3 = require('web3'); + +import {Artifacts} from '../../util/artifacts'; +import {constants} from '../../util/constants'; +import {ContractInstance} from '../../util/types'; + +import {chaiSetup} from './utils/chai_setup'; + +chaiSetup.configure(); +const expect = chai.expect; +const {Exchange, ZRXToken} = new Artifacts(artifacts); +const web3: Web3 = (global as any).web3; + +contract('ZRXToken', (accounts: string[]) => { + const owner = accounts[0]; + const spender = accounts[1]; + let zeroEx: ZeroEx; + + let MAX_UINT: BigNumber; + + let zrx: ContractInstance; + let zrxAddress: string; + + beforeEach(async () => { + zeroEx = new ZeroEx(web3.currentProvider, { + exchangeContractAddress: Exchange.address, + networkId: constants.TESTRPC_NETWORK_ID, + }); + zrxAddress = zeroEx.exchange.getZRXTokenAddress(); + zrx = await ZRXToken.at(zrxAddress); + MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; + }); + + describe('constants', () => { + it('should have 18 decimals', async () => { + const decimals = new BigNumber(await zrx.decimals.call()); + const expectedDecimals = 18; + expect(decimals).to.be.bignumber.equal(expectedDecimals); + }); + + it('should have a total supply of 1 billion tokens', async () => { + const totalSupply = new BigNumber(await zrx.totalSupply.call()); + const expectedTotalSupply = 1000000000; + expect(ZeroEx.toUnitAmount(totalSupply, 18)).to.be.bignumber.equal(expectedTotalSupply); + }); + + it('should be named 0x Protocol Token', async () => { + const name = await zrx.name.call(); + const expectedName = '0x Protocol Token'; + expect(name).to.be.equal(expectedName); + }); + + it('should have the symbol ZRX', async () => { + const symbol = await zrx.symbol.call(); + const expectedSymbol = 'ZRX'; + expect(symbol).to.be.equal(expectedSymbol); + }); + }); + + describe('constructor', () => { + it('should initialize owner balance to totalSupply', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const totalSupply = new BigNumber(await zrx.totalSupply.call()); + expect(totalSupply).to.be.bignumber.equal(ownerBalance); + }); + }); + + describe('transfer', () => { + it('should transfer balance from sender to receiver', async () => { + const receiver = spender; + const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const amountToTransfer = new BigNumber(1); + const txHash = await zeroEx.token.transferAsync(zrxAddress, owner, receiver, amountToTransfer); + await zeroEx.awaitTransactionMinedAsync(txHash); + const finalOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const finalReceiverBalance = await zeroEx.token.getBalanceAsync(zrxAddress, receiver); + + const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer); + const expectedFinalReceiverBalance = amountToTransfer; + expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance); + expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance); + }); + + it('should return true on a 0 value transfer', async () => { + const didReturnTrue = await zrx.transfer.call(spender, 0, {from: owner}); + expect(didReturnTrue).to.be.true(); + }); + }); + + describe('transferFrom', () => { + it('should return false if owner has insufficient balance', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const amountToTransfer = ownerBalance.plus(1); + let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer); + await zeroEx.awaitTransactionMinedAsync(txHash); + const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); + expect(didReturnTrue).to.be.false(); + // Reset allowance + txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, new BigNumber(0)); + await zeroEx.awaitTransactionMinedAsync(txHash); + }); + + it('should return false if spender has insufficient allowance', async () => { + const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const amountToTransfer = ownerBalance; + + const spenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); + const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; + expect(spenderAllowanceIsInsufficient).to.be.true(); + + const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); + expect(didReturnTrue).to.be.false(); + }); + + it('should return true on a 0 value transfer', async () => { + const amountToTransfer = 0; + const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); + expect(didReturnTrue).to.be.true(); + }); + + it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = MAX_UINT; + let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); + await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer); + await zeroEx.awaitTransactionMinedAsync(txHash); + + const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); + expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); + // Restore balance + txHash = await zeroEx.token.transferAsync(zrxAddress, spender, owner, amountToTransfer); + await zeroEx.awaitTransactionMinedAsync(txHash); + }); + + it('should transfer the correct balances if spender has sufficient allowance', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const initSpenderBalance = await zeroEx.token.getBalanceAsync(zrxAddress, spender); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = initOwnerBalance; + let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); + await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer); + await zeroEx.awaitTransactionMinedAsync(txHash); + + const newOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const newSpenderBalance = await zeroEx.token.getBalanceAsync(zrxAddress, spender); + + expect(newOwnerBalance).to.be.bignumber.equal(0); + expect(newSpenderBalance).to.be.bignumber.equal(initSpenderBalance.plus(initOwnerBalance)); + }); + + it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => { + const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); + const amountToTransfer = initOwnerBalance; + const initSpenderAllowance = initOwnerBalance; + let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); + await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer); + await zeroEx.awaitTransactionMinedAsync(txHash); + + const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); + expect(newSpenderAllowance).to.be.bignumber.equal(0); + }); + }); +}); -- cgit v1.2.3 From 1dda4d5f78705d96934a08f00000e9a98a3bbc3d Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 11 Dec 2017 13:29:59 -0800 Subject: Rename contracts lib to utils --- packages/contracts/contracts/Exchange.sol | 2 +- packages/contracts/contracts/TokenRegistry.sol | 2 +- .../contracts/contracts/TokenTransferProxy.sol | 2 +- packages/contracts/contracts/test/DummyToken.sol | 2 +- .../contracts/contracts/test/DummyToken_v2.sol | 2 +- packages/contracts/contracts/test/Mintable.sol | 2 +- packages/contracts/contracts/test/Mintable_v2.sol | 2 +- packages/contracts/contracts/tokens/EtherToken.sol | 2 +- .../contracts/contracts/tokens/EtherToken_v2.sol | 2 +- packages/contracts/contracts/utils/Ownable.sol | 27 ++++++++ packages/contracts/contracts/utils/Ownable_v2.sol | 32 ++++++++++ packages/contracts/contracts/utils/SafeMath.sol | 73 ++++++++++++++++++++++ packages/contracts/contracts/utils/SafeMath_v2.sol | 73 ++++++++++++++++++++++ 13 files changed, 214 insertions(+), 9 deletions(-) create mode 100644 packages/contracts/contracts/utils/Ownable.sol create mode 100644 packages/contracts/contracts/utils/Ownable_v2.sol create mode 100644 packages/contracts/contracts/utils/SafeMath.sol create mode 100644 packages/contracts/contracts/utils/SafeMath_v2.sol (limited to 'packages') diff --git a/packages/contracts/contracts/Exchange.sol b/packages/contracts/contracts/Exchange.sol index 2f734fb20..1da74deef 100644 --- a/packages/contracts/contracts/Exchange.sol +++ b/packages/contracts/contracts/Exchange.sol @@ -20,7 +20,7 @@ pragma solidity ^0.4.11; import "./TokenTransferProxy.sol"; import "./tokens/Token.sol"; -import "./lib/SafeMath.sol"; +import "./utils/SafeMath.sol"; /// @title Exchange - Facilitates exchange of ERC20 tokens. /// @author Amir Bandeali - , Will Warren - diff --git a/packages/contracts/contracts/TokenRegistry.sol b/packages/contracts/contracts/TokenRegistry.sol index c76eaea9d..891d923ee 100644 --- a/packages/contracts/contracts/TokenRegistry.sol +++ b/packages/contracts/contracts/TokenRegistry.sol @@ -18,7 +18,7 @@ pragma solidity ^0.4.11; -import "./lib/Ownable.sol"; +import "./utils/Ownable.sol"; /// @title Token Registry - Stores metadata associated with ERC20 tokens. See ERC22 https://github.com/ethereum/EIPs/issues/22 /// @author Amir Bandeali - , Will Warren - diff --git a/packages/contracts/contracts/TokenTransferProxy.sol b/packages/contracts/contracts/TokenTransferProxy.sol index 81ada804d..e92c37243 100644 --- a/packages/contracts/contracts/TokenTransferProxy.sol +++ b/packages/contracts/contracts/TokenTransferProxy.sol @@ -19,7 +19,7 @@ pragma solidity ^0.4.11; import "./tokens/Token.sol"; -import "./lib/Ownable.sol"; +import "./utils/Ownable.sol"; /// @title TokenTransferProxy - Transfers tokens on behalf of contracts that have been approved via decentralized governance. /// @author Amir Bandeali - , Will Warren - diff --git a/packages/contracts/contracts/test/DummyToken.sol b/packages/contracts/contracts/test/DummyToken.sol index cf8c27201..d71edf260 100644 --- a/packages/contracts/contracts/test/DummyToken.sol +++ b/packages/contracts/contracts/test/DummyToken.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.11; import "./Mintable.sol"; -import "./../lib/Ownable.sol"; +import "./../utils/Ownable.sol"; contract DummyToken is Mintable, Ownable { string public name; diff --git a/packages/contracts/contracts/test/DummyToken_v2.sol b/packages/contracts/contracts/test/DummyToken_v2.sol index e3392bf64..9b4808703 100644 --- a/packages/contracts/contracts/test/DummyToken_v2.sol +++ b/packages/contracts/contracts/test/DummyToken_v2.sol @@ -1,7 +1,7 @@ pragma solidity 0.4.18; import "./Mintable_v2.sol"; -import "./../lib/Ownable_v2.sol"; +import "./../utils/Ownable_v2.sol"; contract DummyToken_v2 is Mintable_v2, Ownable_v2 { string public name; diff --git a/packages/contracts/contracts/test/Mintable.sol b/packages/contracts/contracts/test/Mintable.sol index 34c9eb858..3c790534f 100644 --- a/packages/contracts/contracts/test/Mintable.sol +++ b/packages/contracts/contracts/test/Mintable.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.11; import "./../tokens/UnlimitedAllowanceToken.sol"; -import "./../lib/SafeMath.sol"; +import "./../utils/SafeMath.sol"; /* * Mintable diff --git a/packages/contracts/contracts/test/Mintable_v2.sol b/packages/contracts/contracts/test/Mintable_v2.sol index a2605791f..54085e029 100644 --- a/packages/contracts/contracts/test/Mintable_v2.sol +++ b/packages/contracts/contracts/test/Mintable_v2.sol @@ -1,7 +1,7 @@ pragma solidity 0.4.18; import "./../tokens/UnlimitedAllowanceToken_v2.sol"; -import "./../lib/SafeMath_v2.sol"; +import "./../utils/SafeMath_v2.sol"; /* * Mintable diff --git a/packages/contracts/contracts/tokens/EtherToken.sol b/packages/contracts/contracts/tokens/EtherToken.sol index daef97d8f..d7e51a8f3 100644 --- a/packages/contracts/contracts/tokens/EtherToken.sol +++ b/packages/contracts/contracts/tokens/EtherToken.sol @@ -19,7 +19,7 @@ pragma solidity ^0.4.11; import "./UnlimitedAllowanceToken.sol"; -import "./../lib/SafeMath.sol"; +import "./../utils/SafeMath.sol"; contract EtherToken is UnlimitedAllowanceToken, SafeMath { diff --git a/packages/contracts/contracts/tokens/EtherToken_v2.sol b/packages/contracts/contracts/tokens/EtherToken_v2.sol index a501013e4..1ed668909 100644 --- a/packages/contracts/contracts/tokens/EtherToken_v2.sol +++ b/packages/contracts/contracts/tokens/EtherToken_v2.sol @@ -19,7 +19,7 @@ pragma solidity 0.4.18; import "./UnlimitedAllowanceToken_v2.sol"; -import "./../lib/SafeMath_v2.sol"; +import "./../utils/SafeMath_v2.sol"; contract EtherToken_v2 is UnlimitedAllowanceToken_v2, SafeMath_v2 { diff --git a/packages/contracts/contracts/utils/Ownable.sol b/packages/contracts/contracts/utils/Ownable.sol new file mode 100644 index 000000000..5488896d7 --- /dev/null +++ b/packages/contracts/contracts/utils/Ownable.sol @@ -0,0 +1,27 @@ +pragma solidity ^0.4.11; + +/* + * Ownable + * + * Base contract with an owner. + * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner. + */ + +contract Ownable { + address public owner; + + function Ownable() { + owner = msg.sender; + } + + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + function transferOwnership(address newOwner) onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } +} diff --git a/packages/contracts/contracts/utils/Ownable_v2.sol b/packages/contracts/contracts/utils/Ownable_v2.sol new file mode 100644 index 000000000..8cdf5985f --- /dev/null +++ b/packages/contracts/contracts/utils/Ownable_v2.sol @@ -0,0 +1,32 @@ +pragma solidity 0.4.18; + +/* + * Ownable + * + * Base contract with an owner. + * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner. + */ + +contract Ownable_v2 { + address public owner; + + function Ownable_v2() + public + { + owner = msg.sender; + } + + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + function transferOwnership(address newOwner) + public + onlyOwner + { + if (newOwner != address(0)) { + owner = newOwner; + } + } +} diff --git a/packages/contracts/contracts/utils/SafeMath.sol b/packages/contracts/contracts/utils/SafeMath.sol new file mode 100644 index 000000000..cf8ac3265 --- /dev/null +++ b/packages/contracts/contracts/utils/SafeMath.sol @@ -0,0 +1,73 @@ +pragma solidity ^0.4.11; + +contract SafeMath { + function safeMul(uint a, uint b) + internal + constant + returns (uint256) + { + uint c = a * b; + assert(a == 0 || c / a == b); + return c; + } + + function safeDiv(uint a, uint b) + internal + constant + returns (uint256) + { + uint c = a / b; + return c; + } + + function safeSub(uint a, uint b) + internal + constant + returns (uint256) + { + assert(b <= a); + return a - b; + } + + function safeAdd(uint a, uint b) + internal + constant + returns (uint256) + { + uint c = a + b; + assert(c >= a); + return c; + } + + function max64(uint64 a, uint64 b) + internal + constant + returns (uint64) + { + return a >= b ? a : b; + } + + function min64(uint64 a, uint64 b) + internal + constant + returns (uint64) + { + return a < b ? a : b; + } + + function max256(uint256 a, uint256 b) + internal + constant + returns (uint256) + { + return a >= b ? a : b; + } + + function min256(uint256 a, uint256 b) + internal + constant + returns (uint256) + { + return a < b ? a : b; + } +} diff --git a/packages/contracts/contracts/utils/SafeMath_v2.sol b/packages/contracts/contracts/utils/SafeMath_v2.sol new file mode 100644 index 000000000..3a4bbb8fb --- /dev/null +++ b/packages/contracts/contracts/utils/SafeMath_v2.sol @@ -0,0 +1,73 @@ +pragma solidity 0.4.18; + +contract SafeMath_v2 { + function safeMul(uint a, uint b) + internal + pure + returns (uint256) + { + uint c = a * b; + assert(a == 0 || c / a == b); + return c; + } + + function safeDiv(uint a, uint b) + internal + pure + returns (uint256) + { + uint c = a / b; + return c; + } + + function safeSub(uint a, uint b) + internal + pure + returns (uint256) + { + assert(b <= a); + return a - b; + } + + function safeAdd(uint a, uint b) + internal + pure + returns (uint256) + { + uint c = a + b; + assert(c >= a); + return c; + } + + function max64(uint64 a, uint64 b) + internal + pure + returns (uint256) + { + return a >= b ? a : b; + } + + function min64(uint64 a, uint64 b) + internal + pure + returns (uint256) + { + return a < b ? a : b; + } + + function max256(uint256 a, uint256 b) + internal + pure + returns (uint256) + { + return a >= b ? a : b; + } + + function min256(uint256 a, uint256 b) + internal + pure + returns (uint256) + { + return a < b ? a : b; + } +} -- cgit v1.2.3 From b97f140b78a0420943291af57d122bc90a488112 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 11 Dec 2017 22:47:47 -0800 Subject: Add gas limits to failing tests --- packages/contracts/test/ts/ether_token.ts | 3 ++- packages/contracts/test/ts/ether_token_v2.ts | 6 ++++-- packages/contracts/test/ts/unlimited_allowance_token.ts | 9 ++++++--- .../contracts/test/ts/unlimited_allowance_token_v2.ts | 9 ++++++--- packages/contracts/test/ts/zrx_token.ts | 15 ++++++++++----- packages/contracts/util/constants.ts | 3 +++ 6 files changed, 31 insertions(+), 14 deletions(-) (limited to 'packages') diff --git a/packages/contracts/test/ts/ether_token.ts b/packages/contracts/test/ts/ether_token.ts index 79c618ec2..db281e511 100644 --- a/packages/contracts/test/ts/ether_token.ts +++ b/packages/contracts/test/ts/ether_token.ts @@ -81,7 +81,8 @@ contract('EtherToken', (accounts: string[]) => { const initEthBalance = await getEthBalanceAsync(account); const ethTokensToWithdraw = initEthTokenBalance; expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0); - const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account); + const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account, + {gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS}); const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); const ethSpentOnGas = gasPrice.times(receipt.gasUsed); diff --git a/packages/contracts/test/ts/ether_token_v2.ts b/packages/contracts/test/ts/ether_token_v2.ts index 4931eb798..174403445 100644 --- a/packages/contracts/test/ts/ether_token_v2.ts +++ b/packages/contracts/test/ts/ether_token_v2.ts @@ -104,7 +104,8 @@ contract('EtherTokenV2', (accounts: string[]) => { const initEthBalance = await getEthBalanceAsync(account); const ethTokensToWithdraw = initEthTokenBalance; expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0); - const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account); + const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account, + {gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS}); const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); const ethSpentOnGas = gasPrice.times(receipt.gasUsed); @@ -121,7 +122,8 @@ contract('EtherTokenV2', (accounts: string[]) => { const initEthBalance = await getEthBalanceAsync(account); const ethTokensToWithdraw = initEthTokenBalance; expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0); - const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account); + const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account, + {gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS}); const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); const logs = receipt.logs; diff --git a/packages/contracts/test/ts/unlimited_allowance_token.ts b/packages/contracts/test/ts/unlimited_allowance_token.ts index 3b4d2db77..a328563cd 100644 --- a/packages/contracts/test/ts/unlimited_allowance_token.ts +++ b/packages/contracts/test/ts/unlimited_allowance_token.ts @@ -85,7 +85,8 @@ contract('UnlimitedAllowanceToken', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, + {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); @@ -96,7 +97,8 @@ contract('UnlimitedAllowanceToken', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, + {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender); @@ -110,7 +112,8 @@ contract('UnlimitedAllowanceToken', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, + {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); expect(newSpenderAllowance).to.be.bignumber.equal(0); diff --git a/packages/contracts/test/ts/unlimited_allowance_token_v2.ts b/packages/contracts/test/ts/unlimited_allowance_token_v2.ts index 73e12f00c..137fcd8a5 100644 --- a/packages/contracts/test/ts/unlimited_allowance_token_v2.ts +++ b/packages/contracts/test/ts/unlimited_allowance_token_v2.ts @@ -92,7 +92,8 @@ contract('UnlimitedAllowanceTokenV2', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, + {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); @@ -103,7 +104,8 @@ contract('UnlimitedAllowanceTokenV2', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, + {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender); @@ -117,7 +119,8 @@ contract('UnlimitedAllowanceTokenV2', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, + {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); expect(newSpenderAllowance).to.be.bignumber.equal(0); diff --git a/packages/contracts/test/ts/zrx_token.ts b/packages/contracts/test/ts/zrx_token.ts index 1c9655402..6312056b2 100644 --- a/packages/contracts/test/ts/zrx_token.ts +++ b/packages/contracts/test/ts/zrx_token.ts @@ -94,12 +94,14 @@ contract('ZRXToken', (accounts: string[]) => { it('should return false if owner has insufficient balance', async () => { const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); const amountToTransfer = ownerBalance.plus(1); - let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer); + let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer, + {gasLimit: constants.MAX_TOKEN_APPROVE_GAS}); await zeroEx.awaitTransactionMinedAsync(txHash); const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender}); expect(didReturnTrue).to.be.false(); // Reset allowance - txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, new BigNumber(0)); + txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, new BigNumber(0), + {gasLimit: constants.MAX_TOKEN_APPROVE_GAS}); await zeroEx.awaitTransactionMinedAsync(txHash); }); @@ -127,7 +129,8 @@ contract('ZRXToken', (accounts: string[]) => { const initSpenderAllowance = MAX_UINT; let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); await zeroEx.awaitTransactionMinedAsync(txHash); - txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer); + txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer, + {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); await zeroEx.awaitTransactionMinedAsync(txHash); const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); @@ -144,7 +147,8 @@ contract('ZRXToken', (accounts: string[]) => { const initSpenderAllowance = initOwnerBalance; let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); await zeroEx.awaitTransactionMinedAsync(txHash); - txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer); + txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer, + {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); await zeroEx.awaitTransactionMinedAsync(txHash); const newOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner); @@ -160,7 +164,8 @@ contract('ZRXToken', (accounts: string[]) => { const initSpenderAllowance = initOwnerBalance; let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance); await zeroEx.awaitTransactionMinedAsync(txHash); - txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer); + txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer, + {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); await zeroEx.awaitTransactionMinedAsync(txHash); const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender); diff --git a/packages/contracts/util/constants.ts b/packages/contracts/util/constants.ts index c28a18e27..e61b2f802 100644 --- a/packages/contracts/util/constants.ts +++ b/packages/contracts/util/constants.ts @@ -3,4 +3,7 @@ export const constants = { INVALID_OPCODE: 'invalid opcode', REVERT: 'revert', TESTRPC_NETWORK_ID: 50, + MAX_ETHERTOKEN_WITHDRAW_GAS: 43000, + MAX_TOKEN_TRANSFERFROM_GAS: 80000, + MAX_TOKEN_APPROVE_GAS: 60000, }; -- cgit v1.2.3 From 145fea5253c3e4b11a79f5cefbf733d1297c205b Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 11 Dec 2017 23:01:39 -0800 Subject: Add test:circleci command, add newlines to end of contracts --- packages/contracts/contracts/Exchange.sol | 1 + packages/contracts/contracts/TokenRegistry.sol | 1 + packages/contracts/contracts/TokenTransferProxy.sol | 1 + packages/contracts/contracts/multisig/MultiSigWallet.sol | 1 + packages/contracts/contracts/multisig/MultiSigWalletWithTimeLock.sol | 1 + .../MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol | 1 + packages/contracts/contracts/test/DummyToken.sol | 1 + packages/contracts/contracts/test/DummyToken_v2.sol | 1 + packages/contracts/contracts/test/MaliciousToken.sol | 1 + packages/contracts/contracts/test/Mintable.sol | 1 + packages/contracts/contracts/test/Mintable_v2.sol | 1 + packages/contracts/contracts/tokens/ERC20Token.sol | 2 +- packages/contracts/contracts/tokens/EtherToken.sol | 1 + packages/contracts/contracts/tokens/EtherToken_v2.sol | 1 + packages/contracts/contracts/tokens/StandardToken.sol | 1 + packages/contracts/contracts/tokens/Token.sol | 2 +- packages/contracts/contracts/tokens/Token_v2.sol | 1 + packages/contracts/contracts/tokens/UnlimitedAllowanceToken.sol | 1 + packages/contracts/contracts/tokens/UnlimitedAllowanceToken_v2.sol | 1 + packages/contracts/contracts/tokens/ZRXToken.sol | 1 + packages/contracts/contracts/utils/Ownable.sol | 1 + packages/contracts/contracts/utils/Ownable_v2.sol | 1 + packages/contracts/contracts/utils/SafeMath.sol | 1 + packages/contracts/contracts/utils/SafeMath_v2.sol | 1 + packages/contracts/package.json | 1 + 25 files changed, 25 insertions(+), 2 deletions(-) (limited to 'packages') diff --git a/packages/contracts/contracts/Exchange.sol b/packages/contracts/contracts/Exchange.sol index 1da74deef..a402e7ca5 100644 --- a/packages/contracts/contracts/Exchange.sol +++ b/packages/contracts/contracts/Exchange.sol @@ -600,3 +600,4 @@ contract Exchange is SafeMath { return Token(token).allowance.gas(EXTERNAL_QUERY_GAS_LIMIT)(owner, TOKEN_TRANSFER_PROXY_CONTRACT); // Limit gas to prevent reentrancy } } + diff --git a/packages/contracts/contracts/TokenRegistry.sol b/packages/contracts/contracts/TokenRegistry.sol index 891d923ee..d2570e71d 100644 --- a/packages/contracts/contracts/TokenRegistry.sol +++ b/packages/contracts/contracts/TokenRegistry.sol @@ -306,3 +306,4 @@ contract TokenRegistry is Ownable { return tokenAddresses; } } + diff --git a/packages/contracts/contracts/TokenTransferProxy.sol b/packages/contracts/contracts/TokenTransferProxy.sol index e92c37243..fd2358496 100644 --- a/packages/contracts/contracts/TokenTransferProxy.sol +++ b/packages/contracts/contracts/TokenTransferProxy.sol @@ -113,3 +113,4 @@ contract TokenTransferProxy is Ownable { return authorities; } } + diff --git a/packages/contracts/contracts/multisig/MultiSigWallet.sol b/packages/contracts/contracts/multisig/MultiSigWallet.sol index 68f70fe83..ae7ef06fd 100644 --- a/packages/contracts/contracts/multisig/MultiSigWallet.sol +++ b/packages/contracts/contracts/multisig/MultiSigWallet.sol @@ -363,3 +363,4 @@ contract MultiSigWallet { _transactionIds[i - from] = transactionIdsTemp[i]; } } + diff --git a/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLock.sol b/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLock.sol index ed625f7f7..62273eba3 100644 --- a/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLock.sol +++ b/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLock.sol @@ -130,3 +130,4 @@ contract MultiSigWalletWithTimeLock is MultiSigWallet { ConfirmationTimeSet(transactionId, confirmationTime); } } + diff --git a/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol b/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol index 5c1620808..07beb9f5b 100644 --- a/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol +++ b/packages/contracts/contracts/multisig/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.sol @@ -80,3 +80,4 @@ contract MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress is MultiSigWall return true; } } + diff --git a/packages/contracts/contracts/test/DummyToken.sol b/packages/contracts/contracts/test/DummyToken.sol index d71edf260..046af3059 100644 --- a/packages/contracts/contracts/test/DummyToken.sol +++ b/packages/contracts/contracts/test/DummyToken.sol @@ -33,3 +33,4 @@ contract DummyToken is Mintable, Ownable { balances[_target] = _value; } } + diff --git a/packages/contracts/contracts/test/DummyToken_v2.sol b/packages/contracts/contracts/test/DummyToken_v2.sol index 9b4808703..bd4d06be9 100644 --- a/packages/contracts/contracts/test/DummyToken_v2.sol +++ b/packages/contracts/contracts/test/DummyToken_v2.sol @@ -35,3 +35,4 @@ contract DummyToken_v2 is Mintable_v2, Ownable_v2 { balances[_target] = _value; } } + diff --git a/packages/contracts/contracts/test/MaliciousToken.sol b/packages/contracts/contracts/test/MaliciousToken.sol index 9e1322984..3e7d5d1a5 100644 --- a/packages/contracts/contracts/test/MaliciousToken.sol +++ b/packages/contracts/contracts/test/MaliciousToken.sol @@ -29,3 +29,4 @@ contract MaliciousToken is StandardToken { return allowed[_owner][_spender]; } } + diff --git a/packages/contracts/contracts/test/Mintable.sol b/packages/contracts/contracts/test/Mintable.sol index 3c790534f..3b91415ef 100644 --- a/packages/contracts/contracts/test/Mintable.sol +++ b/packages/contracts/contracts/test/Mintable.sol @@ -16,3 +16,4 @@ contract Mintable is UnlimitedAllowanceToken, SafeMath { totalSupply = safeAdd(totalSupply, _value); } } + diff --git a/packages/contracts/contracts/test/Mintable_v2.sol b/packages/contracts/contracts/test/Mintable_v2.sol index 54085e029..829145cfb 100644 --- a/packages/contracts/contracts/test/Mintable_v2.sol +++ b/packages/contracts/contracts/test/Mintable_v2.sol @@ -16,3 +16,4 @@ contract Mintable_v2 is UnlimitedAllowanceToken_v2, SafeMath_v2 { totalSupply = safeAdd(totalSupply, _value); } } + diff --git a/packages/contracts/contracts/tokens/ERC20Token.sol b/packages/contracts/contracts/tokens/ERC20Token.sol index 5ec81032f..aead59d6d 100644 --- a/packages/contracts/contracts/tokens/ERC20Token.sol +++ b/packages/contracts/contracts/tokens/ERC20Token.sol @@ -55,4 +55,4 @@ contract ERC20Token is Token_v2 { mapping (address => uint) balances; mapping (address => mapping (address => uint)) allowed; uint public totalSupply; -} \ No newline at end of file +} diff --git a/packages/contracts/contracts/tokens/EtherToken.sol b/packages/contracts/contracts/tokens/EtherToken.sol index d7e51a8f3..2eae012fc 100644 --- a/packages/contracts/contracts/tokens/EtherToken.sol +++ b/packages/contracts/contracts/tokens/EtherToken.sol @@ -54,3 +54,4 @@ contract EtherToken is UnlimitedAllowanceToken, SafeMath { require(msg.sender.send(amount)); } } + diff --git a/packages/contracts/contracts/tokens/EtherToken_v2.sol b/packages/contracts/contracts/tokens/EtherToken_v2.sol index 1ed668909..28ccf1306 100644 --- a/packages/contracts/contracts/tokens/EtherToken_v2.sol +++ b/packages/contracts/contracts/tokens/EtherToken_v2.sol @@ -56,3 +56,4 @@ contract EtherToken_v2 is UnlimitedAllowanceToken_v2, SafeMath_v2 { Transfer(msg.sender, address(0), _value); } } + diff --git a/packages/contracts/contracts/tokens/StandardToken.sol b/packages/contracts/contracts/tokens/StandardToken.sol index 0e5c33a3a..9cd53d94a 100644 --- a/packages/contracts/contracts/tokens/StandardToken.sol +++ b/packages/contracts/contracts/tokens/StandardToken.sol @@ -42,3 +42,4 @@ contract StandardToken is Token { mapping (address => mapping (address => uint)) allowed; uint public totalSupply; } + diff --git a/packages/contracts/contracts/tokens/Token.sol b/packages/contracts/contracts/tokens/Token.sol index 10c6c41c1..f18614498 100644 --- a/packages/contracts/contracts/tokens/Token.sol +++ b/packages/contracts/contracts/tokens/Token.sol @@ -35,4 +35,4 @@ contract Token { event Transfer(address indexed _from, address indexed _to, uint _value); event Approval(address indexed _owner, address indexed _spender, uint _value); -} \ No newline at end of file +} diff --git a/packages/contracts/contracts/tokens/Token_v2.sol b/packages/contracts/contracts/tokens/Token_v2.sol index bd46dec2b..027f706f4 100644 --- a/packages/contracts/contracts/tokens/Token_v2.sol +++ b/packages/contracts/contracts/tokens/Token_v2.sol @@ -36,3 +36,4 @@ contract Token_v2 { event Transfer(address indexed _from, address indexed _to, uint _value); event Approval(address indexed _owner, address indexed _spender, uint _value); } + diff --git a/packages/contracts/contracts/tokens/UnlimitedAllowanceToken.sol b/packages/contracts/contracts/tokens/UnlimitedAllowanceToken.sol index 035993990..0994cfae4 100644 --- a/packages/contracts/contracts/tokens/UnlimitedAllowanceToken.sol +++ b/packages/contracts/contracts/tokens/UnlimitedAllowanceToken.sol @@ -50,3 +50,4 @@ contract UnlimitedAllowanceToken is StandardToken { } } } + diff --git a/packages/contracts/contracts/tokens/UnlimitedAllowanceToken_v2.sol b/packages/contracts/contracts/tokens/UnlimitedAllowanceToken_v2.sol index 2da54fee2..b2caab8af 100644 --- a/packages/contracts/contracts/tokens/UnlimitedAllowanceToken_v2.sol +++ b/packages/contracts/contracts/tokens/UnlimitedAllowanceToken_v2.sol @@ -44,3 +44,4 @@ contract UnlimitedAllowanceToken_v2 is ERC20Token { return true; } } + diff --git a/packages/contracts/contracts/tokens/ZRXToken.sol b/packages/contracts/contracts/tokens/ZRXToken.sol index 9456d1649..af1dfac99 100644 --- a/packages/contracts/contracts/tokens/ZRXToken.sol +++ b/packages/contracts/contracts/tokens/ZRXToken.sol @@ -31,3 +31,4 @@ contract ZRXToken is UnlimitedAllowanceToken { balances[msg.sender] = totalSupply; } } + diff --git a/packages/contracts/contracts/utils/Ownable.sol b/packages/contracts/contracts/utils/Ownable.sol index 5488896d7..77fdaf085 100644 --- a/packages/contracts/contracts/utils/Ownable.sol +++ b/packages/contracts/contracts/utils/Ownable.sol @@ -25,3 +25,4 @@ contract Ownable { } } } + diff --git a/packages/contracts/contracts/utils/Ownable_v2.sol b/packages/contracts/contracts/utils/Ownable_v2.sol index 8cdf5985f..77e1fed08 100644 --- a/packages/contracts/contracts/utils/Ownable_v2.sol +++ b/packages/contracts/contracts/utils/Ownable_v2.sol @@ -30,3 +30,4 @@ contract Ownable_v2 { } } } + diff --git a/packages/contracts/contracts/utils/SafeMath.sol b/packages/contracts/contracts/utils/SafeMath.sol index cf8ac3265..a7891a7af 100644 --- a/packages/contracts/contracts/utils/SafeMath.sol +++ b/packages/contracts/contracts/utils/SafeMath.sol @@ -71,3 +71,4 @@ contract SafeMath { return a < b ? a : b; } } + diff --git a/packages/contracts/contracts/utils/SafeMath_v2.sol b/packages/contracts/contracts/utils/SafeMath_v2.sol index 3a4bbb8fb..6eda03999 100644 --- a/packages/contracts/contracts/utils/SafeMath_v2.sol +++ b/packages/contracts/contracts/utils/SafeMath_v2.sol @@ -71,3 +71,4 @@ contract SafeMath_v2 { return a < b ? a : b; } } + diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 31c69e8d5..f4d0b5865 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -15,6 +15,7 @@ "migrate:truffle": "npm run build; truffle migrate", "migrate": "npm run build; node lib/deploy/cli.js migrate", "lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'", + "test:circleci": "yarn test; yarn test:deployer", "test:deployer": "npm run build; mocha lib/deploy/test/*_test.js" }, "repository": { -- cgit v1.2.3 From cf50a82ecc2eb9175294a6446fc084a45e25bddb Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 11 Dec 2017 23:12:23 -0800 Subject: fix tests after merging with development --- packages/contracts/test/ts/ether_token_v2.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'packages') diff --git a/packages/contracts/test/ts/ether_token_v2.ts b/packages/contracts/test/ts/ether_token_v2.ts index 174403445..61bf1a980 100644 --- a/packages/contracts/test/ts/ether_token_v2.ts +++ b/packages/contracts/test/ts/ether_token_v2.ts @@ -1,7 +1,7 @@ import {ZeroEx, ZeroExError} from '0x.js'; +import {promisify} from '@0xproject/utils'; import {BigNumber} from 'bignumber.js'; import * as chai from 'chai'; -import promisify = require('es6-promisify'); import Web3 = require('web3'); import {Artifacts} from '../../util/artifacts'; @@ -33,9 +33,9 @@ contract('EtherTokenV2', (accounts: string[]) => { }); }); - const sendTransactionAsync = promisify(web3.eth.sendTransaction); + const sendTransactionAsync = promisify(web3.eth.sendTransaction); const getEthBalanceAsync = async (owner: string) => { - const balanceStr = await promisify(web3.eth.getBalance)(owner); + const balanceStr = await promisify(web3.eth.getBalance)(owner); const balance = new BigNumber(balanceStr); return balance; }; -- cgit v1.2.3 From 88db8c37242f899d00f1195a368d58a914d499cb Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 12 Dec 2017 09:34:46 -0800 Subject: Add missing package in utils, fix linting error --- packages/subproviders/package.json | 1 + 1 file changed, 1 insertion(+) (limited to 'packages') diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index b0c5686a6..8a222457d 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -31,6 +31,7 @@ }, "devDependencies": { "@0xproject/tslint-config": "^0.2.1", + "@0xproject/utils": "^0.1.0", "@types/lodash": "^4.14.86", "@types/mocha": "^2.2.42", "@types/node": "^8.0.53", -- cgit v1.2.3 From 1fb643cb69fba85434ada35755f90dbc1d9ee85f Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 12 Dec 2017 13:08:59 -0800 Subject: Formatting fixes --- packages/contracts/contracts/tokens/ERC20Token.sol | 1 + packages/contracts/contracts/tokens/Token.sol | 1 + packages/contracts/test/ts/ether_token.ts | 5 +++-- packages/contracts/test/ts/ether_token_v2.ts | 10 ++++++---- packages/contracts/test/ts/unlimited_allowance_token.ts | 15 +++++++++------ .../contracts/test/ts/unlimited_allowance_token_v2.ts | 15 +++++++++------ 6 files changed, 29 insertions(+), 18 deletions(-) (limited to 'packages') diff --git a/packages/contracts/contracts/tokens/ERC20Token.sol b/packages/contracts/contracts/tokens/ERC20Token.sol index aead59d6d..318da8c01 100644 --- a/packages/contracts/contracts/tokens/ERC20Token.sol +++ b/packages/contracts/contracts/tokens/ERC20Token.sol @@ -56,3 +56,4 @@ contract ERC20Token is Token_v2 { mapping (address => mapping (address => uint)) allowed; uint public totalSupply; } + diff --git a/packages/contracts/contracts/tokens/Token.sol b/packages/contracts/contracts/tokens/Token.sol index f18614498..507de9b12 100644 --- a/packages/contracts/contracts/tokens/Token.sol +++ b/packages/contracts/contracts/tokens/Token.sol @@ -36,3 +36,4 @@ contract Token { event Transfer(address indexed _from, address indexed _to, uint _value); event Approval(address indexed _owner, address indexed _spender, uint _value); } + diff --git a/packages/contracts/test/ts/ether_token.ts b/packages/contracts/test/ts/ether_token.ts index db281e511..2f9df59a4 100644 --- a/packages/contracts/test/ts/ether_token.ts +++ b/packages/contracts/test/ts/ether_token.ts @@ -81,8 +81,9 @@ contract('EtherToken', (accounts: string[]) => { const initEthBalance = await getEthBalanceAsync(account); const ethTokensToWithdraw = initEthTokenBalance; expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0); - const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account, - {gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS}); + const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account, { + gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS, + }); const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); const ethSpentOnGas = gasPrice.times(receipt.gasUsed); diff --git a/packages/contracts/test/ts/ether_token_v2.ts b/packages/contracts/test/ts/ether_token_v2.ts index 61bf1a980..b88fef579 100644 --- a/packages/contracts/test/ts/ether_token_v2.ts +++ b/packages/contracts/test/ts/ether_token_v2.ts @@ -104,8 +104,9 @@ contract('EtherTokenV2', (accounts: string[]) => { const initEthBalance = await getEthBalanceAsync(account); const ethTokensToWithdraw = initEthTokenBalance; expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0); - const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account, - {gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS}); + const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account, { + gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS, + }); const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); const ethSpentOnGas = gasPrice.times(receipt.gasUsed); @@ -122,8 +123,9 @@ contract('EtherTokenV2', (accounts: string[]) => { const initEthBalance = await getEthBalanceAsync(account); const ethTokensToWithdraw = initEthTokenBalance; expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0); - const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account, - {gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS}); + const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account, { + gasLimit: constants.MAX_ETHERTOKEN_WITHDRAW_GAS, + }); const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); const logs = receipt.logs; diff --git a/packages/contracts/test/ts/unlimited_allowance_token.ts b/packages/contracts/test/ts/unlimited_allowance_token.ts index a328563cd..33b2a5721 100644 --- a/packages/contracts/test/ts/unlimited_allowance_token.ts +++ b/packages/contracts/test/ts/unlimited_allowance_token.ts @@ -85,8 +85,9 @@ contract('UnlimitedAllowanceToken', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, - {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { + gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, + }); const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); @@ -97,8 +98,9 @@ contract('UnlimitedAllowanceToken', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, - {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { + gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, + }); const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender); @@ -112,8 +114,9 @@ contract('UnlimitedAllowanceToken', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, - {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { + gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, + }); const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); expect(newSpenderAllowance).to.be.bignumber.equal(0); diff --git a/packages/contracts/test/ts/unlimited_allowance_token_v2.ts b/packages/contracts/test/ts/unlimited_allowance_token_v2.ts index 137fcd8a5..4fa06e483 100644 --- a/packages/contracts/test/ts/unlimited_allowance_token_v2.ts +++ b/packages/contracts/test/ts/unlimited_allowance_token_v2.ts @@ -92,8 +92,9 @@ contract('UnlimitedAllowanceTokenV2', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, - {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { + gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, + }); const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance); @@ -104,8 +105,9 @@ contract('UnlimitedAllowanceTokenV2', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, - {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { + gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, + }); const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender); @@ -119,8 +121,9 @@ contract('UnlimitedAllowanceTokenV2', (accounts: string[]) => { const amountToTransfer = initOwnerBalance; const initSpenderAllowance = initOwnerBalance; await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance); - await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, - {gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS}); + await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer, { + gasLimit: constants.MAX_TOKEN_TRANSFERFROM_GAS, + }); const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender); expect(newSpenderAllowance).to.be.bignumber.equal(0); -- cgit v1.2.3 From ff422ecfb22597d81f6eea29c67f8d3261ba959d Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 12 Dec 2017 13:57:35 -0800 Subject: Add version string to EtherToken_v2 --- packages/contracts/contracts/tokens/EtherToken_v2.sol | 1 + 1 file changed, 1 insertion(+) (limited to 'packages') diff --git a/packages/contracts/contracts/tokens/EtherToken_v2.sol b/packages/contracts/contracts/tokens/EtherToken_v2.sol index 28ccf1306..f172c8e35 100644 --- a/packages/contracts/contracts/tokens/EtherToken_v2.sol +++ b/packages/contracts/contracts/tokens/EtherToken_v2.sol @@ -25,6 +25,7 @@ contract EtherToken_v2 is UnlimitedAllowanceToken_v2, SafeMath_v2 { string constant public name = "Ether Token"; string constant public symbol = "WETH"; + string constant public version = "2.0.0"; // version 1.0.0 deployed on mainnet at 0x2956356cd2a2bf3202f771f50d3d14a367b48070 uint8 constant public decimals = 18; /// @dev Fallback to calling deposit when ether is sent directly to contract. -- cgit v1.2.3 From 987637abed4a74a3e851c54e93c0164607a5ab6f Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 12 Dec 2017 15:11:57 -0800 Subject: Increase timeout on deployer tests --- packages/contracts/deploy/test/util/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages') diff --git a/packages/contracts/deploy/test/util/constants.ts b/packages/contracts/deploy/test/util/constants.ts index a2de44b63..65525a1f7 100644 --- a/packages/contracts/deploy/test/util/constants.ts +++ b/packages/contracts/deploy/test/util/constants.ts @@ -5,7 +5,7 @@ export const constants = { jsonrpcPort: 8545, optimizerEnabled: 0, gasPrice: new BigNumber(20000000000), - timeoutMs: 12000, + timeoutMs: 20000, zrxTokenAddress: '0xe41d2489571d322189246dafa5ebde1f4699f498', tokenTransferProxyAddress: '0x8da0d80f5007ef1e431dd2127178d224e32c2ef4', }; -- cgit v1.2.3