# Fee bypass via wrong aggregation or threshold

Fee checks using any() instead of all(), hardcoded rate thresholds, or fees omitted from recomputation

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; latest 2025-03-31. Updated 2026-11-01._

## How it works
Fee logic encodes an assumption about the world that the code does not enforce. Three shapes recur: a check that should require every fee item paid instead requires only one (`any()` vs `all()`); a fee curve uses threshold constants hardcoded for one asset's rate or decimals; or a state recomputation drops a fee term so the recorded position no longer matches reality. In each case the fee is computed against a model that diverges from what actually happened, so the protocol under-collects or the call reverts.

## Where it shows up
- Fee validation loops using `any()`/`iter().any()` over required fee denoms, or strict equality on a summed amount [E3](https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-01.md)
- Fee curves with two hardcoded threshold constants (min/max start) [E2](https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AM-24.md)
- Setters whose ordering constraint contradicts the formula's assumed ordering [E2](https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AM-24.md)
- Position recomputation after a flashloan or debt adjustment that subtracts only the principal delta, not the fee [E1](https://bugbountylibrary.com/r/c4%3A2024-05-bakerfi%3AM-03.md)
- Collateral and debt deltas treated as symmetric when a fee is paid out of collateral [E1](https://bugbountylibrary.com/r/c4%3A2024-05-bakerfi%3AM-03.md)

## How to review
For each fee check, state the invariant: every required fee item must be satisfied, and the recorded position must equal actual collateral minus actual debt including fees. Verify the aggregation operator matches (all required items, not any), that threshold constants are valid for every asset the code accepts (decimals, oracle rate), and that any setter can actually produce the ordering the formula assumes. For recomputation, trace every term: if a flashloan fee is paid from collateral, the new collateral must drop by principal plus fee while debt drops by principal only [E1](https://bugbountylibrary.com/r/c4%3A2024-05-bakerfi%3AM-03.md). Diff re-implemented fee logic against the external module's own source [E3](https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-01.md).

## Variants seen
- `any()` instead of `all()` plus strict equality on summed fees, causing underpay or revert on denom overlap [E3](https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-01.md)
- Hardcoded min/max fee thresholds valid only for stablecoin rates; setter ordering blocks correction [E2](https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AM-24.md)
- Flashloan fee omitted from deployed-amount recomputation, overstating collateral and under-charging management fee [E1](https://bugbountylibrary.com/r/c4%3A2024-05-bakerfi%3AM-03.md)

## Why fixes fail
In [E2](https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AM-24.md) the setter enforces `_min < _max` while the formula assumes the opposite ordering, so the intended correction cannot be applied through the setter — the bug is locked in by its own guard.

## Impact and severity
Medium in the evidence: fee under-collection, overstated collateral, or reverting pool creation [E1](https://bugbountylibrary.com/r/c4%3A2024-05-bakerfi%3AM-03.md)[E2](https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AM-24.md)[E3](https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-01.md). Worse when the wrong value feeds downstream accounting (management fees, collateral ratios) or when a guard prevents remediation [E2](https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AM-24.md).

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2024-05-bakerfi%3AM-03.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2024-02-tapioca%3AM-24.md
- E3: https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AM-01.md
