Optimized gas costs in ceilDiv (#4553)
This commit is contained in:
5
.changeset/angry-dodos-grow.md
Normal file
5
.changeset/angry-dodos-grow.md
Normal file
@ -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;
|
||||
}
|
||||
|
||||
// (a + b - 1) / b can overflow on addition, so we distribute.
|
||||
return a == 0 ? 0 : (a - 1) / b + 1;
|
||||
// The following calculation ensures accurate ceiling division without overflow.
|
||||
// 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) {
|
||||
assertEq(a, 0);
|
||||
} else {
|
||||
uint256 maxdiv = UINT256_MAX / b;
|
||||
bool overflow = maxdiv * b < a;
|
||||
assertTrue(a > b * (result - 1));
|
||||
assertTrue(overflow ? result == maxdiv + 1 : a <= b * result);
|
||||
uint256 expect = a / b;
|
||||
if (expect * b < a) {
|
||||
expect += 1;
|
||||
}
|
||||
assertEq(result, expect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user