Skip to main content

Monad network reference

Vessel runs on Monad. This page collects the network facts a user, keeper, or integrator needs before sending a transaction. Every value below was read at the named primary source on 2026-08-29; the source list is in the page footer.

Vessel is deployed on Monad testnet only. The mainnet column is here because the same rules apply there and because integrators routinely need both.

Networks

MainnetTestnet
Chain ID143 (0x8F)10143 (0x279F)
Native currencyMON, 18 decimalsMON, 18 decimals
Primary RPChttps://rpc.monad.xyzhttps://testnet-rpc.monad.xyz
Explorer (MonadVision)monadvision.comtestnet.monadvision.com
Explorer (Monadscan)monadscan.comtestnet.monadscan.com
Faucetn/afaucet.monad.xyz
App hubn/atestnet.monad.xyz

Chain IDs are triple-agreed across docs.monad.xyz, the viem chain definitions, and ethereum-lists/chains.

Network version at time of writing: v0.15.2 / MONAD_NINE. Testnet was reset from genesis on 2025-12-16; any testnet history, address, or explorer link from before that date refers to a chain that no longer exists.

Explorer conflict

viem and ethereum-lists still list testnet.monadexplorer.com as the testnet explorer. Current docs.monad.xyz does not reference it. This page ships the docs.monad.xyz set: MonadVision and Monadscan on both networks.

RPC endpoints

Mainnet

EndpointOperatorLimits
https://rpc.monad.xyzQuickNode (primary)25 rps, batch 100
https://rpc1.monad.xyzAlchemyUNVERIFIED — PENDING GATE-0
https://rpc2.monad.xyzGoldskyUNVERIFIED — PENDING GATE-0
https://rpc3.monad.xyzAnkrUNVERIFIED — PENDING GATE-0
https://rpc-mainnet.monadinfra.comMonad InfraUNVERIFIED — PENDING GATE-0

