From ed0fcf2829aacd81a79c29d51d3a5b08b23d0655 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 21 May 2019 12:01:56 -0500 Subject: [PATCH] Remove LibAbiEncoder --- .../contracts/src/MixinExchangeWrapper.sol | 7 +- contracts/exchange-libs/compiler.json | 1 - .../contracts/src/LibAbiEncoder.sol | 215 ------------------ .../exchange-libs/contracts/test/TestLibs.sol | 21 +- contracts/exchange-libs/package.json | 2 +- contracts/exchange-libs/src/artifacts.ts | 2 - contracts/exchange-libs/src/wrappers.ts | 1 - contracts/exchange-libs/tsconfig.json | 1 - .../contracts/src/MixinWrapperFunctions.sol | 2 +- .../utils/fill_order_combinatorial_utils.ts | 15 -- 10 files changed, 7 insertions(+), 260 deletions(-) delete mode 100644 contracts/exchange-libs/contracts/src/LibAbiEncoder.sol diff --git a/contracts/exchange-forwarder/contracts/src/MixinExchangeWrapper.sol b/contracts/exchange-forwarder/contracts/src/MixinExchangeWrapper.sol index 032067627e..33672623da 100644 --- a/contracts/exchange-forwarder/contracts/src/MixinExchangeWrapper.sol +++ b/contracts/exchange-forwarder/contracts/src/MixinExchangeWrapper.sol @@ -21,17 +21,17 @@ pragma experimental ABIEncoderV2; import "./libs/LibConstants.sol"; import "./mixins/MExchangeWrapper.sol"; -import "@0x/contracts-exchange-libs/contracts/src/LibAbiEncoder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol"; +import "@0x/contracts-exchange-libs/contracts/src/LibExchangeSelectors.sol"; contract MixinExchangeWrapper is - LibAbiEncoder, LibFillResults, LibMath, LibConstants, + LibExchangeSelectors, MExchangeWrapper { /// @dev Fills the input order. @@ -49,7 +49,8 @@ contract MixinExchangeWrapper is returns (FillResults memory fillResults) { // ABI encode calldata for `fillOrder` - bytes memory fillOrderCalldata = _abiEncodeFillOrder( + bytes memory fillOrderCalldata = abi.encodeWithSelector( + FILL_ORDER_SELECTOR, order, takerAssetFillAmount, signature diff --git a/contracts/exchange-libs/compiler.json b/contracts/exchange-libs/compiler.json index f599203b88..36f80e9b3f 100644 --- a/contracts/exchange-libs/compiler.json +++ b/contracts/exchange-libs/compiler.json @@ -24,7 +24,6 @@ } }, "contracts": [ - "src/LibAbiEncoder.sol", "src/LibConstants.sol", "src/LibEIP712ExchangeDomain.sol", "src/LibFillResults.sol", diff --git a/contracts/exchange-libs/contracts/src/LibAbiEncoder.sol b/contracts/exchange-libs/contracts/src/LibAbiEncoder.sol deleted file mode 100644 index a83d45560e..0000000000 --- a/contracts/exchange-libs/contracts/src/LibAbiEncoder.sol +++ /dev/null @@ -1,215 +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.5.5; -pragma experimental ABIEncoderV2; - -import "./LibOrder.sol"; - - -contract LibAbiEncoder { - - /// @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 ABI encoded calldata for `fillOrder`. - function _abiEncodeFillOrder( - LibOrder.Order memory order, - uint256 takerAssetFillAmount, - bytes memory signature - ) - internal - pure - 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 - // need the input encoded in memory in the Ethereum ABIv2 format [1]. - - // | Area | Offset | Length | Contents | - // | -------- |--------|---------|-------------------------------------------- | - // | Header | 0x00 | 4 | function selector | - // | Params | | 3 * 32 | function parameters: | - // | | 0x00 | | 1. offset to order (*) | - // | | 0x20 | | 2. takerAssetFillAmount | - // | | 0x40 | | 3. offset to signature (*) | - // | Data | | 12 * 32 | order: | - // | | 0x000 | | 1. senderAddress | - // | | 0x020 | | 2. makerAddress | - // | | 0x040 | | 3. takerAddress | - // | | 0x060 | | 4. feeRecipientAddress | - // | | 0x080 | | 5. makerAssetAmount | - // | | 0x0A0 | | 6. takerAssetAmount | - // | | 0x0C0 | | 7. makerFeeAmount | - // | | 0x0E0 | | 8. takerFeeAmount | - // | | 0x100 | | 9. expirationTimeSeconds | - // | | 0x120 | | 10. salt | - // | | 0x140 | | 11. Offset to makerAssetData (*) | - // | | 0x160 | | 12. Offset to takerAssetData (*) | - // | | 0x180 | 32 | makerAssetData Length | - // | | 0x1A0 | ** | makerAssetData Contents | - // | | 0x1C0 | 32 | takerAssetData Length | - // | | 0x1E0 | ** | takerAssetData Contents | - // | | 0x200 | 32 | signature Length | - // | | 0x220 | ** | signature Contents | - - // * Offsets are calculated from the beginning of the current area: Header, Params, Data: - // An offset stored in the Params area is calculated from the beginning of the Params section. - // An offset stored in the Data area is calculated from the beginning of the Data section. - - // ** The length of dynamic array contents are stored in the field immediately preceeding the contents. - - // [1]: https://solidity.readthedocs.io/en/develop/abi-spec.html - - assembly { - - // Areas below may use the following variables: - // 1. Start -- Start of this area in memory - // 2. End -- End of this area in memory. This value may - // be precomputed (before writing contents), - // or it may be computed as contents are written. - // 3. Offset -- Current offset into area. If an area's End - // is precomputed, this variable tracks the - // offsets of contents as they are written. - - /////// Setup Header Area /////// - // Load free memory pointer - fillOrderCalldata := mload(0x40) - // bytes4(keccak256("fillOrder((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),uint256,bytes)")) - // = 0xb4be83d5 - // Leave 0x20 bytes to store the length - mstore(add(fillOrderCalldata, 0x20), 0xb4be83d500000000000000000000000000000000000000000000000000000000) - let headerAreaEnd := add(fillOrderCalldata, 0x24) - - /////// Setup Params Area /////// - // This area is preallocated and written to later. - // This is because we need to fill in offsets that have not yet been calculated. - let paramsAreaStart := headerAreaEnd - let paramsAreaEnd := add(paramsAreaStart, 0x60) - let paramsAreaOffset := paramsAreaStart - - /////// Setup Data Area /////// - let dataAreaStart := paramsAreaEnd - let dataAreaEnd := dataAreaStart - - // Offset from the source data we're reading from - let sourceOffset := order - // arrayLenBytes and arrayLenWords track the length of a dynamically-allocated bytes array. - let arrayLenBytes := 0 - let arrayLenWords := 0 - - /////// Write order Struct /////// - // Write memory location of Order, relative to the start of the - // parameter list, then increment the paramsAreaOffset respectively. - mstore(paramsAreaOffset, sub(dataAreaEnd, paramsAreaStart)) - paramsAreaOffset := add(paramsAreaOffset, 0x20) - - // Write values for each field in the order - // It would be nice to use a loop, but we save on gas by writing - // the stores sequentially. - mstore(dataAreaEnd, mload(sourceOffset)) // makerAddress - mstore(add(dataAreaEnd, 0x20), mload(add(sourceOffset, 0x20))) // takerAddress - mstore(add(dataAreaEnd, 0x40), mload(add(sourceOffset, 0x40))) // feeRecipientAddress - mstore(add(dataAreaEnd, 0x60), mload(add(sourceOffset, 0x60))) // senderAddress - mstore(add(dataAreaEnd, 0x80), mload(add(sourceOffset, 0x80))) // makerAssetAmount - mstore(add(dataAreaEnd, 0xA0), mload(add(sourceOffset, 0xA0))) // takerAssetAmount - mstore(add(dataAreaEnd, 0xC0), mload(add(sourceOffset, 0xC0))) // makerFeeAmount - mstore(add(dataAreaEnd, 0xE0), mload(add(sourceOffset, 0xE0))) // takerFeeAmount - mstore(add(dataAreaEnd, 0x100), mload(add(sourceOffset, 0x100))) // expirationTimeSeconds - mstore(add(dataAreaEnd, 0x120), mload(add(sourceOffset, 0x120))) // salt - mstore(add(dataAreaEnd, 0x140), mload(add(sourceOffset, 0x140))) // Offset to makerAssetData - mstore(add(dataAreaEnd, 0x160), mload(add(sourceOffset, 0x160))) // Offset to takerAssetData - dataAreaEnd := add(dataAreaEnd, 0x180) - sourceOffset := add(sourceOffset, 0x180) - - // Write offset to - mstore(add(dataAreaStart, mul(10, 0x20)), sub(dataAreaEnd, dataAreaStart)) - - // Calculate length of - sourceOffset := mload(add(order, 0x140)) // makerAssetData - arrayLenBytes := mload(sourceOffset) - sourceOffset := add(sourceOffset, 0x20) - arrayLenWords := div(add(arrayLenBytes, 0x1F), 0x20) - - // Write length of - mstore(dataAreaEnd, arrayLenBytes) - dataAreaEnd := add(dataAreaEnd, 0x20) - - // Write contents of - for {let i := 0} lt(i, arrayLenWords) {i := add(i, 1)} { - mstore(dataAreaEnd, mload(sourceOffset)) - dataAreaEnd := add(dataAreaEnd, 0x20) - sourceOffset := add(sourceOffset, 0x20) - } - - // Write offset to - mstore(add(dataAreaStart, mul(11, 0x20)), sub(dataAreaEnd, dataAreaStart)) - - // Calculate length of - sourceOffset := mload(add(order, 0x160)) // takerAssetData - arrayLenBytes := mload(sourceOffset) - sourceOffset := add(sourceOffset, 0x20) - arrayLenWords := div(add(arrayLenBytes, 0x1F), 0x20) - - // Write length of - mstore(dataAreaEnd, arrayLenBytes) - dataAreaEnd := add(dataAreaEnd, 0x20) - - // Write contents of - for {let i := 0} lt(i, arrayLenWords) {i := add(i, 1)} { - mstore(dataAreaEnd, mload(sourceOffset)) - dataAreaEnd := add(dataAreaEnd, 0x20) - sourceOffset := add(sourceOffset, 0x20) - } - - /////// Write takerAssetFillAmount /////// - mstore(paramsAreaOffset, takerAssetFillAmount) - paramsAreaOffset := add(paramsAreaOffset, 0x20) - - /////// Write signature /////// - // Write offset to paramsArea - mstore(paramsAreaOffset, sub(dataAreaEnd, paramsAreaStart)) - - // Calculate length of signature - sourceOffset := signature - arrayLenBytes := mload(sourceOffset) - sourceOffset := add(sourceOffset, 0x20) - arrayLenWords := div(add(arrayLenBytes, 0x1F), 0x20) - - // Write length of signature - mstore(dataAreaEnd, arrayLenBytes) - dataAreaEnd := add(dataAreaEnd, 0x20) - - // Write contents of signature - for {let i := 0} lt(i, arrayLenWords) {i := add(i, 1)} { - mstore(dataAreaEnd, mload(sourceOffset)) - dataAreaEnd := add(dataAreaEnd, 0x20) - sourceOffset := add(sourceOffset, 0x20) - } - - // Set length of calldata - mstore(fillOrderCalldata, sub(dataAreaEnd, add(fillOrderCalldata, 0x20))) - - // Increment free memory pointer - mstore(0x40, dataAreaEnd) - } - - return fillOrderCalldata; - } -} diff --git a/contracts/exchange-libs/contracts/test/TestLibs.sol b/contracts/exchange-libs/contracts/test/TestLibs.sol index 1ae1843059..8548e0fbdd 100644 --- a/contracts/exchange-libs/contracts/test/TestLibs.sol +++ b/contracts/exchange-libs/contracts/test/TestLibs.sol @@ -23,7 +23,6 @@ import "../src/LibEIP712ExchangeDomain.sol"; import "../src/LibMath.sol"; import "../src/LibOrder.sol"; import "../src/LibFillResults.sol"; -import "../src/LibAbiEncoder.sol"; // solhint-disable no-empty-blocks @@ -31,31 +30,13 @@ contract TestLibs is LibEIP712ExchangeDomain, LibMath, LibOrder, - LibFillResults, - LibAbiEncoder + LibFillResults { constructor (uint256 chainId) public LibEIP712ExchangeDomain(chainId, address(0)) {} - function abiEncodeFillOrder( - Order memory order, - uint256 takerAssetFillAmount, - bytes memory signature - ) - public - pure - returns (bytes memory fillOrderCalldata) - { - fillOrderCalldata = _abiEncodeFillOrder( - order, - takerAssetFillAmount, - signature - ); - return fillOrderCalldata; - } - function getPartialAmountFloor( uint256 numerator, uint256 denominator, diff --git a/contracts/exchange-libs/package.json b/contracts/exchange-libs/package.json index 9240967b77..fcc73c2dac 100644 --- a/contracts/exchange-libs/package.json +++ b/contracts/exchange-libs/package.json @@ -34,7 +34,7 @@ "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol" }, "config": { - "abis": "./generated-artifacts/@(LibAbiEncoder|LibAssetProxyErrors|LibConstants|LibEIP712ExchangeDomain|LibFillResults|LibMath|LibOrder|LibZeroExTransaction|TestLibs).json", + "abis": "./generated-artifacts/@(LibAssetProxyErrors|LibConstants|LibEIP712ExchangeDomain|LibFillResults|LibMath|LibOrder|LibZeroExTransaction|TestLibs).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/exchange-libs/src/artifacts.ts b/contracts/exchange-libs/src/artifacts.ts index 700d08af69..6b3159f20a 100644 --- a/contracts/exchange-libs/src/artifacts.ts +++ b/contracts/exchange-libs/src/artifacts.ts @@ -5,7 +5,6 @@ */ import { ContractArtifact } from 'ethereum-types'; -import * as LibAbiEncoder from '../generated-artifacts/LibAbiEncoder.json'; import * as LibConstants from '../generated-artifacts/LibConstants.json'; import * as LibEIP712ExchangeDomain from '../generated-artifacts/LibEIP712ExchangeDomain.json'; import * as LibFillResults from '../generated-artifacts/LibFillResults.json'; @@ -14,7 +13,6 @@ import * as LibOrder from '../generated-artifacts/LibOrder.json'; import * as LibZeroExTransaction from '../generated-artifacts/LibZeroExTransaction.json'; import * as TestLibs from '../generated-artifacts/TestLibs.json'; export const artifacts = { - LibAbiEncoder: LibAbiEncoder as ContractArtifact, LibConstants: LibConstants as ContractArtifact, LibFillResults: LibFillResults as ContractArtifact, LibMath: LibMath as ContractArtifact, diff --git a/contracts/exchange-libs/src/wrappers.ts b/contracts/exchange-libs/src/wrappers.ts index 4d9adda8cf..4908d5a01a 100644 --- a/contracts/exchange-libs/src/wrappers.ts +++ b/contracts/exchange-libs/src/wrappers.ts @@ -3,7 +3,6 @@ * Warning: This file is auto-generated by contracts-gen. Don't edit manually. * ----------------------------------------------------------------------------- */ -export * from '../generated-wrappers/lib_abi_encoder'; export * from '../generated-wrappers/lib_constants'; export * from '../generated-wrappers/lib_e_i_p712_exchange_domain'; export * from '../generated-wrappers/lib_fill_results'; diff --git a/contracts/exchange-libs/tsconfig.json b/contracts/exchange-libs/tsconfig.json index 08efc17267..c189082e61 100644 --- a/contracts/exchange-libs/tsconfig.json +++ b/contracts/exchange-libs/tsconfig.json @@ -3,7 +3,6 @@ "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true }, "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"], "files": [ - "generated-artifacts/LibAbiEncoder.json", "generated-artifacts/LibConstants.json", "generated-artifacts/LibEIP712ExchangeDomain.json", "generated-artifacts/LibFillResults.json", diff --git a/contracts/exchange/contracts/src/MixinWrapperFunctions.sol b/contracts/exchange/contracts/src/MixinWrapperFunctions.sol index 0412b45cc6..d7f8ccd1b6 100644 --- a/contracts/exchange/contracts/src/MixinWrapperFunctions.sol +++ b/contracts/exchange/contracts/src/MixinWrapperFunctions.sol @@ -33,7 +33,7 @@ contract MixinWrapperFunctions is ReentrancyGuard, LibMath, LibFillResults, - LibAbiEncoder, + LibExchangeSelectors, MExchangeCore, MWrapperFunctions, MExchangeRichErrors diff --git a/contracts/exchange/test/utils/fill_order_combinatorial_utils.ts b/contracts/exchange/test/utils/fill_order_combinatorial_utils.ts index a3cb1e25f7..3e331c7b31 100644 --- a/contracts/exchange/test/utils/fill_order_combinatorial_utils.ts +++ b/contracts/exchange/test/utils/fill_order_combinatorial_utils.ts @@ -431,8 +431,6 @@ export class FillOrderCombinatorialUtils { lazyStore, fillRevertReasonIfExists, ); - - await this._abiEncodeFillOrderAndAssertOutcomeAsync(signedOrder, takerAssetFillAmount); } private async _fillOrderAndAssertOutcomeAsync( signedOrder: SignedOrder, @@ -609,19 +607,6 @@ export class FillOrderCombinatorialUtils { 'ZRXAssetBalanceOfFeeRecipient', ); } - private async _abiEncodeFillOrderAndAssertOutcomeAsync( - signedOrder: SignedOrder, - takerAssetFillAmount: BigNumber, - ): Promise { - const params = orderUtils.createFill(signedOrder, takerAssetFillAmount); - const abiDataEncodedByContract = await this.testLibsContract.abiEncodeFillOrder.callAsync( - params.order, - params.takerAssetFillAmount, - params.signature, - ); - const paramsDecodedByClient = this.exchangeWrapper.abiDecodeFillOrder(abiDataEncodedByContract); - expect(paramsDecodedByClient).to.be.deep.equal(params, 'ABIEncodedFillOrderData'); - } private async _getTakerAssetFillAmountAsync( signedOrder: SignedOrder, takerAssetFillAmountScenario: TakerAssetFillAmountScenario,