`@0x/contracts-exchange-libs: Appease the linter and prettier gods.
This commit is contained in:
parent
4711ce5532
commit
6345faa4a9
@ -3,18 +3,12 @@ import { LibMathRevertErrors } from '@0x/order-utils';
|
||||
import { FillResults } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
const {
|
||||
safeAdd,
|
||||
safeSub,
|
||||
safeMul,
|
||||
safeDiv,
|
||||
} = ReferenceFunctions;
|
||||
const { safeAdd, safeSub, safeMul, safeDiv } = ReferenceFunctions;
|
||||
|
||||
export function isRoundingErrorFloor(
|
||||
numerator: BigNumber,
|
||||
denominator: BigNumber,
|
||||
target: BigNumber,
|
||||
): boolean {
|
||||
/**
|
||||
* Checks if rounding error >= 0.1% when rounding down.
|
||||
*/
|
||||
export function isRoundingErrorFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): boolean {
|
||||
if (denominator.eq(0)) {
|
||||
throw new LibMathRevertErrors.DivisionByZeroError();
|
||||
}
|
||||
@ -28,11 +22,10 @@ export function isRoundingErrorFloor(
|
||||
return lhs.gte(rhs);
|
||||
}
|
||||
|
||||
export function isRoundingErrorCeil(
|
||||
numerator: BigNumber,
|
||||
denominator: BigNumber,
|
||||
target: BigNumber,
|
||||
): boolean {
|
||||
/**
|
||||
* Checks if rounding error >= 0.1% when rounding up.
|
||||
*/
|
||||
export function isRoundingErrorCeil(numerator: BigNumber, denominator: BigNumber, target: BigNumber): boolean {
|
||||
if (denominator.eq(0)) {
|
||||
throw new LibMathRevertErrors.DivisionByZeroError();
|
||||
}
|
||||
@ -47,66 +40,46 @@ export function isRoundingErrorCeil(
|
||||
return lhs.gte(rhs);
|
||||
}
|
||||
|
||||
export function safeGetPartialAmountFloor(
|
||||
numerator: BigNumber,
|
||||
denominator: BigNumber,
|
||||
target: BigNumber,
|
||||
): BigNumber {
|
||||
/**
|
||||
* Calculates partial value given a numerator and denominator rounded down.
|
||||
* Reverts if rounding error is >= 0.1%
|
||||
*/
|
||||
export function safeGetPartialAmountFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
|
||||
if (isRoundingErrorFloor(numerator, denominator, target)) {
|
||||
throw new LibMathRevertErrors.RoundingError(numerator, denominator, target);
|
||||
}
|
||||
return safeDiv(
|
||||
safeMul(numerator, target),
|
||||
denominator,
|
||||
);
|
||||
return safeDiv(safeMul(numerator, target), denominator);
|
||||
}
|
||||
|
||||
export function safeGetPartialAmountCeil(
|
||||
numerator: BigNumber,
|
||||
denominator: BigNumber,
|
||||
target: BigNumber,
|
||||
): BigNumber {
|
||||
/**
|
||||
* Calculates partial value given a numerator and denominator rounded down.
|
||||
* Reverts if rounding error is >= 0.1%
|
||||
*/
|
||||
export function safeGetPartialAmountCeil(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
|
||||
if (isRoundingErrorCeil(numerator, denominator, target)) {
|
||||
throw new LibMathRevertErrors.RoundingError(numerator, denominator, target);
|
||||
}
|
||||
return safeDiv(
|
||||
safeAdd(
|
||||
safeMul(numerator, target),
|
||||
safeSub(denominator, new BigNumber(1)),
|
||||
),
|
||||
denominator,
|
||||
);
|
||||
return safeDiv(safeAdd(safeMul(numerator, target), safeSub(denominator, new BigNumber(1))), denominator);
|
||||
}
|
||||
|
||||
export function getPartialAmountFloor(
|
||||
numerator: BigNumber,
|
||||
denominator: BigNumber,
|
||||
target: BigNumber,
|
||||
): BigNumber {
|
||||
return safeDiv(
|
||||
safeMul(numerator, target),
|
||||
denominator,
|
||||
);
|
||||
/**
|
||||
* Calculates partial value given a numerator and denominator rounded down.
|
||||
*/
|
||||
export function getPartialAmountFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
|
||||
return safeDiv(safeMul(numerator, target), denominator);
|
||||
}
|
||||
|
||||
export function getPartialAmountCeil(
|
||||
numerator: BigNumber,
|
||||
denominator: BigNumber,
|
||||
target: BigNumber,
|
||||
): BigNumber {
|
||||
return safeDiv(
|
||||
safeAdd(
|
||||
safeMul(numerator, target),
|
||||
safeSub(denominator, new BigNumber(1)),
|
||||
),
|
||||
denominator,
|
||||
);
|
||||
/**
|
||||
* Calculates partial value given a numerator and denominator rounded down.
|
||||
*/
|
||||
export function getPartialAmountCeil(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
|
||||
return safeDiv(safeAdd(safeMul(numerator, target), safeSub(denominator, new BigNumber(1))), denominator);
|
||||
}
|
||||
|
||||
export function addFillResults(
|
||||
a: FillResults,
|
||||
b: FillResults,
|
||||
): FillResults {
|
||||
/**
|
||||
* Adds properties of two `FillResults`.
|
||||
*/
|
||||
export function addFillResults(a: FillResults, b: FillResults): FillResults {
|
||||
return {
|
||||
makerAssetFilledAmount: safeAdd(a.makerAssetFilledAmount, b.makerAssetFilledAmount),
|
||||
takerAssetFilledAmount: safeAdd(a.takerAssetFilledAmount, b.takerAssetFilledAmount),
|
||||
|
@ -1,9 +1,4 @@
|
||||
import {
|
||||
blockchainTests,
|
||||
constants,
|
||||
describe,
|
||||
expect,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { blockchainTests, constants, describe, expect } from '@0x/contracts-test-utils';
|
||||
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
@ -41,58 +36,54 @@ blockchainTests('LibFillResults', env => {
|
||||
];
|
||||
|
||||
it('matches the output of the reference function', async () => {
|
||||
const [ a, b ] = DEFAULT_FILL_RESULTS;
|
||||
const [a, b] = DEFAULT_FILL_RESULTS;
|
||||
const expected = ReferenceFunctions.addFillResults(a, b);
|
||||
const actual = await libsContract.addFillResults.callAsync(a, b);
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it('reverts if computing `makerAssetFilledAmount` overflows', async () => {
|
||||
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
const [a, b] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
b.makerAssetFilledAmount = MAX_UINT256;
|
||||
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
|
||||
a.makerAssetFilledAmount,
|
||||
b.makerAssetFilledAmount,
|
||||
);
|
||||
return expect(libsContract.addFillResults.callAsync(a, b))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(libsContract.addFillResults.callAsync(a, b)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('reverts if computing `takerAssetFilledAmount` overflows', async () => {
|
||||
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
const [a, b] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
b.takerAssetFilledAmount = MAX_UINT256;
|
||||
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
|
||||
a.takerAssetFilledAmount,
|
||||
b.takerAssetFilledAmount,
|
||||
);
|
||||
return expect(libsContract.addFillResults.callAsync(a, b))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(libsContract.addFillResults.callAsync(a, b)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('reverts if computing `makerFeePaid` overflows', async () => {
|
||||
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
const [a, b] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
b.makerFeePaid = MAX_UINT256;
|
||||
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
|
||||
a.makerFeePaid,
|
||||
b.makerFeePaid,
|
||||
);
|
||||
return expect(libsContract.addFillResults.callAsync(a, b))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(libsContract.addFillResults.callAsync(a, b)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('reverts if computing `takerFeePaid` overflows', async () => {
|
||||
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
const [a, b] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
b.takerFeePaid = MAX_UINT256;
|
||||
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
|
||||
a.takerFeePaid,
|
||||
b.takerFeePaid,
|
||||
);
|
||||
return expect(libsContract.addFillResults.callAsync(a, b))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(libsContract.addFillResults.callAsync(a, b)).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -26,17 +26,13 @@ blockchainTests('LibMath', env => {
|
||||
});
|
||||
|
||||
// Wrap a reference function with identical arguments in a promise.
|
||||
function createAsyncReferenceFunction<T>(
|
||||
ref: (...args: any[]) => T,
|
||||
): (...args: any[]) => Promise<T> {
|
||||
function createAsyncReferenceFunction<T>(ref: (...args: any[]) => T): (...args: any[]) => Promise<T> {
|
||||
return async (...args: any[]): Promise<T> => {
|
||||
return ref(...args);
|
||||
};
|
||||
}
|
||||
|
||||
function createContractTestFunction<T>(
|
||||
name: string,
|
||||
): (...args: any[]) => Promise<T> {
|
||||
function createContractTestFunction<T>(name: string): (...args: any[]) => Promise<T> {
|
||||
return async (...args: any[]): Promise<T> => {
|
||||
const method = (libsContract as any)[name] as { callAsync: (...args: any[]) => Promise<T> };
|
||||
return method.callAsync(...args);
|
||||
@ -72,8 +68,9 @@ blockchainTests('LibMath', env => {
|
||||
numerator.times(target),
|
||||
denominator,
|
||||
);
|
||||
return expect(libsContract.getPartialAmountFloor.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(
|
||||
libsContract.getPartialAmountFloor.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', async () => {
|
||||
@ -85,8 +82,9 @@ blockchainTests('LibMath', env => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(libsContract.getPartialAmountFloor.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(
|
||||
libsContract.getPartialAmountFloor.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -121,8 +119,9 @@ blockchainTests('LibMath', env => {
|
||||
denominator,
|
||||
new BigNumber(1),
|
||||
);
|
||||
return expect(libsContract.getPartialAmountCeil.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(
|
||||
libsContract.getPartialAmountCeil.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', async () => {
|
||||
@ -134,8 +133,9 @@ blockchainTests('LibMath', env => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(libsContract.getPartialAmountCeil.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(
|
||||
libsContract.getPartialAmountCeil.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -164,13 +164,10 @@ blockchainTests('LibMath', env => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(333);
|
||||
const expectedError = new LibMathRevertErrors.RoundingError(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
);
|
||||
return expect(libsContract.safeGetPartialAmountFloor.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
const expectedError = new LibMathRevertErrors.RoundingError(numerator, denominator, target);
|
||||
return expect(
|
||||
libsContract.safeGetPartialAmountFloor.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('reverts if `denominator` is zero', async () => {
|
||||
@ -178,8 +175,9 @@ blockchainTests('LibMath', env => {
|
||||
const denominator = ZERO_AMOUNT;
|
||||
const target = ONE_ETHER.times(0.01);
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(libsContract.safeGetPartialAmountFloor.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(
|
||||
libsContract.safeGetPartialAmountFloor.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', async () => {
|
||||
@ -191,8 +189,9 @@ blockchainTests('LibMath', env => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(libsContract.safeGetPartialAmountFloor.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(
|
||||
libsContract.safeGetPartialAmountFloor.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -221,13 +220,10 @@ blockchainTests('LibMath', env => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(333);
|
||||
const expectedError = new LibMathRevertErrors.RoundingError(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
);
|
||||
return expect(libsContract.safeGetPartialAmountCeil.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
const expectedError = new LibMathRevertErrors.RoundingError(numerator, denominator, target);
|
||||
return expect(
|
||||
libsContract.safeGetPartialAmountCeil.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('reverts if `denominator` is zero', async () => {
|
||||
@ -235,8 +231,9 @@ blockchainTests('LibMath', env => {
|
||||
const denominator = ZERO_AMOUNT;
|
||||
const target = ONE_ETHER.times(0.01);
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(libsContract.safeGetPartialAmountCeil.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(
|
||||
libsContract.safeGetPartialAmountCeil.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', async () => {
|
||||
@ -248,8 +245,9 @@ blockchainTests('LibMath', env => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(libsContract.safeGetPartialAmountCeil.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(
|
||||
libsContract.safeGetPartialAmountCeil.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -269,6 +267,7 @@ blockchainTests('LibMath', env => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(333);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target);
|
||||
expect(actual).to.eq(true);
|
||||
});
|
||||
@ -277,6 +276,7 @@ blockchainTests('LibMath', env => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(5e2);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target);
|
||||
expect(actual).to.eq(false);
|
||||
});
|
||||
@ -285,7 +285,9 @@ blockchainTests('LibMath', env => {
|
||||
const numerator = ONE_ETHER;
|
||||
const denominator = ONE_ETHER.dividedToIntegerBy(2);
|
||||
const target = ONE_ETHER.times(0.01);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const expected = ReferenceFunctions.isRoundingErrorFloor(numerator, denominator, target);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target);
|
||||
expect(actual).to.eq(expected);
|
||||
});
|
||||
@ -295,8 +297,9 @@ blockchainTests('LibMath', env => {
|
||||
const denominator = ZERO_AMOUNT;
|
||||
const target = ONE_ETHER.times(0.01);
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(
|
||||
libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', async () => {
|
||||
@ -308,8 +311,9 @@ blockchainTests('LibMath', env => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(
|
||||
libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -329,7 +333,8 @@ blockchainTests('LibMath', env => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(333);
|
||||
const actual = await libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorCeil.callAsync(numerator, denominator, target);
|
||||
expect(actual).to.eq(true);
|
||||
});
|
||||
|
||||
@ -337,7 +342,8 @@ blockchainTests('LibMath', env => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(5e2);
|
||||
const actual = await libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorCeil.callAsync(numerator, denominator, target);
|
||||
expect(actual).to.eq(false);
|
||||
});
|
||||
|
||||
@ -345,7 +351,9 @@ blockchainTests('LibMath', env => {
|
||||
const numerator = ONE_ETHER;
|
||||
const denominator = ONE_ETHER.dividedToIntegerBy(2);
|
||||
const target = ONE_ETHER.times(0.01);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const expected = ReferenceFunctions.isRoundingErrorCeil(numerator, denominator, target);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorCeil.callAsync(numerator, denominator, target);
|
||||
expect(actual).to.eq(expected);
|
||||
});
|
||||
@ -355,8 +363,9 @@ blockchainTests('LibMath', env => {
|
||||
const denominator = ZERO_AMOUNT;
|
||||
const target = ONE_ETHER.times(0.01);
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(libsContract.isRoundingErrorCeil.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(libsContract.isRoundingErrorCeil.callAsync(numerator, denominator, target)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', async () => {
|
||||
@ -368,8 +377,9 @@ blockchainTests('LibMath', env => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(libsContract.isRoundingErrorCeil.callAsync(numerator, denominator, target))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(libsContract.isRoundingErrorCeil.callAsync(numerator, denominator, target)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,4 @@
|
||||
import {
|
||||
constants,
|
||||
describe,
|
||||
expect,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { constants, describe, expect } from '@0x/contracts-test-utils';
|
||||
import { LibMathRevertErrors } from '@0x/order-utils';
|
||||
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
@ -20,7 +16,6 @@ import {
|
||||
describe('Reference Functions', () => {
|
||||
const { ONE_ETHER, MAX_UINT256, MAX_UINT256_ROOT, ZERO_AMOUNT } = constants;
|
||||
describe('LibFillResults', () => {
|
||||
|
||||
describe('addFillResults', () => {
|
||||
const DEFAULT_FILL_RESULTS = [
|
||||
{
|
||||
@ -38,7 +33,7 @@ describe('Reference Functions', () => {
|
||||
];
|
||||
|
||||
it('reverts if computing `makerAssetFilledAmount` overflows', () => {
|
||||
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
const [a, b] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
b.makerAssetFilledAmount = MAX_UINT256;
|
||||
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
|
||||
@ -49,7 +44,7 @@ describe('Reference Functions', () => {
|
||||
});
|
||||
|
||||
it('reverts if computing `takerAssetFilledAmount` overflows', () => {
|
||||
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
const [a, b] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
b.takerAssetFilledAmount = MAX_UINT256;
|
||||
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
|
||||
@ -60,7 +55,7 @@ describe('Reference Functions', () => {
|
||||
});
|
||||
|
||||
it('reverts if computing `makerFeePaid` overflows', () => {
|
||||
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
const [a, b] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
b.makerFeePaid = MAX_UINT256;
|
||||
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
|
||||
@ -71,7 +66,7 @@ describe('Reference Functions', () => {
|
||||
});
|
||||
|
||||
it('reverts if computing `takerFeePaid` overflows', () => {
|
||||
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
const [a, b] = _.cloneDeep(DEFAULT_FILL_RESULTS);
|
||||
b.takerFeePaid = MAX_UINT256;
|
||||
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
|
||||
@ -95,8 +90,9 @@ describe('Reference Functions', () => {
|
||||
numerator.times(target),
|
||||
denominator,
|
||||
);
|
||||
return expect(() => getPartialAmountFloor(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => getPartialAmountFloor(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', () => {
|
||||
@ -108,8 +104,9 @@ describe('Reference Functions', () => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(() => getPartialAmountFloor(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => getPartialAmountFloor(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -126,8 +123,9 @@ describe('Reference Functions', () => {
|
||||
denominator,
|
||||
new BigNumber(1),
|
||||
);
|
||||
return expect(() => getPartialAmountCeil(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => getPartialAmountCeil(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', () => {
|
||||
@ -139,8 +137,9 @@ describe('Reference Functions', () => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(() => getPartialAmountCeil(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => getPartialAmountCeil(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -151,13 +150,10 @@ describe('Reference Functions', () => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(333);
|
||||
const expectedError = new LibMathRevertErrors.RoundingError(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
const expectedError = new LibMathRevertErrors.RoundingError(numerator, denominator, target);
|
||||
return expect(() => safeGetPartialAmountFloor(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
return expect(() => safeGetPartialAmountFloor(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
});
|
||||
|
||||
it('reverts if `denominator` is zero', () => {
|
||||
@ -165,8 +161,9 @@ describe('Reference Functions', () => {
|
||||
const denominator = ZERO_AMOUNT;
|
||||
const target = ONE_ETHER.times(0.01);
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(() => safeGetPartialAmountFloor(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => safeGetPartialAmountFloor(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', () => {
|
||||
@ -178,8 +175,9 @@ describe('Reference Functions', () => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(() => safeGetPartialAmountFloor(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => safeGetPartialAmountFloor(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -190,13 +188,10 @@ describe('Reference Functions', () => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(333);
|
||||
const expectedError = new LibMathRevertErrors.RoundingError(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
const expectedError = new LibMathRevertErrors.RoundingError(numerator, denominator, target);
|
||||
return expect(() => safeGetPartialAmountCeil(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
return expect(() => safeGetPartialAmountCeil(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
});
|
||||
|
||||
it('reverts if `denominator` is zero', () => {
|
||||
@ -204,8 +199,9 @@ describe('Reference Functions', () => {
|
||||
const denominator = ZERO_AMOUNT;
|
||||
const target = ONE_ETHER.times(0.01);
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(() => safeGetPartialAmountCeil(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => safeGetPartialAmountCeil(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', () => {
|
||||
@ -217,8 +213,9 @@ describe('Reference Functions', () => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(() => safeGetPartialAmountCeil(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => safeGetPartialAmountCeil(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -229,6 +226,7 @@ describe('Reference Functions', () => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(333);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = isRoundingErrorFloor(numerator, denominator, target);
|
||||
expect(actual).to.eq(true);
|
||||
});
|
||||
@ -237,6 +235,7 @@ describe('Reference Functions', () => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(5e2);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = isRoundingErrorFloor(numerator, denominator, target);
|
||||
expect(actual).to.eq(false);
|
||||
});
|
||||
@ -246,8 +245,9 @@ describe('Reference Functions', () => {
|
||||
const denominator = ZERO_AMOUNT;
|
||||
const target = ONE_ETHER.times(0.01);
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(() => isRoundingErrorFloor(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => isRoundingErrorFloor(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', () => {
|
||||
@ -259,8 +259,9 @@ describe('Reference Functions', () => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(() => isRoundingErrorFloor(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => isRoundingErrorFloor(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -271,7 +272,8 @@ describe('Reference Functions', () => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(333);
|
||||
const actual = isRoundingErrorFloor(numerator, denominator, target);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = isRoundingErrorCeil(numerator, denominator, target);
|
||||
expect(actual).to.eq(true);
|
||||
});
|
||||
|
||||
@ -279,7 +281,8 @@ describe('Reference Functions', () => {
|
||||
const numerator = new BigNumber(1e3);
|
||||
const denominator = new BigNumber(1e4);
|
||||
const target = new BigNumber(5e2);
|
||||
const actual = isRoundingErrorFloor(numerator, denominator, target);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = isRoundingErrorCeil(numerator, denominator, target);
|
||||
expect(actual).to.eq(false);
|
||||
});
|
||||
|
||||
@ -288,8 +291,9 @@ describe('Reference Functions', () => {
|
||||
const denominator = ZERO_AMOUNT;
|
||||
const target = ONE_ETHER.times(0.01);
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(() => isRoundingErrorCeil(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => isRoundingErrorCeil(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if `numerator * target` overflows', () => {
|
||||
@ -301,8 +305,9 @@ describe('Reference Functions', () => {
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(() => isRoundingErrorCeil(numerator, denominator, target))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => isRoundingErrorCeil(numerator, denominator, target)).to.throw(
|
||||
expectedError.message,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -33,10 +33,10 @@
|
||||
"src/interfaces/IExchangeCore.sol",
|
||||
"src/interfaces/IMatchOrders.sol",
|
||||
"src/interfaces/ISignatureValidator.sol",
|
||||
"test/IsolatedExchange.sol",
|
||||
"src/interfaces/ITransactions.sol",
|
||||
"src/interfaces/IWallet.sol",
|
||||
"src/interfaces/IWrapperFunctions.sol",
|
||||
"test/IsolatedExchange.sol",
|
||||
"test/ReentrantERC20Token.sol",
|
||||
"test/TestAssetProxyDispatcher.sol",
|
||||
"test/TestExchangeInternals.sol",
|
||||
|
@ -64,7 +64,7 @@ contract IsolatedExchange is
|
||||
|
||||
// Fail if the first byte is 0.
|
||||
if (assetData.length > 0 && assetData[0] == 0x00) {
|
||||
revert('TRANSFER_FAILED');
|
||||
revert("TRANSFER_FAILED");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,25 +4,17 @@ import { BigNumber } from '@0x/utils';
|
||||
|
||||
const { safeGetPartialAmountFloor } = ExchangeLibsReferenceFunctions;
|
||||
|
||||
export function calculateFillResults(
|
||||
order: OrderWithoutDomain,
|
||||
takerAssetFilledAmount: BigNumber,
|
||||
): FillResults {
|
||||
/**
|
||||
* Calculates amounts filled and fees paid by maker and taker.
|
||||
*/
|
||||
export function calculateFillResults(order: OrderWithoutDomain, takerAssetFilledAmount: BigNumber): FillResults {
|
||||
const makerAssetFilledAmount = safeGetPartialAmountFloor(
|
||||
takerAssetFilledAmount,
|
||||
order.takerAssetAmount,
|
||||
order.makerAssetAmount,
|
||||
);
|
||||
const makerFeePaid = safeGetPartialAmountFloor(
|
||||
makerAssetFilledAmount,
|
||||
order.makerAssetAmount,
|
||||
order.makerFee,
|
||||
);
|
||||
const takerFeePaid = safeGetPartialAmountFloor(
|
||||
takerAssetFilledAmount,
|
||||
order.takerAssetAmount,
|
||||
order.takerFee,
|
||||
);
|
||||
const makerFeePaid = safeGetPartialAmountFloor(makerAssetFilledAmount, order.makerAssetAmount, order.makerFee);
|
||||
const takerFeePaid = safeGetPartialAmountFloor(takerAssetFilledAmount, order.takerAssetAmount, order.takerFee);
|
||||
return {
|
||||
makerAssetFilledAmount,
|
||||
takerAssetFilledAmount,
|
||||
|
@ -19,8 +19,8 @@ import {
|
||||
artifacts,
|
||||
ReferenceFunctions,
|
||||
TestExchangeInternalsContract,
|
||||
TestExchangeInternalsFillEventArgs,
|
||||
TestExchangeInternalsDispatchTransferFromCalledEventArgs,
|
||||
TestExchangeInternalsFillEventArgs,
|
||||
} from '../src';
|
||||
|
||||
blockchainTests('Exchange core internal functions', env => {
|
||||
@ -50,7 +50,7 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
let senderAddress: string;
|
||||
|
||||
before(async () => {
|
||||
[ senderAddress ] = await env.getAccountAddressesAsync();
|
||||
[senderAddress] = await env.getAccountAddressesAsync();
|
||||
testExchange = await TestExchangeInternalsContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestExchangeInternals,
|
||||
env.provider,
|
||||
@ -114,11 +114,7 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
describe('explicit tests', () => {
|
||||
const MAX_UINT256_ROOT = constants.MAX_UINT256_ROOT;
|
||||
function makeOrder(details?: Partial<Order>): Order {
|
||||
return _.assign(
|
||||
{},
|
||||
EMPTY_ORDER,
|
||||
details,
|
||||
);
|
||||
return _.assign({}, EMPTY_ORDER, details);
|
||||
}
|
||||
|
||||
it('matches the output of the reference function', async () => {
|
||||
@ -146,8 +142,9 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
takerAssetFilledAmount,
|
||||
order.makerAssetAmount,
|
||||
);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if computing `fillResults.makerFeePaid` overflows', async () => {
|
||||
@ -168,8 +165,9 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
makerAssetFilledAmount,
|
||||
order.makerFee,
|
||||
);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if computing `fillResults.takerFeePaid` overflows', async () => {
|
||||
@ -185,8 +183,9 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
takerAssetFilledAmount,
|
||||
order.takerFee,
|
||||
);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if `order.makerAssetAmount` is 0', async () => {
|
||||
@ -196,8 +195,9 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
});
|
||||
const takerAssetFilledAmount = ONE_ETHER;
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if `order.takerAssetAmount` is 0', async () => {
|
||||
@ -207,8 +207,9 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
});
|
||||
const takerAssetFilledAmount = ONE_ETHER;
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if there is a rounding error computing `makerAsssetFilledAmount`', async () => {
|
||||
@ -222,8 +223,9 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
order.takerAssetAmount,
|
||||
order.makerAssetAmount,
|
||||
);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if there is a rounding error computing `makerFeePaid`', async () => {
|
||||
@ -243,8 +245,9 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
order.makerAssetAmount,
|
||||
order.makerFee,
|
||||
);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
it('reverts if there is a rounding error computing `takerFeePaid`', async () => {
|
||||
@ -264,8 +267,9 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
order.makerAssetAmount,
|
||||
order.takerFee,
|
||||
);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(testExchange.calculateFillResults.callAsync(order, takerAssetFilledAmount)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -299,10 +303,7 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
takerAssetFillAmount: BigNumber,
|
||||
): Promise<void> {
|
||||
const orderHash = randomHash();
|
||||
const fillResults = ReferenceFunctions.calculateFillResults(
|
||||
order,
|
||||
takerAssetFillAmount,
|
||||
);
|
||||
const fillResults = ReferenceFunctions.calculateFillResults(order, takerAssetFillAmount);
|
||||
const expectedFilledState = orderTakerAssetFilledAmount.plus(takerAssetFillAmount);
|
||||
// CAll `testUpdateFilledState()`, which will set the `filled`
|
||||
// state for this order to `orderTakerAssetFilledAmount` before
|
||||
@ -321,6 +322,7 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
// Assert the `filled` state for this order.
|
||||
expect(actualFilledState).to.bignumber.eq(expectedFilledState);
|
||||
// Assert the logs.
|
||||
// tslint:disable-next-line: no-unnecessary-type-assertion
|
||||
const fillEvent = receipt.logs[0] as LogWithDecodedArgs<TestExchangeInternalsFillEventArgs>;
|
||||
expect(fillEvent.event).to.eq('Fill');
|
||||
expect(fillEvent.args.makerAddress).to.eq(order.makerAddress);
|
||||
@ -363,13 +365,15 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
orderTakerAssetFilledAmount,
|
||||
takerAssetFillAmount,
|
||||
);
|
||||
return expect(testExchange.testUpdateFilledState.awaitTransactionSuccessAsync(
|
||||
order,
|
||||
randomAddress(),
|
||||
randomHash(),
|
||||
orderTakerAssetFilledAmount,
|
||||
fillResults,
|
||||
)).to.revertWith(expectedError);
|
||||
return expect(
|
||||
testExchange.testUpdateFilledState.awaitTransactionSuccessAsync(
|
||||
order,
|
||||
randomAddress(),
|
||||
randomHash(),
|
||||
orderTakerAssetFilledAmount,
|
||||
fillResults,
|
||||
),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
|
||||
@ -402,14 +406,11 @@ blockchainTests('Exchange core internal functions', env => {
|
||||
takerFeePaid: ONE_ETHER.times(0.025),
|
||||
};
|
||||
const receipt = await logDecoder.getTxWithDecodedLogsAsync(
|
||||
await testExchange.settleOrder.sendTransactionAsync(
|
||||
orderHash,
|
||||
order,
|
||||
takerAddress,
|
||||
fillResults,
|
||||
),
|
||||
await testExchange.settleOrder.sendTransactionAsync(orderHash, order, takerAddress, fillResults),
|
||||
);
|
||||
const logs = receipt.logs as Array<LogWithDecodedArgs<TestExchangeInternalsDispatchTransferFromCalledEventArgs>>;
|
||||
const logs = receipt.logs as Array<
|
||||
LogWithDecodedArgs<TestExchangeInternalsDispatchTransferFromCalledEventArgs>
|
||||
>;
|
||||
expect(logs.length === 4);
|
||||
expect(_.every(logs, log => log.event === 'DispatchTransferFromCalled')).to.be.true();
|
||||
// taker -> maker
|
||||
|
@ -1,10 +1,5 @@
|
||||
import { ReferenceFunctions as LibReferenceFunctions } from '@0x/contracts-exchange-libs';
|
||||
import {
|
||||
blockchainTests,
|
||||
constants,
|
||||
expect,
|
||||
hexRandom,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { blockchainTests, constants, expect, hexRandom } from '@0x/contracts-test-utils';
|
||||
import { ExchangeRevertErrors, LibMathRevertErrors } from '@0x/order-utils';
|
||||
import { FillResults, OrderInfo, OrderStatus, SignatureType } from '@0x/types';
|
||||
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
|
||||
@ -50,7 +45,7 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
let nextSaltValue = 1;
|
||||
|
||||
before(async () => {
|
||||
[ takerAddress, notTakerAddress ] = await env.getAccountAddressesAsync();
|
||||
[takerAddress, notTakerAddress] = await env.getAccountAddressesAsync();
|
||||
exchange = await IsolatedExchangeWrapper.deployAsync(
|
||||
env.web3Wrapper,
|
||||
_.assign(env.txDefaults, { from: takerAddress }),
|
||||
@ -79,14 +74,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
const fillResults = await exchange.fillOrderAsync(order, takerAssetFillAmount, signature);
|
||||
const newOrderInfo = await exchange.getOrderInfoAsync(order);
|
||||
// Check returned fillResults.
|
||||
expect(fillResults.makerAssetFilledAmount)
|
||||
.to.bignumber.eq(efr.makerAssetFilledAmount);
|
||||
expect(fillResults.takerAssetFilledAmount)
|
||||
.to.bignumber.eq(efr.takerAssetFilledAmount);
|
||||
expect(fillResults.makerFeePaid)
|
||||
.to.bignumber.eq(efr.makerFeePaid);
|
||||
expect(fillResults.takerFeePaid)
|
||||
.to.bignumber.eq(efr.takerFeePaid);
|
||||
expect(fillResults.makerAssetFilledAmount).to.bignumber.eq(efr.makerAssetFilledAmount);
|
||||
expect(fillResults.takerAssetFilledAmount).to.bignumber.eq(efr.takerAssetFilledAmount);
|
||||
expect(fillResults.makerFeePaid).to.bignumber.eq(efr.makerFeePaid);
|
||||
expect(fillResults.takerFeePaid).to.bignumber.eq(efr.takerFeePaid);
|
||||
// Check balances.
|
||||
for (const assetData of Object.keys(efb)) {
|
||||
for (const address of Object.keys(efb[assetData])) {
|
||||
@ -98,13 +89,11 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
}
|
||||
// Check order info.
|
||||
expect(newOrderInfo.orderStatus).to.eq(eoi.orderStatus);
|
||||
expect(newOrderInfo.orderTakerAssetFilledAmount)
|
||||
.to.bignumber.eq(eoi.orderTakerAssetFilledAmount);
|
||||
expect(newOrderInfo.orderTakerAssetFilledAmount).to.bignumber.eq(eoi.orderTakerAssetFilledAmount);
|
||||
// Check that there wasn't an overfill.
|
||||
expect(
|
||||
newOrderInfo.orderTakerAssetFilledAmount.lte(order.takerAssetAmount),
|
||||
'checking for overfill',
|
||||
).to.be.ok('');
|
||||
expect(newOrderInfo.orderTakerAssetFilledAmount.lte(order.takerAssetAmount), 'checking for overfill').to.be.ok(
|
||||
'',
|
||||
);
|
||||
return {
|
||||
fillResults,
|
||||
orderInfo: newOrderInfo,
|
||||
@ -116,24 +105,17 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
orderInfo: OrderInfo,
|
||||
takerAssetFillAmount: BigNumber,
|
||||
): FillResults {
|
||||
const remainingTakerAssetAmount = order.takerAssetAmount.minus(
|
||||
orderInfo.orderTakerAssetFilledAmount,
|
||||
);
|
||||
return calculateFillResults(
|
||||
order,
|
||||
BigNumber.min(takerAssetFillAmount, remainingTakerAssetAmount),
|
||||
);
|
||||
const remainingTakerAssetAmount = order.takerAssetAmount.minus(orderInfo.orderTakerAssetFilledAmount);
|
||||
return calculateFillResults(order, BigNumber.min(takerAssetFillAmount, remainingTakerAssetAmount));
|
||||
}
|
||||
|
||||
function calculateExpectedOrderInfo(
|
||||
order: Order,
|
||||
orderInfo: OrderInfo,
|
||||
fillResults: FillResults,
|
||||
): OrderInfo {
|
||||
const orderTakerAssetFilledAmount =
|
||||
orderInfo.orderTakerAssetFilledAmount.plus(fillResults.takerAssetFilledAmount);
|
||||
const orderStatus = orderTakerAssetFilledAmount.gte(order.takerAssetAmount) ?
|
||||
OrderStatus.FullyFilled : OrderStatus.Fillable;
|
||||
function calculateExpectedOrderInfo(order: Order, orderInfo: OrderInfo, fillResults: FillResults): OrderInfo {
|
||||
const orderTakerAssetFilledAmount = orderInfo.orderTakerAssetFilledAmount.plus(
|
||||
fillResults.takerAssetFilledAmount,
|
||||
);
|
||||
const orderStatus = orderTakerAssetFilledAmount.gte(order.takerAssetAmount)
|
||||
? OrderStatus.FullyFilled
|
||||
: OrderStatus.Fillable;
|
||||
return {
|
||||
orderHash: exchange.getOrderHash(order),
|
||||
orderStatus,
|
||||
@ -141,10 +123,7 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
};
|
||||
}
|
||||
|
||||
function calculateExpectedFillBalances(
|
||||
order: Order,
|
||||
fillResults: FillResults,
|
||||
): AssetBalances {
|
||||
function calculateExpectedFillBalances(order: Order, fillResults: FillResults): AssetBalances {
|
||||
const balances: AssetBalances = {};
|
||||
const addBalance = (assetData: string, address: string, amount: BigNumber) => {
|
||||
balances[assetData] = balances[assetData] || {};
|
||||
@ -176,7 +155,7 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
expect(orderInfo.orderStatus).to.eq(OrderStatus.FullyFilled);
|
||||
});
|
||||
|
||||
it('can\'t overfill an order', async () => {
|
||||
it("can't overfill an order", async () => {
|
||||
const order = createOrder();
|
||||
const { orderInfo } = await fillOrderAndAssertResultsAsync(order, order.takerAssetAmount.times(1.01));
|
||||
expect(orderInfo.orderStatus).to.eq(OrderStatus.FullyFilled);
|
||||
@ -266,7 +245,7 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
expect(orderInfos[1].orderStatus).to.eq(OrderStatus.Fillable);
|
||||
});
|
||||
|
||||
it('can\'t overfill an order in two fills', async () => {
|
||||
it("can't overfill an order in two fills", async () => {
|
||||
const order = createOrder();
|
||||
const fillAmounts = splitAmount(order.takerAssetAmount);
|
||||
fillAmounts[0] = fillAmounts[0].times(1.01);
|
||||
@ -320,7 +299,7 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
});
|
||||
|
||||
describe('bad fills', () => {
|
||||
it('can\'t fill an order with zero takerAssetAmount', async () => {
|
||||
it("can't fill an order with zero takerAssetAmount", async () => {
|
||||
const order = createOrder({
|
||||
takerAssetAmount: ZERO_AMOUNT,
|
||||
});
|
||||
@ -328,11 +307,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
exchange.getOrderHash(order),
|
||||
OrderStatus.InvalidTakerAssetAmount,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, ONE_ETHER))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, ONE_ETHER)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order with zero makerAssetAmount', async () => {
|
||||
it("can't fill an order with zero makerAssetAmount", async () => {
|
||||
const order = createOrder({
|
||||
makerAssetAmount: ZERO_AMOUNT,
|
||||
});
|
||||
@ -340,22 +318,20 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
exchange.getOrderHash(order),
|
||||
OrderStatus.InvalidMakerAssetAmount,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, ONE_ETHER))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, ONE_ETHER)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order that is fully filled', async () => {
|
||||
it("can't fill an order that is fully filled", async () => {
|
||||
const order = createOrder();
|
||||
const expectedError = new ExchangeRevertErrors.OrderStatusError(
|
||||
exchange.getOrderHash(order),
|
||||
OrderStatus.FullyFilled,
|
||||
);
|
||||
await exchange.fillOrderAsync(order, order.takerAssetAmount);
|
||||
return expect(exchange.fillOrderAsync(order, 1))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, 1)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order that is expired', async () => {
|
||||
it("can't fill an order that is expired", async () => {
|
||||
const order = createOrder({
|
||||
expirationTimeSeconds: new BigNumber(getCurrentTime() - 60),
|
||||
});
|
||||
@ -363,11 +339,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
exchange.getOrderHash(order),
|
||||
OrderStatus.Expired,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order that is cancelled by `cancelOrder()`', async () => {
|
||||
it("can't fill an order that is cancelled by `cancelOrder()`", async () => {
|
||||
const order = createOrder({
|
||||
makerAddress: notTakerAddress,
|
||||
});
|
||||
@ -376,11 +351,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
OrderStatus.Cancelled,
|
||||
);
|
||||
await exchange.cancelOrderAsync(order, { from: notTakerAddress });
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order that is cancelled by `cancelOrdersUpTo()`', async () => {
|
||||
it("can't fill an order that is cancelled by `cancelOrdersUpTo()`", async () => {
|
||||
const order = createOrder({
|
||||
makerAddress: notTakerAddress,
|
||||
});
|
||||
@ -389,11 +363,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
OrderStatus.Cancelled,
|
||||
);
|
||||
await exchange.cancelOrdersUpToAsync(order.salt, { from: notTakerAddress });
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order if taker is not `takerAddress`', async () => {
|
||||
it("can't fill an order if taker is not `takerAddress`", async () => {
|
||||
const order = createOrder({
|
||||
takerAddress: randomAddress(),
|
||||
});
|
||||
@ -401,11 +374,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
exchange.getOrderHash(order),
|
||||
takerAddress,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order if sender is not `senderAddress`', async () => {
|
||||
it("can't fill an order if sender is not `senderAddress`", async () => {
|
||||
const order = createOrder({
|
||||
senderAddress: randomAddress(),
|
||||
});
|
||||
@ -413,11 +385,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
exchange.getOrderHash(order),
|
||||
takerAddress,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order with a taker amount that results in a maker asset rounding error', async () => {
|
||||
it("can't fill an order with a taker amount that results in a maker asset rounding error", async () => {
|
||||
const order = createOrder({
|
||||
makerAssetAmount: new BigNumber(100),
|
||||
takerAssetAmount: ONE_ETHER,
|
||||
@ -428,11 +399,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
order.takerAssetAmount,
|
||||
order.makerAssetAmount,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order with a taker amount that results in a maker fee rounding error', async () => {
|
||||
it("can't fill an order with a taker amount that results in a maker fee rounding error", async () => {
|
||||
const order = createOrder({
|
||||
makerAssetAmount: ONE_ETHER.times(2),
|
||||
takerAssetAmount: ONE_ETHER,
|
||||
@ -444,11 +414,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
order.makerAssetAmount,
|
||||
order.makerFee,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order with a taker amount that results in a taker fee rounding error', async () => {
|
||||
it("can't fill an order with a taker amount that results in a taker fee rounding error", async () => {
|
||||
const order = createOrder({
|
||||
makerAssetAmount: ONE_ETHER.times(2),
|
||||
takerAssetAmount: ONE_ETHER,
|
||||
@ -460,11 +429,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
order.takerAssetAmount,
|
||||
order.takerFee,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order that results in a `makerAssetFilledAmount` overflow.', async () => {
|
||||
it("can't fill an order that results in a `makerAssetFilledAmount` overflow.", async () => {
|
||||
// All values need to be large to ensure we don't trigger a Rounding.
|
||||
const order = createOrder({
|
||||
makerAssetAmount: MAX_UINT256_ROOT.times(2),
|
||||
@ -476,11 +444,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
takerAssetFillAmount,
|
||||
order.makerAssetAmount,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order that results in a `makerFeePaid` overflow.', async () => {
|
||||
it("can't fill an order that results in a `makerFeePaid` overflow.", async () => {
|
||||
// All values need to be large to ensure we don't trigger a Rounding.
|
||||
const order = createOrder({
|
||||
makerAssetAmount: MAX_UINT256_ROOT,
|
||||
@ -498,11 +465,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
makerAssetFilledAmount,
|
||||
order.makerFee,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order that results in a `takerFeePaid` overflow.', async () => {
|
||||
it("can't fill an order that results in a `takerFeePaid` overflow.", async () => {
|
||||
// All values need to be large to ensure we don't trigger a Rounding.
|
||||
const order = createOrder({
|
||||
makerAssetAmount: MAX_UINT256_ROOT,
|
||||
@ -515,11 +481,10 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
takerAssetFillAmount,
|
||||
order.takerFee,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmount)).to.revertWith(expectedError);
|
||||
});
|
||||
|
||||
it('can\'t fill an order with a bad signature', async () => {
|
||||
it("can't fill an order with a bad signature", async () => {
|
||||
const order = createOrder();
|
||||
const signature = createBadSignature();
|
||||
const expectedError = new ExchangeRevertErrors.SignatureError(
|
||||
@ -528,11 +493,12 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
order.makerAddress,
|
||||
signature,
|
||||
);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount, signature))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount, signature)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
it('can\'t complementary fill an order with a bad signature that is always checked', async () => {
|
||||
it("can't complementary fill an order with a bad signature that is always checked", async () => {
|
||||
const order = createOrder();
|
||||
const takerAssetFillAmounts = splitAmount(order.takerAssetAmount);
|
||||
const goodSignature = createGoodSignature(SignatureType.Wallet);
|
||||
@ -544,42 +510,39 @@ blockchainTests('Isolated fillOrder() tests', env => {
|
||||
badSignature,
|
||||
);
|
||||
await exchange.fillOrderAsync(order, takerAssetFillAmounts[0], goodSignature);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmounts[1], badSignature))
|
||||
.to.revertWith(expectedError);
|
||||
return expect(exchange.fillOrderAsync(order, takerAssetFillAmounts[1], badSignature)).to.revertWith(
|
||||
expectedError,
|
||||
);
|
||||
});
|
||||
|
||||
const TRANSFER_ERROR = 'TRANSFER_FAILED';
|
||||
|
||||
it('can\'t fill an order with a maker asset that fails to transfer', async () => {
|
||||
it("can't fill an order with a maker asset that fails to transfer", async () => {
|
||||
const order = createOrder({
|
||||
makerAssetData: createBadAssetData(),
|
||||
});
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount))
|
||||
.to.revertWith(TRANSFER_ERROR);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount)).to.revertWith(TRANSFER_ERROR);
|
||||
});
|
||||
|
||||
it('can\'t fill an order with a taker asset that fails to transfer', async () => {
|
||||
it("can't fill an order with a taker asset that fails to transfer", async () => {
|
||||
const order = createOrder({
|
||||
takerAssetData: createBadAssetData(),
|
||||
});
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount))
|
||||
.to.revertWith(TRANSFER_ERROR);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount)).to.revertWith(TRANSFER_ERROR);
|
||||
});
|
||||
|
||||
it('can\'t fill an order with a maker fee asset that fails to transfer', async () => {
|
||||
it("can't fill an order with a maker fee asset that fails to transfer", async () => {
|
||||
const order = createOrder({
|
||||
makerFeeAssetData: createBadAssetData(),
|
||||
});
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount))
|
||||
.to.revertWith(TRANSFER_ERROR);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount)).to.revertWith(TRANSFER_ERROR);
|
||||
});
|
||||
|
||||
it('can\'t fill an order with a taker fee asset that fails to transfer', async () => {
|
||||
it("can't fill an order with a taker fee asset that fails to transfer", async () => {
|
||||
const order = createOrder({
|
||||
takerFeeAssetData: createBadAssetData(),
|
||||
});
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount))
|
||||
.to.revertWith(TRANSFER_ERROR);
|
||||
return expect(exchange.fillOrderAsync(order, order.takerAssetAmount)).to.revertWith(TRANSFER_ERROR);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -270,17 +270,9 @@ describe('matchOrders', () => {
|
||||
const numerator = signedOrderLeft.makerAssetAmount;
|
||||
const denominator = signedOrderLeft.takerAssetAmount;
|
||||
const target = signedOrderRight.makerAssetAmount;
|
||||
const _isRoundingErrorCeil = isRoundingErrorCeil(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
);
|
||||
const _isRoundingErrorCeil = isRoundingErrorCeil(numerator, denominator, target);
|
||||
expect(_isRoundingErrorCeil).to.be.true();
|
||||
const _isRoundingErrorFloor = isRoundingErrorFloor(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
);
|
||||
const _isRoundingErrorFloor = isRoundingErrorFloor(numerator, denominator, target);
|
||||
expect(_isRoundingErrorFloor).to.be.false();
|
||||
// Match signedOrderLeft with signedOrderRight
|
||||
// Note that the left maker received a slightly better sell price.
|
||||
@ -336,17 +328,9 @@ describe('matchOrders', () => {
|
||||
const numerator = signedOrderRight.takerAssetAmount;
|
||||
const denominator = signedOrderRight.makerAssetAmount;
|
||||
const target = signedOrderLeft.takerAssetAmount;
|
||||
const _isRoundingErrorFloor = isRoundingErrorFloor(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
);
|
||||
const _isRoundingErrorFloor = isRoundingErrorFloor(numerator, denominator, target);
|
||||
expect(_isRoundingErrorFloor).to.be.true();
|
||||
const _isRoundingErrorCeil = isRoundingErrorCeil(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
);
|
||||
const _isRoundingErrorCeil = isRoundingErrorCeil(numerator, denominator, target);
|
||||
expect(_isRoundingErrorCeil).to.be.false();
|
||||
// Match signedOrderLeft isRoundingErrorFloor right maker received a slightly better purchase price.
|
||||
// This is intentional; see note in MixinMatchOrders.calculateMatchedFillResults.
|
||||
@ -1414,17 +1398,9 @@ describe('matchOrders', () => {
|
||||
const numerator = signedOrderLeft.makerAssetAmount;
|
||||
const denominator = signedOrderLeft.takerAssetAmount;
|
||||
const target = signedOrderRight.makerAssetAmount;
|
||||
const _isRoundingErrorCeil = isRoundingErrorCeil(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
);
|
||||
const _isRoundingErrorCeil = isRoundingErrorCeil(numerator, denominator, target);
|
||||
expect(_isRoundingErrorCeil).to.be.true();
|
||||
const _isRoundingErrorFloor = isRoundingErrorFloor(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
);
|
||||
const _isRoundingErrorFloor = isRoundingErrorFloor(numerator, denominator, target);
|
||||
expect(_isRoundingErrorFloor).to.be.false();
|
||||
// Match signedOrderLeft with signedOrderRight
|
||||
// Note that the left maker received a slightly better sell price.
|
||||
@ -1480,17 +1456,9 @@ describe('matchOrders', () => {
|
||||
const numerator = signedOrderRight.makerAssetAmount;
|
||||
const denominator = signedOrderRight.takerAssetAmount;
|
||||
const target = signedOrderLeft.makerAssetAmount;
|
||||
const _isRoundingErrorCeil = isRoundingErrorCeil(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
);
|
||||
const _isRoundingErrorCeil = isRoundingErrorCeil(numerator, denominator, target);
|
||||
expect(_isRoundingErrorCeil).to.be.false();
|
||||
const _isRoundingErrorFloor = isRoundingErrorFloor(
|
||||
numerator,
|
||||
denominator,
|
||||
target,
|
||||
);
|
||||
const _isRoundingErrorFloor = isRoundingErrorFloor(numerator, denominator, target);
|
||||
expect(_isRoundingErrorFloor).to.be.false();
|
||||
// Match signedOrderLeft with signedOrderRight
|
||||
// Note that the right maker received a slightly better purchase price.
|
||||
|
@ -1,9 +1,5 @@
|
||||
import { ReferenceFunctions as LibReferenceFunctions } from '@0x/contracts-exchange-libs';
|
||||
import {
|
||||
constants,
|
||||
describe,
|
||||
expect,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { constants, describe, expect } from '@0x/contracts-test-utils';
|
||||
import { LibMathRevertErrors } from '@0x/order-utils';
|
||||
import { OrderWithoutDomain as Order } from '@0x/types';
|
||||
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
|
||||
@ -33,11 +29,7 @@ describe('Reference functions', () => {
|
||||
describe('calculateFillResults', () => {
|
||||
const MAX_UINT256_ROOT = constants.MAX_UINT256_ROOT;
|
||||
function makeOrder(details?: Partial<Order>): Order {
|
||||
return _.assign(
|
||||
{},
|
||||
EMPTY_ORDER,
|
||||
details,
|
||||
);
|
||||
return _.assign({}, EMPTY_ORDER, details);
|
||||
}
|
||||
|
||||
it('reverts if computing `fillResults.makerAssetFilledAmount` overflows', () => {
|
||||
@ -52,8 +44,7 @@ describe('Reference functions', () => {
|
||||
takerAssetFilledAmount,
|
||||
order.makerAssetAmount,
|
||||
);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
|
||||
});
|
||||
|
||||
it('reverts if computing `fillResults.makerFeePaid` overflows', () => {
|
||||
@ -74,8 +65,7 @@ describe('Reference functions', () => {
|
||||
makerAssetFilledAmount,
|
||||
order.makerFee,
|
||||
);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
|
||||
});
|
||||
|
||||
it('reverts if computing `fillResults.takerFeePaid` overflows', () => {
|
||||
@ -91,8 +81,7 @@ describe('Reference functions', () => {
|
||||
takerAssetFilledAmount,
|
||||
order.takerFee,
|
||||
);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
|
||||
});
|
||||
|
||||
it('reverts if `order.makerAssetAmount` is 0', () => {
|
||||
@ -102,8 +91,7 @@ describe('Reference functions', () => {
|
||||
});
|
||||
const takerAssetFilledAmount = ONE_ETHER;
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
|
||||
});
|
||||
|
||||
it('reverts if `order.takerAssetAmount` is 0', () => {
|
||||
@ -113,8 +101,7 @@ describe('Reference functions', () => {
|
||||
});
|
||||
const takerAssetFilledAmount = ONE_ETHER;
|
||||
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
|
||||
});
|
||||
|
||||
it('reverts if there is a rounding error computing `makerAsssetFilledAmount`', () => {
|
||||
@ -128,8 +115,7 @@ describe('Reference functions', () => {
|
||||
order.takerAssetAmount,
|
||||
order.makerAssetAmount,
|
||||
);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
|
||||
});
|
||||
|
||||
it('reverts if there is a rounding error computing `makerFeePaid`', () => {
|
||||
@ -149,8 +135,7 @@ describe('Reference functions', () => {
|
||||
order.makerAssetAmount,
|
||||
order.makerFee,
|
||||
);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
|
||||
});
|
||||
|
||||
it('reverts if there is a rounding error computing `takerFeePaid`', () => {
|
||||
@ -170,8 +155,7 @@ describe('Reference functions', () => {
|
||||
order.makerAssetAmount,
|
||||
order.takerFee,
|
||||
);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount))
|
||||
.to.throw(expectedError.message);
|
||||
return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,12 +1,7 @@
|
||||
import { artifacts as erc1155Artifacts } from '@0x/contracts-erc1155';
|
||||
import { artifacts as erc20Artifacts } from '@0x/contracts-erc20';
|
||||
import { artifacts as erc721Artifacts } from '@0x/contracts-erc721';
|
||||
import {
|
||||
BatchMatchOrder,
|
||||
LogDecoder,
|
||||
orderUtils,
|
||||
Web3ProviderEngine,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { BatchMatchOrder, LogDecoder, orderUtils, Web3ProviderEngine } from '@0x/contracts-test-utils';
|
||||
import {
|
||||
BatchMatchedFillResults,
|
||||
FillResults,
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
export enum FeeRecipientAddressScenario {
|
||||
BurnAddress = 'BURN_ADDRESS',
|
||||
EthUserAddress = 'ETH_USER_ADDRESS',
|
||||
|
@ -130,9 +130,7 @@ export class IsolatedExchangeWrapper {
|
||||
await this.instance.fillOrder.sendTransactionAsync.call(this.instance, ...args),
|
||||
);
|
||||
this.lastTxEvents = extractEvents(receipt.logs);
|
||||
this.lastTxBalanceChanges = getBalanceChangesFromTransferFromCalls(
|
||||
this.lastTxEvents.transferFromCalls,
|
||||
);
|
||||
this.lastTxBalanceChanges = getBalanceChangesFromTransferFromCalls(this.lastTxEvents.transferFromCalls);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -179,21 +177,16 @@ function createEmptyEvents(): IsolatedExchangeEvents {
|
||||
function extractEvents(logs: LogEntry[]): IsolatedExchangeEvents {
|
||||
return {
|
||||
fillEvents: filterLogsToArguments<FillEventArgs>(logs, 'Fill'),
|
||||
transferFromCalls: filterLogsToArguments<DispatchTransferFromCallArgs>(
|
||||
logs,
|
||||
'DispatchTransferFromCalled',
|
||||
),
|
||||
transferFromCalls: filterLogsToArguments<DispatchTransferFromCallArgs>(logs, 'DispatchTransferFromCalled'),
|
||||
};
|
||||
}
|
||||
|
||||
// Executes transferFrom calls to compute relative balances for addresses.
|
||||
function getBalanceChangesFromTransferFromCalls(
|
||||
calls: DispatchTransferFromCallArgs[],
|
||||
): AssetBalances {
|
||||
function getBalanceChangesFromTransferFromCalls(calls: DispatchTransferFromCallArgs[]): AssetBalances {
|
||||
const changes: AssetBalances = {};
|
||||
for (const call of calls) {
|
||||
const { assetData, from, to, amount } = call;
|
||||
const balances = changes[assetData] = changes[assetData ] || {};
|
||||
const balances = (changes[assetData] = changes[assetData] || {});
|
||||
const fromBalance = balances[from] || constants.ZERO_AMOUNT;
|
||||
const toBalance = balances[to] || constants.ZERO_AMOUNT;
|
||||
balances[from] = fromBalance.minus(amount);
|
||||
|
@ -1,17 +1,7 @@
|
||||
import { ERC1155ProxyWrapper, ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy';
|
||||
import {
|
||||
ERC1155HoldingsByOwner,
|
||||
expect,
|
||||
OrderStatus,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { ERC1155HoldingsByOwner, expect, OrderStatus } from '@0x/contracts-test-utils';
|
||||
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
|
||||
import {
|
||||
AssetProxyId,
|
||||
BatchMatchedFillResults,
|
||||
FillResults,
|
||||
MatchedFillResults,
|
||||
SignedOrder,
|
||||
} from '@0x/types';
|
||||
import { AssetProxyId, BatchMatchedFillResults, FillResults, MatchedFillResults, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
@ -2,5 +2,8 @@
|
||||
"extends": ["@0x/tslint-config"],
|
||||
"rules": {
|
||||
"custom-no-magic-numbers": false
|
||||
},
|
||||
"linterOptions": {
|
||||
"exclude": ["src/artifacts.ts"]
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@
|
||||
{
|
||||
"note": "Update `testWithReferenceFuncAsync` to work with `RevertErrors`",
|
||||
"pr": "TODO"
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -83,11 +83,7 @@ export async function testWithReferenceFuncAsync(
|
||||
if (expectedError !== undefined) {
|
||||
// Expecting an error.
|
||||
if (actualError === undefined) {
|
||||
return expect.fail(
|
||||
actualError,
|
||||
expectedError,
|
||||
`${testCaseString}: expected failure but instead succeeded`,
|
||||
);
|
||||
return expect.fail(actualError, expectedError, `${testCaseString}: expected failure but instead succeeded`);
|
||||
} else {
|
||||
if (expectedError instanceof RevertError) {
|
||||
// Expecting a RevertError.
|
||||
@ -112,7 +108,9 @@ export async function testWithReferenceFuncAsync(
|
||||
return expect.fail(
|
||||
actualError,
|
||||
expectedError,
|
||||
`${testCaseString}: expected error message '${actualError.message}' to equal '${expectedError.message}'`,
|
||||
`${testCaseString}: expected error message '${actualError.message}' to equal '${
|
||||
expectedError.message
|
||||
}'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -120,11 +118,7 @@ export async function testWithReferenceFuncAsync(
|
||||
} else {
|
||||
// Not expecting an error.
|
||||
if (actualError !== undefined) {
|
||||
return expect.fail(
|
||||
actualError,
|
||||
expectedError,
|
||||
`${testCaseString}: expected success but instead failed`,
|
||||
);
|
||||
return expect.fail(actualError, expectedError, `${testCaseString}: expected success but instead failed`);
|
||||
}
|
||||
if (expected instanceof BigNumber) {
|
||||
// Technically we can do this with `deep.eq`, but this prints prettier
|
||||
|
@ -28,8 +28,9 @@ describe('testWithReferenceFuncAsync', () => {
|
||||
});
|
||||
|
||||
it('fails when both succeed and actual != expected', async () => {
|
||||
return expect(testWithReferenceFuncAsync(alwaysValueFunc(3), divAsync, [1, 2]))
|
||||
.to.be.rejectedWith('{"x":1,"y":2}: expected 0.5 to deeply equal 3');
|
||||
return expect(testWithReferenceFuncAsync(alwaysValueFunc(3), divAsync, [1, 2])).to.be.rejectedWith(
|
||||
'{"x":1,"y":2}: expected 0.5 to deeply equal 3',
|
||||
);
|
||||
});
|
||||
|
||||
it('passes when both fail and error messages are the same', async () => {
|
||||
@ -44,9 +45,7 @@ describe('testWithReferenceFuncAsync', () => {
|
||||
const notError = new Error(notErrorMessage);
|
||||
return expect(
|
||||
testWithReferenceFuncAsync(alwaysFailFunc(notError), alwaysFailFunc(error), [1, 2]),
|
||||
).to.be.rejectedWith(
|
||||
`{"x":1,"y":2}: expected error message '${errorMessage}' to equal '${notErrorMessage}'`,
|
||||
);
|
||||
).to.be.rejectedWith(`{"x":1,"y":2}: expected error message '${errorMessage}' to equal '${notErrorMessage}'`);
|
||||
});
|
||||
|
||||
it('passes when both fail with compatible RevertErrors', async () => {
|
||||
@ -58,34 +57,32 @@ describe('testWithReferenceFuncAsync', () => {
|
||||
it('fails when both fail with incompatible RevertErrors', async () => {
|
||||
const error1 = new StringRevertError('whoopsie');
|
||||
const error2 = new StringRevertError('not whoopsie');
|
||||
return expect(testWithReferenceFuncAsync(alwaysFailFunc(error1), alwaysFailFunc(error2), [1, 1]))
|
||||
.to.be.rejectedWith(
|
||||
`{"x":1,"y":1}: expected error StringRevertError({ message: 'not whoopsie' }) to equal StringRevertError({ message: 'whoopsie' })`,
|
||||
);
|
||||
return expect(
|
||||
testWithReferenceFuncAsync(alwaysFailFunc(error1), alwaysFailFunc(error2), [1, 1]),
|
||||
).to.be.rejectedWith(
|
||||
`{"x":1,"y":1}: expected error StringRevertError({ message: 'not whoopsie' }) to equal StringRevertError({ message: 'whoopsie' })`,
|
||||
);
|
||||
});
|
||||
|
||||
it('fails when reference function fails with a RevertError but test function fails with a regular Error', async () => {
|
||||
const error1 = new StringRevertError('whoopsie');
|
||||
const error2 = new Error('whoopsie');
|
||||
return expect(testWithReferenceFuncAsync(alwaysFailFunc(error1), alwaysFailFunc(error2), [1, 1]))
|
||||
.to.be.rejectedWith(
|
||||
`{"x":1,"y":1}: expected a RevertError but received an Error`,
|
||||
);
|
||||
return expect(
|
||||
testWithReferenceFuncAsync(alwaysFailFunc(error1), alwaysFailFunc(error2), [1, 1]),
|
||||
).to.be.rejectedWith(`{"x":1,"y":1}: expected a RevertError but received an Error`);
|
||||
});
|
||||
|
||||
it('fails when referenceFunc succeeds and testFunc fails', async () => {
|
||||
const error = new Error('whoopsie');
|
||||
return expect(testWithReferenceFuncAsync(alwaysValueFunc(0), alwaysFailFunc(error), [1, 2]))
|
||||
.to.be.rejectedWith(
|
||||
`{"x":1,"y":2}: expected success but instead failed`,
|
||||
);
|
||||
return expect(testWithReferenceFuncAsync(alwaysValueFunc(0), alwaysFailFunc(error), [1, 2])).to.be.rejectedWith(
|
||||
`{"x":1,"y":2}: expected success but instead failed`,
|
||||
);
|
||||
});
|
||||
|
||||
it('fails when referenceFunc fails and testFunc succeeds', async () => {
|
||||
const error = new Error('whoopsie');
|
||||
return expect(testWithReferenceFuncAsync(alwaysFailFunc(error), divAsync, [1, 2]))
|
||||
.to.be.rejectedWith(
|
||||
'{"x":1,"y":2}: expected failure but instead succeeded',
|
||||
);
|
||||
return expect(testWithReferenceFuncAsync(alwaysFailFunc(error), divAsync, [1, 2])).to.be.rejectedWith(
|
||||
'{"x":1,"y":2}: expected failure but instead succeeded',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -2,6 +2,9 @@ import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
|
||||
|
||||
const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
|
||||
|
||||
/**
|
||||
* Add two `uint256` values. Reverts on overflow.
|
||||
*/
|
||||
export function safeAdd(a: BigNumber, b: BigNumber): BigNumber {
|
||||
const r = a.plus(b);
|
||||
if (r.isGreaterThan(MAX_UINT256)) {
|
||||
@ -14,6 +17,9 @@ export function safeAdd(a: BigNumber, b: BigNumber): BigNumber {
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subract two `uint256` values. Reverts on overflow.
|
||||
*/
|
||||
export function safeSub(a: BigNumber, b: BigNumber): BigNumber {
|
||||
const r = a.minus(b);
|
||||
if (r.isLessThan(0)) {
|
||||
@ -26,6 +32,9 @@ export function safeSub(a: BigNumber, b: BigNumber): BigNumber {
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two `uint256` values. Reverts on overflow.
|
||||
*/
|
||||
export function safeMul(a: BigNumber, b: BigNumber): BigNumber {
|
||||
const r = a.times(b);
|
||||
if (r.isGreaterThan(MAX_UINT256)) {
|
||||
@ -38,6 +47,9 @@ export function safeMul(a: BigNumber, b: BigNumber): BigNumber {
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two `uint256` values. Reverts on division by zero.
|
||||
*/
|
||||
export function safeDiv(a: BigNumber, b: BigNumber): BigNumber {
|
||||
if (b.isEqualTo(0)) {
|
||||
throw new SafeMathRevertErrors.SafeMathError(
|
||||
|
Loading…
x
Reference in New Issue
Block a user