Summary
Can use stale prices
Vulnerability Details
OracleLib uses Chainlink’s latestRoundData
, but there is no check if the return value indicates stale data.
function staleCheckLatestRoundData(AggregatorV3Interface priceFeed)
public
view
returns (uint80, int256, uint256, uint256, uint80)
{
(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
priceFeed.latestRoundData();
uint256 secondsSince = block.timestamp - updatedAt;
if (secondsSince > TIMEOUT) revert OracleLib__StalePrice();
return (roundId, answer, startedAt, updatedAt, answeredInRound);
}
https://github.com/Cyfrin/2023-07-foundry-defi-stablecoin/blob/d1c5501aa79320ca0aeaa73f47f0dbc88c7b77e2/src/libraries/OracleLib.sol#L21-L33
It also doesn't check return value at the caller of OracleLib.staleCheckLatestRoundData
function.
(, int256 price,,,) = priceFeed.staleCheckLatestRoundData();
https://github.com/Cyfrin/2023-07-foundry-defi-stablecoin/blob/d1c5501aa79320ca0aeaa73f47f0dbc88c7b77e2/src/DSCEngine.sol#L345
(, int256 price,,,) = priceFeed.staleCheckLatestRoundData();
https://github.com/Cyfrin/2023-07-foundry-defi-stablecoin/blob/d1c5501aa79320ca0aeaa73f47f0dbc88c7b77e2/src/DSCEngine.sol#L363
Impact
This could lead to stale prices according to the Chainlink documentation
Tools Used
vscode
Recommendations
Add checks on the return data with proper revert messages if the price is stale or the round is uncomplete.
(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
priceFeed.latestRoundData();
require(answeredInRound >= roundId, "Stale price");
require(updatedAt != 0, "Round not complete");
require(answer > 0,"Chainlink answer reporting 0");