# Assignment vs accumulation accounting bugs

Accumulators written with = instead of +=, or per-account state overwritten by later calls

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

## How it works
A value that should grow over time is written with `=` instead of `+=`, or a per-account slot is overwritten by a later call. Earlier contributions vanish silently. The code still runs; only the number is wrong. Downstream math (shares, collateral, interest, pool value) then trusts a total that no longer reflects what was actually credited.

## Where it shows up
- Per-leg or per-asset loops where an accumulator is assigned inside the loop [E6](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-02.md).
- Settlement functions that recompute a value already accrued elsewhere [E2](https://bugbountylibrary.com/r/sherlock%3A2024-11-autonomint%3AH-27.md).
- Accounting mappings keyed by a shared identifier (collateral, token) written with `=` [E7](https://bugbountylibrary.com/r/cantina%3Aterm_structure_february2025%3A3.1.4.md).
- Cursor rewind paths that do not reset the running total they advanced [E8](https://bugbountylibrary.com/r/c4%3A2024-04-noya%3AH-10.md).
- Per-account scheduling state (pending epoch) set unconditionally on deposit [E1](https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AH-1.md).
- Pool value recomputed from a snapshot gated on a counter reaching zero [E2](https://bugbountylibrary.com/r/sherlock%3A2024-11-autonomint%3AH-27.md).
- Global bad debt incremented while per-position bad debt is overwritten [E3](https://bugbountylibrary.com/r/c4%3A2024-02-wise-lending%3AH-03.md).
- Cached struct written back to storage after a helper credited the same slot [E4](https://bugbountylibrary.com/r/sherlock%3A2024-02-perennial-v2-3%3AM-5.md).
- Partial fill that re-registers a new quote for one party but not the other [E5](https://bugbountylibrary.com/r/sherlock%3A2023-06-symmetrical%3AH-6.md).

## How to review
For every state variable, ask: is it a running total? If so, every write site must be `+=` unless it is an explicit reset, and every reset must be paired with the cursor or counter it belongs to. For per-account slots, check whether a second call can overwrite a pending entry before it is consumed. For cached-struct functions, check whether any helper writes the same storage slot mid-execution before the cache is stored back. The invariant: after any sequence of deposits, withdrawals, extensions and partial fills, the stored total equals the sum of all credited contributions minus all settled ones. Trace each accumulator from accrual site to settlement site and confirm no path assigns over it. Detection heuristic: grep for `=` on names like total, credits, debt, poolValue, pending; diff every accrual site against its settlement site.

## Variants seen
- Loop accumulator overwritten, dropping earlier legs' credits [E6](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-02.md).
- Pool value recomputed from snapshot, discarding cumulative profit [E2](https://bugbountylibrary.com/r/sherlock%3A2024-11-autonomint%3AH-27.md).
- Bad debt mapping overwritten across markets sharing a collateral key [E7](https://bugbountylibrary.com/r/cantina%3Aterm_structure_february2025%3A3.1.4.md).
- Cursor rewound without zeroing the running total [E8](https://bugbountylibrary.com/r/c4%3A2024-04-noya%3AH-10.md).
- Pending epoch overwritten by a later deposit, desyncing user vs global settlement [E1](https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AH-1.md).
- Global bad debt incremented while per-position debt overwritten, bricking a zero-gated claim [E3](https://bugbountylibrary.com/r/c4%3A2024-02-wise-lending%3AH-03.md).
- In-memory context stored back over a freshly credited slot [E4](https://bugbountylibrary.com/r/sherlock%3A2024-02-perennial-v2-3%3AM-5.md).
- Partial fill leaves locked balance inflated for one party [E5](https://bugbountylibrary.com/r/sherlock%3A2023-06-symmetrical%3AH-6.md).

## Impact and severity
Fund loss, trapped profit, inflated locked balances, and wrongful liquidation of solvent accounts [E1](https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AH-1.md)[E2](https://bugbountylibrary.com/r/sherlock%3A2024-11-autonomint%3AH-27.md)[E3](https://bugbountylibrary.com/r/c4%3A2024-02-wise-lending%3AH-03.md)[E6](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-02.md). Severity is high because the wrong number is trusted by pricing and solvency logic. Worse when permissionless third parties can trigger the overwrite [E1](https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AH-1.md), when the stale value feeds liquidation [E6](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-02.md), or when a zero-gated accumulator is permanently desynced [E3](https://bugbountylibrary.com/r/c4%3A2024-02-wise-lending%3AH-03.md).

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AH-1.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2024-11-autonomint%3AH-27.md
- E3: https://bugbountylibrary.com/r/c4%3A2024-02-wise-lending%3AH-03.md
- E4: https://bugbountylibrary.com/r/sherlock%3A2024-02-perennial-v2-3%3AM-5.md
- E5: https://bugbountylibrary.com/r/sherlock%3A2023-06-symmetrical%3AH-6.md
- E6: https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-02.md
- E7: https://bugbountylibrary.com/r/cantina%3Aterm_structure_february2025%3A3.1.4.md
- E8: https://bugbountylibrary.com/r/c4%3A2024-04-noya%3AH-10.md
