# Oracle Data Corruption via Storage Key Collision

Ekubo Oracle storage key collision lets a crafted token address overwrite another token's snapshot, corrupting historical price data for downstream consumers.

- Payout: Contest reward
- Severity: medium
- Program: Ekubo
- Credited: BlueSheep
- Disclosed: 2026-01-12
- Write-up quality: 7/10
- Original: https://code4rena.com/reports/2025-11-ekubo#m-01
- Library page: https://bugbountylibrary.com/r/c4%3A2025-11-ekubo%3AM-01
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error

**Target:** Oracle extension smart contract
**Root cause:** Snapshot storage slot is computed as (token << 32) | index, which can equal the slot of another token's Counts struct (token address), causing overwrites when a token has 32 leading zeros.
**Steps:**
1. Choose tokenB with 32 leading zeros (e.g., address(100)).
2. Compute tokenA = address(uint160(tokenB) << 32).
3. Initialize pool for tokenB, creating Snapshot(tokenB, 0) at slot tokenB<<32.
4. Initialize pool for tokenA, writing Counts(tokenA) to slot tokenA, which equals tokenB<<32.
5. Observe Snapshot(tokenB, 0) overwritten: timestamp becomes 0, cumulative values corrupted.
**How found:** Code review of storage slot derivation in Oracle.sol revealed that snapshot slot (token << 32) | index can collide with another token's Counts slot (token) when the token address has 32 leading zeros.
**Exploitation:** Attacker deploys or finds a token with 32 leading zeros, then initializes a pool for the colliding tokenA, overwriting the snapshot of tokenB. This corrupts oracle data for tokenB, affecting downstream consumers like ERC7726 and PriceFetcher.
**Insight:** When storage slots are derived by bit-packing addresses and indices, check for collisions between different data structures; addresses with leading zeros can cause unintended overlaps.
