Curve's Oracle Security Explained

An overview of Curve’s Oracle Design and Security:

Curve's Oracle Security Explained

In DeFi, many protocols rely on accurate asset pricing. Lending markets, for instance, must know the real-time value of collateral to assess loan health and trigger liquidations. Solving this “oracle problem” is a longstanding challenge, and many platforms outsource this challenge to third-party solutions.

Curve takes a different approach. Its oracles are built directly into its AMMs, drawing prices directly from the on-chain trading activity. Because of this native integration, they are used for the crvUSD minting and Llamalend lending markets - and trusted by many other DeFi protocols.

How Curve Price Oracles Work

Curve’s oracles are secured through two core mechanisms: a mathematically resilient EMA pricing system, and an economic design that makes manipulation unprofitable.

Exponential Moving Average (EMA) Pricing

Rather than outputting a volatile, easily manipulated spot price, Curve oracles use an exponential moving average (EMA). This works similarly to a simple (standard) moving average, but weights recent trades more heavily. This allows the oracle to reflect price trends faster than a simple MA, while also dampening sudden spikes, as can be seen below in this Price and Moving Averages chart:

Each oracle has a time window, typically 10 minutes, though this can be changed through DAO governance for each specific pool. Importantly, oracles update only once per block, preventing intra-block manipulation.

The smoothing effect gives the oracle inertia. A flash loan or other large, sudden trades have dampened influence on the EMA. It protects against short-term manipulation by ensuring that price changes are gradual and harder to exploit.

Economic Defense Against Manipulation

The oracle’s second layer of security is economic. Any attempt to distort its price incurs a direct and significant cost due to the structure of Curve’s AMM.

Manipulating the EMA requires a large swap that significantly shifts the pool’s balance. This incurs substantial slippage, where the attacker receives far less than what they put in, resulting in a guaranteed financial loss. Additionally, because Curve pools are actively monitored by searchers and arbitrageurs, any deviation from the fair market price is likely to be quickly corrected for profit, making sustained manipulation even harder. The combined cost and competitive arbitrage pressure are designed to outweigh any potential gain from exploiting downstream protocols using the oracle.

This combination of mathematical smoothing and strong economic incentives makes Curve’s oracles a reliable foundation for systems like Llamalend and crvUSD. Users borrowing through Curve benefit from price feeds that are tamper‑resistant and fully on‑chain, with mechanisms in place to defend against manipulation. However, increasing the moving‑average (MA) window strengthens manipulation resistance at the cost of responsiveness, particularly for liquidations, so oracle design is an explicit trade‑off between stability and reactivity.

Why Curve's Oracle Held During the deUSD Event

In a recent incident, the Chainlink oracle for deUSD was unintentionally manipulated during a sandwich attack on the deUSD/USDT pool. The result: over $500,000 in liquidations on Euler’s Avalanche deployment.

This occurred because the Chainlink feed was using a volume-weighted average price (VWAP). A large sandwich trade caused the VWAP to spike—since the manipulated trade accounted for most of the measured volume. In contrast, the Curve pool’s internal oracle barely moved, as designed. Because Curve’s EMA is not swayed by large intra-block trades, it remained stable throughout the event. See below for details. Note that Oracle Price is the Pool’s Price Oracle, and VWAP Price is the 1-day rolling VWAP Price of the pool.

Transaction Sold Bought Swap Price Oracle Price VWAP Price
Swap Before 183 USDT 183 deUSD $0.99961 $0.99949 $0.99950
Pre-sandwich 210k USDT 203k deUSD $1.03493 $0.99952 $1.03217
Victim Swap 5.06k USDT 2.92k deUSD $1.73227 $0.99952 $1.04740
Post-sandwich 203k deUSD 212k USDT $1.04520 $0.99952 $1.04637
Swap After 67 USDT 67 deUSD $0.99976 $0.99963 $1.04673
A comparison of the price of deUSD as reported by Curve’s oracle (blue) and the Chainlink VWAP oracle (yellow)

As seen in the chart, the VWAP price spiked sharply due to the large swap volume, which disproportionately influenced the volume-weighted average. In contrast, the Curve pool’s oracle held steady, accurately reflecting the price that regular users with tight slippage tolerances would receive. Had the external protocol used Curve’s built-in oracle, this event could likely have been avoided.

Developer Guide: Integrating Curve Oracles

Because Curve’s pricing logic is embedded directly in its pools, developers gain access to a permissionless, on-chain oracle with no external dependencies or fees. The oracle updates automatically with each trade, requiring no off-chain inputs or maintenance.

Curve pools expose two key functions:

  • price_oracle() – The EMA Price: This function returns the exponential moving average, providing a smoothed price that updates with each trade. It is the recommended source for use cases involving collateral valuation, liquidations, or settlement - anywhere it is critical to have resistance to manipulation. However, it’s important that the pool’s liquidity and trading volume are quite big. Ideally larger than the protocol relying on the oracle to ensure that the oracle cannot be easily influenced relative to the value being secured.
  • last_price() – The Spot Price: This function outputs the raw result from the most recent swap. While useful for dashboards and visualizations, it is not safe for automated decision-making due to its sensitivity to individual trades.
⚠️
The price_oracle() function does not account for rates of oracleized assets such as ERC-4626 tokens (yield-bearing tokens). For pools containing these assets, developers need to manually calculate the actual price by incorporating the conversion rate. For example, if a pool contains sUSDS (a yield-bearing USDS token), the oracle returns the underlying USDS price, not the sUSDS price including accumulated yield. More here.

Developers can refer to Curve’s technical documentation or engage with the team for implementation help.


Dive into the technical Documentation or chat with Curve on Telegram about its Oracles: