Update contracts with revert reasons and constructor keyword

This commit is contained in:
Amir Bandeali
2018-05-02 14:14:17 -07:00
parent 853b5e1b72
commit c84be8ddb3
42 changed files with 410 additions and 181 deletions

View File

@@ -16,12 +16,14 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../utils/Authorizable/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.

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "./mixins/MAssetProxy.sol";
@@ -25,8 +25,8 @@ import "../../utils/Authorizable/Authorizable.sol";
contract MixinAssetProxy is
IAssetProxy,
MAssetProxy,
Authorizable
Authorizable,
MAssetProxy
{
/// @dev Transfers assets. Either succeeds or throws.

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
contract MAssetProxy {

View File

@@ -16,10 +16,9 @@
*/
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";
@@ -29,8 +28,14 @@ contract ERC20Proxy is
MixinAssetProxy
{
// 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 +49,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.

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../../utils/LibBytes/LibBytes.sol";
@@ -28,8 +28,14 @@ contract ERC721Proxy is
MixinAssetProxy
{
// 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 +49,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);

View File

@@ -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()

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
contract ISigner {

View File

@@ -1,35 +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 LibErrors {
// 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);
}

View File

@@ -0,0 +1,59 @@
/*
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;
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 GREATER_THAN_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 GREATER_THAN_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.";
}

View File

@@ -16,12 +16,14 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../utils/SafeMath/SafeMath.sol";
contract LibFillResults is SafeMath {
contract LibFillResults is
SafeMath
{
struct FillResults {
uint256 makerAssetFilledAmount;

View File

@@ -16,12 +16,14 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
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.

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
contract LibOrder {

View File

@@ -16,13 +16,16 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../utils/Ownable/Ownable.sol";
import "../AssetProxy/IAssetProxy.sol";
import "./LibExchangeErrors.sol";
import "./mixins/MAssetProxyDispatcher.sol";
contract MixinAssetProxyDispatcher is
LibExchangeErrors,
Ownable,
MAssetProxyDispatcher
{
@@ -43,8 +46,11 @@ contract MixinAssetProxyDispatcher is
{
// Do nothing if no amount should be transferred.
if (amount > 0) {
// Lookup asset proxy.
require(assetMetadata.length >= 1);
// Lookup asset proxy
require(
assetMetadata.length >= 1,
GREATER_THAN_ZERO_LENGTH_REQUIRED
);
uint8 assetProxyId = uint8(assetMetadata[0]);
IAssetProxy assetProxy = assetProxies[assetProxyId];
@@ -65,15 +71,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 +101,7 @@ contract MixinAssetProxyDispatcher is
view
returns (address)
{
IAssetProxy assetProxy = assetProxies[assetProxyId];
return address(assetProxy);
address assetProxy = address(assetProxies[assetProxyId]);
return assetProxy;
}
}

View File

@@ -16,13 +16,13 @@
*/
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 "./LibExchangeErrors.sol";
import "./mixins/MExchangeCore.sol";
import "./mixins/MSettlement.sol";
import "./mixins/MSignatureValidator.sol";
@@ -34,8 +34,8 @@ import "./mixins/MTransactions.sol";
contract MixinExchangeCore is
LibOrder,
LibFillResults,
LibErrors,
LibMath,
LibExchangeErrors,
MExchangeCore,
MSettlement,
MSignatureValidator,
@@ -111,22 +111,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,
GREATER_THAN_ZERO_AMOUNT_REQUIRED
);
require(
order.takerAssetAmount > 0,
GREATER_THAN_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,
GREATER_THAN_ZERO_AMOUNT_REQUIRED
);
// Validate order expiration
if (block.timestamp >= order.expirationTimeSeconds) {
@@ -173,17 +191,29 @@ contract MixinExchangeCore is
bytes32 orderHash = getOrderHash(order);
// Validate the order
require(order.makerAssetAmount > 0);
require(order.takerAssetAmount > 0);
require(
order.makerAssetAmount > 0,
GREATER_THAN_ZERO_AMOUNT_REQUIRED
);
require(
order.takerAssetAmount > 0,
GREATER_THAN_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);
@@ -211,8 +241,11 @@ contract MixinExchangeCore is
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
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);
}

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "./mixins/MSettlement.sol";
@@ -41,7 +41,7 @@ contract MixinSettlement is
return ZRX_PROXY_DATA;
}
function MixinSettlement(bytes memory _zrxProxyData)
constructor (bytes memory _zrxProxyData)
public
{
ZRX_PROXY_DATA = _zrxProxyData;

View File

@@ -16,15 +16,20 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "./mixins/MSignatureValidator.sol";
import "./ISigner.sol";
import "./LibExchangeErrors.sol";
import "../../utils/LibBytes/LibBytes.sol";
/// @dev Provides MSignatureValidator
contract MixinSignatureValidator is MSignatureValidator {
contract MixinSignatureValidator is
LibBytes,
LibExchangeErrors,
MSignatureValidator
{
enum SignatureType {
Illegal, // Default value
Invalid,
@@ -54,7 +59,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 +77,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 +101,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 +128,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 +148,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,7 +180,8 @@ 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.
@@ -169,24 +194,10 @@ contract MixinSignatureValidator is MSignatureValidator {
bytes signature)
external
{
require(isValidSignature(hash, signer, signature));
require(
isValidSignature(hash, signer, signature),
SIGNATURE_VALIDATION_FAILED
);
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;
}
}

View File

@@ -20,8 +20,10 @@ pragma experimental ABIEncoderV2;
import "./mixins/MSignatureValidator.sol";
import "./mixins/MTransactions.sol";
import "./LibExchangeErrors.sol";
contract MixinTransactions is
LibExchangeErrors,
MSignatureValidator,
MTransactions
{
@@ -56,12 +58,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 +77,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.

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../utils/LibBytes/LibBytes.sol";
@@ -24,6 +24,7 @@ import "./mixins/MExchangeCore.sol";
import "./LibMath.sol";
import "./LibOrder.sol";
import "./LibFillResults.sol";
import "./LibExchangeErrors.sol";
/// @dev Consumes MExchangeCore
contract MixinWrapperFunctions is
@@ -31,6 +32,7 @@ contract MixinWrapperFunctions is
LibFillResults,
LibMath,
LibBytes,
LibExchangeErrors,
MExchangeCore
{
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
@@ -49,7 +51,10 @@ contract MixinWrapperFunctions is
takerAssetFillAmount,
signature
);
require(fillResults.takerAssetFilledAmount == takerAssetFillAmount);
require(
fillResults.takerAssetFilledAmount == takerAssetFillAmount,
COMPLETE_FILL_FAILED
);
return fillResults;
}
@@ -327,7 +332,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 +375,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 +417,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 +468,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);

View File

@@ -16,7 +16,8 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
contract MAssetProxyDispatcher {

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../LibOrder.sol";

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../LibOrder.sol";
@@ -33,5 +33,5 @@ contract MSettlement {
uint256 makerFeePaid,
uint256 takerFeePaid
);
}

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
contract MSignatureValidator {

View File

@@ -15,12 +15,10 @@
limitations under the License.
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "./MSignatureValidator.sol";
contract MTransactions is MSignatureValidator {
contract MTransactions {
/// @dev Executes an exchange method call in the context of signer.
/// @param salt Arbitrary number to ensure uniqueness of transaction hash.

View File

@@ -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,

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -16,7 +16,8 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/MixinAssetProxyDispatcher.sol";

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/LibMath.sol";

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/MixinSignatureValidator.sol";

View File

@@ -16,7 +16,8 @@
*/
pragma solidity ^0.4.18;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "./IERC20Token.sol";
@@ -26,7 +27,14 @@ contract ERC20Token is IERC20Token {
public
returns (bool)
{
require(balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]);
require(
balances[msg.sender] >= _value,
"Insufficient balance to complete transfer."
);
require(
balances[_to] + _value >= balances[_to],
"Transfer would result in an overflow."
);
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
@@ -37,7 +45,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 to complete transfer."
);
require(
allowed[_from][msg.sender] >= _value,
"Insufficient allowance to complete transfer."
);
require(
balances[_to] + _value >= balances[_to],
"Transfer would result in an overflow."
);
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;

View File

@@ -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
);
}

View File

@@ -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";

View File

@@ -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

View File

@@ -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

View File

@@ -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 to complete transfer."
);
require(
allowance >= _value,
"Insufficient allowance to complete transfer."
);
require(
balances[_to] + _value >= balances[_to],
"Transfer would result in an overflow."
);
balances[_to] += _value;
balances[_from] -= _value;
if (allowance < MAX_UINT) {

View File

@@ -16,7 +16,8 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "./IAuthorizable.sol";
import "../Ownable/Ownable.sol";
@@ -28,17 +29,26 @@ contract Authorizable is
/// @dev Only authorized addresses can invoke functions with this modifier.
modifier onlyAuthorized {
require(authorized[msg.sender]);
require(
authorized[msg.sender],
"Sender not authorized to call this method."
);
_;
}
modifier targetAuthorized(address target) {
require(authorized[target]);
require(
authorized[target],
"Target address not authorized to call this method."
);
_;
}
modifier targetNotAuthorized(address target) {
require(!authorized[target]);
require(
!authorized[target],
"Target must not already be authorized to call this method."
);
_;
}
@@ -85,8 +95,14 @@ contract Authorizable is
function removeAuthorizedAddressAtIndex(address target, uint256 index)
public
{
require(index < authorities.length);
require(authorities[index] == target);
require(
index < authorities.length,
"Specified index is out of bounds."
);
require(
authorities[index] == target,
"Address found at index does not match target address."
);
delete authorized[target];
authorities[index] = authorities[authorities.length - 1];
authorities.length -= 1;

View File

@@ -16,7 +16,8 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
contract IAuthorizable {
@@ -44,9 +45,11 @@ contract IAuthorizable {
event AuthorizedAddressAdded(
address indexed target,
address indexed caller);
address indexed caller
);
event AuthorizedAddressRemoved(
address indexed target,
address indexed caller);
address indexed caller
);
}

View File

@@ -16,7 +16,8 @@
*/
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
contract LibBytes {
@@ -61,7 +62,10 @@ contract LibBytes {
public pure
returns (address result)
{
require(b.length >= index + 20); // 20 is length of address
require(
b.length >= index + 20, // 20 is length of address
"Cannot read address from byte array shorter than 20 bytes."
);
// Add offset to index:
// 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
@@ -88,7 +92,10 @@ contract LibBytes {
address input)
public pure
{
require(b.length >= index + 20); // 20 is length of address
require(
b.length >= index + 20, // 20 is length of address
"Cannot write address to byte array shorter than 20 bytes."
);
// Add offset to index:
// 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
@@ -122,7 +129,10 @@ contract LibBytes {
public pure
returns (bytes32 result)
{
require(b.length >= index + 32);
require(
b.length >= index + 32,
"Cannot read 32 bytes from byte array shorter than 32 bytes."
);
// Arrays are prefixed by a 256 bit length parameter
index += 32;
@@ -144,7 +154,10 @@ contract LibBytes {
bytes32 input)
public pure
{
require(b.length >= index + 32);
require(
b.length >= index + 32,
"Cannot write 32 bytes to byte array shorter than 32 bytes."
);
// Arrays are prefixed by a 256 bit length parameter
index += 32;

View File

@@ -1,4 +1,5 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
/*
* Ownable

View File

@@ -1,4 +1,5 @@
pragma solidity ^0.4.21;
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
/*
* Ownable
@@ -12,14 +13,17 @@ import "../Ownable/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."
);
_;
}

View File

@@ -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)