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