DeFi Security Lecture 7 —Price Oracle Manipulation

Beaver Finance
beaver-smartcontract-security
14 min readJan 13, 2022

On 31st December 2021, Vesper Finance, a yield optimization protocol, tweeted that its №23 lending pool — “Vesper Lend beta” launched on the interest rate agreement with Fuse, has been attacked again.

The attacker had manipulated an oracle and depleted the beta test borrowing pool of DAI, ETH, WBTC, and USDC of approximately $1 million. This was not an attack on the Vesper contract, no VSP or VVSP was threatened. Following the attack, Vesper quickly paused the lending of all tokens in Beta Vesper Lend Rari Pool #23 and switched the oracle from VUSD/USDC to VUSD/ETH (Uni v3). Prior to this incident, the Vesper Lend loan pool on Rari Fuse was attacked once before, and the attacker had made a profit of 3 million US dollars.

Let’s begin with the basics,

What is an oracle?

An oracle is an intermediary bridging between real-world (off-chain) services and blockchain (on-chain) protocols. Oracles retrieve off-chain data and publish this data on the blockchain to be then used by smart contracts.

They also forward information and instructions from smart contracts to external systems off-chain. Additionally, oracles must ensure accurate data and remain resistant to manipulation.

On-chain oracles vs. Off-chain oracles

Off-chain data is generally slower to respond to price fluctuations, a feature that can be good or bad depending on what you want to use it for. However, it usually requires a small number of sophisticated users to push on-chain data, so you have to trust them into perpetually acting in good faith.

On-chain data does not require any intermediary involvement and is always up-to-date, but that means it can be easily manipulated by attackers, which can have disastrous consequences.

DeFi oracles can be divided into two types: on-chain and off-chain.

The price of the former comes from on-chain data sources (such as Uniswap), while the price of the latter comes from off-chain sources. In addition to this, oracles can be further divided into centralized and decentralized, the former’s data is verified by a single operator (such as Compound), and the latter’s data is verified by independent operators (such as MakerDAO).

On-chain centralized oracles

This type of oracle uses on-chain resources such as DEXs to determine the price of an asset. However, only a central authority can trigger oracles to read data from on-chain sources. Like off-chain centralized oracles, this type of oracle needs to be updated quickly, dYdX uses this type of oracle.

On-chain decentralized oracles

This type of oracle uses on-chain resources to determine the price of an asset, and it can be updated by anyone. There may be some sanity checks to make sure the price doesn’t fluctuate too much. DDEX uses this type of oracle for DAI, and bZx uses this type of oracle for all assets.

Off-chain decentralized oracles

This type of oracle accepts new prices from multiple off-chain sources and combines these values through a mathematical function to derive an average. In this model, multi-signature wallets are typically used to manage the list of authorized sources.

Maker and Chainlink use this type of oracle for ETH and other assets.

Off-chain centralized oracles

This type of oracle simply accepts new prices from an off-chain source, usually an account controlled by the project, due to the need to update oracles with new exchange rates quickly. There may be some sanity checks to make sure the price doesn’t fluctuate too much. Compound Finance and Synthetix primarily use this type of oracle for most assets.

Top Oracles Currently

1. Chainlink Oracle (Hybrid Decentralization)

Chainlink uses a decentralized oracle network of at least seven independent node operators. Node operators are responsible for retrieving off-chain data and feeding it back to the requesting smart contract. Node operators provide data in two ways. The first is that when the node operator is an entity independent of the data source, the data will be provided through the Chainlink standard API model. Prices provided by node operators are aggregated on-chain by FluxAggregator into a single response and used to update the on-chain price reference source. These updates occur when the price deviates from off-chain by more than a contract deviation threshold or is accompanied by a minimal time-based update, the heartbeat threshold.

The second mode is the Origin Signed Data Model, which occurs when a data provider operates its own node. The data provided will be signed with a unique private key and delivered directly to the smart contract, making the data feed Sybil resistant. Additionally, each node operator submits data from a public address, and nodes can be evaluated against their reputation, sometimes referred to as “security through transparency”.

2. Uniswap v3 Oracle (chain decentralization)

