You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solidity的view函数中msg.sender能否被伪造?

核心原因说明

你观察到的现象不是合约漏洞,也不是ethers.js的逻辑问题,本质是以太坊eth_call接口的固有设计:

  • 所有不发送链上交易的view/pure函数调用,底层都会走节点的eth_call接口完成。这个接口的作用是在节点本地的EVM环境里模拟执行交易,全程不会广播交易、不会产生任何链上状态变更,本身就不要求调用方提供私钥签名,也不会校验你传入的from(也就是合约里的msg.sender)地址的实际控制权。你传什么地址当调用者,节点模拟的时候就会用什么地址作为msg.sender跑合约代码,全程没有身份校验环节。
  • 你甚至不需要用ethers.js,直接给公开RPC节点发HTTP请求,把from字段填成任意地址(包括零地址、知名地址、任意合约地址),调用带onlyOwner校验的view函数都能顺利拿到返回值,这个过程和真实的链上执行完全无关。
  • 你提到的setSecret这类会改链上状态的函数调用必须发真实交易,交易需要对应私钥生成的合法签名,节点广播、矿工打包环节会强制校验签名和from地址的匹配关系,伪造地址的交易根本没法上链,自然会执行失败。
可行的校验方案

首先要明确一个前提:你永远没法在合约层面阻止别人伪造msg.sender做eth_call模拟调用——模拟执行完全发生在节点本地,根本不会走到链上共识层,合约代码管不到节点的本地行为。所有依赖msg.sender做权限控制的view函数,对公开RPC节点来说都是不设防的,任何人都能传对应地址绕过修饰器校验拿到返回值。
如果需要确认调用者确实是对应地址的实际持有人,可以参考以下方案:

  • 所有涉及敏感操作、需要强身份校验的逻辑,不要放在view函数里做纯链下返回,必须放到会触发真实链上交易的函数中,依托以太坊交易本身的签名校验机制做身份验证,这是链上唯一可靠的身份校验方式。
  • 如果业务场景必须在链下向授权地址返回敏感数据,不要依赖合约view函数的权限修饰器做拦截:
    • 可以采用签名挑战机制:给调用方返回一个随机生成的挑战串,要求调用方用自己的私钥对挑战串签名,校验端通过ecrecover恢复出签名地址,确认地址在授权列表后再返回对应数据。
    • 如果敏感数据必须存在链上,可以将数据用授权地址的公钥加密后上链,就算他人伪造msg.sender通过模拟调用拿到链上存储的密文,没有对应私钥也无法解密得到真实数据。
  • 不要信任公开RPC节点返回的带权限view函数执行结果,这类结果完全可以被调用方通过伪造from参数篡改,没有任何可信性。

注意:很多开发者误以为给view函数加onlyOwner这类权限修饰器就能阻止非授权地址读取数据,实际上这类修饰器只会在真实链上交易执行时生效,对eth_call的模拟执行没有任何身份拦截能力。

内容的提问来源于stack exchange,提问作者GGizmos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 21:51:27