@0x:contracts-exchange Addressed review feedback

This commit is contained in:
Alex Towle
2019-08-29 00:31:30 -07:00
parent 75e6c45285
commit dba0d8469d
34 changed files with 510 additions and 291 deletions

View File

@@ -8,6 +8,7 @@ import { artifacts as erc20Artifacts } from '@0x/contracts-erc20';
import { artifacts as erc721Artifacts } from '@0x/contracts-erc721';
import { ReferenceFunctions as LibReferenceFunctions } from '@0x/contracts-exchange-libs';
import {
constants,
expect,
FillEventArgs,
filterLogsToArguments,
@@ -58,7 +59,13 @@ export class FillOrderWrapper {
const balanceStore = LocalBalanceStore.create(initBalanceStore);
const takerAssetFillAmount =
opts.takerAssetFillAmount !== undefined ? opts.takerAssetFillAmount : signedOrder.takerAssetAmount;
const fillResults = LibReferenceFunctions.calculateFillResults(signedOrder, takerAssetFillAmount);
// TODO(jalextowle): Change this if the integration tests take protocol fees into account.
const fillResults = LibReferenceFunctions.calculateFillResults(
signedOrder,
takerAssetFillAmount,
constants.ZERO_AMOUNT,
constants.ZERO_AMOUNT,
);
const fillEvent = FillOrderWrapper.simulateFillEvent(signedOrder, takerAddress, fillResults);
// Taker -> Maker
balanceStore.transferAsset(

View File

@@ -0,0 +1,18 @@
import { chaiSetup, getCodesizeFromArtifact } from '@0x/contracts-test-utils';
import * as chai from 'chai';
chaiSetup.configure();
const expect = chai.expect;
import { artifacts } from '../src';
describe('Contract Size Checks', () => {
const MAX_CODE_SIZE = 24576;
describe('Exchange', () => {
it('should have a codesize less than the maximum', async () => {
const actualSize = getCodesizeFromArtifact(artifacts.Exchange);
expect(actualSize).to.be.lt(MAX_CODE_SIZE);
});
});
});

View File

@@ -23,6 +23,8 @@ blockchainTests('Exchange core internal functions', env => {
let testExchange: TestExchangeInternalsContract;
let logDecoder: LogDecoder;
let senderAddress: string;
const DEFAULT_PROTOCOL_MULTIPLIER = new BigNumber(150000);
const DEFAULT_GAS_PRICE = new BigNumber(200000);
before(async () => {
const accounts = await env.getAccountAddressesAsync();
@@ -169,12 +171,16 @@ blockchainTests('Exchange core internal functions', env => {
orderTakerAssetFilledAmount: BigNumber,
takerAddress: string,
takerAssetFillAmount: BigNumber,
// protocolFeeMultiplier: BigNumber,
// gasPrice: BigNumber,
// isProtocolFeePaidInEth: boolean,
protocolFeeMultiplier: BigNumber,
gasPrice: BigNumber,
): Promise<void> {
const orderHash = randomHash();
const fillResults = LibReferenceFunctions.calculateFillResults(order, takerAssetFillAmount);
const fillResults = LibReferenceFunctions.calculateFillResults(
order,
takerAssetFillAmount,
protocolFeeMultiplier,
gasPrice,
);
const expectedFilledState = orderTakerAssetFilledAmount.plus(takerAssetFillAmount);
// const opts = isProtocolFeePaidInEth
// ? { value: fillResults.protocolFeePaid }
@@ -189,7 +195,6 @@ blockchainTests('Exchange core internal functions', env => {
orderHash,
orderTakerAssetFilledAmount,
fillResults,
// opts,
),
);
// Grab the new `filled` state for this order.
@@ -209,31 +214,22 @@ blockchainTests('Exchange core internal functions', env => {
expect(fillEvent.args.takerAssetFilledAmount).to.bignumber.eq(fillResults.takerAssetFilledAmount);
expect(fillEvent.args.makerFeePaid).to.bignumber.eq(fillResults.makerFeePaid);
expect(fillEvent.args.takerFeePaid).to.bignumber.eq(fillResults.takerFeePaid);
// expect(fillEvent.args.protocolFeePaid).to.bignumber.eq(fillResults.protocolFeePaid);
// expect(fillEvent.args.isProtocolFeePaidInEth).to.eq(isProtocolFeePaidInEth);
expect(fillEvent.args.makerAssetData).to.eq(order.makerAssetData);
expect(fillEvent.args.takerAssetData).to.eq(order.takerAssetData);
expect(fillEvent.args.makerFeeAssetData).to.eq(order.makerFeeAssetData);
expect(fillEvent.args.takerFeeAssetData).to.eq(order.takerFeeAssetData);
expect(fillEvent.args.protocolFeePaid).to.bignumber.eq(fillResults.protocolFeePaid);
}
it('emits a `Fill` event and updates `filled` state correctly if protocol fee is paid in ETH', async () => {
const order = makeOrder();
return testUpdateFilledStateAsync(
order,
order.takerAssetAmount.times(0.1),
randomAddress(),
order.takerAssetAmount.times(0.25),
);
});
it('emits a `Fill` event and updates `filled` state correctly if protocol fee is paid in WETH', async () => {
it('emits a `Fill` event and updates `filled` state correctly', async () => {
const order = makeOrder();
return testUpdateFilledStateAsync(
order,
order.takerAssetAmount.times(0.1),
randomAddress(),
order.takerAssetAmount.times(0.25),
DEFAULT_PROTOCOL_MULTIPLIER,
DEFAULT_GAS_PRICE,
);
});

View File

@@ -37,6 +37,8 @@ blockchainTests('Isolated fillOrder() tests', env => {
makerFeeAssetData: createGoodAssetData(),
takerFeeAssetData: createGoodAssetData(),
};
const DEFAULT_GAS_PRICE = new BigNumber(20000);
const DEFAULT_PROTOCOL_FEE_MULTIPLIER = new BigNumber(15000);
let takerAddress: string;
let notTakerAddress: string;
let exchange: IsolatedExchangeWrapper;
@@ -69,7 +71,13 @@ blockchainTests('Isolated fillOrder() tests', env => {
signature?: string,
): Promise<FillOrderAndAssertResultsResults> {
const orderInfo = await exchange.getOrderInfoAsync(order);
const efr = calculateExpectedFillResults(order, orderInfo, takerAssetFillAmount);
const efr = calculateExpectedFillResults(
order,
orderInfo,
takerAssetFillAmount,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
DEFAULT_GAS_PRICE,
);
const eoi = calculateExpectedOrderInfo(order, orderInfo, efr);
const efb = calculateExpectedFillBalances(order, efr);
// Fill the order.
@@ -106,11 +114,15 @@ blockchainTests('Isolated fillOrder() tests', env => {
order: Order,
orderInfo: OrderInfo,
takerAssetFillAmount: BigNumber,
protocolFeeMultiplier: BigNumber,
gasPrice: BigNumber,
): FillResults {
const remainingTakerAssetAmount = order.takerAssetAmount.minus(orderInfo.orderTakerAssetFilledAmount);
return LibReferenceFunctions.calculateFillResults(
order,
BigNumber.min(takerAssetFillAmount, remainingTakerAssetAmount),
protocolFeeMultiplier,
gasPrice,
);
}

View File

@@ -42,7 +42,7 @@ blockchainTests('Protocol Fee Payments', env => {
);
});
it('should pay protocol fee in WETH when too little value is sent', async () => {
it('should not forward ETH when too little value is sent', async () => {
await testProtocolFeesReceiver.testFillOrderProtocolFees.awaitTransactionSuccessAsync(
testProtocolFees.address,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
@@ -92,7 +92,7 @@ blockchainTests('Protocol Fee Payments', env => {
);
});
it('should pay protocol fee in WETH twice when too little value is sent', async () => {
it('should not forward ETH twice when too little value is sent', async () => {
await testProtocolFeesReceiver.testMatchOrdersProtocolFees.awaitTransactionSuccessAsync(
testProtocolFees.address,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
@@ -104,7 +104,7 @@ blockchainTests('Protocol Fee Payments', env => {
);
});
it('should pay protocol fee in ETH and then WETH when the correct value is sent', async () => {
it('should pay protocol fee in ETH and then not forward ETH when exactly one protocol fee is sent', async () => {
await testProtocolFeesReceiver.testMatchOrdersProtocolFees.awaitTransactionSuccessAsync(
testProtocolFees.address,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
@@ -116,7 +116,7 @@ blockchainTests('Protocol Fee Payments', env => {
);
});
it('should pay protocol fee in ETH when extra value is sent and then pay in WETH', async () => {
it('should pay protocol fee in ETH and then not forward ETH when a bit more than one protocol fee is sent', async () => {
await testProtocolFeesReceiver.testMatchOrdersProtocolFees.awaitTransactionSuccessAsync(
testProtocolFees.address,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
@@ -167,7 +167,7 @@ blockchainTests('Protocol Fee Payments', env => {
);
});
it('should pay one protocol fee in WETH when too little ETH is sent and only one order is in the batch', async () => {
it('should not forward ETH when less than one protocol fee is sent and only one order is in the batch', async () => {
await testProtocolFeesReceiver.testBatchFillOrdersProtocolFees.awaitTransactionSuccessAsync(
testProtocolFees.address,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
@@ -206,7 +206,7 @@ blockchainTests('Protocol Fee Payments', env => {
);
});
it('should pay both protocol fees in WETH when an insuffiecent amount of ETH for one protocol fee is sent', async () => {
it('should not forward ETH twice when an insuffiecent amount of ETH for one protocol fee is sent', async () => {
await testProtocolFeesReceiver.testBatchFillOrdersProtocolFees.awaitTransactionSuccessAsync(
testProtocolFees.address,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
@@ -219,7 +219,7 @@ blockchainTests('Protocol Fee Payments', env => {
);
});
it('should pay a protocol in ETH and then a fee in WETH when exactly one protocol fee in ETH is sent', async () => {
it('should pay a protocol in ETH and not forward ETH for the second when exactly one protocol fee in ETH is sent', async () => {
await testProtocolFeesReceiver.testBatchFillOrdersProtocolFees.awaitTransactionSuccessAsync(
testProtocolFees.address,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
@@ -245,7 +245,7 @@ blockchainTests('Protocol Fee Payments', env => {
);
});
it('should pay two protocol fees in ETH and one in WETH when exactly two protocol fees in ETH is sent', async () => {
it('should pay two protocol fees in ETH and then not forward ETH for a third when exactly two protocol fees in ETH is sent', async () => {
await testProtocolFeesReceiver.testBatchFillOrdersProtocolFees.awaitTransactionSuccessAsync(
testProtocolFees.address,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,

View File

@@ -1,18 +1,17 @@
import { blockchainTests, constants, expect, LogDecoder } from '@0x/contracts-test-utils';
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
import { BigNumber, OwnableRevertErrors } from '@0x/utils';
import { LogWithDecodedArgs } from 'ethereum-types';
import {
artifacts,
ExchangeContract,
ExchangeUpdatedProtocolFeeCollectorAddressEventArgs,
ExchangeUpdatedProtocolFeeMultiplierEventArgs,
ExchangeProtocolFeeCollectorAddressEventArgs,
ExchangeProtocolFeeMultiplierEventArgs,
} from '../src';
blockchainTests.resets('MixinProtocolFees', env => {
let accounts: string[];
let exchange: ExchangeContract;
let logDecoder: LogDecoder;
let nonOwner: string;
let owner: string;
let protocolFeeCollector: string;
@@ -37,60 +36,59 @@ blockchainTests.resets('MixinProtocolFees', env => {
{},
new BigNumber(1337),
);
// Configure the log decoder
logDecoder = new LogDecoder(env.web3Wrapper, artifacts);
});
blockchainTests.resets('updateProtocolFeeMultiplier', () => {
blockchainTests.resets('setProtocolFeeMultiplier', () => {
it('should revert if msg.sender != owner', async () => {
const expectedError = new OwnableRevertErrors.OnlyOwnerError(nonOwner, owner);
// Ensure that the transaction reverts with the expected rich error.
const tx = exchange.updateProtocolFeeCollectorAddress.sendTransactionAsync(protocolFeeCollector, {
const tx = exchange.setProtocolFeeCollectorAddress.sendTransactionAsync(protocolFeeCollector, {
from: nonOwner,
});
return expect(tx).to.revertWith(expectedError);
});
it('should succeed and emit an UpdatedProtocolFeeMultiplier event if msg.sender == owner', async () => {
// Call the `updateProtocolFeeMultiplier()` function and get the receipt.
const receipt = await logDecoder.getTxWithDecodedLogsAsync(
await exchange.updateProtocolFeeMultiplier.sendTransactionAsync(protocolFeeMultiplier, {
it('should succeed and emit an ProtocolFeeMultiplier event if msg.sender == owner', async () => {
// Call the `setProtocolFeeMultiplier()` function and get the receipt.
const receipt = await exchange.setProtocolFeeMultiplier.awaitTransactionSuccessAsync(
protocolFeeMultiplier,
{
from: owner,
}),
},
);
// Verify that the protocolFeeCollector address was actually updated to the correct address.
const updated = await exchange.protocolFeeMultiplier.callAsync();
expect(updated).bignumber.to.be.eq(protocolFeeMultiplier);
// Ensure that the correct `UpdatedProtocolFeeCollectorAddress` event was logged.
// Ensure that the correct `ProtocolFeeCollectorAddress` event was logged.
// tslint:disable:no-unnecessary-type-assertion
const updatedEvent = receipt.logs[0] as LogWithDecodedArgs<ExchangeUpdatedProtocolFeeMultiplierEventArgs>;
expect(updatedEvent.event).to.be.eq('UpdatedProtocolFeeMultiplier');
const updatedEvent = receipt.logs[0] as LogWithDecodedArgs<ExchangeProtocolFeeMultiplierEventArgs>;
expect(updatedEvent.event).to.be.eq('ProtocolFeeMultiplier');
expect(updatedEvent.args.oldProtocolFeeMultiplier).bignumber.to.be.eq(constants.ZERO_AMOUNT);
expect(updatedEvent.args.updatedProtocolFeeMultiplier).bignumber.to.be.eq(protocolFeeMultiplier);
});
});
blockchainTests.resets('updateProtocolFeeCollectorAddress', () => {
blockchainTests.resets('setProtocolFeeCollectorAddress', () => {
it('should revert if msg.sender != owner', async () => {
const expectedError = new OwnableRevertErrors.OnlyOwnerError(nonOwner, owner);
// Ensure that the transaction reverts with the expected rich error.
const tx = exchange.updateProtocolFeeCollectorAddress.sendTransactionAsync(protocolFeeCollector, {
const tx = exchange.setProtocolFeeCollectorAddress.sendTransactionAsync(protocolFeeCollector, {
from: nonOwner,
});
return expect(tx).to.revertWith(expectedError);
});
it('should succeed and emit an UpdatedProtocolFeeCollectorAddress event if msg.sender == owner', async () => {
// Call the `updateProtocolFeeCollectorAddress()` function and get the receipt.
const receipt = await logDecoder.getTxWithDecodedLogsAsync(
await exchange.updateProtocolFeeCollectorAddress.sendTransactionAsync(protocolFeeCollector, {
it('should succeed and emit an ProtocolFeeCollectorAddress event if msg.sender == owner', async () => {
// Call the `setProtocolFeeCollectorAddress()` function and get the receipt.
const receipt = await exchange.setProtocolFeeCollectorAddress.awaitTransactionSuccessAsync(
protocolFeeCollector,
{
from: owner,
}),
},
);
// Verify that the protocolFeeCollector address was actually updated to the correct address.
@@ -99,10 +97,8 @@ blockchainTests.resets('MixinProtocolFees', env => {
// Ensure that the correct `UpdatedProtocolFeeCollectorAddress` event was logged.
// tslint:disable:no-unnecessary-type-assertion
const updatedEvent = receipt.logs[0] as LogWithDecodedArgs<
ExchangeUpdatedProtocolFeeCollectorAddressEventArgs
>;
expect(updatedEvent.event).to.be.eq('UpdatedProtocolFeeCollectorAddress');
const updatedEvent = receipt.logs[0] as LogWithDecodedArgs<ExchangeProtocolFeeCollectorAddressEventArgs>;
expect(updatedEvent.event).to.be.eq('ProtocolFeeCollectorAddress');
expect(updatedEvent.args.oldProtocolFeeCollector).to.be.eq(constants.NULL_ADDRESS);
expect(updatedEvent.args.updatedProtocolFeeCollector).to.be.eq(protocolFeeCollector);
});

View File

@@ -7,6 +7,8 @@ import * as _ from 'lodash';
describe('Reference functions', () => {
const ONE_ETHER = constants.ONE_ETHER;
const DEFAULT_GAS_PRICE = new BigNumber(2);
const DEFAULT_PROTOCOL_FEE_MULTIPLIER = new BigNumber(150);
const EMPTY_ORDER: Order = {
senderAddress: constants.NULL_ADDRESS,
makerAddress: constants.NULL_ADDRESS,
@@ -42,9 +44,14 @@ describe('Reference functions', () => {
takerAssetFilledAmount,
order.makerAssetAmount,
);
return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(
expectedError.message,
);
return expect(() =>
LibReferenceFunctions.calculateFillResults(
order,
takerAssetFilledAmount,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
DEFAULT_GAS_PRICE,
),
).to.throw(expectedError.message);
});
it('reverts if computing `fillResults.makerFeePaid` overflows', () => {
@@ -65,9 +72,14 @@ describe('Reference functions', () => {
makerAssetFilledAmount,
order.makerFee,
);
return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(
expectedError.message,
);
return expect(() =>
LibReferenceFunctions.calculateFillResults(
order,
takerAssetFilledAmount,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
DEFAULT_GAS_PRICE,
),
).to.throw(expectedError.message);
});
it('reverts if computing `fillResults.takerFeePaid` overflows', () => {
@@ -83,9 +95,14 @@ describe('Reference functions', () => {
takerAssetFilledAmount,
order.takerFee,
);
return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(
expectedError.message,
);
return expect(() =>
LibReferenceFunctions.calculateFillResults(
order,
takerAssetFilledAmount,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
DEFAULT_GAS_PRICE,
),
).to.throw(expectedError.message);
});
it('reverts if `order.makerAssetAmount` is 0', () => {
@@ -95,9 +112,14 @@ describe('Reference functions', () => {
});
const takerAssetFilledAmount = ONE_ETHER;
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(
expectedError.message,
);
return expect(() =>
LibReferenceFunctions.calculateFillResults(
order,
takerAssetFilledAmount,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
DEFAULT_GAS_PRICE,
),
).to.throw(expectedError.message);
});
it('reverts if `order.takerAssetAmount` is 0', () => {
@@ -107,9 +129,14 @@ describe('Reference functions', () => {
});
const takerAssetFilledAmount = ONE_ETHER;
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(
expectedError.message,
);
return expect(() =>
LibReferenceFunctions.calculateFillResults(
order,
takerAssetFilledAmount,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
DEFAULT_GAS_PRICE,
),
).to.throw(expectedError.message);
});
it('reverts if there is a rounding error computing `makerAsssetFilledAmount`', () => {
@@ -123,9 +150,14 @@ describe('Reference functions', () => {
order.takerAssetAmount,
order.makerAssetAmount,
);
return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(
expectedError.message,
);
return expect(() =>
LibReferenceFunctions.calculateFillResults(
order,
takerAssetFilledAmount,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
DEFAULT_GAS_PRICE,
),
).to.throw(expectedError.message);
});
it('reverts if there is a rounding error computing `makerFeePaid`', () => {
@@ -145,9 +177,14 @@ describe('Reference functions', () => {
order.makerAssetAmount,
order.makerFee,
);
return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(
expectedError.message,
);
return expect(() =>
LibReferenceFunctions.calculateFillResults(
order,
takerAssetFilledAmount,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
DEFAULT_GAS_PRICE,
),
).to.throw(expectedError.message);
});
it('reverts if there is a rounding error computing `takerFeePaid`', () => {
@@ -167,9 +204,36 @@ describe('Reference functions', () => {
order.makerAssetAmount,
order.takerFee,
);
return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(
expectedError.message,
return expect(() =>
LibReferenceFunctions.calculateFillResults(
order,
takerAssetFilledAmount,
DEFAULT_PROTOCOL_FEE_MULTIPLIER,
DEFAULT_GAS_PRICE,
),
).to.throw(expectedError.message);
});
it('reverts if there is an overflow computing `protocolFeePaid`', () => {
const order = makeOrder({
makerAssetAmount: ONE_ETHER,
takerAssetAmount: ONE_ETHER,
takerFee: constants.ZERO_AMOUNT,
});
const takerAssetFilledAmount = order.takerAssetAmount.dividedToIntegerBy(3);
const expectedError = new SafeMathRevertErrors.Uint256BinOpError(
SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
MAX_UINT256_ROOT,
MAX_UINT256_ROOT,
);
return expect(() =>
LibReferenceFunctions.calculateFillResults(
order,
takerAssetFilledAmount,
MAX_UINT256_ROOT,
MAX_UINT256_ROOT,
),
).to.throw(expectedError.message);
});
});
});

View File

@@ -9,8 +9,8 @@ export const constants = {
ExchangeFunctionName.RegisterAssetProxy,
ExchangeFunctionName.SimulateDispatchTransferFromCalls,
ExchangeFunctionName.TransferOwnership,
ExchangeFunctionName.UpdateProtocolFeeMultiplier,
ExchangeFunctionName.UpdateProtocolFeeCollectorAddress,
ExchangeFunctionName.SetProtocolFeeMultiplier,
ExchangeFunctionName.SetProtocolFeeCollectorAddress,
],
SINGLE_FILL_FN_NAMES: [
ExchangeFunctionName.FillOrder,

View File

@@ -32,6 +32,6 @@ export enum ExchangeFunctionName {
SetSignatureValidatorApproval = 'setSignatureValidatorApproval',
SimulateDispatchTransferFromCalls = 'simulateDispatchTransferFromCalls',
TransferOwnership = 'transferOwnership',
UpdateProtocolFeeMultiplier = 'updateProtocolFeeMultiplier',
UpdateProtocolFeeCollectorAddress = 'updateProtocolFeeCollectorAddress',
SetProtocolFeeMultiplier = 'setProtocolFeeMultiplier',
SetProtocolFeeCollectorAddress = 'setProtocolFeeCollectorAddress',
}

View File

@@ -91,7 +91,7 @@ blockchainTests.resets('Exchange wrappers', env => {
);
// Set the protocol fee multiplier of the exchange
await exchange.updateProtocolFeeMultiplier.awaitTransactionSuccessAsync(PROTOCOL_FEE_MULTIPLIER, {
await exchange.setProtocolFeeMultiplier.awaitTransactionSuccessAsync(PROTOCOL_FEE_MULTIPLIER, {
from: owner,
});

View File

@@ -62,7 +62,7 @@ blockchainTests('Exchange wrapper functions unit tests.', env => {
);
// Set the protocol fee multiplier.
await testContract.updateProtocolFeeMultiplier.awaitTransactionSuccessAsync(protocolFeeMultiplier, {
await testContract.setProtocolFeeMultiplier.awaitTransactionSuccessAsync(protocolFeeMultiplier, {
from: owner,
});
});
@@ -1320,50 +1320,50 @@ blockchainTests('Exchange wrapper functions unit tests.', env => {
const tx = txHelper.getResultAndReceiptAsync(testContract.batchCancelOrders, orders);
return expect(tx).to.revertWith(expectedError);
});
});
describe('getOrdersInfo', () => {
// Computes the expected (fake) order info generated by the `TestWrapperFunctions` contract.
function getExpectedOrderInfo(order: Order): OrderInfo {
const MAX_ORDER_STATUS = OrderStatus.Cancelled as number;
return {
orderHash: getExpectedOrderHash(order),
// Lower uint128 of `order.salt` is the `orderTakerAssetFilledAmount`.
orderTakerAssetFilledAmount: order.salt.mod(new BigNumber(2).pow(128)),
// High byte of `order.salt` is the `orderStatus`.
orderStatus:
order.salt.dividedToIntegerBy(new BigNumber(2).pow(248)).toNumber() % (MAX_ORDER_STATUS + 1),
};
}
describe('getOrdersInfo', () => {
// Computes the expected (fake) order info generated by the `TestWrapperFunctions` contract.
function getExpectedOrderInfo(order: Order): OrderInfo {
const MAX_ORDER_STATUS = OrderStatus.Cancelled as number;
return {
orderHash: getExpectedOrderHash(order),
// Lower uint128 of `order.salt` is the `orderTakerAssetFilledAmount`.
orderTakerAssetFilledAmount: order.salt.mod(new BigNumber(2).pow(128)),
// High byte of `order.salt` is the `orderStatus`.
orderStatus:
order.salt.dividedToIntegerBy(new BigNumber(2).pow(248)).toNumber() % (MAX_ORDER_STATUS + 1),
};
}
it('works with no orders', async () => {
const infos = await testContract.getOrdersInfo.callAsync([]);
expect(infos.length).to.eq(0);
});
it('works with no orders', async () => {
const infos = await testContract.getOrdersInfo.callAsync([]);
expect(infos.length).to.eq(0);
});
it('works with one order', async () => {
const orders = [randomOrder()];
const expectedResult = orders.map(getExpectedOrderInfo);
const actualResult = await testContract.getOrdersInfo.callAsync(orders);
expect(actualResult).to.deep.eq(expectedResult);
});
it('works with one order', async () => {
const orders = [randomOrder()];
const expectedResult = orders.map(getExpectedOrderInfo);
const actualResult = await testContract.getOrdersInfo.callAsync(orders);
expect(actualResult).to.deep.eq(expectedResult);
});
it('works with many orders', async () => {
const NUM_ORDERS = 16;
const orders = _.times(NUM_ORDERS, () => randomOrder());
const expectedResult = orders.map(getExpectedOrderInfo);
const actualResult = await testContract.getOrdersInfo.callAsync(orders);
expect(actualResult).to.deep.eq(expectedResult);
});
it('works with many orders', async () => {
const NUM_ORDERS = 16;
const orders = _.times(NUM_ORDERS, () => randomOrder());
const expectedResult = orders.map(getExpectedOrderInfo);
const actualResult = await testContract.getOrdersInfo.callAsync(orders);
expect(actualResult).to.deep.eq(expectedResult);
});
it('works with duplicate orders', async () => {
const NUM_UNIQUE_ORDERS = 4;
const CLONE_COUNT = 2;
const uniqueOrders = _.times(NUM_UNIQUE_ORDERS, () => randomOrder());
const orders = _.shuffle(_.flatten(_.times(CLONE_COUNT, () => uniqueOrders)));
const expectedResult = orders.map(getExpectedOrderInfo);
const actualResult = await testContract.getOrdersInfo.callAsync(orders);
expect(actualResult).to.deep.eq(expectedResult);
});
it('works with duplicate orders', async () => {
const NUM_UNIQUE_ORDERS = 4;
const CLONE_COUNT = 2;
const uniqueOrders = _.times(NUM_UNIQUE_ORDERS, () => randomOrder());
const orders = _.shuffle(_.flatten(_.times(CLONE_COUNT, () => uniqueOrders)));
const expectedResult = orders.map(getExpectedOrderInfo);
const actualResult = await testContract.getOrdersInfo.callAsync(orders);
expect(actualResult).to.deep.eq(expectedResult);
});
});
});