# Fee unit and cap mismatch

Fee scaled by unbounded multiplier, wrong unit, or partial validation, so charges exceed intent

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

## How it works
A fee is computed from a parameter whose unit or scale does not match how it is applied, or whose growth is not bounded. The code assumes the fee stays a small fraction of the amount, but the multiplier, share list, or denom check lets the computed fee exceed the intended percentage or the payer's balance. The invariant "total fee <= intended rate * amount" is never enforced.

## Where it shows up
- Fee split across a configurable list of shares with no check that the shares sum to <= 100% [E1](https://bugbountylibrary.com/r/dhl%3A20260112-mttoken.md)
- Fee = ceil(size/standardSize) * baseFee with no cap relative to collateral [E2](https://bugbountylibrary.com/r/c4%3A2023-03-polynomial%3AH-09.md)
- A new fee-override layer (feeManager) added, but some entry points still read the old default field directly [E3](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.2.2.md)
- Fee validation using strict equality on summed amounts, or `.any()` where `.all()` is required across denoms [E4](https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-01.md)
- Fee-on-transfer tokens interacting with AMM `sync`/`skim`

## How to review
- For every fee path, identify the unit of each input (percent, basis points, absolute amount) and confirm the arithmetic keeps that unit.
- Check the bound: is there an explicit cap tying the fee to the amount or collateral? If a multiplier scales with size or a share list is summed, verify the sum/multiplier is constrained.
- Grep all fee-charging entry points (claim, collect, withdraw, transfer) for direct reads of a default fee field instead of the override accessor [E3](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.2.2.md).
- When re-implementing an external module's fee check, diff against that module's own validation; require `.all()` and correct equality semantics [E4](https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-01.md).
- Invariant to hold: computed fee <= configured rate * base amount, and total debited <= payer balance.

## Variants seen
- Unbounded share list overcharging transfers to AMM pairs [E1](https://bugbountylibrary.com/r/dhl%3A20260112-mttoken.md)
- Linear region multiplier making order fees exceed 100% of collateral [E2](https://bugbountylibrary.com/r/c4%3A2023-03-polynomial%3AH-09.md)
- Override layer bypassed on reward-claim path [E3](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.2.2.md)
- `.any()` vs `.all()` and strict equality in fee validation [E4](https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-01.md)

## Impact and severity
Led to AMM pair drain (~37K USDT) [E1](https://bugbountylibrary.com/r/dhl%3A20260112-mttoken.md), up to 99.9% collateral loss for traders [E2](https://bugbountylibrary.com/r/c4%3A2023-03-polynomial%3AH-09.md), systematic mischarging on every claim [E3](https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.2.2.md), and underpayment or revert of pool creation [E4](https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-01.md). Severity rises when the fee path is reachable by anyone and touches shared liquidity or user collateral.

## Evidence
- E1: https://bugbountylibrary.com/r/dhl%3A20260112-mttoken.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-03-polynomial%3AH-09.md
- E3: https://bugbountylibrary.com/r/cantina%3Ajigsaw_june2025%3A3.2.2.md
- E4: https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-01.md
