15,000 USDC
View results
Submission Details
Severity: medium
Valid

Chainlink’s latestRoundData Might Return Stale Results

Summary

The OracleLib library is utilized to verify the freshness of data fetched from the Chainlink Oracle. However, a critical oversight in the staleCheckLatestRoundData function can potentially lead to the usage of stale price data. This issue poses a risk of financial losses and incorrect calculations for users relying on the protocol using this library.

Vulnerability Details

The OracleLib library provides a function called staleCheckLatestRoundData, intended to check for stale price data from the Chainlink Oracle. The function calls the latestRoundData API to retrieve the most recent price data, including the round ID, answer, timestamps, and related information.

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);
}

The issue with this function is that it solely relies on checking the updatedAt timestamp to determine if the price data is stale. It fails to perform other crucial checks, such as ensuring that the answer is greater than zero, validating if the answeredInRound corresponds to the round ID, and verifying if the timestamp is not zero, indicating a complete round.

Impact

By not verifying for stale prices properly, the function may return outdated and incorrect price data to the protocol using OracleLib. Users interacting with the protocol may make decisions based on stale data, leading to erroneous valuations and potential financial losses.

Tools Used

Manual

Recommendations

To resolve this vulnerability, the staleCheckLatestRoundData function must be updated to include additional checks for stale data. By implementing the following checks, the function will ensure that only up-to-date and valid price data is utilized:

function staleCheckLatestRoundData(AggregatorV3Interface priceFeed)
internal
view
returns (uint80, int256, uint256, uint256, uint80)
{
(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
priceFeed.latestRoundData();
// Check for a non-zero answer
require(answer > 0, "Chainlink price <= 0");
// Check for non-stale price
require(answeredInRound >= roundId, "Stale price");
// Check for a complete round
require(updatedAt != 0, "Round not complete");
uint256 secondsSince = block.timestamp - updatedAt;
if (secondsSince > TIMEOUT) revert OracleLib__StalePrice();
return (roundId, answer, startedAt, updatedAt, answeredInRound);
}

By incorporating these checks, the function will effectively prevent the usage of stale price data and safeguard the protocol from potential financial losses and incorrect valuations. Additionally, it is advisable to undergo a thorough smart contract audit by security experts before deploying any financial protocols to production environments.

Support

FAQs

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