还记得《我是一个区块链黑客(第一篇)》结尾那份防范清单吗?最后一条写着”定期审计合约代码”——一句话打发了价值几十万美元的行业服务,堪称全文最省钱的一条建议。无独有偶,聊 DeFi 保险的《DeFi 保险:谁来保护你的链上资产?》更直接,把”审计次数”列进了协议风险评分表。
那么问题来了:审计到底是什么?谁在审?报告怎么读?普通人能不能自己跑两下?本文就回答这四个问题。
先把心态立正:审计不是保险单。这话怎么理解?想想体检。体检报告只能告诉你”抽血那天的你”状态如何,不能保证你一年不生病;车过了年检,上了高速照样可能爆胎。被多家审计公司轮番体检过的协议也一样——Euler Finance 审过不止一轮,2023 年 3 月还是被闪电贷攻击卷走 1.97 亿美元(后来黑客退还了大部分,堪称行业奇观)。原因并不神秘:审计是时间盒(time-boxed)内的抽检,不是数学证明。几个工程师花一两周,对着几万行代码找毛病,找到的是”他们能找到的”,而不是”不存在的”。
本文按四个问题展开:漏洞长什么样、审计怎么跑、报告怎么读、以及你自己怎么动手。读不懂 Solidity 没关系——审计报告本来就不全是写给程序员的,普通用户才是最该会读它的人。看完至少能看懂报告;看得懂代码更好,文末有个一百来行的玩具扫描器等你复现。
一、审计不是保险单,是什么?
先给审计一个准确定位:在有限时间内,用工具加人力,对特定版本的合约代码做一次系统性检查。三个关键词全是限定词,一个都不能丢,每个都值得用体检来翻译一遍:
- “有限时间”(一到四周):医生再厉害,也不可能给你查一整年。抽检就是抽检;
- “特定版本”(审的是哪个 commit 就是哪个 commit):体检报告查的是抽血那天的你。你下周开始熬夜蹦迪,报告管不着;
- “系统性检查”(覆盖已知模式,但不承诺穷尽):套餐查得出脂肪肝,查不出你有没有罕见的食物过敏。
不信的话,看看两份”体检报告”当众失效的著名案例:
- Euler Finance(2023 年 3 月,1.97 亿美元):这个借贷协议审过不止一轮(还办过审计竞赛),但出问题的
donateToReserves函数是最后一轮审计之后新加的,缺了偿付能力检查。体检完第二天就去蹦极,报告救不了你——审计的是 A 版本,上线的是 B 版本,审计结论不随代码演进而自动续期。 - Wormhole(2022 年 2 月,约 3.26 亿美元):这个跨链桥的 Solana 侧合约被安全公司 Neodyme 审过,漏洞出在”补丁提交到了 GitHub、线上程序没更新”。医生开了药,你把处方裱起来挂在墙上,药一粒没吃——代码修了、部署没跟上,等于没修,攻击者伪造守护人签名搬走了约 3.26 亿美元。有意思的是,同一个协议后来通过 Immunefi 给一位白帽付了 1000 万美元赏金——当年创下纪录。钱花在哪、什么时候花,是门学问。
还要补一句:审计审的是合约代码,管不了合约之外的世界。《我是一个区块链黑客(第一篇)》开头聊的 Bybit 事件,14.6 亿美元的损失,Safe 的合约本身没有任何漏洞,问题出在某位开发者的电脑被入侵。体检报告一切正常,不代表你家厨房的煤气阀没漏——审计管不到你同事的电脑,也管不到前端和运维。
所以正确的预期是:审计降低风险,不消灭风险。它和锁门、监控、保险一起构成防御纵深,单独拎出来谁都不是护身符。
二、漏洞都长什么样:六大类
审计公司在找什么?绝大多数被利用的漏洞,逃不出这六类。不用背定义,每类记住一个画面就够:
- 重入攻击:外部转账先于状态更新——余额还没扣,钱已经递出去了,调用者借着转账时的回调”人又回来了”,再取一次。像你把货交给快递员,才想起签收单还没签,而对方已经拿着货去办”下一单”了。历史第一名就是 The DAO 事件(2016 年,约 360 万枚 ETH),《我是一个区块链黑客(第一篇)》用整段代码拆解过。
- 权限控制缺失:该设权限的函数裸奔,或者用
tx.origin做鉴权——钓鱼合约能冒充”最初的交易发起人”通过校验,等于门锁用的是一把人人能配的假钥匙。反过来,onlyOwner滥用是另一个极端:全楼的门只有物业经理一把钥匙,他想开哪间开哪间,去中心化名存实亡(授权模型的细节见《Web3 中的授权与撤销授权》)。 - 预言机操纵:合约自身逻辑没错,但喂给它的价格输入可以被人一手遮天。像体检前有人偷偷调了你的体重秤——你照着秤上的数字填表,表填得再工整也是错的。抵押品被高估,然后凭空贷出真金白银,这是当代 DeFi 被黑的第一大类(详见《预言机:DeFi 里的价格到底是从哪来的?》)。
- 整数溢出:里程表跑过头归零的老问题。Solidity 0.8 起编译器内置了溢出检查,新合约基本免疫;但链上还跑着大量 0.8 之前部署的老合约。2018 年 BEC 代币因为一个整数溢出,把余额直接刷成了天文数字,项目几乎当场归零——那是老一辈”踩坑人”的学费。
- 逻辑与经济模型漏洞:最难查的一类——每一行代码单独看都”对”,但规则组合起来能被玩死。像下棋,对手每一步都合规,连起来就将死了你。2022 年 10 月,Solana 上的 Mango Markets 被人用互相挂单的方式,在低流动性的 MNGO 永续市场里把价格拉到远高于市场的位置,再凭虚高的抵押品贷走约 1.15 亿美元——事后当事人还公开认领,声称这是”合法交易策略”。
- 精度与舍入:Solidity 的整数除法向下取整,单次误差小到可以忽略?配合循环批量操作和闪电贷放大,舍入误差就是利润。超市抹零,一次抹一分没人当回事;可有人一秒钟”抹”你一万次,把零头全扫进自己口袋——这种”蚂蚁搬家”式攻击在收益聚合器里尤其常见。
汇总成一张分类表,方便你以后对着审计报告”按图索骥”:
| 漏洞类型 | 一句话诊断 | 典型事故 | 本博客对应文章 |
|---|---|---|---|
| 重入攻击 | 转账在前、记账在后 | The DAO(约 360 万枚 ETH) | 《我是一个区块链黑客(第一篇)》 |
| 权限控制缺失 | 该锁的门没锁,或锁用了假钥匙 | tx.origin 钓鱼链 | 《Web3 中的授权与撤销授权》 |
| 预言机操纵 | 价格输入被污染 | Mango Markets(约 1.15 亿美元) | 《预言机:DeFi 里的价格到底是从哪来的?》 |
| 整数溢出 | 0.8 以前的时代病,老合约仍有 | BEC 代币刷成天量 | — |
| 逻辑与经济模型 | 代码都对,规则能被玩死 | Euler(1.97 亿美元) | — |
| 精度与舍入 | 向下取整的误差被薅成利润 | 收益聚合器多见 | — |
一个真实实例:Wormhole 的 19 天
第一节那句”药一粒没吃”,值得单独拉出来算一遍,因为它把”修复没部署”的代价标到了小数点后。时间线如下(数字按公开报道口径整理):
| 时间 | 发生了什么 |
|---|---|
| 2022 年 1 月 14 日 | 签名验证漏洞的修复补丁提交到 Wormhole 的 GitHub 仓库——代码修好了,但没有部署到 Solana 链上合约 |
| 2022 年 2 月 2 日 | 链上跑的还是旧版。攻击者伪造守护人签名,无抵押铸出 120,000 枚 wETH,时值约 3.26 亿美元——正是第一节那个数字 |
| 同日稍后 | 其中 93,750 枚经桥转到以太坊主网(时值约 2.5 亿美元),开始套现 |
| 2022 年 2 月 3 日 | 幕后支持方 Jump Crypto 注入 120,000 ETH(约 3.25 亿美元)补上窟窿,用户资金完好 |
漏洞的真实名字不是”签名验证写错了”——那个 1 月 14 日就修完了——而是”修复没有跑到链上“。从补丁提交到攻击发生,中间隔着约 19 天:够做三轮审计、发两版公告、开十次复盘会,唯独没有做那一件最要紧的事。攻击者甚至不需要挖掘新漏洞,他只是发现药方开了 19 天,药还摆在药房货架上没人取。再算一下三方账单:攻击者试图赚走约 3.26 亿,用户一分未损,真正掏钱的是 Jump——用约 3.25 亿美元买回一个教训。
一句话点题:漏洞报告和修复只是纸面动作,补丁部署到链上才算闭环——审了、修了、没上线,等于零。这也是为什么下文的读报告清单,第一步就是拿报告里的 commit 与链上合约地址对表。
三、一次审计是怎么跑的
正规审计大体四步,一步比一步贵。整个流程你可以想象成一次大体检:先上仪器,再见医生,最后拿报告、遵医嘱。

第一步:静态分析——机器粗筛,相当于 CT 扫描。 用 Slither 这类工具把代码推进舱里扫一遍,已知病灶(漏洞模式)秒级到分钟级现形:重入的形状、tx.origin 的写法、没人接的返回值。CT 的好处是快、便宜、不知疲倦;局限也摆在明面上——它只认得”影像上见过的病”。后文我们自己也会跑一遍。
第二步:人工审查——老医生问诊,费用的大头,也是价值的大头。 业务逻辑的怪病,机器看不出来:审业务逻辑有没有死循环、权限模型合不合理、经济模型能不能被闪电贷撬动,以及组合场景——A 协议的闪电贷加上 B 协议的定价机制再遇上你这个合约。攻击者从来不会按模块出牌,也不按科室挂号。Mango 那类漏洞,CT 扫一百遍也扫不出来,全靠老医生望闻问切——这正是审计费按周计价的原因。
第三步:出报告——分级,像体检报告上的”立刻住院、尽快就诊、定期复查”。 每条发现(finding)带一个严重度标签,行业通行的五级如下:
| 等级 | 官方含义 | 相当于体检报告上的 |
|---|---|---|
| Critical | 资金可被直接盗取,几乎无需前置条件 | “立刻住院”——门没锁,路人都能搬东西 |
| High | 资金损失概率高,触发条件现实可行 | “尽快就诊”——锁了,但钥匙挂在门上 |
| Medium | 特定条件下造成有限损失或功能受限 | “定期复查”——窗户没关,得费点劲爬进来 |
| Low | 偏离最佳实践,存在间接风险 | “注意生活习惯”——猫眼装反了,暂时出不了大事 |
| Informational | 建议与风格提示 | 医生的唠叨——“建议把花盆从窗台上挪开” |

