@0x/types: Add FillResults, MatchedFillResults, and

`BatchMatchedFillResults` types.
`@0x/contracts-utils`: Add reference functions for `SafeMath`.
`@0x/contracts-exchange-libs`: Add reference functions for `LibMath` and
`LibFillResults`.
`@0x/contracts-test-utils`: Move `*FillResults` types to `@0x/types`.
`@0x/contracts-test-utils`: Add `log_utils.ts`.
`@0x/contracts-test-utils`: Add `hexRandom()` to `hex_utils.ts`.
`@0x/contracts-test-utils`: Add the contstants: `MAX_UINT256`,
`ADDRESS_LENGTH`.
This commit is contained in:
Lawrence Forman 2019-07-31 15:56:36 -04:00
parent c54d69e5ae
commit c30d59d5d3
11 changed files with 249 additions and 47 deletions

View File

@ -1,29 +1,7 @@
[
{
"timestamp": 1563193019,
"version": "3.0.2",
"version": "3.1.0",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1563047529,
"version": "3.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.0.0",
"changes": [
{
"note": "Move `LibTransactionDecoder` to contracts/dev-utils package",
"pr": 1848
},
{
"note": "Break up `LibEIP712` into reusable components",
"pr": 1742
@ -75,6 +53,37 @@
{
"note": "Add `expirationTimeSeconds` to `ZeroExTransaction` struct",
"pr": 1823
},
{
"note": "Add reference functions for `LibMath` and `LibFillResults`",
"pr": "TODO"
}
]
},
{
"timestamp": 1563193019,
"version": "3.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1563047529,
"version": "3.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.0.0",
"changes": [
{
"note": "Move `LibTransactionDecoder` to contracts/dev-utils package",
"pr": 1848
}
],
"timestamp": 1563006338

View File

@ -1,2 +1,5 @@
export * from './artifacts';
export * from './wrappers';
import * as reference_functions from './reference_functions';
export import ReferenceFunctions = reference_functions;

View File

@ -0,0 +1,122 @@
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;
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.multipliedBy(target).mod(denominator);
return safeMul(new BigNumber(1000), remainder).gte(safeMul(numerator, target));
}
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.multipliedBy(target).mod(denominator);
remainder = safeSub(denominator, remainder).mod(denominator);
return safeMul(new BigNumber(1000), remainder).gte(safeMul(numerator, target));
}
export function safeGetPartialAmountFloor(
numerator: BigNumber,
denominator: BigNumber,
target: BigNumber,
): BigNumber {
if (denominator.eq(0)) {
throw new LibMathRevertErrors.DivisionByZeroError();
}
if (isRoundingErrorFloor(numerator, denominator, target)) {
throw new LibMathRevertErrors.RoundingError(numerator, denominator, target);
}
return safeDiv(
safeMul(numerator, target),
denominator,
);
}
export function safeGetPartialAmountCeil(
numerator: BigNumber,
denominator: BigNumber,
target: BigNumber,
): BigNumber {
if (denominator.eq(0)) {
throw new LibMathRevertErrors.DivisionByZeroError();
}
if (isRoundingErrorCeil(numerator, denominator, target)) {
throw new LibMathRevertErrors.RoundingError(numerator, denominator, target);
}
return safeDiv(
safeAdd(
safeMul(numerator, target),
safeSub(denominator, new BigNumber(1)),
),
denominator,
);
}
export function getPartialAmountFloor(
numerator: BigNumber,
denominator: BigNumber,
target: BigNumber,
): BigNumber {
if (denominator.eq(0)) {
throw new LibMathRevertErrors.DivisionByZeroError();
}
return safeDiv(
safeMul(numerator, target),
denominator,
);
}
export function getPartialAmountCeil(
numerator: BigNumber,
denominator: BigNumber,
target: BigNumber,
): BigNumber {
if (denominator.eq(0)) {
throw new LibMathRevertErrors.DivisionByZeroError();
}
return safeDiv(
safeAdd(
safeMul(numerator, target),
safeSub(denominator, new BigNumber(1)),
),
denominator,
);
}
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),
};
}

View File

