EIP-2015 详解:`wallet_updateEthereumChain` 钱包链切换 RPC 方法

原创2026-09-14 12:42:56105 阅读
文章标签:区块链文档Web3

EIP-2015 详解:wallet_updateEthereumChain 钱包链切换 RPC 方法

导读

EIP-2015 是 Ethereum Improvement Proposal 仓库(EIPS 目录)中定义的一条 Interface 类别标准提案,它向钱包的 web3 provider API 新增了一个 wallet_ 命名空间下的 RPC 端点 wallet_updateEthereumChain,用于在 EVM 兼容链之间进行切换,并在钱包尚未识别该链时将其注册进去。读完本文,你将掌握该方法的完整 TypeScript 参数结构、chainId 等各字段的语义与约束、返回值与 4001 错误码约定,以及 SSRF、钓鱼攻击等安全设计要点,并了解它与 wallet_addEthereumChain(EIP-3085)、wallet_switchEthereumChain(EIP-3326)等兄弟方法的定位差异。

提案背景:为什么需要"切换链"的标准化接口

DApp 生态中,钱包通常通过一个 JavaScript Provider 对象向页面暴露 API(见 EIP-1193)。不同的钱包对 Provider 的实现历史上存在接口与行为冲突,而"在 EVM 兼容链之间切换"更是长期缺乏统一标准:DApp 无法用一套通用的 JSON-RPC 调用,要求钱包切换到某个指定网络。

EIP-2015 正是为了填补这一空白而提出:它定义了一个钱包命名空间下的 RPC 方法 wallet_updateEthereumChain,让 DApp 可以携带最少的必要参数请求钱包切换网络。该方法只要求 chainId 一个必填字段,其余字段(chainName、rpcUrls、nativeCurrency、blockExplorerUrl)均为可选,是"设计得尽可能简单,同时又能提供切换新链所需必要信息"的产物——因为 chainId 是唯一保证全局唯一的参数,其余字段本质上只是对钱包的"建议"(suggestion)。

规范:wallet_updateEthereumChain 方法定义

方法语义

wallet_updateEthereumChain 用于切换到一个网络;如果该网络尚未被钱包识别,则同时将其注册到钱包中。它接收一个参数——EthereumChainSwitchRequest 对象,其完整 TypeScript 定义如下(原文出自 eip-2015.md):

interface NativeCurrencyData {
  name: string;
  symbol: string;
  decimals: number;
}

interface EthereumChainSwitchRequest {
  chainId: string;
  chainName?: string;
  rpcUrls?: string[];
  nativeCurrency?: NativeCurrencyData;
  blockExplorerUrl?: string;
}

该规范的约束词(MUST / MUST NOT / REQUIRED / SHALL / SHALL NOT / SHOULD / SHOULD NOT / RECOMMENDED / MAY / OPTIONAL)按 RFC 2119 解释。

参数语义逐字段解析

  • chainId(必填):以 0x 为前缀、符合 EIP-155 的链 ID 字符串。EIP-155 规定交易签名时需将 chainid 纳入九元素 RLP 编码(nonce, gasprice, startgas, to, value, data, chainid, 0, 0),签名 v 值设为 {0,1} + CHAIN_ID * 2 + 35,从而天然实现重放攻击防护;各条链通过唯一的 CHAIN_ID 区分,因此 chainId 是识别链的唯一可靠依据。主网为 1,Goerli 为 5,Geth 私有链默认 1337(完整列表见 eip-155.md)。
  • chainName(可选):建议的、人类可读的链名称,用于向用户展示。
  • rpcUrls(可选):针对该 chainId 的 RPC 端点列表。
  • nativeCurrency(可选):建议原生币的展示方式,其 name、symbol、decimals 三个字段的语义应参照 EIP-20(ERC-20)来解释——即 name 为代币全称、symbol 为交易符号、decimals 为小数位精度。
  • blockExplorerUrl(可选):应指向与该 chainId 兼容的区块浏览器。

关键行为约束

  • 除 chainId 外,所有键均为可选,且都是对钱包的"建议";钱包可以选择忽略,或向用户展示其他数据。
  • 钱包在切换或添加链之前,应提示用户并获得确认(prompt the user)。
  • 钱包应内置一份常用链的默认数据列表,以避免钓鱼攻击。
  • 钱包在使用每个 RPC URL 发送其他请求之前,必须对其进行净化(sanitize),包括确认它能正确响应 net_version 与 eth_chainId 方法——后者由 EIP-695 定义,用于可靠地标识当前通信的链。
  • 只要当前活动链与请求的链一致,方法即返回 true,无论该链此前是否已处于活动状态、还是本次才被添加到钱包中。
  • 若用户拒绝该请求,必须返回错误码为 4001 的错误——该错误码对应 EIP-1193 中 Provider 错误标准表里的 "User Rejected Request"(见 eip-1193.md)。

一次典型的 JSON-RPC 调用

