aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/src
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2018-09-28 19:08:12 +0800
committerFabio Berger <me@fabioberger.com>2018-09-28 19:08:12 +0800
commitba7de7204d29d4004c347190be7a3b8c84951b82 (patch)
tree9dddbd1ded45484a6cb968cdf799bf5ce991477b /packages/contracts/src
parentf3ad64aa1c2930affbfd074316b5f407580b7523 (diff)
parenta737cfa004ee1dc18be935f61fb9c289ed5623fd (diff)
downloaddexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar.gz
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar.bz2
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar.lz
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar.xz
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar.zst
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.zip
merge development
Diffstat (limited to 'packages/contracts/src')
-rw-r--r--packages/contracts/src/2.0.0/extensions/Forwarder/Forwarder.sol1
-rw-r--r--packages/contracts/src/2.0.0/extensions/Forwarder/MixinAssets.sol1
-rw-r--r--packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol3
-rw-r--r--packages/contracts/src/2.0.0/extensions/Forwarder/MixinForwarderCore.sol11
-rw-r--r--packages/contracts/src/2.0.0/extensions/Forwarder/MixinWeth.sol1
-rw-r--r--packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MAssets.sol1
-rw-r--r--packages/contracts/src/2.0.0/extensions/OrderValidator/OrderValidator.sol4
-rw-r--r--packages/contracts/src/2.0.0/multisig/MultiSigWallet.sol90
-rw-r--r--packages/contracts/src/2.0.0/multisig/MultiSigWalletWithTimeLock.sol99
-rw-r--r--packages/contracts/src/2.0.0/protocol/AssetProxy/ERC20Proxy.sol68
-rw-r--r--packages/contracts/src/2.0.0/protocol/AssetProxy/ERC721Proxy.sol3
-rw-r--r--packages/contracts/src/2.0.0/protocol/AssetProxy/MixinAuthorizable.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/AssetProxy/interfaces/IAssetProxy.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/AssetProxy/interfaces/IAuthorizable.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/AssetProxy/mixins/MAuthorizable.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol61
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/Exchange.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol5
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol57
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinMatchOrders.sol16
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol4
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol10
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol6
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/libs/LibFillResults.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol94
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/mixins/MAssetProxyDispatcher.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/mixins/MExchangeCore.sol5
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/mixins/MMatchOrders.sol1
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/mixins/MTransactions.sol22
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/mixins/MWrapperFunctions.sol5
-rw-r--r--packages/contracts/src/2.0.0/test/DummyERC20Token/DummyMultipleReturnERC20Token.sol69
-rw-r--r--packages/contracts/src/2.0.0/test/DummyERC20Token/DummyNoReturnERC20Token.sol1
-rw-r--r--packages/contracts/src/2.0.0/test/DummyERC721Receiver/DummyERC721Receiver.sol1
-rw-r--r--packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol8
-rw-r--r--packages/contracts/src/2.0.0/test/TestAssetProxyOwner/TestAssetProxyOwner.sol24
-rw-r--r--packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol36
-rw-r--r--packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol1
-rw-r--r--packages/contracts/src/2.0.0/test/TestSignatureValidator/TestSignatureValidator.sol1
-rw-r--r--packages/contracts/src/2.0.0/tokens/ERC20Token/ERC20Token.sol1
-rw-r--r--packages/contracts/src/2.0.0/tokens/ERC20Token/MintableERC20Token.sol1
-rw-r--r--packages/contracts/src/2.0.0/tokens/ERC20Token/UnlimitedAllowanceERC20Token.sol1
-rw-r--r--packages/contracts/src/2.0.0/tokens/ERC721Token/MintableERC721Token.sol1
-rw-r--r--packages/contracts/src/2.0.0/tokens/ZRXToken/ZRXToken.sol6
-rw-r--r--packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol13
-rw-r--r--packages/contracts/src/2.0.0/utils/Ownable/IOwnable.sol7
-rw-r--r--packages/contracts/src/2.0.0/utils/Ownable/Ownable.sol11
-rw-r--r--packages/contracts/src/2.0.0/utils/ReentrancyGuard/ReentrancyGuard.sol1
-rw-r--r--packages/contracts/src/2.0.0/utils/SafeMath/SafeMath.sol1
50 files changed, 501 insertions, 260 deletions
diff --git a/packages/contracts/src/2.0.0/extensions/Forwarder/Forwarder.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/Forwarder.sol
index 6b17bb29b..94dec40ed 100644
--- a/packages/contracts/src/2.0.0/extensions/Forwarder/Forwarder.sol
+++ b/packages/contracts/src/2.0.0/extensions/Forwarder/Forwarder.sol
@@ -34,7 +34,6 @@ contract Forwarder is
MixinExchangeWrapper,
MixinForwarderCore
{
-
constructor (
address _exchange,
bytes memory _zrxAssetData,
diff --git a/packages/contracts/src/2.0.0/extensions/Forwarder/MixinAssets.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinAssets.sol
index d6a38aa6e..43efb5ff3 100644
--- a/packages/contracts/src/2.0.0/extensions/Forwarder/MixinAssets.sol
+++ b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinAssets.sol
@@ -31,7 +31,6 @@ contract MixinAssets is
LibConstants,
MAssets
{
-
using LibBytes for bytes;
bytes4 constant internal ERC20_TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)"));
diff --git a/packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol
index 9e816716c..fea9a53c2 100644
--- a/packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol
+++ b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol
@@ -34,7 +34,6 @@ contract MixinExchangeWrapper is
LibConstants,
MExchangeWrapper
{
-
/// @dev Fills the input order.
/// Returns false if the transaction would otherwise revert.
/// @param order Order struct containing order specifications.
@@ -61,7 +60,7 @@ contract MixinExchangeWrapper is
// Call `fillOrder` and handle any exceptions gracefully
assembly {
let success := call(
- gas, // forward all gas, TODO: look into gas consumption of assert/throw
+ gas, // forward all gas
exchange, // call address of Exchange contract
0, // transfer 0 wei
add(fillOrderCalldata, 32), // pointer to start of input (skip array length in first 32 bytes)
diff --git a/packages/contracts/src/2.0.0/extensions/Forwarder/MixinForwarderCore.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinForwarderCore.sol
index 14f191879..54487f726 100644
--- a/packages/contracts/src/2.0.0/extensions/Forwarder/MixinForwarderCore.sol
+++ b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinForwarderCore.sol
@@ -39,7 +39,6 @@ contract MixinForwarderCore is
MExchangeWrapper,
IForwarderCore
{
-
using LibBytes for bytes;
/// @dev Constructor approves ERC20 proxy to transfer ZRX and WETH on this contract's behalf.
@@ -47,10 +46,12 @@ contract MixinForwarderCore is
public
{
address proxyAddress = EXCHANGE.getAssetProxy(ERC20_DATA_ID);
- if (proxyAddress != address(0)) {
- ETHER_TOKEN.approve(proxyAddress, MAX_UINT);
- ZRX_TOKEN.approve(proxyAddress, MAX_UINT);
- }
+ require(
+ proxyAddress != address(0),
+ "UNREGISTERED_ASSET_PROXY"
+ );
+ ETHER_TOKEN.approve(proxyAddress, MAX_UINT);
+ ZRX_TOKEN.approve(proxyAddress, MAX_UINT);
}
/// @dev Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value.
diff --git a/packages/contracts/src/2.0.0/extensions/Forwarder/MixinWeth.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinWeth.sol
index 5863b522d..d2814a49b 100644
--- a/packages/contracts/src/2.0.0/extensions/Forwarder/MixinWeth.sol
+++ b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinWeth.sol
@@ -28,7 +28,6 @@ contract MixinWeth is
LibConstants,
MWeth
{
-
/// @dev Default payabale function, this allows us to withdraw WETH
function ()
public
diff --git a/packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MAssets.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MAssets.sol
index 83636432a..9e7f80d97 100644
--- a/packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MAssets.sol
+++ b/packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MAssets.sol
@@ -24,7 +24,6 @@ import "../interfaces/IAssets.sol";
contract MAssets is
IAssets
{
-
/// @dev Transfers given amount of asset to sender.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param amount Amount of asset to transfer to sender.
diff --git a/packages/contracts/src/2.0.0/extensions/OrderValidator/OrderValidator.sol b/packages/contracts/src/2.0.0/extensions/OrderValidator/OrderValidator.sol
index a18345245..8bfde3847 100644
--- a/packages/contracts/src/2.0.0/extensions/OrderValidator/OrderValidator.sol
+++ b/packages/contracts/src/2.0.0/extensions/OrderValidator/OrderValidator.sol
@@ -28,11 +28,11 @@ import "../../utils/LibBytes/LibBytes.sol";
contract OrderValidator {
+ using LibBytes for bytes;
+
bytes4 constant internal ERC20_DATA_ID = bytes4(keccak256("ERC20Token(address)"));
bytes4 constant internal ERC721_DATA_ID = bytes4(keccak256("ERC721Token(address,uint256)"));
- using LibBytes for bytes;
-
struct TraderInfo {
uint256 makerBalance; // Maker's balance of makerAsset
uint256 makerAllowance; // Maker's allowance to corresponding AssetProxy
diff --git a/packages/contracts/src/2.0.0/multisig/MultiSigWallet.sol b/packages/contracts/src/2.0.0/multisig/MultiSigWallet.sol
index eb54fe047..516e7391c 100644
--- a/packages/contracts/src/2.0.0/multisig/MultiSigWallet.sol
+++ b/packages/contracts/src/2.0.0/multisig/MultiSigWallet.sol
@@ -1,13 +1,14 @@
// solhint-disable
-pragma solidity ^0.4.10;
+pragma solidity ^0.4.15;
/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution.
/// @author Stefan George - <stefan.george@consensys.net>
contract MultiSigWallet {
- uint constant public MAX_OWNER_COUNT = 50;
-
+ /*
+ * Events
+ */
event Confirmation(address indexed sender, uint indexed transactionId);
event Revocation(address indexed sender, uint indexed transactionId);
event Submission(uint indexed transactionId);
@@ -18,6 +19,14 @@ contract MultiSigWallet {
event OwnerRemoval(address indexed owner);
event RequirementChange(uint required);
+ /*
+ * Constants
+ */
+ uint constant public MAX_OWNER_COUNT = 50;
+
+ /*
+ * Storage
+ */
mapping (uint => Transaction) public transactions;
mapping (uint => mapping (address => bool)) public confirmations;
mapping (address => bool) public isOwner;
@@ -32,60 +41,54 @@ contract MultiSigWallet {
bool executed;
}
+ /*
+ * Modifiers
+ */
modifier onlyWallet() {
- if (msg.sender != address(this))
- throw;
+ require(msg.sender == address(this));
_;
}
modifier ownerDoesNotExist(address owner) {
- if (isOwner[owner])
- throw;
+ require(!isOwner[owner]);
_;
}
modifier ownerExists(address owner) {
- if (!isOwner[owner])
- throw;
+ require(isOwner[owner]);
_;
}
modifier transactionExists(uint transactionId) {
- if (transactions[transactionId].destination == 0)
- throw;
+ require(transactions[transactionId].destination != 0);
_;
}
modifier confirmed(uint transactionId, address owner) {
- if (!confirmations[transactionId][owner])
- throw;
+ require(confirmations[transactionId][owner]);
_;
}
modifier notConfirmed(uint transactionId, address owner) {
- if (confirmations[transactionId][owner])
- throw;
+ require(!confirmations[transactionId][owner]);
_;
}
modifier notExecuted(uint transactionId) {
- if (transactions[transactionId].executed)
- throw;
+ require(!transactions[transactionId].executed);
_;
}
modifier notNull(address _address) {
- if (_address == 0)
- throw;
+ require(_address != 0);
_;
}
modifier validRequirement(uint ownerCount, uint _required) {
- if ( ownerCount > MAX_OWNER_COUNT
- || _required > ownerCount
- || _required == 0
- || ownerCount == 0)
- throw;
+ require(ownerCount <= MAX_OWNER_COUNT
+ && _required <= ownerCount
+ && _required != 0
+ && ownerCount != 0);
_;
}
@@ -108,8 +111,7 @@ contract MultiSigWallet {
validRequirement(_owners.length, _required)
{
for (uint i=0; i<_owners.length; i++) {
- if (isOwner[_owners[i]] || _owners[i] == 0)
- throw;
+ require(!isOwner[_owners[i]] && _owners[i] != 0);
isOwner[_owners[i]] = true;
}
owners = _owners;
@@ -151,7 +153,7 @@ contract MultiSigWallet {
/// @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.
+ /// @param newOwner Address of new owner.
function replaceOwner(address owner, address newOwner)
public
onlyWallet
@@ -222,20 +224,44 @@ contract MultiSigWallet {
/// @param transactionId Transaction ID.
function executeTransaction(uint transactionId)
public
+ ownerExists(msg.sender)
+ confirmed(transactionId, msg.sender)
notExecuted(transactionId)
{
if (isConfirmed(transactionId)) {
- Transaction tx = transactions[transactionId];
- tx.executed = true;
- if (tx.destination.call.value(tx.value)(tx.data))
+ Transaction storage txn = transactions[transactionId];
+ txn.executed = true;
+ if (external_call(txn.destination, txn.value, txn.data.length, txn.data))
Execution(transactionId);
else {
ExecutionFailure(transactionId);
- tx.executed = false;
+ txn.executed = false;
}
}
}
+ // call has been separated into its own function in order to take advantage
+ // of the Solidity's code generator to produce a loop that copies tx.data into memory.
+ function external_call(address destination, uint value, uint dataLength, bytes data) internal returns (bool) {
+ bool result;
+ assembly {
+ let x := mload(0x40) // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention)
+ let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that
+ result := call(
+ sub(gas, 34710), // 34710 is the value that solidity is currently emitting
+ // It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +
+ // callNewAccountGas (25000, in case the destination address does not exist and needs creating)
+ destination,
+ value,
+ d,
+ dataLength, // Size of the input (in bytes) - this is what fixes the padding problem
+ x,
+ 0 // Output is ignored, therefore the output size is zero
+ )
+ }
+ return result;
+ }
+
/// @dev Returns the confirmation status of a transaction.
/// @param transactionId Transaction ID.
/// @return Confirmation status.
@@ -364,4 +390,4 @@ contract MultiSigWallet {
for (i=from; i<to; i++)
_transactionIds[i - from] = transactionIdsTemp[i];
}
-}
+} \ No newline at end of file
diff --git a/packages/contracts/src/2.0.0/multisig/MultiSigWalletWithTimeLock.sol b/packages/contracts/src/2.0.0/multisig/MultiSigWalletWithTimeLock.sol
index 8c5e6e1e6..9513d3b30 100644
--- a/packages/contracts/src/2.0.0/multisig/MultiSigWalletWithTimeLock.sol
+++ b/packages/contracts/src/2.0.0/multisig/MultiSigWalletWithTimeLock.sol
@@ -16,47 +16,57 @@
*/
-// solhint-disable
-pragma solidity ^0.4.10;
+pragma solidity 0.4.24;
import "./MultiSigWallet.sol";
/// @title Multisignature wallet with time lock- Allows multiple parties to execute a transaction after a time lock has passed.
/// @author Amir Bandeali - <amir@0xProject.com>
-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));
+// solhint-disable not-rely-on-time
+contract MultiSigWalletWithTimeLock is
+ MultiSigWallet
+{
+ event ConfirmationTimeSet(uint256 indexed transactionId, uint256 confirmationTime);
+ event TimeLockChange(uint256 secondsTimeLocked);
+
+ uint256 public secondsTimeLocked;
+
+ mapping (uint256 => uint256) public confirmationTimes;
+
+ modifier notFullyConfirmed(uint256 transactionId) {
+ require(
+ !isConfirmed(transactionId),
+ "TX_FULLY_CONFIRMED"
+ );
_;
}
- modifier fullyConfirmed(uint transactionId) {
- require(isConfirmed(transactionId));
+ modifier fullyConfirmed(uint256 transactionId) {
+ require(
+ isConfirmed(transactionId),
+ "TX_NOT_FULLY_CONFIRMED"
+ );
_;
}
- modifier pastTimeLock(uint transactionId) {
- require(block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked);
+ modifier pastTimeLock(uint256 transactionId) {
+ require(
+ block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked,
+ "TIME_LOCK_INCOMPLETE"
+ );
_;
}
- /*
- * 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)
+ constructor (
+ address[] _owners,
+ uint256 _required,
+ uint256 _secondsTimeLocked
+ )
public
MultiSigWallet(_owners, _required)
{
@@ -65,17 +75,17 @@ contract MultiSigWalletWithTimeLock is MultiSigWallet {
/// @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)
+ function changeTimeLock(uint256 _secondsTimeLocked)
public
onlyWallet
{
secondsTimeLocked = _secondsTimeLocked;
- TimeLockChange(_secondsTimeLocked);
+ emit TimeLockChange(_secondsTimeLocked);
}
/// @dev Allows an owner to confirm a transaction.
/// @param transactionId Transaction ID.
- function confirmTransaction(uint transactionId)
+ function confirmTransaction(uint256 transactionId)
public
ownerExists(msg.sender)
transactionExists(transactionId)
@@ -83,52 +93,35 @@ contract MultiSigWalletWithTimeLock is MultiSigWallet {
notFullyConfirmed(transactionId)
{
confirmations[transactionId][msg.sender] = true;
- Confirmation(msg.sender, transactionId);
+ emit 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)
+ function executeTransaction(uint256 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;
+ Transaction storage txn = transactions[transactionId];
+ txn.executed = true;
+ if (external_call(txn.destination, txn.value, txn.data.length, txn.data)) {
+ emit Execution(transactionId);
+ } else {
+ emit ExecutionFailure(transactionId);
+ txn.executed = false;
}
}
- /*
- * Internal functions
- */
-
/// @dev Sets the time of when a submission first passed.
- function setConfirmationTime(uint transactionId, uint confirmationTime)
+ function setConfirmationTime(uint256 transactionId, uint256 confirmationTime)
internal
{
confirmationTimes[transactionId] = confirmationTime;
- ConfirmationTimeSet(transactionId, confirmationTime);
+ emit ConfirmationTimeSet(transactionId, confirmationTime);
}
}
diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC20Proxy.sol
index 004c3892d..258443bca 100644
--- a/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC20Proxy.sol
+++ b/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC20Proxy.sol
@@ -18,7 +18,6 @@
pragma solidity 0.4.24;
-import "../../utils/LibBytes/LibBytes.sol";
import "./MixinAuthorizable.sol";
@@ -59,15 +58,64 @@ contract ERC20Proxy is
mstore(96, 0)
revert(0, 100)
}
-
- /////// Token contract address ///////
- // The token address is found as follows:
- // * It is stored at offset 4 in `assetData` contents.
- // * This is stored at offset 32 from `assetData`.
- // * The offset to `assetData` from Params is stored at offset
- // 4 in calldata.
- // * The offset of Params in calldata is 4.
- // So we read location 4 and add 32 + 4 + 4 to it.
+
+ // `transferFrom`.
+ // The function is marked `external`, so no abi decodeding is done for
+ // us. Instead, we expect the `calldata` memory to contain the
+ // following:
+ //
+ // | Area | Offset | Length | Contents |
+ // |----------|--------|---------|-------------------------------------|
+ // | Header | 0 | 4 | function selector |
+ // | Params | | 4 * 32 | function parameters: |
+ // | | 4 | | 1. offset to assetData (*) |
+ // | | 36 | | 2. from |
+ // | | 68 | | 3. to |
+ // | | 100 | | 4. amount |
+ // | Data | | | assetData: |
+ // | | 132 | 32 | assetData Length |
+ // | | 164 | ** | assetData Contents |
+ //
+ // (*): offset is computed from start of function parameters, so offset
+ // by an additional 4 bytes in the calldata.
+ //
+ // (**): see table below to compute length of assetData Contents
+ //
+ // WARNING: The ABIv2 specification allows additional padding between
+ // the Params and Data section. This will result in a larger
+ // offset to assetData.
+
+ // Asset data itself is encoded as follows:
+ //
+ // | Area | Offset | Length | Contents |
+ // |----------|--------|---------|-------------------------------------|
+ // | Header | 0 | 4 | function selector |
+ // | Params | | 1 * 32 | function parameters: |
+ // | | 4 | 12 + 20 | 1. token address |
+
+ // We construct calldata for the `token.transferFrom` ABI.
+ // The layout of this calldata is in the table below.
+ //
+ // | Area | Offset | Length | Contents |
+ // |----------|--------|---------|-------------------------------------|
+ // | Header | 0 | 4 | function selector |
+ // | Params | | 3 * 32 | function parameters: |
+ // | | 4 | | 1. from |
+ // | | 36 | | 2. to |
+ // | | 68 | | 3. amount |
+
+ /////// Read token address from calldata ///////
+ // * The token address is stored in `assetData`.
+ //
+ // * The "offset to assetData" is stored at offset 4 in the calldata (table 1).
+ // [assetDataOffsetFromParams = calldataload(4)]
+ //
+ // * Notes that the "offset to assetData" is relative to the "Params" area of calldata;
+ // add 4 bytes to account for the length of the "Header" area (table 1).
+ // [assetDataOffsetFromHeader = assetDataOffsetFromParams + 4]
+ //
+ // * The "token address" is offset 32+4=36 bytes into "assetData" (tables 1 & 2).
+ // [tokenOffset = assetDataOffsetFromHeader + 36 = calldataload(4) + 4 + 36]
let token := calldataload(add(calldataload(4), 40))
/////// Setup Header Area ///////
diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC721Proxy.sol
index 9d0bc0f74..65b664b8b 100644
--- a/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC721Proxy.sol
+++ b/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC721Proxy.sol
@@ -18,7 +18,6 @@
pragma solidity 0.4.24;
-import "../../utils/LibBytes/LibBytes.sol";
import "./MixinAuthorizable.sol";
@@ -80,6 +79,8 @@ contract ERC721Proxy is
// (*): offset is computed from start of function parameters, so offset
// by an additional 4 bytes in the calldata.
//
+ // (**): see table below to compute length of assetData Contents
+ //
// WARNING: The ABIv2 specification allows additional padding between
// the Params and Data section. This will result in a larger
// offset to assetData.
diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxy/MixinAuthorizable.sol b/packages/contracts/src/2.0.0/protocol/AssetProxy/MixinAuthorizable.sol
index ff4660a31..fe9bbf848 100644
--- a/packages/contracts/src/2.0.0/protocol/AssetProxy/MixinAuthorizable.sol
+++ b/packages/contracts/src/2.0.0/protocol/AssetProxy/MixinAuthorizable.sol
@@ -26,7 +26,6 @@ contract MixinAuthorizable is
Ownable,
MAuthorizable
{
-
/// @dev Only authorized addresses can invoke functions with this modifier.
modifier onlyAuthorized {
require(
diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxy/interfaces/IAssetProxy.sol b/packages/contracts/src/2.0.0/protocol/AssetProxy/interfaces/IAssetProxy.sol
index 3651dd694..b25d2d75a 100644
--- a/packages/contracts/src/2.0.0/protocol/AssetProxy/interfaces/IAssetProxy.sol
+++ b/packages/contracts/src/2.0.0/protocol/AssetProxy/interfaces/IAssetProxy.sol
@@ -24,7 +24,6 @@ import "./IAuthorizable.sol";
contract IAssetProxy is
IAuthorizable
{
-
/// @dev Transfers assets. Either succeeds or throws.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param from Address to transfer asset from.
diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxy/interfaces/IAuthorizable.sol b/packages/contracts/src/2.0.0/protocol/AssetProxy/interfaces/IAuthorizable.sol
index 8fac43a47..ba1d4aa77 100644
--- a/packages/contracts/src/2.0.0/protocol/AssetProxy/interfaces/IAuthorizable.sol
+++ b/packages/contracts/src/2.0.0/protocol/AssetProxy/interfaces/IAuthorizable.sol
@@ -24,7 +24,6 @@ import "../../../utils/Ownable/IOwnable.sol";
contract IAuthorizable is
IOwnable
{
-
/// @dev Authorizes an address.
/// @param target Address to authorize.
function addAuthorizedAddress(address target)
diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxy/mixins/MAuthorizable.sol b/packages/contracts/src/2.0.0/protocol/AssetProxy/mixins/MAuthorizable.sol
index 8afc8c8d8..d63fb7f6d 100644
--- a/packages/contracts/src/2.0.0/protocol/AssetProxy/mixins/MAuthorizable.sol
+++ b/packages/contracts/src/2.0.0/protocol/AssetProxy/mixins/MAuthorizable.sol
@@ -24,7 +24,6 @@ import "../interfaces/IAuthorizable.sol";
contract MAuthorizable is
IAuthorizable
{
-
// Event logged when a new address is authorized.
event AuthorizedAddressAdded(
address indexed target,
diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol b/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol
index 8b7333646..edb788fab 100644
--- a/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol
+++ b/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol
@@ -16,14 +16,16 @@
*/
-pragma solidity 0.4.10;
+pragma solidity 0.4.24;
import "../../multisig/MultiSigWalletWithTimeLock.sol";
+import "../../utils/LibBytes/LibBytes.sol";
contract AssetProxyOwner is
MultiSigWalletWithTimeLock
{
+ using LibBytes for bytes;
event AssetProxyRegistration(address assetProxyContract, bool isRegistered);
@@ -36,9 +38,15 @@ contract AssetProxyOwner is
/// @dev Function will revert if the transaction does not call `removeAuthorizedAddressAtIndex`
/// on an approved AssetProxy contract.
modifier validRemoveAuthorizedAddressAtIndexTx(uint256 transactionId) {
- Transaction storage tx = transactions[transactionId];
- require(isAssetProxyRegistered[tx.destination]);
- require(readBytes4(tx.data, 0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR);
+ Transaction storage txn = transactions[transactionId];
+ require(
+ isAssetProxyRegistered[txn.destination],
+ "UNREGISTERED_ASSET_PROXY"
+ );
+ require(
+ txn.data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR,
+ "INVALID_FUNCTION_SELECTOR"
+ );
_;
}
@@ -48,7 +56,7 @@ contract AssetProxyOwner is
/// @param _assetProxyContracts Array of AssetProxy contract addresses.
/// @param _required Number of required confirmations.
/// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds.
- function AssetProxyOwner(
+ constructor (
address[] memory _owners,
address[] memory _assetProxyContracts,
uint256 _required,
@@ -59,7 +67,10 @@ contract AssetProxyOwner is
{
for (uint256 i = 0; i < _assetProxyContracts.length; i++) {
address assetProxy = _assetProxyContracts[i];
- require(assetProxy != address(0));
+ require(
+ assetProxy != address(0),
+ "INVALID_ASSET_PROXY"
+ );
isAssetProxyRegistered[assetProxy] = true;
}
}
@@ -74,7 +85,7 @@ contract AssetProxyOwner is
notNull(assetProxyContract)
{
isAssetProxyRegistered[assetProxyContract] = isRegistered;
- AssetProxyRegistration(assetProxyContract, isRegistered);
+ emit AssetProxyRegistration(assetProxyContract, isRegistered);
}
/// @dev Allows execution of `removeAuthorizedAddressAtIndex` without time lock.
@@ -85,35 +96,13 @@ contract AssetProxyOwner is
fullyConfirmed(transactionId)
validRemoveAuthorizedAddressAtIndexTx(transactionId)
{
- Transaction storage tx = transactions[transactionId];
- tx.executed = true;
- // solhint-disable-next-line avoid-call-value
- if (tx.destination.call.value(tx.value)(tx.data))
- Execution(transactionId);
- else {
- ExecutionFailure(transactionId);
- tx.executed = false;
+ Transaction storage txn = transactions[transactionId];
+ txn.executed = true;
+ if (external_call(txn.destination, txn.value, txn.data.length, txn.data)) {
+ emit Execution(transactionId);
+ } else {
+ emit ExecutionFailure(transactionId);
+ txn.executed = false;
}
}
-
- /// @dev Reads an unpadded bytes4 value from a position in a byte array.
- /// @param b Byte array containing a bytes4 value.
- /// @param index Index in byte array of bytes4 value.
- /// @return bytes4 value from byte array.
- function readBytes4(
- bytes memory b,
- uint256 index
- )
- internal
- returns (bytes4 result)
- {
- require(b.length >= index + 4);
- assembly {
- result := mload(add(b, 32))
- // Solidity does not require us to clean the trailing bytes.
- // We do it anyway
- result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
- }
- return result;
- }
}
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/Exchange.sol b/packages/contracts/src/2.0.0/protocol/Exchange/Exchange.sol
index 7507d3da1..ead36009f 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/Exchange.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/Exchange.sol
@@ -37,7 +37,6 @@ contract Exchange is
MixinAssetProxyDispatcher,
MixinWrapperFunctions
{
-
string constant public VERSION = "2.0.1-alpha";
// Mixins are instantiated in the order they are inherited
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol
index 80475e6e3..87b09b6b3 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol
@@ -19,7 +19,6 @@
pragma solidity 0.4.24;
import "../../utils/Ownable/Ownable.sol";
-import "../../utils/LibBytes/LibBytes.sol";
import "./mixins/MAssetProxyDispatcher.sol";
import "../AssetProxy/interfaces/IAssetProxy.sol";
@@ -28,8 +27,6 @@ contract MixinAssetProxyDispatcher is
Ownable,
MAssetProxyDispatcher
{
- using LibBytes for bytes;
-
// Mapping from Asset Proxy Id's to their respective Asset Proxy
mapping (bytes4 => IAssetProxy) public assetProxies;
@@ -90,7 +87,7 @@ contract MixinAssetProxyDispatcher is
"LENGTH_GREATER_THAN_3_REQUIRED"
);
- // Lookup assetProxy
+ // Lookup assetProxy. We do not use `LibBytes.readBytes4` for gas efficiency reasons.
bytes4 assetProxyId;
assembly {
assetProxyId := and(mload(
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol
index be163ec97..736dcd0b1 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol
@@ -75,7 +75,11 @@ contract MixinExchangeCore is
// Update orderEpoch
orderEpoch[makerAddress][senderAddress] = newOrderEpoch;
- emit CancelUpTo(makerAddress, senderAddress, newOrderEpoch);
+ emit CancelUpTo(
+ makerAddress,
+ senderAddress,
+ newOrderEpoch
+ );
}
/// @dev Fills the input order.
@@ -107,14 +111,7 @@ contract MixinExchangeCore is
public
nonReentrant
{
- // Fetch current order status
- OrderInfo memory orderInfo = getOrderInfo(order);
-
- // Validate context
- assertValidCancel(order, orderInfo);
-
- // Perform cancel
- updateCancelledState(order, orderInfo.orderHash);
+ cancelOrderInternal(order);
}
/// @dev Gets information about an order: status, hash, and amount filled.
@@ -231,11 +228,31 @@ contract MixinExchangeCore is
);
// Settle order
- settleOrder(order, takerAddress, fillResults);
+ settleOrder(
+ order,
+ takerAddress,
+ fillResults
+ );
return fillResults;
}
+ /// @dev After calling, the order can not be filled anymore.
+ /// Throws if order is invalid or sender does not have permission to cancel.
+ /// @param order Order to cancel. Order must be OrderStatus.FILLABLE.
+ function cancelOrderInternal(Order memory order)
+ internal
+ {
+ // Fetch current order status
+ OrderInfo memory orderInfo = getOrderInfo(order);
+
+ // Validate context
+ assertValidCancel(order, orderInfo);
+
+ // Perform cancel
+ updateCancelledState(order, orderInfo.orderHash);
+ }
+
/// @dev Updates state with results of a fill order.
/// @param order that was filled.
/// @param takerAddress Address of taker who filled the order.
@@ -404,16 +421,6 @@ contract MixinExchangeCore is
safeMul(order.makerAssetAmount, takerAssetFilledAmount),
"INVALID_FILL_PRICE"
);
-
- // Validate fill order rounding
- require(
- !isRoundingErrorFloor(
- takerAssetFilledAmount,
- order.takerAssetAmount,
- order.makerAssetAmount
- ),
- "ROUNDING_ERROR"
- );
}
/// @dev Validates context for cancelOrder. Succeeds or throws.
@@ -463,17 +470,17 @@ contract MixinExchangeCore is
{
// Compute proportional transfer amounts
fillResults.takerAssetFilledAmount = takerAssetFilledAmount;
- fillResults.makerAssetFilledAmount = getPartialAmountFloor(
+ fillResults.makerAssetFilledAmount = safeGetPartialAmountFloor(
takerAssetFilledAmount,
order.takerAssetAmount,
order.makerAssetAmount
);
- fillResults.makerFeePaid = getPartialAmountFloor(
- takerAssetFilledAmount,
- order.takerAssetAmount,
+ fillResults.makerFeePaid = safeGetPartialAmountFloor(
+ fillResults.makerAssetFilledAmount,
+ order.makerAssetAmount,
order.makerFee
);
- fillResults.takerFeePaid = getPartialAmountFloor(
+ fillResults.takerFeePaid = safeGetPartialAmountFloor(
takerAssetFilledAmount,
order.takerAssetAmount,
order.takerFee
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinMatchOrders.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinMatchOrders.sol
index 075a610b5..b4f6bdb26 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinMatchOrders.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinMatchOrders.sol
@@ -177,13 +177,13 @@ contract MixinMatchOrders is
{
// Derive maker asset amounts for left & right orders, given store taker assert amounts
uint256 leftTakerAssetAmountRemaining = safeSub(leftOrder.takerAssetAmount, leftOrderTakerAssetFilledAmount);
- uint256 leftMakerAssetAmountRemaining = getPartialAmountFloor(
+ uint256 leftMakerAssetAmountRemaining = safeGetPartialAmountFloor(
leftOrder.makerAssetAmount,
leftOrder.takerAssetAmount,
leftTakerAssetAmountRemaining
);
uint256 rightTakerAssetAmountRemaining = safeSub(rightOrder.takerAssetAmount, rightOrderTakerAssetFilledAmount);
- uint256 rightMakerAssetAmountRemaining = getPartialAmountFloor(
+ uint256 rightMakerAssetAmountRemaining = safeGetPartialAmountFloor(
rightOrder.makerAssetAmount,
rightOrder.takerAssetAmount,
rightTakerAssetAmountRemaining
@@ -205,7 +205,7 @@ contract MixinMatchOrders is
matchedFillResults.left.takerAssetFilledAmount = matchedFillResults.right.makerAssetFilledAmount;
// Round down to ensure the maker's exchange rate does not exceed the price specified by the order.
// We favor the maker when the exchange rate must be rounded.
- matchedFillResults.left.makerAssetFilledAmount = getPartialAmountFloor(
+ matchedFillResults.left.makerAssetFilledAmount = safeGetPartialAmountFloor(
leftOrder.makerAssetAmount,
leftOrder.takerAssetAmount,
matchedFillResults.left.takerAssetFilledAmount
@@ -217,7 +217,7 @@ contract MixinMatchOrders is
matchedFillResults.right.makerAssetFilledAmount = matchedFillResults.left.takerAssetFilledAmount;
// Round up to ensure the maker's exchange rate does not exceed the price specified by the order.
// We favor the maker when the exchange rate must be rounded.
- matchedFillResults.right.takerAssetFilledAmount = getPartialAmountCeil(
+ matchedFillResults.right.takerAssetFilledAmount = safeGetPartialAmountCeil(
rightOrder.takerAssetAmount,
rightOrder.makerAssetAmount,
matchedFillResults.right.makerAssetFilledAmount
@@ -231,24 +231,24 @@ contract MixinMatchOrders is
);
// Compute fees for left order
- matchedFillResults.left.makerFeePaid = getPartialAmountFloor(
+ matchedFillResults.left.makerFeePaid = safeGetPartialAmountFloor(
matchedFillResults.left.makerAssetFilledAmount,
leftOrder.makerAssetAmount,
leftOrder.makerFee
);
- matchedFillResults.left.takerFeePaid = getPartialAmountFloor(
+ matchedFillResults.left.takerFeePaid = safeGetPartialAmountFloor(
matchedFillResults.left.takerAssetFilledAmount,
leftOrder.takerAssetAmount,
leftOrder.takerFee
);
// Compute fees for right order
- matchedFillResults.right.makerFeePaid = getPartialAmountFloor(
+ matchedFillResults.right.makerFeePaid = safeGetPartialAmountFloor(
matchedFillResults.right.makerAssetFilledAmount,
rightOrder.makerAssetAmount,
rightOrder.makerFee
);
- matchedFillResults.right.takerFeePaid = getPartialAmountFloor(
+ matchedFillResults.right.takerFeePaid = safeGetPartialAmountFloor(
matchedFillResults.right.takerAssetFilledAmount,
rightOrder.takerAssetAmount,
rightOrder.takerFee
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol
index 4eb6a2fa6..176e28351 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol
@@ -251,7 +251,7 @@ contract MixinSignatureValidator is
walletAddress, // address of Wallet contract
cdStart, // pointer to start of input
mload(calldata), // length of input
- cdStart, // write input over output
+ cdStart, // write output over input
32 // output size is 32 bytes
)
@@ -301,7 +301,7 @@ contract MixinSignatureValidator is
validatorAddress, // address of Validator contract
cdStart, // pointer to start of input
mload(calldata), // length of input
- cdStart, // write input over output
+ cdStart, // write output over input
32 // output size is 32 bytes
)
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol
index 4a59b6c0f..3a76ca202 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol
@@ -28,7 +28,6 @@ contract MixinTransactions is
MSignatureValidator,
MTransactions
{
-
// Mapping of transaction hash => executed
// This prevents transactions from being executed more than once.
mapping (bytes32 => bool) public transactions;
@@ -36,15 +35,6 @@ contract MixinTransactions is
// Address of current transaction signer
address public currentContextAddress;
- // Hash for the EIP712 ZeroEx Transaction Schema
- bytes32 constant internal EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = keccak256(abi.encodePacked(
- "ZeroExTransaction(",
- "uint256 salt,",
- "address signerAddress,",
- "bytes data",
- ")"
- ));
-
/// @dev Executes an exchange method call in the context of signer.
/// @param salt Arbitrary number to ensure uniqueness of transaction hash.
/// @param signerAddress Address of transaction signer.
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol
index a5459a21e..cddff0e5f 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol
@@ -36,7 +36,6 @@ contract MixinWrapperFunctions is
MExchangeCore,
MWrapperFunctions
{
-
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
/// @param order Order struct containing order specifications.
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
@@ -82,7 +81,7 @@ contract MixinWrapperFunctions is
// Delegate to `fillOrder` and handle any exceptions gracefully
assembly {
let success := delegatecall(
- gas, // forward all gas, TODO: look into gas consumption of assert/throw
+ gas, // forward all gas
address, // call address of this contract
add(fillOrderCalldata, 32), // pointer to start of input (skip array length in first 32 bytes)
mload(fillOrderCalldata), // length of input
@@ -377,10 +376,11 @@ contract MixinWrapperFunctions is
/// @param orders Array of order specifications.
function batchCancelOrders(LibOrder.Order[] memory orders)
public
+ nonReentrant
{
uint256 ordersLength = orders.length;
for (uint256 i = 0; i != ordersLength; i++) {
- cancelOrder(orders[i]);
+ cancelOrderInternal(orders[i]);
}
}
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol
index b02f7632e..203edc1fd 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol
@@ -20,6 +20,7 @@ pragma solidity 0.4.24;
contract LibEIP712 {
+
// EIP191 header for EIP712 prefix
string constant internal EIP191_HEADER = "\x19\x01";
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibFillResults.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibFillResults.sol
index 1b4181d94..659ae9a69 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibFillResults.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibFillResults.sol
@@ -24,7 +24,6 @@ import "../../../utils/SafeMath/SafeMath.sol";
contract LibFillResults is
SafeMath
{
-
struct FillResults {
uint256 makerAssetFilledAmount; // Total amount of makerAsset(s) filled.
uint256 takerAssetFilledAmount; // Total amount of takerAsset(s) filled.
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol
index 0e0fba5d2..c0b85ea10 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol
@@ -24,6 +24,83 @@ import "../../../utils/SafeMath/SafeMath.sol";
contract LibMath is
SafeMath
{
+ /// @dev Calculates partial value given a numerator and denominator rounded down.
+ /// Reverts if rounding error is >= 0.1%
+ /// @param numerator Numerator.
+ /// @param denominator Denominator.
+ /// @param target Value to calculate partial of.
+ /// @return Partial value of target rounded down.
+ function safeGetPartialAmountFloor(
+ uint256 numerator,
+ uint256 denominator,
+ uint256 target
+ )
+ internal
+ pure
+ returns (uint256 partialAmount)
+ {
+ require(
+ denominator > 0,
+ "DIVISION_BY_ZERO"
+ );
+
+ require(
+ !isRoundingErrorFloor(
+ numerator,
+ denominator,
+ target
+ ),
+ "ROUNDING_ERROR"
+ );
+
+ partialAmount = safeDiv(
+ safeMul(numerator, target),
+ denominator
+ );
+ return partialAmount;
+ }
+
+ /// @dev Calculates partial value given a numerator and denominator rounded down.
+ /// Reverts if rounding error is >= 0.1%
+ /// @param numerator Numerator.
+ /// @param denominator Denominator.
+ /// @param target Value to calculate partial of.
+ /// @return Partial value of target rounded up.
+ function safeGetPartialAmountCeil(
+ uint256 numerator,
+ uint256 denominator,
+ uint256 target
+ )
+ internal
+ pure
+ returns (uint256 partialAmount)
+ {
+ require(
+ denominator > 0,
+ "DIVISION_BY_ZERO"
+ );
+
+ require(
+ !isRoundingErrorCeil(
+ numerator,
+ denominator,
+ target
+ ),
+ "ROUNDING_ERROR"
+ );
+
+ // safeDiv computes `floor(a / b)`. We use the identity (a, b integer):
+ // ceil(a / b) = floor((a + b - 1) / b)
+ // To implement `ceil(a / b)` using safeDiv.
+ partialAmount = safeDiv(
+ safeAdd(
+ safeMul(numerator, target),
+ safeSub(denominator, 1)
+ ),
+ denominator
+ );
+ return partialAmount;
+ }
/// @dev Calculates partial value given a numerator and denominator rounded down.
/// @param numerator Numerator.
@@ -43,7 +120,7 @@ contract LibMath is
denominator > 0,
"DIVISION_BY_ZERO"
);
-
+
partialAmount = safeDiv(
safeMul(numerator, target),
denominator
@@ -69,7 +146,7 @@ contract LibMath is
denominator > 0,
"DIVISION_BY_ZERO"
);
-
+
// safeDiv computes `floor(a / b)`. We use the identity (a, b integer):
// ceil(a / b) = floor((a + b - 1) / b)
// To implement `ceil(a / b)` using safeDiv.
@@ -128,7 +205,11 @@ contract LibMath is
// 1000 * remainder < numerator * target
// so we have a rounding error iff:
// 1000 * remainder >= numerator * target
- uint256 remainder = mulmod(target, numerator, denominator);
+ uint256 remainder = mulmod(
+ target,
+ numerator,
+ denominator
+ );
isError = safeMul(1000, remainder) >= safeMul(numerator, target);
return isError;
}
@@ -160,8 +241,11 @@ contract LibMath is
return false;
}
// Compute remainder as before
- uint256 remainder = mulmod(target, numerator, denominator);
- // TODO: safeMod
+ uint256 remainder = mulmod(
+ target,
+ numerator,
+ denominator
+ );
remainder = safeSub(denominator, remainder) % denominator;
isError = safeMul(1000, remainder) >= safeMul(numerator, target);
return isError;
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol
index 68f4f5f1b..0fe7c2161 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol
@@ -24,7 +24,6 @@ import "./LibEIP712.sol";
contract LibOrder is
LibEIP712
{
-
// Hash for the EIP712 Order Schema
bytes32 constant internal EIP712_ORDER_SCHEMA_HASH = keccak256(abi.encodePacked(
"Order(",
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MAssetProxyDispatcher.sol b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
index c6904300a..0ddfca270 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
@@ -24,7 +24,6 @@ import "../interfaces/IAssetProxyDispatcher.sol";
contract MAssetProxyDispatcher is
IAssetProxyDispatcher
{
-
// Logs registration of new asset proxy
event AssetProxyRegistered(
bytes4 id, // Id of new registered AssetProxy.
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MExchangeCore.sol
index d85913e0f..742499568 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MExchangeCore.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MExchangeCore.sol
@@ -72,6 +72,11 @@ contract MExchangeCore is
internal
returns (LibFillResults.FillResults memory fillResults);
+ /// @dev After calling, the order can not be filled anymore.
+ /// @param order Order struct containing order specifications.
+ function cancelOrderInternal(LibOrder.Order memory order)
+ internal;
+
/// @dev Updates state with results of a fill order.
/// @param order that was filled.
/// @param takerAddress Address of taker who filled the order.
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MMatchOrders.sol b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MMatchOrders.sol
index a31ec1585..96fa34bc0 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MMatchOrders.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MMatchOrders.sol
@@ -26,7 +26,6 @@ import "../interfaces/IMatchOrders.sol";
contract MMatchOrders is
IMatchOrders
{
-
/// @dev Validates context for matchOrders. Succeeds or throws.
/// @param leftOrder First order to match.
/// @param rightOrder Second order to match.
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MTransactions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MTransactions.sol
index f2b5e4b16..4f61a4945 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MTransactions.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MTransactions.sol
@@ -23,6 +23,28 @@ import "../interfaces/ITransactions.sol";
contract MTransactions is
ITransactions
{
+ // Hash for the EIP712 ZeroEx Transaction Schema
+ bytes32 constant internal EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = keccak256(abi.encodePacked(
+ "ZeroExTransaction(",
+ "uint256 salt,",
+ "address signerAddress,",
+ "bytes data",
+ ")"
+ ));
+
+ /// @dev Calculates EIP712 hash of the Transaction.
+ /// @param salt Arbitrary number to ensure uniqueness of transaction hash.
+ /// @param signerAddress Address of transaction signer.
+ /// @param data AbiV2 encoded calldata.
+ /// @return EIP712 hash of the Transaction.
+ function hashZeroExTransaction(
+ uint256 salt,
+ address signerAddress,
+ bytes memory data
+ )
+ internal
+ pure
+ returns (bytes32 result);
/// @dev The current function will be called in the context of this address (either 0x transaction signer or `msg.sender`).
/// If calling a fill function, this address will represent the taker.
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MWrapperFunctions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MWrapperFunctions.sol
index e04d4a429..4adfbde01 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MWrapperFunctions.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MWrapperFunctions.sol
@@ -24,8 +24,9 @@ import "../libs/LibFillResults.sol";
import "../interfaces/IWrapperFunctions.sol";
-contract MWrapperFunctions {
-
+contract MWrapperFunctions is
+ IWrapperFunctions
+{
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
/// @param order LibOrder.Order struct containing order specifications.
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
diff --git a/packages/contracts/src/2.0.0/test/DummyERC20Token/DummyMultipleReturnERC20Token.sol b/packages/contracts/src/2.0.0/test/DummyERC20Token/DummyMultipleReturnERC20Token.sol
new file mode 100644
index 000000000..733d4437e
--- /dev/null
+++ b/packages/contracts/src/2.0.0/test/DummyERC20Token/DummyMultipleReturnERC20Token.sol
@@ -0,0 +1,69 @@
+/*
+
+ Copyright 2018 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.24;
+
+import "./DummyERC20Token.sol";
+
+
+// solhint-disable no-empty-blocks
+contract DummyMultipleReturnERC20Token is
+ DummyERC20Token
+{
+ constructor (
+ string _name,
+ string _symbol,
+ uint256 _decimals,
+ uint256 _totalSupply
+ )
+ public
+ DummyERC20Token(
+ _name,
+ _symbol,
+ _decimals,
+ _totalSupply
+ )
+ {}
+
+ /// @dev 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
+ function transferFrom(
+ address _from,
+ address _to,
+ uint256 _value
+ )
+ external
+ returns (bool)
+ {
+ emit Transfer(
+ _from,
+ _to,
+ _value
+ );
+
+ // HACK: This contract will not compile if we remove `returns (bool)`, so we manually return 64 bytes (equiavalent to true, true)
+ assembly {
+ mstore(0, 1)
+ mstore(32, 1)
+ return(0, 64)
+ }
+ }
+}
+
diff --git a/packages/contracts/src/2.0.0/test/DummyERC20Token/DummyNoReturnERC20Token.sol b/packages/contracts/src/2.0.0/test/DummyERC20Token/DummyNoReturnERC20Token.sol
index 79156d3dd..e16825a16 100644
--- a/packages/contracts/src/2.0.0/test/DummyERC20Token/DummyNoReturnERC20Token.sol
+++ b/packages/contracts/src/2.0.0/test/DummyERC20Token/DummyNoReturnERC20Token.sol
@@ -25,7 +25,6 @@ import "./DummyERC20Token.sol";
contract DummyNoReturnERC20Token is
DummyERC20Token
{
-
constructor (
string _name,
string _symbol,
diff --git a/packages/contracts/src/2.0.0/test/DummyERC721Receiver/DummyERC721Receiver.sol b/packages/contracts/src/2.0.0/test/DummyERC721Receiver/DummyERC721Receiver.sol
index ac95e47bd..6c8371559 100644
--- a/packages/contracts/src/2.0.0/test/DummyERC721Receiver/DummyERC721Receiver.sol
+++ b/packages/contracts/src/2.0.0/test/DummyERC721Receiver/DummyERC721Receiver.sol
@@ -24,7 +24,6 @@ import "../../tokens/ERC721Token/IERC721Receiver.sol";
contract DummyERC721Receiver is
IERC721Receiver
{
-
// Function selector for ERC721Receiver.onERC721Received
// 0x150b7a02
bytes4 constant internal ERC721_RECEIVED = bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
diff --git a/packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol b/packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol
index 8bfdd2e66..99dd47a78 100644
--- a/packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol
+++ b/packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol
@@ -25,10 +25,10 @@ import "../../protocol/Exchange/interfaces/IExchange.sol";
import "../../protocol/Exchange/libs/LibOrder.sol";
+// solhint-disable no-unused-vars
contract ReentrantERC20Token is
ERC20Token
{
-
using LibBytes for bytes;
// solhint-disable-next-line var-name-mixedcase
@@ -50,6 +50,7 @@ contract ReentrantERC20Token is
MARKET_SELL_ORDERS,
MATCH_ORDERS,
CANCEL_ORDER,
+ BATCH_CANCEL_ORDERS,
CANCEL_ORDERS_UP_TO,
SET_SIGNATURE_VALIDATOR_APPROVAL
}
@@ -149,6 +150,11 @@ contract ReentrantERC20Token is
EXCHANGE.cancelOrder.selector,
order
);
+ } else if (currentFunctionId == uint8(ExchangeFunction.BATCH_CANCEL_ORDERS)) {
+ calldata = abi.encodeWithSelector(
+ EXCHANGE.batchCancelOrders.selector,
+ orders
+ );
} else if (currentFunctionId == uint8(ExchangeFunction.CANCEL_ORDERS_UP_TO)) {
calldata = abi.encodeWithSelector(
EXCHANGE.cancelOrdersUpTo.selector,
diff --git a/packages/contracts/src/2.0.0/test/TestAssetProxyOwner/TestAssetProxyOwner.sol b/packages/contracts/src/2.0.0/test/TestAssetProxyOwner/TestAssetProxyOwner.sol
index 75e782d43..52c66cb56 100644
--- a/packages/contracts/src/2.0.0/test/TestAssetProxyOwner/TestAssetProxyOwner.sol
+++ b/packages/contracts/src/2.0.0/test/TestAssetProxyOwner/TestAssetProxyOwner.sol
@@ -16,7 +16,7 @@
*/
-pragma solidity 0.4.10;
+pragma solidity 0.4.24;
import "../../protocol/AssetProxyOwner/AssetProxyOwner.sol";
@@ -25,8 +25,7 @@ import "../../protocol/AssetProxyOwner/AssetProxyOwner.sol";
contract TestAssetProxyOwner is
AssetProxyOwner
{
-
- function TestAssetProxyOwner(
+ constructor (
address[] memory _owners,
address[] memory _assetProxyContracts,
uint256 _required,
@@ -38,6 +37,7 @@ contract TestAssetProxyOwner is
function testValidRemoveAuthorizedAddressAtIndexTx(uint256 id)
public
+ view
validRemoveAuthorizedAddressAtIndexTx(id)
returns (bool)
{
@@ -50,23 +50,9 @@ contract TestAssetProxyOwner is
/// @return Successful if data is a call to `removeAuthorizedAddressAtIndex`.
function isFunctionRemoveAuthorizedAddressAtIndex(bytes memory data)
public
+ pure
returns (bool)
{
- return readBytes4(data, 0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR;
- }
-
- /// @dev Reads an unpadded bytes4 value from a position in a byte array.
- /// @param b Byte array containing a bytes4 value.
- /// @param index Index in byte array of bytes4 value.
- /// @return bytes4 value from byte array.
- function publicReadBytes4(
- bytes memory b,
- uint256 index
- )
- public
- returns (bytes4 result)
- {
- result = readBytes4(b, index);
- return result;
+ return data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR;
}
}
diff --git a/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol b/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol
index da9313e02..27187f8f8 100644
--- a/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol
+++ b/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol
@@ -63,6 +63,42 @@ contract TestExchangeInternals is
}
/// @dev Calculates partial value given a numerator and denominator.
+ /// Reverts if rounding error is >= 0.1%
+ /// @param numerator Numerator.
+ /// @param denominator Denominator.
+ /// @param target Value to calculate partial of.
+ /// @return Partial value of target.
+ function publicSafeGetPartialAmountFloor(
+ uint256 numerator,
+ uint256 denominator,
+ uint256 target
+ )
+ public
+ pure
+ returns (uint256 partialAmount)
+ {
+ return safeGetPartialAmountFloor(numerator, denominator, target);
+ }
+
+ /// @dev Calculates partial value given a numerator and denominator.
+ /// Reverts if rounding error is >= 0.1%
+ /// @param numerator Numerator.
+ /// @param denominator Denominator.
+ /// @param target Value to calculate partial of.
+ /// @return Partial value of target.
+ function publicSafeGetPartialAmountCeil(
+ uint256 numerator,
+ uint256 denominator,
+ uint256 target
+ )
+ public
+ pure
+ returns (uint256 partialAmount)
+ {
+ return safeGetPartialAmountCeil(numerator, denominator, target);
+ }
+
+ /// @dev Calculates partial value given a numerator and denominator.
/// @param numerator Numerator.
/// @param denominator Denominator.
/// @param target Value to calculate partial of.
diff --git a/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol b/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol
index c8c58545f..a10f981fc 100644
--- a/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol
+++ b/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol
@@ -31,7 +31,6 @@ contract TestLibs is
LibFillResults,
LibAbiEncoder
{
-
function publicAbiEncodeFillOrder(
Order memory order,
uint256 takerAssetFillAmount,
diff --git a/packages/contracts/src/2.0.0/test/TestSignatureValidator/TestSignatureValidator.sol b/packages/contracts/src/2.0.0/test/TestSignatureValidator/TestSignatureValidator.sol
index e1a610469..ea3e2de59 100644
--- a/packages/contracts/src/2.0.0/test/TestSignatureValidator/TestSignatureValidator.sol
+++ b/packages/contracts/src/2.0.0/test/TestSignatureValidator/TestSignatureValidator.sol
@@ -26,7 +26,6 @@ contract TestSignatureValidator is
MixinSignatureValidator,
MixinTransactions
{
-
function publicIsValidSignature(
bytes32 hash,
address signer,
diff --git a/packages/contracts/src/2.0.0/tokens/ERC20Token/ERC20Token.sol b/packages/contracts/src/2.0.0/tokens/ERC20Token/ERC20Token.sol
index 5ef5ee7ce..725d304df 100644
--- a/packages/contracts/src/2.0.0/tokens/ERC20Token/ERC20Token.sol
+++ b/packages/contracts/src/2.0.0/tokens/ERC20Token/ERC20Token.sol
@@ -24,7 +24,6 @@ import "./IERC20Token.sol";
contract ERC20Token is
IERC20Token
{
-
mapping (address => uint256) internal balances;
mapping (address => mapping (address => uint256)) internal allowed;
diff --git a/packages/contracts/src/2.0.0/tokens/ERC20Token/MintableERC20Token.sol b/packages/contracts/src/2.0.0/tokens/ERC20Token/MintableERC20Token.sol
index cd1c7b4bb..9dc924422 100644
--- a/packages/contracts/src/2.0.0/tokens/ERC20Token/MintableERC20Token.sol
+++ b/packages/contracts/src/2.0.0/tokens/ERC20Token/MintableERC20Token.sol
@@ -26,7 +26,6 @@ contract MintableERC20Token is
SafeMath,
UnlimitedAllowanceERC20Token
{
-
/// @dev Mints new tokens
/// @param _to Address of the beneficiary that will own the minted token
/// @param _value Amount of tokens to mint
diff --git a/packages/contracts/src/2.0.0/tokens/ERC20Token/UnlimitedAllowanceERC20Token.sol b/packages/contracts/src/2.0.0/tokens/ERC20Token/UnlimitedAllowanceERC20Token.sol
index e6f7c063e..2e5bd4348 100644
--- a/packages/contracts/src/2.0.0/tokens/ERC20Token/UnlimitedAllowanceERC20Token.sol
+++ b/packages/contracts/src/2.0.0/tokens/ERC20Token/UnlimitedAllowanceERC20Token.sol
@@ -24,7 +24,6 @@ import "../ERC20Token/ERC20Token.sol";
contract UnlimitedAllowanceERC20Token is
ERC20Token
{
-
uint256 constant internal 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
diff --git a/packages/contracts/src/2.0.0/tokens/ERC721Token/MintableERC721Token.sol b/packages/contracts/src/2.0.0/tokens/ERC721Token/MintableERC721Token.sol
index 85d192779..bc5cd2cc2 100644
--- a/packages/contracts/src/2.0.0/tokens/ERC721Token/MintableERC721Token.sol
+++ b/packages/contracts/src/2.0.0/tokens/ERC721Token/MintableERC721Token.sol
@@ -24,7 +24,6 @@ import "./ERC721Token.sol";
contract MintableERC721Token is
ERC721Token
{
-
/// @dev Function to mint a new token
/// Reverts if the given token ID already exists
/// @param _to Address of the beneficiary that will own the minted token
diff --git a/packages/contracts/src/2.0.0/tokens/ZRXToken/ZRXToken.sol b/packages/contracts/src/2.0.0/tokens/ZRXToken/ZRXToken.sol
index 28c0b2fb3..f4855759c 100644
--- a/packages/contracts/src/2.0.0/tokens/ZRXToken/ZRXToken.sol
+++ b/packages/contracts/src/2.0.0/tokens/ZRXToken/ZRXToken.sol
@@ -22,11 +22,13 @@ pragma solidity 0.4.11;
import { UnlimitedAllowanceToken_v1 as UnlimitedAllowanceToken } from "../../../1.0.0/UnlimitedAllowanceToken/UnlimitedAllowanceToken_v1.sol";
-contract ZRXToken is UnlimitedAllowanceToken {
+contract ZRXToken is
+ UnlimitedAllowanceToken
+{
// solhint-disable const-name-snakecase
uint8 constant public decimals = 18;
- uint public totalSupply = 10**27; // 1 billion tokens, 18 decimal places
+ uint256 public totalSupply = 10**27; // 1 billion tokens, 18 decimal places
string constant public name = "0x Protocol Token";
string constant public symbol = "ZRX";
// solhint-enableconst-name-snakecase
diff --git a/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol b/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol
index 504e950a8..369f588ad 100644
--- a/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol
+++ b/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol
@@ -188,7 +188,8 @@ library LibBytes {
memCopy(
result.contentAddress(),
b.contentAddress() + from,
- result.length);
+ result.length
+ );
return result;
}
@@ -433,7 +434,8 @@ library LibBytes {
pure
returns (uint256 result)
{
- return uint256(readBytes32(b, index));
+ result = uint256(readBytes32(b, index));
+ return result;
}
/// @dev Writes a uint256 into a specific position in a byte array.
@@ -467,8 +469,13 @@ library LibBytes {
b.length >= index + 4,
"GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED"
);
+
+ // Arrays are prefixed by a 32 byte length field
+ index += 32;
+
+ // Read the bytes4 from array memory
assembly {
- result := mload(add(b, 32))
+ result := mload(add(b, index))
// Solidity does not require us to clean the trailing bytes.
// We do it anyway
result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
diff --git a/packages/contracts/src/2.0.0/utils/Ownable/IOwnable.sol b/packages/contracts/src/2.0.0/utils/Ownable/IOwnable.sol
index 116b8dc89..5deb13497 100644
--- a/packages/contracts/src/2.0.0/utils/Ownable/IOwnable.sol
+++ b/packages/contracts/src/2.0.0/utils/Ownable/IOwnable.sol
@@ -1,13 +1,8 @@
pragma solidity 0.4.24;
-/*
- * 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 IOwnable {
+
function transferOwnership(address newOwner)
public;
}
diff --git a/packages/contracts/src/2.0.0/utils/Ownable/Ownable.sol b/packages/contracts/src/2.0.0/utils/Ownable/Ownable.sol
index aca65aad2..0c830be68 100644
--- a/packages/contracts/src/2.0.0/utils/Ownable/Ownable.sol
+++ b/packages/contracts/src/2.0.0/utils/Ownable/Ownable.sol
@@ -1,16 +1,11 @@
pragma solidity 0.4.24;
-/*
- * Ownable
- *
- * Base contract with an owner.
- * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.
- */
-
import "./IOwnable.sol";
-contract Ownable is IOwnable {
+contract Ownable is
+ IOwnable
+{
address public owner;
constructor ()
diff --git a/packages/contracts/src/2.0.0/utils/ReentrancyGuard/ReentrancyGuard.sol b/packages/contracts/src/2.0.0/utils/ReentrancyGuard/ReentrancyGuard.sol
index 1dee512d4..9f98a7a16 100644
--- a/packages/contracts/src/2.0.0/utils/ReentrancyGuard/ReentrancyGuard.sol
+++ b/packages/contracts/src/2.0.0/utils/ReentrancyGuard/ReentrancyGuard.sol
@@ -15,6 +15,7 @@
limitations under the License.
*/
+
pragma solidity 0.4.24;
diff --git a/packages/contracts/src/2.0.0/utils/SafeMath/SafeMath.sol b/packages/contracts/src/2.0.0/utils/SafeMath/SafeMath.sol
index 63a2a085f..2855edb9d 100644
--- a/packages/contracts/src/2.0.0/utils/SafeMath/SafeMath.sol
+++ b/packages/contracts/src/2.0.0/utils/SafeMath/SafeMath.sol
@@ -2,6 +2,7 @@ pragma solidity 0.4.24;
contract SafeMath {
+
function safeMul(uint256 a, uint256 b)
internal
pure