aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/src
diff options
context:
space:
mode:
authorAmir Bandeali <abandeali1@gmail.com>2018-06-10 10:01:28 +0800
committerAmir Bandeali <abandeali1@gmail.com>2018-06-13 02:45:02 +0800
commitee8c9b764d0ee153efa91075b35f3192b72be119 (patch)
tree0d74a5df1e25f58fe16e998c34404fbbdeb21c98 /packages/contracts/src
parent787015f5370718e31c7990446fb1da298ed13e6b (diff)
downloaddexon-sol-tools-ee8c9b764d0ee153efa91075b35f3192b72be119.tar
dexon-sol-tools-ee8c9b764d0ee153efa91075b35f3192b72be119.tar.gz
dexon-sol-tools-ee8c9b764d0ee153efa91075b35f3192b72be119.tar.bz2
dexon-sol-tools-ee8c9b764d0ee153efa91075b35f3192b72be119.tar.lz
dexon-sol-tools-ee8c9b764d0ee153efa91075b35f3192b72be119.tar.xz
dexon-sol-tools-ee8c9b764d0ee153efa91075b35f3192b72be119.tar.zst
dexon-sol-tools-ee8c9b764d0ee153efa91075b35f3192b72be119.zip
Pop id from assetData before dispatching to AssetProxies
Diffstat (limited to 'packages/contracts/src')
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol37
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol34
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol5
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol14
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol7
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol18
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol42
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol52
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol1
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol2
-rw-r--r--packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol21
-rw-r--r--packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol3
-rw-r--r--packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol24
-rw-r--r--packages/contracts/src/utils/exchange_wrapper.ts2
-rw-r--r--packages/contracts/src/utils/formatters.ts16
-rw-r--r--packages/contracts/src/utils/order_utils.ts3
16 files changed, 132 insertions, 149 deletions
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol
index dd25bf41a..ddcd78e93 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol
@@ -47,16 +47,7 @@ contract ERC20Proxy is
internal
{
// Decode asset data.
- (
- uint8 proxyId,
- address token
- ) = decodeERC20AssetData(assetData);
-
- // Data must be intended for this proxy.
- require(
- proxyId == PROXY_ID,
- ASSET_PROXY_ID_MISMATCH
- );
+ address token = readAddress(assetData, 0);
// Transfer tokens.
bool success = IERC20Token(token).transferFrom(from, to, amount);
@@ -75,30 +66,4 @@ contract ERC20Proxy is
{
return PROXY_ID;
}
-
- /// @dev Decodes ERC20 Asset data.
- /// @param assetData Encoded byte array.
- /// @return proxyId Intended ERC20 proxy id.
- /// @return token ERC20 token address.
- function decodeERC20AssetData(bytes memory assetData)
- internal
- pure
- returns (
- uint8 proxyId,
- address token
- )
- {
- // Validate encoded data length
- uint256 length = assetData.length;
- require(
- length == 21,
- LENGTH_21_REQUIRED
- );
-
- // Decode data
- token = readAddress(assetData, 0);
- proxyId = uint8(assetData[length - 1]);
-
- return (proxyId, token);
- }
}
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
index 25136133d..861fac2c1 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
@@ -46,30 +46,22 @@ contract ERC721Proxy is
)
internal
{
+ // There exists only 1 of each token.
+ require(
+ amount == 1,
+ INVALID_AMOUNT
+ );
+
// Decode asset data.
(
- uint8 proxyId,
address token,
uint256 tokenId,
bytes memory receiverData
) = decodeERC721AssetData(assetData);
-
- // Data must be intended for this proxy.
- require(
- proxyId == PROXY_ID,
- ASSET_PROXY_ID_MISMATCH
- );
-
- // There exists only 1 of each token.
- require(
- amount == 1,
- INVALID_AMOUNT
- );
-
// Transfer token. Saves gas by calling safeTransferFrom only
// when there is receiverData present. Either succeeds or throws.
- if(receiverData.length > 0) {
+ if (receiverData.length > 0) {
ERC721Token(token).safeTransferFrom(from, to, tokenId, receiverData);
} else {
ERC721Token(token).transferFrom(from, to, tokenId);
@@ -97,29 +89,19 @@ contract ERC721Proxy is
internal
pure
returns (
- uint8 proxyId,
address token,
uint256 tokenId,
bytes memory receiverData
)
{
- // Validate encoded data length
- uint256 length = assetData.length;
- require(
- length >= 53,
- LENGTH_AT_LEAST_53_REQUIRED
- );
-
// Decode asset data.
token = readAddress(assetData, 0);
tokenId = readUint256(assetData, 20);
- if (length > 53) {
+ if (assetData.length > 52) {
receiverData = readBytes(assetData, 52);
}
- proxyId = uint8(assetData[length - 1]);
return (
- proxyId,
token,
tokenId,
receiverData
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol
index 80180a0d9..65bdacdb7 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol
@@ -27,11 +27,6 @@ contract LibAssetProxyErrors {
string constant AUTHORIZED_ADDRESS_MISMATCH = "AUTHORIZED_ADDRESS_MISMATCH"; // Address at index does not match given target address.
/// AssetProxy errors ///
- string constant ASSET_PROXY_ID_MISMATCH = "ASSET_PROXY_ID_MISMATCH"; // Proxy id in metadata does not match this proxy id.
string constant INVALID_AMOUNT = "INVALID_AMOUNT"; // Transfer amount must equal 1.
string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Transfer failed.
-
- /// Length validation errors ///
- string constant LENGTH_21_REQUIRED = "LENGTH_21_REQUIRED"; // Byte array must have a length of 21.
- string constant LENGTH_AT_LEAST_53_REQUIRED = "LENGTH_AT_LEAST_53_REQUIRED"; // Byte array must have a length of at least 53.
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
index e77d81c06..9e0246303 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
@@ -19,12 +19,14 @@
pragma solidity ^0.4.24;
import "../../utils/Ownable/Ownable.sol";
+import "../../utils/LibBytes/LibBytes.sol";
import "./libs/LibExchangeErrors.sol";
import "./mixins/MAssetProxyDispatcher.sol";
import "../AssetProxy/interfaces/IAssetProxy.sol";
contract MixinAssetProxyDispatcher is
Ownable,
+ LibBytes,
LibExchangeErrors,
MAssetProxyDispatcher
{
@@ -81,11 +83,13 @@ contract MixinAssetProxyDispatcher is
/// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
/// @param assetData Byte array encoded for the respective asset proxy.
+ /// @param assetProxyId Id of assetProxy to dispach to.
/// @param from Address to transfer token from.
/// @param to Address to transfer token to.
/// @param amount Amount of token to transfer.
function dispatchTransferFrom(
bytes memory assetData,
+ uint8 assetProxyId,
address from,
address to,
uint256 amount
@@ -94,16 +98,8 @@ contract MixinAssetProxyDispatcher is
{
// Do nothing if no amount should be transferred.
if (amount > 0) {
-
- // Lookup asset proxy
- uint256 length = assetData.length;
- require(
- length > 0,
- LENGTH_GREATER_THAN_0_REQUIRED
- );
- uint8 assetProxyId = uint8(assetData[length - 1]);
+ // Lookup assetProxy
IAssetProxy assetProxy = assetProxies[assetProxyId];
-
// transferFrom will either succeed or throw.
assetProxy.transferFrom(assetData, from, to, amount);
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
index 12b57d99f..0a0f0209a 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
@@ -108,9 +108,6 @@ contract MixinExchangeCore is
// Compute proportional fill amounts
fillResults = calculateFillResults(order, takerAssetFilledAmount);
- // Settle order
- settleOrder(order, takerAddress, fillResults);
-
// Update exchange internal state
updateFilledState(
order,
@@ -119,6 +116,10 @@ contract MixinExchangeCore is
orderInfo.orderTakerAssetFilledAmount,
fillResults
);
+
+ // Settle order
+ settleOrder(order, takerAddress, fillResults);
+
return fillResults;
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol
index ed76287e0..517b743fe 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinMatchOrders.sol
@@ -14,7 +14,6 @@
pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
-import "../../utils/LibBytes/LibBytes.sol";
import "./libs/LibMath.sol";
import "./libs/LibOrder.sol";
import "./libs/LibFillResults.sol";
@@ -25,7 +24,6 @@ import "./mixins/MSettlement.sol";
import "./mixins/MTransactions.sol";
contract MixinMatchOrders is
- LibBytes,
LibMath,
LibExchangeErrors,
MExchangeCore,
@@ -94,14 +92,6 @@ contract MixinMatchOrders is
rightSignature
);
- // Settle matched orders. Succeeds or throws.
- settleMatchedOrders(
- leftOrder,
- rightOrder,
- takerAddress,
- matchedFillResults
- );
-
// Update exchange state
updateFilledState(
leftOrder,
@@ -117,6 +107,14 @@ contract MixinMatchOrders is
rightOrderInfo.orderTakerAssetFilledAmount,
matchedFillResults.right
);
+
+ // Settle matched orders. Succeeds or throws.
+ settleMatchedOrders(
+ leftOrder,
+ rightOrder,
+ takerAddress,
+ matchedFillResults
+ );
return matchedFillResults;
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
index 83e9dfdf4..f0caf7446 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
@@ -19,6 +19,7 @@
pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
+import "../../utils/LibBytes/LibBytes.sol";
import "./libs/LibMath.sol";
import "./libs/LibFillResults.sol";
import "./libs/LibOrder.sol";
@@ -28,6 +29,7 @@ import "./mixins/MSettlement.sol";
import "./mixins/MAssetProxyDispatcher.sol";
contract MixinSettlement is
+ LibBytes,
LibMath,
LibExchangeErrors,
MMatchOrders,
@@ -37,7 +39,7 @@ contract MixinSettlement is
// ZRX metadata used for fee transfers.
// This will be constant throughout the life of the Exchange contract,
// since ZRX will always be transferred via the ERC20 AssetProxy.
- bytes internal ZRX_PROXY_DATA;
+ bytes internal ZRX_ASSET_DATA;
/// @dev Gets the ZRX metadata used for fee transfers.
function zrxAssetData()
@@ -45,7 +47,7 @@ contract MixinSettlement is
view
returns (bytes memory)
{
- return ZRX_PROXY_DATA;
+ return ZRX_ASSET_DATA;
}
/// TODO: _zrxAssetData should be a constant in production.
@@ -54,7 +56,7 @@ contract MixinSettlement is
constructor (bytes memory _zrxAssetData)
public
{
- ZRX_PROXY_DATA = _zrxAssetData;
+ ZRX_ASSET_DATA = _zrxAssetData;
}
/// @dev Settles an order by transferring assets between counterparties.
@@ -68,26 +70,34 @@ contract MixinSettlement is
)
internal
{
+ uint8 makerAssetProxyId = uint8(popByte(order.makerAssetData));
+ uint8 takerAssetProxyId = uint8(popByte(order.takerAssetData));
+ bytes memory zrxAssetData = ZRX_ASSET_DATA;
+ uint8 zrxProxyId = uint8(popByte(zrxAssetData));
dispatchTransferFrom(
order.makerAssetData,
+ makerAssetProxyId,
order.makerAddress,
takerAddress,
fillResults.makerAssetFilledAmount
);
dispatchTransferFrom(
order.takerAssetData,
+ takerAssetProxyId,
takerAddress,
order.makerAddress,
fillResults.takerAssetFilledAmount
);
dispatchTransferFrom(
- ZRX_PROXY_DATA,
+ zrxAssetData,
+ zrxProxyId,
order.makerAddress,
order.feeRecipientAddress,
fillResults.makerFeePaid
);
dispatchTransferFrom(
- ZRX_PROXY_DATA,
+ zrxAssetData,
+ zrxProxyId,
takerAddress,
order.feeRecipientAddress,
fillResults.takerFeePaid
@@ -107,21 +117,28 @@ contract MixinSettlement is
)
internal
{
+ uint8 leftMakerAssetProxyId = uint8(popByte(leftOrder.makerAssetData));
+ uint8 rightMakerAssetProxyId = uint8(popByte(rightOrder.makerAssetData));
+ bytes memory zrxAssetData = ZRX_ASSET_DATA;
+ uint8 zrxProxyId = uint8(popByte(zrxAssetData));
// Order makers and taker
dispatchTransferFrom(
leftOrder.makerAssetData,
+ leftMakerAssetProxyId,
leftOrder.makerAddress,
rightOrder.makerAddress,
matchedFillResults.right.takerAssetFilledAmount
);
dispatchTransferFrom(
rightOrder.makerAssetData,
+ rightMakerAssetProxyId,
rightOrder.makerAddress,
leftOrder.makerAddress,
matchedFillResults.left.takerAssetFilledAmount
);
dispatchTransferFrom(
leftOrder.makerAssetData,
+ leftMakerAssetProxyId,
leftOrder.makerAddress,
takerAddress,
matchedFillResults.leftMakerAssetSpreadAmount
@@ -129,13 +146,15 @@ contract MixinSettlement is
// Maker fees
dispatchTransferFrom(
- ZRX_PROXY_DATA,
+ zrxAssetData,
+ zrxProxyId,
leftOrder.makerAddress,
leftOrder.feeRecipientAddress,
matchedFillResults.left.makerFeePaid
);
dispatchTransferFrom(
- ZRX_PROXY_DATA,
+ zrxAssetData,
+ zrxProxyId,
rightOrder.makerAddress,
rightOrder.feeRecipientAddress,
matchedFillResults.right.makerFeePaid
@@ -144,7 +163,8 @@ contract MixinSettlement is
// Taker fees
if (leftOrder.feeRecipientAddress == rightOrder.feeRecipientAddress) {
dispatchTransferFrom(
- ZRX_PROXY_DATA,
+ zrxAssetData,
+ zrxProxyId,
takerAddress,
leftOrder.feeRecipientAddress,
safeAdd(
@@ -154,13 +174,15 @@ contract MixinSettlement is
);
} else {
dispatchTransferFrom(
- ZRX_PROXY_DATA,
+ zrxAssetData,
+ zrxProxyId,
takerAddress,
leftOrder.feeRecipientAddress,
matchedFillResults.left.takerFeePaid
);
dispatchTransferFrom(
- ZRX_PROXY_DATA,
+ zrxAssetData,
+ zrxProxyId,
takerAddress,
rightOrder.feeRecipientAddress,
matchedFillResults.right.takerFeePaid
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
index e09f80bcc..cd5e26fb7 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
@@ -335,12 +335,13 @@ contract MixinWrapperFunctions is
{
for (uint256 i = 0; i < orders.length; i++) {
- // Token being sold by taker must be the same for each order
- // TODO: optimize by only using takerAssetData for first order.
- require(
- areBytesEqual(orders[i].takerAssetData, orders[0].takerAssetData),
- ASSET_DATA_MISMATCH
- );
+ // We assume that asset being sold by taker is the same for each order.
+ // Rather than passing this in as calldata, we copy the takerAssetData from the first order onto all later orders.
+ // We cannot reference the same takerAssetData byte array because the array is modified when a trade is settled.
+ uint256 next = i + 1;
+ if (next != orders.length) {
+ deepCopyBytes(orders[next].takerAssetData, orders[i].takerAssetData);
+ }
// Calculate the remaining amount of takerAsset to sell
uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount);
@@ -379,12 +380,13 @@ contract MixinWrapperFunctions is
{
for (uint256 i = 0; i < orders.length; i++) {
- // Token being sold by taker must be the same for each order
- // TODO: optimize by only using takerAssetData for first order.
- require(
- areBytesEqual(orders[i].takerAssetData, orders[0].takerAssetData),
- ASSET_DATA_MISMATCH
- );
+ // We assume that asset being sold by taker is the same for each order.
+ // Rather than passing this in as calldata, we copy the takerAssetData from the first order onto all later orders.
+ // We cannot reference the same takerAssetData byte array because the array is modified when a trade is settled.
+ uint256 next = i + 1;
+ if (next != orders.length) {
+ deepCopyBytes(orders[next].takerAssetData, orders[i].takerAssetData);
+ }
// Calculate the remaining amount of takerAsset to sell
uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount);
@@ -422,12 +424,13 @@ contract MixinWrapperFunctions is
{
for (uint256 i = 0; i < orders.length; i++) {
- // Token being bought by taker must be the same for each order
- // TODO: optimize by only using makerAssetData for first order.
- require(
- areBytesEqual(orders[i].makerAssetData, orders[0].makerAssetData),
- ASSET_DATA_MISMATCH
- );
+ // We assume that asset being bought by taker is the same for each order.
+ // Rather than passing this in as calldata, we copy the makerAssetData from the first order onto all later orders.
+ // We cannot reference the same makerAssetData byte array because the array is modified when a trade is settled.
+ uint256 next = i + 1;
+ if (next != orders.length) {
+ deepCopyBytes(orders[next].makerAssetData, orders[i].makerAssetData);
+ }
// Calculate the remaining amount of makerAsset to buy
uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);
@@ -474,12 +477,13 @@ contract MixinWrapperFunctions is
{
for (uint256 i = 0; i < orders.length; i++) {
- // Token being bought by taker must be the same for each order
- // TODO: optimize by only using makerAssetData for first order.
- require(
- areBytesEqual(orders[i].makerAssetData, orders[0].makerAssetData),
- ASSET_DATA_MISMATCH
- );
+ // We assume that asset being bought by taker is the same for each order.
+ // Rather than passing this in as calldata, we copy the makerAssetData from the first order onto all later orders.
+ // We cannot reference the same makerAssetData byte array because the array is modified when a trade is settled.
+ uint256 next = i + 1;
+ if (next != orders.length) {
+ deepCopyBytes(orders[next].makerAssetData, orders[i].makerAssetData);
+ }
// Calculate the remaining amount of makerAsset to buy
uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol
index 2b4bbeec4..48dd0f8be 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol
@@ -25,7 +25,6 @@ contract LibExchangeErrors {
string constant INVALID_TAKER = "INVALID_TAKER"; // Invalid takerAddress.
string constant INVALID_SENDER = "INVALID_SENDER"; // Invalid `msg.sender`.
string constant INVALID_ORDER_SIGNATURE = "INVALID_ORDER_SIGNATURE"; // Signature validation failed.
- string constant ASSET_DATA_MISMATCH = "ASSET_DATA_MISMATCH"; // Asset data must be the same for each order.
/// fillOrder validation errors ///
string constant INVALID_TAKER_AMOUNT = "INVALID_TAKER_AMOUNT"; // takerAssetFillAmount cannot equal 0.
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
index 82eafb529..d16a830f4 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
@@ -34,11 +34,13 @@ contract MAssetProxyDispatcher is
/// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
/// @param assetData Byte array encoded for the respective asset proxy.
+ /// @param assetProxyId Id of assetProxy to dispach to.
/// @param from Address to transfer token from.
/// @param to Address to transfer token to.
/// @param amount Amount of token to transfer.
function dispatchTransferFrom(
bytes memory assetData,
+ uint8 assetProxyId,
address from,
address to,
uint256 amount
diff --git a/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol b/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol
index 2c6a8fdb0..5987291d2 100644
--- a/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol
+++ b/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol
@@ -23,26 +23,8 @@ import "../../protocol/AssetProxy/ERC20Proxy.sol";
import "../../protocol/AssetProxy/ERC721Proxy.sol";
contract TestAssetDataDecoders is
- ERC20Proxy,
ERC721Proxy
{
-
- /// @dev Decodes ERC20 Asset data.
- /// @param assetData Encoded byte array.
- /// @return proxyId Intended ERC20 proxy id.
- /// @return token ERC20 token address.
- function publicDecodeERC20Data(bytes memory assetData)
- public
- pure
- returns (
- uint8 proxyId,
- address token
- )
- {
- (proxyId, token) = decodeERC20AssetData(assetData);
- return (proxyId, token);
- }
-
/// @dev Decodes ERC721 Asset data.
/// @param assetData Encoded byte array.
/// @return proxyId Intended ERC721 proxy id.
@@ -54,21 +36,18 @@ contract TestAssetDataDecoders is
public
pure
returns (
- uint8 proxyId,
address token,
uint256 tokenId,
bytes memory receiverData
)
{
(
- proxyId,
token,
tokenId,
receiverData
) = decodeERC721AssetData(assetData);
return (
- proxyId,
token,
tokenId,
receiverData
diff --git a/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol
index 2ae69e0ef..d469a07f0 100644
--- a/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol
@@ -24,11 +24,12 @@ import "../../protocol/Exchange/MixinAssetProxyDispatcher.sol";
contract TestAssetProxyDispatcher is MixinAssetProxyDispatcher {
function publicDispatchTransferFrom(
bytes memory assetData,
+ uint8 assetProxyId,
address from,
address to,
uint256 amount)
public
{
- dispatchTransferFrom(assetData, from, to, amount);
+ dispatchTransferFrom(assetData, assetProxyId, from, to, amount);
}
}
diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol
index d1d10476f..aac0ffc31 100644
--- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol
+++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol
@@ -30,6 +30,7 @@ contract LibBytes is
string constant GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED";
string constant GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED";
string constant GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED";
+ string constant GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED";
/// @dev Pops the last byte off of a byte array by modifying its length.
/// @param b Byte array that will be modified.
@@ -114,6 +115,29 @@ contract LibBytes is
return equal;
}
+ /// @dev Performs a deep copy of a byte array onto another byte array of greater than or equal length.
+ /// @param dest Byte array that will be overwritten with source bytes.
+ /// @param source Byte array to copy onto dest bytes.
+ function deepCopyBytes(
+ bytes memory dest,
+ bytes memory source
+ )
+ internal
+ pure
+ {
+ uint256 sourceLen = source.length;
+ // Dest length must be >= source length, or some bytes would not be copied.
+ require(
+ dest.length >= sourceLen,
+ GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED
+ );
+ memCopy(
+ getMemAddress(dest) + 32, // +32 to skip length of <dest>
+ getMemAddress(source) + 32, // +32 to skip length of <source>
+ sourceLen
+ );
+ }
+
/// @dev Reads an address from a position in a byte array.
/// @param b Byte array containing an address.
/// @param index Index in byte array of address.
diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts
index a8ca5183e..6603538b9 100644
--- a/packages/contracts/src/utils/exchange_wrapper.ts
+++ b/packages/contracts/src/utils/exchange_wrapper.ts
@@ -165,7 +165,7 @@ export class ExchangeWrapper {
public async marketBuyOrdersNoThrowAsync(
orders: SignedOrder[],
from: string,
- opts: { makerAssetFillAmount: BigNumber },
+ opts: { makerAssetFillAmount: BigNumber; gas?: number },
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketBuyOrders(orders, opts.makerAssetFillAmount);
const txHash = await this._exchange.marketBuyOrdersNoThrow.sendTransactionAsync(
diff --git a/packages/contracts/src/utils/formatters.ts b/packages/contracts/src/utils/formatters.ts
index 1035f2d7c..b25dec27c 100644
--- a/packages/contracts/src/utils/formatters.ts
+++ b/packages/contracts/src/utils/formatters.ts
@@ -28,8 +28,14 @@ export const formatters = {
signatures: [],
takerAssetFillAmount,
};
- _.forEach(signedOrders, signedOrder => {
+ _.forEach(signedOrders, (signedOrder, i) => {
const orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
+ if (i !== 0) {
+ orderWithoutExchangeAddress.takerAssetData = `0x${_.repeat(
+ '0',
+ signedOrders[0].takerAssetData.length - 2,
+ )}`;
+ }
marketSellOrders.orders.push(orderWithoutExchangeAddress);
marketSellOrders.signatures.push(signedOrder.signature);
});
@@ -41,8 +47,14 @@ export const formatters = {
signatures: [],
makerAssetFillAmount,
};
- _.forEach(signedOrders, signedOrder => {
+ _.forEach(signedOrders, (signedOrder, i) => {
const orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
+ if (i !== 0) {
+ orderWithoutExchangeAddress.makerAssetData = `0x${_.repeat(
+ '0',
+ signedOrders[0].makerAssetData.length - 2,
+ )}`;
+ }
marketBuyOrders.orders.push(orderWithoutExchangeAddress);
marketBuyOrders.signatures.push(signedOrder.signature);
});
diff --git a/packages/contracts/src/utils/order_utils.ts b/packages/contracts/src/utils/order_utils.ts
index 2a8791e4c..a9f994d80 100644
--- a/packages/contracts/src/utils/order_utils.ts
+++ b/packages/contracts/src/utils/order_utils.ts
@@ -1,6 +1,7 @@
import { OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
+import { constants } from './constants';
import { CancelOrder, MatchOrder } from './types';
export const orderUtils = {
@@ -43,6 +44,8 @@ export const orderUtils = {
leftSignature: signedOrderLeft.signature,
rightSignature: signedOrderRight.signature,
};
+ fill.right.makerAssetData = constants.NULL_BYTES;
+ fill.right.takerAssetData = constants.NULL_BYTES;
return fill;
},
};