> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# JSON-RPC 概述

> JSON-RPC 方法、与以太坊的差异、速率限制和错误码

Monad 支持通过 [JSON-RPC](https://www.jsonrpc.org/specification) 接口与区块链进行交互。Monad 力求尽可能匹配 [Geth](https://geth.ethereum.org/docs/interacting-with-geth/rpc) 的 RPC 行为,但由于架构上的根本差异,某些行为会偏离以太坊。

## 支持的方法

| 方法                                                                                                              | 备注                                                                     |
| --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| [`eth_blockNumber`](/zh/reference/json-rpc/api#eth_blocknumber)                                                 |                                                                        |
| [`eth_call`](/zh/reference/json-rpc/api#eth_call)                                                               | [Gas 限制](#eth_call-%2F-eth_estimategas)、[状态可用性限制](#state-availability) |
| [`eth_chainId`](/zh/reference/json-rpc/api#eth_chainid)                                                         |                                                                        |
| [`eth_createAccessList`](/zh/reference/json-rpc/api#eth_createaccesslist)                                       | [存储 key 按页去重](/zh/developer-essentials/opcode-pricing#storage-pages)   |
| [`eth_estimateGas`](/zh/reference/json-rpc/api#eth_estimategas)                                                 | [Gas 限制](#eth_call-%2F-eth_estimategas)                                |
| [`eth_feeHistory`](/zh/reference/json-rpc/api#eth_feehistory)                                                   | [与以太坊的差异](#fee-estimation)                                             |
| [`eth_fillTransaction`](/zh/reference/json-rpc/api#eth_filltransaction)                                         |                                                                        |
| [`eth_gasPrice`](/zh/reference/json-rpc/api#eth_gasprice)                                                       |                                                                        |
| [`eth_getBalance`](/zh/reference/json-rpc/api#eth_getbalance)                                                   |                                                                        |
| [`eth_getBlockByHash`](/zh/reference/json-rpc/api#eth_getblockbyhash)                                           |                                                                        |
| [`eth_getBlockByNumber`](/zh/reference/json-rpc/api#eth_getblockbynumber)                                       |                                                                        |
| [`eth_getBlockReceipts`](/zh/reference/json-rpc/api#eth_getblockreceipts)                                       |                                                                        |
| [`eth_getBlockTransactionCountByHash`](/zh/reference/json-rpc/api#eth_getblocktransactioncountbyhash)           |                                                                        |
| [`eth_getBlockTransactionCountByNumber`](/zh/reference/json-rpc/api#eth_getblocktransactioncountbynumber)       |                                                                        |
| [`eth_getCode`](/zh/reference/json-rpc/api#eth_getcode)                                                         |                                                                        |
| [`eth_getLogs`](/zh/reference/json-rpc/api#eth_getlogs)                                                         | [区块范围限制](#eth_getlogs)                                                 |
| [`eth_getStorageAt`](/zh/reference/json-rpc/api#eth_getstorageat)                                               |                                                                        |
| [`eth_getTransactionByBlockHashAndIndex`](/zh/reference/json-rpc/api#eth_gettransactionbyblockhashandindex)     |                                                                        |
| [`eth_getTransactionByBlockNumberAndIndex`](/zh/reference/json-rpc/api#eth_gettransactionbyblocknumberandindex) |                                                                        |
| [`eth_getTransactionByHash`](/zh/reference/json-rpc/api#eth_gettransactionbyhash)                               | [不返回挂起的交易](#transaction-lifecycle)                                     |
| [`eth_getTransactionCount`](/zh/reference/json-rpc/api#eth_gettransactioncount)                                 |                                                                        |
| [`eth_getTransactionReceipt`](/zh/reference/json-rpc/api#eth_gettransactionreceipt)                             |                                                                        |
| [`eth_maxPriorityFeePerGas`](/zh/reference/json-rpc/api#eth_maxpriorityfeepergas)                               | [返回硬编码值](#fee-estimation)                                              |
| [`eth_sendRawTransaction`](/zh/reference/json-rpc/api#eth_sendrawtransaction)                                   | [异步验证行为](#transaction-lifecycle)                                       |
| [`eth_sendRawTransactionSync`](/zh/reference/json-rpc/api#eth_sendrawtransactionsync)                           | [异步验证行为](#transaction-lifecycle)                                       |
| [`eth_syncing`](/zh/reference/json-rpc/api#eth_syncing)                                                         |                                                                        |
| `eth_subscribe`                                                                                                 | 仅 WebSocket,请参见 [WebSocket 订阅](#websocket-subscriptions)               |
| [`debug_getRawBlock`](/zh/reference/json-rpc/api#debug_getrawblock)                                             |                                                                        |
| [`debug_getRawHeader`](/zh/reference/json-rpc/api#debug_getrawheader)                                           |                                                                        |
| [`debug_getRawReceipts`](/zh/reference/json-rpc/api#debug_getrawreceipts)                                       |                                                                        |
| [`debug_getRawTransaction`](/zh/reference/json-rpc/api#debug_getrawtransaction)                                 |                                                                        |
| [`debug_traceBlockByHash`](/zh/reference/json-rpc/api#debug_traceblockbyhash)                                   | [必须提供 trace 选项](#debug-%2F-tracing)                                    |
| [`debug_traceBlockByNumber`](/zh/reference/json-rpc/api#debug_traceblockbynumber)                               | [必须提供 trace 选项](#debug-%2F-tracing)                                    |
| [`debug_traceCall`](/zh/reference/json-rpc/api#debug_tracecall)                                                 | [必须提供 trace 选项](#debug-%2F-tracing)                                    |
| [`debug_traceTransaction`](/zh/reference/json-rpc/api#debug_tracetransaction)                                   | [必须提供 trace 选项](#debug-%2F-tracing)                                    |
| [`admin_ethCallStatistics`](/zh/reference/json-rpc/api#admin_ethcallstatistics)                                 | Monad 专有                                                               |
| [`net_version`](/zh/reference/json-rpc/api#net_version)                                                         |                                                                        |
| [`txpool_statusByAddress`](/zh/reference/json-rpc/api#txpool_statusbyaddress)                                   | Monad 专有                                                               |
| [`txpool_statusByHash`](/zh/reference/json-rpc/api#txpool_statusbyhash)                                         | Monad 专有                                                               |
| [`web3_clientVersion`](/zh/reference/json-rpc/api#web3_clientversion)                                           |                                                                        |

## 与以太坊的差异

Monad 与 Geth 兼容,但其架构 —— 包括 [异步执行](/zh/monad-arch/consensus/asynchronous-execution) 与亚秒级出块时间 —— 在若干方面引入了行为差异。

### 交易生命周期

**延迟的 nonce/余额验证。** `eth_sendRawTransaction` 可能不会立即拒绝存在 nonce 缺口或 gas 余额不足的交易。由于 Monad 的 RPC 服务器面向异步执行设计,提交时它可能没有最新的账户状态。这些交易会先被接受,因为它们可能在区块创建期间变为有效。

**不支持挂起交易查询。** `eth_getTransactionByHash` 仅返回已被打包到区块中的交易。查询仍在 mempool 中的交易将返回 `null`。

### 状态可用性

引用旧状态的 `eth_call` 调用(即使用旧的区块号)可能失败,因为全节点不提供对任意历史状态的访问。详见 [历史数据](/zh/developer-essentials/historical-data),了解哪些状态可用以及如何访问。

### 手续费估算

**`eth_maxPriorityFeePerGas`** 目前返回硬编码的建议手续费 2 gwei。这是暂时的做法。

**`eth_feeHistory`** 当 `newest_block = latest` 时:按照惯例,该方法会返回所请求范围内的手续费历史,*加上* 一个针对下一区块的额外预测手续费。Monad 没有计算下一区块 base fee 所需的全部输入,因此当最新请求的区块为 `latest` 时,最新的 `baseFeePerGas` 会被返回两次。

### 调试 / 跟踪

**必须提供 trace 选项参数。** `debug_traceCall`、`debug_traceTransaction` 及相关的 `debug_trace*` 方法要求显式提供 trace 选项对象。与该参数为可选的标准 EVM 客户端不同,如果省略,Monad RPC 会返回错误 `-32602 Invalid params`。即使为空也务必包含该参数:

```json theme={null}
{
  "method": "debug_traceCall",
  "params": [
    {
      "to": "0x6b175474e89094c44da98b954eedeac495271d0f"
    },
    "latest",
    {}
  ]
}
```

**默认 tracer 为 `callTracer`。** 当提供空的 trace 选项对象 `{}` 时,Monad 默认使用 `callTracer`,而不是其他 EVM 客户端中常见的 struct logs tracer。Monad 目前不支持 VM 级别的操作码 struct logs。

### 不支持的功能

| 功能                            | 影响的方法                                                 | 详情           |
| ----------------------------- | ----------------------------------------------------- | ------------ |
| EIP-4844(blob 交易)             | `eth_sendRawTransaction`、`eth_call`、`eth_estimateGas` | Blob 交易类型被拒绝 |
| `"syncing"` 订阅                | `eth_subscribe`                                       | 不支持          |
| `"newPendingTransactions"` 订阅 | `eth_subscribe`                                       | 不支持          |

## 区块标签

Monad 区块会经历四个 [提交状态](/zh/monad-arch/consensus/block-states):`Proposed`、`Voted`、`Finalized` 和 `Verified`。JSON-RPC API 通过标准的以太坊兼容区块标签来暴露这些状态。

| 区块标签          | Monad 状态    | 指南                                                                                                                            |
| ------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `"latest"`    | `Proposed`  | 延迟最低的视图,但由 [推测执行](/zh/monad-arch/consensus/asynchronous-execution#speculative-execution) 支持 —— 尚未有共识投票。适用于对新鲜度比确定性更看重的读多型 UI。 |
| `"safe"`      | `Voted`     | 由超多数投票支持。回滚需要极为 [不可能的条件](/zh/monad-arch/consensus/monad-bft#the-only-loophole)。                                               |
| `"finalized"` | `Finalized` | 除非硬分叉,否则不可逆转。适用于价值结算:桥、存款、支付入账。                                                                                               |

<Note>`"pending"` 标签受支持,但其行为与 `"latest"` 相同。[了解更多](/zh/monad-arch/consensus/local-mempool)。</Note>

### 未终结的数据

任何包含来自未终结区块数据的 RPC 响应,在后续对同一请求进行时其结果可能发生变化。

* **带有区块号/标签参数的方法**(`eth_call`、`eth_getBalance`、`eth_getLogs` 等)—— 当以 `"latest"` 或未终结的区块号调用时,可能返回未终结的数据。
* **交易哈希查询**(`eth_getTransactionByHash`、`eth_getTransactionReceipt`)—— 可能命中处于未终结区块中的交易。返回的 `blockNumber`、日志索引,甚至结果本身(`null`)都可能发生变化。
* **隐式 latest 的方法**(`eth_gasPrice`、`eth_maxPriorityFeePerGas`)—— 始终使用 `"latest"` 标签返回未终结的数据。

<Tip>
  将来自未终结区块的数据视为临时数据。对于交易哈希查询,在采取行动之前,请将返回的 `blockNumber` 与 `"finalized"` 区块高度(在客户端跟踪)进行比较。
</Tip>

## 限制

### `eth_call` / `eth_estimateGas`

#### 每次调用的 gas 限制

| 提供商              | 公共 RPC                       | Gas 限制   |
| ---------------- | ---------------------------- | -------- |
| QuickNode        | `rpc.monad.xyz`              | 200M gas |
| Alchemy          | `rpc1.monad.xyz`             | 200M gas |
| Ankr             | `rpc3.monad.xyz`             | 1B gas   |
| Monad Foundation | `rpc-mainnet.monadinfra.com` | 200M gas |

<Note>
  **节点运营者**。使用 `--eth-call-provider-gas-limit`(默认 30M)和 `--eth-estimate-gas-provider-gas-limit`(默认 30M)来配置这些限制。
</Note>

#### Gas 限制的解析

当调用者指定了 gas **价格**(`gasPrice` 或 `maxFeePerGas`)时,有效的 gas 限制为 `min(gas 限制额度, 提供商 gas 限制)`,其中 gas 限制额度是给定调用者余额和所指定价格下的最大 gas。当未指定 gas 价格时,直接使用提供商 gas 限制。这与 Geth 的行为一致。

#### 双池执行模型

`eth_call` 和 `eth_estimateGas` 请求会根据调用者指定的 gas 限制被路由到两个执行池之一:

| 池     | Gas 限制      | 用途           |
| ----- | ----------- | ------------ |
| 低 gas | ≤ 8,100,000 | 大多数调用;更高的吞吐量 |
| 高 gas | > 8,100,000 | 大型模拟;并发有限    |

当调用者未指定 gas 限制时,请求会先尝试使用低 gas 池。如果出现 gas 耗尽,则会自动重试到高 gas 池。

<Note>
  **节点运营者**。使用 `--eth-call-max-concurrent-requests`(默认 1000)和 `--eth-call-high-max-concurrent-requests`(默认 20)来配置池的并发度。
</Note>

### `eth_getLogs`

#### 每次调用的区块范围限制

| 提供商              | 公共 RPC                       | 区块范围限制                         |
| ---------------- | ---------------------------- | ------------------------------ |
| QuickNode        | `rpc.monad.xyz`              | 100 个区块                        |
| Alchemy          | `rpc1.monad.xyz`             | 1,000 个区块和 10,000 条日志(以更严格者为准) |
| Ankr             | `rpc3.monad.xyz`             | 1,000 个区块                      |
| Monad Foundation | `rpc-mainnet.monadinfra.com` | 100 个区块                        |

<Note>
  **节点运营者**。使用 `--eth-get-logs-max-block-range` 来配置区块范围限制。
</Note>

#### 为什么区块范围限制这么低?

Monad 每 300ms 产生一个区块,每个区块可容纳最多 3,750 笔交易和高达 150M gas 的计算量。区块既极为频繁,又显著大于以太坊的区块,这是保持每次调用区块范围限制较低的主要原因。

## 错误

Monad 的 JSON-RPC 错误码力求与以太坊等价,但由于以太坊各客户端之间缺乏标准化,某些错误码有所偏差。

### 请求级错误 (-32601)

| 消息                   | 解释                    | 常见原因      |
| -------------------- | --------------------- | --------- |
| Parse error          | 无法解析 JSON-RPC 请求      | JSON 格式错误 |
| Invalid request      | 请求在结构上无效              | 请求超出大小限制  |
| Method not found     | 该方法不属于 JSON-RPC 规范    | 方法名拼写错误   |
| Method not supported | 该方法存在于规范中但 Monad 尚未支持 | 调用了未实现的方法 |

### 参数错误 (-32602)

| 消息                  | 解释                            | 常见原因                                      |
| ------------------- | ----------------------------- | ----------------------------------------- |
| Invalid block range | 请求的 `eth_getLogs` 区块范围超出提供商限制 | 请参见 [区块范围限制](#block-range-limit-per-call) |
| Invalid params      | 方法参数不正确                       | 类型错误、缺少必需字段、省略 trace 选项                   |

### 执行错误 (-32603)

| 消息                         | 解释       | 常见原因                              |
| -------------------------- | -------- | --------------------------------- |
| Internal error             | 请求无法被完成  | 服务端故障                             |
| Execution reverted         | 模拟交易发生回滚 | `eth_call` 或 `eth_estimateGas` 失败 |
| Transaction decoding error | 无法解码原始交易 | `eth_sendRawTransaction` 中 RLP 无效 |

## WebSocket 订阅

Monad 的 RPC 服务器通过 WebSocket 连接支持 JSON-RPC,从而通过 `eth_subscribe` 实现持久连接和实时数据。有关 `eth_subscribe` 的一般行为,请参见 [Geth 文档](https://geth.ethereum.org/docs/interacting-with-geth/rpc/pubsub)。

Monad 在标准订阅类型基础上扩展了两种变体(`monadNewHeads` 和 `monadLogs`),它们包含用于跟踪区块在共识中进展的额外数据。有关推测执行的背景,请参阅 [推测式实时数据](/zh/monad-arch/realtime-data/spec-realtime);关于完整的区块生命周期,请参阅 [区块状态](/zh/monad-arch/consensus/block-states)。

### 订阅类型

| 类型              | 触发时机                                                                                     |
| --------------- | ---------------------------------------------------------------------------------------- |
| `newHeads`      | 区块处于 `Proposed` 状态并已 [推测执行](/zh/monad-arch/realtime-data/spec-realtime) 时,发出一个区块头        |
| `logs`          | 区块处于 `Proposed` 状态并已 [推测执行](/zh/monad-arch/realtime-data/spec-realtime) 时,发出与所提供过滤器匹配的日志 |
| `monadNewHeads` | 与 `newHeads` 相同的已提案区块事件,以及后续的提交状态更新,包括 `commitState`                                     |
| `monadLogs`     | 与 `logs` 相同的已提案区块日志,以及后续针对匹配日志的提交状态更新,包括 `commitState`                                   |

不支持 `syncing` 和 `newPendingTransactions` 订阅类型。

### 推测型订阅行为

`monadNewHeads` 和 `monadLogs` 的更新包含两个标准变体中不存在的额外字段:

* **`blockId`** —— 此特定区块提案的唯一标识符(不同于区块号,因为同一高度可能存在多个提案)。
* **`commitState`** —— 区块当前的 [提交状态](/zh/monad-arch/consensus/block-states):`Proposed`、`Voted`、`Finalized` 或 `Verified`。

同一个区块通常会随着其 `commitState` 在生命周期内推进而产生多次更新。当共识领先于执行时,区块可能会跳过 `Voted` 直接从 `Proposed` 进入 `Finalized`。当区块未能被终结时,它会被隐式放弃 —— 同一高度上不同区块的终结会取代它,但不会发布明确的放弃事件。
