# Fee unit and scale mismatch

A fee or rate produced in one unit or precision and consumed in another, changing magnitude silently

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; latest 2026-01-10. Updated 2026-10-24._

## How it works

A fee or rate is produced in one unit or fixed-point scale and consumed in another. The producer and consumer each assume their own convention, so the same integer means different things on each side. The broken assumption is that "a fee is a fee" — that the number crossing a function boundary carries its unit with it. Integers carry no unit, so a mismatch silently changes magnitude by orders of magnitude, or makes a subtraction underflow. A related shape is a rate truncated by a coarse divisor, so the fee is computed at the wrong scale even without a producer/consumer disagreement.

## Where it shows up

- A value stored or validated with one precision library (e.g. 1e27) but consumed with another (e.g. 1e6) [E1](https://bugbountylibrary.com/r/c4%3A2023-08-livepeer%3AH-01.md).
- A computed token amount passed into a shared fee manager that expects basis points or weights [E2](https://bugbountylibrary.com/r/dhl%3A20260110-futureswap.md).
- A fee derived from one token's units (debt token) but paid out in another token with different decimals [E3](https://bugbountylibrary.com/r/cantina%3Aalchemix_may2025%3A3.1.4.md).
- Any `percOf`, `mulDiv`, or `/BPS` call where the divisor differs from the one used when the rate was set [E1](https://bugbountylibrary.com/r/c4%3A2023-08-livepeer%3AH-01.md)[E2](https://bugbountylibrary.com/r/dhl%3A20260110-futureswap.md).
- Coarse divisor constants or intermediate divisions that truncate a rate to a floor, undercharging fees.

## How to review

For every fee or rate, trace the value from where it is set/validated to every consumer. The invariant: the unit and scale at production must equal the unit and scale at consumption. Concretely:
- Grep every consumer of a stored rate for the same PERC_DIVISOR / BPS / WAD constant used by the setter [E1](https://bugbountylibrary.com/r/c4%3A2023-08-livepeer%3AH-01.md).
- Confirm a fee forwarded to a shared manager is in that manager's documented unit (bps vs token amount) [E2](https://bugbountylibrary.com/r/dhl%3A20260110-futureswap.md).
- Confirm fees paid in token B are normalized from token A's decimals before transfer [E3](https://bugbountylibrary.com/r/cantina%3Aalchemix_may2025%3A3.1.4.md).
- Check intermediate divisions for truncation and confirm the divisor matches the rate's scale.

## Variants seen

- Precision-library mismatch between setter and consumer causing underflow [E1](https://bugbountylibrary.com/r/c4%3A2023-08-livepeer%3AH-01.md).
- Token-units fee read as basis points, inflating fee weight [E2](https://bugbountylibrary.com/r/dhl%3A20260110-futureswap.md).
- Decimals not normalized between debt and underlying token on payout [E3](https://bugbountylibrary.com/r/cantina%3Aalchemix_may2025%3A3.1.4.md).
- Coarse divisor and truncating intermediate division undercharging fees (rounding-down variant).

## Impact and severity

High: undercharged fees delay liquidations and shortchange LPs; underflow corrupts state and loses redeemable tickets [E1](https://bugbountylibrary.com/r/c4%3A2023-08-livepeer%3AH-01.md); inflated fee weight drains ~395K USDC.e plus WETH [E2](https://bugbountylibrary.com/r/dhl%3A20260110-futureswap.md); a small fee becomes a full fee-vault drain [E3](https://bugbountylibrary.com/r/cantina%3Aalchemix_may2025%3A3.1.4.md). Severity rises when the mismatched value feeds a transfer or a subtraction, turning a rounding error into theft or underflow.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2023-08-livepeer%3AH-01.md
- E2: https://bugbountylibrary.com/r/dhl%3A20260110-futureswap.md
- E3: https://bugbountylibrary.com/r/cantina%3Aalchemix_may2025%3A3.1.4.md
