Skip to main content
Monad supports a JSON-RPC interface for interacting with the blockchain. Monad aims to match the RPC behavior of Geth as closely as possible, but due to fundamental architectural differences, some behaviors deviate from Ethereum.

Supported methods

Behavioral differences from Ethereum

Monad is Geth-compatible, but its architecture — including asynchronous execution and sub-second block times — introduces behavioral differences in several areas.

Transaction lifecycle

Deferred nonce/balance validation. eth_sendRawTransaction may not immediately reject transactions with a nonce gap or insufficient gas balance. Because Monad’s RPC server is designed for asynchronous execution, it may not have the latest account state at the time of submission. These transactions are initially accepted because they may become valid during block creation. No pending transaction queries. eth_getTransactionByHash only returns transactions that have been included in a block. Querying a transaction that is still in the mempool returns null.

State availability

eth_call invocations that reference old state (i.e. with an old block number) may fail, because full nodes do not provide access to arbitrary historic state. See Historical Data for details on what state is available and how to access it.

Fee estimation

eth_maxPriorityFeePerGas currently returns a hardcoded suggested fee of 2 gwei. This is temporary. eth_feeHistory with newest_block = latest: by convention, this method returns the fee history for the requested range plus one extra projected fee for the next block. Monad does not have all the inputs required to compute the next block’s base fee, so when the newest requested block is latest, the latest baseFeePerGas is returned twice.

Debug / tracing

Trace options parameter is required. debug_traceCall, debug_traceTransaction, and related debug_trace* methods require the trace options object to be explicitly provided. Unlike standard EVM clients where this parameter is optional, Monad RPC returns error -32602 Invalid params if it is omitted. Always include the parameter, even if empty:
{
  "method": "debug_traceCall",
  "params": [
    {
      "to": "0x6b175474e89094c44da98b954eedeac495271d0f"
    },
    "latest",
    {}
  ]
}
Default tracer is callTracer. When an empty trace options object {} is provided, Monad defaults to the callTracer instead of the struct logs tracer typical in other EVM clients. Monad does not currently support opcode-level struct logs at the VM level.

Unsupported features

FeatureAffected methodsDetails
EIP-4844 (blob transactions)eth_sendRawTransaction, eth_call, eth_estimateGasBlob transaction type is rejected
syncing subscriptioneth_subscribeNot supported
newPendingTransactions subscriptioneth_subscribeNot supported

Limits

eth_call / eth_estimateGas

Gas limit per call

ProviderPublic RPCGas limit
QuickNoderpc.monad.xyz200M gas
Alchemyrpc1.monad.xyz200M gas
Ankrrpc3.monad.xyz1B gas
Monad Foundationrpc-mainnet.monadinfra.com200M gas
Node operators. Use --eth-call-provider-gas-limit (default 30M) and --eth-estimate-gas-provider-gas-limit (default 30M) to configure these limits.

Gas limit resolution

When the caller specifies a gas price (gasPrice or maxFeePerGas), the effective gas limit is min(gas limit allowance, provider gas limit), where the gas limit allowance is the maximum gas given the caller’s balance and specified price. When no gas price is specified, the provider gas limit applies directly. This is consistent with Geth’s behavior.

Dual-pool execution model

eth_call and eth_estimateGas requests are routed to one of two execution pools based on the caller-specified gas limit:
PoolGas limitPurpose
Low-gas≤ 8,100,000Most calls; higher throughput
High-gas> 8,100,000Large simulations; limited concurrency
When the caller does not specify a gas limit, the request is first attempted in the low-gas pool. If it runs out of gas, it is automatically retried in the high-gas pool.
Node operators. Use --eth-call-max-concurrent-requests (default 1000) and --eth-call-high-max-concurrent-requests (default 20) to configure pool concurrency.

eth_getLogs

Block range limit per call

ProviderPublic RPCBlock range limit
QuickNoderpc.monad.xyz100 blocks
Alchemyrpc1.monad.xyz1,000 blocks and 10,000 logs (whichever is more constraining)
Ankrrpc3.monad.xyz1,000 blocks
Monad Foundationrpc-mainnet.monadinfra.com100 blocks
Node operators. Use --eth-get-logs-max-block-range to configure the block range limit.

Why are block range limits low?

Monad produces a block every 400ms and can accommodate up to 5,000 transactions per block with computation up to 200M gas. Blocks are both extremely frequent and significantly larger than Ethereum blocks, which is the main motivation for keeping per-call block range limits low.

Errors

Monad’s JSON-RPC error codes aim to be equivalent to Ethereum’s, but some codes deviate due to lack of standardization across Ethereum clients.

Request-level errors (-32601)

MessageExplanationCommon cause
Parse errorUnable to parse the JSON-RPC requestMalformed JSON
Invalid requestThe request is structurally invalidRequest exceeds size limit
Method not foundThe method is not part of the JSON-RPC specTypo in method name
Method not supportedThe method exists in the spec but is not yet supported by MonadCalling an unimplemented method

Parameter errors (-32602)

MessageExplanationCommon cause
Invalid block rangeThe requested eth_getLogs block range exceeds the provider limitSee block range limits
Invalid paramsIncorrect parameters for the methodWrong types, missing required fields, omitted trace options

Execution errors (-32603)

MessageExplanationCommon cause
Internal errorThe request could not be fulfilledServer-side failure
Execution revertedThe simulated transaction revertedFailed eth_call or eth_estimateGas
Transaction decoding errorThe raw transaction could not be decodedInvalid RLP in eth_sendRawTransaction

WebSocket subscriptions

Monad’s RPC server supports JSON-RPC over WebSocket connections, enabling persistent connections and real-time data via eth_subscribe. See the Geth documentation for general eth_subscribe behavior. Monad extends the standard subscription types with two speculative variants (monadNewHeads and monadLogs) that publish data sooner — approximately one second earlier on average — on a speculative basis. See Speculative Real-Time Data for background on speculative execution and Block States for the full block lifecycle.

Subscription types

TypeFires when
newHeadsA new header is appended, once the block is Voted
logsMatching logs appear in a new block, once the block is Voted
monadNewHeadsA new header is available, once the block is Proposed and speculatively executed
monadLogsMatching logs are available, once the block is Proposed and speculatively executed
The subscription types syncing and newPendingTransactions are not supported.

Speculative subscription behavior

monadNewHeads and monadLogs updates include two additional fields not present in the standard variants:
  • blockId — a unique identifier for this specific block proposal (distinct from block number, since multiple proposals can exist for the same height).
  • commitState — the block’s current commit state: Proposed, Voted, Finalized, or Verified.
The same block will typically produce multiple updates as its commitState advances through the lifecycle. A block may skip Voted and go directly from Proposed to Finalized when consensus is ahead of execution. When a block fails to finalize, it is abandoned implicitly — the finalization of a different block at the same height supersedes it, but no explicit abandonment event is published.