Skip to content

v3.3.0

Choose a tag to compare

@github-actions github-actions released this 03 Sep 22:02
· 46 commits to main since this release
15ab537

A new built-in chain, and a fix to the front door. A nest already running gains nothing from
restarting; anyone about to run nuthatch init for the first time should use this release.

Monad is built in (#1136, RFC-0051)

nuthatch init 0xADDR --chain monad works with no key and no --rpc. Chain id 143, a full-EVM L1
with MonadBFT single-slot finality, blocks every 300 ms, on the generic EVM path: a registry entry,
not an adapter. The freeze was lifted for this one chain and nothing else; it is carve-out three in
the brief, and the Robinhood Chain draft stays frozen.

What an operator should know. Everything below was measured on 2026-09-03 and is recorded on
the tracking issue.

  • The seal boundary is a depth of eight blocks, about 2.4 s, not the finalized tag. Monad
    executes a block up to three blocks after consensus finalises it, so the tag says final, not
    executed. Eight is an execution margin over that deferral. Nothing past finalized reorgs on
    Monad, so do not raise it by analogy with an L2, and do not lower it to the tag without the soak
    the RFC asks for. What makes the depth safe rather than merely wide: every shipped endpoint answers
    a height it has not executed with an error, never an empty list, and that error is retried.
  • The window is 100 blocks, the documented cap on the canonical public endpoint. Monad blocks are
    dense - the busiest contract that day carried 77 logs per block - so on a busy address it is the
    result cap you hit. Alchemy's rpc1.monad.xyz serves 640 address-filtered on its own.
  • No shipped endpoint keeps historic state. All three serve logs and blocks from block 1, so a
    from-genesis backfill of events works on the defaults. A pinned [[calls]] at an old block, and
    init's deployment-block detection, both need an archive endpoint: set start_block or pass
    --backfill, and use --rpc for pinned calls. The Foundation endpoint keeps state but refuses
    JSON-RPC batches, so it is not listed.
  • Alert on tip lag in seconds, not blocks. Twenty blocks behind is six seconds.

Two over-wide-range refusal shapes found on Monad's public endpoints are now classified as
narrowable rather than retried at the same width forever: Ankr's HTTP 200 response exceeds size limit and QuickNode's eth_getLogs is limited to a 100 range.

Measured end to end with no key: init on the AgoraDollar proxy resolved the ABI through Sourcify in
two seconds; dev sealed 2,000 blocks in one second, caught the tip in four, and followed about two
seconds behind for two minutes with zero reorgs.

Keyless init was dark on four of the eight built-in chains (#1138)

init asks Sourcify for a contract's ABI first, and Sourcify's v2 API stopped accepting the name
field selector the request carried. The answer became HTTP 400 on every chain, for every contract,
for an unknown stretch, and the code fell through to the next source in silence: a Blockscout
instance where one is wired in, which is mainnet, Base and Gnosis, and otherwise Etherscan, which
needs ETHERSCAN_API_KEY. So a keyless init on Arbitrum One, Optimism, Polygon or BSC could not
fetch an ABI at all, and 3.2.0 shipped that way.

The request now selects compilation, where Sourcify keeps the contract name today, and the alias
hint is read from there with the old top-level field kept as a fallback, picking the first usable
name rather than the first present field. Measured after the fix: a keyless init of mainnet USDC
resolves through Sourcify in two seconds.

How it hid, and the gate for it. No test asks the live service which fields it accepts, and the
nightly endpoint gate never touched the ABI path. That gate now runs a keyless init of mainnet USDC
and requires the line naming Sourcify as the source; a fallback quietly answering instead fails it.
The same gate now probes Monad's three endpoints alongside the other chains.

Also in this release

--rpc on a built-in chain name is the whole pool: your endpoints replace the bundled public ones
outright and nothing public is appended. Only the chain id is never looked up over it. The README
used to say the flag was ignored for built-in names, which was wrong.

No data migration, no schema change, no runtime change for an existing nest. A binary swap and a
restart, as ever, and for a nest already on 3.2.0 there is no reason to do even that.