diff --git a/.soliumrc.json b/.soliumrc.json index e6ddaf36c..c3d5711fa 100644 --- a/.soliumrc.json +++ b/.soliumrc.json @@ -14,6 +14,7 @@ "security/no-block-members": 0, "security/no-named-returns": ["error"], "security/no-suicide-or-selfdestruct": ["error"], - "security/no-var": ["error"] + "security/no-var": ["error"], + "security/no-inline-assembly": "off" } } diff --git a/contracts/core/external/ZeroExExchangeWrapper.sol b/contracts/core/external/ZeroExExchangeWrapper.sol new file mode 100644 index 000000000..904949606 --- /dev/null +++ b/contracts/core/external/ZeroExExchangeWrapper.sol @@ -0,0 +1,85 @@ +/* + Copyright 2018 Set Labs Inc. + + 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 { SafeMath } from "zeppelin-solidity/contracts/math/SafeMath.sol"; +import { LibBytes } from "../../external/LibBytes.sol"; +import { ZeroExOrderDataHandler as ZeroEx } from "./lib/ZeroExOrderDataHandler.sol"; + + +/** + * @title ZeroExExchangeWrapper + * @author Set Protocol + * + * The ZeroExExchangeWrapper contract wrapper to interface with 0x V2 + */ +contract ZeroExExchangeWrapper +{ + using SafeMath for uint256; + + /* ============ State Variables ============ */ + + address public ZERO_EX_EXCHANGE; + address public ZERO_EX_PROXY; + + + /* ============ Constructor ============ */ + + constructor( + // address _zeroExExchange, + // address _zeroExProxy, + ) + public + { + // ZERO_EX_EXCHANGE = _zeroExExchange; + // ZERO_EX_PROXY = _zeroExProxy; + } + + + /* ============ Public Functions ============ */ + + function exchange( + address tradeOriginator, + bytes orderData + ) + external + // returns (uint256) + { + + // Parse fill Amount + // uint256 fillAmount = parseFillAmount(_orderData); + + // Slice the signature out. + + // Slice the Order + + // Construct the order + // Order memory order = parseZeroExOrder(orderData); + + // Move the required takerToken into the wrapper + + // Ensure allowance + + + // return 1; + } + + /* ============ Getters ============ */ + + /* ============ Private ============ */ +} diff --git a/contracts/core/external/lib/ZeroExOrderDataHandler.sol b/contracts/core/external/lib/ZeroExOrderDataHandler.sol new file mode 100644 index 000000000..ad08379f9 --- /dev/null +++ b/contracts/core/external/lib/ZeroExOrderDataHandler.sol @@ -0,0 +1,202 @@ +/* + Copyright 2018 Set Labs Inc. + + 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 { SafeMath } from "zeppelin-solidity/contracts/math/SafeMath.sol"; +import { LibBytes } from "../../../external/LibBytes.sol"; + + +/** + * @title ZeroExOrderDataHandler + * @author Set Protocol + * + * This library contains functions and structs to assist with parsing exchange orders data + */ +library ZeroExOrderDataHandler { + using SafeMath for uint256; + using LibBytes for bytes; + + // ============ Structs ============ + + struct Order { + address makerAddress; // Address that created the order. + address takerAddress; // Address that is allowed to fill the order. + address feeRecipientAddress; // Address that will recieve fees when order is filled. + address senderAddress; // Address that is allowed to call Exchange contract. + uint256 makerAssetAmount; // Amount of makerAsset being offered by maker. + uint256 takerAssetAmount; // Amount of takerAsset being bid on by maker. + uint256 makerFee; // Amount of ZRX paid to feeRecipient by maker + uint256 takerFee; // Amount of ZRX paid to feeRecipient by taker + uint256 expirationTimeSeconds; // Timestamp in seconds at which order expires. + uint256 salt; // Number to facilitate uniqueness of the order's hash. + bytes makerAssetData; // Encoded data when transferring makerAsset. + bytes takerAssetData; // Encoded data when transferring takerAsset. + } + + struct ZeroExHeader { + uint256 signatureLength; + uint256 orderLength; + uint256 makerAssetDataLength; + uint256 takerAssetDataLength; + } + + // ============ Internal Functions ============ + + // We construct the following to allow calling fillOrder on ZeroEx V2 Exchange + // The layout of this orderData is in the table below. + // + // | Section | Data | Offset | Length | Contents | + // |---------|-----------------------|---------------------|-----------------|-------------------------------| + // | Header | signatureLength | 0 | 32 | Num Bytes of 0x Signature | + // | | orderLength | 32 | 32 | Num Bytes of 0x Order | + // | | makerAssetDataLength | 64 | 32 | Num Bytes of maker asset data | + // | | takerAssetDataLength | 96 | 32 | Num Bytes of taker asset data | + // | Body | fillAmount | 128 | 32 | taker asset fill amouint | + // | | signature | 160 | signatureLength | signature in bytes | + // | | order | 160+signatureLength | orderLength | ZeroEx Order | + + /* + * Parses the header of the orderData + * Can only be called by authorized contracts. + * + * @param _orderData + * @return ZeroExHeader + */ + function parseOrderHeader(bytes _orderData) + internal + pure + returns (ZeroExHeader) + { + ZeroExHeader memory header; + + uint256 orderDataAddr = _orderData.contentAddress(); + + assembly { + mstore(header, mload(orderDataAddr)) // signatureLength + mstore(add(header, 32), mload(add(orderDataAddr, 32))) // orderLength + mstore(add(header, 64), mload(add(orderDataAddr, 64))) // makerAssetDataLength + mstore(add(header, 96), mload(add(orderDataAddr, 96))) // takerAssetDataLength + } + + return header; + } + + function parseFillAmount(bytes _orderData) + internal + pure + returns (uint256) + { + uint256 orderDataAddr = _orderData.contentAddress(); + uint256 fillAmount; + + assembly { + fillAmount := mload(add(orderDataAddr, 128)) + } + + return fillAmount; + } + + function sliceSignature(bytes _orderData, uint _signatureLength) + internal + pure + returns (bytes) + { + bytes memory signature = _orderData.slice(160, _signatureLength.add(160)); + return signature; + } + + function sliceZeroExOrder(bytes _orderData, uint _signatureLength, uint _orderLength) + internal + pure + returns (bytes) + { + uint256 orderDataAddr = _orderData.contentAddress(); + uint256 orderStartAddress = orderDataAddr.add(_signatureLength); + bytes memory order = _orderData.slice( + orderStartAddress, + orderStartAddress.add(_orderLength) + ); + return order; + } + + function parseZeroExOrder( + bytes _zeroExOrder, + uint _makerAssetDataLength, + uint _takerAssetDataLength + ) + internal + pure + returns (Order memory) + { + Order memory order; + uint256 orderDataAddr = _zeroExOrder.contentAddress(); + + // | Data | Location | Length | + // |----------------------------|----------|--------| + // | maker | 0 | | + // | taker | 32 | | + // | feeRecipient | 64 | | + // | senderAddress | 96 | | + // | makerAssetAmount | 128 | | + // | takerAssetAmount | 160 | | + // | makerFee | 192 | | + // | takerFee | 224 | | + // | expirationUnixTimeStampSec | 256 | | + // | salt | 288 | | + // | makerAssetData | 320 | ** | + // | takerAssetData | 320 + ** | *** | + // ** - Maker Asset Data Length + // *** - Taker Asset Data Length + assembly { + mstore(order, mload(orderDataAddr)) // maker + mstore(add(order, 32), mload(add(orderDataAddr, 32))) // taker + mstore(add(order, 64), mload(add(orderDataAddr, 64))) // feeRecipient + mstore(add(order, 96), mload(add(orderDataAddr, 96))) // senderAddress + mstore(add(order, 128), mload(add(orderDataAddr, 128))) // makerAssetAmount + mstore(add(order, 160), mload(add(orderDataAddr, 160))) // takerAssetAmount + mstore(add(order, 192), mload(add(orderDataAddr, 192))) // makerFee + mstore(add(order, 224), mload(add(orderDataAddr, 224))) // takerFee + mstore(add(order, 256), mload(add(orderDataAddr, 256))) // expirationUnixTimestampSec + mstore(add(order, 288), mload(add(orderDataAddr, 288))) // salt + } + + order.makerAssetData = _zeroExOrder.slice(320, _makerAssetDataLength.add(320)); + order.takerAssetData = _zeroExOrder.slice( + _makerAssetDataLength.add(320), + _makerAssetDataLength.add(320).add(_takerAssetDataLength) + ); + + return order; + } + + function parseZeroExOrderData(bytes _orderData) + internal + pure + returns(Order memory) + { + ZeroExHeader memory header = parseOrderHeader(_orderData); + + Order memory order = parseZeroExOrder( + sliceZeroExOrder(_orderData, header.signatureLength, header.orderLength), + header.makerAssetDataLength, + header.takerAssetDataLength + ); + + return order; + } +} diff --git a/contracts/external/LibBytes.sol b/contracts/external/LibBytes.sol index 0c6be6f23..1324a6637 100644 --- a/contracts/external/LibBytes.sol +++ b/contracts/external/LibBytes.sol @@ -179,6 +179,7 @@ library LibBytes { "FROM_LESS_THAN_TO_REQUIRED" ); require( + // NOTE: Set Protocol changed from `to < b.length` so that the last byte can be sliced off to <= b.length, "TO_LESS_THAN_LENGTH_REQUIRED" ); diff --git a/contracts/test/lib/ZeroExOrderDataHandlerLib.sol b/contracts/test/lib/ZeroExOrderDataHandlerLib.sol new file mode 100644 index 000000000..8b4f74d71 --- /dev/null +++ b/contracts/test/lib/ZeroExOrderDataHandlerLib.sol @@ -0,0 +1,67 @@ +pragma solidity 0.4.24; +pragma experimental "ABIEncoderV2"; + +import { ZeroExOrderDataHandler } from "../../core/external/lib/ZeroExOrderDataHandler.sol"; + + +// Mock class implementing internal OrderHandler methods +contract MockZeroExOrderDataHandlerLibrary { + function parseOrderDataHeader(bytes _orderData) + public + pure + returns (uint256[4]) + { + ZeroExOrderDataHandler.ZeroExHeader memory header = ZeroExOrderDataHandler.parseOrderHeader(_orderData); + return [ + header.signatureLength, + header.orderLength, + header.makerAssetDataLength, + header.takerAssetDataLength + ]; + } + + function parseFillAmount(bytes _orderData) + public + pure + returns (uint256) + { + return ZeroExOrderDataHandler.parseFillAmount(_orderData); + } + + function parseSignature(bytes _orderData) + public + pure + returns (bytes) + { + ZeroExOrderDataHandler.ZeroExHeader memory header = ZeroExOrderDataHandler.parseOrderHeader(_orderData); + uint256 signatureLength = header.signatureLength; + return ZeroExOrderDataHandler.sliceSignature(_orderData, signatureLength); + } + + function parseZeroExOrderData(bytes _orderData) + public + pure + returns(address[4], uint256[6], bytes, bytes) + { + ZeroExOrderDataHandler.Order memory order = ZeroExOrderDataHandler.parseZeroExOrderData(_orderData); + + return ( + [ + order.makerAddress, + order.takerAddress, + order.feeRecipientAddress, + order.senderAddress + ], + [ + order.makerAssetAmount, + order.takerAssetAmount, + order.makerFee, + order.takerFee, + order.expirationTimeSeconds, + order.salt + ], + order.makerAssetData, + order.takerAssetData + ); + } +} diff --git a/test/core/external/lib/mockZeroExOrderDataHandlerLibrary.spec.ts b/test/core/external/lib/mockZeroExOrderDataHandlerLibrary.spec.ts new file mode 100644 index 000000000..0f7c441e3 --- /dev/null +++ b/test/core/external/lib/mockZeroExOrderDataHandlerLibrary.spec.ts @@ -0,0 +1,204 @@ +import * as chai from "chai"; +import * as _ from "lodash"; +import * as ethUtil from "ethereumjs-util"; + +import * as ABIDecoder from "abi-decoder"; +import { BigNumber } from "bignumber.js"; + +// Types +import { Address, Bytes32, Log, UInt } from "../../../../types/common.js"; +import { ZeroExSignature, ZeroExOrderHeader, ZeroExOrder } from "../../../../types/zeroEx"; + +// Contract types +import { MockZeroExOrderDataHandlerLibraryContract } from "../../../../types/generated/mock_zero_ex_order_data_handler_library"; + +// Artifacts +const MockZeroExOrderDataHandlerLibrary = artifacts.require("MockZeroExOrderDataHandlerLibrary"); + +import { + bufferZeroExOrder, + createZeroExOrder, + getZeroExOrderLengthFromBuffer, + generateStandardZeroExOrderBytesArray, +} from "../../../utils/zeroExExchangeWrapper"; + +// Testing Set up +import { BigNumberSetup } from "../../../config/bigNumberSetup"; +import ChaiSetup from "../../../config/chaiSetup"; +BigNumberSetup.configure(); +ChaiSetup.configure(); +const { expect, assert } = chai; + +import { + DEFAULT_GAS, +} from "../../../utils/constants"; + +contract("MockZeroExOrderDataHandlerLibrary", (accounts) => { + const [ownerAccount, takerAddress, feeRecipientAddress, senderAddress] = accounts; + let zeroExExchangeWrapper: MockZeroExOrderDataHandlerLibraryContract; + + // Signature + let signature: ZeroExSignature = "ABCDEFgiHIJKLMNOPQRSTUVWXYZ"; + + // 0x Order Subject Data + let fillAmount = new BigNumber(5); + + let makerAssetAmount = new BigNumber(1); + let takerAssetAmount = new BigNumber(2); + let makerFee = new BigNumber(3); + let takerFee = new BigNumber(4); + let expirationTimeSeconds = new BigNumber(5); + let salt = new BigNumber(6); + let makerAssetData = "ABC"; + let takerAssetData = "XYZ"; + + let zeroExOrder: ZeroExOrder = createZeroExOrder( + ownerAccount, + takerAddress, + feeRecipientAddress, + senderAddress, + makerAssetAmount, + takerAssetAmount, + makerFee, + takerFee, + expirationTimeSeconds, + salt, + makerAssetData, + takerAssetData, + ); + + beforeEach(async () => { + const zeroExExchangeWrapperInstance = await MockZeroExOrderDataHandlerLibrary.new( + { from: ownerAccount, gas: DEFAULT_GAS }, + ); + + zeroExExchangeWrapper = new MockZeroExOrderDataHandlerLibraryContract( + web3.eth.contract(zeroExExchangeWrapperInstance.abi).at(zeroExExchangeWrapperInstance.address), + { from: ownerAccount }, + ); + }); + + describe("#parseOrderDataHeader", async () => { + // Header Subject Data + let signatureLength: UInt; + let zeroExOrderLength: BigNumber; + let makerAssetDataLength: BigNumber; + let takerAssetDataLength: BigNumber; + + + let subjectOrderData: Bytes32; + + beforeEach(async () => { + subjectOrderData = generateStandardZeroExOrderBytesArray( + zeroExOrder, + signature, + fillAmount, + ); + + const zeroExOrderBuffer = bufferZeroExOrder(zeroExOrder); + zeroExOrderLength = getZeroExOrderLengthFromBuffer(zeroExOrderBuffer); + + signatureLength = new BigNumber(signature.length); + makerAssetDataLength = new BigNumber(makerAssetData.length); + takerAssetDataLength = new BigNumber(takerAssetData.length); + }); + + async function subject(): Promise { + return zeroExExchangeWrapper.parseOrderDataHeader.callAsync(subjectOrderData); + } + + it("should correctly parse the order data header", async () => { + const [sigLen, zeroExOrderLen, makerAssetDataLen, takerAssetDataLen ] = await subject(); + + expect(sigLen).to.bignumber.equal(signatureLength); + expect(zeroExOrderLen).to.bignumber.equal(zeroExOrderLength); + expect(makerAssetDataLen).to.bignumber.equal(makerAssetDataLength); + expect(takerAssetDataLen).to.bignumber.equal(takerAssetDataLength); + }); + }); + + describe("#parseFillAmount", async () => { + let subjectOrderData: Bytes32; + + beforeEach(async () => { + subjectOrderData = generateStandardZeroExOrderBytesArray( + zeroExOrder, + signature, + fillAmount, + ); + }); + + async function subject(): Promise { + return zeroExExchangeWrapper.parseFillAmount.callAsync(subjectOrderData); + } + + it("correctly parse the fill amount", async () => { + const fillAmountResult = await subject(); + expect(fillAmountResult).to.be.bignumber.equal(fillAmount); + }); + }); + + describe("#parseSignature", async () => { + let subjectOrderData: Bytes32; + + beforeEach(async () => { + subjectOrderData = generateStandardZeroExOrderBytesArray( + zeroExOrder, + signature, + fillAmount, + ); + }); + + async function subject(): Promise { + return zeroExExchangeWrapper.parseSignature.callAsync(subjectOrderData); + } + + it("should correctly parse the signature", async () => { + const signatureResult = await subject(); + expect(web3.toAscii(signatureResult)).to.equal(signature); + }); + }); + + describe("#parseZeroExOrderData", async () => { + let subjectOrderData: Bytes32; + + beforeEach(async () => { + subjectOrderData = generateStandardZeroExOrderBytesArray( + zeroExOrder, + signature, + fillAmount, + ); + }); + + async function subject(): Promise { + return zeroExExchangeWrapper.parseZeroExOrderData.callAsync(subjectOrderData); + } + + it("should correctly parse the zeroEx order", async () => { + const [addresses, uints, makerAssetDataResult, takerAssetDataResult] = await subject(); + + const [makerResult, takerResult, feeRecipientResult, senderResult] = addresses; + const [ + makerAssetAmountResult, + takerAssetAmountResult, + makerFeeResult, + takerFeeResult, + expirationResult, + saltResult, + ] = uints; + + expect(ownerAccount).to.equal(makerResult); + expect(takerAddress).to.equal(takerResult); + expect(feeRecipientAddress).to.equal(feeRecipientResult); + expect(senderAddress).to.equal(senderResult); + expect(makerAssetAmount).to.be.bignumber.equal(makerAssetAmountResult); + expect(takerAssetAmount).to.be.bignumber.equal(takerAssetAmountResult); + expect(makerFee).to.be.bignumber.equal(makerFeeResult); + expect(takerFee).to.be.bignumber.equal(takerFeeResult); + expect(expirationTimeSeconds).to.be.bignumber.equal(expirationResult); + expect(salt).to.be.bignumber.equal(saltResult); + expect(makerAssetData).to.equal(web3.toAscii(makerAssetDataResult)); + expect(takerAssetData).to.equal(web3.toAscii(takerAssetDataResult)); + }); + }); +}); diff --git a/test/core/external/zeroExExchangeWrapper.spec.ts b/test/core/external/zeroExExchangeWrapper.spec.ts new file mode 100644 index 000000000..2e6cb1212 --- /dev/null +++ b/test/core/external/zeroExExchangeWrapper.spec.ts @@ -0,0 +1,47 @@ +import * as chai from "chai"; +import * as _ from "lodash"; +import * as ethUtil from "ethereumjs-util"; + +import * as ABIDecoder from "abi-decoder"; +import { BigNumber } from "bignumber.js"; + +// Types +import { Address, Bytes32, Log, UInt } from "../../../types/common.js"; +import { ZeroExSignature, ZeroExOrderHeader, ZeroExOrder } from "../../../types/zeroEx"; + +// Contract types +import { ZeroExExchangeWrapperContract } from "../../../types/generated/zero_ex_exchange_wrapper"; + +// Artifacts +const ZeroExExchangeWrapper = artifacts.require("ZeroExExchangeWrapper"); + +import { + createZeroExOrder, +} from "../../utils/zeroExExchangeWrapper"; + +// Testing Set up +import { BigNumberSetup } from "../../config/bigNumberSetup"; +import ChaiSetup from "../../config/chaiSetup"; +BigNumberSetup.configure(); +ChaiSetup.configure(); +const { expect, assert } = chai; + +import { + DEFAULT_GAS, +} from "../../utils/constants"; + +contract("ZeroExExchangeWrapper", (accounts) => { + const [ownerAccount, takerAddress, feeRecipientAddress, senderAddress] = accounts; + let zeroExExchangeWrapper: ZeroExExchangeWrapperContract; + + beforeEach(async () => { + const zeroExExchangeWrapperInstance = await ZeroExExchangeWrapper.new( + { from: ownerAccount, gas: DEFAULT_GAS }, + ); + + zeroExExchangeWrapper = new ZeroExExchangeWrapperContract( + web3.eth.contract(zeroExExchangeWrapperInstance.abi).at(zeroExExchangeWrapperInstance.address), + { from: ownerAccount }, + ); + }); +}); diff --git a/test/utils/zeroExExchangeWrapper.ts b/test/utils/zeroExExchangeWrapper.ts new file mode 100644 index 000000000..a47afc285 --- /dev/null +++ b/test/utils/zeroExExchangeWrapper.ts @@ -0,0 +1,131 @@ +import * as _ from "lodash"; +import * as ethUtil from "ethereumjs-util"; +import * as Web3 from "web3"; +const web3 = new Web3(); + +import { BigNumber } from "bignumber.js"; +import { Address, Bytes32, Bytes, UInt } from "../../types/common.js"; +import { ZeroExOrder, ZeroExSignature, ZeroExOrderHeader } from "../../types/zeroEx"; + +function bufferAndLPad32(input: any): Buffer { + return ethUtil.setLengthLeft(ethUtil.toBuffer(input), 32); +} + +export function createZeroExOrder( + makerAddress: Address, + takerAddress: Address, + feeRecipientAddress: Address, + senderAddress: Address, + makerAssetAmount: UInt, + takerAssetAmount: UInt, + makerFee: UInt, + takerFee: UInt, + expirationTimeSeconds: UInt, + salt: UInt, + makerAssetData: Bytes, + takerAssetData: Bytes, +): ZeroExOrder { + return { + makerAddress, + takerAddress, + feeRecipientAddress, + senderAddress, + makerAssetAmount, + takerAssetAmount, + makerFee, + takerFee, + expirationTimeSeconds, + salt, + makerAssetData, + takerAssetData, + } +} + +export function generateStandardZeroExOrderBytesArray( + zeroExOrder: ZeroExOrder, + signature: ZeroExSignature, + fillAmount: UInt, +) { + const { makerAssetData, takerAssetData } = zeroExOrder; + + const makerAssetDataLength = new BigNumber(makerAssetData.length); + const takerAssetDataLength = new BigNumber(takerAssetData.length); + + // Get signature length + const signatureLength: UInt = new BigNumber(signature.length); + + // Get order length + const zeroExOrderBuffer = bufferZeroExOrder(zeroExOrder); + const zeroExOrderLength = getZeroExOrderLengthFromBuffer(zeroExOrderBuffer); + + // Generate the standard byte array + return bufferArrayToHex( + bufferOrderHeader( + signatureLength, + zeroExOrderLength, + makerAssetDataLength, + takerAssetDataLength, + ) + .concat(bufferFillAmount(fillAmount)) + .concat(bufferSignature(signature)) + .concat(zeroExOrderBuffer) + ); +} + +export function getZeroExOrderLengthFromBuffer( + zeroExOrder: Buffer[], +): BigNumber { + return new BigNumber(Buffer.concat(zeroExOrder).length); +} + +export function bufferZeroExOrder( + order: ZeroExOrder, +): Buffer[] { + return [ + bufferAndLPad32(order.makerAddress), + bufferAndLPad32(order.takerAddress), + bufferAndLPad32(order.feeRecipientAddress), + bufferAndLPad32(order.senderAddress), + bufferAndLPad32(web3.toHex(order.makerAssetAmount)), + bufferAndLPad32(web3.toHex(order.takerAssetAmount)), + bufferAndLPad32(web3.toHex(order.makerFee)), + bufferAndLPad32(web3.toHex(order.takerFee)), + bufferAndLPad32(web3.toHex(order.expirationTimeSeconds)), + bufferAndLPad32(web3.toHex(order.salt)), + ethUtil.toBuffer(order.makerAssetData), + ethUtil.toBuffer(order.takerAssetData), + ]; +} + +function bufferOrderHeader( + signatureLength: UInt, + orderLength: UInt, + makerAssetDataLength: UInt, + takerAssetDataLength: UInt, +): Buffer[] { + return [ + bufferAndLPad32(web3.toHex(signatureLength)), + bufferAndLPad32(web3.toHex(orderLength)), + bufferAndLPad32(web3.toHex(makerAssetDataLength)), + bufferAndLPad32(web3.toHex(takerAssetDataLength)), + ]; +} + +function bufferFillAmount( + fillAmount: UInt = 0, +): Buffer[] { + return [bufferAndLPad32(web3.toHex(fillAmount))]; +} + +function bufferSignature( + signature: Bytes32 = '', +): Buffer[] { + return [ethUtil.toBuffer(signature)]; +} + +function bufferArrayToHex( + bufferArr: Buffer[] +): Bytes32 { + const buffer = Buffer.concat(bufferArr); + return ethUtil.bufferToHex(buffer); +} diff --git a/types/common.ts b/types/common.ts index b01c8ab01..1941421f3 100644 --- a/types/common.ts +++ b/types/common.ts @@ -50,6 +50,7 @@ export interface Log { export type Address = string; export type UInt = number | BigNumber; export type Bytes32 = string; +export type Bytes = string; export enum SolidityTypes { Address = 'address', diff --git a/types/zeroEx.d.ts b/types/zeroEx.d.ts new file mode 100644 index 000000000..e378fc4de --- /dev/null +++ b/types/zeroEx.d.ts @@ -0,0 +1,25 @@ +import { Address, Bytes, UInt } from "./common"; + +export interface ZeroExOrderHeader { + signatureLength: UInt; + orderLength: UInt; + makerAssetDataLength: UInt; + takerAssetDataLength: UInt; +} + +export interface ZeroExOrder { + makerAddress: Address; + takerAddress: Address; + feeRecipientAddress: Address; + senderAddress: Address; + makerAssetAmount: UInt; + takerAssetAmount: UInt; + makerFee: UInt; + takerFee: UInt; + expirationTimeSeconds: UInt; + salt: UInt; + makerAssetData: Bytes; + takerAssetData: Bytes; +} + +export type ZeroExSignature = string;