Skip to content

Latest commit

 

History

History
65 lines (47 loc) · 3.91 KB

2024-01-Salty.md

File metadata and controls

65 lines (47 loc) · 3.91 KB

Salty

Contest Summary

Code under review: 2024-01-Salty (3288 nSLOC)

Contest Page: Salty-contest

Findings

[H-1] Chainlink price feed uses BTC, not WBTC. In case of depegging, oracles will become easier to manipulate.

Lines of code

https://github.com/code-423n4/2024-01-salty/blob/main/src/price_feed/CoreChainlinkFeed.sol#L15 https://github.com/code-423n4/2024-01-salty/blob/main/src/price_feed/CoreSaltyFeed.sol#L32-L41 https://github.com/code-423n4/2024-01-salty/blob/main/src/price_feed/PriceAggregator.sol#L108

Summary

Chainlink BTC price feed is BTC/USD, not WBTC/USD. In the event of WBTC depegging, the oracle's return price will deviate from its actual value. We also provide a real-life WBTC depegging event as evidence.

This alone is not enough for the price aggregator to return the incorrect price, as an adversary needs to manipulate two of three price feeds to manipulate the price. However, due to the aggregator design, we also make an argument that in case of actual depegging, the price will indeed be easier to manipulate.

Vulnerability details

According to the official Chainlink docs, there are four price feeds for BTC on Ethereum Mainnet:

  • BTC / ETH
  • BTC / USD
  • ETH / BTC
  • WBTC / BTC Based on the following observations, we believe Salty will use BTC/USD on the Chainlink price feed, instead of WBTC:

All test cases use BTC/USD feed, and nowhere in the code repo is the WBTC feed used. There is no WBTC/USD feed on Ethereum Mainnet (they are available on some other networks). Salty's Chainlink price fetcher uses only one feed for the WBTC price. At least two feeds are needed (WBTC/BTC and BTC/USD) to fetch the WBTC/USD price. Historically, WBTC has depegged down to 0.98 before, in the event of wild market swing, specifically during the LUNA crash.

Even as of time of report writing, the Chainlink feed for WBTC/BTC does not return a price of 1. Screenshot. This article explains some of the reasons of why WBTC can depeg.

Full oracle manipulation (PoC)

This alone is not enough to manipulate the oracle entirely, as Salty uses a triple-oracle setting, consisting of Uniswap V3 TWAP, Chainlink price, and Salty pool spot price:

Out of the three prices, the oracle selects the two price with the lower absolute difference. If the two chosen prices are too different, returns 0 signalling failure. Otherwise, return the average of the chosen prices. However, if the Chainlink price has already deviates, then an adversary will only have to manipulate one more oracle to manipulate the price feed.

The weaker Oracle out of the remaining two is the Salty WBTC pool spot price. Assuming WBTC has already depegged, an adversary can perform the following attack to gain profit:

  • Flash loan a large amount of WBTC from anywhere.
  • Perform a swap on the WBTC Salty pool, skewing its spot price to be closer to the Chainlink (wrong) price feed.
  • The aggregated price now reflects the BTC/USD price, instead of WBTC/USD.
  • With a deviated price, there is a lot that the attacker can do for free:
  • Liquidate positions that is actually not yet underwater, and take profit.
  • Return the flash loan amount.
  • An attacker can also take an undercollateralized position. However, this is more difficult to profit from, as it also requires rapid market swing and the lack of liquation before the position becomes insolvent. This also requires that an attacker has large enough capital.

Given the scenario where the de-peg has already occured, then this becomes more realistic.

Impact

In the event of WBTC/BTC depeg, such as rapid market swing, the price oracle will become easier to manipulate.

Given the price of BTC, even a 2% deviation can be considered large.

Recommended mitigation steps

Collect the WBTC price from two Chainlink price feeds, the BTC/USD feed and the WBTC/BTC feed, as the source of truth.

Assessed type

Oracle