DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: medium
Valid

ChainlinkUtils.getPrice consume data returned in invalid rounds

Summary

ChainlinkUtil.getPrice implements sequencerUptime feed checks to ensure the L2 sequencer is up and runing. But these checks are not implemented corectly. Callers may consume stale or incorrect price data.

Vulnerability Details

From Chainlink Documentation:

tartedAt: This timestamp indicates when the sequencer changed status. This timestamp returns 0 if a round is invalid.

When using Chainlink's sequencerUptimeFeed.latestRoundData() function, the startedAt value will be 0 if the update round is invalid or incomplete. However, the getPrice() function does not verify whether startedAt is 0.

If the round is invalid, the getPrice() cannot detect that the sequencer has just come back up after an outage and is still in the grace period. Consequently, a caller might inadvertently consume stale or incorrect price data.

//ChainlinkUtil.sol
function getPrice(
IAggregatorV3 priceFeed,
uint32 priceFeedHeartbeatSeconds,
IAggregatorV3 sequencerUptimeFeed
)
internal
view
returns (UD60x18 price)
{
uint8 priceDecimals = priceFeed.decimals();
// should revert if priceDecimals > 18
if (priceDecimals > Constants.SYSTEM_DECIMALS) {
revert Errors.InvalidOracleReturn();
}
if (address(sequencerUptimeFeed) != address(0)) {
try sequencerUptimeFeed.latestRoundData() returns (
uint80, int256 answer, uint256 startedAt, uint256, uint80
) {
bool isSequencerUp = answer == 0;
if (!isSequencerUp) {
revert Errors.OracleSequencerUptimeFeedIsDown(address(sequencerUptimeFeed));
}
// @audit when startedAt is 0 that round is invalid
uint256 timeSinceUp = block.timestamp - startedAt;
if (timeSinceUp <= Constants.SEQUENCER_GRACE_PERIOD_TIME) {
revert Errors.GracePeriodNotOver();
}
} catch {
revert Errors.InvalidSequencerUptimeFeedReturn();
}
}
//...
}

Chainlink's sample code does not implement this check. For details please see here .

Impact

When the sequencer comes back up after an outage, startedAt returned by latestRoundDatawill be 0 for invalid rounds. Callers can consume stale or incorect price data.

Tools Used

Manual review

Recommendations

Revert when startedAt returned by sequencerUptimeFeed.latestRoundData() is 0.

Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Inadequate implementation of sequencer check

Support

FAQs

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