By Daniel Von Fange
Translated by: angelilu, Foresight News
Yesterday, independent researcher Daniel Von Fange published an article on the X platform, revealing that Curve has the risk of oracle manipulation, and this risk is difficult to detect during an attack. Oracle manipulation behavior will cause the oracle to report incorrect data about external events or the real world, making the protocol connected to the oracle also face the risk of manipulation. Daniel Von Fange said that he has notified the relevant teams that may be affected.
Curve founder Michael Egorov responded to the issue in the community, saying that "the risk may exist in the old version of the pool. The old version of the pool is not used in crvusd, and the use of oracles is not recommended." He also confirmed that the risk disclosed by Daniel Von Fange does exist.
However, Curve contributor fiddy expressed dissatisfaction with the way this independent researcher publicly released this information without discussion, and issued a clarification, saying that the vulnerability disclosed by Daniel Von Fange had been discussed privately before, but he believed that it was costly for attackers to increase the gas fee in order to improve accuracy, and the external audit also classified this as low impact. And the vulnerability disclosed by the researcher is related to Curve's older cryptoswap algorithm, which uses the last_price price, but the newer cryptoswap-ng implementation uses the AMM state price, which can solve such problems. In addition, yAuditDAO did find some oracle errors, which are currently being fixed. No one uses these oracles, and the LPs (liquidity providers) in these stablecoin trading pools are not affected.
However, some teams have begun to adjust the protocol and enhance security based on the risks disclosed. Yearn Finance developer @storming0x also responded to the risks disclosed by Daniel Von Fange, saying that "Yearn contracts are not affected, except for one contract that uses Chainlink's redundancy mechanism to mitigate potential attack paths. Out of caution, the Yearn development team decided to redeploy a new version."
The following is the full text of Daniel Von Fange’s disclosure of the risk of price manipulation by Curve Oracles:
Over the past two weeks, I have been taking a deep dive into Curve’s price oracle and have noticed some extremely unusual behavior.
These oracles don’t work the way you think, they are easier to manipulate than expected, and can also make mistakes under normal circumstances.
Brief overview: In most pools, an attacker can manipulate Curve’s price oracle to 10x to 500x higher than normal price in just one block. And this manipulation can be hidden so that it is impossible to find signs of manipulation when viewing the pool.
There are many Curve pools, and no one can accurately count the number of code bases of different pools.
What I write may or may not apply to certain pools. Different pools have different vulnerabilities. Some pools may not have any vulnerabilities at all.
The Curve team was excellent in receiving the report, discussing it, and confirming within minutes that CrvUSD was not affected by these issues.
I also checked the ~100 contracts on mainnet that use the Curve price oracle and notified the relevant teams as appropriate.
A key issue with this vulnerability is that last_price may be miscalculated when the price is not close to 1:1 or the fee is high.
First, fees are not included in the last_price calculation, which makes the number it uses different from the actual transaction or pool balance.
The EMA price oracle is driven by last_price. When last_price is wrong, the price oracle will start moving towards the wrong target price.
In normal trading, I have seen the price oracle pinpoint a price that deviates by more than 1% from the actual current price in the pool. Worst case scenarios can be much worse (normalized prices in the chart).
Depending on the pool, this drift error may be higher or lower than the actual price.
The biggest problem is that during manipulation, the last_price error can be an order of magnitude higher than the actual manipulated price, making it much more likely that the pool oracle can be effectively manipulated.
Even a tiny transaction can correct the deviation in the last price/oracle price, leading to some absurd situations.
Due to the combined effect of large price fluctuations and last_price calculation errors, an attacker can manipulate the EMA price oracle in the next block without having to incur huge costs to maintain high prices for dozens of blocks to fight arbitrageurs.
In theory, an attacker could control the mining of two consecutive blocks, which is necessary to achieve this operation. The attacker needs to have sufficient capital to carry out this price attack, but many past attackers have tens of millions of dollars in their hands.
Next, let’s talk about common strategies for defending against Curve price oracle manipulation, and how effective they are.
Curve v1 pools have four numbers that can be used to try to detect manipulation, actual price, price oracle, last_price, and EMA price. Unfortunately, after a manipulation, a single transaction to manipulate the price_oracle price can reset all of these to the same number.
The price_scale of the Curve v2 pool is harder to manipulate than the price oracle. It changes more slowly and requires actual transaction fee costs to move. If this fast price oracle matches the slow price_scale, then things are stable, right?
No! The core attack problem is to align three numbers, the actual price, the fast oracle, and the slow scale. The actual price is easy to control because it can be manipulated instantly. The problem then becomes engineering an intersection between the other two.
The attacker briefly raises the price, then returns it to normal in the next block, and waits a few blocks to attack until the falling price oracle encounters the rising price_scale. The actual price only needs to be high for one block to be enough to disrupt the oracle, and the price_scale will follow.
Many oracles use caps that limit the price they use from the Curve oracle price to a maximum value that is 1:1. This is fine, and rules out stupidly high values. But be aware that if the asset is actually depegged, an attacker can buy the asset at a low price, and then manipulate it to appear to be repegged.
Protocols sometimes set a floor where if the Curve price oracle’s response falls below a certain percentage of the peg, it will be ignored. But if prices are ignored when an asset is truly depegged, that defeats the whole purpose of having a price oracle.
Another common strategy is to mix in prices from another AMM system. This depends a lot on the quality and manipulation characteristics of the other pool. If it has lower liquidity and is easier to manipulate, then the purpose is not achieved.
Oops + Oops = Oops.
The new Curve pools for stablecoin/stablecoin pairs internally limit last_price to 2x the 1:1 value. This prevents one-block attacks because last_price can't be pushed to stupidly high values that would overload the EMA.
But it would be wrong if the wrong assets were legally decoupled.
If you want to use Curve pools to price collateral assets, you probably shouldn’t do this.
New pools usually have higher attack costs. If the manipulated pool has a small impact on the market (perhaps just to protect the profit distribution), and the cost of simulating an attack on the pool is high, then it can be used.
Finally, the author recommends that you conduct actual attack simulations on the pools you use. Do not predict the behavior of price oracles based on assumptions or theories, but instead conduct detailed simulation tests on the pools you actually use. By simulating manipulation attacks, you can better understand how the pools perform in different situations.
Below is a chart showing the increase in Curve oracle usage over the past 90 days:
Some Curve pools have great price oracles, I couldn’t get them to behave in any weird way, they behaved exactly as expected from a well behaved EMA. Still need to check though…