WebSocket (wss://) variants exist for all five mainnet endpoints. The source states their existence; it does not publish separate rate limits for them.

Testnet

EndpointLimits
https://testnet-rpc.monad.xyz (primary, archive)50 rps, batch 100; 25 rps for eth_call and eth_estimateGas
https://rpc.ankr.com/monad_testnetUNVERIFIED — PENDING GATE-0
https://rpc-testnet.monadinfra.comUNVERIFIED — PENDING GATE-0

Testnet WebSocket endpoints: wss://testnet-rpc.monad.xyz and wss://rpc-testnet.monadinfra.com.

A keeper polling Vessel state against the primary testnet RPC should size its loop against the 25 rps eth_call ceiling, not the 50 rps headline figure. The full provider directory, 16 providers on mainnet and 15 on testnet, is at docs.monad.xyz/tooling-and-infra/rpc-providers.

# Confirm you are talking to the right chain
cast chain-id --rpc-url https://testnet-rpc.monad.xyz # 10143
cast chain-id --rpc-url https://rpc.monad.xyz # 143

Blocks and finality

Block time is 300ms. Speculative finality is 300ms; full finality is 600ms.

The Vessel litepaper cites 400ms blocks and 800ms finality. Those figures predate the current network and are stale; the numbers above are from current docs.monad.xyz.

Monad exposes four block states. They map onto the standard JSON-RPC block tags as follows.

Block stateRPC tagMeaning
ProposedlatestSpeculative; the leader has proposed the block
VotedsafeValidator-backed
FinalizedfinalizedIrreversible
Verified(after finalized)Execution outputs verified

Use finalized for anything irreversible: crediting a deposit, releasing a Hull redemption, marking a keeper job as done, or triggering an off-chain action on a Vessel event. latest is fine for display and for simulation.

Two consequences of Monad's asynchronous execution:

  • Consensus validates against a state view delayed by three blocks (D=3). A newly funded account cannot send a transaction until its funding is three blocks old, roughly 1.2 seconds. Scripts that fund a fresh keeper wallet and immediately transact from it will fail on the first attempt.
  • eth_call and eth_estimateGas simulate against speculative state and return accurate results.

Parallel execution is optimistic-concurrency under the hood; results are identical to serial Ethereum semantics. No contract changes are required and Vessel makes none for this reason.

Gas

Monad charges the gas limit, not the gas used

From docs.monad.xyz, verbatim: "In Monad, the gas charged for a transaction is the gas limit set in the transaction, rather than the gas used in the course of execution."

gas_paid = gas_limit × price_per_gas. This exists because of asynchronous execution: the leader builds the block before executing it, so actual consumption is unknown at inclusion time, and charging the limit prevents under-priced-compute denial of service.

What this means in practice:

  • A keeper must fund its wallet against the gas limits it sets, not against historical gasUsed. A rebalance that uses 400k gas but is sent with a 2M limit costs 2M.
  • An integrator estimating the cost of Vessel calls from receipts' gasUsed will underfund. Estimate from the limit you intend to set.
  • If eth_estimateGas reverts, some wallets fall back to a very large default limit. On Ethereum that is harmless; on Monad the user pays the entire limit. A failed estimate followed by a blind send costs real money.

Parameters, all from docs.monad.xyz and matching MONSKILLS v0.7.2:

ParameterValue
Block gas limit200M
Per-transaction gas limit30M
Minimum base fee100 MON-gwei
Base fee target160M gas per block (80% of capacity)
Native MON transferexactly 21,000 gas

Pricing is EIP-1559 type-2: price_per_gas = min(base + priority, max). Transactions are ordered by a priority gas auction, descending total gas price.

The base fee controller rises more slowly and falls more quickly than Ethereum's (max_step = 1/28, beta = 0.96). A burst of demand takes longer to push fees up and fees recover sooner afterwards. Do not port fee-bump heuristics tuned for Ethereum without re-testing them.

Two rules for anyone writing transaction code against Vessel:

  1. A native MON transfer always costs 21,000 gas. Hardcode it; do not call eth_estimateGas for it.
  2. Keep estimation buffers small, at or under about 10%. Every unit of buffer is paid, whether or not it is used.

Cold-access repricing

Cold state access is priced higher than on Ethereum. Warm access is unchanged.

AccessMonadEthereum
Cold account access10,1002,600
Cold storage access8,1002,100
Warm access100100

This affects BALANCE, EXTCODE*, CALL*, SELFDESTRUCT, SLOAD, and SSTORE. A Vessel operation that touches many cold slots (a rebalance reading tranche NAVs, reserve, and venue state for the first time in a block) will estimate noticeably higher than the same bytecode on Ethereum. That is expected, not a bug.

Precompile repricing

PrecompileMonadMultiple of Ethereum
ecRecover6,000
ecAdd300
ecMul30,000
ecPairing225,000
blake2f(2×)
point evaluation200,000

The source gives blake2f as a 2× multiple without an absolute figure.

Full reference: docs.monad.xyz/developer-essentials/gas-pricing.

Other limits and behaviours

  • Reserve balance. Every EOA carries a 10 MON reserve floor. Accounts below it are limited to roughly one transaction per 1.2 seconds. Keeper wallets should hold well above 10 MON, and the balance alert threshold should sit above the floor, not at zero.
  • Contract size. Maximum contract size is 128kb, larger than Ethereum's 24kb. Vessel's contract sizes are not published UNVERIFIED — PENDING GATE-0; the repository contains no contracts as of 2026-08-29.
  • eth_sendRawTransactionSync. Monad returns the transaction receipt in the send call itself. A keeper can use it to skip the submit-then-poll loop. Treat the returned receipt with the same finality discipline as any other: it is speculative until the block reaches finalized.

Contract verification

Vessel's testnet contracts are not yet published, so there is nothing to verify today. When they are, the procedure is Monad's standard one. The guide, with Foundry and Hardhat sub-guides, is at docs.monad.xyz/guides/verify-smart-contract. The MonadVision path uses Sourcify and needs no API key:

forge verify-contract <addr> <name> --chain 10143 --verifier sourcify \
--verifier-url https://sourcify-api-monad.blockvision.org/

Use --chain 143 for mainnet. The Monadscan path uses --verifier etherscan with an API key. foundry.toml needs metadata = true, metadata_hash = "none", and use_literal_content = true. The verify command can print errors even when verification succeeded; confirm on the explorer before concluding it failed.

To check whether any address holds code:

cast code <addr> --rpc-url https://testnet-rpc.monad.xyz

Sources

Verified from: docs.monad.xyz · monskills/gas · monskills/concepts · viem/ethereum-lists — Sat Aug 29 2026 00:00:00 GMT+0000 (Coordinated Universal Time) · How we verify this site →