Addressed more review feedback and fixed a bug in Actor
This commit is contained in:
parent
4fe57ba025
commit
bb923d2b7d
@ -99,6 +99,10 @@ blockchainTests.resets('Coordinator integration tests', env => {
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
Actor.count = 0;
|
||||
});
|
||||
|
||||
async function simulateFillsAsync(
|
||||
orders: SignedOrder[],
|
||||
txReceipt: TransactionReceiptWithDecodedLogs,
|
||||
|
862
contracts/integrations/test/exchange/batch_match_orders_test.ts
Normal file
862
contracts/integrations/test/exchange/batch_match_orders_test.ts
Normal file
@ -0,0 +1,862 @@
|
||||
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
|
||||
import { ExchangeRevertErrors } from '@0x/contracts-exchange';
|
||||
import { blockchainTests, constants, expect, toBaseUnitAmount } from '@0x/contracts-test-utils';
|
||||
import { Order, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { Actor } from '../framework/actors/base';
|
||||
import { Maker } from '../framework/actors/maker';
|
||||
import { actorAddressesByName } from '../framework/actors/utils';
|
||||
import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store';
|
||||
import { TokenIds } from '../framework/balances/types';
|
||||
import { DeploymentManager } from '../framework/deployment_manager';
|
||||
|
||||
import { MatchOrderTester, MatchTransferAmounts } from './match_order_tester';
|
||||
|
||||
blockchainTests.resets('matchOrders integration tests', env => {
|
||||
// The fee recipient addresses.
|
||||
let feeRecipientLeft: Actor;
|
||||
let feeRecipientRight: Actor;
|
||||
|
||||
// The address that should be responsible for matching orders.
|
||||
let matcher: Actor;
|
||||
|
||||
// Market makers who have opposite maker and taker assets.
|
||||
let makerLeft: Maker;
|
||||
let makerRight: Maker;
|
||||
|
||||
// The addresses of important assets for testing.
|
||||
let makerAssetLeft: DummyERC20TokenContract;
|
||||
let makerAssetRight: DummyERC20TokenContract;
|
||||
let feeAsset: DummyERC20TokenContract;
|
||||
|
||||
let makerAssetDataLeft: string;
|
||||
let makerAssetDataRight: string;
|
||||
let feeAssetData: string;
|
||||
|
||||
let deployment: DeploymentManager;
|
||||
let matchOrderTester: MatchOrderTester;
|
||||
let leftId: BigNumber;
|
||||
let rightId: BigNumber;
|
||||
|
||||
before(async () => {
|
||||
deployment = await DeploymentManager.deployAsync(env, {
|
||||
numErc20TokensToDeploy: 3,
|
||||
numErc721TokensToDeploy: 1,
|
||||
numErc1155TokensToDeploy: 1,
|
||||
});
|
||||
|
||||
makerAssetLeft = deployment.tokens.erc20[0];
|
||||
makerAssetRight = deployment.tokens.erc20[1];
|
||||
feeAsset = deployment.tokens.erc20[2];
|
||||
|
||||
// Create the fee recipient actors.
|
||||
feeRecipientLeft = new Actor({
|
||||
name: 'left fee recipient',
|
||||
deployment,
|
||||
});
|
||||
feeRecipientRight = new Actor({
|
||||
name: 'right fee recipient',
|
||||
deployment,
|
||||
});
|
||||
|
||||
// Encode the asset data.
|
||||
makerAssetDataLeft = deployment.assetDataEncoder
|
||||
.ERC20Token(makerAssetLeft.address)
|
||||
.getABIEncodedTransactionData();
|
||||
makerAssetDataRight = deployment.assetDataEncoder
|
||||
.ERC20Token(makerAssetRight.address)
|
||||
.getABIEncodedTransactionData();
|
||||
feeAssetData = deployment.assetDataEncoder.ERC20Token(feeAsset.address).getABIEncodedTransactionData();
|
||||
|
||||
// Create two market makers with compatible orders for matching.
|
||||
makerLeft = new Maker({
|
||||
name: 'left maker',
|
||||
deployment,
|
||||
orderConfig: {
|
||||
makerAssetData: makerAssetDataLeft,
|
||||
takerAssetData: makerAssetDataRight,
|
||||
makerFeeAssetData: feeAssetData,
|
||||
takerFeeAssetData: feeAssetData,
|
||||
feeRecipientAddress: feeRecipientLeft.address,
|
||||
},
|
||||
});
|
||||
makerRight = new Maker({
|
||||
name: 'right maker',
|
||||
deployment,
|
||||
orderConfig: {
|
||||
makerAssetData: makerAssetDataRight,
|
||||
takerAssetData: makerAssetDataLeft,
|
||||
makerFeeAssetData: feeAssetData,
|
||||
takerFeeAssetData: feeAssetData,
|
||||
feeRecipientAddress: feeRecipientRight.address,
|
||||
},
|
||||
});
|
||||
|
||||
// Create a matcher.
|
||||
matcher = new Actor({
|
||||
name: 'matcher',
|
||||
deployment,
|
||||
});
|
||||
|
||||
// Configure the appropriate actors with initial balances.
|
||||
await Promise.all([
|
||||
...deployment.tokens.erc20.map(async token => makerLeft.configureERC20TokenAsync(token)),
|
||||
...deployment.tokens.erc20.map(async token => makerRight.configureERC20TokenAsync(token)),
|
||||
makerLeft.configureERC20TokenAsync(deployment.tokens.weth, deployment.staking.stakingProxy.address),
|
||||
makerRight.configureERC20TokenAsync(deployment.tokens.weth, deployment.staking.stakingProxy.address),
|
||||
matcher.configureERC20TokenAsync(feeAsset),
|
||||
matcher.configureERC20TokenAsync(deployment.tokens.weth, deployment.staking.stakingProxy.address),
|
||||
feeRecipientLeft.configureERC20TokenAsync(feeAsset),
|
||||
feeRecipientLeft.configureERC20TokenAsync(deployment.tokens.weth, deployment.staking.stakingProxy.address),
|
||||
feeRecipientRight.configureERC20TokenAsync(feeAsset),
|
||||
feeRecipientRight.configureERC20TokenAsync(deployment.tokens.weth, deployment.staking.stakingProxy.address),
|
||||
]);
|
||||
|
||||
leftId = await makerLeft.configureERC1155TokenAsync(deployment.tokens.erc1155[0]);
|
||||
[rightId] = await makerRight.configureERC721TokenAsync(deployment.tokens.erc721[0]);
|
||||
|
||||
const tokenIds: TokenIds = { erc721: {}, erc1155: {} };
|
||||
tokenIds.erc1155[deployment.tokens.erc1155[0].address] = { fungible: [leftId], nonFungible: [] };
|
||||
tokenIds.erc721[deployment.tokens.erc721[0].address] = [rightId];
|
||||
|
||||
const blockchainBalanceStore = new BlockchainBalanceStore(
|
||||
{
|
||||
...actorAddressesByName([feeRecipientLeft, feeRecipientRight, makerLeft, makerRight, matcher]),
|
||||
stakingProxy: deployment.staking.stakingProxy.address,
|
||||
},
|
||||
{
|
||||
erc20: {
|
||||
makerTokenLeft: deployment.tokens.erc20[0],
|
||||
makerTokenRight: deployment.tokens.erc20[1],
|
||||
feeToken: deployment.tokens.erc20[2],
|
||||
weth: deployment.tokens.weth,
|
||||
},
|
||||
erc721: {
|
||||
nft: deployment.tokens.erc721[0],
|
||||
},
|
||||
erc1155: {
|
||||
fungible: deployment.tokens.erc1155[0],
|
||||
},
|
||||
},
|
||||
tokenIds,
|
||||
);
|
||||
|
||||
matchOrderTester = new MatchOrderTester(deployment, blockchainBalanceStore);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
Actor.count = 0;
|
||||
});
|
||||
|
||||
describe('batchMatchOrders and batchMatchOrdersWithMaximalFill rich errors', async () => {
|
||||
it('should fail if there are zero leftOrders with the ZeroLeftOrders rich error reason', async () => {
|
||||
const leftOrders: SignedOrder[] = [];
|
||||
const rightOrders = [
|
||||
await makerRight.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
}),
|
||||
];
|
||||
const expectedError = new ExchangeRevertErrors.BatchMatchOrdersError(
|
||||
ExchangeRevertErrors.BatchMatchOrdersErrorCodes.ZeroLeftOrders,
|
||||
);
|
||||
let tx = deployment.exchange
|
||||
.batchMatchOrders(
|
||||
leftOrders,
|
||||
rightOrders,
|
||||
leftOrders.map(order => order.signature),
|
||||
rightOrders.map(order => order.signature),
|
||||
)
|
||||
.awaitTransactionSuccessAsync({ from: matcher.address });
|
||||
await expect(tx).to.revertWith(expectedError);
|
||||
tx = deployment.exchange
|
||||
.batchMatchOrdersWithMaximalFill(
|
||||
leftOrders,
|
||||
rightOrders,
|
||||
leftOrders.map(order => order.signature),
|
||||
rightOrders.map(order => order.signature),
|
||||
)
|
||||
.awaitTransactionSuccessAsync({ from: matcher.address });
|
||||
return expect(tx).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('should fail if there are zero rightOrders', async () => {
|
||||
const leftOrders = [
|
||||
await makerLeft.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
}),
|
||||
];
|
||||
const rightOrders: SignedOrder[] = [];
|
||||
const expectedError = new ExchangeRevertErrors.BatchMatchOrdersError(
|
||||
ExchangeRevertErrors.BatchMatchOrdersErrorCodes.ZeroRightOrders,
|
||||
);
|
||||
let tx = deployment.exchange
|
||||
.batchMatchOrders(
|
||||
leftOrders,
|
||||
rightOrders,
|
||||
leftOrders.map(order => order.signature),
|
||||
rightOrders.map(order => order.signature),
|
||||
)
|
||||
.awaitTransactionSuccessAsync({ from: matcher.address });
|
||||
await expect(tx).to.revertWith(expectedError);
|
||||
tx = deployment.exchange
|
||||
.batchMatchOrdersWithMaximalFill(
|
||||
leftOrders,
|
||||
rightOrders,
|
||||
leftOrders.map(order => order.signature),
|
||||
rightOrders.map(order => order.signature),
|
||||
)
|
||||
.awaitTransactionSuccessAsync({ from: matcher.address });
|
||||
return expect(tx).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('should fail if there are a different number of left orders and signatures', async () => {
|
||||
const leftOrders = [
|
||||
await makerLeft.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
}),
|
||||
await makerRight.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
}),
|
||||
];
|
||||
const rightOrders = [
|
||||
await makerRight.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
}),
|
||||
await makerRight.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
}),
|
||||
];
|
||||
const expectedError = new ExchangeRevertErrors.BatchMatchOrdersError(
|
||||
ExchangeRevertErrors.BatchMatchOrdersErrorCodes.InvalidLengthLeftSignatures,
|
||||
);
|
||||
let tx = deployment.exchange
|
||||
.batchMatchOrders(
|
||||
leftOrders,
|
||||
rightOrders,
|
||||
[leftOrders[0].signature],
|
||||
rightOrders.map(order => order.signature),
|
||||
)
|
||||
.awaitTransactionSuccessAsync({ from: matcher.address });
|
||||
await expect(tx).to.revertWith(expectedError);
|
||||
tx = deployment.exchange
|
||||
.batchMatchOrdersWithMaximalFill(
|
||||
leftOrders,
|
||||
rightOrders,
|
||||
[leftOrders[0].signature],
|
||||
rightOrders.map(order => order.signature),
|
||||
)
|
||||
.awaitTransactionSuccessAsync({ from: matcher.address });
|
||||
return expect(tx).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('should fail if there are a different number of right orders and signatures', async () => {
|
||||
const leftOrders = [
|
||||
await makerLeft.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
}),
|
||||
await makerLeft.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
}),
|
||||
];
|
||||
const rightOrders = [
|
||||
await makerRight.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
}),
|
||||
await makerRight.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
}),
|
||||
];
|
||||
const expectedError = new ExchangeRevertErrors.BatchMatchOrdersError(
|
||||
ExchangeRevertErrors.BatchMatchOrdersErrorCodes.InvalidLengthRightSignatures,
|
||||
);
|
||||
let tx = deployment.exchange
|
||||
.batchMatchOrders(leftOrders, rightOrders, leftOrders.map(order => order.signature), [
|
||||
rightOrders[0].signature,
|
||||
])
|
||||
.awaitTransactionSuccessAsync({ from: matcher.address });
|
||||
await expect(tx).to.revertWith(expectedError);
|
||||
tx = deployment.exchange
|
||||
.batchMatchOrdersWithMaximalFill(leftOrders, rightOrders, leftOrders.map(order => order.signature), [
|
||||
rightOrders[0].signature,
|
||||
])
|
||||
.awaitTransactionSuccessAsync({ from: matcher.address });
|
||||
return expect(tx).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a batch order matching scenario with both eth and weth protocol fees.
|
||||
*/
|
||||
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,
|
||||
DeploymentManager.protocolFee.times(args.matchIndices.length).times(2),
|
||||
args.matchIndices,
|
||||
args.expectedTransferAmounts.map(transferAmounts => {
|
||||
return {
|
||||
...transferAmounts,
|
||||
leftProtocolFeePaidByTakerInEthAmount: DeploymentManager.protocolFee,
|
||||
rightProtocolFeePaidByTakerInEthAmount: DeploymentManager.protocolFee,
|
||||
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: DeploymentManager.protocolFee,
|
||||
rightProtocolFeePaidByTakerInWethAmount: DeploymentManager.protocolFee,
|
||||
};
|
||||
}),
|
||||
args.shouldMaximallyFill,
|
||||
);
|
||||
}
|
||||
|
||||
describe('batchMatchOrders', () => {
|
||||
it('should correctly match two opposite orders', async () => {
|
||||
await testBatchMatchOrdersAsync({
|
||||
leftOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
},
|
||||
],
|
||||
rightOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
],
|
||||
expectedTransferAmounts: [
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
},
|
||||
],
|
||||
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
matchIndices: [[0, 0]],
|
||||
shouldMaximallyFill: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly match a partial fill', async () => {
|
||||
await testBatchMatchOrdersAsync({
|
||||
leftOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(4),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
],
|
||||
rightOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
],
|
||||
expectedTransferAmounts: [
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
},
|
||||
],
|
||||
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
matchIndices: [[0, 0]],
|
||||
shouldMaximallyFill: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly match two left orders to one complementary right order', async () => {
|
||||
await testBatchMatchOrdersAsync({
|
||||
leftOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
},
|
||||
{
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
},
|
||||
],
|
||||
rightOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(4),
|
||||
},
|
||||
],
|
||||
expectedTransferAmounts: [
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Right Maker
|
||||
leftMakerAssetBoughtByRightMakerAmount: new BigNumber(2),
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 50%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
},
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(100, 16), // 50%
|
||||
// Right Maker
|
||||
leftMakerAssetBoughtByRightMakerAmount: new BigNumber(2),
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 50%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
},
|
||||
],
|
||||
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
|
||||
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
matchIndices: [[0, 0], [1, 0]],
|
||||
shouldMaximallyFill: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly match one left order to two complementary right orders', async () => {
|
||||
await testBatchMatchOrdersAsync({
|
||||
leftOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(4),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
],
|
||||
rightOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
{
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
],
|
||||
expectedTransferAmounts: [
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
},
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
},
|
||||
],
|
||||
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
|
||||
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 () => {
|
||||
await testBatchMatchOrdersAsync({
|
||||
leftOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
},
|
||||
],
|
||||
rightOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
{
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
],
|
||||
expectedTransferAmounts: [
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
},
|
||||
],
|
||||
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
|
||||
matchIndices: [[0, 0]],
|
||||
shouldMaximallyFill: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should have three order matchings with only two left orders and two right orders', async () => {
|
||||
await testBatchMatchOrdersAsync({
|
||||
leftOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(4),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
{
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
},
|
||||
],
|
||||
rightOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
{
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(4),
|
||||
},
|
||||
],
|
||||
expectedTransferAmounts: [
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
},
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
},
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(50, 16), // 50%
|
||||
},
|
||||
],
|
||||
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
|
||||
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
|
||||
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 () => {
|
||||
await testBatchMatchOrdersAsync({
|
||||
leftOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(17),
|
||||
takerAssetAmount: new BigNumber(98),
|
||||
},
|
||||
],
|
||||
rightOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(75),
|
||||
takerAssetAmount: new BigNumber(13),
|
||||
},
|
||||
],
|
||||
expectedTransferAmounts: [
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(13),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount('76.4705882352941176', 16), // 76.47%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(75),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount('76.5306122448979591', 16), // 76.53%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
},
|
||||
],
|
||||
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
matchIndices: [[0, 0]],
|
||||
shouldMaximallyFill: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should transfer correct amounts when left order is fully filled', async () => {
|
||||
await testBatchMatchOrdersAsync({
|
||||
leftOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(15),
|
||||
takerAssetAmount: new BigNumber(90),
|
||||
},
|
||||
],
|
||||
rightOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(196),
|
||||
takerAssetAmount: new BigNumber(28),
|
||||
},
|
||||
],
|
||||
expectedTransferAmounts: [
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(15),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
rightMakerAssetBoughtByLeftMakerAmount: new BigNumber(90),
|
||||
// Right Maker
|
||||
leftMakerAssetBoughtByRightMakerAmount: new BigNumber(15),
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(105),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount('53.5714285714285714', 16), // 53.57%
|
||||
// Taker
|
||||
rightMakerAssetReceivedByTakerAmount: new BigNumber(15),
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount('53.5714285714285714', 16), // 53.57%
|
||||
},
|
||||
],
|
||||
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
matchIndices: [[0, 0]],
|
||||
shouldMaximallyFill: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly match one left order to two right orders, where the last should not be touched', async () => {
|
||||
await testBatchMatchOrdersAsync({
|
||||
leftOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
},
|
||||
],
|
||||
rightOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
{
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(2),
|
||||
},
|
||||
],
|
||||
expectedTransferAmounts: [
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
},
|
||||
],
|
||||
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
|
||||
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
|
||||
matchIndices: [[0, 0]],
|
||||
shouldMaximallyFill: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly fill all four orders in three matches', async () => {
|
||||
await testBatchMatchOrdersAsync({
|
||||
leftOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(2),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
},
|
||||
{
|
||||
makerAssetAmount: new BigNumber(72),
|
||||
takerAssetAmount: new BigNumber(36),
|
||||
},
|
||||
],
|
||||
rightOrders: [
|
||||
{
|
||||
makerAssetAmount: new BigNumber(15),
|
||||
takerAssetAmount: new BigNumber(30),
|
||||
},
|
||||
{
|
||||
makerAssetAmount: new BigNumber(22),
|
||||
takerAssetAmount: new BigNumber(44),
|
||||
},
|
||||
],
|
||||
expectedTransferAmounts: [
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(2),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount('6.6666666666666666', 16), // 6.66%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount('6.6666666666666666', 16), // 6.66%
|
||||
},
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(28),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount('38.8888888888888888', 16), // 38.88%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(14),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount('93.3333333333333333', 16), // 93.33%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount('38.8888888888888888', 16), // 38.88%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount('93.3333333333333333', 16), // 93.33%
|
||||
},
|
||||
{
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(44),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount('61.1111111111111111', 16), // 61.11%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(22),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount('61.1111111111111111', 16), // 61.11%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
},
|
||||
],
|
||||
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
|
||||
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
|
||||
matchIndices: [[0, 0], [1, 0], [1, 1]],
|
||||
shouldMaximallyFill: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('token sanity checks', () => {
|
||||
it('should be able to match ERC721 tokens with ERC1155 tokens', async () => {
|
||||
const leftMakerAssetData = deployment.assetDataEncoder
|
||||
.ERC1155Assets(deployment.tokens.erc1155[0].address, [leftId], [new BigNumber(1)], '0x')
|
||||
.getABIEncodedTransactionData();
|
||||
const rightMakerAssetData = deployment.assetDataEncoder
|
||||
.ERC721Token(deployment.tokens.erc721[0].address, rightId)
|
||||
.getABIEncodedTransactionData();
|
||||
|
||||
const signedOrderLeft = await makerLeft.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(4),
|
||||
takerAssetAmount: new BigNumber(1),
|
||||
makerAssetData: leftMakerAssetData,
|
||||
takerAssetData: rightMakerAssetData,
|
||||
});
|
||||
const signedOrderRight = await makerRight.signOrderAsync({
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
takerAssetAmount: new BigNumber(4),
|
||||
makerAssetData: rightMakerAssetData,
|
||||
takerAssetData: leftMakerAssetData,
|
||||
});
|
||||
|
||||
const expectedTransferAmounts = {
|
||||
// Left Maker
|
||||
leftMakerAssetSoldByLeftMakerAmount: new BigNumber(4),
|
||||
leftMakerFeeAssetPaidByLeftMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Right Maker
|
||||
rightMakerAssetSoldByRightMakerAmount: new BigNumber(1),
|
||||
rightMakerFeeAssetPaidByRightMakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
// Taker
|
||||
leftTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
rightTakerFeeAssetPaidByTakerAmount: toBaseUnitAmount(100, 16), // 100%
|
||||
leftProtocolFeePaidByTakerInEthAmount: DeploymentManager.protocolFee,
|
||||
rightProtocolFeePaidByTakerInEthAmount: DeploymentManager.protocolFee,
|
||||
};
|
||||
|
||||
await matchOrderTester.matchOrdersAndAssertEffectsAsync(
|
||||
{
|
||||
leftOrder: signedOrderLeft,
|
||||
rightOrder: signedOrderRight,
|
||||
},
|
||||
expectedTransferAmounts,
|
||||
matcher.address,
|
||||
DeploymentManager.protocolFee.times(2),
|
||||
false,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:disable-line:max-file-line-count
|
@ -123,6 +123,10 @@ blockchainTests.resets('Exchange wrappers', env => {
|
||||
localBalances = LocalBalanceStore.create(deployment.devUtils, initialLocalBalances);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
Actor.count = 0;
|
||||
});
|
||||
|
||||
interface SignedOrderWithValidity {
|
||||
signedOrder: SignedOrder;
|
||||
isValid: boolean;
|
||||
|
@ -21,6 +21,7 @@ import { SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||
|
||||
import { Actor } from '../framework/actors/base';
|
||||
import { FeeRecipient } from '../framework/actors/fee_recipient';
|
||||
import { OperatorStakerMaker, StakerKeeper } from '../framework/actors/hybrids';
|
||||
import { Maker } from '../framework/actors/maker';
|
||||
@ -107,6 +108,10 @@ blockchainTests.resets('fillOrder integration tests', env => {
|
||||
await balanceStore.updateBalancesAsync();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
Actor.count = 0;
|
||||
});
|
||||
|
||||
async function simulateFillAsync(
|
||||
order: SignedOrder,
|
||||
txReceipt: TransactionReceiptWithDecodedLogs,
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { BlockchainBalanceStore, LocalBalanceStore } from '@0x/contracts-exchange';
|
||||
import { constants, expect, orderHashUtils, OrderStatus } from '@0x/contracts-test-utils';
|
||||
import { BatchMatchedFillResults, FillResults, MatchedFillResults, SignedOrder } from '@0x/types';
|
||||
import { BlockchainTestsEnvironment, constants, expect, orderHashUtils, OrderStatus } from '@0x/contracts-test-utils';
|
||||
import { BatchMatchedFillResults, FillResults, MatchedFillResults, Order, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { DeploymentManager } from '../deployment_manager';
|
||||
import { Maker } from '../framework/actors/maker';
|
||||
import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store';
|
||||
import { LocalBalanceStore } from '../framework/balances/local_balance_store';
|
||||
import { DeploymentManager } from '../framework/deployment_manager';
|
||||
|
||||
export interface FillEventArgs {
|
||||
orderHash: string;
|
||||
@ -66,6 +68,64 @@ export interface MatchedOrders {
|
||||
rightOrderTakerAssetFilledAmount?: BigNumber;
|
||||
}
|
||||
|
||||
export interface TestMatchOrdersArgs {
|
||||
env: BlockchainTestsEnvironment;
|
||||
matchOrderTester: MatchOrderTester;
|
||||
leftOrder: Partial<Order>;
|
||||
rightOrder: Partial<Order>;
|
||||
makerLeft: Maker;
|
||||
makerRight: Maker;
|
||||
expectedTransferAmounts: Partial<MatchTransferAmounts>;
|
||||
withMaximalFill: boolean;
|
||||
matcherAddress: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an order matching scenario with both eth and weth protocol fees.
|
||||
*/
|
||||
export async function testMatchOrdersAsync(args: TestMatchOrdersArgs): Promise<void> {
|
||||
// Create orders to match.
|
||||
const signedOrderLeft = await args.makerLeft.signOrderAsync(args.leftOrder);
|
||||
const signedOrderRight = await args.makerRight.signOrderAsync(args.rightOrder);
|
||||
|
||||
await args.matchOrderTester.matchOrdersAndAssertEffectsAsync(
|
||||
{
|
||||
leftOrder: signedOrderLeft,
|
||||
rightOrder: signedOrderRight,
|
||||
},
|
||||
{
|
||||
...args.expectedTransferAmounts,
|
||||
leftProtocolFeePaidByTakerInEthAmount: DeploymentManager.protocolFee,
|
||||
rightProtocolFeePaidByTakerInEthAmount: DeploymentManager.protocolFee,
|
||||
leftProtocolFeePaidByTakerInWethAmount: constants.ZERO_AMOUNT,
|
||||
rightProtocolFeePaidByTakerInWethAmount: constants.ZERO_AMOUNT,
|
||||
},
|
||||
args.matcherAddress,
|
||||
DeploymentManager.protocolFee.times(2),
|
||||
args.withMaximalFill,
|
||||
);
|
||||
|
||||
await args.env.blockchainLifecycle.revertAsync();
|
||||
await args.env.blockchainLifecycle.startAsync();
|
||||
|
||||
await args.matchOrderTester.matchOrdersAndAssertEffectsAsync(
|
||||
{
|
||||
leftOrder: signedOrderLeft,
|
||||
rightOrder: signedOrderRight,
|
||||
},
|
||||
{
|
||||
...args.expectedTransferAmounts,
|
||||
leftProtocolFeePaidByTakerInEthAmount: constants.ZERO_AMOUNT,
|
||||
rightProtocolFeePaidByTakerInEthAmount: constants.ZERO_AMOUNT,
|
||||
leftProtocolFeePaidByTakerInWethAmount: DeploymentManager.protocolFee,
|
||||
rightProtocolFeePaidByTakerInWethAmount: DeploymentManager.protocolFee,
|
||||
},
|
||||
args.matcherAddress,
|
||||
constants.ZERO_AMOUNT,
|
||||
args.withMaximalFill,
|
||||
);
|
||||
}
|
||||
|
||||
export class MatchOrderTester {
|
||||
/**
|
||||
* Constructs new MatchOrderTester.
|
File diff suppressed because it is too large
Load Diff
1090
contracts/integrations/test/exchange/match_orders_test.ts
Normal file
1090
contracts/integrations/test/exchange/match_orders_test.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@ import {
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { Actor } from '../framework/actors/base';
|
||||
import { FeeRecipient } from '../framework/actors/fee_recipient';
|
||||
import { Maker } from '../framework/actors/maker';
|
||||
import { Taker } from '../framework/actors/taker';
|
||||
@ -117,6 +118,10 @@ blockchainTests('Forwarder integration tests', env => {
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
Actor.count = 0;
|
||||
});
|
||||
|
||||
blockchainTests.resets('constructor', () => {
|
||||
it('should revert if assetProxy is unregistered', async () => {
|
||||
const chainId = await env.getChainIdAsync();
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ERC1155MintableContract } from '@0x/contracts-erc1155';
|
||||
import { ERC1155MintableContract, ERC1155TransferSingleEventArgs } from '@0x/contracts-erc1155';
|
||||
import { DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20';
|
||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||
import { constants, getRandomInteger, TransactionFactory } from '@0x/contracts-test-utils';
|
||||
import { constants, filterLogsToArguments, getRandomInteger, TransactionFactory } from '@0x/contracts-test-utils';
|
||||
import { SignatureType, SignedZeroExTransaction, ZeroExTransaction } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
@ -33,6 +33,12 @@ export class Actor {
|
||||
|
||||
constructor(config: ActorConfig) {
|
||||
Actor.count++;
|
||||
|
||||
// Emit an error if the actor count is too high.
|
||||
if (Actor.count >= config.deployment.accounts.length) {
|
||||
throw new Error('Actor count too large');
|
||||
}
|
||||
|
||||
this.address = config.deployment.accounts[Actor.count];
|
||||
this.name = config.name || this.address;
|
||||
this.deployment = config.deployment;
|
||||
@ -106,8 +112,15 @@ export class Actor {
|
||||
amount?: BigNumber,
|
||||
): Promise<BigNumber> {
|
||||
// Create a fungible token.
|
||||
const id = await token.create('', false).callAsync({ from: this.address });
|
||||
await token.create('', false).awaitTransactionSuccessAsync({ from: this.address });
|
||||
const receipt = await token.create('', false).awaitTransactionSuccessAsync({ from: this.address });
|
||||
const logs = filterLogsToArguments<ERC1155TransferSingleEventArgs>(receipt.logs, 'TransferSingle');
|
||||
|
||||
// Throw if the wrong number of logs were received.
|
||||
if (logs.length !== 1) {
|
||||
throw new Error('Invalid number of `TransferSingle` logs');
|
||||
}
|
||||
|
||||
const { id } = logs[0];
|
||||
|
||||
// Mint the token
|
||||
await token
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { blockchainTests } from '@0x/contracts-test-utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { Actor } from '../framework/actors/base';
|
||||
import { PoolOperator } from '../framework/actors/pool_operator';
|
||||
import { AssertionResult } from '../framework/assertions/function_assertion';
|
||||
import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store';
|
||||
@ -28,6 +29,10 @@ export class PoolManagementSimulation extends Simulation {
|
||||
}
|
||||
|
||||
blockchainTests.skip('Pool management fuzz test', env => {
|
||||
after(async () => {
|
||||
Actor.count = 0;
|
||||
});
|
||||
|
||||
it('fuzz', async () => {
|
||||
const deployment = await DeploymentManager.deployAsync(env, {
|
||||
numErc20TokensToDeploy: 0,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { blockchainTests } from '@0x/contracts-test-utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { Actor } from '../framework/actors/base';
|
||||
import { Staker } from '../framework/actors/staker';
|
||||
import { AssertionResult } from '../framework/assertions/function_assertion';
|
||||
import { BlockchainBalanceStore } from '../framework/balances/blockchain_balance_store';
|
||||
@ -32,6 +33,10 @@ export class StakeManagementSimulation extends Simulation {
|
||||
}
|
||||
|
||||
blockchainTests.skip('Stake management fuzz test', env => {
|
||||
after(async () => {
|
||||
Actor.count = 0;
|
||||
});
|
||||
|
||||
it('fuzz', async () => {
|
||||
const deployment = await DeploymentManager.deployAsync(env, {
|
||||
numErc20TokensToDeploy: 0,
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user