@0x/contracts-utils
: Roll back additions to LibFractions
.
`@0x/contracts-dev-utils`: Add `D18` library for working with base-10, 18-digit decimals. `@0x/contracts-dev-utils`: Use `D18` library instead of `LibFractions` in `LibDydxBalance`.
This commit is contained in:
parent
c2d06a4a23
commit
b0387245f0
@ -50,6 +50,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Add `DydxBridge` order validation",
|
"note": "Add `DydxBridge` order validation",
|
||||||
"pr": 2466
|
"pr": 2466
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add `D18` library for working with base-10, 18-precision decimals",
|
||||||
|
"pr": 2466
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"timestamp": 1581204851
|
"timestamp": 1581204851
|
||||||
|
239
contracts/dev-utils/contracts/src/D18.sol
Normal file
239
contracts/dev-utils/contracts/src/D18.sol
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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.16;
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev A library for working with 18 digit, base 10 decimals.
|
||||||
|
library D18 {
|
||||||
|
|
||||||
|
/// @dev Decimal places for dydx value quantities.
|
||||||
|
uint256 private constant PRECISION = 18;
|
||||||
|
/// @dev 1.0 in base-18 decimal.
|
||||||
|
int256 private constant DECIMAL_ONE = int256(10 ** PRECISION);
|
||||||
|
/// @dev Minimum signed integer value.
|
||||||
|
int256 private constant MIN_INT256_VALUE = int256(0x8000000000000000000000000000000000000000000000000000000000000000);
|
||||||
|
|
||||||
|
/// @dev Return `1.0`
|
||||||
|
function one()
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
r = DECIMAL_ONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Add two decimals.
|
||||||
|
function add(int256 a, int256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
r = _add(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Add two decimals.
|
||||||
|
function add(uint256 a, int256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = _add(int256(a), b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Add two decimals.
|
||||||
|
function add(uint256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = _add(int256(a), int256(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Subract two decimals.
|
||||||
|
function sub(int256 a, int256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
r = _add(a, -b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Subract two decimals.
|
||||||
|
function sub(uint256 a, int256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = _add(int256(a), -b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Subract two decimals.
|
||||||
|
function sub(uint256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = _add(int256(a), -int256(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Multiply two decimals.
|
||||||
|
function mul(int256 a, int256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
r = _div(_mul(a, b), DECIMAL_ONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Multiply two decimals.
|
||||||
|
function mul(uint256 a, int256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = _div(_mul(int256(a), b), DECIMAL_ONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Multiply two decimals.
|
||||||
|
function mul(int256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = _div(_mul(a, int256(b)), DECIMAL_ONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Multiply two decimals.
|
||||||
|
function mul(uint256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = _div(_mul(int256(a), int256(b)), DECIMAL_ONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Divide two decimals.
|
||||||
|
function div(int256 a, int256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(a != MIN_INT256_VALUE || b != -1, "D18/DECIMAL_MUL_OVERFLOW");
|
||||||
|
r = _div(_mul(a, DECIMAL_ONE), b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Divide two decimals.
|
||||||
|
function div(uint256 a, int256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = _div(_mul(int256(a), DECIMAL_ONE), b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Divide two decimals.
|
||||||
|
function div(int256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = _div(_mul(a, DECIMAL_ONE), int256(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Divide two decimals.
|
||||||
|
function div(uint256 a, uint256 b)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(uint256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
require(uint256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = _div(_mul(int256(a), DECIMAL_ONE), int256(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Safely convert an unsigned integer into a signed integer.
|
||||||
|
function toSigned(uint256 a)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(uint256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||||
|
r = int256(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Clip a signed value to be positive.
|
||||||
|
function clip(int256 a)
|
||||||
|
internal
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
r = a < 0 ? 0 : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Safely multiply two signed integers.
|
||||||
|
function _mul(int256 a, int256 b)
|
||||||
|
private
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
if (a == 0 || b == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
r = a * b;
|
||||||
|
require(r / a == b && r / b == a, "D18/DECIMAL_MUL_OVERFLOW");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Safely divide two signed integers.
|
||||||
|
function _div(int256 a, int256 b)
|
||||||
|
private
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
require(b != 0, "D18/DECIMAL_DIVISION_BY_ZERO");
|
||||||
|
require(a != MIN_INT256_VALUE || b != -1, "D18/DECIMAL_MUL_OVERFLOW");
|
||||||
|
r = a / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Safely add two signed integers.
|
||||||
|
function _add(int256 a, int256 b)
|
||||||
|
private
|
||||||
|
pure
|
||||||
|
returns (int256 r)
|
||||||
|
{
|
||||||
|
r = a + b;
|
||||||
|
require(
|
||||||
|
!((a < 0 && b < 0 && r > a) || (a > 0 && b > 0 && r < a)),
|
||||||
|
"D18/DECIMAL_MUL_OVERFLOW"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "DevUtils,LibAssetData,LibDydxBalance,LibOrderTransferSimulation,LibTransactionDecoder",
|
"publicInterfaceContracts": "DevUtils,LibAssetData,LibDydxBalance,LibOrderTransferSimulation,LibTransactionDecoder",
|
||||||
"abis": "./test/generated-artifacts/@(Addresses|AssetBalance|DevUtils|EthBalanceChecker|ExternalFunctions|LibAssetData|LibDydxBalance|LibOrderTransferSimulation|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils|TestDydx|TestLibDydxBalance).json",
|
"abis": "./test/generated-artifacts/@(Addresses|AssetBalance|D18|DevUtils|EthBalanceChecker|ExternalFunctions|LibAssetData|LibDydxBalance|LibOrderTransferSimulation|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils|TestDydx|TestLibDydxBalance).json",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -7,6 +7,7 @@ import { ContractArtifact } from 'ethereum-types';
|
|||||||
|
|
||||||
import * as Addresses from '../test/generated-artifacts/Addresses.json';
|
import * as Addresses from '../test/generated-artifacts/Addresses.json';
|
||||||
import * as AssetBalance from '../test/generated-artifacts/AssetBalance.json';
|
import * as AssetBalance from '../test/generated-artifacts/AssetBalance.json';
|
||||||
|
import * as D18 from '../test/generated-artifacts/D18.json';
|
||||||
import * as DevUtils from '../test/generated-artifacts/DevUtils.json';
|
import * as DevUtils from '../test/generated-artifacts/DevUtils.json';
|
||||||
import * as EthBalanceChecker from '../test/generated-artifacts/EthBalanceChecker.json';
|
import * as EthBalanceChecker from '../test/generated-artifacts/EthBalanceChecker.json';
|
||||||
import * as ExternalFunctions from '../test/generated-artifacts/ExternalFunctions.json';
|
import * as ExternalFunctions from '../test/generated-artifacts/ExternalFunctions.json';
|
||||||
@ -21,6 +22,7 @@ import * as TestLibDydxBalance from '../test/generated-artifacts/TestLibDydxBala
|
|||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
Addresses: Addresses as ContractArtifact,
|
Addresses: Addresses as ContractArtifact,
|
||||||
AssetBalance: AssetBalance as ContractArtifact,
|
AssetBalance: AssetBalance as ContractArtifact,
|
||||||
|
D18: D18 as ContractArtifact,
|
||||||
DevUtils: DevUtils as ContractArtifact,
|
DevUtils: DevUtils as ContractArtifact,
|
||||||
EthBalanceChecker: EthBalanceChecker as ContractArtifact,
|
EthBalanceChecker: EthBalanceChecker as ContractArtifact,
|
||||||
ExternalFunctions: ExternalFunctions as ContractArtifact,
|
ExternalFunctions: ExternalFunctions as ContractArtifact,
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
export * from '../test/generated-wrappers/addresses';
|
export * from '../test/generated-wrappers/addresses';
|
||||||
export * from '../test/generated-wrappers/asset_balance';
|
export * from '../test/generated-wrappers/asset_balance';
|
||||||
|
export * from '../test/generated-wrappers/d18';
|
||||||
export * from '../test/generated-wrappers/dev_utils';
|
export * from '../test/generated-wrappers/dev_utils';
|
||||||
export * from '../test/generated-wrappers/eth_balance_checker';
|
export * from '../test/generated-wrappers/eth_balance_checker';
|
||||||
export * from '../test/generated-wrappers/external_functions';
|
export * from '../test/generated-wrappers/external_functions';
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"generated-artifacts/LibTransactionDecoder.json",
|
"generated-artifacts/LibTransactionDecoder.json",
|
||||||
"test/generated-artifacts/Addresses.json",
|
"test/generated-artifacts/Addresses.json",
|
||||||
"test/generated-artifacts/AssetBalance.json",
|
"test/generated-artifacts/AssetBalance.json",
|
||||||
|
"test/generated-artifacts/D18.json",
|
||||||
"test/generated-artifacts/DevUtils.json",
|
"test/generated-artifacts/DevUtils.json",
|
||||||
"test/generated-artifacts/EthBalanceChecker.json",
|
"test/generated-artifacts/EthBalanceChecker.json",
|
||||||
"test/generated-artifacts/ExternalFunctions.json",
|
"test/generated-artifacts/ExternalFunctions.json",
|
||||||
|
@ -56,10 +56,6 @@
|
|||||||
{
|
{
|
||||||
"note": "Export `EvmBytecodeOutputLinkReferences` type.",
|
"note": "Export `EvmBytecodeOutputLinkReferences` type.",
|
||||||
"pr": 2462
|
"pr": 2462
|
||||||
},
|
|
||||||
{
|
|
||||||
"note": "Add more functions to `LibFractions`.",
|
|
||||||
"pr": 2466
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"timestamp": 1580811564
|
"timestamp": 1580811564
|
||||||
|
@ -37,101 +37,7 @@ library LibFractions {
|
|||||||
.safeMul(d2)
|
.safeMul(d2)
|
||||||
.safeAdd(n2.safeMul(d1));
|
.safeAdd(n2.safeMul(d1));
|
||||||
denominator = d1.safeMul(d2);
|
denominator = d1.safeMul(d2);
|
||||||
return normalize(numerator, denominator);
|
return (numerator, denominator);
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Safely subracts two fractions `n1/d1 - n2/d2`
|
|
||||||
/// @param n1 numerator of `1`
|
|
||||||
/// @param d1 denominator of `1`
|
|
||||||
/// @param n2 numerator of `2`
|
|
||||||
/// @param d2 denominator of `2`
|
|
||||||
/// @return numerator Numerator of sum
|
|
||||||
/// @return denominator Denominator of sum
|
|
||||||
function sub(
|
|
||||||
uint256 n1,
|
|
||||||
uint256 d1,
|
|
||||||
uint256 n2,
|
|
||||||
uint256 d2
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (
|
|
||||||
uint256 numerator,
|
|
||||||
uint256 denominator
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (n2 == 0) {
|
|
||||||
return (numerator = n1, denominator = d1);
|
|
||||||
}
|
|
||||||
numerator = n1
|
|
||||||
.safeMul(d2)
|
|
||||||
.safeSub(n2.safeMul(d1));
|
|
||||||
denominator = d1.safeMul(d2);
|
|
||||||
return normalize(numerator, denominator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Multiply two fractions.
|
|
||||||
/// @param n1 numerator of `1`
|
|
||||||
/// @param d1 denominator of `1`
|
|
||||||
/// @param n2 numerator of `2`
|
|
||||||
/// @param d2 denominator of `2`
|
|
||||||
/// @return numerator numerator of product.
|
|
||||||
/// @return denominator numerator of product.
|
|
||||||
function mul(
|
|
||||||
uint256 n1,
|
|
||||||
uint256 d1,
|
|
||||||
uint256 n2,
|
|
||||||
uint256 d2
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (
|
|
||||||
uint256 numerator,
|
|
||||||
uint256 denominator
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return normalize(n1.safeMul(n2), d1.safeMul(d2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Compares two fractions.
|
|
||||||
/// @param n1 numerator of `1`
|
|
||||||
/// @param d1 denominator of `1`
|
|
||||||
/// @param n2 numerator of `2`
|
|
||||||
/// @param d2 denominator of `2`
|
|
||||||
/// @return compareResult
|
|
||||||
/// `-1` if `n1/d1 < n2/d2`.
|
|
||||||
/// `0` if `n1/d1 == n2/d2`.
|
|
||||||
/// `1` if `n1/d1 > n2/d2`.
|
|
||||||
function cmp(
|
|
||||||
uint256 n1,
|
|
||||||
uint256 d1,
|
|
||||||
uint256 n2,
|
|
||||||
uint256 d2
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (int8 compareResult)
|
|
||||||
{
|
|
||||||
// Handle infinities.
|
|
||||||
if (d1 == 0) {
|
|
||||||
if (d2 == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
if (d2 == 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint256 nd1 = n1.safeMul(d2);
|
|
||||||
uint256 nd2 = n2.safeMul(d1);
|
|
||||||
if (nd1 > nd2) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (nd1 < nd2) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Rescales a fraction to prevent overflows during addition if either
|
/// @dev Rescales a fraction to prevent overflows during addition if either
|
||||||
|
Loading…
x
Reference in New Issue
Block a user