From d61759f6dd084e0aad0771f0261fc2a9fe2c06ed Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 19 Jul 2018 16:02:54 +0200 Subject: Returns byte array instead of memory range for encoding fillOrder calldata --- .../protocol/Exchange/MixinWrapperFunctions.sol | 22 +++++++---------- .../2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol | 28 +++++++++++++--------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol index a5038f5cf..567f26c52 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol @@ -71,14 +71,10 @@ contract MixinWrapperFunctions is returns (FillResults memory fillResults) { // ABI encode calldata for `fillOrder` - ( - uint256 calldataBegin, - uint256 calldataLength - ) = abiEncodeFillOrder( + bytes memory fillOrderCalldata = abiEncodeFillOrder( order, takerAssetFillAmount, - signature, - this.fillOrder.selector + signature ); // Delegate to `fillOrder` and handle any exceptions gracefully @@ -86,9 +82,9 @@ contract MixinWrapperFunctions is let success := delegatecall( gas, // forward all gas, TODO: look into gas consumption of assert/throw address, // call address of this contract - calldataBegin, // pointer to start of input - calldataLength, // length of input - calldataBegin, // write output over input + add(fillOrderCalldata, 32), // pointer to start of input (skip array length in first 32 bytes) + mload(fillOrderCalldata), // length of input + fillOrderCalldata, // write output over input 128 // output size is 128 bytes ) switch success @@ -99,10 +95,10 @@ contract MixinWrapperFunctions is mstore(add(fillResults, 96), 0) } case 1 { - mstore(fillResults, mload(calldataBegin)) - mstore(add(fillResults, 32), mload(add(calldataBegin, 32))) - mstore(add(fillResults, 64), mload(add(calldataBegin, 64))) - mstore(add(fillResults, 96), mload(add(calldataBegin, 96))) + mstore(fillResults, mload(fillOrderCalldata)) + mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32))) + mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64))) + mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96))) } } return fillResults; 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 5bea607d6..507e69712 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 @@ -23,6 +23,10 @@ import "./LibOrder.sol"; contract LibAbiEncoder { + + // solhint-disable max-line-length + bytes4 constant internal FILL_ORDER_SELECTOR = bytes4(keccak256("fillOrder((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),uint256,bytes)")); + // solhint-enable max-line-length /// @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 @@ -35,14 +39,10 @@ contract LibAbiEncoder { function abiEncodeFillOrder( LibOrder.Order memory order, uint256 takerAssetFillAmount, - bytes memory signature, - bytes4 fillOrderSelector + bytes memory signature ) public - returns ( - uint256 calldataBegin, - uint256 calldataLength - ) + returns (bytes memory fillOrderCalldata) { // We need to call MExchangeCore.fillOrder using a delegatecall in // assembly so that we can intercept a call that throws. For this, we @@ -83,6 +83,8 @@ contract LibAbiEncoder { // [1]: https://solidity.readthedocs.io/en/develop/abi-spec.html + bytes4 fillOrderSelector = FILL_ORDER_SELECTOR; + assembly { // Areas below may use the following variables: @@ -96,9 +98,10 @@ contract LibAbiEncoder { /////// Setup Header Area /////// // Load free memory pointer - calldataBegin := mload(0x40) - mstore(calldataBegin, fillOrderSelector) - let headerAreaEnd := add(calldataBegin, 0x4) + fillOrderCalldata := mload(0x40) + // Leave 0x20 bytes to store the length + mstore(add(fillOrderCalldata, 0x20), fillOrderSelector) + let headerAreaEnd := add(fillOrderCalldata, 0x24) /////// Setup Params Area /////// // This area is preallocated and written to later. @@ -207,9 +210,12 @@ contract LibAbiEncoder { } // Set length of calldata - calldataLength := sub(dataAreaEnd, calldataBegin) + mstore( + fillOrderCalldata, + sub(dataAreaEnd, add(fillOrderCalldata, 0x20)) + ) } - return (calldataBegin, calldataLength); + return fillOrderCalldata; } } -- cgit v1.2.3