Uniswap v2 attempts to eliminate the manipulation of v2 price oracles by using Time Weighted Average Price (TWAP). The price of the last transaction in the previous block is recorded at the beginning of the block before any transactions take place. The cumulative price at the end of the block, which is the sum of Uniswap prices per second, is added to the end of the block, allowing users to calculate an accurate TWAP. TWAPs increase the cost of manipulation, as this cost increases linearly with Uniswap’s liquidity and the length of TWAP’s time.

Uniswap v3 is expected to launch on May 5 for Ethereum and on May 12 for Optimism. The team claims that it will utilize the same time-weighted average pricing (TWAP) oracle as v2, with the following upgrades:

Accumulator checkpoints are internal, allowing external contracts to calculate the most recent period of on-chain TWAP without storing previous accumulator values.

V3 will track the logarithmic sum of prices where users calculate the geometric mean TWAP, while V2 will track the cumulative sum of prices where users calculate the arithmetic mean TWAP.

Liquidity accumulators will also be tracked, so users can decide which pool has the most reliable TWAP.

Uniswap v3 users can call the accumulator and take the values ​​of t1 and t2 to calculate the weighted geometric average price by the following formula.

New improvements to TWAP make the calculation of moving averages cheaper and allow for outlier analysis. Additionally, liquidity accumulators allow smart contracts to determine which oracles are trustworthy based on their liquidity. This will reduce the volatility of the Uniswap price oracle and reduce mispricing.

3. Coinbase Oracle (decentralized chain)

Coinbase price oracles use the Coinbase Pro API as a source of price data. Anyone can post prices on-chain because the data is signed with Coinbase’s private key. Users can use Coinbase’s public key to verify the authenticity of the data.

Additionally, Coinbase has implemented an off-chain filter to filter out extreme data points that deviate from the expected range of price volatility. It also uses Compound’s open oracle’s ‘anchor’ contract as an on-chain check. If the price of the oracle is too far from the peg, it will be rejected and not pushed to the blockchain.

Compound uses Coinbase’s price oracle as a reporter in its View Contract. And Coinbase’s price is anchored by Uniswap to generate a powerful data feed.

Price Oracles — Use Cases

#1 - Low-collateralized loan liquidation — Lending protocols (i.e. Maker, Compound, Cream, and Aave) rely on price oracles to decide when to liquidate a user’s loan. If a user’s collateral falls below a certain threshold, the account can be liquidated.

#2 - Derivatives Pricing — Derivatives platforms (i.e. Synthetix, Perpetual, Hegic) use oracles to calculate the value of crypto assets, including options, futures, and synthetic assets.

#3 - Index Pricing — Index platforms such as Set use oracles to retrieve the prices of index components.

#4 - Insurance Protocols — Insurance protocols such as Nexus Mutual utilize oracles to validate claims before reporting and publishing them to the blockchain.

#5 - Prediction Markets — Decentralized prediction markets (ie August and Gnosis) rely on oracles for off-chain event settlement.

What are the different ways in which oracles can be manipulated?

1. Oracle oracle failure (random attack)

Synthetix is an Ethereum-based derivatives liquidity protocol that allows users to synthesize other monetary assets. To achieve this, Synthetix (at the time) relied on a custom off-chain price feed mechanism to calculate the total price from a set of secret price feeds and publish it on-chain at regular intervals. Then, based on the calculated price, users are allowed to trade long or short against the asset.

On June 25, 2019, one of the price feed channels that Synthetix relied on incorrectly reported the KRW price, quoting 1,000 times higher than the real exchange rate, plus an additional error in the price oracle system. This price was accepted by the system and published on the chain. A trading bot quickly made buys and sells on that inaccurately reported sKRW market.

2. Use flash loans to manipulate the price of AMM

If an attacker is able to control the price oracle, it is easy to perform an exploit. This is what the entire process looks like:

  • The attacker adjusts the borrowed token price upward (or the collateral price downward);
  • The price liquidates the collateral.

This is often the case with on-chain centralized oracles, decentralized exchanges, where attackers can leverage flash loans to manipulate the price of AMMs to change the spot price of a token before the lender smart contract looks up the token.

What happens if malicious users trade before and after lending from your platform?

  1. Before the user took out a loan, they bought 5,000 ETH for $2,000,000.
  2. The Uniswap exchange now calculates the price as 1 ETH = $1,733.33.
  3. Now, their 375 ETH can be used as collateral for their borrowed assets worth up to $433,333.33.
  4. In the end, they exchanged 5,000 ETH back to the original $2,000,000, thus resetting the price.
  5. The end result is that your lending platform only allows users to borrow an additional $333,333.33 without providing any collateral.

