@0x/contracts-exchange-libs: Add explicit tests for LibMath and LibFillResults functions.

`@0x/contracts-exchange-libs`: Add tests for `ReferenceFunctions`.
This commit is contained in:
Lawrence Forman 2019-08-02 13:02:16 -04:00
parent a179a6892c
commit 293510c087
3 changed files with 652 additions and 43 deletions

View File

@ -1,16 +1,17 @@
import { import {
blockchainTests, blockchainTests,
constants,
describe, describe,
testCombinatoriallyWithReferenceFunc, expect,
uint256Values,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { FillResults } from '@0x/types'; import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
import { BigNumber } from '@0x/utils'; import * as _ from 'lodash';
import { artifacts, ReferenceFunctions, TestLibsContract } from '../src'; import { artifacts, ReferenceFunctions, TestLibsContract } from '../src';
blockchainTests('LibFillResults', env => { blockchainTests('LibFillResults', env => {
const CHAIN_ID = 1337; const CHAIN_ID = 1337;
const { ONE_ETHER, MAX_UINT256 } = constants;
let libsContract: TestLibsContract; let libsContract: TestLibsContract;
before(async () => { before(async () => {
@ -23,47 +24,76 @@ blockchainTests('LibFillResults', env => {
}); });
describe('addFillResults', () => { describe('addFillResults', () => {
function makeFillResults(value: BigNumber): FillResults { describe('explicit tests', () => {
// HACK(dorothy-zbornak): We reuse values across fields, const DEFAULT_FILL_RESULTS = [
// but this is fine because `addFillResults()` never does {
// any math between them. makerAssetFilledAmount: ONE_ETHER,
return { takerAssetFilledAmount: ONE_ETHER.times(2),
makerAssetFilledAmount: value, makerFeePaid: ONE_ETHER.times(0.001),
takerAssetFilledAmount: value, takerFeePaid: ONE_ETHER.times(0.002),
makerFeePaid: value, },
takerFeePaid: value, {
}; makerAssetFilledAmount: ONE_ETHER.times(0.01),
} takerAssetFilledAmount: ONE_ETHER.times(2).times(0.01),
makerFeePaid: ONE_ETHER.times(0.001).times(0.01),
takerFeePaid: ONE_ETHER.times(0.002).times(0.01),
},
];
async function referenceAddFillResultsAsync( it('matches the output of the reference function', async () => {
totalValue: BigNumber, const [ a, b ] = DEFAULT_FILL_RESULTS;
singleValue: BigNumber, const expected = ReferenceFunctions.addFillResults(a, b);
): Promise<FillResults> { const actual = await libsContract.addFillResults.callAsync(a, b);
return ReferenceFunctions.addFillResults( expect(actual).to.deep.equal(expected);
makeFillResults(totalValue), });
makeFillResults(singleValue),
);
}
async function testAddFillResultsAsync( it('reverts if computing `makerAssetFilledAmount` overflows', async () => {
totalValue: BigNumber, const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
singleValue: BigNumber, b.makerAssetFilledAmount = MAX_UINT256;
): Promise<FillResults> { const expectedError = new SafeMathRevertErrors.SafeMathError(
return libsContract.addFillResults.callAsync( SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
makeFillResults(totalValue), a.makerAssetFilledAmount,
makeFillResults(singleValue), b.makerAssetFilledAmount,
); );
} return expect(libsContract.addFillResults.callAsync(a, b))
.to.revertWith(expectedError);
});
// TODO(dorothy-zbornak): Do we really need these? it('reverts if computing `takerAssetFilledAmount` overflows', async () => {
// Just a couple edge cases would likely suffice. const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
describe.optional('combinatorial tests', () => { b.takerAssetFilledAmount = MAX_UINT256;
testCombinatoriallyWithReferenceFunc( const expectedError = new SafeMathRevertErrors.SafeMathError(
'addFillResults', SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
referenceAddFillResultsAsync, a.takerAssetFilledAmount,
testAddFillResultsAsync, b.takerAssetFilledAmount,
[uint256Values, uint256Values], );
); return expect(libsContract.addFillResults.callAsync(a, b))
.to.revertWith(expectedError);
});
it('reverts if computing `makerFeePaid` overflows', async () => {
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
b.makerFeePaid = MAX_UINT256;
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
a.makerFeePaid,
b.makerFeePaid,
);
return expect(libsContract.addFillResults.callAsync(a, b))
.to.revertWith(expectedError);
});
it('reverts if computing `takerFeePaid` overflows', async () => {
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
b.takerFeePaid = MAX_UINT256;
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
a.takerFeePaid,
b.takerFeePaid,
);
return expect(libsContract.addFillResults.callAsync(a, b))
.to.revertWith(expectedError);
});
}); });
}); });
}); });

