Skip to main content

Base’s own documentation contains a sentence that almost nobody in crypto gaming has read. It is addressed to exchanges and bridges, and it says you should only take an off-chain action “once the transaction is in a safe block, and wait for a finalized block for high-value actions”.

Every on-chain casino, raffle and coinflip I know of, this one included, pays out on the block it is standing in. That is the unsafe head, the one your node serves as latest, the one that arrives about two seconds after you click. The documentation does not say that is wrong. It says that people who act off-chain should wait. The question worth asking is which of those two things a gaming platform actually is.

So I went and measured the gap. On the evening of 6 October 2026 I polled Base’s three block heads every six seconds for twelve minutes, asked seven public Base endpoints the same question once a minute, and then hammered three of them once a second to see whether any would change its mind. Two of those measurements came back close to what the documentation promises. The third did something the word “final” is not supposed to permit.

TL;DR

  • A Base block is confirmed in two seconds and irreversible about nineteen minutes later. Median age of the finalized head across 152 samples: 1,114 seconds, 557 blocks. The safe head sat 91 seconds behind.
  • Finality does not creep. It lands in lumps of 172 to 203 blocks at once, roughly six minutes of chain at a time, because Base inherits finality from Ethereum’s epochs rather than producing any of its own.
  • So the wait is not the same for everybody. The newest block in a lump waits 14 minutes 33 seconds for irreversibility; the oldest block in the same lump waited about twenty-one minutes for the identical guarantee. No interface anywhere shows you which one you got.
  • Seven endpoints agreed on latest to within a block or two and gave three different answers for finalized, the extremes 1,518 blocks, roughly fifty minutes, apart.
  • One endpoint’s finalized head moved backwards eight times in 389 consecutive one-second queries. Nothing on the chain reorganised. The head is an assertion, not a proof, and it is the one thing your node tells you that you cannot check.

What I measured, and how you can redo it

An OP Stack node tracks three heads and serves them as block tags. latest is the unsafe head: the sequencer has built a block and is telling you about it. safe means that block’s data has been posted to Ethereum by the batcher, so the ordering no longer depends on the sequencer’s good behaviour. finalized means the Ethereum block carrying that data has itself been finalised by Ethereum’s consensus, at which point reversing your transaction means breaking Ethereum.

The measurement is one JSON-RPC call in a loop, which is why I like it. Anyone can run it, and nobody has to take my word for anything.

curl -s https://base-rpc.publicnode.com -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["finalized",false]}'

Swap finalized for safe and latest, record the block number and the block’s own timestamp against your clock, repeat. Base blocks are spaced at exactly two seconds, which is a counter rather than a clock and the reason every block gap below converts to seconds by doubling. Nothing here is estimated.

Two seconds, 91 seconds, nineteen minutes

The headline numbers land inside the documented ranges, which is the boring and reassuring part. Across 152 samples the safe head ran a median of 91 seconds and 45 blocks behind the clock. The finalized head ran a median of 1,114 seconds and 557 blocks behind. Optimism documents hard finality as “about 15 to 30 minutes”. What I measured sits at the good end of that.

Read it from the other direction and it is less comfortable. At any given instant there are roughly 557 Base blocks in existence that are not yet irreversible. On a chain that settled 1,893 verifiable randomness requests in a single day, that window holds around two dozen draws at any moment, chain-wide: results computed, displayed, celebrated and in most cases already paid out, standing on a stretch of chain whose ordering is still, technically, one company’s claim.

I want to be precise about how small that risk is in practice. Base’s sequencer is operated by Coinbase, unsafe-head reorgs are extremely rare, and I observed exactly zero of them. I am measuring the size of a window, not reporting an incident.

Finality lands in lumps, so your wait is not your neighbour’s

Here is the thing the median hides. The finalized head does not advance block by block. It sits still for minutes, then jumps 172 or 203 blocks at once, because Ethereum finalises whole epochs and Base inherits the result wholesale. One clean interval between lumps measured 352 seconds against Ethereum’s 384-second epoch, the difference being my polling granularity rather than the chain’s.

That makes the age of the finalised head a sawtooth, not a constant. It dropped to 14 minutes 33 seconds the instant a lump landed, climbed steadily while nothing was finalised, and peaked at 22 minutes 3 seconds just before the next lump arrived.

Unpick that and you get the number that matters, which is how long an individual block waits. The newest block in a lump waits the shortest possible time, and I measured that at 14 minutes 33 seconds. The oldest block in the same lump was produced 344 to 406 seconds earlier, so it waited roughly twenty to twenty-one minutes for exactly the same guarantee. Same chain, same second of finalisation, six and a half minutes of difference in what it cost you to get there.

Translate that into a product. Two players enter the same raffle a few minutes apart. Both see “confirmed” in two seconds. Both are paid immediately. One of them held an unfinalised result for about fourteen and a half minutes and the other for about twenty-one, and neither was ever shown that number, because no interface in crypto gaming displays it. The strength of the guarantee you were given depends on where in Ethereum’s epoch you happened to press a button. That is not unfair exactly, but it is a real asymmetry that nobody discloses and nobody can act on.

Seven endpoints, three answers

I have written before about asking twelve strangers’ servers for the same block, and the conclusion then was that an RPC can omit and substitute but cannot fabricate, because block data is self-authenticating. The hash commits to the contents. Ask a second node and you catch the liar.

So this time I asked seven endpoints two questions at once: which block is latest, and which block is finalized. Here is one sample, taken in a single second.

Endpoint latest finalized
publicnode 52,261,275 52,260,659
mainnet.base.org 52,261,275 52,260,831
dRPC 52,261,275 52,260,659
1RPC 52,261,275 52,259,313
Tenderly 52,261,276 52,260,831
BlastAPI 52,261,276 52,260,659
MeowRPC 52,261,276 no answer

On latest, unanimous to within a block or two of ordinary sampling skew. On finalized, three different answers, with 1,518 blocks between the most and least confident. That is about fifty minutes of disagreement over what is already irreversible, and it was not a blip: nine of my ten sweeps found three distinct answers, and one endpoint spent the entire session stuck fifty minutes in the past.

This is where the two measurements stop being the same kind of measurement. If an endpoint lies to you about a block, you can prove it, because the block hashes itself. If an endpoint is wrong about which block is final, there is nothing to check it against. The finalized tag is not data carried in the block. It is the node’s own opinion about the state of a different chain, formed from how recently it synced Ethereum’s consensus and how its operator configured it. No field in the block you are holding commits to it. You can ask a second node, and all that gets you is a second opinion.

The head that went backwards

Then one of them started moving the wrong way.

I put a one-second loop on three endpoints. One behaved perfectly across 336 samples, not a single backward step. A second rate-limited me hard enough that I will not draw conclusions from it. The third, base-rpc.publicnode.com, spent the session flapping between block 52,260,831 and block 52,260,659. In 389 consecutive queries to a single hostname, the finalized head moved forwards nine times and backwards eight times, each reversal unwinding 172 blocks, roughly six minutes of supposedly irreversible chain.

The chain did not reorganise, and I will not imply it did. The explanation is almost certainly mundane: a public endpoint is a load balancer in front of a pool of nodes, and those nodes do not all follow Ethereum’s head at the same instant. Consecutive requests to one URL reached different machines, one of which had seen the newer epoch finalise and one of which had not. Nothing in the protocol was violated. Base’s finality is exactly as sound as the documentation says.

What was violated is the thing an application actually depends on, which is not the guarantee but the report of the guarantee. Write the obvious piece of code, release the payout once finalized is at or above my block, and you would have had that condition come true, then false, then true again, eight times, with no error raised, no reorg to detect and no way to tell from inside your own process that anything had happened. Monotonic is an assumption people make about that number without noticing they have made it. It held on the chain. It did not hold on the wire.

What this actually means for a draw

Now the part that matters for anyone running games here, and it is not what people assume.

