diff options
Diffstat (limited to 'packages/contracts/src')
15 files changed, 138 insertions, 161 deletions
diff --git a/packages/contracts/src/2.0.0/forwarder/MixinAssets.sol b/packages/contracts/src/2.0.0/forwarder/MixinAssets.sol index 5cf5f831b..e06f9a8e3 100644 --- a/packages/contracts/src/2.0.0/forwarder/MixinAssets.sol +++ b/packages/contracts/src/2.0.0/forwarder/MixinAssets.sol @@ -36,28 +36,25 @@ contract MixinAssets is bytes4 constant internal ERC20_TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)")); - /// @dev Withdraws ERC20 tokens from this contract. The contract requires a ZRX balance in order to + /// @dev Withdraws assets from this contract. The contract requires a ZRX balance in order to /// function optimally, and this function allows the ZRX to be withdrawn by owner. It may also be - /// used to withdraw tokens that were accidentally sent to this contract. - /// @param token Address of ERC20 token to withdraw. + /// used to withdraw assets that were accidentally sent to this contract. + /// @param assetData Byte array encoded for the respective asset proxy. /// @param amount Amount of ERC20 token to withdraw. - function withdrawERC20( - address token, + function withdrawAsset( + bytes assetData, uint256 amount ) external onlyOwner { - require( - IERC20Token(token).transfer(msg.sender, amount), - "WITHDRAWAL_FAILED" - ); + transferAssetToSender(assetData, amount); } /// @dev Transfers given amount of asset to sender. /// @param assetData Byte array encoded for the respective asset proxy. /// @param amount Amount of asset to transfer to sender. - function transferPurchasedAssetToSender( + function transferAssetToSender( bytes memory assetData, uint256 amount ) diff --git a/packages/contracts/src/2.0.0/forwarder/MixinExchangeWrapper.sol b/packages/contracts/src/2.0.0/forwarder/MixinExchangeWrapper.sol index f3aa483c5..4584bb840 100644 --- a/packages/contracts/src/2.0.0/forwarder/MixinExchangeWrapper.sol +++ b/packages/contracts/src/2.0.0/forwarder/MixinExchangeWrapper.sol @@ -139,7 +139,7 @@ contract MixinExchangeWrapper is /// @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 marketBuyWithWeth( + function marketBuyExactAmountWithWeth( LibOrder.Order[] memory orders, uint256 makerAssetFillAmount, bytes[] memory signatures @@ -180,10 +180,16 @@ contract MixinExchangeWrapper is addFillResults(totalFillResults, singleFillResults); // Stop execution if the entire amount of makerAsset has been bought - if (totalFillResults.makerAssetFilledAmount >= makerAssetFillAmount) { + uint256 makerAssetFilledAmount = totalFillResults.makerAssetFilledAmount; + if (makerAssetFilledAmount >= makerAssetFillAmount) { break; } } + + require( + makerAssetFilledAmount >= makerAssetFillAmount, + "COMPLETE_FILL_FAILED" + ); return totalFillResults; } @@ -196,7 +202,7 @@ contract MixinExchangeWrapper is /// @param zrxBuyAmount Desired amount of ZRX to buy. /// @param signatures Proofs that orders have been created by makers. /// @return totalFillResults Amounts filled and fees paid by maker and taker. - function marketBuyZrxWithWeth( + function marketBuyExactZrxWithWeth( LibOrder.Order[] memory orders, uint256 zrxBuyAmount, bytes[] memory signatures @@ -248,6 +254,10 @@ contract MixinExchangeWrapper is } } + require( + zrxPurchased >= zrxBuyAmount, + "COMPLETE_FILL_FAILED" + ); return totalFillResults; } } diff --git a/packages/contracts/src/2.0.0/forwarder/MixinForwarderCore.sol b/packages/contracts/src/2.0.0/forwarder/MixinForwarderCore.sol index 1164ae919..93cbf79be 100644 --- a/packages/contracts/src/2.0.0/forwarder/MixinForwarderCore.sol +++ b/packages/contracts/src/2.0.0/forwarder/MixinForwarderCore.sol @@ -23,7 +23,7 @@ import "./libs/LibConstants.sol"; import "./mixins/MWeth.sol"; import "./mixins/MAssets.sol"; import "./mixins/MExchangeWrapper.sol"; -import "./mixins/MForwarderCore.sol"; +import "./interfaces/IForwarderCore.sol"; import "../utils/LibBytes/LibBytes.sol"; import "../protocol/Exchange/libs/LibOrder.sol"; import "../protocol/Exchange/libs/LibFillResults.sol"; @@ -37,7 +37,7 @@ contract MixinForwarderCore is MWeth, MAssets, MExchangeWrapper, - MForwarderCore + IForwarderCore { using LibBytes for bytes; @@ -117,7 +117,7 @@ contract MixinForwarderCore is ); // Buy back all ZRX spent on fees. zrxBuyAmount = orderFillResults.takerFeePaid; - feeOrderFillResults = marketBuyZrxWithWeth( + feeOrderFillResults = marketBuyExactZrxWithWeth( feeOrders, zrxBuyAmount, feeSignatures @@ -125,13 +125,6 @@ contract MixinForwarderCore is makerAssetAmountPurchased = orderFillResults.makerAssetFilledAmount; } - // Ensure that all ZRX fees have been repurchased and no extra WETH owned by this contract has been sold. - assertValidFillResults( - orderFillResults, - feeOrderFillResults, - zrxBuyAmount - ); - // Transfer feePercentage of total ETH spent on primary orders to feeRecipient. // Refund remaining ETH to msg.sender. transferEthFeeAndRefund( @@ -142,7 +135,7 @@ contract MixinForwarderCore is ); // Transfer purchased assets to msg.sender. - transferPurchasedAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased); + transferAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased); } /// @dev Attempt to purchase makerAssetFillAmount of makerAsset by selling ETH provided with transaction. @@ -180,7 +173,7 @@ contract MixinForwarderCore is if (orders[0].makerAssetData.equals(ZRX_ASSET_DATA)) { // If the makerAsset is ZRX, it is not necessary to pay fees out of this // contracts's ZRX balance because fees are factored into the price of the order. - orderFillResults = marketBuyZrxWithWeth( + orderFillResults = marketBuyExactZrxWithWeth( orders, makerAssetFillAmount, signatures @@ -190,14 +183,14 @@ contract MixinForwarderCore is } else { // Attemp to purchase desired amount of makerAsset. // ZRX fees are payed with this contract's balance. - orderFillResults = marketBuyWithWeth( + orderFillResults = marketBuyExactAmountWithWeth( orders, makerAssetFillAmount, signatures ); // Buy back all ZRX spent on fees. zrxBuyAmount = orderFillResults.takerFeePaid; - feeOrderFillResults = marketBuyZrxWithWeth( + feeOrderFillResults = marketBuyExactZrxWithWeth( feeOrders, zrxBuyAmount, feeSignatures @@ -205,13 +198,6 @@ contract MixinForwarderCore is makerAssetAmountPurchased = orderFillResults.makerAssetFilledAmount; } - // Ensure that all ZRX fees have been repurchased and no extra WETH owned by this contract has been sold. - assertValidFillResults( - orderFillResults, - feeOrderFillResults, - zrxBuyAmount - ); - // Transfer feePercentage of total ETH spent on primary orders to feeRecipient. // Refund remaining ETH to msg.sender. transferEthFeeAndRefund( @@ -222,33 +208,6 @@ contract MixinForwarderCore is ); // Transfer purchased assets to msg.sender. - transferPurchasedAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased); - } - - /// @dev Ensures that all ZRX fees have been repurchased and no extra WETH owned by this contract has been sold. - /// @param orderFillResults Amounts filled and fees paid for primary orders. - /// @param feeOrderFillResults Amounts filled and fees paid for fee orders. - /// @param zrxBuyAmount The amount of ZRX that needed to be repurchased after filling primary orders. - function assertValidFillResults( - FillResults memory orderFillResults, - FillResults memory feeOrderFillResults, - uint256 zrxBuyAmount - ) - internal - view - { - // Ensure that all ZRX spent while filling primary orders has been repurchased. - uint256 zrxPurchased = safeSub(feeOrderFillResults.makerAssetFilledAmount, feeOrderFillResults.takerFeePaid); - require( - zrxPurchased >= zrxBuyAmount, - "COMPLETE_FILL_FAILED" - ); - - // Ensure that no extra WETH owned by this contract has been sold. - uint256 wethSold = safeAdd(orderFillResults.takerAssetFilledAmount, feeOrderFillResults.takerAssetFilledAmount); - require( - wethSold <= msg.value, - "OVERSOLD_WETH" - ); + transferAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased); } } diff --git a/packages/contracts/src/2.0.0/forwarder/MixinWeth.sol b/packages/contracts/src/2.0.0/forwarder/MixinWeth.sol index 8ba236e7f..e07940776 100644 --- a/packages/contracts/src/2.0.0/forwarder/MixinWeth.sol +++ b/packages/contracts/src/2.0.0/forwarder/MixinWeth.sol @@ -71,12 +71,16 @@ contract MixinWeth is "FEE_PERCENTAGE_TOO_LARGE" ); - // Calculate amount of WETH that hasn't been sold. - uint256 wethRemaining = safeSub( - msg.value, - safeAdd(wethSoldExcludingFeeOrders, wethSoldForZrx) + // Ensure that no extra WETH owned by this contract has been sold. + uint256 wethSold = safeAdd(wethSoldExcludingFeeOrders, wethSoldForZrx); + require( + wethSold <= msg.value, + "OVERSOLD_WETH" ); + // Calculate amount of WETH that hasn't been sold. + uint256 wethRemaining = safeSub(msg.value, wethSold); + // Calculate ETH fee to pay to feeRecipient. uint256 ethFee = getPartialAmount( feePercentage, diff --git a/packages/contracts/src/2.0.0/forwarder/interfaces/IAssets.sol b/packages/contracts/src/2.0.0/forwarder/interfaces/IAssets.sol index 9b0d995eb..1e034c003 100644 --- a/packages/contracts/src/2.0.0/forwarder/interfaces/IAssets.sol +++ b/packages/contracts/src/2.0.0/forwarder/interfaces/IAssets.sol @@ -21,13 +21,13 @@ pragma solidity 0.4.24; contract IAssets { - /// @dev Withdraws ERC20 tokens from this contract. The contract requires a ZRX balance in order to + /// @dev Withdraws assets from this contract. The contract requires a ZRX balance in order to /// function optimally, and this function allows the ZRX to be withdrawn by owner. It may also be - /// used to withdraw tokens that were accidentally sent to this contract. - /// @param token Address of ERC20 token to withdraw. + /// used to withdraw assets that were accidentally sent to this contract. + /// @param assetData Byte array encoded for the respective asset proxy. /// @param amount Amount of ERC20 token to withdraw. - function withdrawERC20( - address token, + function withdrawAsset( + bytes assetData, uint256 amount ) external; diff --git a/packages/contracts/src/2.0.0/forwarder/mixins/MAssets.sol b/packages/contracts/src/2.0.0/forwarder/mixins/MAssets.sol index 340ee0bcb..83636432a 100644 --- a/packages/contracts/src/2.0.0/forwarder/mixins/MAssets.sol +++ b/packages/contracts/src/2.0.0/forwarder/mixins/MAssets.sol @@ -28,7 +28,7 @@ contract MAssets is /// @dev Transfers given amount of asset to sender. /// @param assetData Byte array encoded for the respective asset proxy. /// @param amount Amount of asset to transfer to sender. - function transferPurchasedAssetToSender( + function transferAssetToSender( bytes memory assetData, uint256 amount ) diff --git a/packages/contracts/src/2.0.0/forwarder/mixins/MExchangeWrapper.sol b/packages/contracts/src/2.0.0/forwarder/mixins/MExchangeWrapper.sol index 5a2def7e5..360dea0e4 100644 --- a/packages/contracts/src/2.0.0/forwarder/mixins/MExchangeWrapper.sol +++ b/packages/contracts/src/2.0.0/forwarder/mixins/MExchangeWrapper.sol @@ -60,7 +60,7 @@ contract MExchangeWrapper { /// @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 marketBuyWithWeth( + function marketBuyExactAmountWithWeth( LibOrder.Order[] memory orders, uint256 makerAssetFillAmount, bytes[] memory signatures @@ -77,7 +77,7 @@ contract MExchangeWrapper { /// @param zrxBuyAmount Desired amount of ZRX to buy. /// @param signatures Proofs that orders have been created by makers. /// @return totalFillResults Amounts filled and fees paid by maker and taker. - function marketBuyZrxWithWeth( + function marketBuyExactZrxWithWeth( LibOrder.Order[] memory orders, uint256 zrxBuyAmount, bytes[] memory signatures diff --git a/packages/contracts/src/2.0.0/forwarder/mixins/MForwarderCore.sol b/packages/contracts/src/2.0.0/forwarder/mixins/MForwarderCore.sol deleted file mode 100644 index 0f5cd9c66..000000000 --- a/packages/contracts/src/2.0.0/forwarder/mixins/MForwarderCore.sol +++ /dev/null @@ -1,42 +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.24; -pragma experimental ABIEncoderV2; - -import "../../protocol/Exchange/libs/LibOrder.sol"; -import "../../protocol/Exchange/libs/LibFillResults.sol"; -import "../interfaces/IForwarderCore.sol"; - - -contract MForwarderCore is - IForwarderCore -{ - - /// @dev Ensures that all ZRX fees have been repurchased and no extra WETH owned by this contract has been sold. - /// @param orderFillResults Amounts filled and fees paid for primary orders. - /// @param feeOrderFillResults Amounts filled and fees paid for fee orders. - /// @param zrxBuyAmount The amount of ZRX that needed to be repurchased after filling primary orders. - function assertValidFillResults( - LibFillResults.FillResults memory orderFillResults, - LibFillResults.FillResults memory feeOrderFillResults, - uint256 zrxBuyAmount - ) - internal - view; -} diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol index ac7382715..44de54817 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinSignatureValidator.sol @@ -96,14 +96,15 @@ contract MixinSignatureValidator is "LENGTH_GREATER_THAN_0_REQUIRED" ); - // Ensure signature is supported + // Pop last byte off of signature byte array. uint8 signatureTypeRaw = uint8(signature.popLastByte()); + + // Ensure signature is supported require( signatureTypeRaw < uint8(SignatureType.NSignatureTypes), "SIGNATURE_UNSUPPORTED" ); - // Pop last byte off of signature byte array. SignatureType signatureType = SignatureType(signatureTypeRaw); // Variables are not scoped in Solidity. @@ -141,7 +142,12 @@ contract MixinSignatureValidator is v = uint8(signature[0]); r = signature.readBytes32(1); s = signature.readBytes32(33); - recovered = ecrecover(hash, v, r, s); + recovered = ecrecover( + hash, + v, + r, + s + ); isValid = signerAddress == recovered; return isValid; @@ -197,7 +203,6 @@ contract MixinSignatureValidator is // | 0x14 + x | 1 | Signature type is always "\x06" | } else if (signatureType == SignatureType.Validator) { // Pop last 20 bytes off of signature byte array. - address validatorAddress = signature.popLast20Bytes(); // Ensure signer has approved validator. diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol index 88d2da7d7..821d30279 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinTransactions.sol @@ -123,22 +123,25 @@ contract MixinTransactions is bytes32 dataHash = keccak256(data); // Assembly for more efficiently computing: - // keccak256(abi.encode( + // keccak256(abi.encodePacked( // EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH, // salt, - // signerAddress, + // bytes32(signerAddress), // keccak256(data) // )); assembly { + // Load free memory pointer let memPtr := mload(64) - mstore(memPtr, schemaHash) - mstore(add(memPtr, 32), salt) - mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff)) - mstore(add(memPtr, 96), dataHash) + + mstore(memPtr, schemaHash) // hash of schema + mstore(add(memPtr, 32), salt) // salt + mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff)) // signerAddress + mstore(add(memPtr, 96), dataHash) // hash of data + + // Compute hash result := keccak256(memPtr, 128) } - return result; } diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol index 704c7061c..4aad37709 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol @@ -24,20 +24,17 @@ import "./LibOrder.sol"; contract LibAbiEncoder { - /// @dev ABI encodes calldata for `fillOrder` in memory and returns the address range. - /// This range can be passed into `call` or `delegatecall` to invoke an external - /// call to `fillOrder`. + /// @dev ABI encodes calldata for `fillOrder`. /// @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 calldataBegin Memory address of ABI encoded calldata. - /// @return calldataLength Lenfgth of ABI encoded calldata. + /// @return ABI encoded calldata for `fillOrder`. function abiEncodeFillOrder( LibOrder.Order memory order, uint256 takerAssetFillAmount, bytes memory signature ) - public + internal pure returns (bytes memory fillOrderCalldata) { @@ -207,10 +204,10 @@ contract LibAbiEncoder { } // Set length of calldata - mstore( - fillOrderCalldata, - sub(dataAreaEnd, add(fillOrderCalldata, 0x20)) - ) + mstore(fillOrderCalldata, sub(dataAreaEnd, add(fillOrderCalldata, 0x20))) + + // Increment free memory pointer + mstore(0x40, dataAreaEnd) } return fillOrderCalldata; diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol index 1fc41dafd..b02f7632e 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibEIP712.sol @@ -30,7 +30,7 @@ contract LibEIP712 { string constant internal EIP712_DOMAIN_VERSION = "2"; // Hash of the EIP712 Domain Separator Schema - bytes32 public constant EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked( + bytes32 constant internal EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked( "EIP712Domain(", "string name,", "string version,", @@ -45,11 +45,11 @@ contract LibEIP712 { constructor () public { - EIP712_DOMAIN_HASH = keccak256(abi.encode( + EIP712_DOMAIN_HASH = keccak256(abi.encodePacked( EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH, keccak256(bytes(EIP712_DOMAIN_NAME)), keccak256(bytes(EIP712_DOMAIN_VERSION)), - address(this) + bytes32(address(this)) )); } @@ -59,8 +59,28 @@ contract LibEIP712 { function hashEIP712Message(bytes32 hashStruct) internal view - returns (bytes32) + returns (bytes32 result) { - return keccak256(abi.encodePacked(EIP191_HEADER, EIP712_DOMAIN_HASH, hashStruct)); + bytes32 eip712DomainHash = EIP712_DOMAIN_HASH; + + // Assembly for more efficient computing: + // keccak256(abi.encodePacked( + // EIP191_HEADER, + // EIP712_DOMAIN_HASH, + // hashStruct + // )); + + assembly { + // Load free memory pointer + let memPtr := mload(64) + + mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header + mstore(add(memPtr, 2), eip712DomainHash) // EIP712 domain hash + mstore(add(memPtr, 34), hashStruct) // Hash of struct + + // Compute hash + result := keccak256(memPtr, 66) + } + return result; } } diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol index 4031ff26b..68f4f5f1b 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibOrder.sol @@ -103,11 +103,12 @@ contract LibOrder is bytes32 takerAssetDataHash = keccak256(order.takerAssetData); // Assembly for more efficiently computing: - // keccak256(abi.encode( - // order.makerAddress, - // order.takerAddress, - // order.feeRecipientAddress, - // order.senderAddress, + // keccak256(abi.encodePacked( + // EIP712_ORDER_SCHEMA_HASH, + // bytes32(order.makerAddress), + // bytes32(order.takerAddress), + // bytes32(order.feeRecipientAddress), + // bytes32(order.senderAddress), // order.makerAssetAmount, // order.takerAssetAmount, // order.makerFee, @@ -119,24 +120,26 @@ contract LibOrder is // )); assembly { + // Calculate memory addresses that will be swapped out before hashing + let pos1 := sub(order, 32) + let pos2 := add(order, 320) + let pos3 := add(order, 352) + // Backup - // solhint-disable-next-line space-after-comma - let temp1 := mload(sub(order, 32)) - let temp2 := mload(add(order, 320)) - let temp3 := mload(add(order, 352)) + let temp1 := mload(pos1) + let temp2 := mload(pos2) + let temp3 := mload(pos3) // Hash in place - // solhint-disable-next-line space-after-comma - mstore(sub(order, 32), schemaHash) - mstore(add(order, 320), makerAssetDataHash) - mstore(add(order, 352), takerAssetDataHash) - result := keccak256(sub(order, 32), 416) + mstore(pos1, schemaHash) + mstore(pos2, makerAssetDataHash) + mstore(pos3, takerAssetDataHash) + result := keccak256(pos1, 416) // Restore - // solhint-disable-next-line space-after-comma - mstore(sub(order, 32), temp1) - mstore(add(order, 320), temp2) - mstore(add(order, 352), temp3) + mstore(pos1, temp1) + mstore(pos2, temp2) + mstore(pos3, temp3) } return result; } diff --git a/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol b/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol index 923bac97d..d9cec9edc 100644 --- a/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol +++ b/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol @@ -22,6 +22,7 @@ pragma experimental ABIEncoderV2; import "../../protocol/Exchange/Exchange.sol"; +// solhint-disable no-empty-blocks contract TestExchangeInternals is Exchange { diff --git a/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol b/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol index 5a349527b..4a99dd9c1 100644 --- a/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol +++ b/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol @@ -22,13 +22,33 @@ pragma experimental ABIEncoderV2; import "../../protocol/Exchange/libs/LibMath.sol"; import "../../protocol/Exchange/libs/LibOrder.sol"; import "../../protocol/Exchange/libs/LibFillResults.sol"; +import "../../protocol/Exchange/libs/LibAbiEncoder.sol"; contract TestLibs is LibMath, LibOrder, - LibFillResults + LibFillResults, + LibAbiEncoder { + + function publicAbiEncodeFillOrder( + Order memory order, + uint256 takerAssetFillAmount, + bytes memory signature + ) + public + pure + returns (bytes memory fillOrderCalldata) + { + fillOrderCalldata = abiEncodeFillOrder( + order, + takerAssetFillAmount, + signature + ); + return fillOrderCalldata; + } + function publicGetPartialAmount( uint256 numerator, uint256 denominator, |