No Circuit-Breaker checks in `ChainlinkOracle.sol`
Closed this issue · 0 comments
c4-bot-7 commented
Lines of code
Vulnerability details
Vulnerability Detail
The ChainlinkOracle contract does not implement checks for minimum and maximum prices returned by Chainlink price feeds. This leaves the contract vulnerable to scenarios where the actual market price of an asset falls below the minimum price that Chainlink's feed will report, potentially leading to significant financial losses for protocols relying on this oracle.
Impact
- Asset Mispricing: During extreme market events (flash crashes, depegging, or bridge compromises), the oracle may report incorrect prices, significantly higher than the actual market value.
- Exploitation Potential: Attackers could exploit this mispricing by: a) Purchasing the asset at a very low price from decentralized exchanges. b) Depositing the asset into lending/borrowing platforms using this oracle. c) Borrowing against the asset at the inflated price reported by the oracle.
- Protocol Drain: This attack vector could lead to substantial drainage of value from lending/borrowing platforms relying on this oracle for price data.
- Loss of User Funds: Users of protocols implementing this oracle could suffer significant financial losses due to incorrect liquidations or unfair loan terms based on inaccurate price data.
Proof of Concept
The vulnerability is evident in the _fetchAndValidate function:
function _fetchAndValidate(address token) internal view returns (bool isValid, uint256 price) {
Oracle memory oracle = oracles[token];
try AggregatorV3Interface(oracle.aggregator).latestRoundData() returns (
uint80 /*roundId*/,
int256 answer,
uint256 /*startedAt*/,
uint256 updatedAt,
uint80 /*answeredInRound*/
) {
isValid = (answer > 0 && block.timestamp - updatedAt <= oracle.stalePeriod);
return (isValid, wdiv(uint256(answer), oracle.aggregatorScale));
} catch {
// return the default values (false, 0) on failure
}
}
This function only checks if the price is positive and not stale. It does not implement any checks for minimum or maximum prices, leaving it vulnerable to the described attack scenario.
Tools Used
Manual code review
Recommended Mitigation Steps
- Implement Min/Max Price Checks: Add minimum and maximum price thresholds for each asset in the Oracle struct:
struct Oracle {
AggregatorV3Interface aggregator;
uint256 stalePeriod;
uint256 aggregatorScale;
uint256 minPrice;
uint256 maxPrice;
}
Modify the _fetchAndValidate function to include these checks:
isValid = (answer > 0 &&
block.timestamp - updatedAt <= oracle.stalePeriod &&
uint256(answer) >= oracle.minPrice &&
uint256(answer) <= oracle.maxPrice);
Assessed type
Oracle