In the previous audit there is an issue related to missing check if the L2 Sequencer is down and in the current version of the protocol there are checks in the ChainlinkUtil::getPrice function to confirm if the Sequencer has the correct status, but this checks are not efficient.
Link: https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/external/chainlink/ChainlinkUtil.sol#L42-L56
In the chainlink docs is written that sequencerUptimeFeed can return 0 value for startedAt if it is called during an invalid round:
Link: https://docs.chain.link/data-feeds/l2-sequencer-feeds
It is important to note that invalid round means that there was a problem updating the Sequencer's status, possibly due to network issues or problems with data from oracles, and is shown by a startedAt time of 0 and answer is 0. One of the chainlink engineers gave an additional clarification about that and it can be read in the public chainlink discord channel:
An "invalid round" means there was a problem updating the sequencer's status, possibly due to network issues or problems with data from oracles, and is shown by a startedAt time of 0. Normally, when a round starts, startedAt is recorded, and the initial status (answer) is set to 0. Later, both the answer and the time it was updated (updatedAt) are set at the same time after getting enough data from oracles, making sure that answer only changes from 0 when there's a confirmed update different from the start time. This process helps avoid mistakes in judging if the sequencer is available, which could cause security issues. Making sure startedAt isn't 0 is crucial for keeping the system secure and properly informed about the sequencer's status.
The checks in the ChainlinkUtil::getPrice function to ensure that the Sequencer's status is up are the following:
But the check for the timeSinceUp is inefficient if its called in an invalid round. In that case the startedAt will be 0 and block.timestamp - startedAt (1722184616 - 0 = 1722184616) will result in a value greater than SEQUENCER_GRACE_PERIOD_TIME that is 3600 and the code will not revert.
Also, there is already created PR about that L2 Sequencer Feed code sample does not match the recommendation from the chainlink docs:
https://github.com/smartcontractkit/documentation/pull/1995
We can have a scenario where a round begins with startedAt set to 0 and answer, the initial status, also set to 0. According to the documentation, if answer equals 0, it indicates that the sequencer is up, while a value of 1 indicates that the sequencer is down. However, in this situation, both answer and startedAt can initially be 0. These values will only be updated to reflect the correct status of the sequencer after all data has been retrieved from oracles and the update is confirmed.
The inefficient checks to confirm the correct status of the sequencer leads the getPrice function to not revert even when the sequencer uptime feed is not updated or it is called in an invalid round.
Manual Review
Add a check to ensure that startedAt is not 0:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.