fix: Overflow guard missing for slots 1-7 in both Optimizer.sol and OptimizerV3Push3.sol (#997)

Add <= 1e18 upper-bound check for all 8 input slots in the validation
loops of both Optimizer.calculateParams() and OptimizerV3Push3Lib.calculateParams().

Previously only slot 0 (percentageStaked) had an overflow guard —
slots 1-7 (averageTaxRate and future indicators) could silently accept
values > 1e18, violating the documented [0, 1e18] invariant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
johba 2026-03-22 12:11:03 +00:00
parent b8ee408b73
commit c59bb81a40
2 changed files with 7 additions and 6 deletions

View file

@ -361,11 +361,13 @@ contract Optimizer is Initializable, UUPSUpgradeable, IOptimizer {
virtual
returns (uint256 capitalInefficiency, uint256 anchorShare, uint24 anchorWidth, uint256 discoveryDepth)
{
// Guard against non-zero shift and negative mantissa.
// Guard against non-zero shift, negative mantissa, and overflow.
// All 8 slots must be in [0, 1e18] the uniform dyadic range.
// shift is reserved for future use; uint256() cast silently wraps negatives.
for (uint256 k; k < 8; k++) {
require(inputs[k].shift == 0, "shift not yet supported");
require(inputs[k].mantissa >= 0, "negative mantissa");
require(inputs[k].mantissa <= 1e18, "mantissa overflow");
}
// Extract slots 0 and 1 (shift=0 enforced above mantissa IS the value)
uint256 percentageStaked = uint256(inputs[0].mantissa);

View file

@ -17,14 +17,13 @@ library OptimizerV3Push3Lib {
pure
returns (uint256 ci, uint256 anchorShare, uint24 anchorWidth, uint256 discoveryDepth)
{
// Validate mantissa for percentageStaked
require(inputs[0].mantissa <= 1e18, "mantissa overflow");
// Validate that shift is 0 (future-only field, not yet supported)
// and that no mantissa is negative (uint256 cast silently wraps negatives).
// Validate that shift is 0 (future-only field, not yet supported),
// that no mantissa is negative (uint256 cast silently wraps negatives),
// and that all slots are within the [0, 1e18] dyadic range.
for (uint256 k = 0; k < 8; k++) {
require(inputs[k].shift == 0, "shift not yet supported");
require(inputs[k].mantissa >= 0, "negative mantissa");
require(inputs[k].mantissa <= 1e18, "mantissa overflow");
}
uint256 percentagestaked = uint256(uint256(inputs[0].mantissa));