# Snapshot key omits a dimension

Check every snapshot/checkpoint mapping key includes market, token, and epoch, not just a shared counter

_Area: DeFi accounting and math bugs. Seen in 3 disclosed reports; latest 2026-03-13. Updated 2026-10-30._

## How it works
A snapshot or checkpoint record is stored under a key built from fewer dimensions than the data actually varies along. Two distinct contexts (different markets, tokens, or message identities) then compute the same key, so writing one record overwrites or shadows another. The broken assumption is that the key is unique per logical record; in reality the omitted dimension is what distinguishes them. Collisions can be accidental (bit-packing overlaps) or structural (a hash helper that drops a field).

## Where it shows up
- Mappings keyed by a shared counter (e.g. a batched shift index) without a market/asset id, especially when sibling mappings do include it [E3](https://bugbountylibrary.com/r/c4%3A2021-08-floatcapital%3AH-02.md)
- Storage slots derived by bit-packing an address with an index, where leading zeros let one struct's slot equal another's [E1](https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-01.md)
- Multiple hash/id helpers for the same struct whose field lists differ; the send-side key and the receipt-side key diverge [E2](https://bugbountylibrary.com/r/c4%3A2025-02-recall%3AH-03.md)
- Any place a record is written under one key and read under a differently-derived key

## How to review
For each snapshot/checkpoint store, list the dimensions the data varies along (market, token, epoch, nonce) and confirm the key includes all of them. The invariant: two records that must coexist must never map to the same key. For bit-packed slots, check that address and index bit ranges cannot overlap another structure's slot. For hash-keyed stores, diff every helper that produces a key for the same struct and confirm identical field sets; trace write-key vs read-key end to end.

## Variants seen
- Missing marketIndex on two sibling mappings while a third is indexed [E3](https://bugbountylibrary.com/r/c4%3A2021-08-floatcapital%3AH-02.md)
- Bit-packed slot (token << 32) | index colliding with another token's Counts slot [E1](https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-01.md)
- Inflight message keyed by toHash() but receipt id from toTracingId() omitting localNonce [E2](https://bugbountylibrary.com/r/c4%3A2025-02-recall%3AH-03.md)

## Impact and severity
Corrupted historical price data for downstream consumers [E1](https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-01.md); permanent fund loss and trapped refunds from failed receipt lookup [E2](https://bugbountylibrary.com/r/c4%3A2025-02-recall%3AH-03.md); misallocated float issuance across markets [E3](https://bugbountylibrary.com/r/c4%3A2021-08-floatcapital%3AH-02.md). Severity is high where the collision silently corrupts accounting or strands funds; worse when the mismatch is deterministic so every affected record fails.

## Why fixes fail
Evidence does not show incomplete or regressed fixes.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-01.md
- E2: https://bugbountylibrary.com/r/c4%3A2025-02-recall%3AH-03.md
- E3: https://bugbountylibrary.com/r/c4%3A2021-08-floatcapital%3AH-02.md
