# Sandwichable predictable price updates

Can an outsider see or trigger a price change and trade on both sides of it?

_Area: DeFi oracles, liquidations and flash loans. Seen in 22 disclosed reports; one confirmed bounty: $28,730; latest 2026-03-09. Updated 2026-10-23._

## How it works
A price, curve parameter, or pool balance changes at a moment an outside party can predict or trigger. That party trades before the change and reverses after, capturing value from other users or the protocol. The broken assumption is that the update is atomic and safe: the pending change is visible (mempool, public trigger, or caller-controlled), and the pool reprices against whoever trades across it. Two shapes exist: pre-positioning (trade before a known future update, unwind after) and atomic same-transaction (trigger the update and the surrounding trades in one tx, often flash-loan funded). A third shape is snapshot manipulation: a value is read once and used later, so a single transaction can move it.

## Where it shows up
- Whitelisting a shared permissionless automation/relayer contract, so anyone can invoke the automated call with chosen parameters [E1](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-alchemix-access-control-issue-bugfix-review.md)
- Mitigations that compare pool output to an oracle price predictable before its next update [E2](https://bugbountylibrary.com/r/sherlock%3A2023-03-olympus%3AH-1.md)
- Permissionless, idempotent pool creation at a caller-chosen initial price before migration [E3](https://bugbountylibrary.com/r/dhl%3A20250211-fourmeme.md)
- User-callable functions that internally perform AMM remove/swap/add at caller-chosen size and timing [E4](https://bugbountylibrary.com/r/c4%3A2023-08-dopex%3AM-08.md)
- Oracle updates gated on a coarse time bucket, where the first caller in the bucket sets the value [E6](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-11.md)
- Owner setters of a parameter that feeds AMM pricing (virtual reserves) [E7](https://bugbountylibrary.com/r/cantina%3Aterm_max_december2024%3A3.1.3.md)
- Keeper/rebalance functions whose profit gate can be forced to revert by a front-run swap [E8](https://bugbountylibrary.com/r/c4%3A2024-12-lambowin%3AM-08.md)
- Detection cues: grep for createAndInitializePoolIfNecessary, minimumAmountOut params, epoch-gated writes, owner setters feeding pricing; for deviation-threshold oracles, check whether the next update price is computable from the current spot before it fires [E2](https://bugbountylibrary.com/r/sherlock%3A2023-03-olympus%3AH-1.md); for epoch-gated writes, check whether the first caller in the bucket is permissionless and reads a manipulable tick [E6](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-11.md)

## How to review
For every state change that moves price or pool balances, ask: can an outside party see it coming or trigger it, and can they trade on both sides? The invariant: no value-changing update should be executable in the same block as an outside-controlled trade without slippage bounds, a ramp, a commit/reveal, or a time-weighted measure. Check each separately:
- Automated calls use a dedicated per-task proxy, not a shared relayer [E1](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-alchemix-access-control-issue-bugfix-review.md).
- AMM-touching functions enforce caller-supplied slippage limits [E3](https://bugbountylibrary.com/r/dhl%3A20250211-fourmeme.md)[E4](https://bugbountylibrary.com/r/c4%3A2023-08-dopex%3AM-08.md).
- Oracle comparisons use a TWAP or commit/reveal, not a pre-update spot price, accounting for deviation-threshold timing [E2](https://bugbountylibrary.com/r/sherlock%3A2023-03-olympus%3AH-1.md).
- Parameter setters ramp over time [E7](https://bugbountylibrary.com/r/cantina%3Aterm_max_december2024%3A3.1.3.md).
- First-caller-in-epoch writes are not permissionless over manipulable ticks [E6](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-11.md).
- Rebalance profit gates cannot be forced to revert by a front-run swap [E8](https://bugbountylibrary.com/r/c4%3A2024-12-lambowin%3AM-08.md).

## Variants seen
- Shared relayer whitelist with attacker-chosen minimumAmountOut [E1](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-alchemix-access-control-issue-bugfix-review.md)
- Oracle-price arb cap bypassed by sandwiching the oracle update [E2](https://bugbountylibrary.com/r/sherlock%3A2023-03-olympus%3AH-1.md)
- Pre-created pool at skewed initial price (pre-positioning, no reversal trade) [E3](https://bugbountylibrary.com/r/dhl%3A20250211-fourmeme.md)
- User-triggered internal AMM rebalance sandwiched [E4](https://bugbountylibrary.com/r/c4%3A2023-08-dopex%3AM-08.md)
- First-caller-in-epoch oracle write from a manipulable tick [E6](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-11.md)
- Owner parameter setter repricing virtual reserves (pre-positioning, no reversal trade) [E7](https://bugbountylibrary.com/r/cantina%3Aterm_max_december2024%3A3.1.3.md)
- Front-run swap forcing a rebalance profit gate to revert (DoS) [E8](https://bugbountylibrary.com/r/c4%3A2024-12-lambowin%3AM-08.md)

## Impact and severity
Yield theft, LP losses socialized onto passive depositors, near-zero-cost collateral acquisition, and DoS of bonding or repeg. Severity rises when the trigger is public and the window is short or cheap to dominate [E2](https://bugbountylibrary.com/r/sherlock%3A2023-03-olympus%3AH-1.md)[E6](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-11.md).

| Factor | Lower | Higher |
|---|---|---|
| Trigger visibility | private/owner-only | public permissionless [E1](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-alchemix-access-control-issue-bugfix-review.md)[E6](https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-11.md) |
| Window | long/ramped | single block [E2](https://bugbountylibrary.com/r/sherlock%3A2023-03-olympus%3AH-1.md) |
| Cost to dominate | high capital | flash-loanable [E4](https://bugbountylibrary.com/r/c4%3A2023-08-dopex%3AM-08.md) |
| Loss bearer | attacker | passive LPs/depositors [E2](https://bugbountylibrary.com/r/sherlock%3A2023-03-olympus%3AH-1.md) |

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-alchemix-access-control-issue-bugfix-review.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2023-03-olympus%3AH-1.md
- E3: https://bugbountylibrary.com/r/dhl%3A20250211-fourmeme.md
- E4: https://bugbountylibrary.com/r/c4%3A2023-08-dopex%3AM-08.md
- E5: https://bugbountylibrary.com/r/c4%3A2023-12-ethereumcreditguild%3AM-16.md
- E6: https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-11.md
- E7: https://bugbountylibrary.com/r/cantina%3Aterm_max_december2024%3A3.1.3.md
- E8: https://bugbountylibrary.com/r/c4%3A2024-12-lambowin%3AM-08.md
