aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/src
diff options
context:
space:
mode:
authorAmir Bandeali <abandeali1@gmail.com>2018-05-09 08:20:23 +0800
committerGitHub <noreply@github.com>2018-05-09 08:20:23 +0800
commit9744b1906a111aa0c65c8fafb4db66aef32a5a23 (patch)
tree6d4c6b8e99fab87190c7de41bdfa8bf6e2213687 /packages/contracts/src
parent853b5e1b72733c5dee862a62b549a6c784aeb4eb (diff)
parent5198c56db94a43148789d3d0561220bd7cf546c0 (diff)
downloaddexon-sol-tools-9744b1906a111aa0c65c8fafb4db66aef32a5a23.tar
dexon-sol-tools-9744b1906a111aa0c65c8fafb4db66aef32a5a23.tar.gz
dexon-sol-tools-9744b1906a111aa0c65c8fafb4db66aef32a5a23.tar.bz2
dexon-sol-tools-9744b1906a111aa0c65c8fafb4db66aef32a5a23.tar.lz
dexon-sol-tools-9744b1906a111aa0c65c8fafb4db66aef32a5a23.tar.xz
dexon-sol-tools-9744b1906a111aa0c65c8fafb4db66aef32a5a23.tar.zst
dexon-sol-tools-9744b1906a111aa0c65c8fafb4db66aef32a5a23.zip
Merge pull request #546 from 0xProject/feature/contracts/solidity-0.4.23
Use Solidity 0.4.23
Diffstat (limited to 'packages/contracts/src')
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol (renamed from packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC20Proxy.sol)34
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol (renamed from packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol)35
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol10
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol (renamed from packages/contracts/src/contracts/current/utils/Authorizable/Authorizable.sol)73
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol (renamed from packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol)8
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAuthorizable.sol (renamed from packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol)26
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol8
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAuthorizable.sol (renamed from packages/contracts/src/contracts/current/protocol/Exchange/LibErrors.sol)29
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol4
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/IExchange.sol289
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol73
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol117
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol23
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol123
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol18
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol40
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol41
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchange.sol34
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol51
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol32
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISigner.sol (renamed from packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol)7
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol33
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol142
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol58
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/libs/LibFillResults.sol (renamed from packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol)9
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/libs/LibMath.sol (renamed from packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol)9
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol (renamed from packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol)3
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol27
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol58
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol12
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol22
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MTransactions.sol25
-rw-r--r--packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol5
-rw-r--r--packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol11
-rw-r--r--packages/contracts/src/contracts/current/test/Mintable/Mintable.sol8
-rw-r--r--packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol3
-rw-r--r--packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol133
-rw-r--r--packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol8
-rw-r--r--packages/contracts/src/contracts/current/test/TestSignatureValidator/TestSignatureValidator.sol2
-rw-r--r--packages/contracts/src/contracts/current/tokens/ERC20Token/ERC20Token.sol39
-rw-r--r--packages/contracts/src/contracts/current/tokens/ERC20Token/IERC20Token.sol13
-rw-r--r--packages/contracts/src/contracts/current/tokens/ERC721Token/ERC721Token.sol2
-rw-r--r--packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Receiver.sol2
-rw-r--r--packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Token.sol2
-rw-r--r--packages/contracts/src/contracts/current/tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol18
-rw-r--r--packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol47
-rw-r--r--packages/contracts/src/contracts/current/utils/Ownable/IOwnable.sol3
-rw-r--r--packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol12
-rw-r--r--packages/contracts/src/contracts/current/utils/SafeMath/SafeMath.sol3
-rw-r--r--packages/contracts/src/utils/types.ts2
50 files changed, 1112 insertions, 674 deletions
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol
index 713e8a6e6..c02536d67 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC20Proxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol
@@ -16,21 +16,28 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
-
-import "../../../utils/LibBytes/LibBytes.sol";
-import "../../../tokens/ERC20Token/IERC20Token.sol";
-import "../MixinAssetProxy.sol";
+import "../../utils/LibBytes/LibBytes.sol";
+import "../../tokens/ERC20Token/IERC20Token.sol";
+import "./MixinAssetProxy.sol";
+import "./MixinAuthorizable.sol";
contract ERC20Proxy is
LibBytes,
- MixinAssetProxy
+ MixinAssetProxy,
+ MixinAuthorizable
{
+ // Id of this proxy.
uint8 constant PROXY_ID = 1;
+ // Revert reasons
+ string constant INVALID_METADATA_LENGTH = "Metadata must have a length of 21.";
+ string constant TRANSFER_FAILED = "Transfer failed.";
+ string constant PROXY_ID_MISMATCH = "Proxy id in metadata does not match this proxy id.";
+
/// @dev Internal version of `transferFrom`.
/// @param assetMetadata Encoded byte array.
/// @param from Address to transfer asset from.
@@ -44,15 +51,24 @@ contract ERC20Proxy is
internal
{
// Data must be intended for this proxy.
- require(uint8(assetMetadata[0]) == PROXY_ID);
+ require(
+ uint8(assetMetadata[0]) == PROXY_ID,
+ PROXY_ID_MISMATCH
+ );
// Decode metadata.
- require(assetMetadata.length == 21);
+ require(
+ assetMetadata.length == 21,
+ INVALID_METADATA_LENGTH
+ );
address token = readAddress(assetMetadata, 1);
// Transfer tokens.
bool success = IERC20Token(token).transferFrom(from, to, amount);
- require(success == true);
+ require(
+ success == true,
+ TRANSFER_FAILED
+ );
}
/// @dev Gets the proxy id associated with the proxy address.
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
index 6a4475d48..475359087 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
@@ -16,20 +16,28 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
-import "../../../utils/LibBytes/LibBytes.sol";
-import "../../../tokens/ERC721Token/ERC721Token.sol";
-import "../MixinAssetProxy.sol";
+import "../../utils/LibBytes/LibBytes.sol";
+import "../../tokens/ERC721Token/ERC721Token.sol";
+import "./MixinAssetProxy.sol";
+import "./MixinAuthorizable.sol";
contract ERC721Proxy is
LibBytes,
- MixinAssetProxy
+ MixinAssetProxy,
+ MixinAuthorizable
{
+ // Id of this proxy.
uint8 constant PROXY_ID = 2;
+ // Revert reasons
+ string constant INVALID_TRANSFER_AMOUNT = "Transfer amount must equal 1.";
+ string constant INVALID_METADATA_LENGTH = "Metadata must have a length of 53.";
+ string constant PROXY_ID_MISMATCH = "Proxy id in metadata does not match this proxy id.";
+
/// @dev Internal version of `transferFrom`.
/// @param assetMetadata Encoded byte array.
/// @param from Address to transfer asset from.
@@ -43,13 +51,22 @@ contract ERC721Proxy is
internal
{
// Data must be intended for this proxy.
- require(uint8(assetMetadata[0]) == PROXY_ID);
+ require(
+ uint8(assetMetadata[0]) == PROXY_ID,
+ PROXY_ID_MISMATCH
+ );
// There exists only 1 of each token.
- require(amount == 1);
+ require(
+ amount == 1,
+ INVALID_TRANSFER_AMOUNT
+ );
- // Decode metadata.
- require(assetMetadata.length == 53);
+ // Decode metadata
+ require(
+ assetMetadata.length == 53,
+ INVALID_METADATA_LENGTH
+ );
address token = readAddress(assetMetadata, 1);
uint256 tokenId = readUint256(assetMetadata, 21);
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol
index 23dce6a8b..d58cfc2dd 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol
@@ -16,17 +16,15 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "./mixins/MAssetProxy.sol";
-import "./IAssetProxy.sol";
-import "../../utils/Authorizable/Authorizable.sol";
+import "./mixins/MAuthorizable.sol";
contract MixinAssetProxy is
- IAssetProxy,
- MAssetProxy,
- Authorizable
+ MAuthorizable,
+ MAssetProxy
{
/// @dev Transfers assets. Either succeeds or throws.
diff --git a/packages/contracts/src/contracts/current/utils/Authorizable/Authorizable.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol
index f6032f889..b66b783ea 100644
--- a/packages/contracts/src/contracts/current/utils/Authorizable/Authorizable.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol
@@ -16,46 +16,47 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
-import "./IAuthorizable.sol";
-import "../Ownable/Ownable.sol";
+import "./mixins/MAuthorizable.sol";
+import "../../utils/Ownable/Ownable.sol";
-contract Authorizable is
+contract MixinAuthorizable is
Ownable,
- IAuthorizable
+ MAuthorizable
{
+ // Revert reasons
+ string constant SENDER_NOT_AUTHORIZED = "Sender not authorized to call this method.";
+ string constant TARGET_NOT_AUTHORIZED = "Target address must be authorized.";
+ string constant TARGET_ALREADY_AUTHORIZED = "Target must not already be authorized.";
+ string constant INDEX_OUT_OF_BOUNDS = "Specified array index is out of bounds.";
+ string constant INDEX_ADDRESS_MISMATCH = "Address found at index does not match target address.";
+
/// @dev Only authorized addresses can invoke functions with this modifier.
modifier onlyAuthorized {
- require(authorized[msg.sender]);
- _;
- }
-
- modifier targetAuthorized(address target) {
- require(authorized[target]);
- _;
- }
-
- modifier targetNotAuthorized(address target) {
- require(!authorized[target]);
+ require(
+ authorized[msg.sender],
+ SENDER_NOT_AUTHORIZED
+ );
_;
}
mapping (address => bool) public authorized;
address[] public authorities;
- /*
- * Public functions
- */
-
/// @dev Authorizes an address.
/// @param target Address to authorize.
function addAuthorizedAddress(address target)
- public
+ external
onlyOwner
- targetNotAuthorized(target)
{
+ require(
+ !authorized[target],
+ TARGET_ALREADY_AUTHORIZED
+ );
+
authorized[target] = true;
authorities.push(target);
emit AuthorizedAddressAdded(target, msg.sender);
@@ -64,10 +65,14 @@ contract Authorizable is
/// @dev Removes authorizion of an address.
/// @param target Address to remove authorization from.
function removeAuthorizedAddress(address target)
- public
+ external
onlyOwner
- targetAuthorized(target)
{
+ require(
+ authorized[target],
+ TARGET_NOT_AUTHORIZED
+ );
+
delete authorized[target];
for (uint i = 0; i < authorities.length; i++) {
if (authorities[i] == target) {
@@ -83,24 +88,28 @@ contract Authorizable is
/// @param target Address to remove authorization from.
/// @param index Index of target in authorities array.
function removeAuthorizedAddressAtIndex(address target, uint256 index)
- public
+ external
{
- require(index < authorities.length);
- require(authorities[index] == target);
+ require(
+ index < authorities.length,
+ INDEX_OUT_OF_BOUNDS
+ );
+ require(
+ authorities[index] == target,
+ INDEX_ADDRESS_MISMATCH
+ );
+
delete authorized[target];
authorities[index] = authorities[authorities.length - 1];
authorities.length -= 1;
emit AuthorizedAddressRemoved(target, msg.sender);
}
- /*
- * Public constant functions
- */
-
/// @dev Gets all authorized addresses.
/// @return Array of authorized addresses.
function getAuthorizedAddresses()
- public view
+ external
+ view
returns (address[] memory)
{
return authorities;
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol
index df993a0ab..eca6524e5 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol
@@ -16,12 +16,14 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
-import "../../utils/Authorizable/IAuthorizable.sol";
+import "./IAuthorizable.sol";
-contract IAssetProxy is IAuthorizable {
+contract IAssetProxy is
+ IAuthorizable
+{
/// @dev Transfers assets. Either succeeds or throws.
/// @param assetMetadata Byte array encoded for the respective asset proxy.
diff --git a/packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAuthorizable.sol
index 10c01c6fe..3120be7ec 100644
--- a/packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAuthorizable.sol
@@ -16,37 +16,35 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
-contract IAuthorizable {
+import "../../../utils/Ownable/IOwnable.sol";
+
+contract IAuthorizable is
+ IOwnable
+{
/// @dev Gets all authorized addresses.
/// @return Array of authorized addresses.
function getAuthorizedAddresses()
- public view
+ external
+ view
returns (address[]);
/// @dev Authorizes an address.
/// @param target Address to authorize.
function addAuthorizedAddress(address target)
- public;
+ external;
/// @dev Removes authorizion of an address.
/// @param target Address to remove authorization from.
function removeAuthorizedAddress(address target)
- public;
+ external;
/// @dev Removes authorizion of an address.
/// @param target Address to remove authorization from.
/// @param index Index of target in authorities array.
function removeAuthorizedAddressAtIndex(address target, uint256 index)
- public;
-
- event AuthorizedAddressAdded(
- address indexed target,
- address indexed caller);
-
- event AuthorizedAddressRemoved(
- address indexed target,
- address indexed caller);
+ external;
}
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol
index 8e9b3bc65..e0ec8c4e1 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol
@@ -16,10 +16,14 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
-contract MAssetProxy {
+import "../interfaces/IAssetProxy.sol";
+
+contract MAssetProxy is
+ IAssetProxy
+{
/// @dev Internal version of `transferFrom`.
/// @param assetMetadata Encoded byte array.
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibErrors.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAuthorizable.sol
index 55160ad5b..71d1910e5 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/LibErrors.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAuthorizable.sol
@@ -16,20 +16,27 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
-contract LibErrors {
+import "../interfaces/IAuthorizable.sol";
- // Error Codes
- enum Errors {
- ORDER_EXPIRED, // Order has already expired
- ORDER_FULLY_FILLED, // Order has already been fully filled
- ORDER_CANCELLED, // Order has already been cancelled
- ROUNDING_ERROR_TOO_LARGE, // Rounding error too large
- INSUFFICIENT_BALANCE_OR_ALLOWANCE // Insufficient balance or allowance for token transfer
- }
+contract MAuthorizable is
+ IAuthorizable
+{
- event ExchangeError(uint8 indexed errorId, bytes32 indexed orderHash);
+ // Event logged when a new address is authorized.
+ event AuthorizedAddressAdded(
+ address indexed target,
+ address indexed caller
+ );
+ // Event logged when a currently authorized address is unauthorized.
+ event AuthorizedAddressRemoved(
+ address indexed target,
+ address indexed caller
+ );
+
+ /// @dev Only authorized addresses can invoke functions with this modifier.
+ modifier onlyAuthorized { _; }
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
index e78446b99..85e2bc47e 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
@@ -16,7 +16,7 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "./MixinExchangeCore.sol";
@@ -36,7 +36,7 @@ contract Exchange is
{
string constant public VERSION = "2.0.1-alpha";
- function Exchange(bytes memory _zrxProxyData)
+ constructor (bytes memory _zrxProxyData)
public
MixinExchangeCore()
MixinSignatureValidator()
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/IExchange.sol b/packages/contracts/src/contracts/current/protocol/Exchange/IExchange.sol
deleted file mode 100644
index ef2fb2a96..000000000
--- a/packages/contracts/src/contracts/current/protocol/Exchange/IExchange.sol
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
-
- 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.21;
-pragma experimental ABIEncoderV2;
-
-contract IExchange {
-
- // Error Codes
- enum Errors {
- ORDER_EXPIRED, // Order has already expired
- ORDER_FULLY_FILLED_OR_CANCELLED, // Order has already been fully filled or cancelled
- ROUNDING_ERROR_TOO_LARGE, // Rounding error too large
- INSUFFICIENT_BALANCE_OR_ALLOWANCE // Insufficient balance or allowance for token transfer
- }
-
- event LogError(uint8 indexed errorId, bytes32 indexed orderHash);
-
- event LogFill(
- address indexed maker,
- address taker,
- address indexed feeRecipient,
- bytes makerAssetData,
- bytes takerAssetData,
- uint256 makerAssetFilledAmount,
- uint256 takerAssetFilledAmount,
- uint256 makerFeePaid,
- uint256 takerFeePaid,
- bytes32 indexed orderHash
- );
-
- event LogCancel(
- address indexed maker,
- address indexed feeRecipient,
- bytes makerAssetData,
- bytes takerAssetData,
- uint256 makerAssetCancelledAmount,
- uint256 takerAssetCancelledAmount,
- bytes32 indexed orderHash
- );
-
- function ZRX_TOKEN_CONTRACT()
- public view
- returns (address);
-
- function EXTERNAL_QUERY_GAS_LIMIT()
- public view
- returns (uint16);
-
- function VERSION()
- public view
- returns (string);
-
- function filled(bytes32)
- public view
- returns (uint256);
-
- function cancelled(bytes32)
- public view
- returns (uint256);
-
- /// @dev Calculates the sum of values already filled and cancelled for a given order.
- /// @param orderHash The Keccak-256 hash of the given order.
- /// @return Sum of values already filled and cancelled.
- function getUnavailableTakerAssetAmount(bytes32 orderHash)
- public view
- returns (uint256 unavailableTakerAssetAmount);
-
- /// @dev Calculates partial value given a numerator and denominator.
- /// @param numerator Numerator.
- /// @param denominator Denominator.
- /// @param target Value to calculate partial of.
- /// @return Partial value of target.
- function getPartialAmount(uint256 numerator, uint256 denominator, uint256 target)
- public pure
- returns (uint256 partialAmount);
-
- /// @dev Checks if rounding error > 0.1%.
- /// @param numerator Numerator.
- /// @param denominator Denominator.
- /// @param target Value to multiply with numerator/denominator.
- /// @return Rounding error is present.
- function isRoundingError(uint256 numerator, uint256 denominator, uint256 target)
- public pure
- returns (bool isError);
-
- /// @dev Calculates Keccak-256 hash of order with specified parameters.
- /// @param orderAddresses Array of order's maker, taker, makerAsset, takerAsset, and feeRecipient.
- /// @param orderValues Array of order's makerAssetAmount, takerAssetAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
- /// @return Keccak-256 hash of order.
- function getOrderHash(address[5] orderAddresses, uint256[6] orderValues)
- public view
- returns (bytes32 orderHash);
-
- /// @dev Verifies that an order signature is valid.
- /// @param signer address of signer.
- /// @param hash Signed Keccak-256 hash.
- /// @param v ECDSA signature parameter v.
- /// @param r ECDSA signature parameters r.
- /// @param s ECDSA signature parameters s.
- /// @return Validity of order signature.
- function isValidSignature(
- address signer,
- bytes32 hash,
- uint8 v,
- bytes32 r,
- bytes32 s)
- public pure
- returns (bool isValid);
-
- /// @dev Fills the input order.
- /// @param orderAddresses Array of order's maker, taker, makerAsset, takerAsset, and feeRecipient.
- /// @param orderValues Array of order's makerAssetAmount, takerAssetAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
- /// @param takerAssetFillAmount Desired amount of takerAsset to fill.
- /// @param v ECDSA signature parameter v.
- /// @param r ECDSA signature parameters r.
- /// @param s ECDSA signature parameters s.
- /// @return Total amount of takerAsset filled in trade.
- function fillOrder(
- address[5] orderAddresses,
- uint256[6] orderValues,
- uint256 takerAssetFillAmount,
- uint8 v,
- bytes32 r,
- bytes32 s)
- public
- returns (uint256 takerAssetFilledAmount);
-
- /// @dev Cancels the input order.
- /// @param orderAddresses Array of order's maker, taker, makerAsset, takerAsset, and feeRecipient.
- /// @param orderValues Array of order's makerAssetAmount, takerAssetAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
- /// @param takerAssetCancelAmount Desired amount of takerAsset to cancel in order.
- /// @return Amount of takerAsset cancelled.
- function cancelOrder(
- address[5] orderAddresses,
- uint256[6] orderValues,
- uint256 takerAssetCancelAmount)
- public
- returns (uint256 takerAssetCancelledAmount);
-
- /// @dev Cancels all orders for a specified maker up to a certain time.
- /// @param salt Orders created with a salt less or equal to this value will be cancelled.
- function cancelOrdersUpTo(uint256 salt)
- external;
-
- /// @dev Fills an order with specified parameters and ECDSA signature. Throws if specified amount not filled entirely.
- /// @param orderAddresses Array of order's maker, taker, makerAsset, takerAsset, and feeRecipient.
- /// @param orderValues Array of order's makerAssetAmount, takerAssetAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
- /// @param takerAssetFillAmount Desired amount of takerAsset to fill.
- /// @param v ECDSA signature parameter v.
- /// @param r ECDSA signature parameters r.
- /// @param s ECDSA signature parameters s.
- function fillOrKillOrder(
- address[5] orderAddresses,
- uint256[6] orderValues,
- uint256 takerAssetFillAmount,
- uint8 v,
- bytes32 r,
- bytes32 s)
- public;
-
- /// @dev Fills an order with specified parameters and ECDSA signature. Returns false if the transaction would otherwise revert.
- /// @param orderAddresses Array of order's maker, taker, makerAsset, takerAsset, and feeRecipient.
- /// @param orderValues Array of order's makerAssetAmount, takerAssetAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
- /// @param takerAssetFillAmount Desired amount of takerAsset to fill.
- /// @param v ECDSA signature parameter v.
- /// @param r ECDSA signature parameters r.
- /// @param s ECDSA signature parameters s.
- /// @return Success if the transaction did not revert.
- /// @return Total amount of takerAsset filled in trade.
- function fillOrderNoThrow(
- address[5] orderAddresses,
- uint256[6] orderValues,
- uint256 takerAssetFillAmount,
- uint8 v,
- bytes32 r,
- bytes32 s)
- public
- returns (bool success, uint256 takerAssetFilledAmount);
-
- /// @dev Synchronously executes multiple calls of fillOrder in a single transaction.
- /// @param orderAddresses Array of address arrays containing individual order addresses.
- /// @param orderValues Array of uint256 arrays containing individual order values.
- /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to fill in orders.
- /// @param v Array ECDSA signature v parameters.
- /// @param r Array of ECDSA signature r parameters.
- /// @param s Array of ECDSA signature s parameters.
- function batchFillOrders(
- address[5][] orderAddresses,
- uint256[6][] orderValues,
- uint256[] takerAssetFillAmounts,
- uint8[] v,
- bytes32[] r,
- bytes32[] s)
- external;
-
- /// @dev Synchronously executes multiple calls of fillOrKill in a single transaction.
- /// @param orderAddresses Array of address arrays containing individual order addresses.
- /// @param orderValues Array of uint256 arrays containing individual order values.
- /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to fill in orders.
- /// @param v Array ECDSA signature v parameters.
- /// @param r Array of ECDSA signature r parameters.
- /// @param s Array of ECDSA signature s parameters.
- function batchFillOrKillOrders(
- address[5][] orderAddresses,
- uint256[6][] orderValues,
- uint256[] takerAssetFillAmounts,
- uint8[] v,
- bytes32[] r,
- bytes32[] s)
- external;
-
- /// @dev Synchronously executes multiple calls of fillOrderNoThrow in a single transaction.
- /// @param orderAddresses Array of address arrays containing individual order addresses.
- /// @param orderValues Array of uint256 arrays containing individual order values.
- /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to fill in orders.
- /// @param v Array ECDSA signature v parameters.
- /// @param r Array of ECDSA signature r parameters.
- /// @param s Array of ECDSA signature s parameters.
- function batchFillOrdersNoThrow(
- address[5][] orderAddresses,
- uint256[6][] orderValues,
- uint256[] takerAssetFillAmounts,
- uint8[] v,
- bytes32[] r,
- bytes32[] s)
- external;
-
- /// @dev Synchronously executes multiple fill orders in a single transaction until total takerAssetFillAmount filled.
- /// @param orderAddresses Array of address arrays containing individual order addresses.
- /// @param orderValues Array of uint256 arrays containing individual order values.
- /// @param takerAssetFillAmount Desired total amount of takerAsset to fill in orders.
- /// @param v Array ECDSA signature v parameters.
- /// @param r Array of ECDSA signature r parameters.
- /// @param s Array of ECDSA signature s parameters.
- /// @return Total amount of takerAssetFillAmount filled in orders.
- function marketFillOrders(
- address[5][] orderAddresses,
- uint256[6][] orderValues,
- uint256 takerAssetFillAmount,
- uint8[] v,
- bytes32[] r,
- bytes32[] s)
- external
- returns (uint256 totalTakerAssetFilledAmount);
-
- /// @dev Synchronously executes multiple calls of fillOrderNoThrow in a single transaction until total takerAssetFillAmount filled.
- /// @param orderAddresses Array of address arrays containing individual order addresses.
- /// @param orderValues Array of uint256 arrays containing individual order values.
- /// @param takerAssetFillAmount Desired total amount of takerAsset to fill in orders.
- /// @param v Array ECDSA signature v parameters.
- /// @param r Array of ECDSA signature r parameters.
- /// @param s Array of ECDSA signature s parameters.
- /// @return Total amount of takerAssetFillAmount filled in orders.
- function marketFillOrdersNoThrow(
- address[5][] orderAddresses,
- uint256[6][] orderValues,
- uint256 takerAssetFillAmount,
- uint8[] v,
- bytes32[] r,
- bytes32[] s)
- external
- returns (uint256 totalTakerAssetFilledAmount);
-
- /// @dev Synchronously cancels multiple orders in a single transaction.
- /// @param orderAddresses Array of address arrays containing individual order addresses.
- /// @param orderValues Array of uint256 arrays containing individual order values.
- /// @param takerAssetCancelAmounts Array of desired amounts of takerAsset to cancel in orders.
- function batchCancelOrders(
- address[5][] orderAddresses,
- uint256[6][] orderValues,
- uint256[] takerAssetCancelAmounts)
- external;
-}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
index b73c6ca90..308dace32 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
@@ -16,43 +16,21 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
import "../../utils/Ownable/Ownable.sol";
-import "../AssetProxy/IAssetProxy.sol";
+import "../AssetProxy/interfaces/IAssetProxy.sol";
+import "./libs/LibExchangeErrors.sol";
import "./mixins/MAssetProxyDispatcher.sol";
contract MixinAssetProxyDispatcher is
+ LibExchangeErrors,
Ownable,
MAssetProxyDispatcher
{
// Mapping from Asset Proxy Id's to their respective Asset Proxy
mapping (uint8 => IAssetProxy) public assetProxies;
- /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
- /// @param assetMetadata Byte array encoded for the respective asset proxy.
- /// @param from Address to transfer token from.
- /// @param to Address to transfer token to.
- /// @param amount Amount of token to transfer.
- function dispatchTransferFrom(
- bytes memory assetMetadata,
- address from,
- address to,
- uint256 amount)
- internal
- {
- // Do nothing if no amount should be transferred.
- if (amount > 0) {
- // Lookup asset proxy.
- require(assetMetadata.length >= 1);
- uint8 assetProxyId = uint8(assetMetadata[0]);
- IAssetProxy assetProxy = assetProxies[assetProxyId];
-
- // transferFrom will either succeed or throw.
- assetProxy.transferFrom(assetMetadata, from, to, amount);
- }
- }
-
/// @dev Registers an asset proxy to an asset proxy id.
/// An id can only be assigned to a single proxy at a given time.
/// @param assetProxyId Id to register`newAssetProxy` under.
@@ -65,15 +43,21 @@ contract MixinAssetProxyDispatcher is
external
onlyOwner
{
- // Ensure the existing asset proxy is not unintentionally overwritten.
- require(oldAssetProxy == address(assetProxies[assetProxyId]));
+ // Ensure the existing asset proxy is not unintentionally overwritten
+ require(
+ oldAssetProxy == address(assetProxies[assetProxyId]),
+ OLD_ASSET_PROXY_MISMATCH
+ );
IAssetProxy assetProxy = IAssetProxy(newAssetProxy);
// Ensure that the id of newAssetProxy matches the passed in assetProxyId, unless it is being reset to 0.
if (newAssetProxy != address(0)) {
uint8 newAssetProxyId = assetProxy.getProxyId();
- require(newAssetProxyId == assetProxyId);
+ require(
+ newAssetProxyId == assetProxyId,
+ NEW_ASSET_PROXY_MISMATCH
+ );
}
// Add asset proxy and log registration.
@@ -89,7 +73,34 @@ contract MixinAssetProxyDispatcher is
view
returns (address)
{
- IAssetProxy assetProxy = assetProxies[assetProxyId];
- return address(assetProxy);
+ address assetProxy = address(assetProxies[assetProxyId]);
+ return assetProxy;
+ }
+
+ /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
+ /// @param assetMetadata Byte array encoded for the respective asset proxy.
+ /// @param from Address to transfer token from.
+ /// @param to Address to transfer token to.
+ /// @param amount Amount of token to transfer.
+ function dispatchTransferFrom(
+ bytes memory assetMetadata,
+ address from,
+ address to,
+ uint256 amount)
+ internal
+ {
+ // Do nothing if no amount should be transferred.
+ if (amount > 0) {
+ // Lookup asset proxy
+ require(
+ assetMetadata.length >= 1,
+ GT_ZERO_LENGTH_REQUIRED
+ );
+ uint8 assetProxyId = uint8(assetMetadata[0]);
+ IAssetProxy assetProxy = assetProxies[assetProxyId];
+
+ // transferFrom will either succeed or throw.
+ assetProxy.transferFrom(assetMetadata, from, to, amount);
+ }
}
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
index 4ca271b2a..82c7a2ddc 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
@@ -16,26 +16,23 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
-import "./LibFillResults.sol";
-import "./LibOrder.sol";
-import "./LibErrors.sol";
-import "./LibMath.sol";
+import "./libs/LibFillResults.sol";
+import "./libs/LibOrder.sol";
+import "./libs/LibMath.sol";
+import "./libs/LibExchangeErrors.sol";
import "./mixins/MExchangeCore.sol";
import "./mixins/MSettlement.sol";
import "./mixins/MSignatureValidator.sol";
import "./mixins/MTransactions.sol";
-/// @dev Provides MExchangeCore
-/// @dev Consumes MSettlement
-/// @dev Consumes MSignatureValidator
contract MixinExchangeCore is
LibOrder,
LibFillResults,
- LibErrors,
LibMath,
+ LibExchangeErrors,
MExchangeCore,
MSettlement,
MSignatureValidator,
@@ -51,35 +48,19 @@ contract MixinExchangeCore is
// Orders with a salt less than their maker's epoch are considered cancelled
mapping (address => uint256) public makerEpoch;
- event Fill(
- address indexed makerAddress,
- address takerAddress,
- address indexed feeRecipientAddress,
- uint256 makerAssetFilledAmount,
- uint256 takerAssetFilledAmount,
- uint256 makerFeePaid,
- uint256 takerFeePaid,
- bytes32 indexed orderHash,
- bytes makerAssetData,
- bytes takerAssetData
- );
-
- event Cancel(
- address indexed makerAddress,
- address indexed feeRecipientAddress,
- bytes32 indexed orderHash,
- bytes makerAssetData,
- bytes takerAssetData
- );
-
- event CancelUpTo(
- address indexed makerAddress,
- uint256 makerEpoch
- );
-
- /*
- * Core exchange functions
- */
+ /// @dev Cancels all orders reated by sender with a salt less than or equal to the specified salt value.
+ /// @param salt Orders created with a salt less or equal to this value will be cancelled.
+ function cancelOrdersUpTo(uint256 salt)
+ external
+ {
+ uint256 newMakerEpoch = salt + 1; // makerEpoch is initialized to 0, so to cancelUpTo we need salt + 1
+ require(
+ newMakerEpoch > makerEpoch[msg.sender], // epoch must be monotonically increasing
+ INVALID_NEW_MAKER_EPOCH
+ );
+ makerEpoch[msg.sender] = newMakerEpoch;
+ emit CancelUpTo(msg.sender, newMakerEpoch);
+ }
/// @dev Fills the input order.
/// @param order Order struct containing order specifications.
@@ -111,22 +92,40 @@ contract MixinExchangeCore is
// Validate order and maker only if first time seen
// TODO: Read filled and cancelled only once
if (filled[orderHash] == 0) {
- require(order.makerAssetAmount > 0);
- require(order.takerAssetAmount > 0);
- require(isValidSignature(orderHash, order.makerAddress, signature));
+ require(
+ order.makerAssetAmount > 0,
+ GT_ZERO_AMOUNT_REQUIRED
+ );
+ require(
+ order.takerAssetAmount > 0,
+ GT_ZERO_AMOUNT_REQUIRED
+ );
+ require(
+ isValidSignature(orderHash, order.makerAddress, signature),
+ SIGNATURE_VALIDATION_FAILED
+ );
}
// Validate sender is allowed to fill this order
if (order.senderAddress != address(0)) {
- require(order.senderAddress == msg.sender);
+ require(
+ order.senderAddress == msg.sender,
+ INVALID_SENDER
+ );
}
// Validate taker is allowed to fill this order
address takerAddress = getCurrentContextAddress();
if (order.takerAddress != address(0)) {
- require(order.takerAddress == takerAddress);
+ require(
+ order.takerAddress == takerAddress,
+ INVALID_CONTEXT
+ );
}
- require(takerAssetFillAmount > 0);
+ require(
+ takerAssetFillAmount > 0,
+ GT_ZERO_AMOUNT_REQUIRED
+ );
// Validate order expiration
if (block.timestamp >= order.expirationTimeSeconds) {
@@ -173,17 +172,29 @@ contract MixinExchangeCore is
bytes32 orderHash = getOrderHash(order);
// Validate the order
- require(order.makerAssetAmount > 0);
- require(order.takerAssetAmount > 0);
+ require(
+ order.makerAssetAmount > 0,
+ GT_ZERO_AMOUNT_REQUIRED
+ );
+ require(
+ order.takerAssetAmount > 0,
+ GT_ZERO_AMOUNT_REQUIRED
+ );
// Validate sender is allowed to cancel this order
if (order.senderAddress != address(0)) {
- require(order.senderAddress == msg.sender);
+ require(
+ order.senderAddress == msg.sender,
+ INVALID_SENDER
+ );
}
// Validate transaction signed by maker
address makerAddress = getCurrentContextAddress();
- require(order.makerAddress == makerAddress);
+ require(
+ order.makerAddress == makerAddress,
+ INVALID_CONTEXT
+ );
if (block.timestamp >= order.expirationTimeSeconds) {
emit ExchangeError(uint8(Errors.ORDER_EXPIRED), orderHash);
@@ -207,16 +218,6 @@ contract MixinExchangeCore is
return true;
}
- /// @param salt Orders created with a salt less or equal to this value will be cancelled.
- function cancelOrdersUpTo(uint256 salt)
- external
- {
- uint256 newMakerEpoch = salt + 1; // makerEpoch is initialized to 0, so to cancelUpTo we need salt+1
- require(newMakerEpoch > makerEpoch[msg.sender]); // epoch must be monotonically increasing
- makerEpoch[msg.sender] = newMakerEpoch;
- emit CancelUpTo(msg.sender, newMakerEpoch);
- }
-
/// @dev Logs a Fill event with the given arguments.
/// The sole purpose of this function is to get around the stack variable limit.
function emitFillEvent(
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
index cab2ccfb6..30f1bb49b 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
@@ -16,23 +16,24 @@
*/
-pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
+pragma solidity ^0.4.23;
import "./mixins/MSettlement.sol";
import "./mixins/MAssetProxyDispatcher.sol";
-import "./LibOrder.sol";
-import "./LibMath.sol";
-import "../AssetProxy/IAssetProxy.sol";
+import "./libs/LibOrder.sol";
+import "./libs/LibMath.sol";
-/// @dev Provides MixinSettlement
contract MixinSettlement is
LibMath,
MSettlement,
MAssetProxyDispatcher
{
+ // ZRX metadata used for fee transfers.
+ // This will be constant throughout the life of the Exchange contract,
+ // since ZRX will always be transferred via the ERC20 AssetProxy.
bytes internal ZRX_PROXY_DATA;
+ /// @dev Gets the ZRX metadata used for fee transfers.
function zrxProxyData()
external
view
@@ -41,12 +42,20 @@ contract MixinSettlement is
return ZRX_PROXY_DATA;
}
- function MixinSettlement(bytes memory _zrxProxyData)
+ /// TODO: _zrxProxyData should be a constant in production.
+ /// @dev Constructor sets the metadata that will be used for paying ZRX fees.
+ /// @param _zrxProxyData Byte array containing ERC20 proxy id concatenated with address of ZRX.
+ constructor (bytes memory _zrxProxyData)
public
{
ZRX_PROXY_DATA = _zrxProxyData;
}
+ /// @dev Settles an order by transferring assets between counterparties.
+ /// @param order Order struct containing order specifications.
+ /// @param takerAddress Address selling takerAsset and buying makerAsset.
+ /// @param takerAssetFilledAmount The amount of takerAsset that will be transferred to the order's maker.
+ /// @return Amount filled by maker and fees paid by maker/taker.
function settleOrder(
LibOrder.Order memory order,
address takerAddress,
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
index 690a70820..2322625d9 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
@@ -16,29 +16,39 @@
*/
-pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
+pragma solidity ^0.4.23;
import "./mixins/MSignatureValidator.sol";
-import "./ISigner.sol";
-
-/// @dev Provides MSignatureValidator
-contract MixinSignatureValidator is MSignatureValidator {
-
- enum SignatureType {
- Illegal, // Default value
- Invalid,
- Caller,
- Ecrecover,
- EIP712,
- Trezor,
- Contract,
- PreSigned
- }
+import "./interfaces/ISigner.sol";
+import "./libs/LibExchangeErrors.sol";
+import "../../utils/LibBytes/LibBytes.sol";
+
+contract MixinSignatureValidator is
+ LibBytes,
+ LibExchangeErrors,
+ MSignatureValidator
+{
// Mapping of hash => signer => signed
mapping(bytes32 => mapping(address => bool)) preSigned;
+ /// @dev Approves a hash on-chain using any valid signature type.
+ /// After presigning a hash, the preSign signature type will become valid for that hash and signer.
+ /// @param signer Address that should have signed the given hash.
+ /// @param signature Proof that the hash has been signed by signer.
+ function preSign(
+ bytes32 hash,
+ address signer,
+ bytes signature)
+ external
+ {
+ require(
+ isValidSignature(hash, signer, signature),
+ SIGNATURE_VALIDATION_FAILED
+ );
+ preSigned[hash][signer] = true;
+ }
+
/// @dev Verifies that a hash has been signed by the given signer.
/// @param hash Any 32 byte hash.
/// @param signer Address that should have signed the given hash.
@@ -54,7 +64,10 @@ contract MixinSignatureValidator is MSignatureValidator {
{
// TODO: Domain separation: make hash depend on role. (Taker sig should not be valid as maker sig, etc.)
- require(signature.length >= 1);
+ require(
+ signature.length >= 1,
+ INVALID_SIGNATURE_LENGTH
+ );
SignatureType signatureType = SignatureType(uint8(signature[0]));
// Variables are not scoped in Solidity
@@ -69,14 +82,18 @@ contract MixinSignatureValidator is MSignatureValidator {
// it an explicit option. This aids testing and analysis. It is
// also the initialization value for the enum type.
if (signatureType == SignatureType.Illegal) {
- revert();
+ // NOTE: Reason cannot be assigned to a variable because of https://github.com/ethereum/solidity/issues/4051
+ revert("Illegal signature type.");
// Always invalid signature
// Like Illegal, this is always implicitly available and therefore
// offered explicitly. It can be implicitly created by providing
// a correctly formatted but incorrect signature.
} else if (signatureType == SignatureType.Invalid) {
- require(signature.length == 1);
+ require(
+ signature.length == 1,
+ INVALID_SIGNATURE_LENGTH
+ );
isValid = false;
return isValid;
@@ -89,16 +106,22 @@ contract MixinSignatureValidator is MSignatureValidator {
// `Caller` for his own signature. Or A and C can sign and B can
// submit using `Caller`. Having `Caller` allows this flexibility.
} else if (signatureType == SignatureType.Caller) {
- require(signature.length == 1);
+ require(
+ signature.length == 1,
+ INVALID_SIGNATURE_LENGTH
+ );
isValid = signer == msg.sender;
return isValid;
// Signed using web3.eth_sign
} else if (signatureType == SignatureType.Ecrecover) {
- require(signature.length == 66);
+ require(
+ signature.length == 66,
+ INVALID_SIGNATURE_LENGTH
+ );
v = uint8(signature[1]);
- r = get32(signature, 2);
- s = get32(signature, 34);
+ r = readBytes32(signature, 2);
+ s = readBytes32(signature, 34);
recovered = ecrecover(
keccak256("\x19Ethereum Signed Message:\n32", hash),
v,
@@ -110,10 +133,13 @@ contract MixinSignatureValidator is MSignatureValidator {
// Signature using EIP712
} else if (signatureType == SignatureType.EIP712) {
- require(signature.length == 66);
+ require(
+ signature.length == 66,
+ INVALID_SIGNATURE_LENGTH
+ );
v = uint8(signature[1]);
- r = get32(signature, 2);
- s = get32(signature, 34);
+ r = readBytes32(signature, 2);
+ s = readBytes32(signature, 34);
recovered = ecrecover(hash, v, r, s);
isValid = signer == recovered;
return isValid;
@@ -127,10 +153,13 @@ contract MixinSignatureValidator is MSignatureValidator {
// https://github.com/trezor/trezor-mcu/blob/master/firmware/ethereum.c#L602
// https://github.com/trezor/trezor-mcu/blob/master/firmware/crypto.c#L36
} else if (signatureType == SignatureType.Trezor) {
- require(signature.length == 66);
+ require(
+ signature.length == 66,
+ INVALID_SIGNATURE_LENGTH
+ );
v = uint8(signature[1]);
- r = get32(signature, 2);
- s = get32(signature, 34);
+ r = readBytes32(signature, 2);
+ s = readBytes32(signature, 34);
recovered = ecrecover(
keccak256("\x19Ethereum Signed Message:\n\x41", hash),
v,
@@ -156,37 +185,7 @@ contract MixinSignatureValidator is MSignatureValidator {
// that we currently support. In this case returning false
// may lead the caller to incorrectly believe that the
// signature was invalid.)
- revert();
+ // NOTE: Reason cannot be assigned to a variable because of https://github.com/ethereum/solidity/issues/4051
+ revert("Unsupported signature type.");
}
-
- /// @dev Approves a hash on-chain using any valid signature type.
- /// After presigning a hash, the preSign signature type will become valid for that hash and signer.
- /// @param signer Address that should have signed the given hash.
- /// @param signature Proof that the hash has been signed by signer.
- function preSign(
- bytes32 hash,
- address signer,
- bytes signature)
- external
- {
- require(isValidSignature(hash, signer, signature));
- preSigned[hash][signer] = true;
- }
-
- function get32(bytes memory b, uint256 index)
- private pure
- returns (bytes32 result)
- {
- require(b.length >= index + 32);
-
- // Arrays are prefixed by a 256 bit length parameter
- index += 32;
-
- // Read the bytes32 from array memory
- assembly {
- result := mload(add(b, index))
- }
- return result;
- }
-
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol
index 9edb1694f..7f12834a3 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol
@@ -16,12 +16,13 @@
*/
pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
import "./mixins/MSignatureValidator.sol";
import "./mixins/MTransactions.sol";
+import "./libs/LibExchangeErrors.sol";
contract MixinTransactions is
+ LibExchangeErrors,
MSignatureValidator,
MTransactions
{
@@ -56,12 +57,18 @@ contract MixinTransactions is
);
// Validate transaction has not been executed
- require(!transactions[transactionHash]);
+ require(
+ !transactions[transactionHash],
+ DUPLICATE_TRANSACTION_HASH
+ );
// TODO: is SignatureType.Caller necessary if we make this check?
if (signer != msg.sender) {
// Validate signature
- require(isValidSignature(transactionHash, signer, signature));
+ require(
+ isValidSignature(transactionHash, signer, signature),
+ SIGNATURE_VALIDATION_FAILED
+ );
// Set the current transaction signer
currentContextAddress = signer;
@@ -69,7 +76,10 @@ contract MixinTransactions is
// Execute transaction
transactions[transactionHash] = true;
- require(address(this).delegatecall(data));
+ require(
+ address(this).delegatecall(data),
+ TRANSACTION_EXECUTION_FAILED
+ );
// Reset current transaction signer
// TODO: Check if gas is paid when currentContextAddress is already 0.
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
index 105c0f0a0..42517221e 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
@@ -16,21 +16,22 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../utils/LibBytes/LibBytes.sol";
import "./mixins/MExchangeCore.sol";
-import "./LibMath.sol";
-import "./LibOrder.sol";
-import "./LibFillResults.sol";
+import "./libs/LibMath.sol";
+import "./libs/LibOrder.sol";
+import "./libs/LibFillResults.sol";
+import "./libs/LibExchangeErrors.sol";
-/// @dev Consumes MExchangeCore
contract MixinWrapperFunctions is
LibOrder,
LibFillResults,
LibMath,
LibBytes,
+ LibExchangeErrors,
MExchangeCore
{
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
@@ -49,7 +50,10 @@ contract MixinWrapperFunctions is
takerAssetFillAmount,
signature
);
- require(fillResults.takerAssetFilledAmount == takerAssetFillAmount);
+ require(
+ fillResults.takerAssetFilledAmount == takerAssetFillAmount,
+ COMPLETE_FILL_FAILED
+ );
return fillResults;
}
@@ -327,7 +331,11 @@ contract MixinWrapperFunctions is
for (uint256 i = 0; i < orders.length; i++) {
// Token being sold by taker must be the same for each order
- require(areBytesEqual(orders[i].takerAssetData, orders[0].takerAssetData));
+ // TODO: optimize by only using takerAssetData for first order.
+ require(
+ areBytesEqual(orders[i].takerAssetData, orders[0].takerAssetData),
+ ASSET_DATA_MISMATCH
+ );
// Calculate the remaining amount of takerAsset to sell
uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount);
@@ -366,7 +374,11 @@ contract MixinWrapperFunctions is
for (uint256 i = 0; i < orders.length; i++) {
// Token being sold by taker must be the same for each order
- require(areBytesEqual(orders[i].takerAssetData, orders[0].takerAssetData));
+ // TODO: optimize by only using takerAssetData for first order.
+ require(
+ areBytesEqual(orders[i].takerAssetData, orders[0].takerAssetData),
+ ASSET_DATA_MISMATCH
+ );
// Calculate the remaining amount of takerAsset to sell
uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount);
@@ -404,7 +416,11 @@ contract MixinWrapperFunctions is
for (uint256 i = 0; i < orders.length; i++) {
// Token being bought by taker must be the same for each order
- require(areBytesEqual(orders[i].makerAssetData, orders[0].makerAssetData));
+ // TODO: optimize by only using makerAssetData for first order.
+ require(
+ areBytesEqual(orders[i].makerAssetData, orders[0].makerAssetData),
+ ASSET_DATA_MISMATCH
+ );
// Calculate the remaining amount of makerAsset to buy
uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);
@@ -451,7 +467,11 @@ contract MixinWrapperFunctions is
for (uint256 i = 0; i < orders.length; i++) {
// Token being bought by taker must be the same for each order
- require(areBytesEqual(orders[i].makerAssetData, orders[0].makerAssetData));
+ // TODO: optimize by only using makerAssetData for first order.
+ require(
+ areBytesEqual(orders[i].makerAssetData, orders[0].makerAssetData),
+ ASSET_DATA_MISMATCH
+ );
// Calculate the remaining amount of makerAsset to buy
uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol
new file mode 100644
index 000000000..4e4ed6be8
--- /dev/null
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol
@@ -0,0 +1,41 @@
+/*
+
+ 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.23;
+
+contract IAssetProxyDispatcher {
+
+ /// @dev Registers an asset proxy to an asset proxy id.
+ /// An id can only be assigned to a single proxy at a given time.
+ /// @param assetProxyId Id to register`newAssetProxy` under.
+ /// @param newAssetProxy Address of new asset proxy to register, or 0x0 to unset assetProxyId.
+ /// @param oldAssetProxy Existing asset proxy to overwrite, or 0x0 if assetProxyId is currently unused.
+ function registerAssetProxy(
+ uint8 assetProxyId,
+ address newAssetProxy,
+ address oldAssetProxy)
+ external;
+
+ /// @dev Gets an asset proxy.
+ /// @param assetProxyId Id of the asset proxy.
+ /// @return The asset proxy registered to assetProxyId. Returns 0x0 if no proxy is registered.
+ function getAssetProxy(uint8 assetProxyId)
+ external
+ view
+ returns (address);
+}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchange.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchange.sol
new file mode 100644
index 000000000..9fba3491b
--- /dev/null
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchange.sol
@@ -0,0 +1,34 @@
+/*
+
+ 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.23;
+pragma experimental ABIEncoderV2;
+
+import "./IExchangeCore.sol";
+import "./ISignatureValidator.sol";
+import "./IAssetProxyDispatcher.sol";
+import "./ITransactions.sol";
+import "./IWrapperFunctions.sol";
+
+contract IExchange is
+ IWrapperFunctions,
+ IExchangeCore,
+ ISignatureValidator,
+ ITransactions,
+ IAssetProxyDispatcher
+{}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol
new file mode 100644
index 000000000..0f19525ca
--- /dev/null
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol
@@ -0,0 +1,51 @@
+/*
+
+ 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.23;
+pragma experimental ABIEncoderV2;
+
+import "../libs/LibOrder.sol";
+import "../libs/LibFillResults.sol";
+
+contract IExchangeCore {
+
+ /// @dev Cancels all orders reated by sender with a salt less than or equal to the specified salt value.
+ /// @param salt Orders created with a salt less or equal to this value will be cancelled.
+ function cancelOrdersUpTo(uint256 salt)
+ external;
+
+ /// @dev Fills the input order.
+ /// @param order Order struct containing order specifications.
+ /// @param takerAssetFillAmount Desired amount of takerAsset to sell.
+ /// @param signature Proof that order has been created by maker.
+ /// @return Amounts filled and fees paid by maker and taker.
+ function fillOrder(
+ LibOrder.Order memory order,
+ uint256 takerAssetFillAmount,
+ bytes memory signature)
+ public
+ returns (LibFillResults.FillResults memory fillResults);
+
+ /// @dev After calling, the order can not be filled anymore.
+ /// @param order Order struct containing order specifications.
+ /// @return True if the order state changed to cancelled.
+ /// False if the transaction was already cancelled or expired.
+ function cancelOrder(LibOrder.Order memory order)
+ public
+ returns (bool);
+}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol
new file mode 100644
index 000000000..b4a238472
--- /dev/null
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol
@@ -0,0 +1,32 @@
+/*
+
+ 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.23;
+
+contract ISignatureValidator {
+
+ /// @dev Approves a hash on-chain using any valid signature type.
+ /// After presigning a hash, the preSign signature type will become valid for that hash and signer.
+ /// @param signer Address that should have signed the given hash.
+ /// @param signature Proof that the hash has been signed by signer.
+ function preSign(
+ bytes32 hash,
+ address signer,
+ bytes signature)
+ external;
+}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISigner.sol
index d5641a09f..e065cfd8a 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISigner.sol
@@ -16,11 +16,14 @@
*/
-pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
+pragma solidity ^0.4.23;
contract ISigner {
+ /// @dev Verifies that a signature is valid.
+ /// @param hash Message hash that is signed.
+ /// @param signature Proof of signing.
+ /// @return Validity of order signature.
function isValidSignature(
bytes32 hash,
bytes signature)
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol
new file mode 100644
index 000000000..76e4cf2fe
--- /dev/null
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol
@@ -0,0 +1,33 @@
+/*
+
+ 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.23;
+
+contract ITransactions {
+
+ /// @dev Executes an exchange method call in the context of signer.
+ /// @param salt Arbitrary number to ensure uniqueness of transaction hash.
+ /// @param signer Address of transaction signer.
+ /// @param data AbiV2 encoded calldata.
+ /// @param signature Proof of signer transaction by signer.
+ function executeTransaction(
+ uint256 salt,
+ address signer,
+ bytes data,
+ bytes signature)
+ external;
+}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol
new file mode 100644
index 000000000..d23170b1c
--- /dev/null
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol
@@ -0,0 +1,142 @@
+/*
+
+ 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.23;
+pragma experimental ABIEncoderV2;
+
+import "./libs/LibOrder.sol";
+import "./libs/LibFillResults.sol";
+
+contract IWrapperFunctions is
+ LibOrder,
+ LibFillResults,
+ LibMath,
+ LibBytes,
+ LibExchangeErrors,
+ MExchangeCore
+{
+ /// @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.
+ /// @param signature Proof that order has been created by maker.
+ function fillOrKillOrder(
+ LibOrder.LibOrder.Order memory order,
+ uint256 takerAssetFillAmount,
+ bytes memory signature)
+ public
+ returns (LibFillResults.LibFillResults.FillResults memory fillResults);
+
+ /// @dev Fills an order with specified parameters and ECDSA signature.
+ /// Returns false if the transaction would otherwise revert.
+ /// @param order LibOrder.Order struct containing order specifications.
+ /// @param takerAssetFillAmount Desired amount of takerAsset to sell.
+ /// @param signature Proof that order has been created by maker.
+ /// @return Amounts filled and fees paid by maker and taker.
+ function fillOrderNoThrow(
+ LibOrder.Order memory order,
+ uint256 takerAssetFillAmount,
+ bytes memory signature)
+ public
+ returns (LibFillResults.FillResults memory fillResults);
+
+ /// @dev Synchronously executes multiple calls of fillOrder.
+ /// @param orders Array of order specifications.
+ /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.
+ /// @param signatures Proofs that orders have been created by makers.
+ function batchFillOrders(
+ LibOrder.Order[] memory orders,
+ uint256[] memory takerAssetFillAmounts,
+ bytes[] memory signatures)
+ public;
+
+ /// @dev Synchronously executes multiple calls of fillOrKill.
+ /// @param orders Array of order specifications.
+ /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.
+ /// @param signatures Proofs that orders have been created by makers.
+ function batchFillOrKillOrders(
+ LibOrder.Order[] memory orders,
+ uint256[] memory takerAssetFillAmounts,
+ bytes[] memory signatures)
+ public;
+
+ /// @dev Fills an order with specified parameters and ECDSA signature.
+ /// Returns false if the transaction would otherwise revert.
+ /// @param orders Array of order specifications.
+ /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.
+ /// @param signatures Proofs that orders have been created by makers.
+ function batchFillOrdersNoThrow(
+ LibOrder.Order[] memory orders,
+ uint256[] memory takerAssetFillAmounts,
+ bytes[] memory signatures)
+ public;
+
+ /// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker.
+ /// @param orders Array of order specifications.
+ /// @param takerAssetFillAmount Desired amount of takerAsset to sell.
+ /// @param signatures Proofs that orders have been created by makers.
+ /// @return Amounts filled and fees paid by makers and taker.
+ function marketSellOrders(
+ LibOrder.Order[] memory orders,
+ uint256 takerAssetFillAmount,
+ bytes[] memory signatures)
+ public
+ returns (LibFillResults.FillResults memory totalFillResults);
+
+ /// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker.
+ /// Returns false if the transaction would otherwise revert.
+ /// @param orders Array of order specifications.
+ /// @param takerAssetFillAmount Desired amount of takerAsset to sell.
+ /// @param signatures Proofs that orders have been signed by makers.
+ /// @return Amounts filled and fees paid by makers and taker.
+ function marketSellOrdersNoThrow(
+ LibOrder.Order[] memory orders,
+ uint256 takerAssetFillAmount,
+ bytes[] memory signatures)
+ public
+ returns (LibFillResults.FillResults memory totalFillResults);
+
+ /// @dev Synchronously executes multiple calls of fillOrder until total amount of makerAsset is bought by taker.
+ /// @param orders Array of order specifications.
+ /// @param makerAssetFillAmount Desired amount of makerAsset to buy.
+ /// @param signatures Proofs that orders have been signed by makers.
+ /// @return Amounts filled and fees paid by makers and taker.
+ function marketBuyOrders(
+ LibOrder.Order[] memory orders,
+ uint256 makerAssetFillAmount,
+ bytes[] memory signatures)
+ public
+ returns (LibFillResults.FillResults memory totalFillResults);
+
+ /// @dev Synchronously executes multiple fill orders in a single transaction until total amount is bought by taker.
+ /// Returns false if the transaction would otherwise revert.
+ /// @param orders Array of order specifications.
+ /// @param makerAssetFillAmount Desired amount of makerAsset to buy.
+ /// @param signatures Proofs that orders have been signed by makers.
+ /// @return Amounts filled and fees paid by makers and taker.
+ function marketBuyOrdersNoThrow(
+ LibOrder.Order[] memory orders,
+ uint256 makerAssetFillAmount,
+ bytes[] memory signatures)
+ public
+ returns (LibFillResults.FillResults memory totalFillResults);
+
+ /// @dev Synchronously cancels multiple orders in a single transaction.
+ /// @param orders Array of order specifications.
+ function batchCancelOrders(LibOrder.Order[] memory orders)
+ public;
+}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol
new file mode 100644
index 000000000..6ffbdfdca
--- /dev/null
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol
@@ -0,0 +1,58 @@
+/*
+
+ 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.23;
+
+contract LibExchangeErrors {
+
+ // Error Codes
+ enum Errors {
+ ORDER_EXPIRED, // Order has already expired
+ ORDER_FULLY_FILLED, // Order has already been fully filled
+ ORDER_CANCELLED, // Order has already been cancelled
+ ROUNDING_ERROR_TOO_LARGE, // Rounding error too large
+ INSUFFICIENT_BALANCE_OR_ALLOWANCE // Insufficient balance or allowance for token transfer
+ }
+
+ event ExchangeError(uint8 indexed errorId, bytes32 indexed orderHash);
+
+ // Core revert reasons
+ string constant GT_ZERO_AMOUNT_REQUIRED = "Amount must be greater than 0.";
+ string constant SIGNATURE_VALIDATION_FAILED = "Signature validation failed.";
+ string constant INVALID_SENDER = "Invalid `msg.sender`.";
+ string constant INVALID_CONTEXT = "Function called in an invalid context.";
+ string constant INVALID_NEW_MAKER_EPOCH = "Specified salt must be greater than or equal to existing makerEpoch.";
+
+ // Transaction revert reasons
+ string constant DUPLICATE_TRANSACTION_HASH = "Transaction has already been executed.";
+ string constant TRANSACTION_EXECUTION_FAILED = "Transaction execution failed.";
+
+ // Wrapper revert reasons
+ string constant COMPLETE_FILL_FAILED = "Desired fill amount could not be completely filled.";
+ string constant ASSET_DATA_MISMATCH = "Asset data must be the same for each order.";
+
+ // Asset proxy dispatcher revert reasons
+ string constant GT_ZERO_LENGTH_REQUIRED = "Length must be greater than 0.";
+ string constant OLD_ASSET_PROXY_MISMATCH = "Old asset proxy does not match asset proxy at given id.";
+ string constant NEW_ASSET_PROXY_MISMATCH = "New asset proxy id does not match given id.";
+
+ // Signature validator revert reasons
+ string constant INVALID_SIGNATURE_LENGTH = "Invalid signature length.";
+ string constant ILLEGAL_SIGNATURE_TYPE = "Illegal signature type.";
+ string constant UNSUPPORTED_SIGNATURE_TYPE = "Unsupported signature type.";
+}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibFillResults.sol
index 41096f448..3b8f2acf9 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibFillResults.sol
@@ -16,12 +16,13 @@
*/
-pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
+pragma solidity ^0.4.23;
-import "../../utils/SafeMath/SafeMath.sol";
+import "../../../utils/SafeMath/SafeMath.sol";
-contract LibFillResults is SafeMath {
+contract LibFillResults is
+ SafeMath
+{
struct FillResults {
uint256 makerAssetFilledAmount;
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibMath.sol
index 3b553ebbc..b48602d19 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibMath.sol
@@ -16,12 +16,13 @@
*/
-pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
+pragma solidity ^0.4.23;
-import "../../utils/SafeMath/SafeMath.sol";
+import "../../../utils/SafeMath/SafeMath.sol";
-contract LibMath is SafeMath {
+contract LibMath is
+ SafeMath
+{
/// @dev Calculates partial value given a numerator and denominator.
/// @param numerator Numerator.
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol
index df974e177..0fe8c8c96 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol
@@ -16,8 +16,7 @@
*/
-pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
+pragma solidity ^0.4.23;
contract LibOrder {
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
index 0cf750d7d..77ee77797 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
@@ -16,9 +16,13 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
-contract MAssetProxyDispatcher {
+import "../interfaces/IAssetProxyDispatcher.sol";
+
+contract MAssetProxyDispatcher is
+ IAssetProxyDispatcher
+{
// Logs registration of new asset proxy
event AssetProxySet(
@@ -38,23 +42,4 @@ contract MAssetProxyDispatcher {
address to,
uint256 amount)
internal;
-
- /// @dev Registers an asset proxy to an asset proxy id.
- /// An id can only be assigned to a single proxy at a given time.
- /// @param assetProxyId Id to register`newAssetProxy` under.
- /// @param newAssetProxy Address of new asset proxy to register, or 0x0 to unset assetProxyId.
- /// @param oldAssetProxy Existing asset proxy to overwrite, or 0x0 if assetProxyId is currently unused.
- function registerAssetProxy(
- uint8 assetProxyId,
- address newAssetProxy,
- address oldAssetProxy)
- external;
-
- /// @dev Gets an asset proxy.
- /// @param assetProxyId Id of the asset proxy.
- /// @return The asset proxy registered to assetProxyId. Returns 0x0 if no proxy is registered.
- function getAssetProxy(uint8 assetProxyId)
- external
- view
- returns (address);
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol
index 656df079e..5b78e70da 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol
@@ -16,25 +16,51 @@
*/
-pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
+pragma solidity ^0.4.23;
-import "../LibOrder.sol";
-import "../LibFillResults.sol";
+import "../libs/LibOrder.sol";
+import "../libs/LibFillResults.sol";
+import "../interfaces/IExchangeCore.sol";
-contract MExchangeCore {
+contract MExchangeCore is
+ IExchangeCore
+{
- function fillOrder(
- LibOrder.Order memory order,
- uint256 takerAssetFillAmount,
- bytes memory signature)
- public
- returns (LibFillResults.FillResults memory fillResults);
+ // Fill event is emitted whenever an order is filled.
+ event Fill(
+ address indexed makerAddress,
+ address takerAddress,
+ address indexed feeRecipientAddress,
+ uint256 makerAssetFilledAmount,
+ uint256 takerAssetFilledAmount,
+ uint256 makerFeePaid,
+ uint256 takerFeePaid,
+ bytes32 indexed orderHash,
+ bytes makerAssetData,
+ bytes takerAssetData
+ );
+
+ // Cancel event is emitted whenever an individual order is cancelled.
+ event Cancel(
+ address indexed makerAddress,
+ address indexed feeRecipientAddress,
+ bytes32 indexed orderHash,
+ bytes makerAssetData,
+ bytes takerAssetData
+ );
- function cancelOrder(LibOrder.Order memory order)
- public
- returns (bool);
+ // CancelUpTo event is emitted whenever `cancelOrdersUpTo` is executed succesfully.
+ event CancelUpTo(
+ address indexed makerAddress,
+ uint256 makerEpoch
+ );
- function cancelOrdersUpTo(uint256 salt)
- external;
+ /// @dev Logs a Fill event with the given arguments.
+ /// The sole purpose of this function is to get around the stack variable limit.
+ function emitFillEvent(
+ LibOrder.Order memory order,
+ address takerAddress,
+ bytes32 orderHash,
+ LibFillResults.FillResults memory fillResults)
+ internal;
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol
index 0d7e59a9a..5e2edbf99 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol
@@ -16,13 +16,17 @@
*/
-pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
+pragma solidity ^0.4.23;
-import "../LibOrder.sol";
+import "../libs/LibOrder.sol";
contract MSettlement {
+ /// @dev Settles an order by transfering assets between counterparties.
+ /// @param order Order struct containing order specifications.
+ /// @param takerAddress Address selling takerAsset and buying makerAsset.
+ /// @param takerAssetFilledAmount The amount of takerAsset that will be transfered to the order's maker.
+ /// @return Amount filled by maker and fees paid by maker/taker.
function settleOrder(
LibOrder.Order memory order,
address takerAddress,
@@ -33,5 +37,5 @@ contract MSettlement {
uint256 makerFeePaid,
uint256 takerFeePaid
);
-
}
+
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol
index 043a7da9c..ba26c07f6 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol
@@ -16,10 +16,24 @@
*/
-pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
-
-contract MSignatureValidator {
+pragma solidity ^0.4.23;
+
+import "../interfaces/ISignatureValidator.sol";
+
+contract MSignatureValidator is
+ ISignatureValidator
+{
+ // Allowed signature types.
+ enum SignatureType {
+ Illegal, // Default value
+ Invalid,
+ Caller,
+ Ecrecover,
+ EIP712,
+ Trezor,
+ Contract,
+ PreSigned
+ }
/// @dev Verifies that a signature is valid.
/// @param hash Message hash that is signed.
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MTransactions.sol
index 10bfcb035..159ed1527 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MTransactions.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MTransactions.sol
@@ -15,24 +15,13 @@
limitations under the License.
*/
-pragma solidity ^0.4.21;
-pragma experimental ABIEncoderV2;
-
-import "./MSignatureValidator.sol";
-
-contract MTransactions is MSignatureValidator {
-
- /// @dev Executes an exchange method call in the context of signer.
- /// @param salt Arbitrary number to ensure uniqueness of transaction hash.
- /// @param signer Address of transaction signer.
- /// @param data AbiV2 encoded calldata.
- /// @param signature Proof of signer transaction by signer.
- function executeTransaction(
- uint256 salt,
- address signer,
- bytes data,
- bytes signature)
- external;
+pragma solidity ^0.4.23;
+
+import "../interfaces/ITransactions.sol";
+
+contract MTransactions is
+ ITransactions
+{
/// @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/contracts/current/test/DummyERC20Token/DummyERC20Token.sol b/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol
index 2626399c2..ab5311e0c 100644
--- a/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol
+++ b/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol
@@ -16,7 +16,8 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
import "../Mintable/Mintable.sol";
import "../../utils/Ownable/Ownable.sol";
@@ -26,7 +27,7 @@ contract DummyERC20Token is Mintable, Ownable {
string public symbol;
uint256 public decimals;
- function DummyERC20Token(
+ constructor (
string _name,
string _symbol,
uint256 _decimals,
diff --git a/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol b/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol
index 4fbaa6b74..22ebbd3c1 100644
--- a/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol
+++ b/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol
@@ -16,7 +16,9 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
+
import "../../tokens/ERC721Token/ERC721Token.sol";
import "../../utils/Ownable/Ownable.sol";
@@ -30,7 +32,7 @@ contract DummyERC721Token is
* @param name of token
* @param symbol of token
*/
- function DummyERC721Token(
+ constructor (
string name,
string symbol)
public
@@ -47,7 +49,10 @@ contract DummyERC721Token is
public
onlyOwner
{
- require(!exists(tokenId));
+ require(
+ !exists(tokenId),
+ "Token with tokenId already exists."
+ );
_mint(to, tokenId);
}
}
diff --git a/packages/contracts/src/contracts/current/test/Mintable/Mintable.sol b/packages/contracts/src/contracts/current/test/Mintable/Mintable.sol
index 305737b72..fd944f244 100644
--- a/packages/contracts/src/contracts/current/test/Mintable/Mintable.sol
+++ b/packages/contracts/src/contracts/current/test/Mintable/Mintable.sol
@@ -16,7 +16,8 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
import "../../tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol";
import "../../utils/SafeMath/SafeMath.sol";
@@ -29,7 +30,10 @@ contract Mintable is UnlimitedAllowanceToken, SafeMath {
function mint(uint256 _value)
public
{
- require(_value <= 100000000000000000000);
+ require(
+ _value <= 100000000000000000000,
+ "Minting more than 100000000000000000000 is not allowed."
+ );
balances[msg.sender] = safeAdd(_value, balances[msg.sender]);
totalSupply = safeAdd(totalSupply, _value);
}
diff --git a/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol
index 8206b84bd..93ec3cef3 100644
--- a/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol
@@ -16,7 +16,8 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/MixinAssetProxyDispatcher.sol";
diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol
new file mode 100644
index 000000000..1597ff8d5
--- /dev/null
+++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol
@@ -0,0 +1,133 @@
+/*
+
+ 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.23;
+pragma experimental ABIEncoderV2;
+
+import "../../utils/LibBytes/LibBytes.sol";
+
+contract TestLibBytes is
+ LibBytes
+{
+
+ /// @dev Tests equality of two byte arrays.
+ /// @param lhs First byte array to compare.
+ /// @param rhs Second byte array to compare.
+ /// @return True if arrays are the same. False otherwise.
+ function publicAreBytesEqual(bytes memory lhs, bytes memory rhs)
+ public
+ pure
+ returns (bool equal)
+ {
+ equal = areBytesEqual(lhs, rhs);
+ return equal;
+ }
+
+ /// @dev Reads an address from a position in a byte array.
+ /// @param b Byte array containing an address.
+ /// @param index Index in byte array of address.
+ /// @return address from byte array.
+ function publicReadAddress(
+ bytes memory b,
+ uint256 index)
+ public
+ pure
+ returns (address result)
+ {
+ result = readAddress(b, index);
+ return result;
+ }
+
+ /// @dev Writes an address into a specific position in a byte array.
+ /// @param b Byte array to insert address into.
+ /// @param index Index in byte array of address.
+ /// @param input Address to put into byte array.
+ function publicWriteAddress(
+ bytes memory b,
+ uint256 index,
+ address input)
+ public
+ pure
+ returns (bytes memory)
+ {
+ writeAddress(b, index, input);
+ return b;
+ }
+
+ /// @dev Reads a bytes32 value from a position in a byte array.
+ /// @param b Byte array containing a bytes32 value.
+ /// @param index Index in byte array of bytes32 value.
+ /// @return bytes32 value from byte array.
+ function publicReadBytes32(
+ bytes memory b,
+ uint256 index)
+ public
+ pure
+ returns (bytes32 result)
+ {
+ result = readBytes32(b, index);
+ return result;
+ }
+
+ /// @dev Writes a bytes32 into a specific position in a byte array.
+ /// @param b Byte array to insert <input> into.
+ /// @param index Index in byte array of <input>.
+ /// @param input bytes32 to put into byte array.
+ function publicWriteBytes32(
+ bytes memory b,
+ uint256 index,
+ bytes32 input)
+ public
+ pure
+ returns (bytes memory)
+ {
+ writeBytes32(b, index, input);
+ return b;
+ }
+
+ /// @dev Reads a uint256 value from a position in a byte array.
+ /// @param b Byte array containing a uint256 value.
+ /// @param index Index in byte array of uint256 value.
+ /// @return uint256 value from byte array.
+ function publicReadUint256(
+ bytes memory b,
+ uint256 index)
+ public
+ pure
+ returns (uint256 result)
+ {
+ result = readUint256(b, index);
+ return result;
+ }
+
+ /// @dev Writes a uint256 into a specific position in a byte array.
+ /// @param b Byte array to insert <input> into.
+ /// @param index Index in byte array of <input>.
+ /// @param input uint256 to put into byte array.
+ function publicWriteUint256(
+ bytes memory b,
+ uint256 index,
+ uint256 input)
+ public
+ pure
+ returns (bytes memory)
+ {
+ writeUint256(b, index, input);
+ return b;
+ }
+}
diff --git a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol
index a5b327a90..0dc7785b2 100644
--- a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol
+++ b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol
@@ -16,12 +16,12 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
-import "../../protocol/Exchange/LibMath.sol";
-import "../../protocol/Exchange/LibOrder.sol";
-import "../../protocol/Exchange/LibFillResults.sol";
+import "../../protocol/Exchange/libs/LibMath.sol";
+import "../../protocol/Exchange/libs/LibOrder.sol";
+import "../../protocol/Exchange/libs/LibFillResults.sol";
contract TestLibs is
LibMath,
diff --git a/packages/contracts/src/contracts/current/test/TestSignatureValidator/TestSignatureValidator.sol b/packages/contracts/src/contracts/current/test/TestSignatureValidator/TestSignatureValidator.sol
index 4ba04b64e..20202cd7b 100644
--- a/packages/contracts/src/contracts/current/test/TestSignatureValidator/TestSignatureValidator.sol
+++ b/packages/contracts/src/contracts/current/test/TestSignatureValidator/TestSignatureValidator.sol
@@ -16,7 +16,7 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/MixinSignatureValidator.sol";
diff --git a/packages/contracts/src/contracts/current/tokens/ERC20Token/ERC20Token.sol b/packages/contracts/src/contracts/current/tokens/ERC20Token/ERC20Token.sol
index 13ceeb2c6..6497d3c7a 100644
--- a/packages/contracts/src/contracts/current/tokens/ERC20Token/ERC20Token.sol
+++ b/packages/contracts/src/contracts/current/tokens/ERC20Token/ERC20Token.sol
@@ -16,17 +16,34 @@
*/
-pragma solidity ^0.4.18;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
import "./IERC20Token.sol";
contract ERC20Token is IERC20Token {
+ string constant INSUFFICIENT_BALANCE = "Insufficient balance to complete transfer.";
+ string constant INSUFFICIENT_ALLOWANCE = "Insufficient allowance to complete transfer.";
+ string constant OVERFLOW = "Transfer would result in an overflow.";
+
+ mapping (address => uint256) balances;
+ mapping (address => mapping (address => uint256)) allowed;
+
+ uint256 public totalSupply;
+
function transfer(address _to, uint256 _value)
public
returns (bool)
{
- require(balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]);
+ require(
+ balances[msg.sender] >= _value,
+ INSUFFICIENT_BALANCE
+ );
+ require(
+ balances[_to] + _value >= balances[_to],
+ OVERFLOW
+ );
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
@@ -37,7 +54,18 @@ contract ERC20Token is IERC20Token {
public
returns (bool)
{
- require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value >= balances[_to]);
+ require(
+ balances[_from] >= _value,
+ INSUFFICIENT_BALANCE
+ );
+ require(
+ allowed[_from][msg.sender] >= _value,
+ INSUFFICIENT_ALLOWANCE
+ );
+ require(
+ balances[_to] + _value >= balances[_to],
+ OVERFLOW
+ );
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
@@ -68,8 +96,5 @@ contract ERC20Token is IERC20Token {
{
return allowed[_owner][_spender];
}
-
- mapping (address => uint256) balances;
- mapping (address => mapping (address => uint256)) allowed;
- uint256 public totalSupply;
}
+
diff --git a/packages/contracts/src/contracts/current/tokens/ERC20Token/IERC20Token.sol b/packages/contracts/src/contracts/current/tokens/ERC20Token/IERC20Token.sol
index 0159b31e8..537f5a83d 100644
--- a/packages/contracts/src/contracts/current/tokens/ERC20Token/IERC20Token.sol
+++ b/packages/contracts/src/contracts/current/tokens/ERC20Token/IERC20Token.sol
@@ -16,11 +16,12 @@
*/
-pragma solidity ^0.4.18;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
contract IERC20Token {
- /// @notice send `_value` token to `_to` from `msg.sender`
+ /// @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
@@ -28,7 +29,7 @@ contract IERC20Token {
public
returns (bool);
- /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
+ /// @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
@@ -61,10 +62,12 @@ contract IERC20Token {
event Transfer(
address indexed _from,
address indexed _to,
- uint256 _value);
+ uint256 _value
+ );
event Approval(
address indexed _owner,
address indexed _spender,
- uint256 _value);
+ uint256 _value
+ );
}
diff --git a/packages/contracts/src/contracts/current/tokens/ERC721Token/ERC721Token.sol b/packages/contracts/src/contracts/current/tokens/ERC721Token/ERC721Token.sol
index 3bf064c3f..b3493bc99 100644
--- a/packages/contracts/src/contracts/current/tokens/ERC721Token/ERC721Token.sol
+++ b/packages/contracts/src/contracts/current/tokens/ERC721Token/ERC721Token.sol
@@ -23,7 +23,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
import "./IERC721Token.sol";
import "./IERC721Receiver.sol";
diff --git a/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Receiver.sol b/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Receiver.sol
index 26871cc89..3484bf824 100644
--- a/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Receiver.sol
+++ b/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Receiver.sol
@@ -23,7 +23,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
/**
* @title ERC721 token receiver interface
diff --git a/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Token.sol b/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Token.sol
index 73741ed53..81e1b97af 100644
--- a/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Token.sol
+++ b/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Token.sol
@@ -23,7 +23,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
/**
* @title ERC721 Non-Fungible Token Standard basic interface
diff --git a/packages/contracts/src/contracts/current/tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol b/packages/contracts/src/contracts/current/tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol
index be774e374..395e5d356 100644
--- a/packages/contracts/src/contracts/current/tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol
+++ b/packages/contracts/src/contracts/current/tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol
@@ -16,9 +16,10 @@
*/
-pragma solidity ^0.4.18;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
-import { ERC20Token } from "../ERC20Token/ERC20Token.sol";
+import "../ERC20Token/ERC20Token.sol";
contract UnlimitedAllowanceToken is ERC20Token {
@@ -34,7 +35,18 @@ contract UnlimitedAllowanceToken is ERC20Token {
returns (bool)
{
uint256 allowance = allowed[_from][msg.sender];
- require(balances[_from] >= _value && allowance >= _value && balances[_to] + _value >= balances[_to]);
+ require(
+ balances[_from] >= _value,
+ INSUFFICIENT_BALANCE
+ );
+ require(
+ allowance >= _value,
+ INSUFFICIENT_ALLOWANCE
+ );
+ require(
+ balances[_to] + _value >= balances[_to],
+ OVERFLOW
+ );
balances[_to] += _value;
balances[_from] -= _value;
if (allowance < MAX_UINT) {
diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol
index ce107f306..3c5531e35 100644
--- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol
+++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol
@@ -16,16 +16,21 @@
*/
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
contract LibBytes {
+ // Revert reasons
+ string constant GTE_20_LENGTH_REQUIRED = "Length must be greater than or equal to 20.";
+ string constant GTE_32_LENGTH_REQUIRED = "Length must be greater than or equal to 32.";
+
/// @dev Tests equality of two byte arrays.
/// @param lhs First byte array to compare.
/// @param rhs Second byte array to compare.
/// @return True if arrays are the same. False otherwise.
function areBytesEqual(bytes memory lhs, bytes memory rhs)
- public pure
+ internal
+ pure
returns (bool equal)
{
assembly {
@@ -58,10 +63,14 @@ contract LibBytes {
function readAddress(
bytes memory b,
uint256 index)
- public pure
+ internal
+ pure
returns (address result)
{
- require(b.length >= index + 20); // 20 is length of address
+ require(
+ b.length >= index + 20, // 20 is length of address
+ GTE_20_LENGTH_REQUIRED
+ );
// Add offset to index:
// 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
@@ -86,9 +95,13 @@ contract LibBytes {
bytes memory b,
uint256 index,
address input)
- public pure
+ internal
+ pure
{
- require(b.length >= index + 20); // 20 is length of address
+ require(
+ b.length >= index + 20, // 20 is length of address
+ GTE_20_LENGTH_REQUIRED
+ );
// Add offset to index:
// 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
@@ -119,10 +132,14 @@ contract LibBytes {
function readBytes32(
bytes memory b,
uint256 index)
- public pure
+ internal
+ pure
returns (bytes32 result)
{
- require(b.length >= index + 32);
+ require(
+ b.length >= index + 32,
+ GTE_32_LENGTH_REQUIRED
+ );
// Arrays are prefixed by a 256 bit length parameter
index += 32;
@@ -142,9 +159,13 @@ contract LibBytes {
bytes memory b,
uint256 index,
bytes32 input)
- public pure
+ internal
+ pure
{
- require(b.length >= index + 32);
+ require(
+ b.length >= index + 32,
+ GTE_32_LENGTH_REQUIRED
+ );
// Arrays are prefixed by a 256 bit length parameter
index += 32;
@@ -162,7 +183,8 @@ contract LibBytes {
function readUint256(
bytes memory b,
uint256 index)
- public pure
+ internal
+ pure
returns (uint256 result)
{
return uint256(readBytes32(b, index));
@@ -176,7 +198,8 @@ contract LibBytes {
bytes memory b,
uint256 index,
uint256 input)
- public pure
+ internal
+ pure
{
writeBytes32(b, index, bytes32(input));
}
diff --git a/packages/contracts/src/contracts/current/utils/Ownable/IOwnable.sol b/packages/contracts/src/contracts/current/utils/Ownable/IOwnable.sol
index 7784a7ba9..63b04945f 100644
--- a/packages/contracts/src/contracts/current/utils/Ownable/IOwnable.sol
+++ b/packages/contracts/src/contracts/current/utils/Ownable/IOwnable.sol
@@ -1,4 +1,5 @@
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
/*
* Ownable
diff --git a/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol b/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol
index 91a5cb7ae..933aa168a 100644
--- a/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol
+++ b/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol
@@ -1,4 +1,5 @@
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
/*
* Ownable
@@ -7,19 +8,22 @@ pragma solidity ^0.4.21;
* Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.
*/
-import "../Ownable/IOwnable.sol";
+import "./IOwnable.sol";
contract Ownable is IOwnable {
address public owner;
- function Ownable()
+ constructor ()
public
{
owner = msg.sender;
}
modifier onlyOwner() {
- require(msg.sender == owner);
+ require(
+ msg.sender == owner,
+ "Only contract owner is allowed to call this method."
+ );
_;
}
diff --git a/packages/contracts/src/contracts/current/utils/SafeMath/SafeMath.sol b/packages/contracts/src/contracts/current/utils/SafeMath/SafeMath.sol
index 7bd9c2122..1ab27eebc 100644
--- a/packages/contracts/src/contracts/current/utils/SafeMath/SafeMath.sol
+++ b/packages/contracts/src/contracts/current/utils/SafeMath/SafeMath.sol
@@ -1,4 +1,5 @@
-pragma solidity ^0.4.21;
+pragma solidity ^0.4.23;
+pragma experimental ABIEncoderV2;
contract SafeMath {
function safeMul(uint a, uint b)
diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts
index 6f9aeda94..2200e09f3 100644
--- a/packages/contracts/src/utils/types.ts
+++ b/packages/contracts/src/utils/types.ts
@@ -99,7 +99,7 @@ export enum ContractName {
ERC20Proxy = 'ERC20Proxy',
ERC721Proxy = 'ERC721Proxy',
DummyERC721Token = 'DummyERC721Token',
- LibBytes = 'LibBytes',
+ TestLibBytes = 'TestLibBytes',
Authorizable = 'Authorizable',
}