# Precision truncation vs validation mismatch

Value checked or stored at different precision than computed; truncation slips past a guard

_Area: DeFi accounting and math bugs. Seen in 33 disclosed reports; one confirmed bounty: $290,497; latest 2026-08-20. Updated 2026-10-23._

## How it works
A number is computed, then truncated by integer division, but the guard that protects it compares or reconstructs a value at a different precision. The broken assumption: the value you validate is the value you keep. When division happens before scaling, a fee is subtracted before a range check, or two small factors are multiplied before a large one, the floored result no longer satisfies the invariant the code relies on. The invariant that must hold: the value validated equals the value stored and used, at the same precision.

## Where it shows up
- Division before scaling in invariant/health checks, e.g. `mulDiv(amount, 1e18, liquidity)` then multiply by scale [E2](https://bugbountylibrary.com/r/c4%3A2023-01-numoen%3AH-01.md)
- Fee/tax as `amount * bps / denom` where small `amount` truncates to zero [E4](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-the-graph-rounding-error-bugfix-review.md)
- Coarse denominator: smallest representable rate is `1/denom`, so any charge below that rounds to zero [E5](https://bugbountylibrary.com/r/sherlock%3A2024-08-velar-artha%3AH-1.md)
- Storing a post-fee balance then reconstructing the pre-fee amount for a min/max range check [E1](https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-04.md)
- Two small fixed-point factors multiplied before a large scaled amount, so a change in one factor leaves the floored product unchanged [E3](https://bugbountylibrary.com/r/cantina%3Aeigenlayer_mar2025%3A3.1.2.md)
- Rounding a fraction that can equal a sentinel value (0 meaning "max") [E8](https://bugbountylibrary.com/r/c4%3A2023-04-rubicon%3AH-16.md)
- Format/width selection that downcasts a mantissa, corrupting downstream arithmetic [E7](https://bugbountylibrary.com/r/c4%3A2025-04-forte-float128-solidity-library%3AH-05.md)
- A burn/mint with a dust-cleanup branch whose effective amount differs from the requested amount [E6](https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AH-14.md)

## How to review
Find every division and truncation, then trace whether the truncated value is later compared, reconstructed, or used as a guard. Check multiply-before-divide ordering; that fee add-back matches fee subtraction; that sentinel values cannot be produced by valid rounding (fuzz just above the minimum) [E8](https://bugbountylibrary.com/r/c4%3A2023-04-rubicon%3AH-16.md); that format selection considers mantissa digit count, not just exponent [E7](https://bugbountylibrary.com/r/c4%3A2025-04-forte-float128-solidity-library%3AH-05.md); and that callers reconcile to a function's actual return value, not the requested amount [E6](https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AH-14.md). Fuzz boundary inputs: dust amounts, leverage just above minimum, factors near floor collisions.

## Variants seen
- Division-before-scale hides reserve changes from invariant [E2](https://bugbountylibrary.com/r/c4%3A2023-01-numoen%3AH-01.md)
- Tax truncates to zero for small inputs, split into dust batches [E4](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-the-graph-rounding-error-bugfix-review.md)
- Post-fee reconstruction falls below minContribution, locking funds [E1](https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-04.md)
- Floor collision between two small factors lets a slash be dodged [E3](https://bugbountylibrary.com/r/cantina%3Aeigenlayer_mar2025%3A3.1.2.md)
- Rounded leverage hits 0 sentinel meaning 100% borrow [E8](https://bugbountylibrary.com/r/c4%3A2023-04-rubicon%3AH-16.md)
- Mantissa downcast between M/L thresholds corrupts arithmetic [E7](https://bugbountylibrary.com/r/c4%3A2025-04-forte-float128-solidity-library%3AH-05.md)
- Dust-cleanup burn exceeds amount callers account for [E6](https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AH-14.md)
- Coarse denominator and intermediate division undercharge fees [E5](https://bugbountylibrary.com/r/sherlock%3A2024-08-velar-artha%3AH-1.md)

## Impact and severity
Loss of user funds (locked voting power, liquidation risk), undercharged fees shortchanging LPs, and invariant bypass enabling value extraction [E1](https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-04.md)[E2](https://bugbountylibrary.com/r/c4%3A2023-01-numoen%3AH-01.md)[E3](https://bugbountylibrary.com/r/cantina%3Aeigenlayer_mar2025%3A3.1.2.md)[E4](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-the-graph-rounding-error-bugfix-review.md)[E5](https://bugbountylibrary.com/r/sherlock%3A2024-08-velar-artha%3AH-1.md)[E8](https://bugbountylibrary.com/r/c4%3A2023-04-rubicon%3AH-16.md). Severity rises when truncation is reachable in dust-sized batches on cheap chains, or when it silently passes a guard meant to protect solvency.

## Why fixes fail
Fixes that adjust one division miss the ordering issue; multiply/divide order and fee add-back must both be corrected, and boundary fuzzing is needed to confirm the validated value equals the stored value.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2023-04-party%3AH-04.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-01-numoen%3AH-01.md
- E3: https://bugbountylibrary.com/r/cantina%3Aeigenlayer_mar2025%3A3.1.2.md
- E4: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-the-graph-rounding-error-bugfix-review.md
- E5: https://bugbountylibrary.com/r/sherlock%3A2024-08-velar-artha%3AH-1.md
- E6: https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AH-14.md
- E7: https://bugbountylibrary.com/r/c4%3A2025-04-forte-float128-solidity-library%3AH-05.md
- E8: https://bugbountylibrary.com/r/c4%3A2023-04-rubicon%3AH-16.md
