# Oracle fallback to spot price

Price path that silently falls back to pool spot or inflated value when a feed reverts or a capacity check fails

_Area: DeFi oracles, liquidations and flash loans. Seen in 2 disclosed reports; latest 2026-05-18. Updated 2026-11-01._

## How it works
A price path is supposed to use a trustworthy source (a median of feeds, a TWAP, a protocol exchange rate). When that source is unavailable or a capacity check fails, the code does not stop — it substitutes a weaker value: the pool's spot price, or a swap-quoted price. The broken assumption is that "unavailable" is rare and benign. In practice an attacker can *cause* unavailability (force a feed to revert, make a balance exceed pool capacity, make a staticcall fail) and then the fallback hands them a price they can move with a flash loan. The guard becomes a switch the attacker flips.

## Where it shows up
- Aggregators that skip feeds which revert instead of reverting the whole computation [E1](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-4.md)
- Submodules whose revert is attacker-triggerable: reentrancy locks (UniV3/Balancer/Bunni), deviation checks, vault-context guards [E1](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-4.md)
- Pricing helpers that branch on whether an amount fits a capacity limit, then return a pool/swap price when it doesn't [E2](https://bugbountylibrary.com/r/c4%3A2023-03-asymmetry%3AH-02.md)
- Callers passing the contract's whole balance instead of the user's deposit into such a helper [E2](https://bugbountylibrary.com/r/c4%3A2023-03-asymmetry%3AH-02.md)
- `staticcall`/try-catch error branches that return `slot0` spot instead of reverting (fail-open) [E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-08.md)
- Maturity/history comparisons whose direction is inverted, so a pool with TWAP data still returns spot [E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-08.md)

## How to review
For every price read, ask: what happens when the primary source fails or the capacity check says no? The invariant: **no failure, revert, or capacity miss may ever yield a spot or swap-derived price to a caller that acts on it.** Trace each branch:
- Does a reverting feed abort the whole aggregation, or get silently dropped? [E1](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-4.md)
- Can an outside actor trigger that revert (locks, deviation, context)? [E1](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-4.md)
- What amount is passed to a capacity-branching helper — user deposit or full balance? [E2](https://bugbountylibrary.com/r/c4%3A2023-03-asymmetry%3AH-02.md)
- Does every error path revert, or return a value? [E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-08.md)
- Is the maturity comparison direction correct, and does the mature branch actually use TWAP? [E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-08.md)

## How finders spotted it
- Read each price submodule, noted reentrancy/deviation guards that revert, then combined that with the aggregator's skip-on-revert and median logic to hypothesize selective silencing of honest feeds [E1](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-4.md)
- Read `stake()`'s value loop and noticed `ethPerDerivative` received `derivatives[i].balance()` rather than the deposit, flipping the capacity branch [E2](https://bugbountylibrary.com/r/c4%3A2023-03-asymmetry%3AH-02.md)
- Reviewed the price guard and noticed the maturity comparison direction returned spot for pools that do have TWAP data, and the staticcall catch returned untrusted price instead of reverting [E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-08.md)

## Variants seen
- Skip-on-revert feed aggregation, attacker forces honest feeds to revert [E1](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-4.md)
- Capacity check evaluated on full contract balance, falling back to inflated pool price [E2](https://bugbountylibrary.com/r/c4%3A2023-03-asymmetry%3AH-02.md)
- Fail-open staticcall plus inverted maturity check returning slot0 spot [E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-08.md)

## Impact and severity
Manipulated prices reached real value movement: Olympus price moved ~6.3 to ~29.5 via a full median-strategy bypass [E1](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-4.md); SafEth depositors received fewer minted shares [E2](https://bugbountylibrary.com/r/c4%3A2023-03-asymmetry%3AH-02.md); POL assets drainable via flash-loan-manipulated slot0 [E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-08.md). Impact rises when the fallback is reachable by an unprivileged actor and repeatable across operations [E1](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-4.md)[E3](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-08.md), and when combined with reserve manipulation [E1](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-4.md).

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-4.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-03-asymmetry%3AH-02.md
- E3: https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-08.md
