Verification checklist
- In one eth_call, read the sequencer feed's answer and startedAt, and the price feed's answer and updatedAt.
- answer 0 means the sequencer is up. answer 1 means it is down. Do not copy 0 as downtime.
- Use the grace period G from the consumer contract. If answer is not 0, or seconds since recovery are at or below G, do not call the price usable, however fresh updatedAt is.
- Only after the grace period passes, run the heartbeat check. The two clocks do not stand in for each other.
1. updatedAt is the price clock; sequencer status is another
The usual sentence in a note is “updatedAt is 12 seconds old, so the feed is fresh.” On Ethereum mainnet, the next step is a heartbeat comparison. On an L2 with a sequencer, an aggregator that can update is not the same thing as a consumer that is allowed to accept the price. Chainlink's L2 sequencer uptime feeds split the read in two: check that the sequencer is up, wait out a grace period after it recovers, and only then read the price.
This is not the site's oracle-delay note. That one asks how old the price round itself is, and what window a manipulator gets from a few blocks of lag. This one assumes updatedAt is already fresh and asks whether the grace period still blocks it. It is not the circuit-breaker note either: that one asks whether a sharp deviation pauses the feed. Here the price need not have moved at all, and it can still be unusable. It is also not the note on a wallet tick versus L1 finality. That one places a transaction on a confirmation clock. This one asks whether a consumer may adopt this price round.
2. A worked example: the price is 12 seconds old, and 45 minutes of grace remain
Suppose the consumer sets the grace period G to 3600 seconds, the same constant as Chainlink's sample. At one timestamp the sequencer answer is 0 and startedAt is 900 seconds ago, so the sequencer has been back for 15 minutes. The price feed's updatedAt is 12 seconds ago and the heartbeat is 3600 seconds, so the age is 12/3600 of the heartbeat. On the price round alone, the note would say “fresh.” Seconds since recovery, 900, are at or below 3600, so the sample rejects the price. A researcher who books that price into a liquidation or a net-asset value fails the screen. The table is entirely hypothetical.
| Field | Teaching value | Reading |
|---|---|---|
| Sequencer answer | 0 | Up, not down |
| Seconds since recovery | 900 | Now minus startedAt |
| Grace period G | 3600 seconds | From the consumer, not the panel |
| 900 against G | 900 ≤ 3600 | Grace still open; price not usable |
| Price updatedAt | 12 seconds ago | Looks fresh |
| Against the heartbeat | 12 / 3600 | Heartbeat passes; it does not override grace |
Twelve seconds does not mean the feed is broken. After the sequencer returns, the aggregator can write a new round while the pipeline still holds state from the outage. The grace period separates “the round is new” from “the round may be used.” The downtime direction is stricter: if answer is 1, an updatedAt of 30 seconds still does not make the price usable. Zero and one mean the reverse of a casual boolean. Invert them once and the column flips sign.
3. The grace period lives in the consumer, not on the price panel
The status feed returns its latest round. It does not enforce the grace period for a lending market or a perpetual. The sample test is: reject when answer is not 0; when answer is 0, compute block.timestamp - startedAt and reject when that is at or below G. G is the caller's constant. One protocol uses 3600, another 1800 or 7200. The note has to read that contract. The documentation sample is not a fact about every deployment.
The OP Stack outages page and Arbitrum's sequencer page both treat the sequencer as the entry for transactions onto the L2. When it stops, user transactions do not get in, but storage already on the chain can still be read. “The RPC still returns a price” and “the spec says that price is usable” can both be true at once. On Arbitrum, startedAt of 0 has a further meaning: the uptime contract is not initialized yet. Chainlink says that zero appears only in that uninitialized phase. Other L2s set startedAt to the block timestamp at construction. A zero is uninitialized. Do not treat it as “just recovered, so the grace period has barely started,” and do not treat it as a sequencer that has been up for a long time.
If the consumer never reads the sequencer feed, that absence is the finding. The price round can be fresh while the second clock the sample requires is missing. Do not write “checked per the Chainlink sample.” Write “this contract does not implement the sequencer check.” If it implements a different G, record that G and compare with at-or-below against that number.
4. A screen: while grace is open, a fresh updatedAt is not “usable”
The teaching screen is ordered, and steps cannot be skipped. First, if answer is not 0, the price is not usable. Second, if answer is 0 and seconds since recovery are at or below the consumer's G, the price is not usable. Third, only after both pass, compare price age with the heartbeat; age above the heartbeat is a separate kind of staleness. When the first two fail, a pretty heartbeat does not change the result. The inequality matches the sample's at-or-below test. It is not a made-up ratio. If a protocol stores a different G, the threshold changes with it. The direction of the test does not.
The screen does not say whether a transaction is finalized on L1, and it does not say whether a deviation will trip a circuit breaker. Finality is the transaction's clock. A breaker is a deviation switch. The heartbeat is the age of the price round. This note only asks whether the spec allows this price to be adopted now. Passing once does not make the next hour usable. The sequencer can stop again, answer can move from 0 to 1, and an earlier “grace has passed” expires immediately. A generalization needs the path of answer and seconds-since-recovery over the window, not one fresh updatedAt standing in for the stretch.
Panels often paint “sequencer up” and “grace period over” as one green dot. Up only satisfies the first line. In the first 3600 seconds after recovery the dot can be honest and the price can still be unfit for a liquidation contract. Write the two lines separately.
5. Keep a record another researcher can replay
The minimum fields are: L2 chain id, sequencer feed address, price feed address, consumer address and the source of G (a source constant or a storage read), answer, startedAt, price answer, updatedAt from the same call, block timestamp, seconds since recovery, whether they are at or below G, heartbeat seconds, price age, and the result of each of the three steps. If two RPCs are seconds apart, book them as two states. A browser label that says “last updated” is not roundData.
Reconcile in a fixed order: whether the consumer reads the status feed, what answer means, seconds since recovery against G, and only then updatedAt against the heartbeat. A protocol that never reads the status feed stops at “check missing.” On Arbitrum, startedAt of 0 stops at “uninitialized”; do not compute a grace ratio. If calling the feed yourself means swapping a gas asset onto that L2, put the swap in a fee footnote. It does not belong in the usable-or-not result.
6. Usable means both clocks, not updatedAt alone
The weak sentence is “updatedAt is fresh, so this L2 price is usable.” A useful one is “answer; seconds since recovery; G; at or below G or not; then price age against the heartbeat.” answer 0 only says the sequencer is up. The grace period after that decides whether this fresh round may be adopted. Missing either clock, usable is an unverified panel.
This is a research framework with hypothetical calculations, not a quality opinion on any L2, oracle, or consumer, and not investment advice.