From 42bb1a030f3a03a2490e771a1a04e8642683af00 Mon Sep 17 00:00:00 2001 From: MathisGD Date: Mon, 4 Sep 2023 17:51:51 +0200 Subject: [PATCH] fix: revert condition wExp underflow --- src/irm/libraries/MathLib.sol | 8 ++++---- test/irm/MathLibTest.sol | 14 +++++++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/irm/libraries/MathLib.sol b/src/irm/libraries/MathLib.sol index 15a50a2e..6b6ff8b8 100644 --- a/src/irm/libraries/MathLib.sol +++ b/src/irm/libraries/MathLib.sol @@ -20,14 +20,14 @@ library MathLib { unchecked { // Revert if x > ln(2^256-1) ~ 177. require(x <= 177.44567822334599921 ether, ErrorsLib.WEXP_OVERFLOW); - // Revert if x > min / 1e18. - require(x >= type(int256).min + 1 ether, ErrorsLib.WEXP_UNDERFLOW); + // Revert if x < min + (ln(2)/2). + require(x >= type(int256).min + LN2_INT / 2, ErrorsLib.WEXP_UNDERFLOW); // Decompose x as x = q * ln(2) + r with q an integer and -ln(2)/2 < r <= ln(2)/2. // q = x / ln(2) rounded half toward zero. - int256 offset = (x < 0) ? - (LN2_INT / 2) : (LN2_INT / 2); + int256 half = (x < 0) ? -(LN2_INT / 2) : (LN2_INT / 2); // Safe unchecked because x is bounded. - int256 q = (x + offset) / LN2_INT; + int256 q = (x + half) / LN2_INT; // Safe unchecked because |q * LN2_INT| <= x. int256 r = x - q * LN2_INT; diff --git a/test/irm/MathLibTest.sol b/test/irm/MathLibTest.sol index b4a29787..8e5d385c 100644 --- a/test/irm/MathLibTest.sol +++ b/test/irm/MathLibTest.sol @@ -10,17 +10,25 @@ contract MathLibTest is Test { using MathLib for uint128; using MathLib for uint256; + int256 private constant LN2_INT = 0.693147180559945309 ether; + function testWExp(int256 x) public { - x = bound(x, - 27 ether, 94 ether); + x = bound(x, -27 ether, 94 ether); assertApproxEqRel(MathLib.wExp(x), uint256(wadExp(x)), 0.01 ether); } function testWExpSmall(int256 x) public { - x = bound(x, type(int256).min + 1 ether, -178 ether); + x = bound(x, type(int256).min + LN2_INT / 2, -178 ether); + assertEq(MathLib.wExp(x), 0); + } + + function testWExpTooSmall(int256 x) public { + x = bound(x, type(int256).min, type(int256).min + LN2_INT / 2 - 1); + vm.expectRevert(bytes(ErrorsLib.WEXP_UNDERFLOW)); assertEq(MathLib.wExp(x), 0); } - function testWExpRevertTooLarge(int256 x) public { + function testWExpTooLarge(int256 x) public { vm.assume(x >= 178 ether); vm.expectRevert(bytes(ErrorsLib.WEXP_OVERFLOW)); MathLib.wExp(x);