Migrate to 200ms Blocks
Read this page if your application consumes Flashblocks. The Denim upgrade swaps Flashblocks for canonical 200ms blocks. Once it activates, Flashblocks subscriptions and the pending state behind them stop being available.
Where to start
Section titled “Where to start”Take an inventory before Denim lands. Two things belong on that list: every Flashblocks subscription your application opens, and every RPC request it makes with the "pending" block tag. Work through the table below and pair each one with its replacement.
Flashblocks integrations are not the only thing Denim touches. If you also own contracts, check them for durations expressed as block counts: block.number advances ten times faster afterwards, so timelocks, cooldowns, vesting schedules, and governance windows written that way shrink to a tenth of their intended length. Block-number contract logic has the pattern table.
Replacements by integration
Section titled “Replacements by integration”| Flashblocks integration | Update for Denim |
|---|---|
eth_subscribe("newFlashblocks") | Use eth_subscribe("newHeads"). |
eth_subscribe("pendingLogs") | Use eth_subscribe("logs"). |
eth_subscribe("newFlashblockTransactions") | Use eth_subscribe("newHeads"), then fetch transactions for each canonical block. |
eth_getBlockByNumber("pending", ...) | Use normal RPC calls to read the latest canonical blocks. |
eth_getBalance(..., "pending") | Use normal RPC calls to read the latest canonical state. |
eth_getTransactionCount(..., "pending", ...) | Use normal RPC calls to read the latest canonical state. |
eth_call(..., "pending") | Use normal RPC calls to read the latest canonical state. |
eth_estimateGas(..., "pending") | Use normal RPC calls to read the latest canonical state. |
eth_simulateV1(..., "pending") | Use normal RPC calls to read the latest canonical state. |
eth_getLogs with a range ending at "pending" | Use normal RPC calls to query logs from canonical blocks. |
eth_getBlockTransactionCountByNumber("pending") | Use normal RPC calls to read the latest canonical block. |
| A bridge or proof flow that reads historical block hashes or beacon roots | Re-check what it assumes about reach. The number of values kept does not change, but each one covers a tenth as much elapsed time. |
The practical difference is one of timing rather than shape. A preconfirmation used to arrive ahead of the block that contained it. A 200ms canonical block arrives at the same cadence but already settled, so the read you make after migrating is a read of committed state.
How far back history reaches
Section titled “How far back history reaches”The last row of that table is the one most likely to be missed, because nothing about it looks like a Flashblocks integration and nothing in the affected code has to change to break.
Onchain history is retained by count, not by duration. The EIP-2935 ring buffer holds 8191 entries, and BLOCKHASH reaches back 256 blocks. Neither figure moves at Denim. What moves is how much time those fixed counts represent, and since blocks arrive ten times more often, each window contracts by the same factor:
| Window | Before Denim | After Denim |
|---|---|---|
BLOCKHASH, 256 blocks | about 8.5 minutes | about 51 seconds |
| EIP-2935 history buffer, 8191 blocks | about 4.5 hours | about 27 minutes |
Audit any flow that fetches a historical block hash or beacon root and ask how long it takes end to end, including the parts you do not control: a user signing, an operator batching, a relay waiting on L1 confirmation. A step that took twenty minutes was well inside a four-and-a-half-hour buffer and sits outside a twenty-seven-minute one. Where a flow cannot be made faster, capture the hash or root at the time of use and carry it through, rather than looking it up again once the work completes.
Try it on Vibenet
Section titled “Try it on Vibenet”Point your migrated integration at Vibenet and exercise it there. For the protocol design behind the change, along with the RPC behaviour it produces, see Denim 200ms Native Blocks.