Added testing for the BatchMatchOrdersError Rich Error

This commit is contained in:
James Towle
2019-07-02 17:49:04 -05:00
committed by Amir Bandeali
parent 29eff3b515
commit 0df68a6e06
8 changed files with 125 additions and 5 deletions

View File

@@ -71,6 +71,7 @@ contract MixinMatchOrders is
bytes[] memory rightSignatures
)
public
nonReentrant
returns (LibFillResults.BatchMatchedFillResults memory batchMatchedFillResults)
{
return _batchMatchOrders(leftOrders, rightOrders, leftSignatures, rightSignatures, true);

View File

@@ -42,6 +42,24 @@ contract IMatchOrders {
public
returns (LibFillResults.BatchMatchedFillResults memory batchMatchedFillResults);
/// @dev Match complementary orders that have a profitable spread.
/// Each order is maximally filled at their respective price point, and
/// the matcher receives a profit denominated in either the left maker asset,
/// right maker asset, or a combination of both.
/// @param leftOrders Set of orders with the same maker / taker asset.
/// @param rightOrders Set of orders to match against `leftOrders`
/// @param leftSignatures Proof that left orders were created by the left makers.
/// @param rightSignatures Proof that right orders were created by the right makers.
/// @return batchMatchedFillResults Amounts filled and profit generated.
function batchMatchOrdersWithMaximalFill(
LibOrder.Order[] memory leftOrders,
LibOrder.Order[] memory rightOrders,
bytes[] memory leftSignatures,
bytes[] memory rightSignatures
)
public
returns (LibFillResults.BatchMatchedFillResults memory batchMatchedFillResults);
/// @dev Calculates fill amounts for the matched orders.
/// Each order is filled at their respective price point. However, the calculations are
/// carried out as though the orders are both being filled at the right order's price point.

View File

@@ -238,6 +238,20 @@ contract ReentrantERC20Token is
orders[1].makerAssetAmount = orders[0].takerAssetAmount;
}
/// @dev Create two complementary test orders.
function _createBatchMatchedOrders()
internal
view
returns (LibOrder.Order[][] memory orders)
{
LibOrder.Order[] memory _orders = _createOrders(2);
orders[0][0] = _orders[0];
orders[0][1] = _orders[1];
orders[0][1].takerAssetAmount = orders[0][1].makerAssetAmount;
orders[0][1].makerAssetAmount = orders[0][0].takerAssetAmount;
}
function _getTakerFillAmounts(
LibOrder.Order[] memory orders
)

View File

@@ -11,7 +11,7 @@ import {
import { ERC1155Contract as ERC1155TokenContract, Erc1155Wrapper as ERC1155Wrapper } from '@0x/contracts-erc1155';
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
import { chaiSetup, constants, OrderFactory, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { chaiSetup, constants, OrderFactory, orderUtils, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
import { OrderStatus, SignedOrder } from '@0x/types';
@@ -2183,6 +2183,78 @@ describe('matchOrders', () => {
const tx = exchangeWrapper.batchMatchOrdersAsync(leftOrders, rightOrders, takerAddress);
return expect(tx).to.revertWith(expectedError);
});
it('should fail if there are a different number of left orders and signatures', async () => {
const leftOrders = [
await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
feeRecipientAddress: feeRecipientAddressLeft,
}),
await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 0),
feeRecipientAddress: feeRecipientAddressRight,
}),
];
const rightOrders = [
await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 0),
feeRecipientAddress: feeRecipientAddressRight,
}),
await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 0),
feeRecipientAddress: feeRecipientAddressRight,
}),
];
const params = orderUtils.createBatchMatchOrders(leftOrders, rightOrders);
// Set params left signatures to only include the first left signature
params.leftSignatures = [params.leftSignatures[0]];
const expectedError = new ExchangeRevertErrors.BatchMatchOrdersError(ExchangeRevertErrors.BatchMatchOrdersErrorCodes.IncompatibleLeftOrders);
const tx = exchangeWrapper.batchMatchOrdersRawAsync(params, takerAddress);
return expect(tx).to.revertWith(expectedError);
});
it('should fail if there are a different number of right orders and signatures', async () => {
const leftOrders = [
await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
feeRecipientAddress: feeRecipientAddressLeft,
}),
await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 0),
feeRecipientAddress: feeRecipientAddressRight,
}),
];
const rightOrders = [
await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 0),
feeRecipientAddress: feeRecipientAddressRight,
}),
await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 0),
feeRecipientAddress: feeRecipientAddressRight,
}),
];
const params = orderUtils.createBatchMatchOrders(leftOrders, rightOrders);
// Set params right signatures to only include the first right signature
params.rightSignatures = [params.rightSignatures[0]];
const expectedError = new ExchangeRevertErrors.BatchMatchOrdersError(ExchangeRevertErrors.BatchMatchOrdersErrorCodes.IncompatibleRightOrders);
const tx = exchangeWrapper.batchMatchOrdersRawAsync(params, takerAddress);
return expect(tx).to.revertWith(expectedError);
});
it('should correctly match two opposite orders', async () => {
const leftOrders = [
await orderFactoryLeft.newSignedOrderAsync({

View File

@@ -9,7 +9,6 @@ export const constants = {
'MARKET_BUY_ORDERS',
'MARKET_SELL_ORDERS',
'MATCH_ORDERS',
'BATCH_MATCH_ORDERS',
'CANCEL_ORDER',
'BATCH_CANCEL_ORDERS',
'CANCEL_ORDERS_UP_TO',

View File

@@ -3,6 +3,7 @@ import { artifacts as erc20Artifacts } from '@0x/contracts-erc20';
import { artifacts as erc721Artifacts } from '@0x/contracts-erc721';
import {
BatchMatchedFillResults,
BatchMatchOrder,
FillResults,
LogDecoder,
MatchedFillResults,
@@ -274,6 +275,20 @@ export class ExchangeWrapper {
const ordersInfo = (await this._exchange.getOrdersInfo.callAsync(signedOrders)) as OrderInfo[];
return ordersInfo;
}
public async batchMatchOrdersRawAsync(
params: BatchMatchOrder,
from: string,
): Promise<TransactionReceiptWithDecodedLogs> {
const txHash = await this._exchange.batchMatchOrders.sendTransactionAsync(
params.leftOrders,
params.rightOrders,
params.leftSignatures,
params.rightSignatures,
{ from },
);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async batchMatchOrdersAsync(
signedOrdersLeft: SignedOrder[],
signedOrdersRight: SignedOrder[],

View File

@@ -186,7 +186,7 @@ export class MatchOrderTester {
takerAddress,
);
// Simulate the batch order match.
const batchMatchResults = simulateBatchMatchOrders(
const expectedBatchMatchResults = simulateBatchMatchOrders(
orders,
takerAddress,
_initialTokenBalances,
@@ -195,13 +195,13 @@ export class MatchOrderTester {
);
// Validate the simulation against reality.
await assertBatchMatchResultsAsync(
batchMatchResults,
expectedBatchMatchResults,
transactionReceipt,
await this.getBalancesAsync(),
_initialTokenBalances,
this.exchangeWrapper,
);
return batchMatchResults;
return expectedBatchMatchResults;
}
/**

View File

@@ -30,6 +30,7 @@ export { testWithReferenceFuncAsync } from './test_with_reference';
export { hexConcat } from './hex_utils';
export {
BatchMatchedFillResults,
BatchMatchOrder,
ContractName,
ERC20BalancesByOwner,
ERC1155FungibleHoldingsByOwner,