“调用SELFDESTRUCT,合约代码就从链上消失”已经不是主网当前的一般结论。EIP-6780把这个操作拆成两种情况:绝大多数时候只把余额发送给目标地址;只有合约在同一笔交易内刚创建又立即销毁时,才保留删除代码和存储的旧效果。
| 场景 | 余额 | 代码与存储 | 后续调用 |
|---|---|---|---|
| 普通既有合约执行 | 转给目标地址 | 保留 | 地址仍有原代码 |
| 同交易创建后执行 | 转给目标地址 | 按旧语义删除 | 交易后不保留实例 |
| 仅观察历史区块 | 按分叉规则 | 取决于当时规则 | 必须固定区块高度 |
为什么协议要改变删除行为
旧SELFDESTRUCT会在交易结束时移除代码和存储,给状态树实现、Verkle迁移和合约生命周期分析带来复杂度。EIP-6049先把该操作标记为弃用风险,EIP-6780随后限制删除效果。名称与操作码仍存在,但开发者不能从名字推断当前行为。
删除语义只有两条路线
- EIP-6780后,SELFDESTRUCT通常把余额发送给目标地址,但不会删除执行账户的代码、存储或账户本身。
- 若合约在同一笔交易中被创建后又执行SELFDESTRUCT,则保留升级前的删除行为。
- EIP-6049已经警告开发者不要依赖SELFDESTRUCT的既有删除语义,EIP-6780进一步改变了其功能。
余额清空不等于账户消失
普通既有合约执行后,余额会被转出,代码和已有存储却继续存在。之后别人仍可能向这个地址发送ETH,合约函数也仍可调用。把SELFDESTRUCT当作“紧急停机”会留下可执行代码;把它当作“清空后重新部署”也会遇到目标地址已有代码或nonce的创建碰撞。
升级和取证必须固定分叉高度
分析旧交易时,不能用今天的规则重演所有历史。节点按区块当时生效的硬分叉语义执行;跨链EVM网络采用EIP-6780的时间也可能不同。审计报告应同时记录chainId、区块号、代码哈希以及合约是否在同一交易中创建。
浏览器里的自毁标签会误导
两个常见误判值得排除:区块浏览器显示“Selfdestruct”事件,不代表代码一定被删;当前余额为零,也不代表该地址不再能执行。真正结论要来自区块上下文、创建时点和eth_getCode等链上读取,而不是操作名称。
迁移旧合约的核对顺序
- 确认网络和目标区块是否已启用EIP-6780
- 追踪合约创建交易与SELFDESTRUCT是否同笔
- 分别记录余额、code和关键storage
- 不要用自毁承担升级或权限撤销职责
- 为旧依赖设计显式暂停与迁移方案
如果系统依赖确定性重新部署,应连同CREATE2地址公式检查;读取代码与账户证明可参考eth_getProof验证方法,交易执行是否成功则看交易回执字段。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。