The OracleLib contract fetches the latest round data from a Chainlink oracle. However, the contract doesn't check for the completeness of the latest round. This could potentially result in the use of incomplete or stale prices, which might disrupt functions relying on accurate price data and can lead to incorrect calculations or operations, and in certain scenarios, loss of funds.
Vulnerability Details
The OracleLib contract retrieves the latest round data from a Chainlink oracle using the latestRoundData() function. Although the contract checks if the data is older than a predefined TIMEOUT, it doesn't check for the completeness of the latest round. According to Chainlink's documentation, latestRoundData() doesn't error out if no consensus has been reached for the latest round; instead, it returns 0 or data from the previous round.
In this function, priceFeed is a reference to a Chainlink oracle. The function retrieves the latest price and timestamp and checks if the data is stale. However, it doesn't check if the latest round of data is complete.
Impact
Functions that rely on accurate price data might not work as expected if the data is incomplete or stale.
Tools Used
Manual review
Recommendations
Check for round completeness: when calling latestRoundData(), check whether the latest round of data is complete. If it isn't, handle this situation appropriately to prevent the use of incomplete or stale price data.
Here is a code example:
function staleCheckLatestRoundData(AggregatorV3Interface priceFeed)
public
view
returns (uint80, int256, uint256, uint256, uint80)
{
(uint80 roundId, int256 price,, uint256 updatedAt, uint80 answeredInRound) =
priceFeed.latestRoundData();
// Check if the latest round of data is complete
require(answeredInRound >= roundId, "Round not complete");
uint256 secondsSince = block.timestamp - updatedAt;
if (secondsSince > TIMEOUT) revert OracleLib__StalePrice();
return (roundId, price, startedAt, updatedAt, answeredInRound);
}
latestRoundData()
does not check round completenessSeverity
Medium Risk
Relevant GitHub Links
https://github.com/Cyfrin/2023-07-foundry-defi-stablecoin/blob/main/src/libraries/OracleLib.sol#L21-#L33
Summary
The
OracleLib
contract fetches the latest round data from a Chainlink oracle. However, the contract doesn't check for the completeness of the latest round. This could potentially result in the use of incomplete or stale prices, which might disrupt functions relying on accurate price data and can lead to incorrect calculations or operations, and in certain scenarios, loss of funds.Vulnerability Details
The
OracleLib
contract retrieves the latest round data from a Chainlink oracle using thelatestRoundData()
function. Although the contract checks if the data is older than a predefinedTIMEOUT
, it doesn't check for the completeness of the latest round. According to Chainlink's documentation,latestRoundData()
doesn't error out if no consensus has been reached for the latest round; instead, it returns 0 or data from the previous round.In this function,
priceFeed
is a reference to a Chainlink oracle. The function retrieves the latest price and timestamp and checks if the data is stale. However, it doesn't check if the latest round of data is complete.Impact
Functions that rely on accurate price data might not work as expected if the data is incomplete or stale.
Tools Used
Manual review
Recommendations
Check for round completeness: when calling
latestRoundData()
, check whether the latest round of data is complete. If it isn't, handle this situation appropriately to prevent the use of incomplete or stale price data.Here is a code example: