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

Inadequate Sequencer Uptime Check in `getPrice` Function Allows Use of Incorrect Price Data

Summary

The getPrice() function in the ChainlinkUtil library has inadequate checks for the sequencer uptime feed, potentially allowing it to pass even when the sequencer is in an invalid state.

Vulnerability Details

The getPrice() function includes checks to verify the status of the sequencer on an L2 network. However, these checks do not correctly handle the case where the startedAt timestamp is 0, which can occur during an "invalid round" as per Chainlink documentation.This can lead to the function not reverting as expected, thereby allowing potentially incorrect price data to be used.

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));
}
uint256 timeSinceUp = block.timestamp - startedAt;
if (timeSinceUp <= Constants.SEQUENCER_GRACE_PERIOD_TIME) {
revert Errors.GracePeriodNotOver();
}
} catch {
revert Errors.InvalidSequencerUptimeFeedReturn();
}
}

The check if (block.timestamp - startedAt <= Constants.SEQUENCER_GRACE_PERIOD_TIME) will not revert if startedAt is 0, because the arithmetic operation block.timestamp - startedAt will result in a value greater than Constants.SEQUENCER_GRACE_PERIOD_TIME. For example, if block.timestamp is 1719739032, the calculation 1719739032 - 0 will be 1719739032, which is much larger than the grace period time (typically 3600 seconds). Therefore, the code will not revert, allowing the function to proceed even during an invalid round.

Impact

The function may not revert as expected when the sequencer uptime feed is not updated or is called in an invalid round. This can lead to the use of incorrect price data, potentially causing financial losses or incorrect contract behavior.

Tools Used

Manual Review

Recommendations

Add a Check for startedAt == 0:

if (address(sequencerUptimeFeed) != address(0)) {
try sequencerUptimeFeed.latestRoundData() returns (
uint80, int256 answer, uint256 startedAt, uint256, uint80
) {
++ if (startedAt == 0) {
revert Errors.InvalidSequencerUptimeFeedReturn();
}
bool isSequencerUp = answer == 0;
if (!isSequencerUp) {
revert Errors.OracleSequencerUptimeFeedIsDown(address(sequencerUptimeFeed));
}
uint256 timeSinceUp = block.timestamp - startedAt;
if (timeSinceUp <= Constants.SEQUENCER_GRACE_PERIOD_TIME) {
revert Errors.GracePeriodNotOver();
}
} catch {
revert Errors.InvalidSequencerUptimeFeedReturn();
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months 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.