以太坊智能合约圈流传最久的一条安全守则,是”不要用 tx.origin 做鉴权”。守则流传了近十年,可被告诫的那个操作码始终留在 EVM 里,谁都能调用。EIP-7645 提出了一个釜底抽薪的方案:不再靠文档和 audits 提醒,而是直接修改语义——ORIGIN 操作码在一切上下文中必须返回与 SENDER(也就是 CALLER)相同的值。这条提案 2024 年 3 月创建,目前状态是 Stagnant(停滞)。
两个操作码差在哪
ORIGIN(编号 0x32)返回的是发起这笔交易的最初账户地址;SENDER 或 CALLER(0x33)返回的是当前这一层调用的直接发起者。一笔交易穿过多层合约调用时,ORIGIN 从头到尾不变,CALLER 每进一层就换一次。合约如果拿 ORIGIN 与某个地址比较来判定”是不是本人操作”,在多跳调用里判的其实是”整条调用链的最上游是谁”,而不是”直接触我的人是谁”。这个区别正是钓鱼结构的生长点:诱导受害者调用一个恶意合约,恶意合约再去调用受害者的钱包合约,此时受害者钱包里的 ORIGIN 仍然是受害者本人,鉴权形同虚设。自 2016 年年中起,这种滥用就有公开记录,安全文档也长期劝退该用法。
账户抽象为什么绕不过它
提案把更大的动机放在账户抽象上。以 ERC-4337 为例,打包者(bundler)用自己的地址为整包用户操作预付 gas;如果智能合约的权限判断看 ORIGIN,那么同一批被打包的每笔用户操作看到的都是 bundler 的地址——任何一笔被打包的交易都可能借这个身份冒领本应属于打包者的权限。更一般地,EIP-7377、EIP-3074 这类方向都不得不先处理 ORIGIN:要么改它,要么绕它。提案的论点是与其让每个账户抽象方案各打各的补丁,不如把 ORIGIN 一次性别名成 SENDER,让 EOA 与智能合约账户在同一套语义下被平等对待,同时顺手清掉这块历史技术债、简化 EVM 的执行模型。
机制与不兼容面
规范文本很简短:ORIGIN(0x32)必须在所有执行上下文中返回与 SENDER 相同的值;客户端实现上,遇到 ORIGIN 就按执行 SENDER 处理。交易结构与验证逻辑不动。提案自己也承认这不是完全向后兼容的改动——凡是依赖 ORIGIN 与 SENDER 之差做逻辑或做安全边界的合约都会受影响。它的辩护理由是:这种用法本来就长期被弃用、影响面小,而且任何账户抽象方案最终都要直面 ORIGIN,早拆比晚拆便宜。提案还建议在 EVM 之外用工具层禁止乃至在部署环节拦截继续使用 ORIGIN 的代码,属于范围之外的补充建议。
一条自查线
对普通读者,这条提案最实际的用处是一把旧合约体检尺:如果某个合约的权限逻辑依赖 tx.origin,那么它要么在硬分叉别名化之后行为改变,要么本来就有被人多跳冒用的敞口。两者都不是好信号。
一次调用的两种问法
把两枚操作码想成合约在调用栈里能问出的两个问题。CALLER 问的是”直接按我门铃的人是谁”,答案随调用深度逐层变化;ORIGIN 问的是”这串门铃最初由谁敲响”,答案从交易第一帧起就冻结。两种问法在简单的单一调用里恰好同答,这正是许多人误以为可以互换的原因——测试网里随手写的一笔直连交易永远测不出差异。真正区分它们的是路径长度:只要资金或权限的链条经过第二只手,两个答案就开始分家,而攻击恰恰只在分家处成形。理解了这个”同答是巧合、分答是常态”的结构,就能明白为什么提案认为把两问合一比继续教育市场”别用第一问”更彻底:语言层面的禁令管不住编译器与老代码,语义层面的合并才管得住。
快速问答
问:tx.origin 还能读吗? 答:能。被建议改掉的是它的返回值语义,不是把它删除;提案状态下主网仍是旧语义。
问:别名化会让钓鱼合约立刻失效吗? 答:它消灭的是”靠 ORIGIN 鉴权的合约被多跳冒名”这一类具体漏洞;其他钓鱼手段不受影响。
问:这条提案现在生效了吗? 答:没有,状态为 Stagnant。以当前主网为准,ORIGIN 仍返回交易最初发起者。
风险提示:涉及合约授权与签名逻辑的操作请先做只读核查与小额验证,本文不构成投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。