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