# Oracle keyed at wrong scope

Oracle or feed state keyed by token, provider, or sequence instead of pair or unique request

_Area: DeFi oracles, liquidations and flash loans. Seen in 3 disclosed reports; latest 2026-02-02. Updated 2026-10-25._

## How it works
Oracle and feed integrations assume a lookup key uniquely identifies the thing being priced or requested. When internal state is keyed by one element of a composite identity — a single token, a provider's counter, a global timestamp — that key is not unique across the real domain. Two distinct pairs, providers, or partial updates then collide on the same key, and the contract silently returns or reuses the wrong entry. The broken assumption is that the key is globally unique when it is only unique within a narrower scope.

## Where it shows up
- Mappings keyed by a single token where the value is a pair oracle [E2](https://bugbountylibrary.com/r/c4%3A2022-09-y2k-finance%3AM-01.md)
- Pending-request maps keyed by an external counter (sequence number) without the provider address [E1](https://bugbountylibrary.com/r/c4%3A2025-11-megapot%3AM-06.md)
- "Latest" price lookups using a global timestamp rather than the latest tick where both assets have records [E3](https://bugbountylibrary.com/r/c4%3A2025-10-reflector-v3%3AM-05.md)
- Silent skip-if-set guards that drop conflicting assignments instead of reverting [E2](https://bugbountylibrary.com/r/c4%3A2022-09-y2k-finance%3AM-01.md)
- Admin-settable provider/feed addresses that change the meaning of stored keys [E1](https://bugbountylibrary.com/r/c4%3A2025-11-megapot%3AM-06.md)

## How to review
Identify the true identity of each stored value (pair, provider+sequence, pair+timestamp) and confirm the key captures all of it. Check collision behavior: does a second write revert, overwrite, or silently skip? Silent skip is the dangerous case [E2](https://bugbountylibrary.com/r/c4%3A2022-09-y2k-finance%3AM-01.md). For external counters, confirm the provider address is part of the key so a swap cannot collide with stale entries [E1](https://bugbountylibrary.com/r/c4%3A2025-11-megapot%3AM-06.md). For "latest" APIs, confirm the timestamp is per-pair, matching sibling history-scanning APIs [E3](https://bugbountylibrary.com/r/c4%3A2025-10-reflector-v3%3AM-05.md). Invariant: for any key, the stored value must belong to exactly the request/pair/tick that produced it, across provider swaps and partial updates.

## Variants seen
- Per-token oracle registry reusing one pair's oracle for another pair sharing a token [E2](https://bugbountylibrary.com/r/c4%3A2022-09-y2k-finance%3AM-01.md)
- Per-provider sequence counter colliding after an entropy provider swap [E1](https://bugbountylibrary.com/r/c4%3A2025-11-megapot%3AM-06.md)
- Global last-timestamp lookup returning nothing when only one asset updated [E3](https://bugbountylibrary.com/r/c4%3A2025-10-reflector-v3%3AM-05.md)

## Impact and severity
E1 let an attacker fix a jackpot outcome and win it — direct fund loss, high severity. E2 produced wrong peg results for a vault pair, corrupting pricing. E3 caused a latest-price call to fail on partial updates. Severity rises when the mis-keyed value feeds payouts or liquidation pricing, and when admin-swappable providers make stale keys reachable.

## Why fixes fail
Guard-style fixes that skip conflicting writes [E2](https://bugbountylibrary.com/r/c4%3A2022-09-y2k-finance%3AM-01.md) hide the collision rather than keying correctly; the wrong oracle persists for the new pair.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2025-11-megapot%3AM-06.md
- E2: https://bugbountylibrary.com/r/c4%3A2022-09-y2k-finance%3AM-01.md
- E3: https://bugbountylibrary.com/r/c4%3A2025-10-reflector-v3%3AM-05.md
