# The Asset.lotPrice doubles the oracle timeout in the worst case

Asset.lotPrice uses lastSave=block.timestamp instead of oracle updateTime, so stale prices persist up to twice the oracle timeout, mispricing rebalances.

- Payout: Contest reward
- Severity: medium
- Program: Reserve
- Credited: ronnyx2017
- Disclosed: 2023-11-13
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-07-reserve-findings/issues/24
- Library page: https://bugbountylibrary.com/r/c4%3A2023-07-reserve%3AM-07
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:oracle-manipulation

**Target:** Asset.lotPrice / refresh() oracle price caching in Reserve protocol contracts
**Root cause:** refresh() sets lastSave to block.timestamp rather than the Chainlink feed's updateTime, so the decay window starts from save time, not the actual oracle update, doubling the effective staleness window.
**Steps:**
1. Oracle feed last updated at block.timestamp - priceTimeout (still passes OracleLib stale check).
2. Call refresh(): tryPrice() succeeds, savedLowPrice/savedHighPrice set, lastSave = block.timestamp.
3. Oracle then goes offline; tryPrice() reverts.
4. lotPrice computes delta = block.timestamp - lastSave; while delta <= oracleTimeout it returns full saved price.
5. Decay only begins at lastSave + oracleTimeout, i.e. up to 2*priceTimeout after the real oracle update.
**How found:** Code reading of refresh()/lotPrice() comparing lastSave assignment (block.timestamp) against OracleLib's updateTime-based staleness check, spotting the mismatch in decay start time.
**Exploitation:** Not a direct attack; during temporary oracle outage, rebalancing or reward sales use stale full price for up to twice the intended timeout, mispricing buys/sells.
**Insight:** When a contract caches oracle values with its own timestamp, check whether that timestamp reflects the oracle's updateTime or the local save time; the gap extends the effective staleness window and can double the intended timeout.
