# Raw balance inflates invariant math

Does invariant, liquidity, or rate math read a raw token balance that outsiders can change?

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

## How it works
Protocol math assumes the contract's token balance equals its internal accounting. That assumption breaks in two distinct ways. First, a direct transfer (donation) raises `balanceOf(address(this))` without the protocol recording it, so any formula reading the raw balance computes on inflated reserves. Second, a token contract may expose a public function that writes or reduces a balance without a transfer, letting an attacker forge reserves directly. Either way the derived value (interest rate, required liquidity, invariant K) no longer reflects real state.

## Where it shows up
- Invariant or reserve math using `token.balanceOf(pair/contract)` instead of tracked reserves [E2](https://bugbountylibrary.com/r/dhl%3A20250429-flylong.md)[E4](https://bugbountylibrary.com/r/dhl%3A20230621-bunn.md)
- Utilisation or interest formulas (`borrowed/loaned`) with no 100% cap, so donations let borrows exceed loans [E1](https://bugbountylibrary.com/r/sherlock%3A2023-12-arcadia%3AM-4.md)
- Migration functions computing required amounts from own balance [E3](https://bugbountylibrary.com/r/c4%3A2025-01-iq-ai%3AM-02.md)
- Token contracts exposing public functions that write balances without transfers (`tokenMarketing`, `tradingTake`, `deliver`) [E2](https://bugbountylibrary.com/r/dhl%3A20250429-flylong.md)[E4](https://bugbountylibrary.com/r/dhl%3A20230621-bunn.md)

## How to review
Identify every read of a raw token balance and ask whether an outside party can change it without the protocol recording it. The invariant: any value used in invariant, liquidity, or rate math must derive from internally tracked state, or the balance must be provably unchangeable by third parties. Check that utilisation/rates are capped at 100% [E1](https://bugbountylibrary.com/r/sherlock%3A2023-12-arcadia%3AM-4.md), that migration math uses tracked amounts not `balanceOf` [E3](https://bugbountylibrary.com/r/c4%3A2025-01-iq-ai%3AM-02.md), and that no public function mutates balances outside a transfer path [E2](https://bugbountylibrary.com/r/dhl%3A20250429-flylong.md)[E4](https://bugbountylibrary.com/r/dhl%3A20230621-bunn.md).

## Variants seen
- Uncapped utilisation inflated by donation then borrow-back [E1](https://bugbountylibrary.com/r/sherlock%3A2023-12-arcadia%3AM-4.md)
- Public balance-forging token functions used inside an AMM callback to satisfy K [E2](https://bugbountylibrary.com/r/dhl%3A20250429-flylong.md)
- Donation inflating computed liquidity, causing revert that blocks migration [E3](https://bugbountylibrary.com/r/c4%3A2025-01-iq-ai%3AM-02.md)
- Reflection `deliver` reducing a pair's balance without transfer [E4](https://bugbountylibrary.com/r/dhl%3A20230621-bunn.md)

## Impact and severity
Led to theft from later depositors via inflated interest [E1](https://bugbountylibrary.com/r/sherlock%3A2023-12-arcadia%3AM-4.md), pair drains of ~1.73 BNB [E2](https://bugbountylibrary.com/r/dhl%3A20250429-flylong.md) and ~52 BNB [E4](https://bugbountylibrary.com/r/dhl%3A20230621-bunn.md), and a migration DOS [E3](https://bugbountylibrary.com/r/c4%3A2025-01-iq-ai%3AM-02.md). Severity rises where the inflated value feeds payouts or swap pricing directly.

## Why fixes fail
Balance-dependent logic remained exploitable after partial hardening [E3](https://bugbountylibrary.com/r/c4%3A2025-01-iq-ai%3AM-02.md); fixing one path left the balance read in place.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2023-12-arcadia%3AM-4.md
- E2: https://bugbountylibrary.com/r/dhl%3A20250429-flylong.md
- E3: https://bugbountylibrary.com/r/c4%3A2025-01-iq-ai%3AM-02.md
- E4: https://bugbountylibrary.com/r/dhl%3A20230621-bunn.md
