一、C1 控制流

术语 含义 出处
重入(reentrancy) 函数执行到一半时被再次进入,此时状态是半更新的 1
CEI 检查 → 生效 → 交互。⭐ 第一道防线,重入锁只是第二道 1
跨函数重入 进入点和出手点是不同的函数。⚠️ 单函数加锁完全无效 12
跨合约重入 两个合约共享状态,各自加了各自的锁 1
只读重入 不写任何状态也能被打穿:外部在中间态读到了不自洽的值 3
ERC-777 钩子 tokensToSend 在扣款之前回调转出方;钩子任何人可注册 2
控制权移交 ⭐ 在 EVM 里,向合约地址转账 = 调用它的代码 1

二、C2 权限与身份

术语 含义 出处
delegatecall 借别人的代码在自己的存储上下文里执行 4
未初始化的实现合约 ⭐ 实现合约是一个活合约,可被任何人初始化并夺取 5
_disableInitializers() 构造函数里锁死实现合约自身的初始化 5
混淆代理人 ⭐⭐ 一个有权限的实体被诱导替没有权限的人执行操作 6
函数选择器碰撞 ⚠️ 4 字节 = 2³² ≈ 43 亿,普通电脑几分钟可穷举 6
零值即有效值 mapping 对不存在的 key 返回零值 ⟹ 零值必须表示"不存在" 7
僵尸权限 当初有理由、现在没人记得的授权 22
利用门槛 利用漏洞所需的能力,决定损失速度(复制粘贴级 ⟹ 全民哄抢) 7

三、C3 数值

术语 含义 出处
类型范围 vs 业务范围 ⭐⭐ 算术运行在类型范围上,除非你显式对齐 8
校验代码里的溢出 ⚠️ 溢出发生在用于判断的算式里 ⟹ 防线消失而一切正常 89
batchOverflow cnt × value 溢出成 0 ⟹ 余额检查恒真 9
0.8 不检查类型转换 uint128(x) 越界静默截断,不 revert ⟹ 用 SafeCast 9
错误的检查 比没有检查更危险——它把语言层的兜底也关掉了 11
舍入攻击 舍入方向反了 ⟹ 极小额反复调用,累积的、无声的损失 19
域分隔 叶子 H(0x00‖x)、内部节点 H(0x01‖l‖r) 10
证明必须绑定三样 根匹配 + 叶子确实是叶子 + 位置唯一 10

四、C4 外部数据

术语 含义 出处
闪电贷 ⭐⭐ 本身完全安全。它把攻击者集合从"有几百万的人"变成"所有会写 Solidity 的人" 12
现货价操纵 恒定乘积池推到 k 倍需 y(√k − 1);k=2 ⟹ 41% 储备 12
两次读数之间的差 ⭐ 不只问"能否被操纵",还要问"读两次之间能否被改变" 13
往返不变量 存入后立即取出必须亏钱。五行代码,覆盖面极大 1319
捐赠攻击 直接 transfer 抬高 totalAssets不铸造份额、不触发任何事件 15
抽象泄漏 ⭐ 接口给的是一个数,你用它做的是一个判断——差距就是没写下来的假设 14
正确地报告了错的东西 ⚠️ 预言机没坏、没人撒谎、没有 bug,钱照样没了 14
清算可行性 清算需要有人接盘。卖不掉的抵押品,清算只是无法执行的承诺 16
多层依赖脆弱性 攻击最弱一环,收益按最上层算 16

五、C5 经济与博弈

术语 含义 出处
可租用的权力 ⭐⭐ 任何能在一个区块内获得的权力都不是权力 17
治理攻击 闪电贷买投票权 ⟹ 投票 ⟹ 通过 ⟹ 执行,全在一笔交易内 17
投票权快照 ⭐ 时点必须早于提案创建 ⟹ 闪电贷彻底失效 17
应急通道 ⚠️ 一条合法的、绕过全部保护的路径。应只能"做减法" 17
自我清算 主动把自己弄成深度不健康,吃最高档清算折扣 18
约定 vs 机制 ⭐ “所有 X 都要做 Y"应实现成”不做 Y 就无法成为 X" 18
递增激励的反向利用 “情况越糟奖励越高” ⟹ 有人会把情况弄糟 18
第一存款人攻击 空金库存 1 wei + 捐赠 ⟹ 后续存款人份额向下取整成 0 19
虚拟份额偏移 OZ 的 _decimalsOffset:offset=6 ⟹ 攻击成本 ×10⁶ 19

六、C6 工具链

术语 含义 出处
信任基础(TCB) ⭐⭐ 代码 + 编译器 + 依赖库 + 部署流程 + 前端 + 开发机 2025
编译器 bug ⚠️ 源码正确、字节码错误。读源码发现不了 20
可复现构建 重新编译并与链上字节码逐字节比对 20
验证运行时行为 ⭐ 安全测试要验证字节码的实际行为,不是源码写了什么 20
供应链攻击 攻击者不攻击你,他攻击你信任的东西 25

七、C7 密钥与签名流程

术语 含义 出处
名义门槛 vs 实际门槛 ⭐⭐ 按"共享攻击面"给密钥分组。Ronin 名义 5/9,实际 1/1 22
盲签 ⭐签的是一个哈希,对它含义的理解全部来自一个可能被攻破的界面 23
operation = 1 ⭐ Safe 交易里的 DELEGATECALL。等于把整个钱包交出去 2325
签名的语义鸿沟 签名证明"某把私钥同意了某个哈希",不证明那个人理解了它 23
异常的常态化 ⭐ 事故最可靠的前兆,是一个被大家习惯了的小毛病 24
定向投毒 ⚠️ 恶意代码只对特定目标激活 ⟹ 抽查和用户反馈结构上失效 25
引用类输入 ⭐ address / account / index / selector —— 也是需要被验证的输入 21
结构性 vs 程序性防御 前者不依赖人(白名单、限额、时间锁),后者依赖人正确执行 25
检测时间 一个可以设计的安全参数。六天 ⟹ 追回无望;几分钟 ⟹ 可止损 22

八、⭐ 反复出现的十条

 1. ⭐⭐ CEI 是第一道防线,锁是第二道                    [1][20]
 2. ⭐⭐ 凡是"本该只发生一次"的事,必须有显式状态位保证  [4]
 3. ⭐⭐ 零值必须表示"不存在"                            [7]
 4. ⭐⭐ 算术运行在类型范围上,不是业务范围上            [8][9]
 5. ⭐⭐ 任何单区块内可改变的量,不能单独决定资金去向    [12][17]
 6. ⭐⭐ "所有 X 都要做 Y" ⟹ "不做 Y 就无法成为 X"       [18]
 7. ⭐⭐ 引用(地址/账户)也是需要验证的输入              [6][21]
 8. ⭐⭐ 限额是唯一在"验证已失守"后还起作用的机制        [7][10][21]
 9. ⭐⭐ 结构性防御 > 程序性防御                          [25]
10. ⭐⭐ 漏洞常常长在两份代码之间,而审计按合约划范围     [2][3][7]

相关上线前检查清单 · 复盘来源与工具