View File

@ -1,15 +1,19 @@
import { import {
blockchainTests, blockchainTests,
constants,
describe, describe,
expect,
testCombinatoriallyWithReferenceFunc, testCombinatoriallyWithReferenceFunc,
uint256Values, uint256Values,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils'; import { LibMathRevertErrors } from '@0x/order-utils';
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
import { artifacts, ReferenceFunctions, TestLibsContract } from '../src'; import { artifacts, ReferenceFunctions, TestLibsContract } from '../src';
blockchainTests('LibMath', env => { blockchainTests('LibMath', env => {
const CHAIN_ID = 1337; const CHAIN_ID = 1337;
const { ONE_ETHER, MAX_UINT256, MAX_UINT256_ROOT, ZERO_AMOUNT } = constants;
let libsContract: TestLibsContract; let libsContract: TestLibsContract;
before(async () => { before(async () => {
@ -48,6 +52,43 @@ blockchainTests('LibMath', env => {
[uint256Values, uint256Values, uint256Values], [uint256Values, uint256Values, uint256Values],
); );
}); });
describe('explicit tests', () => {
it('matches the reference function output', async () => {
const numerator = ONE_ETHER;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = ONE_ETHER.times(0.01);
const expected = ReferenceFunctions.getPartialAmountFloor(numerator, denominator, target);
const actual = await libsContract.getPartialAmountFloor.callAsync(numerator, denominator, target);
expect(actual).to.bignumber.eq(expected);
});
it('reverts if `denominator` is zero', async () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256DivisionByZero,
numerator.times(target),
denominator,
);
return expect(libsContract.getPartialAmountFloor.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
it('reverts if `numerator * target` overflows', async () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(libsContract.getPartialAmountFloor.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
});
}); });
describe('getPartialAmountCeil', () => { describe('getPartialAmountCeil', () => {
@ -59,6 +100,44 @@ blockchainTests('LibMath', env => {
[uint256Values, uint256Values, uint256Values], [uint256Values, uint256Values, uint256Values],
); );
}); });
describe('explicit tests', () => {
it('matches the reference function output', async () => {
const numerator = ONE_ETHER;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = ONE_ETHER.times(0.01);
const expected = ReferenceFunctions.getPartialAmountCeil(numerator, denominator, target);
const actual = await libsContract.getPartialAmountCeil.callAsync(numerator, denominator, target);
expect(actual).to.bignumber.eq(expected);
});
it('reverts if `denominator` is zero', async () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
// This will actually manifest as a subtraction underflow.
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256SubtractionUnderflow,
denominator,
new BigNumber(1),
);
return expect(libsContract.getPartialAmountCeil.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
it('reverts if `numerator * target` overflows', async () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(libsContract.getPartialAmountCeil.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
});
}); });
describe('safeGetPartialAmountFloor', () => { describe('safeGetPartialAmountFloor', () => {
@ -70,6 +149,52 @@ blockchainTests('LibMath', env => {
[uint256Values, uint256Values, uint256Values], [uint256Values, uint256Values, uint256Values],
); );
}); });
describe('explicit tests', () => {
it('matches the reference function output', async () => {
const numerator = ONE_ETHER;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = ONE_ETHER.times(0.01);
const expected = ReferenceFunctions.safeGetPartialAmountFloor(numerator, denominator, target);
const actual = await libsContract.safeGetPartialAmountFloor.callAsync(numerator, denominator, target);
expect(actual).to.bignumber.eq(expected);
});
it('reverts for a rounding error', async () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(333);
const expectedError = new LibMathRevertErrors.RoundingError(
numerator,
denominator,
target,
);
return expect(libsContract.safeGetPartialAmountFloor.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
it('reverts if `denominator` is zero', async () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
return expect(libsContract.safeGetPartialAmountFloor.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
it('reverts if `numerator * target` overflows', async () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(libsContract.safeGetPartialAmountFloor.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
});
}); });
describe('safeGetPartialAmountCeil', () => { describe('safeGetPartialAmountCeil', () => {
@ -81,6 +206,52 @@ blockchainTests('LibMath', env => {
[uint256Values, uint256Values, uint256Values], [uint256Values, uint256Values, uint256Values],
); );
}); });
describe('explicit tests', () => {
it('matches the reference function output', async () => {
const numerator = ONE_ETHER;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = ONE_ETHER.times(0.01);
const expected = ReferenceFunctions.safeGetPartialAmountCeil(numerator, denominator, target);
const actual = await libsContract.safeGetPartialAmountCeil.callAsync(numerator, denominator, target);
expect(actual).to.bignumber.eq(expected);
});
it('reverts for a rounding error', async () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(333);
const expectedError = new LibMathRevertErrors.RoundingError(
numerator,
denominator,
target,
);
return expect(libsContract.safeGetPartialAmountCeil.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
it('reverts if `denominator` is zero', async () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
return expect(libsContract.safeGetPartialAmountCeil.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
it('reverts if `numerator * target` overflows', async () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(libsContract.safeGetPartialAmountCeil.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
});
}); });
describe('isRoundingErrorFloor', () => { describe('isRoundingErrorFloor', () => {
@ -92,6 +263,55 @@ blockchainTests('LibMath', env => {
[uint256Values, uint256Values, uint256Values], [uint256Values, uint256Values, uint256Values],
); );
}); });
describe('explicit tests', () => {
it('returns true for a rounding error', async () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(333);
const actual = await libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target);
expect(actual).to.eq(true);
});
it('returns false for not a rounding error', async () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(5e2);
const actual = await libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target);
expect(actual).to.eq(false);
});
it('matches the reference function output', async () => {
const numerator = ONE_ETHER;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = ONE_ETHER.times(0.01);
const expected = ReferenceFunctions.isRoundingErrorFloor(numerator, denominator, target);
const actual = await libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target);
expect(actual).to.eq(expected);
});
it('reverts if `denominator` is zero', async () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
return expect(libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
it('reverts if `numerator * target` overflows', async () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
});
}); });
describe('isRoundingErrorCeil', () => { describe('isRoundingErrorCeil', () => {
@ -103,5 +323,54 @@ blockchainTests('LibMath', env => {
[uint256Values, uint256Values, uint256Values], [uint256Values, uint256Values, uint256Values],
); );
}); });
describe('explicit tests', () => {
it('returns true for a rounding error', async () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(333);
const actual = await libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target);
expect(actual).to.eq(true);
});
it('returns false for not a rounding error', async () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(5e2);
const actual = await libsContract.isRoundingErrorFloor.callAsync(numerator, denominator, target);
expect(actual).to.eq(false);
});
it('matches the reference function output', async () => {
const numerator = ONE_ETHER;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = ONE_ETHER.times(0.01);
const expected = ReferenceFunctions.isRoundingErrorCeil(numerator, denominator, target);
const actual = await libsContract.isRoundingErrorCeil.callAsync(numerator, denominator, target);
expect(actual).to.eq(expected);
});
it('reverts if `denominator` is zero', async () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
return expect(libsContract.isRoundingErrorCeil.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
it('reverts if `numerator * target` overflows', async () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(libsContract.isRoundingErrorCeil.callAsync(numerator, denominator, target))
.to.revertWith(expectedError);
});
});
}); });
}); });

