@0x:contracts-integrations Added tests with protocol fees for batch order matching

This commit is contained in:
Alex Towle 2019-11-09 16:31:53 -05:00
parent b976101dca
commit b7d92c3c12
2 changed files with 537 additions and 540 deletions

View File

@ -14,7 +14,7 @@ import { MatchOrderTester, MatchTransferAmounts } from '../utils/match_order_tes
const { isRoundingErrorCeil, isRoundingErrorFloor } = LibReferenceFunctions;
blockchainTests.resets('matchOrders', env => {
blockchainTests.resets.only('matchOrders', env => {
// The fee recipient addresses.
let feeRecipientLeft: Actor;
let feeRecipientRight: Actor;
@ -50,6 +50,7 @@ blockchainTests.resets('matchOrders', env => {
numErc721TokensToDeploy: 1,
numErc1155TokensToDeploy: 1,
});
makerAssetAddressLeft = deployment.tokens.erc20[0].address;
makerAssetAddressRight = deployment.tokens.erc20[1].address;
feeAssetAddress = deployment.tokens.erc20[2].address;
@ -180,6 +181,26 @@ blockchainTests.resets('matchOrders', env => {
await env.blockchainLifecycle.revertAsync();
await env.blockchainLifecycle.startAsync();
await matchOrderTester.matchOrdersAndAssertEffectsAsync(
{
leftOrder: signedOrderLeft,
rightOrder: signedOrderRight,
},
{
...expectedTransferAmounts,
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: constants.ZERO_AMOUNT,
leftProtocolFeePaidByTakerInWethAmount: constants.ZERO_AMOUNT,
rightProtocolFeePaidByTakerInWethAmount: PROTOCOL_FEE,
},
matcherAddress || matcher.address,
PROTOCOL_FEE,
withMaximalFill,
);
await env.blockchainLifecycle.revertAsync();
await env.blockchainLifecycle.startAsync();
await matchOrderTester.matchOrdersAndAssertEffectsAsync(
{
leftOrder: signedOrderLeft,
@ -199,7 +220,7 @@ blockchainTests.resets('matchOrders', env => {
}
describe('matchOrders', () => {
it('Should transfer correct amounts when right order is fully filled and values pass isRoundingErrorFloor but fail isRoundingErrorCeil', async () => {
it('should transfer correct amounts when right order is fully filled and values pass isRoundingErrorFloor but fail isRoundingErrorCeil', async () => {
// Create orders to match
const signedOrderLeft = await makerLeft.signOrderAsync({
makerAssetAmount: toBaseUnitAmount(17, 0),
@ -253,7 +274,7 @@ blockchainTests.resets('matchOrders', env => {
);
});
it('Should transfer correct amounts when left order is fully filled and values pass isRoundingErrorCeil but fail isRoundingErrorFloor', async () => {
it('should transfer correct amounts when left order is fully filled and values pass isRoundingErrorCeil but fail isRoundingErrorFloor', async () => {
// Create orders to match
const signedOrderLeft = await makerLeft.signOrderAsync({
makerAssetAmount: toBaseUnitAmount(15, 0),
@ -1194,7 +1215,7 @@ blockchainTests.resets('matchOrders', env => {
);
});
it('Should transfer correct amounts when left order is fully filled and values pass isRoundingErrorCeil and isRoundingErrorFloor', async () => {
it('should transfer correct amounts when left order is fully filled and values pass isRoundingErrorCeil and isRoundingErrorFloor', async () => {
// Create orders to match
const signedOrderLeft = await makerLeft.signOrderAsync({
makerAssetAmount: toBaseUnitAmount(15, 0),
@ -1250,7 +1271,7 @@ blockchainTests.resets('matchOrders', env => {
);
});
it('Should transfer correct amounts when left order is fully filled', async () => {
it('should transfer correct amounts when left order is fully filled', async () => {
await testMatchOrdersAsync(
{
makerAssetAmount: toBaseUnitAmount(16, 0),
@ -1310,7 +1331,7 @@ blockchainTests.resets('matchOrders', env => {
);
});
it('Should give left maker a better sell price when rounding', async () => {
it('should give left maker a better sell price when rounding', async () => {
await testMatchOrdersAsync(
{
makerAssetAmount: toBaseUnitAmount(12, 0),
@ -1337,7 +1358,7 @@ blockchainTests.resets('matchOrders', env => {
);
});
it('Should give right maker and right taker a favorable fee price when rounding', async () => {
it('should give right maker and right taker a favorable fee price when rounding', async () => {
await testMatchOrdersAsync(
{
makerAssetAmount: toBaseUnitAmount(16, 0),
@ -1367,7 +1388,7 @@ blockchainTests.resets('matchOrders', env => {
);
});
it('Should give left maker and left taker a favorable fee price when rounding', async () => {
it('should give left maker and left taker a favorable fee price when rounding', async () => {
await testMatchOrdersAsync(
{
makerAssetAmount: toBaseUnitAmount(12, 0),
@ -1396,7 +1417,7 @@ blockchainTests.resets('matchOrders', env => {
);
});
it('Should give left maker a better sell price when rounding', async () => {
it('should give left maker a better sell price when rounding', async () => {
await testMatchOrdersAsync(
{
makerAssetAmount: toBaseUnitAmount(12, 0),
@ -2197,21 +2218,87 @@ blockchainTests.resets('matchOrders', env => {
});
});
interface TestBatchMatchOrdersArgs {
leftOrders: Array<Partial<Order>>;
rightOrders: Array<Partial<Order>>;
expectedTransferAmounts: Array<Partial<MatchTransferAmounts>>;
leftOrdersTakerAssetFilledAmounts: BigNumber[];
rightOrdersTakerAssetFilledAmounts: BigNumber[];
matchIndices: Array<[number, number]>;
shouldMaximallyFill: boolean;
matcherAddress?: string;
}
async function testBatchMatchOrdersAsync(args: TestBatchMatchOrdersArgs): Promise<void> {
const signedLeftOrders = await Promise.all(args.leftOrders.map(async order => makerLeft.signOrderAsync(order)));
const signedRightOrders = await Promise.all(
args.rightOrders.map(async order => makerRight.signOrderAsync(order)),
);
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders: signedLeftOrders,
rightOrders: signedRightOrders,
leftOrdersTakerAssetFilledAmounts: args.leftOrdersTakerAssetFilledAmounts,
rightOrdersTakerAssetFilledAmounts: args.rightOrdersTakerAssetFilledAmounts,
},
args.matcherAddress || matcher.address,
PROTOCOL_FEE.times(args.matchIndices.length).times(2),
args.matchIndices,
args.expectedTransferAmounts.map(transferAmounts => {
return {
...transferAmounts,
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
leftProtocolFeePaidByTakerInWethAmount: constants.ZERO_AMOUNT,
rightProtocolFeePaidByTakerInWethAmount: constants.ZERO_AMOUNT,
};
}),
args.shouldMaximallyFill,
);
await env.blockchainLifecycle.revertAsync();
await env.blockchainLifecycle.startAsync();
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders: signedLeftOrders,
rightOrders: signedRightOrders,
leftOrdersTakerAssetFilledAmounts: args.leftOrdersTakerAssetFilledAmounts,
rightOrdersTakerAssetFilledAmounts: args.rightOrdersTakerAssetFilledAmounts,
},
args.matcherAddress || matcher.address,
constants.ZERO_AMOUNT,
args.matchIndices,
args.expectedTransferAmounts.map(transferAmounts => {
return {
...transferAmounts,
leftProtocolFeePaidByTakerInEthAmount: constants.ZERO_AMOUNT,
rightProtocolFeePaidByTakerInEthAmount: constants.ZERO_AMOUNT,
leftProtocolFeePaidByTakerInWethAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInWethAmount: PROTOCOL_FEE,
};
}),
args.shouldMaximallyFill,
);
}
describe('batchMatchOrders', () => {
it('should correctly match two opposite orders', async () => {
const leftOrders = [
await makerLeft.signOrderAsync({
await testBatchMatchOrdersAsync({
leftOrders: [
{
makerAssetAmount: toBaseUnitAmount(2, 0),
takerAssetAmount: toBaseUnitAmount(1, 0),
}),
];
const rightOrders = [
await makerRight.signOrderAsync({
},
],
rightOrders: [
{
makerAssetAmount: toBaseUnitAmount(1, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
];
const expectedTransferAmounts = [
},
],
expectedTransferAmounts: [
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(2, 0),
@ -2222,38 +2309,30 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
];
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders,
rightOrders,
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
},
matcher.address,
PROTOCOL_FEE.times(2),
[[0, 0]],
expectedTransferAmounts,
false,
);
matchIndices: [[0, 0]],
shouldMaximallyFill: false,
});
it('Should correctly match a partial fill', async () => {
const leftOrders = [
await makerLeft.signOrderAsync({
});
it('should correctly match a partial fill', async () => {
await testBatchMatchOrdersAsync({
leftOrders: [
{
makerAssetAmount: toBaseUnitAmount(4, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
];
const rightOrders = [
await makerRight.signOrderAsync({
},
],
rightOrders: [
{
makerAssetAmount: toBaseUnitAmount(1, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
];
const expectedTransferAmounts = [
},
],
expectedTransferAmounts: [
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(2, 0),
@ -2264,42 +2343,34 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
];
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders,
rightOrders,
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
},
matcher.address,
PROTOCOL_FEE.times(2),
[[0, 0]],
expectedTransferAmounts,
false,
);
matchIndices: [[0, 0]],
shouldMaximallyFill: false,
});
});
it('should correctly match two left orders to one complementary right order', async () => {
const leftOrders = [
await makerLeft.signOrderAsync({
await testBatchMatchOrdersAsync({
leftOrders: [
{
makerAssetAmount: toBaseUnitAmount(2, 0),
takerAssetAmount: toBaseUnitAmount(1, 0),
}),
await makerLeft.signOrderAsync({
},
{
makerAssetAmount: toBaseUnitAmount(2, 0),
takerAssetAmount: toBaseUnitAmount(1, 0),
}),
];
const rightOrders = [
await makerRight.signOrderAsync({
},
],
rightOrders: [
{
makerAssetAmount: toBaseUnitAmount(2, 0),
takerAssetAmount: toBaseUnitAmount(4, 0),
}),
];
const expectedTransferAmounts = [
},
],
expectedTransferAmounts: [
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(2, 0),
@ -2311,8 +2382,6 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 50%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
{
// Left Maker
@ -2325,42 +2394,34 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 50%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
];
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders,
rightOrders,
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
},
matcher.address,
PROTOCOL_FEE.times(4),
[[0, 0], [1, 0]],
expectedTransferAmounts,
false,
);
matchIndices: [[0, 0], [1, 0]],
shouldMaximallyFill: false,
});
});
it('should correctly match one left order to two complementary right orders', async () => {
const leftOrders = [
await makerLeft.signOrderAsync({
await testBatchMatchOrdersAsync({
leftOrders: [
{
makerAssetAmount: toBaseUnitAmount(4, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
];
const rightOrders = [
await makerRight.signOrderAsync({
},
],
rightOrders: [
{
makerAssetAmount: toBaseUnitAmount(1, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
await makerRight.signOrderAsync({
},
{
makerAssetAmount: toBaseUnitAmount(1, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
];
const expectedTransferAmounts = [
},
],
expectedTransferAmounts: [
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(2, 0),
@ -2371,8 +2432,6 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
{
// Left Maker
@ -2384,42 +2443,34 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
];
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders,
rightOrders,
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
},
matcher.address,
PROTOCOL_FEE.times(4),
[[0, 0], [0, 1]],
expectedTransferAmounts,
false,
);
matchIndices: [[0, 0], [0, 1]],
shouldMaximallyFill: false,
});
});
it('should correctly match one left order to two right orders, where the last should not be touched', async () => {
const leftOrders = [
await makerLeft.signOrderAsync({
await testBatchMatchOrdersAsync({
leftOrders: [
{
makerAssetAmount: toBaseUnitAmount(2, 0),
takerAssetAmount: toBaseUnitAmount(1, 0),
}),
];
const rightOrders = [
await makerRight.signOrderAsync({
},
],
rightOrders: [
{
makerAssetAmount: toBaseUnitAmount(1, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
await makerRight.signOrderAsync({
},
{
makerAssetAmount: toBaseUnitAmount(1, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
];
const expectedTransferAmounts = [
},
],
expectedTransferAmounts: [
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(2, 0),
@ -2430,46 +2481,38 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
];
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders,
rightOrders,
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
},
matcher.address,
PROTOCOL_FEE.times(2),
[[0, 0]],
expectedTransferAmounts,
false,
);
matchIndices: [[0, 0]],
shouldMaximallyFill: false,
});
});
it('should have three order matchings with only two left orders and two right orders', async () => {
const leftOrders = [
await makerLeft.signOrderAsync({
await testBatchMatchOrdersAsync({
leftOrders: [
{
makerAssetAmount: toBaseUnitAmount(4, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
await makerLeft.signOrderAsync({
},
{
makerAssetAmount: toBaseUnitAmount(2, 0),
takerAssetAmount: toBaseUnitAmount(1, 0),
}),
];
const rightOrders = [
await makerRight.signOrderAsync({
},
],
rightOrders: [
{
makerAssetAmount: toBaseUnitAmount(1, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
await makerRight.signOrderAsync({
},
{
makerAssetAmount: toBaseUnitAmount(2, 0),
takerAssetAmount: toBaseUnitAmount(4, 0),
}),
];
const expectedTransferAmounts = [
},
],
expectedTransferAmounts: [
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(2, 0),
@ -2480,8 +2523,6 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
{
// Left Maker
@ -2493,8 +2534,6 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
{
// Left Maker
@ -2506,91 +2545,69 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
];
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders,
rightOrders,
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
},
matcher.address,
PROTOCOL_FEE.times(6),
[[0, 0], [0, 1], [1, 1]],
expectedTransferAmounts,
false,
);
matchIndices: [[0, 0], [0, 1], [1, 1]],
shouldMaximallyFill: false,
});
});
});
describe('batchMatchOrdersWithMaximalFill', () => {
it('should fully fill the the right order and pay the profit denominated in the left maker asset', async () => {
// Create orders to match
const leftOrders = [
await makerLeft.signOrderAsync({
await testBatchMatchOrdersAsync({
leftOrders: [
{
makerAssetAmount: toBaseUnitAmount(17, 0),
takerAssetAmount: toBaseUnitAmount(98, 0),
}),
];
const rightOrders = [
await makerRight.signOrderAsync({
},
],
rightOrders: [
{
makerAssetAmount: toBaseUnitAmount(75, 0),
takerAssetAmount: toBaseUnitAmount(13, 0),
}),
];
const expectedTransferAmounts = [
},
],
expectedTransferAmounts: [
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(13, 0),
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(new BigNumber('76.4705882352941176'), 16), // 76.47%
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(
new BigNumber('76.4705882352941176'),
16,
), // 76.47%
// Right Maker
rightMakerAssetSoldByRightMakerAmount: toBaseUnitAmount(75, 0),
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('76.5306122448979591'), 16), // 76.53%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
];
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders,
rightOrders,
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
},
matcher.address,
PROTOCOL_FEE.times(2),
[[0, 0]],
expectedTransferAmounts,
true,
);
matchIndices: [[0, 0]],
shouldMaximallyFill: true,
});
it('Should transfer correct amounts when left order is fully filled', async () => {
// Create orders to match
const leftOrders = [
await makerLeft.signOrderAsync({
});
it('should transfer correct amounts when left order is fully filled', async () => {
await testBatchMatchOrdersAsync({
leftOrders: [
{
makerAssetAmount: toBaseUnitAmount(15, 0),
takerAssetAmount: toBaseUnitAmount(90, 0),
}),
];
const rightOrders = [
await makerRight.signOrderAsync({
},
],
rightOrders: [
{
makerAssetAmount: toBaseUnitAmount(196, 0),
takerAssetAmount: toBaseUnitAmount(28, 0),
}),
];
// Match signedOrderLeft with signedOrderRight
// Note that the right maker received a slightly better purchase price.
// This is intentional; see note in MixinMatchOrders.calculateMatchedFillResults.
// Because the right maker received a slightly more favorable buy price, the fee
// paid by the right taker is slightly higher than that paid by the right maker.
// Fees can be thought of as a tax paid by the seller, derived from the sale price.
const expectedTransferAmounts = [
},
],
expectedTransferAmounts: [
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(15, 0),
@ -2607,42 +2624,34 @@ blockchainTests.resets('matchOrders', env => {
rightMakerAssetReceivedByTakerAmount: toBaseUnitAmount(15, 0),
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('53.5714285714285714'), 16), // 53.57%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
];
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders,
rightOrders,
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
},
matcher.address,
PROTOCOL_FEE.times(2),
[[0, 0]],
expectedTransferAmounts,
true,
);
matchIndices: [[0, 0]],
shouldMaximallyFill: true,
});
});
it('should correctly match one left order to two right orders, where the last should not be touched', async () => {
const leftOrders = [
await makerLeft.signOrderAsync({
await testBatchMatchOrdersAsync({
leftOrders: [
{
makerAssetAmount: toBaseUnitAmount(2, 0),
takerAssetAmount: toBaseUnitAmount(1, 0),
}),
];
const rightOrders = [
await makerRight.signOrderAsync({
},
],
rightOrders: [
{
makerAssetAmount: toBaseUnitAmount(1, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
await makerRight.signOrderAsync({
},
{
makerAssetAmount: toBaseUnitAmount(1, 0),
takerAssetAmount: toBaseUnitAmount(2, 0),
}),
];
const expectedTransferAmounts = [
},
],
expectedTransferAmounts: [
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(2, 0),
@ -2653,63 +2662,59 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
];
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders,
rightOrders,
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
},
matcher.address,
PROTOCOL_FEE.times(2),
[[0, 0]],
expectedTransferAmounts,
true,
);
matchIndices: [[0, 0]],
shouldMaximallyFill: true,
});
});
it('should correctly fill all four orders in three matches', async () => {
const leftOrders = [
await makerLeft.signOrderAsync({
await testBatchMatchOrdersAsync({
leftOrders: [
{
makerAssetAmount: toBaseUnitAmount(2, 0),
takerAssetAmount: toBaseUnitAmount(1, 0),
}),
await makerLeft.signOrderAsync({
},
{
makerAssetAmount: toBaseUnitAmount(72, 0),
takerAssetAmount: toBaseUnitAmount(36, 0),
}),
];
const rightOrders = [
await makerRight.signOrderAsync({
},
],
rightOrders: [
{
makerAssetAmount: toBaseUnitAmount(15, 0),
takerAssetAmount: toBaseUnitAmount(30, 0),
}),
await makerRight.signOrderAsync({
},
{
makerAssetAmount: toBaseUnitAmount(22, 0),
takerAssetAmount: toBaseUnitAmount(44, 0),
}),
];
const expectedTransferAmounts = [
},
],
expectedTransferAmounts: [
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(2, 0),
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(100, 16), // 100%
// Right Maker
rightMakerAssetSoldByRightMakerAmount: toBaseUnitAmount(1, 0),
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(new BigNumber('6.6666666666666666'), 16), // 6.66%
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(
new BigNumber('6.6666666666666666'),
16,
), // 6.66%
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('6.6666666666666666'), 16), // 6.66%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(28, 0),
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(new BigNumber('38.8888888888888888'), 16), // 38.88%
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(
new BigNumber('38.8888888888888888'),
16,
), // 38.88%
// Right Maker
rightMakerAssetSoldByRightMakerAmount: toBaseUnitAmount(14, 0),
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(
@ -2719,36 +2724,27 @@ blockchainTests.resets('matchOrders', env => {
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('38.8888888888888888'), 16), // 38.88%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('93.3333333333333333'), 16), // 93.33%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
{
// Left Maker
leftMakerAssetSoldByLeftMakerAmount: toBaseUnitAmount(44, 0),
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(new BigNumber('61.1111111111111111'), 16), // 61.11%
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(
new BigNumber('61.1111111111111111'),
16,
), // 61.11%
// Right Maker
rightMakerAssetSoldByRightMakerAmount: toBaseUnitAmount(22, 0),
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
// Taker
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(new BigNumber('61.1111111111111111'), 16), // 61.11%
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
leftProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
rightProtocolFeePaidByTakerInEthAmount: PROTOCOL_FEE,
},
];
await matchOrderTester.batchMatchOrdersAndAssertEffectsAsync(
{
leftOrders,
rightOrders,
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
},
matcher.address,
PROTOCOL_FEE.times(6),
[[0, 0], [1, 0], [1, 1]],
expectedTransferAmounts,
true,
);
matchIndices: [[0, 0], [1, 0], [1, 1]],
shouldMaximallyFill: true,
});
});
});

View File

@ -149,6 +149,7 @@ export class MatchOrderTester {
expectedTransferAmounts,
this._devUtils,
);
const expectedResults = convertToBatchMatchResults(expectedBatchMatchResults);
expect(actualBatchMatchResults).to.be.eql(expectedResults);