If an unsafe Base block were replaced, a fully on-chain raffle rewinds symmetrically. The entry, the draw and the payout are all L2 state, so they vanish together. Nobody is left holding a prize from a draw that never happened, and nobody is left having paid for a ticket in a raffle that no longer exists. There is no accounting hole, because there is no accounting. There is only state, and the state is internally consistent at every point you could rewind it to.

The exposure is not in the chain. It is at every boundary where something steps off it, and there are more of those than people count.

  • Randomness that asked for zero confirmations. When I pulled a full day of VRF requests on Base, 89.3% of them specified zero block confirmations. Replay a request against different block data and the seed changes with it, which means the re-run draw is a perfectly legitimate draw with a different winner. Nothing is stolen. The result you watched is simply not the result that exists.
  • Anything denominated off-chain. A cash-out to an exchange, a bridge, a fiat payment, a leaderboard in a database, a push notification. All of them act on a chain state that could still be replaced, and none of them rewind when it is.
  • A balance that is a row, not a state. If a platform credits an internal ledger when you win and settles later, it is not a game on a chain. It is precisely the exchange that Base’s documentation is warning, and that warning is addressed to it whether anyone there has read it or not.

The useful reframing is that finality risk is not a property of your transaction. It is a property of the boundary your transaction crosses. Keep the whole loop inside one state machine and a rewind is an inconvenience. Let one leg out and a rewind is a loss, and the leg that got out is always the one carrying the money.

What we do, and what we do not do

We pay on the unsafe head, like everybody else. A Satoshie winner is paid in the block the draw resolves in, and I am not going to dress that up as caution it is not. Making a player wait nineteen minutes to collect, to defend against a sequencer failure that has not happened, would be a worse product and a dishonest trade.

What we do is keep the loop closed. The ticket, the VRF proof, the winner selection and the transfer that pays you are the same chain’s state, settled in the same place. There is no internal balance that owes you something later. Nothing about a win survives in a database if the chain changes its mind, because nothing about a win lives in a database at all.

The part I will commit to improving is disclosure, because that is the gap this measurement actually exposes. The confirmation number every platform shows you is the cheap one. The number nobody shows you is how far the block you were paid in sits behind the finalised head, and it is one RPC call away from being on the screen.

Honest limits

Three, and they cut at this post.

First, I measured twelve minutes of six-second polling on one evening. Ethereum’s finality timing moves with its own participation rates, and a day with missed epochs on L1 would stretch every number here. Treat the shape as the finding and the digits as one sample.

Second, the endpoint disagreement is a fact about seven servers, not about Base. The chain has one finalised head. That several providers report it differently, and that one reports it non-monotonically, is a statement about public infrastructure quality. Running your own node deletes the entire problem, and almost nobody does.

Third, we are inside this picture, not above it. Satoshie reads block heads from the same kind of public endpoint, our draws sit in the same unfinalised window as everyone else’s, and the sequencer we depend on is operated by one company. The difference I am claiming is narrow, so I will state it narrowly: our exposure is bounded by a stretch of chain anyone can inspect, rather than by a balance only we can see.

Three questions worth asking any platform

  1. Which block tag does your payout logic read, and what happens to my payout if that block is replaced?
  2. How many confirmations does your randomness request specify, and what number does the draw produce if that request is re-included against different block data?
  3. Is the balance I hold with you a chain state or a row in your database? If it is a row, what are you waiting for before you write it?

Nobody will mind the first two. The third gets a vague answer, and the vagueness is the answer.

“Provably fair” is a claim about a number. It says the draw was not chosen by anybody. It is completely silent on how long the block holding that draw remains a matter of opinion, and on whether the server you asked has a stable opinion of its own. Two seconds to confirmed, nineteen minutes to irreversible, and in between a gap that every platform in this industry is standing in and almost none of them will name.

We are standing in it too. The difference is that this post exists.

📷 Photo by mk. s on Unsplash

Valentina Ní Críonna

Author Valentina Ní Críonna

More posts by Valentina Ní Críonna