chore: Prune old contracts (#304)
Prune exchange-libs deploy migrations at specific address remove exchange-libs, moving LibMath into Utils Remove staking order-utils multisig and remaining asset-proxy
This commit is contained in:
228
contracts/utils/contracts/src/LibMath.sol
Normal file
228
contracts/utils/contracts/src/LibMath.sol
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
import "./LibSafeMath.sol";
|
||||
import "./LibRichErrors.sol";
|
||||
import "./LibMathRichErrors.sol";
|
||||
|
||||
|
||||
library LibMath {
|
||||
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||
/// Reverts if rounding error is >= 0.1%
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target rounded down.
|
||||
function safeGetPartialAmountFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
if (isRoundingErrorFloor(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
)) {
|
||||
LibRichErrors.rrevert(LibMathRichErrors.RoundingError(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
));
|
||||
}
|
||||
|
||||
partialAmount = numerator.safeMul(target).safeDiv(denominator);
|
||||
return partialAmount;
|
||||
}
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||
/// Reverts if rounding error is >= 0.1%
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target rounded up.
|
||||
function safeGetPartialAmountCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
if (isRoundingErrorCeil(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
)) {
|
||||
LibRichErrors.rrevert(LibMathRichErrors.RoundingError(
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
));
|
||||
}
|
||||
|
||||
// safeDiv computes `floor(a / b)`. We use the identity (a, b integer):
|
||||
// ceil(a / b) = floor((a + b - 1) / b)
|
||||
// To implement `ceil(a / b)` using safeDiv.
|
||||
partialAmount = numerator.safeMul(target)
|
||||
.safeAdd(denominator.safeSub(1))
|
||||
.safeDiv(denominator);
|
||||
|
||||
return partialAmount;
|
||||
}
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target rounded down.
|
||||
function getPartialAmountFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
partialAmount = numerator.safeMul(target).safeDiv(denominator);
|
||||
return partialAmount;
|
||||
}
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator rounded down.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target rounded up.
|
||||
function getPartialAmountCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
// safeDiv computes `floor(a / b)`. We use the identity (a, b integer):
|
||||
// ceil(a / b) = floor((a + b - 1) / b)
|
||||
// To implement `ceil(a / b)` using safeDiv.
|
||||
partialAmount = numerator.safeMul(target)
|
||||
.safeAdd(denominator.safeSub(1))
|
||||
.safeDiv(denominator);
|
||||
|
||||
return partialAmount;
|
||||
}
|
||||
|
||||
/// @dev Checks if rounding error >= 0.1% when rounding down.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to multiply with numerator/denominator.
|
||||
/// @return Rounding error is present.
|
||||
function isRoundingErrorFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
if (denominator == 0) {
|
||||
LibRichErrors.rrevert(LibMathRichErrors.DivisionByZeroError());
|
||||
}
|
||||
|
||||
// The absolute rounding error is the difference between the rounded
|
||||
// value and the ideal value. The relative rounding error is the
|
||||
// absolute rounding error divided by the absolute value of the
|
||||
// ideal value. This is undefined when the ideal value is zero.
|
||||
//
|
||||
// The ideal value is `numerator * target / denominator`.
|
||||
// Let's call `numerator * target % denominator` the remainder.
|
||||
// The absolute error is `remainder / denominator`.
|
||||
//
|
||||
// When the ideal value is zero, we require the absolute error to
|
||||
// be zero. Fortunately, this is always the case. The ideal value is
|
||||
// zero iff `numerator == 0` and/or `target == 0`. In this case the
|
||||
// remainder and absolute error are also zero.
|
||||
if (target == 0 || numerator == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, we want the relative rounding error to be strictly
|
||||
// less than 0.1%.
|
||||
// The relative error is `remainder / (numerator * target)`.
|
||||
// We want the relative error less than 1 / 1000:
|
||||
// remainder / (numerator * denominator) < 1 / 1000
|
||||
// or equivalently:
|
||||
// 1000 * remainder < numerator * target
|
||||
// so we have a rounding error iff:
|
||||
// 1000 * remainder >= numerator * target
|
||||
uint256 remainder = mulmod(
|
||||
target,
|
||||
numerator,
|
||||
denominator
|
||||
);
|
||||
isError = remainder.safeMul(1000) >= numerator.safeMul(target);
|
||||
return isError;
|
||||
}
|
||||
|
||||
/// @dev Checks if rounding error >= 0.1% when rounding up.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to multiply with numerator/denominator.
|
||||
/// @return Rounding error is present.
|
||||
function isRoundingErrorCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
if (denominator == 0) {
|
||||
LibRichErrors.rrevert(LibMathRichErrors.DivisionByZeroError());
|
||||
}
|
||||
|
||||
// See the comments in `isRoundingError`.
|
||||
if (target == 0 || numerator == 0) {
|
||||
// When either is zero, the ideal value and rounded value are zero
|
||||
// and there is no rounding error. (Although the relative error
|
||||
// is undefined.)
|
||||
return false;
|
||||
}
|
||||
// Compute remainder as before
|
||||
uint256 remainder = mulmod(
|
||||
target,
|
||||
numerator,
|
||||
denominator
|
||||
);
|
||||
remainder = denominator.safeSub(remainder) % denominator;
|
||||
isError = remainder.safeMul(1000) >= numerator.safeMul(target);
|
||||
return isError;
|
||||
}
|
||||
}
|
||||
39
contracts/utils/contracts/src/LibMathRichErrors.sol
Normal file
39
contracts/utils/contracts/src/LibMathRichErrors.sol
Normal file
@@ -0,0 +1,39 @@
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
library LibMathRichErrors {
|
||||
|
||||
// bytes4(keccak256("DivisionByZeroError()"))
|
||||
bytes internal constant DIVISION_BY_ZERO_ERROR =
|
||||
hex"a791837c";
|
||||
|
||||
// bytes4(keccak256("RoundingError(uint256,uint256,uint256)"))
|
||||
bytes4 internal constant ROUNDING_ERROR_SELECTOR =
|
||||
0x339f3de2;
|
||||
|
||||
// solhint-disable func-name-mixedcase
|
||||
function DivisionByZeroError()
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return DIVISION_BY_ZERO_ERROR;
|
||||
}
|
||||
|
||||
function RoundingError(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
internal
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
return abi.encodeWithSelector(
|
||||
ROUNDING_ERROR_SELECTOR,
|
||||
numerator,
|
||||
denominator,
|
||||
target
|
||||
);
|
||||
}
|
||||
}
|
||||
130
contracts/utils/contracts/test/TestLibMath.sol
Normal file
130
contracts/utils/contracts/test/TestLibMath.sol
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../src/LibMath.sol";
|
||||
|
||||
|
||||
contract TestLibMath {
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator.
|
||||
/// Reverts if rounding error is >= 0.1%
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target.
|
||||
function safeGetPartialAmountFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
return LibMath.safeGetPartialAmountFloor(numerator, denominator, target);
|
||||
}
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator.
|
||||
/// Reverts if rounding error is >= 0.1%
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target.
|
||||
function safeGetPartialAmountCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
return LibMath.safeGetPartialAmountCeil(numerator, denominator, target);
|
||||
}
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target.
|
||||
function getPartialAmountFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
return LibMath.getPartialAmountFloor(numerator, denominator, target);
|
||||
}
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to calculate partial of.
|
||||
/// @return Partial value of target.
|
||||
function getPartialAmountCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (uint256 partialAmount)
|
||||
{
|
||||
return LibMath.getPartialAmountCeil(numerator, denominator, target);
|
||||
}
|
||||
|
||||
/// @dev Checks if rounding error >= 0.1%.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to multiply with numerator/denominator.
|
||||
/// @return Rounding error is present.
|
||||
function isRoundingErrorFloor(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
return LibMath.isRoundingErrorFloor(numerator, denominator, target);
|
||||
}
|
||||
|
||||
/// @dev Checks if rounding error >= 0.1%.
|
||||
/// @param numerator Numerator.
|
||||
/// @param denominator Denominator.
|
||||
/// @param target Value to multiply with numerator/denominator.
|
||||
/// @return Rounding error is present.
|
||||
function isRoundingErrorCeil(
|
||||
uint256 numerator,
|
||||
uint256 denominator,
|
||||
uint256 target
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bool isError)
|
||||
{
|
||||
return LibMath.isRoundingErrorCeil(numerator, denominator, target);
|
||||
}
|
||||
}
|
||||
@@ -36,9 +36,9 @@
|
||||
"compile:truffle": "truffle compile"
|
||||
},
|
||||
"config": {
|
||||
"publicInterfaceContracts": "Authorizable,IAuthorizable,IOwnable,LibAddress,LibAddressArray,LibAddressArrayRichErrors,LibAuthorizableRichErrors,LibBytes,LibBytesRichErrors,LibEIP1271,LibEIP712,LibFractions,LibOwnableRichErrors,LibReentrancyGuardRichErrors,LibRichErrors,LibSafeMath,LibSafeMathRichErrors,Ownable,ReentrancyGuard,Refundable",
|
||||
"publicInterfaceContracts": "Authorizable,IAuthorizable,IOwnable,LibAddress,LibAddressArray,LibAddressArrayRichErrors,LibAuthorizableRichErrors,LibBytes,LibBytesRichErrors,LibEIP1271,LibEIP712,LibFractions,LibOwnableRichErrors,LibReentrancyGuardRichErrors,LibRichErrors,LibMath,LibMathRichErrors,LibSafeMath,LibSafeMathRichErrors,Ownable,ReentrancyGuard,Refundable",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||
"abis": "./test/generated-artifacts/@(Authorizable|AuthorizableV06|D18|DeploymentConstants|IAuthorizable|IAuthorizableV06|IOwnable|IOwnableV06|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibAuthorizableRichErrorsV06|LibBytes|LibBytesRichErrors|LibBytesRichErrorsV06|LibBytesV06|LibEIP1271|LibEIP712|LibFractions|LibMathRichErrorsV06|LibMathV06|LibOwnableRichErrors|LibOwnableRichErrorsV06|LibReentrancyGuardRichErrors|LibReentrancyGuardRichErrorsV06|LibRichErrors|LibRichErrorsV06|LibSafeMath|LibSafeMathRichErrors|LibSafeMathRichErrorsV06|LibSafeMathV06|Ownable|OwnableV06|ReentrancyGuard|ReentrancyGuardV06|Refundable|TestAuthorizable|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibRichErrors|TestLibSafeMath|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestRefundable|TestRefundableReceiver).json"
|
||||
"abis": "./test/generated-artifacts/@(Authorizable|AuthorizableV06|D18|DeploymentConstants|IAuthorizable|IAuthorizableV06|IOwnable|IOwnableV06|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibAuthorizableRichErrorsV06|LibBytes|LibBytesRichErrors|LibBytesRichErrorsV06|LibBytesV06|LibEIP1271|LibEIP712|LibFractions|LibMath|LibMathRichErrors|LibMathRichErrorsV06|LibMathV06|LibOwnableRichErrors|LibOwnableRichErrorsV06|LibReentrancyGuardRichErrors|LibReentrancyGuardRichErrorsV06|LibRichErrors|LibRichErrorsV06|LibSafeMath|LibSafeMathRichErrors|LibSafeMathRichErrorsV06|LibSafeMathV06|Ownable|OwnableV06|ReentrancyGuard|ReentrancyGuardV06|Refundable|TestAuthorizable|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibMath|TestLibRichErrors|TestLibSafeMath|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestRefundable|TestRefundableReceiver).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -17,6 +17,8 @@ import * as LibBytesRichErrors from '../generated-artifacts/LibBytesRichErrors.j
|
||||
import * as LibEIP1271 from '../generated-artifacts/LibEIP1271.json';
|
||||
import * as LibEIP712 from '../generated-artifacts/LibEIP712.json';
|
||||
import * as LibFractions from '../generated-artifacts/LibFractions.json';
|
||||
import * as LibMath from '../generated-artifacts/LibMath.json';
|
||||
import * as LibMathRichErrors from '../generated-artifacts/LibMathRichErrors.json';
|
||||
import * as LibOwnableRichErrors from '../generated-artifacts/LibOwnableRichErrors.json';
|
||||
import * as LibReentrancyGuardRichErrors from '../generated-artifacts/LibReentrancyGuardRichErrors.json';
|
||||
import * as LibRichErrors from '../generated-artifacts/LibRichErrors.json';
|
||||
@@ -41,6 +43,8 @@ export const artifacts = {
|
||||
LibOwnableRichErrors: LibOwnableRichErrors as ContractArtifact,
|
||||
LibReentrancyGuardRichErrors: LibReentrancyGuardRichErrors as ContractArtifact,
|
||||
LibRichErrors: LibRichErrors as ContractArtifact,
|
||||
LibMath: LibMath as ContractArtifact,
|
||||
LibMathRichErrors: LibMathRichErrors as ContractArtifact,
|
||||
LibSafeMath: LibSafeMath as ContractArtifact,
|
||||
LibSafeMathRichErrors: LibSafeMathRichErrors as ContractArtifact,
|
||||
Ownable: Ownable as ContractArtifact,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
|
||||
import { BigNumber, LibMathRevertErrors, SafeMathRevertErrors } from '@0x/utils';
|
||||
|
||||
const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
|
||||
|
||||
@@ -52,3 +52,77 @@ export function safeDiv(a: BigNumber, b: BigNumber): BigNumber {
|
||||
}
|
||||
return a.dividedToIntegerBy(b);
|
||||
}
|
||||
|
||||
// LibMath
|
||||
|
||||
/**
|
||||
* 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(remainder, new BigNumber(1000));
|
||||
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(remainder, new BigNumber(1000));
|
||||
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 {
|
||||
const sub = safeSub(denominator, new BigNumber(1)); // This is computed first to simulate Solidity's order of operations
|
||||
return safeDiv(safeAdd(safeMul(numerator, target), sub), denominator);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ export * from '../generated-wrappers/lib_bytes_rich_errors';
|
||||
export * from '../generated-wrappers/lib_e_i_p1271';
|
||||
export * from '../generated-wrappers/lib_e_i_p712';
|
||||
export * from '../generated-wrappers/lib_fractions';
|
||||
export * from '../generated-wrappers/lib_math';
|
||||
export * from '../generated-wrappers/lib_math_rich_errors';
|
||||
export * from '../generated-wrappers/lib_ownable_rich_errors';
|
||||
export * from '../generated-wrappers/lib_reentrancy_guard_rich_errors';
|
||||
export * from '../generated-wrappers/lib_rich_errors';
|
||||
|
||||
@@ -25,6 +25,8 @@ import * as LibBytesV06 from '../test/generated-artifacts/LibBytesV06.json';
|
||||
import * as LibEIP1271 from '../test/generated-artifacts/LibEIP1271.json';
|
||||
import * as LibEIP712 from '../test/generated-artifacts/LibEIP712.json';
|
||||
import * as LibFractions from '../test/generated-artifacts/LibFractions.json';
|
||||
import * as LibMath from '../test/generated-artifacts/LibMath.json';
|
||||
import * as LibMathRichErrors from '../test/generated-artifacts/LibMathRichErrors.json';
|
||||
import * as LibMathRichErrorsV06 from '../test/generated-artifacts/LibMathRichErrorsV06.json';
|
||||
import * as LibMathV06 from '../test/generated-artifacts/LibMathV06.json';
|
||||
import * as LibOwnableRichErrors from '../test/generated-artifacts/LibOwnableRichErrors.json';
|
||||
@@ -47,6 +49,7 @@ import * as TestLibAddress from '../test/generated-artifacts/TestLibAddress.json
|
||||
import * as TestLibAddressArray from '../test/generated-artifacts/TestLibAddressArray.json';
|
||||
import * as TestLibBytes from '../test/generated-artifacts/TestLibBytes.json';
|
||||
import * as TestLibEIP712 from '../test/generated-artifacts/TestLibEIP712.json';
|
||||
import * as TestLibMath from '../test/generated-artifacts/TestLibMath.json';
|
||||
import * as TestLibRichErrors from '../test/generated-artifacts/TestLibRichErrors.json';
|
||||
import * as TestLibSafeMath from '../test/generated-artifacts/TestLibSafeMath.json';
|
||||
import * as TestLogDecoding from '../test/generated-artifacts/TestLogDecoding.json';
|
||||
@@ -68,6 +71,8 @@ export const artifacts = {
|
||||
LibEIP1271: LibEIP1271 as ContractArtifact,
|
||||
LibEIP712: LibEIP712 as ContractArtifact,
|
||||
LibFractions: LibFractions as ContractArtifact,
|
||||
LibMath: LibMath as ContractArtifact,
|
||||
LibMathRichErrors: LibMathRichErrors as ContractArtifact,
|
||||
LibOwnableRichErrors: LibOwnableRichErrors as ContractArtifact,
|
||||
LibReentrancyGuardRichErrors: LibReentrancyGuardRichErrors as ContractArtifact,
|
||||
LibRichErrors: LibRichErrors as ContractArtifact,
|
||||
@@ -98,6 +103,7 @@ export const artifacts = {
|
||||
TestLibAddressArray: TestLibAddressArray as ContractArtifact,
|
||||
TestLibBytes: TestLibBytes as ContractArtifact,
|
||||
TestLibEIP712: TestLibEIP712 as ContractArtifact,
|
||||
TestLibMath: TestLibMath as ContractArtifact,
|
||||
TestLibRichErrors: TestLibRichErrors as ContractArtifact,
|
||||
TestLibSafeMath: TestLibSafeMath as ContractArtifact,
|
||||
TestLogDecoding: TestLogDecoding as ContractArtifact,
|
||||
|
||||
429
contracts/utils/test/lib_math.ts
Normal file
429
contracts/utils/test/lib_math.ts
Normal file
@@ -0,0 +1,429 @@
|
||||
import {
|
||||
blockchainTests,
|
||||
constants,
|
||||
describe,
|
||||
expect,
|
||||
testCombinatoriallyWithReferenceFunc,
|
||||
uint256Values,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { BigNumber, LibMathRevertErrors, SafeMathRevertErrors } from '@0x/utils';
|
||||
|
||||
import {
|
||||
getPartialAmountCeil,
|
||||
getPartialAmountFloor,
|
||||
isRoundingErrorCeil,
|
||||
isRoundingErrorFloor,
|
||||
safeGetPartialAmountCeil,
|
||||
safeGetPartialAmountFloor,
|
||||
} from '../src/reference_functions';
|
||||
|
||||
import { artifacts } from './artifacts';
|
||||
import { TestLibMathContract } from './wrappers';
|
||||
|
||||
blockchainTests('LibMath', env => {
|
||||
const { ONE_ETHER, MAX_UINT256, MAX_UINT256_ROOT, ZERO_AMOUNT } = constants;
|
||||
let libsContract: TestLibMathContract;
|
||||
|
||||
before(async () => {
|
||||
libsContract = await TestLibMathContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestLibMath,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
{},
|
||||
);
|
||||
});
|
||||
|
||||
// Wrap a reference function with identical arguments in a promise.
|
||||
function createAsyncReferenceFunction<T>(ref: (...args: any[]) => T): (...args: any[]) => Promise<T> {
|
||||
return async (...args: any[]): Promise<T> => {
|
||||
return ref(...args);
|
||||
};
|
||||
}
|
||||
|
||||
function createContractTestFunction<T>(name: string): (...args: any[]) => Promise<T> {
|
||||
return async (...args: any[]): Promise<T> => {
|
||||
return (libsContract as any)[name](...args).callAsync;
|
||||
};
|
||||
}
|
||||
|
||||
describe('getPartialAmountFloor', () => {
|
||||
describe.optional('combinatorial tests', () => {
|
||||
testCombinatoriallyWithReferenceFunc(
|
||||
'getPartialAmountFloor',
|
||||
createAsyncReferenceFunction(getPartialAmountFloor),
|
||||
createContractTestFunction('getPartialAmountFloor'),
|
||||
[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 = getPartialAmountFloor(numerator, denominator, target);
|
||||
const actual = await libsContract.getPartialAmountFloor(numerator, denominator, target).callAsync();
|
||||
expect(actual).to.bignumber.eq(expected);
|
||||
});
|
||||
|
||||
it('rounds down when computing the partial amount', async () => {
|
||||
const numerator = ONE_ETHER.times(0.6);
|
||||
const denominator = ONE_ETHER.times(1.8);
|
||||
const target = ONE_ETHER;
|
||||
const expected = ONE_ETHER.dividedToIntegerBy(3);
|
||||
const actual = await libsContract.getPartialAmountFloor(numerator, denominator, target).callAsync();
|
||||
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.Uint256BinOpError(
|
||||
SafeMathRevertErrors.BinOpErrorCodes.DivisionByZero,
|
||||
numerator.times(target),
|
||||
denominator,
|
||||
);
|
||||
return expect(
|
||||
libsContract.getPartialAmountFloor(numerator, denominator, target).callAsync(),
|
||||
).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.Uint256BinOpError(
|
||||
SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(
|
||||
libsContract.getPartialAmountFloor(numerator, denominator, target).callAsync(),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPartialAmountCeil', () => {
|
||||
describe.optional('combinatorial tests', () => {
|
||||
testCombinatoriallyWithReferenceFunc(
|
||||
'getPartialAmountCeil',
|
||||
createAsyncReferenceFunction(getPartialAmountCeil),
|
||||
createContractTestFunction('getPartialAmountCeil'),
|
||||
[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 = getPartialAmountCeil(numerator, denominator, target);
|
||||
const actual = await libsContract.getPartialAmountCeil(numerator, denominator, target).callAsync();
|
||||
expect(actual).to.bignumber.eq(expected);
|
||||
});
|
||||
|
||||
it('rounds up when computing the partial amount', async () => {
|
||||
const numerator = ONE_ETHER.times(0.6);
|
||||
const denominator = ONE_ETHER.times(1.8);
|
||||
const target = ONE_ETHER;
|
||||
const expected = ONE_ETHER.dividedToIntegerBy(3).plus(1);
|
||||
const actual = await libsContract.getPartialAmountCeil(numerator, denominator, target).callAsync();
|
||||
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.Uint256BinOpError(
|
||||
SafeMathRevertErrors.BinOpErrorCodes.SubtractionUnderflow,
|
||||
denominator,
|
||||
new BigNumber(1),
|
||||
);
|
||||
return expect(
|
||||
libsContract.getPartialAmountCeil(numerator, denominator, target).callAsync(),
|
||||
).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.Uint256BinOpError(
|
||||
SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(
|
||||
libsContract.getPartialAmountCeil(numerator, denominator, target).callAsync(),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('safeGetPartialAmountFloor', () => {
|
||||
describe.optional('combinatorial tests', () => {
|
||||
testCombinatoriallyWithReferenceFunc(
|
||||
'safeGetPartialAmountFloor',
|
||||
createAsyncReferenceFunction(safeGetPartialAmountFloor),
|
||||
createContractTestFunction('safeGetPartialAmountFloor'),
|
||||
[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 = safeGetPartialAmountFloor(numerator, denominator, target);
|
||||
const actual = await libsContract.safeGetPartialAmountFloor(numerator, denominator, target).callAsync();
|
||||
expect(actual).to.bignumber.eq(expected);
|
||||
});
|
||||
|
||||
it('rounds down when computing the partial amount', async () => {
|
||||
const numerator = ONE_ETHER.times(0.6);
|
||||
const denominator = ONE_ETHER.times(1.8);
|
||||
const target = ONE_ETHER;
|
||||
const expected = ONE_ETHER.dividedToIntegerBy(3);
|
||||
const actual = await libsContract.safeGetPartialAmountFloor(numerator, denominator, target).callAsync();
|
||||
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(numerator, denominator, target).callAsync(),
|
||||
).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(numerator, denominator, target).callAsync(),
|
||||
).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.Uint256BinOpError(
|
||||
SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(
|
||||
libsContract.safeGetPartialAmountFloor(numerator, denominator, target).callAsync(),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('safeGetPartialAmountCeil', () => {
|
||||
describe.optional('combinatorial tests', () => {
|
||||
testCombinatoriallyWithReferenceFunc(
|
||||
'safeGetPartialAmountCeil',
|
||||
createAsyncReferenceFunction(safeGetPartialAmountCeil),
|
||||
createContractTestFunction('safeGetPartialAmountCeil'),
|
||||
[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 = safeGetPartialAmountCeil(numerator, denominator, target);
|
||||
const actual = await libsContract.safeGetPartialAmountCeil(numerator, denominator, target).callAsync();
|
||||
expect(actual).to.bignumber.eq(expected);
|
||||
});
|
||||
|
||||
it('rounds up when computing the partial amount', async () => {
|
||||
const numerator = ONE_ETHER.times(0.6);
|
||||
const denominator = ONE_ETHER.times(1.8);
|
||||
const target = ONE_ETHER;
|
||||
const expected = ONE_ETHER.dividedToIntegerBy(3).plus(1);
|
||||
const actual = await libsContract.safeGetPartialAmountCeil(numerator, denominator, target).callAsync();
|
||||
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(numerator, denominator, target).callAsync(),
|
||||
).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(numerator, denominator, target).callAsync(),
|
||||
).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.Uint256BinOpError(
|
||||
SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(
|
||||
libsContract.safeGetPartialAmountCeil(numerator, denominator, target).callAsync(),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isRoundingErrorFloor', () => {
|
||||
describe.optional('combinatorial tests', () => {
|
||||
testCombinatoriallyWithReferenceFunc(
|
||||
'isRoundingErrorFloor',
|
||||
createAsyncReferenceFunction(isRoundingErrorFloor),
|
||||
createContractTestFunction('isRoundingErrorFloor'),
|
||||
[uint256Values, uint256Values, uint256Values],
|
||||
);
|
||||
});
|
||||
|
||||
describe('explicit tests', () => {
|
||||
it('returns true when `numerator * target / denominator` produces an error >= 0.1%', async () => {
|
||||
const numerator = new BigNumber(100);
|
||||
const denominator = new BigNumber(102);
|
||||
const target = new BigNumber(52);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorFloor(numerator, denominator, target).callAsync();
|
||||
expect(actual).to.eq(true);
|
||||
});
|
||||
|
||||
it('returns false when `numerator * target / denominator` produces an error < 0.1%', async () => {
|
||||
const numerator = new BigNumber(100);
|
||||
const denominator = new BigNumber(101);
|
||||
const target = new BigNumber(92);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorFloor(numerator, denominator, target).callAsync();
|
||||
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);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const expected = isRoundingErrorFloor(numerator, denominator, target);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorFloor(numerator, denominator, target).callAsync();
|
||||
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(numerator, denominator, target).callAsync(),
|
||||
).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.Uint256BinOpError(
|
||||
SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(
|
||||
libsContract.isRoundingErrorFloor(numerator, denominator, target).callAsync(),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isRoundingErrorCeil', () => {
|
||||
describe.optional('combinatorial tests', () => {
|
||||
testCombinatoriallyWithReferenceFunc(
|
||||
'isRoundingErrorCeil',
|
||||
createAsyncReferenceFunction(isRoundingErrorCeil),
|
||||
createContractTestFunction('isRoundingErrorCeil'),
|
||||
[uint256Values, uint256Values, uint256Values],
|
||||
);
|
||||
});
|
||||
|
||||
describe('explicit tests', () => {
|
||||
it('returns true when `numerator * target / (denominator - 1)` produces an error >= 0.1%', async () => {
|
||||
const numerator = new BigNumber(100);
|
||||
const denominator = new BigNumber(101);
|
||||
const target = new BigNumber(92);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorCeil(numerator, denominator, target).callAsync();
|
||||
expect(actual).to.eq(true);
|
||||
});
|
||||
|
||||
it('returns false when `numerator * target / (denominator - 1)` produces an error < 0.1%', async () => {
|
||||
const numerator = new BigNumber(100);
|
||||
const denominator = new BigNumber(102);
|
||||
const target = new BigNumber(52);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorCeil(numerator, denominator, target).callAsync();
|
||||
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);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const expected = isRoundingErrorCeil(numerator, denominator, target);
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const actual = await libsContract.isRoundingErrorCeil(numerator, denominator, target).callAsync();
|
||||
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(numerator, denominator, target).callAsync(),
|
||||
).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.Uint256BinOpError(
|
||||
SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
|
||||
numerator,
|
||||
target,
|
||||
);
|
||||
return expect(
|
||||
libsContract.isRoundingErrorCeil(numerator, denominator, target).callAsync(),
|
||||
).to.revertWith(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -23,6 +23,8 @@ export * from '../test/generated-wrappers/lib_bytes_v06';
|
||||
export * from '../test/generated-wrappers/lib_e_i_p1271';
|
||||
export * from '../test/generated-wrappers/lib_e_i_p712';
|
||||
export * from '../test/generated-wrappers/lib_fractions';
|
||||
export * from '../test/generated-wrappers/lib_math';
|
||||
export * from '../test/generated-wrappers/lib_math_rich_errors';
|
||||
export * from '../test/generated-wrappers/lib_math_rich_errors_v06';
|
||||
export * from '../test/generated-wrappers/lib_math_v06';
|
||||
export * from '../test/generated-wrappers/lib_ownable_rich_errors';
|
||||
@@ -45,6 +47,7 @@ export * from '../test/generated-wrappers/test_lib_address';
|
||||
export * from '../test/generated-wrappers/test_lib_address_array';
|
||||
export * from '../test/generated-wrappers/test_lib_bytes';
|
||||
export * from '../test/generated-wrappers/test_lib_e_i_p712';
|
||||
export * from '../test/generated-wrappers/test_lib_math';
|
||||
export * from '../test/generated-wrappers/test_lib_rich_errors';
|
||||
export * from '../test/generated-wrappers/test_lib_safe_math';
|
||||
export * from '../test/generated-wrappers/test_log_decoding';
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
"generated-artifacts/LibEIP1271.json",
|
||||
"generated-artifacts/LibEIP712.json",
|
||||
"generated-artifacts/LibFractions.json",
|
||||
"generated-artifacts/LibMath.json",
|
||||
"generated-artifacts/LibMathRichErrors.json",
|
||||
"generated-artifacts/LibOwnableRichErrors.json",
|
||||
"generated-artifacts/LibReentrancyGuardRichErrors.json",
|
||||
"generated-artifacts/LibRichErrors.json",
|
||||
@@ -43,6 +45,8 @@
|
||||
"test/generated-artifacts/LibEIP1271.json",
|
||||
"test/generated-artifacts/LibEIP712.json",
|
||||
"test/generated-artifacts/LibFractions.json",
|
||||
"test/generated-artifacts/LibMath.json",
|
||||
"test/generated-artifacts/LibMathRichErrors.json",
|
||||
"test/generated-artifacts/LibMathRichErrorsV06.json",
|
||||
"test/generated-artifacts/LibMathV06.json",
|
||||
"test/generated-artifacts/LibOwnableRichErrors.json",
|
||||
@@ -65,6 +69,7 @@
|
||||
"test/generated-artifacts/TestLibAddressArray.json",
|
||||
"test/generated-artifacts/TestLibBytes.json",
|
||||
"test/generated-artifacts/TestLibEIP712.json",
|
||||
"test/generated-artifacts/TestLibMath.json",
|
||||
"test/generated-artifacts/TestLibRichErrors.json",
|
||||
"test/generated-artifacts/TestLibSafeMath.json",
|
||||
"test/generated-artifacts/TestLogDecoding.json",
|
||||
|
||||
Reference in New Issue
Block a user