Optimized gas costs in `ceilDiv` (#4553)

pull/4754/head
carter-ya 1 year ago committed by GitHub
parent 0950532d9a
commit e5fb718d40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      .changeset/angry-dodos-grow.md
  2. 10
      contracts/utils/math/Math.sol
  3. 9
      test/utils/math/Math.t.sol

@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---
`Math`: Optimized gas cost of `ceilDiv` by using `unchecked`.

@ -110,8 +110,14 @@ library Math {
return a / b; return a / b;
} }
// (a + b - 1) / b can overflow on addition, so we distribute. // The following calculation ensures accurate ceiling division without overflow.
return a == 0 ? 0 : (a - 1) / b + 1; // Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return a == 0 ? 0 : (a - 1) / b + 1;
}
} }
/** /**

@ -16,10 +16,11 @@ contract MathTest is Test {
if (result == 0) { if (result == 0) {
assertEq(a, 0); assertEq(a, 0);
} else { } else {
uint256 maxdiv = UINT256_MAX / b; uint256 expect = a / b;
bool overflow = maxdiv * b < a; if (expect * b < a) {
assertTrue(a > b * (result - 1)); expect += 1;
assertTrue(overflow ? result == maxdiv + 1 : a <= b * result); }
assertEq(result, expect);
} }
} }

Loading…
Cancel
Save