From c84be8ddb350d17575e4bb6824fc195e590419fa Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Wed, 2 May 2018 14:14:17 -0700 Subject: Update contracts with revert reasons and constructor keyword --- packages/contracts/package.json | 2 +- .../current/protocol/AssetProxy/IAssetProxy.sol | 6 +- .../protocol/AssetProxy/MixinAssetProxy.sol | 6 +- .../protocol/AssetProxy/mixins/MAssetProxy.sol | 2 +- .../protocol/AssetProxy/proxies/ERC20Proxy.sol | 24 +++++-- .../protocol/AssetProxy/proxies/ERC721Proxy.sol | 25 +++++-- .../current/protocol/Exchange/Exchange.sol | 4 +- .../current/protocol/Exchange/ISigner.sol | 2 +- .../current/protocol/Exchange/LibErrors.sol | 35 ---------- .../protocol/Exchange/LibExchangeErrors.sol | 59 ++++++++++++++++ .../current/protocol/Exchange/LibFillResults.sol | 6 +- .../current/protocol/Exchange/LibMath.sol | 6 +- .../current/protocol/Exchange/LibOrder.sol | 2 +- .../Exchange/MixinAssetProxyDispatcher.sol | 28 +++++--- .../protocol/Exchange/MixinExchangeCore.sol | 63 +++++++++++++---- .../current/protocol/Exchange/MixinSettlement.sol | 4 +- .../protocol/Exchange/MixinSignatureValidator.sol | 81 ++++++++++++---------- .../protocol/Exchange/MixinTransactions.sol | 17 ++++- .../protocol/Exchange/MixinWrapperFunctions.sol | 33 +++++++-- .../Exchange/mixins/MAssetProxyDispatcher.sol | 3 +- .../protocol/Exchange/mixins/MExchangeCore.sol | 2 +- .../protocol/Exchange/mixins/MSettlement.sol | 4 +- .../Exchange/mixins/MSignatureValidator.sol | 2 +- .../protocol/Exchange/mixins/MTransactions.sol | 6 +- .../test/DummyERC20Token/DummyERC20Token.sol | 5 +- .../test/DummyERC721Token/DummyERC721Token.sol | 11 ++- .../contracts/current/test/Mintable/Mintable.sol | 8 ++- .../TestAssetProxyDispatcher.sol | 3 +- .../contracts/current/test/TestLibs/TestLibs.sol | 2 +- .../TestSignatureValidator.sol | 2 +- .../current/tokens/ERC20Token/ERC20Token.sol | 25 ++++++- .../current/tokens/ERC20Token/IERC20Token.sol | 13 ++-- .../current/tokens/ERC721Token/ERC721Token.sol | 2 +- .../current/tokens/ERC721Token/IERC721Receiver.sol | 2 +- .../current/tokens/ERC721Token/IERC721Token.sol | 2 +- .../UnlimitedAllowanceToken.sol | 18 ++++- .../current/utils/Authorizable/Authorizable.sol | 28 ++++++-- .../current/utils/Authorizable/IAuthorizable.sol | 9 ++- .../contracts/current/utils/LibBytes/LibBytes.sol | 23 ++++-- .../contracts/current/utils/Ownable/IOwnable.sol | 3 +- .../contracts/current/utils/Ownable/Ownable.sol | 10 ++- .../contracts/current/utils/SafeMath/SafeMath.sol | 3 +- 42 files changed, 410 insertions(+), 181 deletions(-) delete mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/LibErrors.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/LibExchangeErrors.sol (limited to 'packages') diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 410735359..540846731 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -18,7 +18,7 @@ "compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846", "compile": - "node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --contracts-dir src/contracts --artifacts-dir ../migrations/src/artifacts", + "node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --should-optimize true --contracts-dir src/contracts --artifacts-dir ../migrations/src/artifacts", "clean": "shx rm -rf ./lib ./src/contract_wrappers/generated", "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'", diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol index df993a0ab..7675d684b 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol @@ -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. diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol index 23dce6a8b..b96c84582 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol @@ -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. 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..d1276a61c 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.4.21; +pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; contract MAssetProxy { diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC20Proxy.sol index 713e8a6e6..7e9b41f33 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC20Proxy.sol @@ -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. diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol index 6a4475d48..4d52893b0 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol @@ -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); 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/ISigner.sol b/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol index d5641a09f..d604a1aec 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.4.21; +pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; contract ISigner { diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibErrors.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibErrors.sol deleted file mode 100644 index 55160ad5b..000000000 --- a/packages/contracts/src/contracts/current/protocol/Exchange/LibErrors.sol +++ /dev/null @@ -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); - -} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibExchangeErrors.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibExchangeErrors.sol new file mode 100644 index 000000000..cbd6cac29 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/Exchange/LibExchangeErrors.sol @@ -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."; +} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol index 41096f448..e26da2bce 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol @@ -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; diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol index 3b553ebbc..761c300a1 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol @@ -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. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol index df974e177..32554f45b 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.4.21; +pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; contract LibOrder { diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol index b73c6ca90..eb423ad28 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol @@ -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; } } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index 4ca271b2a..d764d7a4f 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -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); } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol index cab2ccfb6..3e805aa8e 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol @@ -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; diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol index 690a70820..3091adcaf 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol @@ -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; - } - } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol index 9edb1694f..670d454d6 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol @@ -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. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol index 105c0f0a0..0cfcf0c25 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol @@ -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); 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..df2250cd9 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol @@ -16,7 +16,8 @@ */ -pragma solidity ^0.4.21; +pragma solidity ^0.4.23; +pragma experimental ABIEncoderV2; contract MAssetProxyDispatcher { 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..6bd8fd9b6 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.4.21; +pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; import "../LibOrder.sol"; 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..9cb2afeb0 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol @@ -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 ); - } + 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..2b8ae78dd 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.4.21; +pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; contract MSignatureValidator { 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..3d167c0bc 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MTransactions.sol @@ -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. 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/TestLibs/TestLibs.sol b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol index a5b327a90..5a16ae947 100644 --- a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol +++ b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.4.21; +pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; import "../../protocol/Exchange/LibMath.sol"; 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..27e7fa355 100644 --- a/packages/contracts/src/contracts/current/tokens/ERC20Token/ERC20Token.sol +++ b/packages/contracts/src/contracts/current/tokens/ERC20Token/ERC20Token.sol @@ -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; 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..4aedced49 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 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) { diff --git a/packages/contracts/src/contracts/current/utils/Authorizable/Authorizable.sol b/packages/contracts/src/contracts/current/utils/Authorizable/Authorizable.sol index f6032f889..6b84d7aca 100644 --- a/packages/contracts/src/contracts/current/utils/Authorizable/Authorizable.sol +++ b/packages/contracts/src/contracts/current/utils/Authorizable/Authorizable.sol @@ -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; diff --git a/packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol b/packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol index 10c01c6fe..b14cfba22 100644 --- a/packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol +++ b/packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol @@ -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 + ); } diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index ce107f306..cff780ba4 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -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; 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..e9b4d6a3b 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 @@ -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." + ); _; } 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) -- cgit v1.2.3 From bbf088d903b0afd371e3007b5a81f2e84b28bac3 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 4 May 2018 17:00:24 -0700 Subject: Make LibBytes methods internal, add TestLibBytes --- packages/contracts/package.json | 4 +- .../current/test/TestLibBytes/TestLibBytes.sol | 133 +++++++++++++++++++++ .../contracts/current/utils/LibBytes/LibBytes.sol | 22 ++-- packages/contracts/src/utils/types.ts | 2 +- packages/contracts/test/libraries/lib_bytes.ts | 52 ++++---- 5 files changed, 180 insertions(+), 33 deletions(-) create mode 100644 packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol (limited to 'packages') diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 540846731..48019fe8c 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -30,9 +30,9 @@ }, "config": { "abis": - "../migrations/src/artifacts/@(DummyERC20Token|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|TestAssetProxyDispatcher|TestLibs|TestSignatureValidator|ERC20Proxy|ERC721Proxy|DummyERC721Token|LibBytes|Authorizable).json", + "../migrations/src/artifacts/@(DummyERC20Token|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|TestAssetProxyDispatcher|TestLibs|TestSignatureValidator|ERC20Proxy|ERC721Proxy|DummyERC721Token|TestLibBytes|Authorizable).json", "contracts": - "Exchange,DummyERC20Token,ZRXToken,WETH9,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry,TestAssetProxyDispatcher,TestLibs,TestSignatureValidator,ERC20Proxy,ERC721Proxy,DummyERC721Token,LibBytes,Authorizable" + "Exchange,DummyERC20Token,ZRXToken,WETH9,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry,TestAssetProxyDispatcher,TestLibs,TestSignatureValidator,ERC20Proxy,ERC721Proxy,DummyERC721Token,TestLibBytes,Authorizable" }, "repository": { "type": "git", 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 into. + /// @param index Index in byte array of . + /// @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 into. + /// @param index Index in byte array of . + /// @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/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index cff780ba4..3eba0708f 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -17,7 +17,6 @@ */ pragma solidity ^0.4.23; -pragma experimental ABIEncoderV2; contract LibBytes { @@ -26,7 +25,8 @@ contract LibBytes { /// @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 { @@ -59,7 +59,8 @@ contract LibBytes { function readAddress( bytes memory b, uint256 index) - public pure + internal + pure returns (address result) { require( @@ -90,7 +91,8 @@ contract LibBytes { bytes memory b, uint256 index, address input) - public pure + internal + pure { require( b.length >= index + 20, // 20 is length of address @@ -126,7 +128,8 @@ contract LibBytes { function readBytes32( bytes memory b, uint256 index) - public pure + internal + pure returns (bytes32 result) { require( @@ -152,7 +155,8 @@ contract LibBytes { bytes memory b, uint256 index, bytes32 input) - public pure + internal + pure { require( b.length >= index + 32, @@ -175,7 +179,8 @@ contract LibBytes { function readUint256( bytes memory b, uint256 index) - public pure + internal + pure returns (uint256 result) { return uint256(readBytes32(b, index)); @@ -189,7 +194,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/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', } diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index b96fb84b0..1270a617f 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -7,7 +7,7 @@ import * as chai from 'chai'; import ethUtil = require('ethereumjs-util'); import * as Web3 from 'web3'; -import { LibBytesContract } from '../../src/contract_wrappers/generated/lib_bytes'; +import { TestLibBytesContract } from '../../src/contract_wrappers/generated/test_lib_bytes'; import { constants } from '../../src/utils/constants'; import { AssetProxyId, ContractName } from '../../src/utils/types'; import { chaiSetup } from '../utils/chai_setup'; @@ -20,7 +20,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('LibBytes', () => { let owner: string; - let libBytes: LibBytesContract; + let libBytes: TestLibBytesContract; const byteArrayShorterThan32Bytes = '0x012345'; const byteArrayLongerThan32Bytes = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; @@ -38,8 +38,8 @@ describe('LibBytes', () => { owner = accounts[0]; testAddress = accounts[1]; // Deploy LibBytes - const libBytesInstance = await deployer.deployAsync(ContractName.LibBytes); - libBytes = new LibBytesContract(libBytesInstance.abi, libBytesInstance.address, provider); + const libBytesInstance = await deployer.deployAsync(ContractName.TestLibBytes); + libBytes = new TestLibBytesContract(libBytesInstance.abi, libBytesInstance.address, provider); // Verify lengths of test data const byteArrayShorterThan32BytesLength = ethUtil.toBuffer(byteArrayShorterThan32Bytes).byteLength; expect(byteArrayShorterThan32BytesLength).to.be.lessThan(32); @@ -57,7 +57,7 @@ describe('LibBytes', () => { describe('areBytesEqual', () => { it('should return true if byte arrays are equal (both arrays < 32 bytes)', async () => { - const areBytesEqual = await libBytes.areBytesEqual.callAsync( + const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync( byteArrayShorterThan32Bytes, byteArrayShorterThan32Bytes, ); @@ -65,7 +65,7 @@ describe('LibBytes', () => { }); it('should return true if byte arrays are equal (both arrays > 32 bytes)', async () => { - const areBytesEqual = await libBytes.areBytesEqual.callAsync( + const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync( byteArrayLongerThan32Bytes, byteArrayLongerThan32Bytes, ); @@ -73,7 +73,7 @@ describe('LibBytes', () => { }); it('should return false if byte arrays are not equal (first array < 32 bytes, second array > 32 bytes)', async () => { - const areBytesEqual = await libBytes.areBytesEqual.callAsync( + const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync( byteArrayShorterThan32Bytes, byteArrayLongerThan32Bytes, ); @@ -81,7 +81,7 @@ describe('LibBytes', () => { }); it('should return false if byte arrays are not equal (first array > 32 bytes, second array < 32 bytes)', async () => { - const areBytesEqual = await libBytes.areBytesEqual.callAsync( + const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync( byteArrayLongerThan32Bytes, byteArrayShorterThan32Bytes, ); @@ -89,7 +89,7 @@ describe('LibBytes', () => { }); it('should return false if byte arrays are not equal (same length, but a byte in first word differs)', async () => { - const areBytesEqual = await libBytes.areBytesEqual.callAsync( + const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync( byteArrayLongerThan32BytesFirstBytesSwapped, byteArrayLongerThan32Bytes, ); @@ -97,7 +97,7 @@ describe('LibBytes', () => { }); it('should return false if byte arrays are not equal (same length, but a byte in last word differs)', async () => { - const areBytesEqual = await libBytes.areBytesEqual.callAsync( + const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync( byteArrayLongerThan32BytesLastBytesSwapped, byteArrayLongerThan32Bytes, ); @@ -109,7 +109,7 @@ describe('LibBytes', () => { it('should successfully read address when the address takes up the whole array)', async () => { const byteArray = ethUtil.addHexPrefix(testAddress); const testAddressOffset = new BigNumber(0); - const address = await libBytes.readAddress.callAsync(byteArray, testAddressOffset); + const address = await libBytes.publicReadAddress.callAsync(byteArray, testAddressOffset); return expect(address).to.be.equal(testAddress); }); @@ -119,20 +119,24 @@ describe('LibBytes', () => { const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, addressByteArrayBuffer]); const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); const testAddressOffset = new BigNumber(prefixByteArrayBuffer.byteLength); - const address = await libBytes.readAddress.callAsync(combinedByteArray, testAddressOffset); + const address = await libBytes.publicReadAddress.callAsync(combinedByteArray, testAddressOffset); return expect(address).to.be.equal(testAddress); }); it('should fail if the byte array is too short to hold an address)', async () => { const shortByteArray = '0xabcdef'; const offset = new BigNumber(0); - return expect(libBytes.readAddress.callAsync(shortByteArray, offset)).to.be.rejectedWith(constants.REVERT); + return expect(libBytes.publicReadAddress.callAsync(shortByteArray, offset)).to.be.rejectedWith( + constants.REVERT, + ); }); it('should fail if the length between the offset and end of the byte array is too short to hold an address)', async () => { const byteArray = ethUtil.addHexPrefix(testAddress); const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength); - return expect(libBytes.readAddress.callAsync(byteArray, badOffset)).to.be.rejectedWith(constants.REVERT); + return expect(libBytes.publicReadAddress.callAsync(byteArray, badOffset)).to.be.rejectedWith( + constants.REVERT, + ); }); }); @@ -150,7 +154,7 @@ describe('LibBytes', () => { describe('readBytes32', () => { it('should successfully read bytes32 when the bytes32 takes up the whole array)', async () => { const testBytes32Offset = new BigNumber(0); - const bytes32 = await libBytes.readBytes32.callAsync(testBytes32, testBytes32Offset); + const bytes32 = await libBytes.publicReadBytes32.callAsync(testBytes32, testBytes32Offset); return expect(bytes32).to.be.equal(testBytes32); }); @@ -160,20 +164,22 @@ describe('LibBytes', () => { const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, bytes32ByteArrayBuffer]); const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); const testAddressOffset = new BigNumber(prefixByteArrayBuffer.byteLength); - const bytes32 = await libBytes.readBytes32.callAsync(combinedByteArray, testAddressOffset); + const bytes32 = await libBytes.publicReadBytes32.callAsync(combinedByteArray, testAddressOffset); return expect(bytes32).to.be.equal(testBytes32); }); it('should fail if the byte array is too short to hold a bytes32)', async () => { const offset = new BigNumber(0); - return expect(libBytes.readBytes32.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith( + return expect(libBytes.publicReadBytes32.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith( constants.REVERT, ); }); it('should fail if the length between the offset and end of the byte array is too short to hold a bytes32)', async () => { const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength); - return expect(libBytes.readBytes32.callAsync(testBytes32, badOffset)).to.be.rejectedWith(constants.REVERT); + return expect(libBytes.publicReadBytes32.callAsync(testBytes32, badOffset)).to.be.rejectedWith( + constants.REVERT, + ); }); }); @@ -194,7 +200,7 @@ describe('LibBytes', () => { const testUint256AsBuffer = ethUtil.toBuffer(formattedTestUint256); const byteArray = ethUtil.bufferToHex(testUint256AsBuffer); const testUint256Offset = new BigNumber(0); - const uint256 = await libBytes.readUint256.callAsync(byteArray, testUint256Offset); + const uint256 = await libBytes.publicReadUint256.callAsync(byteArray, testUint256Offset); return expect(uint256).to.bignumber.equal(testUint256); }); @@ -205,13 +211,13 @@ describe('LibBytes', () => { const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, testUint256AsBuffer]); const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength); - const uint256 = await libBytes.readUint256.callAsync(combinedByteArray, testUint256Offset); + const uint256 = await libBytes.publicReadUint256.callAsync(combinedByteArray, testUint256Offset); return expect(uint256).to.bignumber.equal(testUint256); }); it('should fail if the byte array is too short to hold a uint256)', async () => { const offset = new BigNumber(0); - return expect(libBytes.readUint256.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith( + return expect(libBytes.publicReadUint256.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith( constants.REVERT, ); }); @@ -221,7 +227,9 @@ describe('LibBytes', () => { const testUint256AsBuffer = ethUtil.toBuffer(formattedTestUint256); const byteArray = ethUtil.bufferToHex(testUint256AsBuffer); const badOffset = new BigNumber(testUint256AsBuffer.byteLength); - return expect(libBytes.readUint256.callAsync(byteArray, badOffset)).to.be.rejectedWith(constants.REVERT); + return expect(libBytes.publicReadUint256.callAsync(byteArray, badOffset)).to.be.rejectedWith( + constants.REVERT, + ); }); }); -- cgit v1.2.3 From 395d06042707892bcb74cb7a0e2897c628e5c903 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 4 May 2018 17:00:39 -0700 Subject: Split up mixins and interfaces --- .../current/protocol/AssetProxy/ERC20Proxy.sol | 81 ++++++ .../current/protocol/AssetProxy/ERC721Proxy.sol | 87 +++++++ .../current/protocol/AssetProxy/IAssetProxy.sol | 59 ----- .../protocol/AssetProxy/MixinAssetProxy.sol | 2 - .../protocol/AssetProxy/interfaces/IAssetProxy.sol | 59 +++++ .../protocol/AssetProxy/mixins/MAssetProxy.sol | 6 +- .../protocol/AssetProxy/proxies/ERC20Proxy.sol | 81 ------ .../protocol/AssetProxy/proxies/ERC721Proxy.sol | 87 ------- .../current/protocol/Exchange/IExchange.sol | 289 --------------------- .../current/protocol/Exchange/ISigner.sol | 30 --- .../protocol/Exchange/LibExchangeErrors.sol | 59 ----- .../current/protocol/Exchange/LibFillResults.sol | 48 ---- .../current/protocol/Exchange/LibMath.sol | 73 ------ .../current/protocol/Exchange/LibOrder.sol | 85 ------ .../Exchange/MixinAssetProxyDispatcher.sol | 59 +++-- .../protocol/Exchange/MixinExchangeCore.sol | 66 ++--- .../current/protocol/Exchange/MixinSettlement.sol | 17 +- .../protocol/Exchange/MixinSignatureValidator.sol | 50 ++-- .../protocol/Exchange/MixinTransactions.sol | 3 +- .../protocol/Exchange/MixinWrapperFunctions.sol | 9 +- .../Exchange/interfaces/IAssetProxyDispatcher.sol | 41 +++ .../protocol/Exchange/interfaces/IExchange.sol | 34 +++ .../protocol/Exchange/interfaces/IExchangeCore.sol | 51 ++++ .../Exchange/interfaces/ISignatureValidator.sol | 32 +++ .../protocol/Exchange/interfaces/ISigner.sol | 33 +++ .../protocol/Exchange/interfaces/ITransactions.sol | 33 +++ .../Exchange/interfaces/IWrapperFunctions.sol | 142 ++++++++++ .../Exchange/mixins/MAssetProxyDispatcher.sol | 26 +- .../protocol/Exchange/mixins/MExchangeCore.sol | 56 ++-- .../protocol/Exchange/mixins/MSettlement.sol | 8 +- .../Exchange/mixins/MSignatureValidator.sol | 18 +- .../protocol/Exchange/mixins/MTransactions.sol | 21 +- .../contracts/current/test/TestLibs/TestLibs.sol | 6 +- 33 files changed, 757 insertions(+), 994 deletions(-) create mode 100644 packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol create mode 100644 packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol delete mode 100644 packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol create mode 100644 packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol delete mode 100644 packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC20Proxy.sol delete mode 100644 packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol delete mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/IExchange.sol delete mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol delete mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/LibExchangeErrors.sol delete mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol delete mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol delete mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchange.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISigner.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol (limited to 'packages') diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol new file mode 100644 index 000000000..5ebdb5095 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -0,0 +1,81 @@ +/* + + 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"; +import "../../tokens/ERC20Token/IERC20Token.sol"; +import "./MixinAssetProxy.sol"; + +contract ERC20Proxy is + LibBytes, + 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. + /// @param to Address to transfer asset to. + /// @param amount Amount of asset to transfer. + function transferFromInternal( + bytes memory assetMetadata, + address from, + address to, + uint256 amount) + internal + { + // Data must be intended for this proxy. + require( + uint8(assetMetadata[0]) == PROXY_ID, + PROXY_ID_MISMATCH + ); + + // Decode metadata. + 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, + TRANSFER_FAILED + ); + } + + /// @dev Gets the proxy id associated with the proxy address. + /// @return Proxy id. + function getProxyId() + external + view + returns (uint8) + { + return PROXY_ID; + } +} diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol new file mode 100644 index 000000000..cc1a60f2e --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -0,0 +1,87 @@ +/* + + 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"; +import "../../tokens/ERC721Token/ERC721Token.sol"; +import "./MixinAssetProxy.sol"; + +contract ERC721Proxy is + LibBytes, + 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. + /// @param to Address to transfer asset to. + /// @param amount Amount of asset to transfer. + function transferFromInternal( + bytes memory assetMetadata, + address from, + address to, + uint256 amount) + internal + { + // Data must be intended for this proxy. + require( + uint8(assetMetadata[0]) == PROXY_ID, + PROXY_ID_MISMATCH + ); + + // There exists only 1 of each token. + require( + amount == 1, + INVALID_TRANSFER_AMOUNT + ); + + // Decode metadata + require( + assetMetadata.length == 53, + INVALID_METADATA_LENGTH + ); + address token = readAddress(assetMetadata, 1); + uint256 tokenId = readUint256(assetMetadata, 21); + + // Transfer token. + // Either succeeds or throws. + // @TODO: Call safeTransferFrom if there is additional + // data stored in `assetMetadata`. + ERC721Token(token).transferFrom(from, to, tokenId); + } + + /// @dev Gets the proxy id associated with the proxy address. + /// @return Proxy id. + function getProxyId() + external + view + returns (uint8) + { + return PROXY_ID; + } +} diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol deleted file mode 100644 index 7675d684b..000000000 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/IAssetProxy.sol +++ /dev/null @@ -1,59 +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.23; -pragma experimental ABIEncoderV2; - -import "../../utils/Authorizable/IAuthorizable.sol"; - -contract IAssetProxy is - IAuthorizable -{ - - /// @dev Transfers assets. Either succeeds or throws. - /// @param assetMetadata Byte array encoded for the respective asset proxy. - /// @param from Address to transfer asset from. - /// @param to Address to transfer asset to. - /// @param amount Amount of asset to transfer. - function transferFrom( - bytes assetMetadata, - address from, - address to, - uint256 amount) - external; - - /// @dev Makes multiple transfers of assets. Either succeeds or throws. - /// @param assetMetadata Array of byte arrays encoded for the respective asset proxy. - /// @param from Array of addresses to transfer assets from. - /// @param to Array of addresses to transfer assets to. - /// @param amounts Array of amounts of assets to transfer. - function batchTransferFrom( - bytes[] memory assetMetadata, - address[] memory from, - address[] memory to, - uint256[] memory amounts) - public; - - /// @dev Gets the proxy id associated with the proxy address. - /// @return Proxy id. - function getProxyId() - external - view - returns (uint8); -} - diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol index b96c84582..0535559ae 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol @@ -20,11 +20,9 @@ pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; import "./mixins/MAssetProxy.sol"; -import "./IAssetProxy.sol"; import "../../utils/Authorizable/Authorizable.sol"; contract MixinAssetProxy is - IAssetProxy, Authorizable, MAssetProxy { diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol new file mode 100644 index 000000000..1cdace0b5 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol @@ -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; + +import "../../../utils/Authorizable/IAuthorizable.sol"; + +contract IAssetProxy is + IAuthorizable +{ + + /// @dev Transfers assets. Either succeeds or throws. + /// @param assetMetadata Byte array encoded for the respective asset proxy. + /// @param from Address to transfer asset from. + /// @param to Address to transfer asset to. + /// @param amount Amount of asset to transfer. + function transferFrom( + bytes assetMetadata, + address from, + address to, + uint256 amount) + external; + + /// @dev Makes multiple transfers of assets. Either succeeds or throws. + /// @param assetMetadata Array of byte arrays encoded for the respective asset proxy. + /// @param from Array of addresses to transfer assets from. + /// @param to Array of addresses to transfer assets to. + /// @param amounts Array of amounts of assets to transfer. + function batchTransferFrom( + bytes[] memory assetMetadata, + address[] memory from, + address[] memory to, + uint256[] memory amounts) + public; + + /// @dev Gets the proxy id associated with the proxy address. + /// @return Proxy id. + function getProxyId() + external + view + returns (uint8); +} + 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 d1276a61c..e0ec8c4e1 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol @@ -19,7 +19,11 @@ 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/AssetProxy/proxies/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC20Proxy.sol deleted file mode 100644 index 7e9b41f33..000000000 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC20Proxy.sol +++ /dev/null @@ -1,81 +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.23; -pragma experimental ABIEncoderV2; - -import "../../../utils/LibBytes/LibBytes.sol"; -import "../../../tokens/ERC20Token/IERC20Token.sol"; -import "../MixinAssetProxy.sol"; - -contract ERC20Proxy is - LibBytes, - 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. - /// @param to Address to transfer asset to. - /// @param amount Amount of asset to transfer. - function transferFromInternal( - bytes memory assetMetadata, - address from, - address to, - uint256 amount) - internal - { - // Data must be intended for this proxy. - require( - uint8(assetMetadata[0]) == PROXY_ID, - PROXY_ID_MISMATCH - ); - - // Decode metadata. - 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, - TRANSFER_FAILED - ); - } - - /// @dev Gets the proxy id associated with the proxy address. - /// @return Proxy id. - function getProxyId() - external - view - returns (uint8) - { - return PROXY_ID; - } -} diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol deleted file mode 100644 index 4d52893b0..000000000 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol +++ /dev/null @@ -1,87 +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.23; -pragma experimental ABIEncoderV2; - -import "../../../utils/LibBytes/LibBytes.sol"; -import "../../../tokens/ERC721Token/ERC721Token.sol"; -import "../MixinAssetProxy.sol"; - -contract ERC721Proxy is - LibBytes, - 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. - /// @param to Address to transfer asset to. - /// @param amount Amount of asset to transfer. - function transferFromInternal( - bytes memory assetMetadata, - address from, - address to, - uint256 amount) - internal - { - // Data must be intended for this proxy. - require( - uint8(assetMetadata[0]) == PROXY_ID, - PROXY_ID_MISMATCH - ); - - // There exists only 1 of each token. - require( - amount == 1, - INVALID_TRANSFER_AMOUNT - ); - - // Decode metadata - require( - assetMetadata.length == 53, - INVALID_METADATA_LENGTH - ); - address token = readAddress(assetMetadata, 1); - uint256 tokenId = readUint256(assetMetadata, 21); - - // Transfer token. - // Either succeeds or throws. - // @TODO: Call safeTransferFrom if there is additional - // data stored in `assetMetadata`. - ERC721Token(token).transferFrom(from, to, tokenId); - } - - /// @dev Gets the proxy id associated with the proxy address. - /// @return Proxy id. - function getProxyId() - external - view - returns (uint8) - { - return PROXY_ID; - } -} 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/ISigner.sol b/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol deleted file mode 100644 index d604a1aec..000000000 --- a/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol +++ /dev/null @@ -1,30 +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.23; -pragma experimental ABIEncoderV2; - -contract ISigner { - - function isValidSignature( - bytes32 hash, - bytes signature) - external - view - returns (bool isValid); -} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibExchangeErrors.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibExchangeErrors.sol deleted file mode 100644 index cbd6cac29..000000000 --- a/packages/contracts/src/contracts/current/protocol/Exchange/LibExchangeErrors.sol +++ /dev/null @@ -1,59 +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.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."; -} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol deleted file mode 100644 index e26da2bce..000000000 --- a/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol +++ /dev/null @@ -1,48 +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.23; -pragma experimental ABIEncoderV2; - -import "../../utils/SafeMath/SafeMath.sol"; - -contract LibFillResults is - SafeMath -{ - - struct FillResults { - uint256 makerAssetFilledAmount; - uint256 takerAssetFilledAmount; - uint256 makerFeePaid; - uint256 takerFeePaid; - } - - /// @dev Adds properties of both FillResults instances. - /// Modifies the first FillResults instance specified. - /// @param totalFillResults Fill results instance that will be added onto. - /// @param singleFillResults Fill results instance that will be added to totalFillResults. - function addFillResults(FillResults memory totalFillResults, FillResults memory singleFillResults) - internal - pure - { - totalFillResults.makerAssetFilledAmount = safeAdd(totalFillResults.makerAssetFilledAmount, singleFillResults.makerAssetFilledAmount); - totalFillResults.takerAssetFilledAmount = safeAdd(totalFillResults.takerAssetFilledAmount, singleFillResults.takerAssetFilledAmount); - totalFillResults.makerFeePaid = safeAdd(totalFillResults.makerFeePaid, singleFillResults.makerFeePaid); - totalFillResults.takerFeePaid = safeAdd(totalFillResults.takerFeePaid, singleFillResults.takerFeePaid); - } -} \ No newline at end of file diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol deleted file mode 100644 index 761c300a1..000000000 --- a/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol +++ /dev/null @@ -1,73 +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.23; -pragma experimental ABIEncoderV2; - -import "../../utils/SafeMath/SafeMath.sol"; - -contract LibMath is - SafeMath -{ - - /// @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) - internal - pure - returns (uint256 partialAmount) - { - partialAmount = safeDiv( - safeMul(numerator, target), - denominator - ); - return 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) - internal - pure - returns (bool isError) - { - uint256 remainder = mulmod(target, numerator, denominator); - if (remainder == 0) { - return false; // No rounding error. - } - - uint256 errPercentageTimes1000000 = safeDiv( - safeMul(remainder, 1000000), - safeMul(numerator, target) - ); - isError = errPercentageTimes1000000 > 1000; - return isError; - } -} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol deleted file mode 100644 index 32554f45b..000000000 --- a/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol +++ /dev/null @@ -1,85 +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.23; -pragma experimental ABIEncoderV2; - -contract LibOrder { - - bytes32 constant ORDER_SCHEMA_HASH = keccak256( - "address exchangeAddress", - "address makerAddress", - "address takerAddress", - "address feeRecipientAddress", - "address senderAddress", - "uint256 makerAssetAmount", - "uint256 takerAssetAmount", - "uint256 makerFee", - "uint256 takerFee", - "uint256 expirationTimeSeconds", - "uint256 salt", - "bytes makerAssetData", - "bytes takerAssetData" - ); - - struct Order { - address makerAddress; - address takerAddress; - address feeRecipientAddress; - address senderAddress; - uint256 makerAssetAmount; - uint256 takerAssetAmount; - uint256 makerFee; - uint256 takerFee; - uint256 expirationTimeSeconds; - uint256 salt; - bytes makerAssetData; - bytes takerAssetData; - } - - /// @dev Calculates Keccak-256 hash of the order. - /// @param order The order structure. - /// @return Keccak-256 EIP712 hash of the order. - function getOrderHash(Order memory order) - internal - view - returns (bytes32 orderHash) - { - // TODO: EIP712 is not finalized yet - // Source: https://github.com/ethereum/EIPs/pull/712 - orderHash = keccak256( - ORDER_SCHEMA_HASH, - keccak256( - address(this), - order.makerAddress, - order.takerAddress, - order.feeRecipientAddress, - order.senderAddress, - order.makerAssetAmount, - order.takerAssetAmount, - order.makerFee, - order.takerFee, - order.expirationTimeSeconds, - order.salt, - order.makerAssetData, - order.takerAssetData - ) - ); - return orderHash; - } -} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol index eb423ad28..14d5eb7ca 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol @@ -17,11 +17,10 @@ */ pragma solidity ^0.4.23; -pragma experimental ABIEncoderV2; import "../../utils/Ownable/Ownable.sol"; -import "../AssetProxy/IAssetProxy.sol"; -import "./LibExchangeErrors.sol"; +import "../AssetProxy/interfaces/IAssetProxy.sol"; +import "./lib/LibExchangeErrors.sol"; import "./mixins/MAssetProxyDispatcher.sol"; contract MixinAssetProxyDispatcher is @@ -32,33 +31,6 @@ contract MixinAssetProxyDispatcher is // 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, - GREATER_THAN_ZERO_LENGTH_REQUIRED - ); - 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. @@ -104,4 +76,31 @@ contract MixinAssetProxyDispatcher is 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, + GREATER_THAN_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 d764d7a4f..c22acf966 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -19,18 +19,15 @@ pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; -import "./LibFillResults.sol"; -import "./LibOrder.sol"; -import "./LibMath.sol"; -import "./LibExchangeErrors.sol"; +import "./lib/LibFillResults.sol"; +import "./lib/LibOrder.sol"; +import "./lib/LibMath.sol"; +import "./lib/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, @@ -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. @@ -237,19 +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 - INVALID_NEW_MAKER_EPOCH - ); - 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 3e805aa8e..ae1dd9bee 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol @@ -17,22 +17,21 @@ */ pragma solidity ^0.4.23; -pragma experimental ABIEncoderV2; import "./mixins/MSettlement.sol"; import "./mixins/MAssetProxyDispatcher.sol"; -import "./LibOrder.sol"; -import "./LibMath.sol"; -import "../AssetProxy/IAssetProxy.sol"; +import "./lib/LibOrder.sol"; +import "./lib/LibMath.sol"; -/// @dev Provides MixinSettlement contract MixinSettlement is LibMath, MSettlement, MAssetProxyDispatcher { + /// ZRX metadata used for fee transfers. bytes internal ZRX_PROXY_DATA; + /// @dev Gets the ZRX metadata used for fee transfers. function zrxProxyData() external view @@ -41,12 +40,20 @@ contract MixinSettlement is return ZRX_PROXY_DATA; } + /// 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 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, diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol index 3091adcaf..43d138669 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol @@ -17,33 +17,38 @@ */ pragma solidity ^0.4.23; -pragma experimental ABIEncoderV2; import "./mixins/MSignatureValidator.sol"; -import "./ISigner.sol"; -import "./LibExchangeErrors.sol"; +import "./interfaces/ISigner.sol"; +import "./lib/LibExchangeErrors.sol"; import "../../utils/LibBytes/LibBytes.sol"; -/// @dev Provides MSignatureValidator contract MixinSignatureValidator is LibBytes, LibExchangeErrors, MSignatureValidator { - enum SignatureType { - Illegal, // Default value - Invalid, - Caller, - Ecrecover, - EIP712, - Trezor, - Contract, - PreSigned - } // 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. @@ -183,21 +188,4 @@ contract MixinSignatureValidator is // 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), - SIGNATURE_VALIDATION_FAILED - ); - preSigned[hash][signer] = true; - } } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol index 670d454d6..a8b60e8a4 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol @@ -16,11 +16,10 @@ */ pragma solidity ^0.4.21; -pragma experimental ABIEncoderV2; import "./mixins/MSignatureValidator.sol"; import "./mixins/MTransactions.sol"; -import "./LibExchangeErrors.sol"; +import "./lib/LibExchangeErrors.sol"; contract MixinTransactions is LibExchangeErrors, diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol index 0cfcf0c25..33a125083 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol @@ -21,12 +21,11 @@ pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; import "./mixins/MExchangeCore.sol"; -import "./LibMath.sol"; -import "./LibOrder.sol"; -import "./LibFillResults.sol"; -import "./LibExchangeErrors.sol"; +import "./lib/LibMath.sol"; +import "./lib/LibOrder.sol"; +import "./lib/LibFillResults.sol"; +import "./lib/LibExchangeErrors.sol"; -/// @dev Consumes MExchangeCore contract MixinWrapperFunctions is LibOrder, LibFillResults, 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..d60b8ca48 --- /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); +} \ No newline at end of file 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..18f794ee8 --- /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 "../lib/LibOrder.sol"; +import "../lib/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); +} \ No newline at end of file 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..806d7c56f --- /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; +} \ No newline at end of file diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISigner.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISigner.sol new file mode 100644 index 000000000..e065cfd8a --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISigner.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 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) + external + view + returns (bool isValid); +} 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..078b07816 --- /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; +} \ No newline at end of file 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..0ebae309d --- /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 "./lib/LibOrder.sol"; +import "./lib/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/mixins/MAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol index df2250cd9..77ee77797 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol @@ -17,9 +17,12 @@ */ pragma solidity ^0.4.23; -pragma experimental ABIEncoderV2; -contract MAssetProxyDispatcher { +import "../interfaces/IAssetProxyDispatcher.sol"; + +contract MAssetProxyDispatcher is + IAssetProxyDispatcher +{ // Logs registration of new asset proxy event AssetProxySet( @@ -39,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 6bd8fd9b6..b80af9dc1 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -17,24 +17,50 @@ */ pragma solidity ^0.4.23; -pragma experimental ABIEncoderV2; -import "../LibOrder.sol"; -import "../LibFillResults.sol"; +import "../lib/LibOrder.sol"; +import "../lib/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 9cb2afeb0..3075aae15 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol @@ -17,12 +17,16 @@ */ pragma solidity ^0.4.23; -pragma experimental ABIEncoderV2; -import "../LibOrder.sol"; +import "../lib/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, 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 2b8ae78dd..ba26c07f6 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol @@ -17,9 +17,23 @@ */ pragma solidity ^0.4.23; -pragma experimental ABIEncoderV2; -contract MSignatureValidator { +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 3d167c0bc..159ed1527 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MTransactions.sol @@ -16,21 +16,12 @@ */ pragma solidity ^0.4.23; -pragma experimental ABIEncoderV2; - -contract MTransactions { - - /// @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; + +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/TestLibs/TestLibs.sol b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol index 5a16ae947..3d199681b 100644 --- a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol +++ b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol @@ -19,9 +19,9 @@ 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/lib/LibMath.sol"; +import "../../protocol/Exchange/lib/LibOrder.sol"; +import "../../protocol/Exchange/lib/LibFillResults.sol"; contract TestLibs is LibMath, -- cgit v1.2.3 From 7e7364fc83167677594f246b418fe939b1b02f2a Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 7 May 2018 11:20:53 -0700 Subject: Move Authorizable to AssetProxy dir, rename to MixinAuthorizable --- packages/contracts/package.json | 4 +- .../current/protocol/AssetProxy/ERC20Proxy.sol | 4 +- .../current/protocol/AssetProxy/ERC721Proxy.sol | 4 +- .../protocol/AssetProxy/MixinAssetProxy.sol | 4 +- .../protocol/AssetProxy/MixinAuthorizable.sol | 117 +++++++++++++++++++ .../protocol/AssetProxy/interfaces/IAssetProxy.sol | 2 +- .../AssetProxy/interfaces/IAuthorizable.sol | 50 +++++++++ .../protocol/AssetProxy/mixins/MAuthorizable.sol | 42 +++++++ .../current/utils/Authorizable/Authorizable.sol | 124 --------------------- .../current/utils/Authorizable/IAuthorizable.sol | 55 --------- .../contracts/current/utils/Ownable/Ownable.sol | 2 +- .../contracts/test/asset_proxy/authorizable.ts | 6 +- 12 files changed, 224 insertions(+), 190 deletions(-) create mode 100644 packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol create mode 100644 packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAuthorizable.sol create mode 100644 packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAuthorizable.sol delete mode 100644 packages/contracts/src/contracts/current/utils/Authorizable/Authorizable.sol delete mode 100644 packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol (limited to 'packages') diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 48019fe8c..2c5ee872e 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -30,9 +30,9 @@ }, "config": { "abis": - "../migrations/src/artifacts/@(DummyERC20Token|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|TestAssetProxyDispatcher|TestLibs|TestSignatureValidator|ERC20Proxy|ERC721Proxy|DummyERC721Token|TestLibBytes|Authorizable).json", + "../migrations/src/artifacts/@(DummyERC20Token|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|TestAssetProxyDispatcher|TestLibs|TestSignatureValidator|ERC20Proxy|ERC721Proxy|DummyERC721Token|TestLibBytes|MixinAuthorizable).json", "contracts": - "Exchange,DummyERC20Token,ZRXToken,WETH9,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry,TestAssetProxyDispatcher,TestLibs,TestSignatureValidator,ERC20Proxy,ERC721Proxy,DummyERC721Token,TestLibBytes,Authorizable" + "Exchange,DummyERC20Token,ZRXToken,WETH9,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry,TestAssetProxyDispatcher,TestLibs,TestSignatureValidator,ERC20Proxy,ERC721Proxy,DummyERC721Token,TestLibBytes,MixinAuthorizable" }, "repository": { "type": "git", diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index 5ebdb5095..c02536d67 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -22,10 +22,12 @@ pragma experimental ABIEncoderV2; 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. diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index cc1a60f2e..475359087 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -22,10 +22,12 @@ pragma experimental ABIEncoderV2; 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. diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol index 0535559ae..d58cfc2dd 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol @@ -20,10 +20,10 @@ pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; import "./mixins/MAssetProxy.sol"; -import "../../utils/Authorizable/Authorizable.sol"; +import "./mixins/MAuthorizable.sol"; contract MixinAssetProxy is - Authorizable, + MAuthorizable, MAssetProxy { diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol new file mode 100644 index 000000000..b66b783ea --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAuthorizable.sol @@ -0,0 +1,117 @@ +/* + + 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 "./mixins/MAuthorizable.sol"; +import "../../utils/Ownable/Ownable.sol"; + +contract MixinAuthorizable is + Ownable, + 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], + SENDER_NOT_AUTHORIZED + ); + _; + } + + mapping (address => bool) public authorized; + address[] public authorities; + + /// @dev Authorizes an address. + /// @param target Address to authorize. + function addAuthorizedAddress(address target) + external + onlyOwner + { + require( + !authorized[target], + TARGET_ALREADY_AUTHORIZED + ); + + authorized[target] = true; + authorities.push(target); + emit AuthorizedAddressAdded(target, msg.sender); + } + + /// @dev Removes authorizion of an address. + /// @param target Address to remove authorization from. + function removeAuthorizedAddress(address target) + external + onlyOwner + { + require( + authorized[target], + TARGET_NOT_AUTHORIZED + ); + + delete authorized[target]; + for (uint i = 0; i < authorities.length; i++) { + if (authorities[i] == target) { + authorities[i] = authorities[authorities.length - 1]; + authorities.length -= 1; + break; + } + } + emit AuthorizedAddressRemoved(target, msg.sender); + } + + /// @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) + external + { + 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); + } + + /// @dev Gets all authorized addresses. + /// @return Array of authorized addresses. + function getAuthorizedAddresses() + external + view + returns (address[] memory) + { + return authorities; + } +} diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol index 1cdace0b5..eca6524e5 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol @@ -19,7 +19,7 @@ pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; -import "../../../utils/Authorizable/IAuthorizable.sol"; +import "./IAuthorizable.sol"; contract IAssetProxy is IAuthorizable diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAuthorizable.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAuthorizable.sol new file mode 100644 index 000000000..3120be7ec --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAuthorizable.sol @@ -0,0 +1,50 @@ +/* + + 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/Ownable/IOwnable.sol"; + +contract IAuthorizable is + IOwnable +{ + + /// @dev Gets all authorized addresses. + /// @return Array of authorized addresses. + function getAuthorizedAddresses() + external + view + returns (address[]); + + /// @dev Authorizes an address. + /// @param target Address to authorize. + function addAuthorizedAddress(address target) + external; + + /// @dev Removes authorizion of an address. + /// @param target Address to remove authorization from. + function removeAuthorizedAddress(address target) + 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) + external; +} diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAuthorizable.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAuthorizable.sol new file mode 100644 index 000000000..71d1910e5 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAuthorizable.sol @@ -0,0 +1,42 @@ +/* + + 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 "../interfaces/IAuthorizable.sol"; + +contract MAuthorizable is + IAuthorizable +{ + + // 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/utils/Authorizable/Authorizable.sol b/packages/contracts/src/contracts/current/utils/Authorizable/Authorizable.sol deleted file mode 100644 index 6b84d7aca..000000000 --- a/packages/contracts/src/contracts/current/utils/Authorizable/Authorizable.sol +++ /dev/null @@ -1,124 +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.23; -pragma experimental ABIEncoderV2; - -import "./IAuthorizable.sol"; -import "../Ownable/Ownable.sol"; - -contract Authorizable is - Ownable, - IAuthorizable -{ - - /// @dev Only authorized addresses can invoke functions with this modifier. - modifier onlyAuthorized { - require( - authorized[msg.sender], - "Sender not authorized to call this method." - ); - _; - } - - modifier targetAuthorized(address target) { - require( - authorized[target], - "Target address not authorized to call this method." - ); - _; - } - - modifier targetNotAuthorized(address target) { - require( - !authorized[target], - "Target must not already be authorized to call this method." - ); - _; - } - - mapping (address => bool) public authorized; - address[] public authorities; - - /* - * Public functions - */ - - /// @dev Authorizes an address. - /// @param target Address to authorize. - function addAuthorizedAddress(address target) - public - onlyOwner - targetNotAuthorized(target) - { - authorized[target] = true; - authorities.push(target); - emit AuthorizedAddressAdded(target, msg.sender); - } - - /// @dev Removes authorizion of an address. - /// @param target Address to remove authorization from. - function removeAuthorizedAddress(address target) - public - onlyOwner - targetAuthorized(target) - { - delete authorized[target]; - for (uint i = 0; i < authorities.length; i++) { - if (authorities[i] == target) { - authorities[i] = authorities[authorities.length - 1]; - authorities.length -= 1; - break; - } - } - emit AuthorizedAddressRemoved(target, msg.sender); - } - - /// @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 - { - 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; - emit AuthorizedAddressRemoved(target, msg.sender); - } - - /* - * Public constant functions - */ - - /// @dev Gets all authorized addresses. - /// @return Array of authorized addresses. - function getAuthorizedAddresses() - public view - returns (address[] memory) - { - return authorities; - } -} diff --git a/packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol b/packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol deleted file mode 100644 index b14cfba22..000000000 --- a/packages/contracts/src/contracts/current/utils/Authorizable/IAuthorizable.sol +++ /dev/null @@ -1,55 +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.23; -pragma experimental ABIEncoderV2; - -contract IAuthorizable { - - /// @dev Gets all authorized addresses. - /// @return Array of authorized addresses. - function getAuthorizedAddresses() - public view - returns (address[]); - - /// @dev Authorizes an address. - /// @param target Address to authorize. - function addAuthorizedAddress(address target) - public; - - /// @dev Removes authorizion of an address. - /// @param target Address to remove authorization from. - function removeAuthorizedAddress(address target) - public; - - /// @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 - ); -} diff --git a/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol b/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol index e9b4d6a3b..933aa168a 100644 --- a/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol +++ b/packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol @@ -8,7 +8,7 @@ pragma experimental ABIEncoderV2; * 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; diff --git a/packages/contracts/test/asset_proxy/authorizable.ts b/packages/contracts/test/asset_proxy/authorizable.ts index cc4f78a31..9cea263e7 100644 --- a/packages/contracts/test/asset_proxy/authorizable.ts +++ b/packages/contracts/test/asset_proxy/authorizable.ts @@ -3,7 +3,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import * as Web3 from 'web3'; -import { AuthorizableContract } from '../../src/contract_wrappers/generated/authorizable'; +import { MixinAuthorizableContract } from '../../src/contract_wrappers/generated/mixin_authorizable'; import { constants } from '../../src/utils/constants'; import { ContractName } from '../../src/utils/types'; import { chaiSetup } from '../utils/chai_setup'; @@ -18,13 +18,13 @@ describe('Authorizable', () => { let owner: string; let notOwner: string; let address: string; - let authorizable: AuthorizableContract; + let authorizable: MixinAuthorizableContract; before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); owner = address = accounts[0]; notOwner = accounts[1]; const authorizableInstance = await deployer.deployAsync(ContractName.Authorizable); - authorizable = new AuthorizableContract(authorizableInstance.abi, authorizableInstance.address, provider); + authorizable = new MixinAuthorizableContract(authorizableInstance.abi, authorizableInstance.address, provider); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); -- cgit v1.2.3 From 5198c56db94a43148789d3d0561220bd7cf546c0 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 8 May 2018 13:06:17 -0700 Subject: Add revert variables, change lib => libs to get around gitignore --- .../Exchange/MixinAssetProxyDispatcher.sol | 4 +- .../protocol/Exchange/MixinExchangeCore.sol | 18 ++--- .../current/protocol/Exchange/MixinSettlement.sol | 12 ++-- .../protocol/Exchange/MixinSignatureValidator.sol | 2 +- .../protocol/Exchange/MixinTransactions.sol | 2 +- .../protocol/Exchange/MixinWrapperFunctions.sol | 8 +-- .../Exchange/interfaces/IAssetProxyDispatcher.sol | 2 +- .../protocol/Exchange/interfaces/IExchangeCore.sol | 6 +- .../Exchange/interfaces/ISignatureValidator.sol | 2 +- .../protocol/Exchange/interfaces/ITransactions.sol | 2 +- .../Exchange/interfaces/IWrapperFunctions.sol | 4 +- .../protocol/Exchange/libs/LibExchangeErrors.sol | 58 +++++++++++++++ .../protocol/Exchange/libs/LibFillResults.sol | 47 ++++++++++++ .../current/protocol/Exchange/libs/LibMath.sol | 72 +++++++++++++++++++ .../current/protocol/Exchange/libs/LibOrder.sol | 84 ++++++++++++++++++++++ .../protocol/Exchange/mixins/MExchangeCore.sol | 4 +- .../protocol/Exchange/mixins/MSettlement.sol | 2 +- .../contracts/current/test/TestLibs/TestLibs.sol | 6 +- .../current/tokens/ERC20Token/ERC20Token.sol | 24 ++++--- .../UnlimitedAllowanceToken.sol | 6 +- .../contracts/current/utils/LibBytes/LibBytes.sol | 12 ++-- 21 files changed, 325 insertions(+), 52 deletions(-) create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/libs/LibFillResults.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/libs/LibMath.sol create mode 100644 packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol (limited to 'packages') diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol index 14d5eb7ca..308dace32 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol @@ -20,7 +20,7 @@ pragma solidity ^0.4.23; import "../../utils/Ownable/Ownable.sol"; import "../AssetProxy/interfaces/IAssetProxy.sol"; -import "./lib/LibExchangeErrors.sol"; +import "./libs/LibExchangeErrors.sol"; import "./mixins/MAssetProxyDispatcher.sol"; contract MixinAssetProxyDispatcher is @@ -94,7 +94,7 @@ contract MixinAssetProxyDispatcher is // Lookup asset proxy require( assetMetadata.length >= 1, - GREATER_THAN_ZERO_LENGTH_REQUIRED + GT_ZERO_LENGTH_REQUIRED ); uint8 assetProxyId = uint8(assetMetadata[0]); IAssetProxy assetProxy = assetProxies[assetProxyId]; diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index c22acf966..82c7a2ddc 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -19,10 +19,10 @@ pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; -import "./lib/LibFillResults.sol"; -import "./lib/LibOrder.sol"; -import "./lib/LibMath.sol"; -import "./lib/LibExchangeErrors.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"; @@ -94,11 +94,11 @@ contract MixinExchangeCore is if (filled[orderHash] == 0) { require( order.makerAssetAmount > 0, - GREATER_THAN_ZERO_AMOUNT_REQUIRED + GT_ZERO_AMOUNT_REQUIRED ); require( order.takerAssetAmount > 0, - GREATER_THAN_ZERO_AMOUNT_REQUIRED + GT_ZERO_AMOUNT_REQUIRED ); require( isValidSignature(orderHash, order.makerAddress, signature), @@ -124,7 +124,7 @@ contract MixinExchangeCore is } require( takerAssetFillAmount > 0, - GREATER_THAN_ZERO_AMOUNT_REQUIRED + GT_ZERO_AMOUNT_REQUIRED ); // Validate order expiration @@ -174,11 +174,11 @@ contract MixinExchangeCore is // Validate the order require( order.makerAssetAmount > 0, - GREATER_THAN_ZERO_AMOUNT_REQUIRED + GT_ZERO_AMOUNT_REQUIRED ); require( order.takerAssetAmount > 0, - GREATER_THAN_ZERO_AMOUNT_REQUIRED + GT_ZERO_AMOUNT_REQUIRED ); // Validate sender is allowed to cancel this order diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol index ae1dd9bee..30f1bb49b 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol @@ -20,15 +20,17 @@ pragma solidity ^0.4.23; import "./mixins/MSettlement.sol"; import "./mixins/MAssetProxyDispatcher.sol"; -import "./lib/LibOrder.sol"; -import "./lib/LibMath.sol"; +import "./libs/LibOrder.sol"; +import "./libs/LibMath.sol"; contract MixinSettlement is LibMath, MSettlement, MAssetProxyDispatcher { - /// ZRX metadata used for fee transfers. + // 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. @@ -49,10 +51,10 @@ contract MixinSettlement is ZRX_PROXY_DATA = _zrxProxyData; } - /// @dev Settles an order by transfering assets between counterparties. + /// @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 transfered to the order's maker. + /// @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, diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol index 43d138669..2322625d9 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol @@ -20,7 +20,7 @@ pragma solidity ^0.4.23; import "./mixins/MSignatureValidator.sol"; import "./interfaces/ISigner.sol"; -import "./lib/LibExchangeErrors.sol"; +import "./libs/LibExchangeErrors.sol"; import "../../utils/LibBytes/LibBytes.sol"; contract MixinSignatureValidator is diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol index a8b60e8a4..7f12834a3 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol @@ -19,7 +19,7 @@ pragma solidity ^0.4.21; import "./mixins/MSignatureValidator.sol"; import "./mixins/MTransactions.sol"; -import "./lib/LibExchangeErrors.sol"; +import "./libs/LibExchangeErrors.sol"; contract MixinTransactions is LibExchangeErrors, diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol index 33a125083..42517221e 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol @@ -21,10 +21,10 @@ pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; import "./mixins/MExchangeCore.sol"; -import "./lib/LibMath.sol"; -import "./lib/LibOrder.sol"; -import "./lib/LibFillResults.sol"; -import "./lib/LibExchangeErrors.sol"; +import "./libs/LibMath.sol"; +import "./libs/LibOrder.sol"; +import "./libs/LibFillResults.sol"; +import "./libs/LibExchangeErrors.sol"; contract MixinWrapperFunctions is LibOrder, diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol index d60b8ca48..4e4ed6be8 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol @@ -38,4 +38,4 @@ contract IAssetProxyDispatcher { external view returns (address); -} \ No newline at end of file +} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol index 18f794ee8..0f19525ca 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol @@ -19,8 +19,8 @@ pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; -import "../lib/LibOrder.sol"; -import "../lib/LibFillResults.sol"; +import "../libs/LibOrder.sol"; +import "../libs/LibFillResults.sol"; contract IExchangeCore { @@ -48,4 +48,4 @@ contract IExchangeCore { function cancelOrder(LibOrder.Order memory order) public returns (bool); -} \ No newline at end of file +} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol index 806d7c56f..b4a238472 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol @@ -29,4 +29,4 @@ contract ISignatureValidator { address signer, bytes signature) external; -} \ No newline at end of file +} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol index 078b07816..76e4cf2fe 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol @@ -30,4 +30,4 @@ contract ITransactions { bytes data, bytes signature) external; -} \ No newline at end of file +} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol index 0ebae309d..d23170b1c 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol @@ -19,8 +19,8 @@ pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; -import "./lib/LibOrder.sol"; -import "./lib/LibFillResults.sol"; +import "./libs/LibOrder.sol"; +import "./libs/LibFillResults.sol"; contract IWrapperFunctions is LibOrder, 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/libs/LibFillResults.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibFillResults.sol new file mode 100644 index 000000000..3b8f2acf9 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibFillResults.sol @@ -0,0 +1,47 @@ +/* + + 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; + +import "../../../utils/SafeMath/SafeMath.sol"; + +contract LibFillResults is + SafeMath +{ + + struct FillResults { + uint256 makerAssetFilledAmount; + uint256 takerAssetFilledAmount; + uint256 makerFeePaid; + uint256 takerFeePaid; + } + + /// @dev Adds properties of both FillResults instances. + /// Modifies the first FillResults instance specified. + /// @param totalFillResults Fill results instance that will be added onto. + /// @param singleFillResults Fill results instance that will be added to totalFillResults. + function addFillResults(FillResults memory totalFillResults, FillResults memory singleFillResults) + internal + pure + { + totalFillResults.makerAssetFilledAmount = safeAdd(totalFillResults.makerAssetFilledAmount, singleFillResults.makerAssetFilledAmount); + totalFillResults.takerAssetFilledAmount = safeAdd(totalFillResults.takerAssetFilledAmount, singleFillResults.takerAssetFilledAmount); + totalFillResults.makerFeePaid = safeAdd(totalFillResults.makerFeePaid, singleFillResults.makerFeePaid); + totalFillResults.takerFeePaid = safeAdd(totalFillResults.takerFeePaid, singleFillResults.takerFeePaid); + } +} \ No newline at end of file diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibMath.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibMath.sol new file mode 100644 index 000000000..b48602d19 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibMath.sol @@ -0,0 +1,72 @@ +/* + + 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; + +import "../../../utils/SafeMath/SafeMath.sol"; + +contract LibMath is + SafeMath +{ + + /// @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) + internal + pure + returns (uint256 partialAmount) + { + partialAmount = safeDiv( + safeMul(numerator, target), + denominator + ); + return 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) + internal + pure + returns (bool isError) + { + uint256 remainder = mulmod(target, numerator, denominator); + if (remainder == 0) { + return false; // No rounding error. + } + + uint256 errPercentageTimes1000000 = safeDiv( + safeMul(remainder, 1000000), + safeMul(numerator, target) + ); + isError = errPercentageTimes1000000 > 1000; + return isError; + } +} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol new file mode 100644 index 000000000..0fe8c8c96 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol @@ -0,0 +1,84 @@ +/* + + 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 LibOrder { + + bytes32 constant ORDER_SCHEMA_HASH = keccak256( + "address exchangeAddress", + "address makerAddress", + "address takerAddress", + "address feeRecipientAddress", + "address senderAddress", + "uint256 makerAssetAmount", + "uint256 takerAssetAmount", + "uint256 makerFee", + "uint256 takerFee", + "uint256 expirationTimeSeconds", + "uint256 salt", + "bytes makerAssetData", + "bytes takerAssetData" + ); + + struct Order { + address makerAddress; + address takerAddress; + address feeRecipientAddress; + address senderAddress; + uint256 makerAssetAmount; + uint256 takerAssetAmount; + uint256 makerFee; + uint256 takerFee; + uint256 expirationTimeSeconds; + uint256 salt; + bytes makerAssetData; + bytes takerAssetData; + } + + /// @dev Calculates Keccak-256 hash of the order. + /// @param order The order structure. + /// @return Keccak-256 EIP712 hash of the order. + function getOrderHash(Order memory order) + internal + view + returns (bytes32 orderHash) + { + // TODO: EIP712 is not finalized yet + // Source: https://github.com/ethereum/EIPs/pull/712 + orderHash = keccak256( + ORDER_SCHEMA_HASH, + keccak256( + address(this), + order.makerAddress, + order.takerAddress, + order.feeRecipientAddress, + order.senderAddress, + order.makerAssetAmount, + order.takerAssetAmount, + order.makerFee, + order.takerFee, + order.expirationTimeSeconds, + order.salt, + order.makerAssetData, + order.takerAssetData + ) + ); + return orderHash; + } +} 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 b80af9dc1..5b78e70da 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -18,8 +18,8 @@ pragma solidity ^0.4.23; -import "../lib/LibOrder.sol"; -import "../lib/LibFillResults.sol"; +import "../libs/LibOrder.sol"; +import "../libs/LibFillResults.sol"; import "../interfaces/IExchangeCore.sol"; contract MExchangeCore is 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 3075aae15..5e2edbf99 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol @@ -18,7 +18,7 @@ pragma solidity ^0.4.23; -import "../lib/LibOrder.sol"; +import "../libs/LibOrder.sol"; contract MSettlement { diff --git a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol index 3d199681b..0dc7785b2 100644 --- a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol +++ b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol @@ -19,9 +19,9 @@ pragma solidity ^0.4.23; pragma experimental ABIEncoderV2; -import "../../protocol/Exchange/lib/LibMath.sol"; -import "../../protocol/Exchange/lib/LibOrder.sol"; -import "../../protocol/Exchange/lib/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/tokens/ERC20Token/ERC20Token.sol b/packages/contracts/src/contracts/current/tokens/ERC20Token/ERC20Token.sol index 27e7fa355..6497d3c7a 100644 --- a/packages/contracts/src/contracts/current/tokens/ERC20Token/ERC20Token.sol +++ b/packages/contracts/src/contracts/current/tokens/ERC20Token/ERC20Token.sol @@ -23,17 +23,26 @@ 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, - "Insufficient balance to complete transfer." + INSUFFICIENT_BALANCE ); require( balances[_to] + _value >= balances[_to], - "Transfer would result in an overflow." + OVERFLOW ); balances[msg.sender] -= _value; balances[_to] += _value; @@ -47,15 +56,15 @@ contract ERC20Token is IERC20Token { { require( balances[_from] >= _value, - "Insufficient balance to complete transfer." + INSUFFICIENT_BALANCE ); require( allowed[_from][msg.sender] >= _value, - "Insufficient allowance to complete transfer." + INSUFFICIENT_ALLOWANCE ); require( balances[_to] + _value >= balances[_to], - "Transfer would result in an overflow." + OVERFLOW ); balances[_to] += _value; balances[_from] -= _value; @@ -87,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/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol b/packages/contracts/src/contracts/current/tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol index 4aedced49..395e5d356 100644 --- a/packages/contracts/src/contracts/current/tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol +++ b/packages/contracts/src/contracts/current/tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol @@ -37,15 +37,15 @@ contract UnlimitedAllowanceToken is ERC20Token { uint256 allowance = allowed[_from][msg.sender]; require( balances[_from] >= _value, - "Insufficient balance to complete transfer." + INSUFFICIENT_BALANCE ); require( allowance >= _value, - "Insufficient allowance to complete transfer." + INSUFFICIENT_ALLOWANCE ); require( balances[_to] + _value >= balances[_to], - "Transfer would result in an overflow." + OVERFLOW ); balances[_to] += _value; balances[_from] -= _value; diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol index 3eba0708f..3c5531e35 100644 --- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol @@ -20,6 +20,10 @@ 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. @@ -65,7 +69,7 @@ contract LibBytes { { require( b.length >= index + 20, // 20 is length of address - "Cannot read address from byte array shorter than 20 bytes." + GTE_20_LENGTH_REQUIRED ); // Add offset to index: @@ -96,7 +100,7 @@ contract LibBytes { { require( b.length >= index + 20, // 20 is length of address - "Cannot write address to byte array shorter than 20 bytes." + GTE_20_LENGTH_REQUIRED ); // Add offset to index: @@ -134,7 +138,7 @@ contract LibBytes { { require( b.length >= index + 32, - "Cannot read 32 bytes from byte array shorter than 32 bytes." + GTE_32_LENGTH_REQUIRED ); // Arrays are prefixed by a 256 bit length parameter @@ -160,7 +164,7 @@ contract LibBytes { { require( b.length >= index + 32, - "Cannot write 32 bytes to byte array shorter than 32 bytes." + GTE_32_LENGTH_REQUIRED ); // Arrays are prefixed by a 256 bit length parameter -- cgit v1.2.3