@0x/contracts-zero-ex: Address review feedback.

This commit is contained in:
Lawrence Forman
2020-05-28 11:55:25 -04:00
parent bf84409839
commit ecfbd6280f
8 changed files with 133 additions and 83 deletions

View File

@@ -130,7 +130,13 @@ library LibTransformERC20RichErrors {
); );
} }
enum InvalidTransformDataErrorCode {
INVALID_TOKENS,
INVALID_ARRAY_LENGTH
}
function InvalidTransformDataError( function InvalidTransformDataError(
InvalidTransformDataErrorCode errorCode,
bytes memory transformData bytes memory transformData
) )
internal internal
@@ -138,7 +144,8 @@ library LibTransformERC20RichErrors {
returns (bytes memory) returns (bytes memory)
{ {
return abi.encodeWithSelector( return abi.encodeWithSelector(
bytes4(keccak256("InvalidTransformDataError(bytes)")), bytes4(keccak256("InvalidTransformDataError(uint8,bytes)")),
errorCode,
transformData transformData
); );
} }

View File

@@ -35,8 +35,16 @@ import "./LibERC20Transformer.sol";
contract FillQuoteTransformer is contract FillQuoteTransformer is
Transformer Transformer
{ {
/// @dev Whether we are performing a market sell or buy.
enum Side {
Sell,
Buy
}
/// @dev Transform data to ABI-encode and pass into `transform()`. /// @dev Transform data to ABI-encode and pass into `transform()`.
struct TransformData { struct TransformData {
// Whether we aer performing a market sell or buy.
Side side;
// The token being sold. // The token being sold.
// This should be an actual token, not the ETH pseudo-token. // This should be an actual token, not the ETH pseudo-token.
IERC20TokenV06 sellToken; IERC20TokenV06 sellToken;
@@ -52,11 +60,10 @@ contract FillQuoteTransformer is
// For sells, this will be the maximum sell amount (taker asset). // For sells, this will be the maximum sell amount (taker asset).
// For buys, this will be the maximum buy amount (maker asset). // For buys, this will be the maximum buy amount (maker asset).
uint256[] maxOrderFillAmounts; uint256[] maxOrderFillAmounts;
// Amount of `sellToken` to sell. May be `uint256(-1)` to sell entire // Amount of `sellToken` to sell or `buyToken` to buy.
// amount of `sellToken` received. Zero if performing a market buy. // For sells, this may be `uint256(-1)` to sell the entire balance of
uint256 sellAmount; // `sellToken`.
// Amount of `buyToken` to buy. Zero if performing a market sell. uint256 fillAmount;
uint256 buyAmount;
} }
/// @dev Results of a call to `_fillOrder()`. /// @dev Results of a call to `_fillOrder()`.
@@ -96,7 +103,6 @@ contract FillQuoteTransformer is
/// @dev Sell this contract's entire balance of of `sellToken` in exchange /// @dev Sell this contract's entire balance of of `sellToken` in exchange
/// for `buyToken` by filling `orders`. Protocol fees should be attached /// for `buyToken` by filling `orders`. Protocol fees should be attached
/// to this call. `buyToken` and excess ETH will be transferred back to the caller. /// to this call. `buyToken` and excess ETH will be transferred back to the caller.
/// This function cannot be re-entered.
/// @param data_ ABI-encoded `TransformData`. /// @param data_ ABI-encoded `TransformData`.
/// @return rlpDeploymentNonce RLP-encoded deployment nonce of the deployer /// @return rlpDeploymentNonce RLP-encoded deployment nonce of the deployer
/// when this transformer was deployed. This is used to verify that /// when this transformer was deployed. This is used to verify that
@@ -113,23 +119,29 @@ contract FillQuoteTransformer is
TransformData memory data = abi.decode(data_, (TransformData)); TransformData memory data = abi.decode(data_, (TransformData));
// Validate data fields. // Validate data fields.
if (data.sellToken.isTokenETH() || if (data.sellToken.isTokenETH() || data.buyToken.isTokenETH()) {
data.buyToken.isTokenETH() || LibTransformERC20RichErrors.InvalidTransformDataError(
data.orders.length != data.signatures.length) LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_TOKENS,
{ data_
LibTransformERC20RichErrors.InvalidTransformDataError(data_).rrevert(); ).rrevert();
}
if (data.orders.length != data.signatures.length) {
LibTransformERC20RichErrors.InvalidTransformDataError(
LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_ARRAY_LENGTH,
data_
).rrevert();
} }
// If `sellAmount == -1` and `buyAmount == 0` then we are selling if (data.side == Side.Sell && data.fillAmount == uint256(-1)) {
// the entire balance of `sellToken`. This is useful in cases where // If `sellAmount == -1 then we are selling
// the exact sell amount is not exactly known in advance, like when // the entire balance of `sellToken`. This is useful in cases where
// unwrapping Chai/cUSDC/cDAI. // the exact sell amount is not exactly known in advance, like when
if (data.sellAmount == uint256(-1) && data.buyAmount == 0) { // unwrapping Chai/cUSDC/cDAI.
data.sellAmount = data.sellToken.getTokenBalanceOf(address(this)); data.fillAmount = data.sellToken.getTokenBalanceOf(address(this));
} }
// Approve the ERC20 proxy to spend `sellToken`. // Approve the ERC20 proxy to spend `sellToken`.
data.sellToken.approveIfBelow(erc20Proxy, data.sellAmount); data.sellToken.approveIfBelow(erc20Proxy, data.fillAmount);
// Fill the orders. // Fill the orders.
uint256 singleProtocolFee = exchange.protocolFeeMultiplier().safeMul(tx.gasprice); uint256 singleProtocolFee = exchange.protocolFeeMultiplier().safeMul(tx.gasprice);
@@ -138,14 +150,14 @@ contract FillQuoteTransformer is
uint256 soldAmount = 0; uint256 soldAmount = 0;
for (uint256 i = 0; i < data.orders.length; ++i) { for (uint256 i = 0; i < data.orders.length; ++i) {
// Check if we've hit our targets. // Check if we've hit our targets.
if (data.buyAmount == 0) { if (data.side == Side.Sell) {
// Market sell check. // Market sell check.
if (soldAmount >= data.sellAmount) { if (soldAmount >= data.fillAmount) {
break; break;
} }
} else { } else {
// Market buy check. // Market buy check.
if (boughtAmount >= data.buyAmount) { if (boughtAmount >= data.fillAmount) {
break; break;
} }
} }
@@ -159,14 +171,14 @@ contract FillQuoteTransformer is
// Fill the order. // Fill the order.
FillOrderResults memory results; FillOrderResults memory results;
if (data.buyAmount == 0) { if (data.side == Side.Sell) {
// Market sell. // Market sell.
results = _sellToOrder( results = _sellToOrder(
data.buyToken, data.buyToken,
data.sellToken, data.sellToken,
data.orders[i], data.orders[i],
data.signatures[i], data.signatures[i],
data.sellAmount.safeSub(soldAmount).min256( data.fillAmount.safeSub(soldAmount).min256(
data.maxOrderFillAmounts.length > i data.maxOrderFillAmounts.length > i
? data.maxOrderFillAmounts[i] ? data.maxOrderFillAmounts[i]
: uint256(-1) : uint256(-1)
@@ -180,7 +192,7 @@ contract FillQuoteTransformer is
data.sellToken, data.sellToken,
data.orders[i], data.orders[i],
data.signatures[i], data.signatures[i],
data.buyAmount.safeSub(boughtAmount).min256( data.fillAmount.safeSub(boughtAmount).min256(
data.maxOrderFillAmounts.length > i data.maxOrderFillAmounts.length > i
? data.maxOrderFillAmounts[i] ? data.maxOrderFillAmounts[i]
: uint256(-1) : uint256(-1)
@@ -196,24 +208,24 @@ contract FillQuoteTransformer is
} }
// Ensure we hit our targets. // Ensure we hit our targets.
if (data.buyAmount == 0) { if (data.side == Side.Sell) {
// Market sell check. // Market sell check.
if (soldAmount < data.sellAmount) { if (soldAmount < data.fillAmount) {
LibTransformERC20RichErrors LibTransformERC20RichErrors
.IncompleteFillSellQuoteError( .IncompleteFillSellQuoteError(
address(data.sellToken), address(data.sellToken),
soldAmount, soldAmount,
data.sellAmount data.fillAmount
).rrevert(); ).rrevert();
} }
} else { } else {
// Market buy check. // Market buy check.
if (boughtAmount < data.buyAmount) { if (boughtAmount < data.fillAmount) {
LibTransformERC20RichErrors LibTransformERC20RichErrors
.IncompleteFillBuyQuoteError( .IncompleteFillBuyQuoteError(
address(data.buyToken), address(data.buyToken),
boughtAmount, boughtAmount,
data.buyAmount data.fillAmount
).rrevert(); ).rrevert();
} }
} }
@@ -238,9 +250,8 @@ contract FillQuoteTransformer is
private private
returns (FillOrderResults memory results) returns (FillOrderResults memory results)
{ {
IERC20TokenV06 takerFeeToken = order.takerFeeAssetData.length == 0 IERC20TokenV06 takerFeeToken =
? IERC20TokenV06(address(0)) _getTokenFromERC20AssetData(order.takerFeeAssetData);
: _getTokenFromERC20AssetData(order.takerFeeAssetData);
uint256 takerTokenFillAmount = sellAmount; uint256 takerTokenFillAmount = sellAmount;
@@ -261,7 +272,7 @@ contract FillQuoteTransformer is
takerTokenFillAmount = LibMathV06.getPartialAmountCeil( takerTokenFillAmount = LibMathV06.getPartialAmountCeil(
order.takerAssetAmount, order.takerAssetAmount,
order.takerAssetAmount.safeAdd(order.takerFee), order.takerAssetAmount.safeAdd(order.takerFee),
takerTokenFillAmount sellAmount
); );
} else { } else {
// Only support taker or maker asset denominated taker fees. // Only support taker or maker asset denominated taker fees.
@@ -306,24 +317,27 @@ contract FillQuoteTransformer is
private private
returns (FillOrderResults memory results) returns (FillOrderResults memory results)
{ {
IERC20TokenV06 takerFeeToken = order.takerFeeAssetData.length == 0 IERC20TokenV06 takerFeeToken =
? IERC20TokenV06(address(0)) _getTokenFromERC20AssetData(order.takerFeeAssetData);
: _getTokenFromERC20AssetData(order.takerFeeAssetData); // Compute the default taker token fill amount.
uint256 takerTokenFillAmount = LibMathV06.getPartialAmountCeil(
uint256 makerTokenFillAmount = buyAmount; buyAmount,
order.makerAssetAmount,
order.takerAssetAmount
);
if (order.takerFee != 0) { if (order.takerFee != 0) {
if (takerFeeToken == makerToken) { if (takerFeeToken == makerToken) {
// Taker fee is payable in the maker token. // Taker fee is payable in the maker token.
// Increase the fill amount to account for maker tokens being // Adjust the taker token fill amount to account for maker
// lost to the taker fee. // tokens being lost to the taker fee.
// makerTokenFillAmount' = // takerTokenFillAmount' =
// (order.makerAssetAmount * makerTokenFillAmount) / // (order.takerAssetAmount * buyAmount) /
// (order.makerAssetAmount - order.takerFee) // (order.makerAssetAmount - order.takerFee)
makerTokenFillAmount = LibMathV06.getPartialAmountCeil( takerTokenFillAmount = LibMathV06.getPartialAmountCeil(
order.makerAssetAmount, buyAmount,
order.makerAssetAmount.safeSub(order.takerFee), order.makerAssetAmount.safeSub(order.takerFee),
makerTokenFillAmount order.takerAssetAmount
); );
// Approve the proxy to spend the maker token. // Approve the proxy to spend the maker token.
// It isn't worth computing the actual taker fee // It isn't worth computing the actual taker fee
@@ -338,14 +352,10 @@ contract FillQuoteTransformer is
} }
} }
// Convert maker fill amount to taker fill amount. // Clamp to order size.
uint256 takerTokenFillAmount = LibSafeMathV06.min256( takerTokenFillAmount = LibSafeMathV06.min256(
order.takerAssetAmount, order.takerAssetAmount,
LibMathV06.getPartialAmountCeil( takerTokenFillAmount
makerTokenFillAmount,
order.makerAssetAmount,
order.takerAssetAmount
)
); );
// Perform the fill. // Perform the fill.
@@ -380,7 +390,7 @@ contract FillQuoteTransformer is
returns (FillOrderResults memory results) returns (FillOrderResults memory results)
{ {
// Track changes in the maker token balance. // Track changes in the maker token balance.
results.makerTokenBoughtAmount = makerToken.balanceOf(address(this)); uint256 initialMakerTokenBalance = makerToken.balanceOf(address(this));
try try
exchange.fillOrder exchange.fillOrder
{value: protocolFee} {value: protocolFee}
@@ -389,7 +399,7 @@ contract FillQuoteTransformer is
{ {
// Update maker quantity based on changes in token balances. // Update maker quantity based on changes in token balances.
results.makerTokenBoughtAmount = makerToken.balanceOf(address(this)) results.makerTokenBoughtAmount = makerToken.balanceOf(address(this))
.safeSub(results.makerTokenBoughtAmount); .safeSub(initialMakerTokenBalance);
// We can trust the other fill result quantities. // We can trust the other fill result quantities.
results.protocolFeePaid = fillResults.protocolFeePaid; results.protocolFeePaid = fillResults.protocolFeePaid;
results.takerTokenSoldAmount = fillResults.takerAssetFilledAmount; results.takerTokenSoldAmount = fillResults.takerAssetFilledAmount;
@@ -400,18 +410,21 @@ contract FillQuoteTransformer is
results.takerTokenSoldAmount.safeAdd(fillResults.takerFeePaid); results.takerTokenSoldAmount.safeAdd(fillResults.takerFeePaid);
} }
} catch (bytes memory) { } catch (bytes memory) {
// If the fill fails, zero out fill quantities. // Swallow failures, leaving all results as zero.
results.makerTokenBoughtAmount = 0;
} }
} }
/// @dev Extract the token from plain ERC20 asset data. /// @dev Extract the token from plain ERC20 asset data.
/// If the asset-data is empty, a zero token address will be returned.
/// @param assetData The order asset data. /// @param assetData The order asset data.
function _getTokenFromERC20AssetData(bytes memory assetData) function _getTokenFromERC20AssetData(bytes memory assetData)
private private
pure pure
returns (IERC20TokenV06 token) returns (IERC20TokenV06 token)
{ {
if (assetData.length == 0) {
return IERC20TokenV06(address(0));
}
if (assetData.length != 36 || if (assetData.length != 36 ||
LibBytesV06.readBytes4(assetData, 0) != ERC20_ASSET_PROXY_ID) LibBytesV06.readBytes4(assetData, 0) != ERC20_ASSET_PROXY_ID)
{ {

View File

@@ -49,7 +49,6 @@ contract PayTakerTransformer is
/// @dev Create this contract. /// @dev Create this contract.
/// @param deploymentNonce_ The nonce of the deployer when deploying this contract. /// @param deploymentNonce_ The nonce of the deployer when deploying this contract.
/// @dev Construct the transformer and store the WETH address in an immutable.
constructor(uint256 deploymentNonce_) constructor(uint256 deploymentNonce_)
public public
Transformer(deploymentNonce_) Transformer(deploymentNonce_)

View File

@@ -47,10 +47,9 @@ contract WethTransformer is
using LibSafeMathV06 for uint256; using LibSafeMathV06 for uint256;
using LibERC20Transformer for IERC20TokenV06; using LibERC20Transformer for IERC20TokenV06;
/// @dev Create this contract. /// @dev Construct the transformer and store the WETH address in an immutable.
/// @param weth_ The weth token. /// @param weth_ The weth token.
/// @param deploymentNonce_ The nonce of the deployer when deploying this contract. /// @param deploymentNonce_ The nonce of the deployer when deploying this contract.
/// @dev Construct the transformer and store the WETH address in an immutable.
constructor(IEtherTokenV06 weth_, uint256 deploymentNonce_) constructor(IEtherTokenV06 weth_, uint256 deploymentNonce_)
public public
Transformer(deploymentNonce_) Transformer(deploymentNonce_)
@@ -74,7 +73,10 @@ contract WethTransformer is
{ {
TransformData memory data = abi.decode(data_, (TransformData)); TransformData memory data = abi.decode(data_, (TransformData));
if (!data.token.isTokenETH() && data.token != weth) { if (!data.token.isTokenETH() && data.token != weth) {
LibTransformERC20RichErrors.InvalidTransformDataError(data_).rrevert(); LibTransformERC20RichErrors.InvalidTransformDataError(
LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_TOKENS,
data_
).rrevert();
} }
uint256 amount = data.amount; uint256 amount = data.amount;

View File

@@ -20,7 +20,6 @@ pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;
contract TestDelegateCaller { contract TestDelegateCaller {
function executeDelegateCall( function executeDelegateCall(
address target, address target,

View File

@@ -26,6 +26,7 @@ export const fillQuoteTransformerDataEncoder = AbiEncoder.create([
name: 'data', name: 'data',
type: 'tuple', type: 'tuple',
components: [ components: [
{ name: 'side', type: 'uint8' },
{ name: 'sellToken', type: 'address' }, { name: 'sellToken', type: 'address' },
{ name: 'buyToken', type: 'address' }, { name: 'buyToken', type: 'address' },
{ {
@@ -35,23 +36,30 @@ export const fillQuoteTransformerDataEncoder = AbiEncoder.create([
}, },
{ name: 'signatures', type: 'bytes[]' }, { name: 'signatures', type: 'bytes[]' },
{ name: 'maxOrderFillAmounts', type: 'uint256[]' }, { name: 'maxOrderFillAmounts', type: 'uint256[]' },
{ name: 'sellAmount', type: 'uint256' }, { name: 'fillAmount', type: 'uint256' },
{ name: 'buyAmount', type: 'uint256' },
], ],
}, },
]); ]);
/**
* Market operation for `FillQuoteTransformerData`.
*/
export enum FillQuoteTransformerSide {
Sell,
Buy,
}
/** /**
* `FillQuoteTransformer.TransformData` * `FillQuoteTransformer.TransformData`
*/ */
export interface FillQuoteTransformerData { export interface FillQuoteTransformerData {
side: FillQuoteTransformerSide;
sellToken: string; sellToken: string;
buyToken: string; buyToken: string;
orders: Array<Exclude<Order, ['signature', 'exchangeAddress', 'chainId']>>; orders: Array<Exclude<Order, ['signature', 'exchangeAddress', 'chainId']>>;
signatures: string[]; signatures: string[];
maxOrderFillAmounts: BigNumber[]; maxOrderFillAmounts: BigNumber[];
sellAmount: BigNumber; fillAmount: BigNumber;
buyAmount: BigNumber;
} }
/** /**

View File

@@ -13,7 +13,11 @@ import { BigNumber, hexUtils, ZeroExRevertErrors } from '@0x/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { rlpEncodeNonce } from '../../src/nonce_utils'; import { rlpEncodeNonce } from '../../src/nonce_utils';
import { encodeFillQuoteTransformerData, FillQuoteTransformerData } from '../../src/transformer_data_encoders'; import {
encodeFillQuoteTransformerData,
FillQuoteTransformerData,
FillQuoteTransformerSide,
} from '../../src/transformer_data_encoders';
import { artifacts } from '../artifacts'; import { artifacts } from '../artifacts';
import { import {
FillQuoteTransformerContract, FillQuoteTransformerContract,
@@ -217,13 +221,13 @@ blockchainTests.resets('FillQuoteTransformer', env => {
function encodeTransformData(fields: Partial<FillQuoteTransformerData> = {}): string { function encodeTransformData(fields: Partial<FillQuoteTransformerData> = {}): string {
return encodeFillQuoteTransformerData({ return encodeFillQuoteTransformerData({
side: FillQuoteTransformerSide.Sell,
sellToken: takerToken.address, sellToken: takerToken.address,
buyToken: makerToken.address, buyToken: makerToken.address,
orders: [], orders: [],
signatures: [], signatures: [],
maxOrderFillAmounts: [], maxOrderFillAmounts: [],
sellAmount: MAX_UINT256, fillAmount: MAX_UINT256,
buyAmount: ZERO_AMOUNT,
...fields, ...fields,
}); });
} }
@@ -455,7 +459,7 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
sellAmount: qfr.takerAssetSpent, fillAmount: qfr.takerAssetSpent,
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -479,7 +483,7 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
sellAmount: qfr.takerAssetSpent, fillAmount: qfr.takerAssetSpent,
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -614,7 +618,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought, side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -636,7 +641,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought, side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -661,7 +667,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought, side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -684,7 +691,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought, side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
}), }),
) )
.awaitTransactionSuccessAsync({ value: maxProtocolFees }); .awaitTransactionSuccessAsync({ value: maxProtocolFees });
@@ -709,7 +717,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought, side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -736,7 +745,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought, side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -760,7 +770,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought.plus(1), side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought.plus(1),
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -789,7 +800,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought, side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -812,7 +824,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought, side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -835,7 +848,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought, side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
}), }),
) )
.awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid }); .awaitTransactionSuccessAsync({ value: qfr.protocolFeePaid });
@@ -855,7 +869,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
buyAmount: qfr.makerAssetBought, side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
// Skip the first order. // Skip the first order.
maxOrderFillAmounts: [ZERO_AMOUNT], maxOrderFillAmounts: [ZERO_AMOUNT],
}), }),
@@ -879,6 +894,8 @@ blockchainTests.resets('FillQuoteTransformer', env => {
encodeTransformData({ encodeTransformData({
orders, orders,
signatures, signatures,
side: FillQuoteTransformerSide.Buy,
fillAmount: qfr.makerAssetBought,
}), }),
) )
.callAsync({ value: qfr.protocolFeePaid }); .callAsync({ value: qfr.protocolFeePaid });

View File

@@ -61,7 +61,12 @@ blockchainTests.resets('WethTransformer', env => {
const tx = host const tx = host
.executeTransform(amount, transformer.address, data) .executeTransform(amount, transformer.address, data)
.awaitTransactionSuccessAsync({ value: amount }); .awaitTransactionSuccessAsync({ value: amount });
return expect(tx).to.revertWith(new ZeroExRevertErrors.TransformERC20.InvalidTransformDataError(data)); return expect(tx).to.revertWith(
new ZeroExRevertErrors.TransformERC20.InvalidTransformDataError(
ZeroExRevertErrors.TransformERC20.InvalidTransformDataErrorCode.InvalidTokens,
data,
),
);
}); });
it('can unwrap WETH', async () => { it('can unwrap WETH', async () => {