3. Centralized exchange leaks

If the private key from the exchange account is compromised, an attacker can simply mint collateral tokens to steal all the funds. They can also borrow new, diluted collateral tokens until the oracle reflects the new price.

4. Arbitrage

For example, Chainlink updates the Dai contract every 24 hours, or when the price changes by 2%. The price of Dai can be set between $0.97 and $1.03. It is still possible to suffer losses when the price of Dai is manipulated to fluctuate within a 2% range.

Real-world examples of Oracle Attacks

Case 1: Synthetix MKR Price Manipulation

In December 2019, Synthetix was attacked again due to price oracle manipulation. Notably, this time it crosses the barrier between on-chain price data and off-chain price data.

The attacker made some very suspicious transactions against sMKR and iMKR (inverse MKR). The attacker first buys sMKR to go long MRK, then buys a large amount of MKR from the Uniswap ETH/MKR pair, after waiting for a while, the attacker sells their sMKR for a short iMKR position, and sells their MKR back to Uniswap , keep repeating this process.

The logic behind this operation is that the attacker trades through Uniswap, which allows them to move the price of MKR on Synthetix at will. The underlying reason is that the off-chain price feed that Synthetix relies on actually depends on the on-chain price of MKR, and MKR does not have enough liquidity for arbitrageurs to set the market price to the best state.

This incident illustrates that even if you think you are using off-chain price data, you may still be using on-chain price data, and you may still be exposed to the complexities of using that data.

Case 2: bZx hacking incident

In February 2020, bZx was hacked twice consequently in a span of a few days and lost about $1 million, here we only look at the second attack.

In the second attack incident, the attacker first purchased almost all sUSD on the Kyber platform with ETH, and the price of sUSD increased for a short time. Then, the attacker himself purchased the second batch of sUSD from Synthetix and stored it in bZx superior. Using these sUSD as collateral, the attacker borrowed the maximum amount of ETH allowed by the bZx platform.

Finally, the attacker sells the sUSD back to the Kyber platform.

If you’re careful enough, you’ll realize that this is essentially the same low-collateralization attack, just using different collateral and a different decentralized exchange.

Case 3: yVault Vulnerability

On July 25, 2020, yEarn reported a bug with their newly launched yVault contract.

The yVault system allows users to deposit tokens to earn income without having to manage it themselves. Internally, the vault tracks the total issuance of yVault tokens as well as the total amount of underlying tokens deposited. The value of a single yVault token is derived from the ratio of tokens minted to tokens deposited. All revenue earned by the vault is distributed to all issued yVault tokens and, therefore, to all yVault token holders.

The first yVault allows users to earn USDC yields by providing liquidity to the Balancer MUSD/USDC pool. When users provide liquidity to the Balancer pool, in return, they receive BPT tokens, which can be exchanged for a portion of the pool. Therefore, yVault calculates the value of its holdings based on the amount of MUSD/USDC that can be redeemed with its BPT.

This seems to be the correct way to implement it, but unfortunately, the same principle as given earlier — the state of the Balancer liquidity pool during transactions is not stable and cannot be trusted. In this case, due to the bonding curve chosen by the Balancer, the user will not get a 1:1 exchange rate when switching from USDC to MUSD, and will in fact leave some MUSD in the pool. This means that the value of BPT can be temporarily inflated, which allows attackers to manipulate the price at will and subsequently drain the vaults of liquidity.

Case 5: Harvest Finance Attack

On October 26, 2020, an unknown user hacked into Harvest Finance’s liquidity pool, using a technique you might have guessed by now.

I’ll briefly summarize it here: the attacker executes a trade that drives down the price of USDC in the Curve pool, enters the Harvest pool at this lower price, and then reverses the previous transaction to restore USDC price and exit the Harvest pool at a higher price. This ultimately resulted in over $33 million in user losses.

How To Prevent Oracle Manipulation?

#1 - Don’t jump into a market with insufficient depth

Like jumping into the shallows of a swimming pool, jumping into a market of insufficient depth is painful and has the potential to cause significant damage that could change your life forever.