@ -37,6 +37,22 @@
{
"note": "Introduce Mocha blockchain extensions",
"pr": 2007
},
{
"note": "Move `*FillResults` types to `@0x/types`",
"pr": "TODO"
},
{
"note": "Add `log_utils.ts`",
"pr": "TODO"
},
{
"note": "Add `haxRandom()` to `hex_utils.ts`",
"pr": "TODO"
},
{
"note": "Add the constants: `MAX_UINT256`, `ADDRESS_LENGTH`",
"pr": "TODO"
}
]
},

View File

@ -29,7 +29,6 @@ export { TransactionFactory } from './transaction_factory';
export { testWithReferenceFuncAsync } from './test_with_reference';
export { hexConcat, hexRandom } from './hex_utils';
export {
BatchMatchedFillResults,
BatchMatchOrder,
ContractName,
ERC20BalancesByOwner,
@ -37,10 +36,8 @@ export {
ERC1155HoldingsByOwner,
ERC1155NonFungibleHoldingsByOwner,
ERC721TokenIdsByOwner,
FillResults,
MarketBuyOrders,
MarketSellOrders,
MatchedFillResults,
OrderInfo,
OrderStatus,
Token,

View File

@ -143,24 +143,3 @@ export interface MatchOrder {
leftSignature: string;
rightSignature: string;
}
export interface FillResults {
makerAssetFilledAmount: BigNumber;
takerAssetFilledAmount: BigNumber;
makerFeePaid: BigNumber;
takerFeePaid: BigNumber;
}
export interface MatchedFillResults {
left: FillResults;
right: FillResults;
profitInLeftMakerAsset: BigNumber;
profitInRightMakerAsset: BigNumber;
}
export interface BatchMatchedFillResults {
left: FillResults[];
right: FillResults[];
profitInLeftMakerAsset: BigNumber;
profitInRightMakerAsset: BigNumber;
}

View File

@ -33,6 +33,10 @@
{
"note": "Updated Ownable to revert when the owner attempts to transfer ownership to the zero address",
"pr": 2019
},
{
"note": "Add reference functions for `SafeMath` functions.",
"pr": "2031"
}
]
},

View File

@ -1,2 +1,5 @@
export * from './artifacts';
export * from './wrappers';
import * as reference_functions from './reference_functions';
export import ReferenceFunctions = reference_functions;

View File

@ -0,0 +1,44 @@
import { AnyRevertError, BigNumber, SafeMathRevertErrors } from '@0x/utils';
const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
export function safeAdd(a: BigNumber, b: BigNumber): BigNumber {
const r = a.plus(b);
if (r.isGreaterThan(MAX_UINT256)) {
throw new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
a,
b,
);
}
return r;
}
export function safeSub(a: BigNumber, b: BigNumber): BigNumber {
const r = a.minus(b);
if (r.isLessThan(0)) {
throw new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256SubtractionUnderflow,
a,
b,
);
}
return r;
}
export function safeMul(a: BigNumber, b: BigNumber): BigNumber {
const r = a.times(b);
if (r.isGreaterThan(MAX_UINT256)) {
// Solidity implementation does not throw a reason.
throw new AnyRevertError();
}
return r;
}
export function safeDiv(a: BigNumber, b: BigNumber): BigNumber {
if (b.isEqualTo(0)) {
// Solidity implementation does not throw a reason.
throw new AnyRevertError();
}
return a.dividedToIntegerBy(b);
}

View File

@ -5,6 +5,10 @@
{
"note": "Add `OrderStatus` type",
"pr": 1761
},
{
"note": "Add `FillResults`, `MatchedFillResults`, `BatchMatchedFillResults` types",
"pr": "TODO"
}
]
},

View File

@ -810,3 +810,24 @@ export enum OrderTransferResults {
MakerFeeAssetDataFailed,
TransfersSuccessful,
}
export interface FillResults {
makerAssetFilledAmount: BigNumber;
takerAssetFilledAmount: BigNumber;
makerFeePaid: BigNumber;
takerFeePaid: BigNumber;
}
export interface MatchedFillResults {
left: FillResults;
right: FillResults;
profitInLeftMakerAsset: BigNumber;
profitInRightMakerAsset: BigNumber;
}
export interface BatchMatchedFillResults {
left: FillResults[];
right: FillResults[];
profitInLeftMakerAsset: BigNumber;
profitInRightMakerAsset: BigNumber;
}