# Precision loss in swap and PnL math

Rounding direction, price division, and tick boundaries that make amounts or liquidity path-dependent

_Area: DeFi accounting and math bugs. Seen in 2 disclosed reports; latest 2023-12-11. Updated 2026-10-23._

## How it works
Accounting math assumes a value is computed the same way regardless of how the state got there. That breaks when a formula divides by a moving quantity (price) or rounds in the wrong direction. The result is a number that depends on the path taken, not just the current state, so repeated small steps accumulate error the protocol never charges for. In concentrated liquidity, a slightly wrong square-root price maps to a wrong tick, and crossing that tick counts the same liquidity twice.

## Where it shows up
- PnL or margin formulas that divide by current price instead of using an absolute dollar delta [E1](https://bugbountylibrary.com/r/sherlock%3A2023-12-flatmoney%3AH-4.md)
- Any per-adjustment reset of a stored reference price that re-applies a nonlinear scale [E1](https://bugbountylibrary.com/r/sherlock%3A2023-12-flatmoney%3AH-4.md)
- `computeSwapStep`-style reinvestment/compounding math where `nextSqrtP` rounding direction is chosen loosely [E2](https://bugbountylibrary.com/r/dhl%3A20231122-kyberswap-exp-eth-1.md)
- Tick derivation from a sqrt price that can land exactly on a boundary tick [E2](https://bugbountylibrary.com/r/dhl%3A20231122-kyberswap-exp-eth-1.md)
- Burn/sync flows reachable through multicall or meta-transactions where reserves are recomputed from a manipulated balance [E3](https://bugbountylibrary.com/r/dhl%3A20231228-dominott.md)
- Fee, reward, or share math that rounds in the protocol's favor on one side only

## How to review
The invariant: for a given absolute price move, the computed PnL/amount must be identical whether applied in one step or many, and rounding must always favor the pool, never the caller. Check each division: is the denominator a stable unit or a moving price? Check each `sqrtP`/tick conversion: does rounding push toward or away from the boundary, and can the result equal a tick edge? For burn/sync paths, confirm reserves are derived from tracked balances, not from a caller-influenced snapshot, and that replay/nonce checks exist [E3](https://bugbountylibrary.com/r/dhl%3A20231228-dominott.md).

## Variants seen
- Relative-price PnL causing asymmetric outcomes on identical moves [E1](https://bugbountylibrary.com/r/sherlock%3A2023-12-flatmoney%3AH-4.md)
- Wrong rounding direction in reinvestment liquidity producing a bad tick and double-counted liquidity [E2](https://bugbountylibrary.com/r/dhl%3A20231122-kyberswap-exp-eth-1.md)
- Precision loss in pair sync after a multicall burn, enabling profitable arbitrage [E3](https://bugbountylibrary.com/r/dhl%3A20231228-dominott.md)

## Impact and severity
Ranges from margin loss on individual positions [E1](https://bugbountylibrary.com/r/sherlock%3A2023-12-flatmoney%3AH-4.md) to full pool drain (~$48M) [E2](https://bugbountylibrary.com/r/dhl%3A20231122-kyberswap-exp-eth-1.md) and smaller arbitrage extraction [E3](https://bugbountylibrary.com/r/dhl%3A20231228-dominott.md). Severity rises when the error is repeatable within one transaction and when flash liquidity lets an attacker amplify it; path-dependence that only bites after many adjustments is lower but still real.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2023-12-flatmoney%3AH-4.md
- E2: https://bugbountylibrary.com/r/dhl%3A20231122-kyberswap-exp-eth-1.md
- E3: https://bugbountylibrary.com/r/dhl%3A20231228-dominott.md
