Skip to content
This repository was archived by the owner on Jan 18, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .soliumrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
85 changes: 85 additions & 0 deletions contracts/core/external/ZeroExExchangeWrapper.sol
Original file line number Diff line number Diff line change
@@ -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 ============ */
}
202 changes: 202 additions & 0 deletions contracts/core/external/lib/ZeroExOrderDataHandler.sol
Original file line number Diff line number Diff line change
@@ -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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's 320? can you make it into a constant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add / update a table

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;
}
}
1 change: 1 addition & 0 deletions contracts/external/LibBytes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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"
);
Expand Down
67 changes: 67 additions & 0 deletions contracts/test/lib/ZeroExOrderDataHandlerLib.sol
Original file line number Diff line number Diff line change
@@ -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
);
}
}
Loading