What Base's Denim Upgrade Changes: 200ms Blocks and BaseTime
Base's Denim upgrade replaces 2-second blocks with five canonical blocks per second and retires Flashblocks. It activates on Base Sepolia Oct. 21; mainnet is targeted for November 2026.

Base's Denim upgrade replaces the two-second block with five canonical blocks per second, and it activates on Base Sepolia on Oct. 21, 2026 at 18:00 UTC, per the upgrades page. Mainnet is targeted for November 2026. Denim also retires Flashblocks, so any app that reads Flashblocks streams or the "pending" block tag has to move to canonical streams.
This guide covers what changes at the protocol level, what BaseTime does, which RPC fields are new, and what developers and node operators need to do. Everything below comes from Base's own documentation. It follows Cobalt, which went live on mainnet on Sept. 30, and the earlier Azul and Beryl releases. Background on the network is on the Base entity page.
What Denim changes
Per the Denim overview, the upgrade has four parts: native blocks at a 200ms cadence, BaseTime for onchain millisecond time, millisecond-resolution RPC timestamps, and B20 transfer and policy improvements.
Today Base produces one canonical block every two seconds. After Denim it produces "five complete canonical blocks per second, each with its own hash, state root, receipts, and forkchoice lifecycle," according to the overview. The 200ms blocks page adds that each block has its own block number and moves through its own unsafe, safe and finalized stages.
Flashblocks, which published incremental pending-state updates, is being replaced. The 200ms blocks page says Denim "replaces Flashblocks" with canonical blocks every 200ms, and the upgrades page describes the result as canonical block and RPC streams.
BaseTime: millisecond time onchain
EVM block.timestamp stays in whole seconds. Millisecond time arrives through a new predeploy called BaseTime, per the 200ms blocks page. The mechanics, as that page documents them:
- Every block after activation carries a BaseTime metadata deposit as its second transaction (
tx[1]), a type0x7edeposit sent to the predeploy at0x4200000000000000000000000000000000000030. - The deposit supplies the sub-second part of the timestamp. The only valid values are 0, 200, 400, 600 and 800.
- The predeploy stores that value as a
uint16in storage slot 0. Contracts read it withtimestampMillisPart()ortimestampMs(). - The full timestamp is
1000 x header.timestamp + timestamp_millis_part, and each block's full timestamp must equal its parent's plus 200ms or the block is rejected.
On existing chains the predeploy implementation is installed at activation, and calls to it revert until then, per the same page. The sequence within a second runs .000, .200, .400, .600, .800, then the next second.
Millisecond timestamps in RPC
The 200ms blocks page lists new optional RPC fields. The existing seconds-based timestamp fields do not change.
- Block and header responses (
eth_getBlockByHash,eth_getBlockByNumber,eth_getHeaderByHash,eth_getHeaderByNumber, andeth_subscribe("newHeads")) addtimestampMs. The docs' example: a block at 42.200 seconds showstimestamp: 0x2aandtimestampMs: 0xa4d8. - Transaction responses add
blockTimestampMs. Pending transactions omit it. - Logs add
blockTimestampMs, including logs frometh_getLogs, the filter methods, and thelogssubscription. Receipts do not carry the field at the top level. - If the BaseTime metadata or block body has been pruned, responses omit
blockTimestampMsrather than estimate it.
For client libraries, the docs say Foundry's AnyRpcBlock and WithOtherFields can preserve the unknown timestampMs field, while Alloy's plain AnyRpcHeader drops it and needs WithOtherFields<AnyRpcHeader>.
What app developers need to do
The migration guide tells developers to inventory every Flashblocks subscription and every RPC request that uses the "pending" block tag before Denim. Its replacement table:
eth_subscribe("newFlashblocks")becomeseth_subscribe("newHeads").eth_subscribe("pendingLogs")becomeseth_subscribe("logs").eth_subscribe("newFlashblockTransactions")becomeseth_subscribe("newHeads")plus fetching the transactions of each canonical block.- Uses of the
"pending"tag become normal RPC calls that read the latest canonical blocks.
The migration guide warns that the "pending" tag and Flashblocks preconfirmation state have no direct equivalent after Denim.
Contract authors face a second change. After activation, block.number advances ten times faster in wall-clock time while block.timestamp still moves in whole seconds, per the 200ms blocks page. The docs list the effects:
- Timelocks and cooldowns written as
block.number - start >= Nelapse in one tenth of the intended time. - Vesting and emission schedules complete 10x faster.
- Per-block rate limits reset five times a second instead of every two seconds.
- Voting delays, including the ERC20Votes default, shrink by 10x.
- Uniswap V3 TWAP oracles cover roughly 50% less history at the same cardinality.
The docs recommend replacing block-count durations with block.timestamp comparisons where possible and planning to divide governance-tunable values by ten at activation. They note that immutable, non-upgradeable contracts cannot be retuned after activation.
What RPC providers and node operators need to know
The documentation's operator-facing requirements sit in the Engine API and derivation sections of the 200ms blocks page:
- After Denim,
BasePayloadAttributesmust includetimestampMillisPartset to 0, 200, 400, 600 or 800. Before Denim it must not be present. - Payload IDs include
timestampMillisPart, so different millisecond values produce different IDs. - Execution clients reject malformed attributes with JSON-RPC error
-32602. - After activation, the derivation pipeline computes each block's scheduled timestamp from the Denim activation schedule and the absolute L2 block number, not from batch data or wall-clock time.
The migration page itself is addressed to application developers; the pages reviewed here publish no separate checklist for RPC providers.
Timeline and testing
| Network | Status | Date |
|---|---|---|
| Base Sepolia | Scheduled | Oct. 21, 2026, 18:00 UTC |
| Base Mainnet | Planning | Targeted for November 2026 |
The Sepolia date and time come from the upgrades page; the overview lists the same date. Mainnet is targeted for November 2026, and the docs give no exact date. The migration guide's status line says Denim is not yet active on Sepolia or Mainnet and that activation timing is undecided, so the Sepolia activation is the first concrete checkpoint.
For testing, the 200ms blocks are live on Vibenet, which the docs describe as an experimental deployment that may change and should not inform production decisions. The migration guide tells developers to test migrated integrations there before mainnet. Anvil is not expected to produce BaseTime metadata for locally mined blocks initially, per the 200ms blocks page.
Not yet published
The documentation does not give a mainnet activation date. It also states no fee or throughput figures for 200ms blocks, so this guide includes none. The B20 changes are listed in the overview (transfers, mints and seizures to a token's own address now revert, TRANSFER_EXECUTOR_POLICY is enforced on all transfer paths, and policies gain a NOT flag), but the pages reviewed here do not detail them further.
Sources
- Denim overview: feature list, timeline, B20 changes.
- 200ms blocks: block structure, BaseTime deposit and predeploy, Engine API, RPC fields, contract effects.
- Migrate from Flashblocks: subscription replacements,
"pending"tag guidance, Vibenet testing. - Base network upgrades: Sepolia date and time, mainnet target.