Web3Exploit logoWeb3Exploit
← Back to Attack Patterns
Attack pattern

Oracle Manipulation

A protocol prices assets off a manipulable source (spot AMM reserves or desynced internal state), letting an attacker forge a favorable price.

Definition

Oracle manipulation exploits a protocol that derives a price from a source the attacker can move within a single transaction — most commonly a spot AMM pool's reserves, or internal accounting variables that can be temporarily desynchronized.

How it works

  1. The protocol reads a price from a manipulable source (e.g. `getReserves()` on a DEX pair, or an internal AUM computed from two variables).
  2. The attacker moves that source — swapping to skew reserves, or reentering to update one accounting variable but not its pair.
  3. The protocol acts on the forged price: minting an LP token cheap, over-borrowing, or redeeming inflated.
  4. The position is unwound, leaving the protocol holding the loss.

Vulnerable vs. fixed

Vulnerable: spot reserves used directly as a pricesolidity
function priceOf(address token) public view returns (uint256) {
    (uint112 r0, uint112 r1, ) = pair.getReserves();
    // Spot reserves are manipulable within one tx via a swap/flash loan.
    return (uint256(r1) * 1e18) / uint256(r0);
}
Fixed: manipulation-resistant oracle (TWAP / signed feed)solidity
function priceOf(address token) public view returns (uint256) {
    // Use a time-weighted average or an external signed feed with staleness
    // checks — a value an attacker cannot move inside a single transaction.
    (, int256 answer, , uint256 updatedAt, ) = chainlinkFeed.latestRoundData();
    require(answer > 0 && block.timestamp - updatedAt < MAX_AGE, "stale price");
    return uint256(answer);
}

Detection steps

  1. Identify the sensitive value or permission the pattern can influence.
  2. Trace every path that can update or consume that value, including callbacks, routers, and privileged helpers.
  3. Reproduce the worst-case attacker flow with adversarial ordering, manipulated inputs, and maximum feasible capital.

Common signals

  • Security depends on an assumption that is not enforced by code.
  • A critical value is consumed immediately after an attacker-controlled interaction.
  • A privileged call path crosses multiple contracts without one clear authorization boundary.

False positives

  • The risky-looking operation is read-only and cannot affect settlement or authorization.
  • The value is bounded by independent checks before it moves assets.
  • All privileged entry points share the same tested guard and monitoring path.

Review questions

  • Which invariant would fail if this input or caller were attacker-controlled?
  • Can the attacker compose setup, trigger, settlement, and cleanup atomically?
  • What independent check stops the exploit if the first guard is wrong?

Defensive checklist

  • Never price off raw spot AMM reserves; prefer TWAPs or vetted signed feeds.
  • Validate oracle freshness (staleness window) and sanity bounds.
  • Ensure every variable feeding a price is updated on all mutation paths (no split-brain accounting).
  • Stress-test pricing under flash-loaned, single-transaction market moves.