# Rounding direction mismatch in paired paths

Paired paths that convert the same value with opposite rounding, so the pair nets a shortfall

_Area: DeFi accounting and math bugs. Seen in 4 disclosed reports; latest 2026-08-20. Updated 2026-10-25._

## How it works
Two code paths convert the same quantity (shares to assets, assets to shares, amount to price) but round in opposite directions, or one path rounds while the other compares an unrounded ratio. Each path is locally reasonable. The pair is not: the value one path computes is smaller than the value the other path demands or credits. The gap is usually 1 wei or a dust unit, but it is enough to make a check fail, a claim succeed that should not, or a balance drift from reality. The broken assumption is that "the same amount" means the same number everywhere.

## Where it shows up
- A wrapper or router that recomputes a value the underlying market also computes (health, debt, price) with its own division.
- `mulDivUp` in one place and plain division in another for the same ratio.
- Ordering structures that compare cross-multiplied ratios while a separate check compares rounded quotients.
- Withdraw/deposit share math where one direction rounds up.
- Burn/mint functions with a dust-cleanup branch that changes the effective amount, called by code that trusts the requested amount.
- Missing virtual assets/shares offsets that the underlying protocol uses.

## How to review
For every value that crosses a boundary, find both producers and confirm they use the same rounding direction and the same offsets. The invariant: for any amount, the value used to size an action must be >= the value the receiving path will demand, and <= the value it will credit. Check that callers reconcile to a function's return value, not its input, when that function can round or clean dust. Check that totalAssets>0 implies totalSupply>0 after any rounding-up conversion.

## Variants seen
- Queue orders by cross-multiplied ratio; claim check uses rounded division, so a non-winning bid claims and locks a winner's funds [E1](https://bugbountylibrary.com/r/sherlock%3A2024-03-axis-finance%3AH-6.md).
- Withdraw rounds shares up, zeroing totalSupply while assets remain; deposits then revert forever [E2](https://bugbountylibrary.com/r/sherlock%3A2024-08-sentiment-v2%3AM-17.md).
- Burn promotes a partial burn to a full dust wipe; repay transfers only the requested amount, cancelling more debt than paid [E3](https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AH-14.md).
- Wrapper health rounds borrow down, underlying repay rounds up; migration flash loan falls 1 wei short and reverts [E4](https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AM-7.md).

## Impact and severity
Locked user funds [E1](https://bugbountylibrary.com/r/sherlock%3A2024-03-axis-finance%3AH-6.md), permanent denial of deposit for a pool [E2](https://bugbountylibrary.com/r/sherlock%3A2024-08-sentiment-v2%3AM-17.md), debt cancelled without payment [E3](https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AH-14.md), and blocked position migration [E4](https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AM-7.md). Severity rises when the mismatch is reachable by an unprivileged caller and the resulting state is persistent rather than a one-off revert.

## Why fixes fail
Fixing one path's rounding without auditing the paired path leaves the gap; E4 shows a wrapper diverging from an underlying it cannot change.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2024-03-axis-finance%3AH-6.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2024-08-sentiment-v2%3AM-17.md
- E3: https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AH-14.md
- E4: https://bugbountylibrary.com/r/sherlock%3A2025-06-notional-exponent%3AM-7.md
