# Counter mutated before checkpoint read

State feeding a fee, price, or id is changed before the checkpoint or insert that reads it

_Area: DeFi accounting and math bugs. Seen in 2 disclosed reports; latest 2024-08-06. Updated 2026-10-29._

## How it works
A counter, length, or index is changed (decremented, shrunk, or set to a sentinel) before the code that reads it to compute a fee, price, or new id. The reader then sees a value that no longer matches reality: a utilization ratio computed from a too-small count, or a new id derived from a length that now collides with a live entry. The assumption that breaks is "the counter still reflects the state the math needs." Ordering of mutation versus read is the whole bug.

## Where it shows up
- A `--counter` or `length--` sitting above a checkpoint, snapshot, or fee calculation that consumes that counter.
- New ids or slots derived from `length` or `length+1` after deletes shrink the same length.
- A sentinel like `i128::MAX` written to an index that other code later subtracts from.
- Utilization- or ratio-based pricing read across several sequential operations in one transaction.

## How to review
Find every counter/index that feeds a fee, price, or id. For each, confirm the mutation happens *after* the read, or that the read uses a saved pre-mutation value. Invariant: any value used in fee/price/id math must equal the state as of the moment that math is meant to represent. For sentinels, check every downstream subtraction and multiplication for overflow/underflow.

## Variants seen
- Length shrunk on delete, new id derived from length, colliding with and overwriting a live order [E1](https://bugbountylibrary.com/r/sherlock%3A2022-09-knox%3AH-4.md).
- Listing count decremented before the checkpoint, understating unlock price across sequential unlocks [E2](https://bugbountylibrary.com/r/sherlock%3A2024-08-flayer%3AH-7.md).
- Removed pool's index set to `i128::MAX`, so later accrual subtraction overflows and reverts, locking distributed emissions [E3](https://bugbountylibrary.com/r/c4%3A2025-02-blend-v2-audit-certora-formal-verification%3AM-16.md).

## Impact and severity
Funds locked and unrecoverable [E1](https://bugbountylibrary.com/r/sherlock%3A2022-09-knox%3AH-4.md), fees underpaid [E2](https://bugbountylibrary.com/r/sherlock%3A2024-08-flayer%3AH-7.md), and legitimate rewards permanently unclaimable via revert [E3](https://bugbountylibrary.com/r/c4%3A2025-02-blend-v2-audit-certora-formal-verification%3AM-16.md). Severity rises when the stale read repeats across sequential operations in one transaction, compounding the undercharge, and when the bad state is permanent (locked funds, frozen index).

## Why fixes fail
A fix that only reorders one call site leaves other paths reading the same counter; the sentinel fix in [E3](https://bugbountylibrary.com/r/c4%3A2025-02-blend-v2-audit-certora-formal-verification%3AM-16.md) stopped emissions but broke accrual, showing a freeze must be checked against every arithmetic consumer.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2022-09-knox%3AH-4.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2024-08-flayer%3AH-7.md
- E3: https://bugbountylibrary.com/r/c4%3A2025-02-blend-v2-audit-certora-formal-verification%3AM-16.md
