Added testing for the BatchMatchOrdersError Rich Error
This commit is contained in:
committed by
Amir Bandeali
parent
29eff3b515
commit
0df68a6e06
@@ -71,6 +71,7 @@ contract MixinMatchOrders is
|
||||
bytes[] memory rightSignatures
|
||||
)
|
||||
public
|
||||
nonReentrant
|
||||
returns (LibFillResults.BatchMatchedFillResults memory batchMatchedFillResults)
|
||||
{
|
||||
return _batchMatchOrders(leftOrders, rightOrders, leftSignatures, rightSignatures, true);
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
)
|
||||
|
@@ -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({
|
||||
|
@@ -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',
|
||||
|
@@ -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[],
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -30,6 +30,7 @@ export { testWithReferenceFuncAsync } from './test_with_reference';
|
||||
export { hexConcat } from './hex_utils';
|
||||
export {
|
||||
BatchMatchedFillResults,
|
||||
BatchMatchOrder,
|
||||
ContractName,
|
||||
ERC20BalancesByOwner,
|
||||
ERC1155FungibleHoldingsByOwner,
|
||||
|
Reference in New Issue
Block a user