Therefore, before considering the specific complex price oracles to use, please consider whether the liquidity of the token has sufficient liquidity to match your platform.

#2 - Introduce artificial delays into decentralized oracles

The problem in relying on on-chain data oracles can be simply summed up as the timeliness of oracles is too strong. That being the case, why not introduce a little artificial delay? Write a contract that updates itself with the latest price from a decentralized exchange like Uniswap, but only when requested by a few privileged users. Now even if an attacker can manipulate the price, they can’t get your protocol to actually use it.

This approach is really simple to implement and works quickly, but has some drawbacks — you may not be able to update prices as quickly as you would like when the blockchain is congested, and you are still vulnerable to sandwich attacks ). Plus, now your users need to trust that you’re really going to keep prices updated.

Manipulating price oracles is a time-sensitive operation as arbitrageurs are always watching and hoping for an opportunity to optimize any suboptimal market. If attackers want to minimize risk, they will want to complete the two transactions needed to manipulate the price oracle in a single transaction, so that no arbitrageurs jump in the middle. As a protocol developer, if your system supports it, you may only need to increase the delay of at least 1 block for the time interval between users entering and leaving the system.

Of course, this may affect composability, and miner-trader cooperation is increasing. In the future, bad actors may conduct price oracle manipulation across multiple transactions, knowing that the miners they work with will guarantee that no one can jump in the middle and get a cut of their earnings.

#3 - Don’t use on-chain decentralized oracles without some kind of validation

Due to the nature of on-chain decentralised oracles, make sure the exchange rate returned is verified, either by accepting the order (thus offsetting any gains that may have been realised) or by comparing the exchange rate to a known normal exchange rate (in the case of DAI).

Suppose you want to find the price of WBTC in ETH:

A seemingly obvious solution would be to use the Uniswap V2 pair for ETH/WBTC, grab the ETH and WBTC balances, and then separate the two. However, you have just calculated the spot price, which can be easily manipulated by an attacker by buying or selling in the pool.

#4 - Time Weighted Average Price (TWAP)

Uniswap V2 introduces a TWAP oracle for use by on-chain developers. There are documents detailing the specific security guarantees provided by the oracle. Generally speaking, for large asset pools without long-term on-chain congestion, TWAP oracles are highly resistant to oracle manipulation attacks. However, due to the nature of its implementation, it may not be responsive enough in times of high market volatility and is only applicable to token assets that already have liquidity on-chain.

#5 - M-of-N reporter mechanism

Sometimes people say, if you want to do something well, do it yourself. What if you call up N trusted friends and ask them to submit on-chain prices as they see fit, and the best M answers converge into the current price?

Many large projects are using this approach today. Maker runs a set of price feeds operated by trusted entities, Compound creates Open Oracle and has reporters such as Coinbase, and Chainlink aggregates price data from Chainlink operators and exposes it on-chain.

Just remember that if you choose to use one of these solutions, you’ve now delegated trust to a third party, and your users must do the same. Requiring nodes to manually post updates on-chain also means that price updates may not arrive in time during times of high market volatility and on-chain congestion.

Summing up

There are generally two ways for the price oracle to obtain the price information data source. One way is to apply for the exchange to obtain the price API, you can obtain the existing off-chain price data and bring it to the chain; the other way, you need to obtain the real-time price through the calculation of the on-chain exchange.

Off-chain or on-chain oracles have their own advantages and disadvantages. The main problem with on-chain oracles is that they are easily manipulated. For example, on-chain oracles can be combined with flash loans to leverage protocols such as security incidents on Harvest Finance (October 2020), yVault (July 2020), and bZx (February 2020). These vulnerabilities have led many protocols to integrate off-chain or hybrid price oracles in their smart contracts to reduce the likelihood of oracle manipulation.

Beaver Finance team up with experienced security experts on building our system and would continuously share our findings on DeFi security topics.

Stay Alert, Stay Safe!

Reference:

1,https://www.gemini.com/cryptopedia/crypto-oracle-blockchain-overview#section-blockchain-oracles-providers-of-external-data

2,https://arxiv.org/pdf/2005.04377.pdf

--

--

Beaver Finance
beaver-smartcontract-security

Beaver Finance is a Single-Asset Intelligent Yield Enhancing platform with the Option-based cutting-edge hedging solution for Impermanent Loss.