注意分级不是拍照——同一条发现,不同公司可能给差一档的定级,就像两家医院看同一个结节,一家说观察、一家说切了。看分布比抠单个标签更有意义。
第四步:修复确认(mitigation review)——复诊。 医生开的药,吃了没有?项目方修复后,审计方复核补丁,把对应条目标成 mitigated(已缓解)。没修的条目会带着”未修复”或”已确认但不修”的标签留在报告里——相当于报告里写着”建议立刻住院(患者拒绝)”。这才是读报告时最该盯的地方,下一节展开。
四、怎么读一份审计报告:四步实操清单
拿到一份报告,普通人按这个顺序看,五分钟内能建立基本判断:
先看 Scope(审计范围)——先看体检套餐里都有什么项目。 套餐没包含的器官,就等于没查。审了哪些合约、对应哪个版本的 commit、部署地址是什么,全写在 Scope 里,范围之外的部分等于裸奔——Euler 就死在这:审的是旧版,出事的是新加的函数。拿到报告第一件事,就是拿它和项目当前公开的合约地址对表:审的和跑在链上的,是不是同一套代码。

搜有没有未修复的 Critical / High——先翻”立刻住院”那一页。 每条发现都有状态:已修复(mitigated)、已确认(acknowledged)、未修复(unresolved)。只要存在未修复的 Critical,这份报告的其他部分不用看了——项目方明知道门没锁还不锁,剩下全是细节。就像体检报告写着”建议立刻住院”,你却把报告塞进抽屉照常上班。
- 看发现数量的同时看严重度分布。 50 条 Informational 不如 1 条 Critical 值得关注。医生说五十句”多喝水少熬夜”,不如说一句”血管堵了九成”。数量多但全是低级别,说明代码有点草但骨架还行;数量少却藏着 Critical,那才是地雷——密度和烈度是两个维度。
- 核实报告是真的。 伪造审计报告是 rug 项目的常规操作,套路和号贩子如出一辙:抄一份知名审计公司的排版,贴个 logo,一份唬人的 PDF 就出炉了——好比黄牛把”知名专家”四个字印在小卡片上卖你三百块,医院官网根本查不到这位专家今天出诊。正确姿势是去审计公司官网核对(多数公司有已发布报告的列表),核对项目名、报告编号和日期;项目方转贴的 PDF 在官网找不到对应条目,直接按 rug 处理。用户视角的快速排查清单,见《上新币之前,先做这五项检查:Rug Pull 与貔貅盘识别》。
顺带一提,”审计次数”为什么会被 DeFi 保险协议当评分项:单次审计有遗漏概率,多轮独立审计叠加能显著压低漏网风险——就像拿不准的病灶,多挂一个专家号总踏实些。这和《DeFi 保险:谁来保护你的链上资产?》里”多轮审计 + 赏金计划的协议评分更高”是同一个逻辑。不是审得越多越安全的迷信,而是独立抽样次数越多、覆盖越广的统计常识。
五、自己动手:跑一次 Slither
说了这么多,不如亲手跑一遍。别人的体检套餐再贵也轮不到你,但 CT 机有开源的,可以搬回自己家。
Slither 是 Trail of Bits 开源的静态分析器,Solidity 审计的行业标配,pip 一行装好,支持对源码文件、乃至区块浏览器上验证过源码的合约地址,直接一条命令出结果。
1 | # 安装 Slither(solc-select 是它的依赖,随装附带,用来管理 solc 版本) |
诚实记录一下沙箱翻车:我在 macOS 上第一次安装时 cbor2 编译失败——本机的 Rust 工具链太老,认不了新版 cbor2 的 Cargo 配置。先执行 pip install cbor2==5.6.5 绕过(或者用 rustup update 升级工具链)再装,就顺了。工具链依赖是静态分析工具的常见门槛,这也是为什么很多团队直接把 Slither 挂进 CI,让机器替人记环境。
接着造一个教学用漏洞合约,三个函数各埋一颗雷,看看这台 CT 机能不能全扫出来:
1 | // SPDX-License-Identifier: MIT |
跑起来只要一条命令(在合约文件所在目录执行):
1 | slither VulnerableBank.sol |
以下是我沙箱里的真实输出(同一个文件、同一条命令,篇幅原因节选了三颗雷对应的发现,另有 solc 编译警告和 arbitrary-send-eth、missing-zero-check、low-level-calls 等条目略去):
1 | INFO:Detectors: |
对着输出读一遍:第一颗雷 reentrancy-eth,Slither 不光报了名字,连”外部调用在第 21 行、状态写入在第 23 行”都给你圈出来了——相当于 CT 不光说”有结节”,连片子第几层都标好了。第二颗 tx-origin、第三颗 unchecked-send 也全中,还附赠了几个我没打算埋的(比如 tip 收款地址没做零地址检查)。注意两点:一是 Slither 内置了 102 个检测器,输出末尾那行就是汇总;二是它报的是”可疑模式”,算不算真漏洞、能不能被实际利用,仍需要人判断——CT 报出结节,良恶性还得医生说了算。这就是静态分析的天花板,也是人工审查收费的原因。
六、自研扫描器:一百行看懂静态分析的骨架
CT 机贵,原理却不神秘:把身体切成一层层图像,再用规则找异常。Slither 的骨架一模一样:把代码变成结构化数据,然后用一堆检测器做模式匹配。
来,做一个玩具版 mini_auditor。它不解析真正的 Solidity,而是输入一份”合约特征描述”(函数列表、修饰符、语句序列),用正则检测三类模式:重入嫌疑(外部转账发生在状态更新之前)、tx.origin 鉴权、未检查返回值的转账调用,并输出带 severity 的报告。
先说直觉,最有意思的是怎么用正则抓重入:看语句的先后顺序——外部转账出现的位置,后面还有没有”记账”语句。有,就是”先转账后记账”,报 Critical。就这么朴素。
1 | #!/usr/bin/env python3 |
用 python3 mini_auditor.py 跑它,以下是真实输出:
1 | ============================================================== |
对着输出看:带病的 VulnerableBank,三颗雷各报一条,等级、位置、修复建议一样不缺;整改后的 SafeBank——先记账后转账、加了 nonReentrant 锁、返回值也接住了——只剩一条”报平安”的 Informational。一病一愈,对照着读,检测器的脾气一目了然。
再和上一节 Slither 的结果对照一下:同一个 withdraw,Slither 报 reentrancy-eth,我们报 Critical 重入嫌疑;同一个 tx.origin,两边都抓到了。区别只在覆盖面——它有 102 个检测器,我们有 3 个正则。但思路完全一致:把”人逐行读”变成”机器先筛、人再判断”。真实的审计公司在这之上还有更重的武器:MythX 这类深度分析平台、Echidna 这类模糊测试工具、Certora 这类形式化验证——至于经济模型能不能被玩死,目前还是纯人工科目,机器帮不上忙,还得老医生坐诊。
七、漏洞赏金:白帽的正当获利路径
审计之外的另一道防线是漏洞赏金,代表平台是 Immunefi。逻辑很简单:白帽发现漏洞,通过平台负责任地披露给项目方,换取赏金;项目方花钱买”雷还没炸”的时间。像旧时官府贴悬赏告示:捉拿要犯,赏银百两——江湖高手有了正路,就不必落草为寇。
规模感受一下:Wormhole 曾在这里付出过 1000 万美元的单笔赏金(史上最大之一);LayerZero 挂出过 1500 万美元的赏金上限;整个平台累计发放的赏金已上亿美元。顶级协议赏金上百万美元是常态——对有能力找到漏洞的人,这是一条完全正当、且收入可观的职业路径。
这也解释了《DeFi 保险:谁来保护你的链上资产?》里那句”Immunefi 赏金 + 多轮审计的协议更安全”:赏金计划本质上是把攻击者的期望收益翻转成正收益——同样发现一个 Critical,偷偷利用可能吃官司、赚一次,走 Immunefi 报告则合法、拿钱、还能上排行榜。悬赏令一贴,小偷的最优解就变成了领赏的守门员,这是除审计之外性价比最高的安全投资。
边界也要说清:没授权的”先斩后奏”不叫白帽,叫犯罪。Mango 那位当事人事后声称自己是”合法利用市场规则”,结果吃了 CFTC、SEC、DOJ 三家连诉——刑事定罪虽然在 2025 年被推翻,但这场耗时数年的官司本身就说明:绕过赏金计划直接搬走资金,法律不会自动站在你这一边。发现漏洞,先找 Immunefi 或项目方的官方渠道,别急着表演。
总结
回答开头四个问题:
- 审计是什么:时间盒内的抽检,是防御纵深的一环,不是保险单——体检报告不能保证你一年不生病,Euler 和 Wormhole 的账单就是证据。
- 谁在审:Slither 这类工具做秒级 CT 粗筛,审计工程师做老医生式问诊(业务逻辑、经济模型、组合场景占大头),最后复诊确认修复、按 Critical 到 Informational 五级出报告。
- 报告怎么读:看 Scope 对不对表(套餐外等于没查)、搜未修复的 Critical/High(”建议立刻住院”却拒绝住院)、看严重度分布而不只是数量、去审计公司官网验真(当心挂名专家号)——伪造审计是 rug 项目的常规操作。
- 普通人能不能自己跑:能。Slither 一条命令扫源码或地址;一百行 Python 也能写个玩具扫描器,抓出教科书级的重入。
如果只记一句话:读不懂 Solidity,至少要学会看懂审计报告——就像看不懂化验单,也该认得”建议住院”四个字;看得懂代码,就更没有理由不看。
相关阅读
- 《我是一个区块链黑客(第一篇)》:重入攻击的代码级拆解,本文分类表的第一个嫌疑人
- 《预言机:DeFi 里的价格到底是从哪来的?》:预言机操纵——当代 DeFi 被黑第一大类
- 《DeFi 保险:谁来保护你的链上资产?》:审计次数作为风险评分项、Immunefi 赏金
- 《上新币之前,先做这五项检查:Rug Pull 与貔貅盘识别》:本文是专业审计视角,那篇是用户掏钱前的五分钟体检
- 《Web3 中的授权与撤销授权》:权限模型——审计重点科目之一