View File

@ -0,0 +1,310 @@
import {
constants,
describe,
expect,
} from '@0x/contracts-test-utils';
import { LibMathRevertErrors } from '@0x/order-utils';
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
import * as _ from 'lodash';
import {
addFillResults,
getPartialAmountCeil,
getPartialAmountFloor,
isRoundingErrorCeil,
isRoundingErrorFloor,
safeGetPartialAmountCeil,
safeGetPartialAmountFloor,
} from '../src/reference_functions';
describe('Reference Functions', () => {
const { ONE_ETHER, MAX_UINT256, MAX_UINT256_ROOT, ZERO_AMOUNT } = constants;
describe('LibFillResults', () => {
describe('addFillResults', () => {
const DEFAULT_FILL_RESULTS = [
{
makerAssetFilledAmount: ONE_ETHER,
takerAssetFilledAmount: ONE_ETHER.times(2),
makerFeePaid: ONE_ETHER.times(0.001),
takerFeePaid: ONE_ETHER.times(0.002),
},
{
makerAssetFilledAmount: ONE_ETHER.times(0.01),
takerAssetFilledAmount: ONE_ETHER.times(2).times(0.01),
makerFeePaid: ONE_ETHER.times(0.001).times(0.01),
takerFeePaid: ONE_ETHER.times(0.002).times(0.01),
},
];
it('reverts if computing `makerAssetFilledAmount` overflows', () => {
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
b.makerAssetFilledAmount = MAX_UINT256;
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
a.makerAssetFilledAmount,
b.makerAssetFilledAmount,
);
expect(() => addFillResults(a, b)).to.throw(expectedError.message);
});
it('reverts if computing `takerAssetFilledAmount` overflows', () => {
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
b.takerAssetFilledAmount = MAX_UINT256;
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
a.takerAssetFilledAmount,
b.takerAssetFilledAmount,
);
expect(() => addFillResults(a, b)).to.throw(expectedError.message);
});
it('reverts if computing `makerFeePaid` overflows', () => {
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
b.makerFeePaid = MAX_UINT256;
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
a.makerFeePaid,
b.makerFeePaid,
);
expect(() => addFillResults(a, b)).to.throw(expectedError.message);
});
it('reverts if computing `takerFeePaid` overflows', () => {
const [ a, b ] = _.cloneDeep(DEFAULT_FILL_RESULTS);
b.takerFeePaid = MAX_UINT256;
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
a.takerFeePaid,
b.takerFeePaid,
);
expect(() => addFillResults(a, b)).to.throw(expectedError.message);
});
});
});
describe('LibMath', () => {
describe('getPartialAmountFloor', () => {
describe('explicit tests', () => {
it('reverts if `denominator` is zero', () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256DivisionByZero,
numerator.times(target),
denominator,
);
return expect(() => getPartialAmountFloor(numerator, denominator, target))
.to.throw(expectedError.message);
});
it('reverts if `numerator * target` overflows', () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(() => getPartialAmountFloor(numerator, denominator, target))
.to.throw(expectedError.message);
});
});
});
describe('getPartialAmountCeil', () => {
describe('explicit tests', () => {
it('reverts if `denominator` is zero', () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
// This will actually manifest as a subtraction underflow.
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256SubtractionUnderflow,
denominator,
new BigNumber(1),
);
return expect(() => getPartialAmountCeil(numerator, denominator, target))
.to.throw(expectedError.message);
});
it('reverts if `numerator * target` overflows', () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(() => getPartialAmountCeil(numerator, denominator, target))
.to.throw(expectedError.message);
});
});
});
describe('safeGetPartialAmountFloor', () => {
describe('explicit tests', () => {
it('reverts for a rounding error', () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(333);
const expectedError = new LibMathRevertErrors.RoundingError(
numerator,
denominator,
target,
);
return expect(() => safeGetPartialAmountFloor(numerator, denominator, target))
.to.throw(expectedError.message);
});
it('reverts if `denominator` is zero', () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
return expect(() => safeGetPartialAmountFloor(numerator, denominator, target))
.to.throw(expectedError.message);
});
it('reverts if `numerator * target` overflows', () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(() => safeGetPartialAmountFloor(numerator, denominator, target))
.to.throw(expectedError.message);
});
});
});
describe('safeGetPartialAmountCeil', () => {
describe('explicit tests', () => {
it('reverts for a rounding error', () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(333);
const expectedError = new LibMathRevertErrors.RoundingError(
numerator,
denominator,
target,
);
return expect(() => safeGetPartialAmountCeil(numerator, denominator, target))
.to.throw(expectedError.message);
});
it('reverts if `denominator` is zero', () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
return expect(() => safeGetPartialAmountCeil(numerator, denominator, target))
.to.throw(expectedError.message);
});
it('reverts if `numerator * target` overflows', () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(() => safeGetPartialAmountCeil(numerator, denominator, target))
.to.throw(expectedError.message);
});
});
});
describe('isRoundingErrorFloor', () => {
describe('explicit tests', () => {
it('returns true for a rounding error', () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(333);
const actual = isRoundingErrorFloor(numerator, denominator, target);
expect(actual).to.eq(true);
});
it('returns false for not a rounding error', () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(5e2);
const actual = isRoundingErrorFloor(numerator, denominator, target);
expect(actual).to.eq(false);
});
it('reverts if `denominator` is zero', () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
return expect(() => isRoundingErrorFloor(numerator, denominator, target))
.to.throw(expectedError.message);
});
it('reverts if `numerator * target` overflows', () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(() => isRoundingErrorFloor(numerator, denominator, target))
.to.throw(expectedError.message);
});
});
});
describe('isRoundingErrorCeil', () => {
describe('explicit tests', () => {
it('returns true for a rounding error', () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(333);
const actual = isRoundingErrorFloor(numerator, denominator, target);
expect(actual).to.eq(true);
});
it('returns false for not a rounding error', () => {
const numerator = new BigNumber(1e3);
const denominator = new BigNumber(1e4);
const target = new BigNumber(5e2);
const actual = isRoundingErrorFloor(numerator, denominator, target);
expect(actual).to.eq(false);
});
it('reverts if `denominator` is zero', () => {
const numerator = ONE_ETHER;
const denominator = ZERO_AMOUNT;
const target = ONE_ETHER.times(0.01);
const expectedError = new LibMathRevertErrors.DivisionByZeroError();
return expect(() => isRoundingErrorCeil(numerator, denominator, target))
.to.throw(expectedError.message);
});
it('reverts if `numerator * target` overflows', () => {
const numerator = MAX_UINT256;
const denominator = ONE_ETHER.dividedToIntegerBy(2);
const target = MAX_UINT256_ROOT.times(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
numerator,
target,
);
return expect(() => isRoundingErrorCeil(numerator, denominator, target))
.to.throw(expectedError.message);
});
});
});
});
});