Base's planned Denim upgrade removes the Flashblocks subscriptions and pending-state reads that some apps use for live updates. If your wallet or trading interface depends on them, its transaction feed needs to change before activation. Code that assumes two seconds per block also needs review.
Denim replaces Flashblocks with complete canonical blocks every 200 milliseconds. The migration affects how your app reads state, processes events, and measures time. This guide takes you from finding those dependencies to testing their replacements and coordinating the release with your remote procedure call (RPC) provider.
Status checked September 14, 2026: Base targets October 2026 for Sepolia and Mainnet. Exact activation times and required client versions remain undecided. Vibenet already supports experimental testing; the Denim specification is the source for rollout updates.
Find the assumptions Denim changes
Start with the code that turns chain activity into application state. For a trading interface, that includes the swap-status listener, token-balance reads, and the worker that records completed trades.
Search your client code and configuration for newFlashblocks, newFlashblockTransactions, pendingLogs, and the pending block tag. Include software development kit (SDK) wrappers and background workers. A subscription hidden inside a shared library still needs an owner for the migration.
Record what each call does for the product. A swap listener needs transaction events; a portfolio screen needs account state. That distinction determines which replacement to use.
Also find assumptions about block duration. Look for block-count deadlines, polling intervals, and conversions such as blocks * 2. Your RPC client can keep returning valid data while those calculations produce the wrong result.
The output should be a short list of affected calls and time-based rules, with a test for each expected behavior.
Replace Flashblocks calls and their response handlers
Use the Base migration table to replace each affected integration. The main changes are:

Changing the subscription name is only the first step. newHeads returns a header. A handler that expects a Flashblock diff cannot decode it as the same payload.
For a transaction feed, take the header's hash and request eth_getBlockByHash(hash, true). Process the returned transactions. A hash ties that fetch to the observed header, while a later latest query could select a newer block.
For contract events, move the address and topic filters from pendingLogs to logs. Preserve the event's block hash and transaction hash. Keep reorganization handling, including corrections for removed logs and replacement blocks.
For state reads, use canonical queries such as eth_getBalance(address, "latest") or eth_call(transaction, "latest"). Inventory nonce reads, gas estimates, simulations, and log ranges too. The migration covers more than the balance widget.
latest does not reproduce the old preconfirmation snapshot. It selects canonical state under the new block model. Update labels, cache keys, and assumptions about when a result becomes available accordingly.
Audit timers before keeping the same block counts
A fixed block count represents less elapsed time when blocks arrive more often. At the stated cadences, 30 blocks take 60 seconds before Denim and 6 seconds after it. This is a timing calculation, not a measured latency guarantee.

Review cooldowns, expiry rules, and jobs scheduled by block count. For a duration expressed in seconds, use an appropriate time-based rule instead of assuming that the old block count preserves it. Immutable contract rules require a migration assessment.
Existing timestamp fields remain seconds-based. Do not divide them by 1,000 or assume they uniquely identify blocks. The planned timestampMs field supplies millisecond block timestamps when available; consumers must handle its absence.
Faster canonical inclusion also does not establish finality. Denim retains the unsafe, safe, and finalized lifecycle. Keep confirmation requirements tied to the action your application takes, rather than treating a 200ms block as permission for irreversible settlement.
Test the migration on Vibenet
Vibenet is Base's experimental preview network. It uses chain ID 84538453 and the public endpoint https://rpc.vibes.base.org. Its state may reset without notice, so use isolated test data and test accounts.
The following Node.js example reads two consecutive blocks. Save it as check-denim.mjs and run node check-denim.mjs. It checks the network and prints the timestamp fields without sending a transaction.
const url = 'https://rpc.vibes.base.org';
async function rpc(method, params) {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),
signal: AbortSignal.timeout(10000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const payload = await response.json();
if (payload.error) throw new Error(payload.error.message);
return payload.result;
}
const chainId = BigInt(await rpc('eth_chainId', []));
if (chainId !== 84538453n) throw new Error('Expected Base Vibenet');
const head = await rpc('eth_getBlockByNumber', ['latest', false]);
const parent = await rpc('eth_getBlockByHash', [head.parentHash, false]);
for (const block of [parent, head]) {
console.log({
number: BigInt(block.number).toString(),
hash: block.hash,
timestampSeconds: BigInt(block.timestamp).toString(),
timestampMs: block.timestampMs == null
? 'not supplied'
: BigInt(block.timestampMs).toString(),
});
}
This checks RPC responses, not the whole application. Next, exercise your actual event handlers and state updates. Use the endpoint capabilities listed in the Vibenet hub for the current test environment.
Use these acceptance checks for the affected application paths:
| Migrated path | Expected result | Recovery check |
|---|---|---|
newHeads plus a block fetch | The feed processes the transactions in the observed block. | Fetch missed blocks after reconnecting without duplicating application effects. |
logs | Matching contract events update application state. | Recover the missed log range and correct events removed by a reorganization. |
| Canonical state reads | Balances and other values match the selected canonical block. | Invalidate cached values associated with a replaced block. |
| Block-based timers | Each deadline preserves its intended duration. | Test the rule across consecutive blocks with the same seconds timestamp. |
Test an interrupted connection as well as the normal path. Record the last processed canonical block, disconnect, and recover the gap before resuming live processing. For contract events, compare recovered logs with the canonical block range and verify that your app does not apply an event twice.
Measure processing backlog and request volume under the new cadence. A client that fetches data for every canonical block has a different workload from one that waits for two-second blocks. A client already consuming 200ms Flashblock notifications starts from a different baseline.
Do not infer readiness from one successful request. The migration is ready for rollout planning when the application's reads, events, recovery, and timing rules work together.
Coordinate the network and RPC rollout
A hosted endpoint removes node operations from your application team, but it cannot rewrite your subscriptions or contract timing rules. With Dwellir's Base RPC, your team still owns those application changes.
Before switching a production integration, confirm the target network's activation schedule and your provider's endpoint support. Ask which client behavior is available for testing, what changes at activation, and how service issues will be communicated.
Keep the old and migrated paths associated with explicit network and activation criteria. Do not assume that experimental Vibenet behavior means Denim has activated on Sepolia or Mainnet.
After activation, verify the first processed blocks and events against canonical RPC data. Check gaps, duplicate application effects, and timing-based alerts before considering the migration complete.
For endpoint planning, contact Dwellir with your affected subscriptions, request volume, and recovery requirements. Use the Base RPC documentation alongside the Denim migration guide to prepare the application changes.


