# Rounding direction favors user

Conversions and subtractions where the truncated remainder lands on the caller's side, not the protocol's

_Area: DeFi accounting and math bugs. Seen in 66 disclosed reports; latest 2026-10-06. Updated 2026-10-23._

## How it works
Integer division truncates, so every share/asset conversion and every `a - b` leaves a remainder. The protocol is safe only if that remainder always lands on the protocol's side. When a conversion rounds in the caller's favor, or a subtraction of a truncated quotient flips the direction, each call extracts a sliver. The broken assumption is that per-user rounding and aggregate rounding agree, and that inputs are whole. Dust, fractional state from another path, and repeated or split calls amplify the drift until balances no longer match reality [E2](https://bugbountylibrary.com/r/dhl%3A20261006-setprotocolethmacoapy.md)[E3](https://bugbountylibrary.com/r/dhl%3A20260809-usm.md)[E5](https://bugbountylibrary.com/r/sherlock%3A2023-12-jojo-exchange-update%3AH-2.md).

## Where it shows up
- Redeem converts underlying to shares with a round-down, so fewer shares burn than the underlying paid out [E1](https://bugbountylibrary.com/r/sherlock%3A2025-07-malda%3AM-1.md).
- Permissionless share-price recompute using `divCeil`; a donation inflates the numerator without minting supply [E2](https://bugbountylibrary.com/r/dhl%3A20261006-setprotocolethmacoapy.md).
- Redemption curve priced off an estimated post-trade value and mutating per-call state; not split-invariant [E3](https://bugbountylibrary.com/r/dhl%3A20260809-usm.md).
- Per-token value distribution with `Ceil` over a dust share [E4](https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.1.md).
- A "locked" amount rounded down, inflating the withdrawable remainder [E5](https://bugbountylibrary.com/r/sherlock%3A2023-12-jojo-exchange-update%3AH-2.md).
- Allowance charged in nominal units while balances convert with ceiling division [E6](https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AM-42.md).
- Refund/cancellation computed with `roundUp: true` [E7](https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-03.md).
- Scale-down then scale-up across contract boundaries, truncating and inflating a derived subtraction [E8](https://bugbountylibrary.com/r/c4%3A2025-04-virtuals-protocol%3AM-05.md).

## How to review
The invariant: for every conversion and subtraction, protocol-accounted value >= sum of what users can extract, and rounding favors the protocol on both sides of any deposit/redeem pair. Check each `mulDiv`/division for direction. For aggregate-vs-per-user, compute `sum(mulDivDown(user_i))` and compare to `mulDivDown(sum(user_i))`; if the sum exceeds the aggregate, the gap is extractable. Confirm any `a - b` cannot underflow given reachable inputs (dust donations, fractional state from other paths). Confirm allowance units match balance units. Rounding up is legitimate only when it increases protocol-held value or reduces user claims; flag any round-up that increases a user payout or refund. On redeem, shares should round up so the caller cannot burn fewer shares than the underlying received [E1](https://bugbountylibrary.com/r/sherlock%3A2025-07-malda%3AM-1.md). Test with 1 wei, dust, and repeated or split calls.

## Variants seen
- Redeem shares rounded down, enabling exchange-rate inflation drain [E1](https://bugbountylibrary.com/r/sherlock%3A2025-07-malda%3AM-1.md).
- Permissionless `divCeil` share-price recompute plus donation [E2](https://bugbountylibrary.com/r/dhl%3A20261006-setprotocolethmacoapy.md).
- Split-invariance failure in a redemption curve [E3](https://bugbountylibrary.com/r/dhl%3A20260809-usm.md).
- Ceil per-token distribution over dust supply [E4](https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.1.md).
- Round-down on a locked amount inflating the remainder [E5](https://bugbountylibrary.com/r/sherlock%3A2023-12-jojo-exchange-update%3AH-2.md).
- Ceiling division on dust transfers exceeding nominal allowance [E6](https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AM-42.md).
- Round-up refund on cancellation, amplified by order splitting [E7](https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-03.md).
- Truncating scale-down inflating a subtraction [E8](https://bugbountylibrary.com/r/c4%3A2025-04-virtuals-protocol%3AM-05.md).

## Impact and severity
Led to drained refund pools, over-redemption and under-collateralization, allowance bypass, locked dust, and permanent DoS of withdrawals/snapshots [E1](https://bugbountylibrary.com/r/sherlock%3A2025-07-malda%3AM-1.md)[E2](https://bugbountylibrary.com/r/dhl%3A20261006-setprotocolethmacoapy.md)[E5](https://bugbountylibrary.com/r/sherlock%3A2023-12-jojo-exchange-update%3AH-2.md)[E6](https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AM-42.md)[E7](https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-03.md). Severity rises when errors are repeatable or splittable, when the rounding path is permissionless, and when dust donations are permissionless.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2025-07-malda%3AM-1.md
- E2: https://bugbountylibrary.com/r/dhl%3A20261006-setprotocolethmacoapy.md
- E3: https://bugbountylibrary.com/r/dhl%3A20260809-usm.md
- E4: https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.1.md
- E5: https://bugbountylibrary.com/r/sherlock%3A2023-12-jojo-exchange-update%3AH-2.md
- E6: https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AM-42.md
- E7: https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-03.md
- E8: https://bugbountylibrary.com/r/c4%3A2025-04-virtuals-protocol%3AM-05.md
