Skip to content

audit/M03: toFixedDecimalLossy panics on positive-exponent overflow instead of returning lossless=false #192

@thedavidmeister

Description

@thedavidmeister

Audit reference

Protofire, March 2026, finding M03 — toFixedDecimalLossy Reverts on Positive-Exponent Overflow. Severity: Medium. Status at audit (19a65ffa): New.

What

toFixedDecimalLossy(Float, uint8 decimals) in src/lib/LibDecimalFloat.sol is documented as a lossy conversion returning (uint256 value, bool lossless). The implementation, when finalExponent > 0, scales via unsignedCoefficient * scale in checked arithmetic; large products trigger Panic(0x11) (arithmetic overflow) instead of returning lossless = false.

Impact

The ...Lossy suffix is a contract: callers may rely on the function NOT reverting and instead branching on the bool. A revert breaks that contract and can brick caller workflows that assumed safe fallback. Severity is medium because reachability requires a Float magnitude > uint256.max — large but constructible (e.g. 1e80).

Recommendation

Wrap the positive-exponent scaling in unchecked and pre-check with if (unsignedCoefficient > type(uint256).max / scale) return (0, false);. Alternatively revert with a typed ExponentOverflow error so callers at least see a meaningful selector instead of Panic(0x11). Returning (0, false) matches the ...Lossy API contract better.

Verification

Unit test (int224.max, 50) (or any input where coefficient * 10^exp > uint256.max) → assert returns (0, false), not a revert.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions