以太坊能否彻底移除SELFDESTRUCT?

本文分析了以太坊坎昆升级后(区块20M-25M)SELFDESTRUCT操作码的使用情况。

Cancun 后主网 SELFDESTRUCT 使用报告——区块 2000 万–2500 万

已发布数据集(472,641 个事件):https://gist.github.com/chfast/7923cc97710e6e788b2fcd840c17ffb0

1. 数据格式

数据集为 CSV 格式,包含一个标题行,每个 SD-SAMETX 事件占用一行。行按收集顺序追加,大致按 block 的时间顺序排列。所有十六进制字段均为小写,不带 0x 前缀。

标题行

block,tx,addr,ben,balance,origin,caller,initcode,codesize,codehash

列说明

类型 含义
block 十进制 uint64 包含 SELFDESTRUCT 的区块编号
tx 32 字节十六进制 交易哈希
addr 20 字节十六进制 被销毁合约的地址
ben 20 字节十六进制 受益人(addr 的 ETH 余额接收方)
balance 十进制 wei SD 操作码执行时的 ETH 余额
origin 20 字节十六进制 顶层签名者 EOA(evm.TxContext.Origin
caller 20 字节十六进制 被销毁合约的直接调用方——通常是部署并立即销毁(deploy-and-die-in-constructor)模式中的工厂;对于直接的合约创建交易,等于 origin
initcode 01 1 表示 SD 在构造函数内触发(运行时代码从未持久化);0 表示 SD 在构造完成后触发(运行时代码当前存在于状态中)
codesize 十进制字节 (仅当 initcode=0 时;否则为空) 持久化运行时代码的大小
codehash 32 字节十六进制 (仅当 initcode=0 时;否则为空) 持久化运行时代码的 keccak256 哈希

关于 initcode 的检测说明:它是在 SD 操作码执行时从 IntraBlockState.GetCodeSize(self) 设置而来的。在构造函数帧中,运行时代码尚未存入(SetCodeevm.Run() 返回后执行),因此 codesize == 0 能可靠地标记为构造函数内的情况。一个具有空运行时代码的持久化合约无法到达 SD(对空代码地址的调用不会分派任何操作码),因此等价关系 initcode == 1 ⇔ 在构造函数帧中 在实践中成立。

范围:仅 SD-SAMETX

此数据集仅包含 SD-SAMETX 事件(Cancun 后同一交易创建的合约的每个 SELFDESTRUCT,即 EIP-6780 实际销毁账户的路径)。生成此数据的 Erigon 工具还会发出其他三个标签——SD-BURNSD-BROKEN-BURNFINAL-BURN——涵盖正交现象(销毁账户、EIP-6780 阻止的销毁、延迟销毁)。这些标签不在本 CSV 中,也不在此分析中,因为它们与本报告调查的问题“移除 EIP-6780 会在状态膨胀方面带来什么代价”无关。

2. 关键数字(仅 SD-SAMETX)

指标
SD-SAMETX 事件总数 472,641
区块范围 20,000,000 → 24,999,999(500 万个区块,约 695 天 @12秒)
唯一 CREATE2 地址(= 如果 SD 被禁用,则为浪费的账户 413,508
硬失败事件(事件数 − 唯一地址数;重新部署时的 CREATE2 冲突) 59,133(12.51%)
浪费的代码字节(对 initcode=0 的唯一地址的 codesize 求和) 3,268,302 字节(约 3.27 MB)
initcode=0 合约中唯一的运行时代码哈希 305
按代码哈希去重后的浪费代码字节(每个唯一哈希仅保留一份副本) 909,207 字节(约 909 KB)

每个指标的计算方式

模型如下:在没有 SD 的世界中,每个唯一 CREATE2 地址的 首次 部署成功并留下一个持久化账户;之后在同一地址上的每次部署都会硬失败(当目标地址具有 nonce != 0 或非空 codehash 时,CREATE2 冲突检查会拒绝部署)。

浪费的账户数        =  N_unique_addrs
                          (每个唯一 CREATE2 地址恰好留下一个持久化账户——类别和 initcode 对计数不重要,只影响账户中的内容)

硬失败事件数        =  N_total_events − N_unique_addrs
                          (在已存在于状态中的地址上的事件会触发 CREATE2 冲突并回滚)

浪费的代码字节      =  Σ codesize  针对 initcode=0 的唯一地址
                          (initcode=1 意味着运行时代码从未存入——持久化账户会带有空代码,因此不计入代码字节)

去重后的浪费代码字节 =  Σ codesize  针对 initcode=0 的唯一 codehash
                          (Erigon 的状态存储以 codehash 为键存储代码,因此在许多地址上部署的相同模板会在 trie 中共享同一份代码块)

3.27 MB 到 909 KB 的压缩比(约 3.6 倍)反映了相同的 Deposit/Wrapper 模板被部署在许多不同的地址上。状态实际上只会增加约 909 KB 的新代码,但会增加约 41.4 万个新账户记录。

3. 使用类别

每个事件根据以下决策树分为六大类之一(第一个匹配优先):

A_DirectScript            origin == caller
                          (顶层 CREATE 交易;无工厂合约)

B_SharedFactory           caller 有 ≥ 2 个不同的 origin
                          (一个工厂合约被多个操作者使用)

C_SybilBatch              origin 使用 ≥ 3 个不同的工厂,并且 事件数/交易数 ≥ 3
                          (单个操作者轮换使用多个工厂,每笔交易批量部署多个临时合约)

D_MultiTenantAggregator   (origin, caller) 有 ≥ 5 个不同的受益人
                          并且 事件数/受益人数 < 50
                          (一个操作者加一个工厂路由到多个客户钱包,每个受益人交易量少)

E_DepositForwarder        该事件的 addr 在日志中出现 ≥ 2 次
                          (CEX 风格:同一 CREATE2 地址被重新部署)

F_OneShot                 其他情况
                          (单租户存款转发器,不重用地址——每次都使用新的 CREATE2 地址)

阈值(Sybil 类别:f ≥ 3 && ept ≥ 3;MultiTenant 类别:bens ≥ 5 && events/ben < 50)是在较小的样本上调优的,以免多租户检测器误判在少量热钱包之间轮换的单租户操作者。

按类别细分(合并日志,472,641 个事件)

类别 事件数 %ev 唯一地址数 硬失败数 %hf 有代码的地址数 代码字节数 起源数 调用者数
A_DirectScript 34,384 7.3% 34,339 45 0.13% 172 180,069 2,098 2,098
B_SharedFactory 98,972 20.9% 97,120 1,852 1.87% 1,849 1,140,264 604 79
C_SybilBatch 37,262 7.9% 34,638 2,624 7.04% 264 45,634 28 190
D_MultiTenantAggregator 10,618 2.2% 3,764 6,854 64.55% 90 1,914 7 7
E_DepositForwarder 59,768 12.6% 12,010 47,758 79.91% 496 107,282 112 129
F_OneShot 231,637 49.0% 231,637 0 0.00% 1,048 1,793,139 504 3,251
总计 472,641 100.0% 413,508 59,133 12.51% 3,919 3,268,302

%hf = 该类别内的硬失败率(hard_fail / events);粗体总计是数据集整体比率。

表格解读

  • F_OneShot 占据主导地位(占事件数的 49%),并占唯一浪费账户的 56%。这些操作者已经每次使用新地址——他们不需要地址重用,只是希望避免留下持久化合约。纯状态膨胀吸收者。
  • B_SharedFactory 出乎意料地大(占事件数的 21%,代码字节 1.14 MB)。79 个不同的共享工厂合约共同服务于 604 个不同的 EOA——这是该模式显著的 SaaS 式使用。
  • E_DepositForwarder 集中了硬失败(47,758 个,占全部 59,133 个硬失败事件的 80.8%)。112 个操作者,跨越 129 个工厂。这是真正依赖 EIP-6780 同一交易重新部署语义的部分。
  • D_MultiTenantAggregator 事件数量极小(2.2%),但硬失败与事件数之比最高(65%)——每个客户都会重新存入,因此大多数事件发生在已重用的地址上。该类别只有 7 个不同的操作者。
  • C_SybilBatch 占 7.9%,符合空投/挖矿模式:28 个操作者平均轮换使用约 7 个工厂(190 个调用者 ÷ 28 个起源),批量部署临时辅助合约。
  • A_DirectScript 占 7.3%——超过 2000 个不同的 EOA 各自运行自己的单次 init-code-as-script 模式。没有工厂。

4. 每 10 万区块桶的频率

计算方法:bucket = floor(block / 100_000) * 100_000;每个桶的事件数只是 block 落在 [bucket, bucket + 100_000) 范围内的 SD-SAMETX 行的计数。

 20,000,000   5,392  #####
 20,100,000   4,255  ####
 20,200,000   4,272  ####
 20,300,000   6,087  ######
 20,400,000   5,129  #####
 20,500,000   4,803  ####
 20,600,000   5,013  #####
 20,700,000   5,308  #####
 20,800,000   4,613  ####
 20,900,000   4,849  ####
 21,000,000   6,090  ######
 21,100,000   6,539  ######
 21,200,000   4,414  ####
 21,300,000   3,761  ###
 21,400,000   3,412  ###
 21,500,000   4,120  ####
 21,600,000   4,185  ####
 21,700,000   5,195  #####
 21,800,000   5,335  #####
 21,900,000   4,714  ####
 22,000,000   5,651  #####
 22,100,000   6,143  ######
 22,200,000   6,928  ######
 22,300,000   6,735  ######
 22,400,000   5,649  #####
 22,500,000   6,599  ######
 22,600,000   7,057  #######
 22,700,000   9,515  #########
 22,800,000   9,049  #########
 22,900,000   8,573  ########
 23,000,000 100,530  ####################################################################################################
 23,100,000   7,647  #######
 23,200,000   7,522  #######
 23,300,000   7,291  #######
 23,400,000   8,049  ########
 23,500,000   8,847  ########
 23,600,000   8,389  ########
 23,700,000   8,121  ########
 23,800,000   7,787  #######
 23,900,000  11,747  ###########
 24,000,000   8,907  ########
 24,100,000   7,757  #######
 24,200,000   9,079  #########
 24,300,000  17,025  #################
 24,400,000  17,207  #################
 24,500,000  15,887  ###############
 24,600,000  13,394  #############
 24,700,000  13,835  #############
 24,800,000  10,026  ##########
 24,900,000  14,209  ##############

(1 个字符 ≈ 1,000 个事件。)

趋势解读

  • 背景区间(20.0 M – 22.6 M):平稳,大约每 10 万区块 4–7 k 事件(约每天 50–80 事件)。Cancun 后的稳定采用。
  • 第一次跃升(约 22.7 M):上升至约 7–10 k。
  • 23.0 M 处的异常:单一 10 万区块窗口内 100,530 个事件——是周围速率的 13 倍。可能是一个操作者/一笔批量交易主导;标记出来待单独调查。
  • 平台期(23.1 M – 23.8 M):稳定在约 7–9 k。
  • 第二次跃升(约 24.3 M):翻倍至约 14–17 k。此态势持续至样本结束。

总体趋势:从窗口开始到结束,使用量大约增长到原来的三倍(每 10 万区块 5 k → 约 14 k),其中在 23.0 M 处有一次异常峰值。

  • 原文链接: ethereum-magicians.org/t...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
以太坊中文
以太坊中文
以太坊中文, 用中文传播以太坊的最新进展