# Public getter preserves stale baseline

Unauthenticated PriceOracle::get_last_price extends TTL of the circuit-breaker baseline, letting an attacker keep a stale price alive and freeze a dormant reserve.

- Payout: Contest reward
- Severity: medium
- Program: K2
- Credited: v12
- Disclosed: 2026-08-20
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2026-04-k2#m-12
- Library page: https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AM-12
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:rust technique:source-review vuln:business-logic vuln:dos vuln:oracle-manipulation

**Target:** Soroban smart contract price oracle storage helper (storage::get_last_price / PriceOracle::get_last_price)
**Root cause:** storage::get_last_price calls extend_ttl on PersistentKey::LastPrice when the entry exists, so a read helper mutates the lifetime of a security-critical circuit-breaker baseline and is reachable via an unauthenticated public entry point.
**Steps:**
1. Identify that PriceOracle::get_last_price is unauthenticated and calls storage::get_last_price.
2. Observe storage::get_last_price invokes extend_ttl on PersistentKey::LastPrice whenever the entry exists.
3. Pick a rarely used reserve whose stored baseline is stale relative to the real market.
4. Periodically call `PriceOracle::get_last_price` to keep the stale baseline entry alive across inactivity.
5. When the asset is used again, the next legitimate price query exceeds max_price_change_bps versus the preserved baseline and reverts with PriceChangeTooLarge.
**How found:** Code reading of the storage helper revealed that get_last_price is not a pure read because it calls extend_ttl, and tracing the public entry point showed the mutation is reachable unauthenticated.
**Exploitation:** Attacker repeatedly invokes the public get_last_price entry point on a dormant reserve, refreshing the TTL of the old baseline without producing a new observation. Once the real market price diverges beyond max_price_change_bps, the next legitimate price update fails validation, reverting router flows that need that asset until an admin manually resets the circuit breaker.
**Insight:** Audit 'read' helpers for hidden state mutations (TTL extension, counters, last-access timestamps) on security-critical keys; a getter that refreshes lifetime turns circuit-breaker/staleness windows into attacker-controlled state.
