This repository has been archived by the owner on Jul 9, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 465
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/3.0/exchange/fill-order-unit-tests' into 3.0
- Loading branch information
Showing
64 changed files
with
3,130 additions
and
1,169 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
export * from './artifacts'; | ||
export * from './wrappers'; | ||
|
||
import * as ReferenceFunctionsToExport from './reference_functions'; | ||
export import ReferenceFunctions = ReferenceFunctionsToExport; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { ReferenceFunctions } from '@0x/contracts-utils'; | ||
import { LibMathRevertErrors } from '@0x/order-utils'; | ||
import { FillResults } from '@0x/types'; | ||
import { BigNumber } from '@0x/utils'; | ||
|
||
const { safeAdd, safeSub, safeMul, safeDiv } = ReferenceFunctions; | ||
|
||
/** | ||
* Checks if rounding error >= 0.1% when rounding down. | ||
*/ | ||
export function isRoundingErrorFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): boolean { | ||
if (denominator.eq(0)) { | ||
throw new LibMathRevertErrors.DivisionByZeroError(); | ||
} | ||
if (numerator.eq(0) || target.eq(0)) { | ||
return false; | ||
} | ||
const remainder = numerator.times(target).mod(denominator); | ||
// Need to do this separately because solidity evaluates RHS of the comparison expression first. | ||
const rhs = safeMul(numerator, target); | ||
const lhs = safeMul(new BigNumber(1000), remainder); | ||
return lhs.gte(rhs); | ||
} | ||
|
||
/** | ||
* Checks if rounding error >= 0.1% when rounding up. | ||
*/ | ||
export function isRoundingErrorCeil(numerator: BigNumber, denominator: BigNumber, target: BigNumber): boolean { | ||
if (denominator.eq(0)) { | ||
throw new LibMathRevertErrors.DivisionByZeroError(); | ||
} | ||
if (numerator.eq(0) || target.eq(0)) { | ||
return false; | ||
} | ||
let remainder = numerator.times(target).mod(denominator); | ||
remainder = safeSub(denominator, remainder).mod(denominator); | ||
// Need to do this separately because solidity evaluates RHS of the comparison expression first. | ||
const rhs = safeMul(numerator, target); | ||
const lhs = safeMul(new BigNumber(1000), remainder); | ||
return lhs.gte(rhs); | ||
} | ||
|
||
/** | ||
* Calculates partial value given a numerator and denominator rounded down. | ||
* Reverts if rounding error is >= 0.1% | ||
*/ | ||
export function safeGetPartialAmountFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber { | ||
if (isRoundingErrorFloor(numerator, denominator, target)) { | ||
throw new LibMathRevertErrors.RoundingError(numerator, denominator, target); | ||
} | ||
return safeDiv(safeMul(numerator, target), denominator); | ||
} | ||
|
||
/** | ||
* Calculates partial value given a numerator and denominator rounded down. | ||
* Reverts if rounding error is >= 0.1% | ||
*/ | ||
export function safeGetPartialAmountCeil(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber { | ||
if (isRoundingErrorCeil(numerator, denominator, target)) { | ||
throw new LibMathRevertErrors.RoundingError(numerator, denominator, target); | ||
} | ||
return safeDiv(safeAdd(safeMul(numerator, target), safeSub(denominator, new BigNumber(1))), denominator); | ||
} | ||
|
||
/** | ||
* Calculates partial value given a numerator and denominator rounded down. | ||
*/ | ||
export function getPartialAmountFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber { | ||
return safeDiv(safeMul(numerator, target), denominator); | ||
} | ||
|
||
/** | ||
* Calculates partial value given a numerator and denominator rounded down. | ||
*/ | ||
export function getPartialAmountCeil(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber { | ||
return safeDiv(safeAdd(safeMul(numerator, target), safeSub(denominator, new BigNumber(1))), denominator); | ||
} | ||
|
||
/** | ||
* Adds properties of two `FillResults`. | ||
*/ | ||
export function addFillResults(a: FillResults, b: FillResults): FillResults { | ||
return { | ||
makerAssetFilledAmount: safeAdd(a.makerAssetFilledAmount, b.makerAssetFilledAmount), | ||
takerAssetFilledAmount: safeAdd(a.takerAssetFilledAmount, b.takerAssetFilledAmount), | ||
makerFeePaid: safeAdd(a.makerFeePaid, b.makerFeePaid), | ||
takerFeePaid: safeAdd(a.takerFeePaid, b.takerFeePaid), | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { blockchainTests, constants, describe, expect } from '@0x/contracts-test-utils'; | ||
import { BigNumber, SafeMathRevertErrors } from '@0x/utils'; | ||
import * as _ from 'lodash'; | ||
|
||
import { artifacts, ReferenceFunctions, TestLibsContract } from '../src'; | ||
|
||
blockchainTests('LibFillResults', env => { | ||
const CHAIN_ID = 1337; | ||
const { ONE_ETHER, MAX_UINT256 } = constants; | ||
let libsContract: TestLibsContract; | ||
|
||
before(async () => { | ||
libsContract = await TestLibsContract.deployFrom0xArtifactAsync( | ||
artifacts.TestLibs, | ||
env.provider, | ||
env.txDefaults, | ||
new BigNumber(CHAIN_ID), | ||
); | ||
}); | ||
|
||
describe('addFillResults', () => { | ||
describe('explicit tests', () => { | ||
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('matches the output of the reference function', async () => { | ||
const [a, b] = DEFAULT_FILL_RESULTS; | ||
const expected = ReferenceFunctions.addFillResults(a, b); | ||
const actual = await libsContract.addFillResults.callAsync(a, b); | ||
expect(actual).to.deep.equal(expected); | ||
}); | ||
|
||
it('reverts if computing `makerAssetFilledAmount` overflows', async () => { | ||
const [a, b] = _.cloneDeep(DEFAULT_FILL_RESULTS); | ||
b.makerAssetFilledAmount = MAX_UINT256; | ||
const expectedError = new SafeMathRevertErrors.SafeMathError( | ||
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow, | ||
a.makerAssetFilledAmount, | ||
b.makerAssetFilledAmount, | ||
); | ||
return expect(libsContract.addFillResults.callAsync(a, b)).to.revertWith(expectedError); | ||
}); | ||
|
||
it('reverts if computing `takerAssetFilledAmount` overflows', async () => { | ||
const [a, b] = _.cloneDeep(DEFAULT_FILL_RESULTS); | ||
b.takerAssetFilledAmount = MAX_UINT256; | ||
const expectedError = new SafeMathRevertErrors.SafeMathError( | ||
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow, | ||
a.takerAssetFilledAmount, | ||
b.takerAssetFilledAmount, | ||
); | ||
return expect(libsContract.addFillResults.callAsync(a, b)).to.revertWith(expectedError); | ||
}); | ||
|
||
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); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.