LibChainlinkOracle:getEthUsdPrice
& LibChainlinkOracle:getEthUsdTwap
functions use latestRoundData
to get price of ETH/USD. ChainlinkFeedRegistry#latestRoundData
pulls the associated aggregator and requests round data from it. ChainlinkAggregators have minPrice and maxPrice circuit breakers built into them. This means that if the price of the asset drops below the minPrice, the protocol will continue to value the token at minPrice instead of it's actual value.
In LibEthUsdOracle:getEthUsdPrice
the ETH/USD price from Chainlink Oracle is also compared with ETH/USDC & ETH/USDT from Uniswap. The logic is if ETH/USD & ETH/USDC price difference is within 0.3% range then an average of these two will be returned otherwise it will do the same for ETH/USDT. If none of these is true then it will just return ETH/USD price form chainlink.
Now if price crashes hard and chainlink returns minPrice, it will obviously not satisfy both checking conditions with Uniswap. The oracle price will be returned, which will be the wrong price as compared to market.
Example:
TokenA has a minPrice of $1. The price of TokenA drops to $0.10. The aggregator still returns $1 allowing the user to borrow against TokenA as if it is $1 which is 10x it's actual value.
See the code below:
In the event that an asset crashes (i.e. LUNA) the protocol can be manipulated to give out loans at an inflated price. This can open doors for several attacks on the protocol to loose assets.
Manual Review
ChainlinkAdapterOracle should check the returned answer against the minPrice/maxPrice and revert if the answer is outside of the bounds:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.