# Read-only reentrancy in price oracles

Oracle reads pool balances and supply during callbacks without a reentrancy guard, so prices desync

_Area: DeFi oracles, liquidations and flash loans. Seen in 7 disclosed reports; latest 2024-03-30. Updated 2026-10-23._

## How it works
An oracle computes a price from live pool state: balances, LP/BPT total supply, or a rate. Those values are read through separate external calls. During a callback (native ETH transfer, ERC777/ERC1363 hook, token `_transfer`), the pool is mid-update: some values already changed, others not. The oracle reads the mismatched snapshot and returns a skewed price. The root assumption that breaks is "pool state is consistent whenever I read it." It is not, unless the reader proves no callback is active.

## Where it shows up
- Price functions calling `getPoolTokens`, `totalSupply`, `getRate`, or `balances()` as separate external calls, with no guard check [E3](https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-13.md)[E5](https://bugbountylibrary.com/r/cantina%3Aopal_feb2024%3A3.2.1.md).
- A reentrancy-guard library imported or `using`-declared but never invoked [E5](https://bugbountylibrary.com/r/cantina%3Aopal_feb2024%3A3.2.1.md).
- Guards gated on a sentinel (e.g. `0xEeee...`) for native ETH, while the pool lists WETH and accepts ETH via `use_eth` [E1](https://bugbountylibrary.com/r/sherlock%3A2023-06-tokemak%3AH-5.md).
- Curve pools that burn LP before paying out raw ETH, so `totalSupply` drops while coins remain [E4](https://bugbountylibrary.com/r/c4%3A2023-07-reserve%3AM-01.md).
- Deviation/slippage check before an external swap, never re-checked before `addLiquidity` [E2](https://bugbountylibrary.com/r/sherlock%3A2023-06-arrakis%3AH-1.md).
- AMM quote reading live reserves while effects (share updates) precede the asset pull [E6](https://bugbountylibrary.com/r/c4%3A2022-12-caviar%3AH-01.md).

## How to review
For every oracle read, identify all callbacks reachable during that read and confirm the invariant: either the read happens outside any pool context, or the guard is checked immediately before use. Concretely: does the code call the vendor guard (`ensureNotInVaultContext`) in the same function that reads balances and supply [E5](https://bugbountylibrary.com/r/cantina%3Aopal_feb2024%3A3.2.1.md)? Is the guard condition based on actual ETH-acceptance (`use_eth`), not a sentinel address [E1](https://bugbountylibrary.com/r/sherlock%3A2023-06-tokemak%3AH-5.md)? Are balances and supply read atomically or cross-checked against a stored value? For checks-then-actions, is the price/deviation re-validated after the external call [E2](https://bugbountylibrary.com/r/sherlock%3A2023-06-arrakis%3AH-1.md)?

## Variants seen
- Sentinel-address guard misses WETH pools accepting ETH [E1](https://bugbountylibrary.com/r/sherlock%3A2023-06-tokemak%3AH-5.md).
- Guard library imported but not called [E5](https://bugbountylibrary.com/r/cantina%3Aopal_feb2024%3A3.2.1.md).
- Balancer balances vs BPT supply read out of sync during join/exit [E3](https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-13.md).
- Curve LP burn-before-ETH-payout inflating `aum/supply` [E4](https://bugbountylibrary.com/r/c4%3A2023-07-reserve%3AM-01.md).
- Stale deviation check bypassed by token transfer callback [E2](https://bugbountylibrary.com/r/sherlock%3A2023-06-arrakis%3AH-1.md).
- ERC777 hook re-entering AMM buy at stale reserves [E6](https://bugbountylibrary.com/r/c4%3A2022-12-caviar%3AH-01.md).

## Impact and severity
Led to inflated prices, premature liquidations, discounted buys, and full vault drains [E1](https://bugbountylibrary.com/r/sherlock%3A2023-06-tokemak%3AH-5.md)[E2](https://bugbountylibrary.com/r/sherlock%3A2023-06-arrakis%3AH-1.md)[E3](https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-13.md)[E6](https://bugbountylibrary.com/r/c4%3A2022-12-caviar%3AH-01.md). Severity is high because the manipulation is cheap and often flash-loan-funded, and the oracle is trusted by downstream lending or vault logic. Worse when the guard exists but is misapplied, giving false confidence [E1](https://bugbountylibrary.com/r/sherlock%3A2023-06-tokemak%3AH-5.md)[E5](https://bugbountylibrary.com/r/cantina%3Aopal_feb2024%3A3.2.1.md).

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2023-06-tokemak%3AH-5.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2023-06-arrakis%3AH-1.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2023-04-blueberry%3AH-13.md
- E4: https://bugbountylibrary.com/r/c4%3A2023-07-reserve%3AM-01.md
- E5: https://bugbountylibrary.com/r/cantina%3Aopal_feb2024%3A3.2.1.md
- E6: https://bugbountylibrary.com/r/c4%3A2022-12-caviar%3AH-01.md
