15,000 USDC
View results
Submission Details
Severity: medium

Med - ChainlinkAdapterOracle will return the wrong price for asset if underlying aggregator hits minAnswer

Summary

Chainlink aggregators have a built-in circuit breaker if the price of an asset goes outside of a predetermined price band. The result is that if an asset experiences a huge drop in value (i.e. LUNA crash) the price of the oracle will continue to return the minPrice instead of the actual price of the asset. This would allow users to continue borrowing with the asset but at the wrong price. This is exactly what happened to Venus on BSC when LUNA imploded.

Vulnerability Details

ChainlinkAdapterOracle uses the ChainlinkFeedRegistry to obtain the price of the requested tokens.

Note:
Chainlink oracles are used as just one piece of the OracleAggregator system and it is assumed that using a combination of other oracles, a scenario like this can be avoided. However, this is not the case because the other oracles also have their flaws that can still allow this to be exploited. As an example, if the chainlink oracle is being used with a UniswapV3Oracle which uses a long TWAP then this will be exploitable when the TWAP is near the minPrice on the way down. In a scenario like that it wouldn't matter what the third oracle was because it would be bypassed with the two matching oracles prices. If secondary oracles like Band are used a malicious user could DDOS relayers to prevent update pricing. Once the price becomes stale the chainlink oracle would be the only oracle left and its price would be used.

Impact

In the event that an asset crashes (i.e. LUNA) the protocol can be manipulated to give out loans at an inflated price

Tools Used

Manual Review

Recommendations

ChainlinkAdapterOracle should check the returned answer against the minPrice/maxPrice and revert if the answer is outside of the bounds:

(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) = priceFeed.latestRoundData();
+ if (answer >= maxPrice or answer <= minPrice) revert();

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.