EIP-2015 原文未给出调用示例,但作为 wallet_ 系列方法,其调用形态遵循标准 JSON-RPC 2.0 约定(同类方法示例可参考 EIP-3326)。以下为切到主网并携带元数据的示意请求:

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "wallet_updateEthereumChain",
  "params": [
    {
      "chainId": "0x1",
      "chainName": "Ethereum Mainnet",
      "rpcUrls": ["https://mainnet.infura.io/v3/YOUR-PROJECT-ID"],
      "nativeCurrency": {
        "name": "Ether",
        "symbol": "ETH",
        "decimals": 18
      },
      "blockExplorerUrl": "https://etherscan.io"
    }
  ]
}

成功时返回 true(活动链与请求链一致);用户拒绝时返回 code: 4001 的错误对象。

设计理由(Rationale)

规范原文从三个方面阐述了设计动机:

  1. 极简但够用:chainId 是唯一必填参数,因为它是唯一保证唯一的标识;chainName 提供人类可读名称;rpcUrls 提供 RPC 端点列表;nativeCurrency 提供原生币展示建议;blockExplorerUrl 提供区块浏览器链接。
  2. 命名空间隔离:方法挂在 wallet_ 前缀下,避免与其他方法冲突。该前缀被许多钱包专属方法使用,如 wallet_addEthereumChain 与 wallet_switchEthereumChain。
  3. 与兄弟方法互补:在仓库的 EIPS 目录中可以看到完整的 wallet_ 家族——EIP-3085 的 wallet_addEthereumChain 负责"添加链"(返回 null),EIP-3326 的 wallet_switchEthereumChain 只负责"切换活动链"(仅接收 chainId 单字段参数,返回 null),而本 EIP-2015 的 wallet_updateEthereumChain 则将"切换 + 必要时注册"合二为一(返回 true)。三者共用 wallet_ 命名空间与 0x 前缀十六进制 chainId 约定,DApp 可根据场景选用。

向后兼容性

该提案被判定为完全向后兼容(fully backwards compatible):它只是向钱包的 provider API 新增一个方法,不改变任何既有 RPC 方法的语义,也不影响已有的签名、交易格式或网络行为。值得注意的是,本提案在仓库中状态为 Stagnant(停滞),且作者后续通过 EIP-3085 / EIP-3326 将"添加"与"切换"拆分为两个更细粒度的方法,这正体现了标准演进中"先合并、后拆分"的实践路径。

安全考量

服务端请求伪造(SSRF)

rpcUrls 参数携带的是链的 RPC 端点列表,钱包在向这些端点发起任何请求之前必须逐一净化,核心手段是确认端点能正确响应 net_version 与 eth_chainId。这一约束的意义在于:恶意请求者可能提交指向内网地址、本地主机或其他敏感目标的 URL,诱导钱包充当代理发起请求(即 SSRF 攻击面)。EIP-2015 要求钱包先验证端点身份(eth_chainId 返回值应与请求的 chainId 匹配),再将其用于后续请求,从而阻断这一风险。可对照 EIP-3085 中更严格的同类要求:钱包必须拒绝 file: 或 http: 协议的 URL,且必须在任一 RPC URL 的 eth_chainId 与请求 chainId 不匹配时拒绝整个请求。

钓鱼攻击

由于 chainName、nativeCurrency、blockExplorerUrl 等展示类元数据完全由请求方提供,恶意 DApp 可能伪造"知名链"的名称与图标来欺骗用户。为此规范要求钱包内置一份常用链的默认数据列表,以已知可信数据覆盖或校验请求方提交的元数据,从源头削弱钓鱼攻击的成功率。这与 EIP-3085 安全章节中"维护已知链列表、校验请求、优先采用钱包自身元数据"的建议一脉相承。

用户确认与隐私

  • 钱包在切换或添加链之前应该提示用户(prompt),用户拒绝时返回 4001 错误,确保任何链的变更都经过用户明确授权。
  • 结合 EIP-1193 的错误标准(eip-1193.md),4001 属于 Provider 错误码体系的一部分,与 4100(Unauthorized)、4200(Unsupported Method)、4900(Disconnected)、4901(Chain Disconnected)并列,DApp 端可按统一约定解析。

与仓库其他文档的关联

深入阅读本仓库可建立完整的 wallet_ 方法知识图谱:

  • eip-2015.md:本提案原文(wallet_updateEthereumChain,切换 + 注册,返回 true);
  • eip-3085.md:wallet_addEthereumChain,添加链并返回 null,含最严格的 URL 与 chainId 校验要求;
  • eip-3326.md:wallet_switchEthereumChain,仅切换活动链,参数只有 chainId,并明确引用本提案与 EIP-3085 作为相关工作;
  • eip-155.md:chainId 的来源与重放攻击防护原理;
  • eip-695.md:eth_chainId 方法,RPC URL 净化的验证手段;
  • eip-1193.md:Provider API 与 4001 等错误码的标准来源;
  • eip-20.md:nativeCurrency 字段语义的解释依据(该文件在仓库中已移至 ERC 仓库,链接指向 LICENSE.md 说明版权豁免)。

综上,EIP-2015 为钱包生态提供了一种"一键切换并注册 EVM 链"的标准化入口,其极简参数模型、以 chainId 为核心的唯一性设计,以及对 SSRF、钓鱼攻击的防御要求,至今仍是钱包实现多链切换能力时的重要参考。

登录后查看全文
EIPs