diff options
Diffstat (limited to 'packages/contracts/src')
-rw-r--r-- | packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol index fa09da6ac..146bb9943 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol @@ -46,7 +46,7 @@ contract LibMath is return partialAmount; } - /// @dev Checks if rounding error > 0.1%. + /// @dev Checks if rounding error >= 0.1%. /// @param numerator Numerator. /// @param denominator Denominator. /// @param target Value to multiply with numerator/denominator. @@ -60,16 +60,23 @@ contract LibMath is pure returns (bool isError) { + // 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. We want the relative rounding error to be strictly less + // than 0.1%. + // Let's call `numerator * target % denominator` the remainder. + // The ideal value is `numerator * target / denominator`. + // The absolute error is `remainder / denominator`. + // 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); - if (remainder == 0) { - return false; // No rounding error. - } - - uint256 errPercentageTimes1000000 = safeDiv( - safeMul(remainder, 1000000), - safeMul(numerator, target) - ); - isError = errPercentageTimes1000000 > 1000; + isError = safeMul(1000, remainder) >= safeMul(numerator, target); return isError; } } |