The protocol's Sequencer status validation in KeeperProxy
contract lacks a check for "invalid rounds".
"Invalid round" is described to mean there was a problem updating the sequencer's status, possibly due to network issues or problems with data from oracles.
According to Chainlink documentation , when startedAt
returns 0, it indicates an invalid round where the Sequencer's status wasn't properly updated:
The current implementation only checks if answer == 0 but misses the validation of startedAt
, which could allow operations during network issues or oracle data problems.
As startedAt
will be 0, the arithmetic operation block.timestamp - startedAt
will result in a value greater than GRACE_PERIOD_TIME
(which is hardcoded to be 3600). I.e., block.timestamp = 1739442308
, so 1739442308 - 0 = 1739442308 which is bigger than 3600. The code won't revert.
Imagine a scenario where a new round begins: initially, startedAt
is set to 0
, and answer
is also 0
. According to the documentation, if answer = 0
, it indicates that the sequencer is up, whereas if answer = 1
, it means the sequencer is down. However, in this case, both answer
and startedAt
can initially be 0
until all data is retrieved from the oracles and the update is confirmed, at which point these values are set correctly to reflect the actual status of the sequencer.
From this, it follows that startedAt
is a crucial second parameter that should be considered when checking whether the sequencer is up, down, or correctly updated. The checks in KeeperProxy::_validatePrice
allow for successful calls even in an invalid round, as reverts do not occur if answer == 0
and startedAt == 0
. This effectively defeats the purpose of having a sequencerFeed
check, which is meant to determine whether the sequencer on L2 is up, down, active, or if its status has actually been confirmed.
Inadequate checks to confirm the correct status of the Sequencer in KeeperProxy
contract will cause _validatePrice()
to not revert even when the sequencer uptime feed is not updated or is called in an invalid round.
Add invalid round check:
startedAt is only 0 when contract is not initialized on Arbitrum, but it is already initialized on Arbitrum. startedAt is sufficient for the protocol, it does not need roundID. Current documentation of Chainlink does not have this sentence: “This timestamp returns `0` if a round is invalid.“
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.