第 24 章 · Crypto 为什么不断发生归零和攻击
钱到底是怎样丢掉的?
- 练习的能力
- System ThinkingResearchOnchain Literacy
- 动手
- 挑一次真实事故,按十种风险逐项打勾,还原资金是怎样一步步流走的。
- AI Lab
- 让 AI 复盘一次攻击,再对照官方事后报告,标出它编造或含糊的地方。
一个现实问题
三个人,同一年,各自把一笔钱亏光了。
第一个人在一个借贷协议里存了稳定币。某天早上协议发公告:一次价格操纵导致池子里出现了大额坏账。他没有做错任何操作,存款按比例被削减。
第二个人把币放在一个平台上,享受着一个不错的固定收益。某天平台公告暂停提现,三个月后进入破产程序。他的币还在,只是排在一张债权人名单上。
第三个人的钱包被转空了。他没有丢私钥,没有泄露助记词,也没有点进假网站。查下来,是几个月前他给一个网站签过一次授权,那个网站后来把合约换了。
三个人在事后会说同一句话:Crypto 不安全。
这句话没错,但它没有任何用处。因为这是三件完全不同的事——防住其中任何一件的办法,对另外两件完全无效。 第一个人需要的是看懂抵押品的价格是从哪里取的;第二个人需要的是分清「我的币」和「平台欠我的币」;第三个人需要的是定期检查自己签过哪些授权。三件事之间没有共同的防御动作。
所以这一章不是一份事故名单,它是一套分类法。 理由很简单:你没法防住一个你叫不出名字的东西。把「不安全」拆成十个有名字、有对应问题、有对应检查动作的类别之后,你才第一次有了可以做的事。
这一章也是 Part A 前四阶段的风险总收口。前面每一章讲机制时留下的那些「这里会出事」的伏笔,在这一章被收拢成一张表。
思想实验
先离开链上。你被雇来当一座仓库的保安队长。
这座仓库替别人存放货物。上任第一天,你要做的第一件事不是巡逻,是把这座仓库所有能让货物进出的通道列一张清单。
你走了一圈,列出了这些:
- 前门。任何人都可以推门进来办业务,规则写在墙上,照着做就行。
- 墙上的那台秤。仓库按外面市场的价格给货物估值,所有的抵押、放货、扣货都依赖这个估值。
- 后面的运货通道。有一部分货其实存在另一座仓库里,这边只是一张凭条。
- 管理员门的那串钥匙。它能绕过前门的全部规则,在谁身上?
- 每周一次的业主会议。它能改墙上的规则,包括改成什么样。
- 地板的承重。仓库里堆的货有多少是借来的、加了杠杆的?
- 出货通道的宽度。如果所有人同一天来取货,门有多宽?
- 隔壁那家替你保管钥匙的公司。它自己靠不靠谱?
- 你自己会不会点错数。上一次盘点是什么时候?
九条通道,每一条都是一个能让货物流出去的路径。这已经比「仓库安不安全」有用得多了。
但真正重要的是下一步:把这些通道两两连起来,问一句「这一条坏了,会不会带着另一条一起坏」。 你会发现连线多得吓人,随便走一条:
秤被动了手脚 → 一批货被严重低估 → 按规则,这些货可以被低价拉走 → 拉走的人把货堆到出货通道上卖 → 通道被堵死 → 后面正常来取货的人取不到 → 仓库里留下一个填不上的缺口 → 业主紧急开会改规则 → 而「谁有资格来开这个会」,此刻变成了一个全新的风险。
一条链,五个通道,一次事故。
这就是这一章最重要的那句话的来源:真实事故几乎从来不是一扇门坏了,而是一扇门坏了之后,其他门跟着坏。
你来决定
你要给一份项目研究报告写「风险」那一节。你怎么写?
观察结果
那份固定清单长这样。它是整个课程共用的统一风险模型,也会一直跟到毕业项目:
| Smart Contract Risk | 代码有没有被审计?升级权限在谁手里? |
| Liquidity Risk | 想退出的时候,池子里还有没有钱? |
| Oracle Risk | 价格从哪里来?能不能被操纵? |
| Bridge Risk | 跨过来的资产,背后到底抵押着什么? |
| Custody Risk | 资产由谁保管?私钥在谁手里? |
| Counterparty Risk | 对手方跑路,你还剩下什么? |
| Governance Risk | 一次投票能不能把钱投走? |
| Leverage Risk | 价格下跌 30%,会触发多少连环清算? |
| Token Risk | 解锁和增发会把谁稀释掉? |
| Operational Risk | 多签、私钥管理和运维出错的概率有多大? |
三件事值得说清楚。
第一,它不是穷举,是分类。 十类的设计目标不是覆盖所有可能,而是互相不重叠、且覆盖住绝大多数真实事故。你遇到一个装不进任何一类的风险时,那本身就是一个值得写下来的发现。
第二,真正干活的是右边那一列。 每一类都被写成了一个可以拿去查、并且能得到确定答案的问题。「代码有没有被审计」有答案;「升级权限在谁手里」有答案;「价格从哪里来」有答案。风险管理在这里变成了一件查资料的事,而不是一件需要预感的事。
第三,也是这一章的核心——这十类在真实事故里经常同时发生。
看这条链,它不是假设,它是过去几年里反复出现的同一个剧本:
- 一个薄池子的价格被操纵
- 协议按这个错误价格给抵押品估值
- 一批头寸被错误清算
- 清算卖单抽干剩余流动性
- 抵押品卖不掉,缺口留成坏账
- 紧急治理投票改参数救场
把这条链拆开,逐项对照那张表:
| 这一步 | 属于哪一类 | 单独看的时候像什么 |
|---|---|---|
| 价格被操纵 | Oracle Risk | 「取价来源比较集中,但那个池子还挺大」 |
| 按错误价格估值 | Smart Contract Risk | 「代码完全按设计执行了」 |
| 一批头寸被清算 | Leverage Risk | 「清算机制运转正常」 |
| 卖单抽干流动性 | Liquidity Risk | 「平时深度足够」 |
| 缺口留成坏账 | Counterparty Risk | 「有储备金」 |
| 紧急投票改参数 | Governance Risk | 「有应急机制,是好事」 |
每一格单独看都是「可控」,连起来是「归零」。
这是单点故障和复合事故的根本区别:
| 单点故障 | 复合事故 | |
|---|---|---|
| 触发 | 一个组件失效 | 一个组件失效,并传导 |
| 损失规模 | 大致等于那个组件的敞口 | 可以远大于任何单个组件的敞口 |
| 能不能被审计发现 | 常常可以 | 几乎不行,审计的边界是单个协议 |
| 事后复盘怎么说 | 「某某模块有漏洞」 | 「一系列小概率事件同时发生」 |
| 事前怎么防 | 逐项检查 | 逐项检查 + 画出传导路径 |
最后那一行是这一章要教的额外动作。十项打勾只是第一步,第二步是在打完勾的十项之间画箭头。
建立模型
三层:代码、经济、人
把十类风险按「它出在哪一层」重新分组,会看到一个很有用的分布:
| 层 | 包含哪几类 | 能不能被审计发现 | 典型的损失方式 |
|---|---|---|---|
| 代码层 | Smart Contract、Bridge 的验证部分 | 大部分可以 | 一笔交易里被掏空 |
| 经济层 | Oracle、Liquidity、Leverage、Token | 基本不行 | 规则被按设计利用 |
| 人的层 | Custody、Counterparty、Governance、Operational | 完全不行 | 钱被合法地转走 |
这张表有一个反直觉的推论:最容易被检查的那一层,恰恰不是损失最集中的那一层。 审计能告诉你代码有没有写错,却没办法告诉你「把一个只有几十万深度的池子当作价格来源」是不是一个好主意——那不是代码错误,是设计选择。它在链上完美执行,然后把协议掏空。
第 16 章结尾那句话现在可以补完了:代码可以完美执行,系统照样亏钱。原因就是代码层只占三层里的一层。
钱流走的五条路径
不管事故多复杂,钱最终只会从这五条路径之一流出去。记住这五条,比记住五十个事故名字有用:
| 路径 | 它长什么样 | 主要对应 | 你这一侧能做什么 |
|---|---|---|---|
| 逻辑被利用 | 一笔交易调用了设计者没想到的组合 | Smart Contract | 看审计范围和修复记录;看合约上线多久 |
| 价格被操纵 | 喂进来的价格不等于真实市价 | Oracle | 查取价来源、有几个源、用不用延迟和中位数 |
| 钥匙被拿走 | 有人拿到了能直接动钱的权限 | Custody、Operational | 查多签门槛、时间锁、权限地址是不是单签 |
| 规则被改掉 | 一次合法的投票或升级改变了资金归属 | Governance | 查投票权分布、提案到执行的间隔、有没有时间锁 |
| 你自己签了名 | 你授权过的合约后来做了别的事 | 用户侧 | 定期检查并撤销授权;大额资产不放在常用钱包 |
第五条要单独强调,因为它是唯一一条完全发生在你自己这一侧的路径。它不需要任何人攻破任何协议。 它只需要你几个月前签过一次名,而那个授权额度是无限的、永久的、且指向一个可以被升级的合约。这条路径造成的个人损失总额,可能是五条里最大的一条,而它也是唯一一条你可以单方面关掉的。
风险不是加法
第 17 章讲收益叠加时给过一个结论:收益相加,风险相乘。这一章要把后半句说得更准确——风险不只是相乘,它们还相关。
假设一个仓位横跨三个协议,每个协议「这一年不出事」的概率是 97%。
如果三者独立:0.97 × 0.97 × 0.97 = 91.3%但它们通常不独立。如果三个协议用同一个预言机、接受同一种抵押品、或者依赖同一座跨链桥,那么一次事故会同时击穿三层,真实的联合风险远差于 91.3%。
所以评估组合风险时,加一个动作:把每一层的依赖列出来,找重叠。
| 找哪些重叠 | 为什么要紧 |
|---|---|
| 同一个预言机 / 同一个价格来源 | 一次操纵同时影响全部 |
| 同一种抵押品 | 那个资产脱锚,全部同时穿仓 |
| 同一座跨链桥 | 桥出事,上面所有的资产同时变成无锚凭证 |
| 同一个多签 / 同一批权限地址 | 一次私钥泄露,全部沦陷 |
| 同一条链的同一个排序者 | 停机时全部无法清算、无法逃生 |
重叠越多,分散就越是假的。 第 18 章那个「分散在不同场所并不构成分散」的结论,在这里是一个通用规律。
把每一类变成一个能查的问题
最后一步是把模型变成动作。每一类风险,都要落成一条能得到确定答案的记录:
风险类别:Oracle Risk
问题: 价格从哪里来?能不能被操纵?
查到的: 用 A 源和 B 源的中位数,取 30 分钟时间加权
出处: 官方文档第 X 节 + 合约地址 0x…(我在区块浏览器上核对过)
结论: 单一池子操纵的成本被抬高了;但两个源在极端行情下可能同时失真
剩余不确定:没有查到喂价停更时的降级逻辑 → 标记为「未评估」六行一条,十条填完,这一节就写完了。而整套方法的关键在最后一行:
一份风险清单的质量,不取决于它列了多少条,取决于它有多少条诚实地标了「未评估」。
一份十项全绿的报告,通常不是因为这个项目没有风险,而是因为写的人没有去查。分析工具箱那一页把这张表和十八问、Project Canvas 放在一起,研究任何项目时直接取用。
它叫什么
代码本身的缺陷,或者代码可以被升级成别的样子。
它分成两半,很多人只看前一半。前一半是漏洞:逻辑错误、状态更新顺序不当、外部调用的处理不当。后一半是权限:谁能升级这个合约,改完之后多久生效,有没有时间锁。
第二半经常更要紧——一个没有时间锁的可升级合约,等于把所有资金交给了持有升级权限的那把钥匙。 完整的攻击面模型在 T28、T29 两章。
喂进协议的价格,不等于真实的市场价格。
三个必查项:取价来源有几个、用不用时间加权或中位数、喂价停更时协议怎么办。第三项最常被漏掉,而它恰恰是极端行情下最容易发生的。
要记住它的成本结构:操纵一个价格的成本,取决于那个价格来源的深度。把一个浅池子当作估值依据,等于给攻击者标了一个明码标价。 工程实现见 T21。
跨过来的资产,背后到底抵押着什么。
绝大多数跨链资产的本质是:原链上锁着真资产,目标链上是一张凭条。 于是整个体系的安全性等于「谁在看守那把锁」——可能是一组多签,可能是一套验证逻辑,也可能是一个链下服务。
必查的一句话:如果看守方失效,我手上这张凭条还值什么。 答案常常是零。跨链桥是这个行业里单次损失金额最集中的一类事故,原因就在这里:它把很多条链的资产,汇到了一个点上。第 12 章讲多链格局时留下的那个问题,答案在这里。
资产由谁保管,私钥在谁手里。
这是第 5 章那句话的风险版本:资产在别人那里时,你持有的不是资产,是一份债权。 平静时两者看起来一样,出事时完全不同——债权要排队,而且可能排在很后面。
它有一个很少被提的反面:自我保管把托管风险换成了运维风险。 私钥丢了、备份进水了、助记词抄错一个词,这些也是真实的归零方式,而且没有人可以申诉。两种方式都有代价,重点是知道自己选的是哪一种。
一次合法的投票,能不能把钱投走。
三个必查项:投票权怎么分布(前十个地址加起来占多少)、提案到执行之间有多长(有没有时间锁让人来得及退出)、有没有紧急通道(谁能跳过流程)。
有一类特别值得注意的攻击:投票权可以被临时借来。 如果一个协议的治理代币可以在市场上大量借到,那么「持有多数票」就变成了一笔可以计算成本的生意——借票、提案、投票、执行、还票,全部在很短时间内完成。
你签名允许某个合约动用你钱包里某种资产的额度。
它不是一次性的:签一次,效力持续到你主动撤销为止。 而且默认额度常常是无限。
这意味着一件很多人没意识到的事:你今天的资金安全,取决于你过去所有签过名的合约,此刻都还没有出问题。 这个集合只会越来越大,除非你定期清理。
它在这一章的分类里横跨了好几格,但它是唯一一条你可以单方面关掉的风险路径。
动手
这个 Lab 从头到尾只需要读。 不要连接钱包,不要签名,也不要尝试在任何网络上复现攻击——还原资金流靠的是读交易记录,不是执行交易。
选事故的标准只有一条:它有一份公开的官方事后报告。 规模不需要最大,有完整材料比有名气重要得多。
先只读报告,画一条时间线。 在打开区块浏览器之前,先把官方报告读一遍:第一笔异常交易的时间、协议发现的时间、暂停的时间、公告的时间、资金流出完成的时间。
特别留意发现与暂停之间的间隔。这个数字常常以小时计,而攻击本身可能只用了几分钟。这个差值本身就是一项风险指标。
在区块浏览器上找到关键交易,自己看一遍。 报告里通常会给出攻击交易,打开它看三件事:调用了哪些合约、按什么顺序、资金最后去了哪个地址。
不要求你看懂每一行调用。目标只是确认一件事:报告里写的那个顺序,和链上记录是一致的。 这一步是整个 Lab 里最能建立信心的部分——你在用一手事实核对别人的结论,这正是第 23 章那套方法。
画资金流向图。 从「事故前资金在哪」开始,一步步画到「事故后资金在哪」。
用户存款 → 协议池子 → ? → ? → 攻击者地址 → ?中间每一个问号都要填上一个具体的动作和一个具体的地址。填不出来的地方标一个问号留着,它是你这次复盘里还没搞清楚的部分。
十项打勾。 逐条过一遍,每一项写「触发 / 未触发 / 无法判断」,以及一句依据。
| 风险类别 | 是否触发 | 依据(来自报告还是链上) |
|---|---|---|
| Smart Contract | ||
| Liquidity | ||
| Oracle | ||
| Bridge | ||
| Custody | ||
| Counterparty | ||
| Governance | ||
| Leverage | ||
| Token | ||
| Operational |
多数事故会勾到三到五项。 只勾到一项,通常说明你还没看到传导链条。
这一步是核心:在打了勾的那几项之间画箭头。 从第一张骨牌开始,一条一条问「它为什么会导致下一项」。画完之后你手上会有一张图,而不是一张清单。
清单告诉你出了什么事,图告诉你为什么这件事这么贵。
回答四个问题,每个一两句:
- 第一张骨牌是哪一项?
- 如果事前只能修一处,修哪一处能把损失压到最小?
- 损失最终由谁承担了:协议金库、存款人、代币持有人、还是保险基金?
- 这个设计在事故之前,有没有人公开质疑过?(去翻翻论坛和审计报告的「中低危」部分,答案常常是有。)
第四问是这个 Lab 最扎心也最有价值的一问。很多事故在发生前都被人指出过,只是当时没人把它当回事。
收尾:把同一张十项表,拿去过一遍你自己正在用的一个协议。 这一步只花十五分钟,但它是这个 Lab 真正的产出——复盘别人的事故是练习,检查自己的敞口才是目的。
AI Lab
这个任务有一个特别的性质:它的正确答案是公开的、固定的、可以逐字核对的。 官方事后报告就在那里,链上记录也在那里,模型要么对上了,要么没有。这让它成为整个课程里最适合用来校准「我该多信任模型」的一个练习。
请复盘 [某次事故的名称与大致时间] 这次事件。
第一部分,时间线。每一行包含:时间(标明时区)、发生了什么、
对应的交易哈希或区块高度、你的信息来源链接。
第二部分,攻击路径。一步一步写清楚:调用了哪个合约的哪个函数,
这一步达成了什么,为什么协议的设计允许这一步发生。
第三部分,按下面十类风险逐项判断「触发 / 未触发 / 无法判断」,
每一项给一句依据,依据必须来自公开材料:
Smart Contract / Liquidity / Oracle / Bridge / Custody /
Counterparty / Governance / Leverage / Token / Operational
第四部分,损失:总金额是多少、按哪个时点的价格计算、
最终由谁承担(协议金库 / 存款人 / 代币持有人 / 保险基金 / 其他)。
第五部分,单独列出:
- 哪些内容你有明确来源,来源是什么
- 哪些内容你是根据同类事故推断的
- 哪些内容你查不到
规则:不确定的一律写「查不到」。不要为了完整而补一个看起来合理的
交易哈希、地址或数字。拿到之后,第一件事是打开区块浏览器,核对它给的每一个哈希和地址。
这类任务上模型有三个高频错误,按危险程度排序:
- 编造哈希和地址。 格式完全正确、校验位看起来也对,但链上不存在。这类错误无法从文本上看出来,只能靠核对。
- 把同类事故串味。 两次都是桥、两次都是预言机操纵,细节会被混在一起,时间线读起来依然通顺。对照官方报告的时间线是唯一的检测方法。
- 把不确定说成确定。 尤其是「损失最终由谁承担」这一项——这件事在很多事故里到今天都没有定论,而模型会给你一个干脆的答案。
第五部分是整个提示词里最重要的一段。让它自己划分确定与不确定,然后你重点去查它标为「确定」的那些。 这个动作把核对的工作量降低了一大半,而且它有一个副作用:模型在被要求区分的时候,输出的可靠性通常会明显提高。
AI 说完之后,你必须自己验证
- 它给的交易哈希和合约地址,你在区块浏览器上打开过吗——格式正确不等于存在
- 它给的时间线,和官方事后报告的时间线能不能对上,有没有多出或少掉关键节点
- 它有没有把两次不同的事故混在一起:同类事故的细节最容易被串味
- 它给的损失金额,是按事发当时的价格还是按别的时点,它说明了吗
- 它有没有把「据称」「疑似」写成了确定的事实
- 它的十项打勾里,有没有哪一项是它自己推断出来的而报告里并没有说
- 最关键的一条:它有没有说清楚损失最终由谁承担——这一项模型几乎总是含糊带过
- 它标为「不确定」的地方有几条?一条都没有,本身就是一个危险信号
真实案例
跨链桥的结构是:原链锁资产,目标链发凭条。谁有权说「原链确实锁了」,谁就掌握了发凭条的权力。多次大额事故的模式高度一致:攻击者让桥相信了一笔并不存在的锁定。 可能是伪造了一份验证材料,可能是绕过了签名检查,也可能是直接拿到了多签里足够多的钥匙。
为什么桥的单次损失总是排在最前面?因为它是一个汇聚点:很多条链、很多种资产的价值,全部押在同一套验证逻辑上。第 12 章讲的多链世界越繁荣,这个汇聚点就越大。
必问的一句话还是那句:如果看守方失效,我手上这张凭条还值什么。
一个协议接受某种代币作为抵押品,而这个代币的价格取自它在某个 DEX 上的池子,那个池子只有几十万到几百万的深度。
攻击可以被算成一笔明账:借一大笔钱,把那个池子的价格推上去,用被高估的抵押品借出协议里的真实资产,然后收手。整个过程可能在一笔交易之内完成。
这次事故里,代码完全按设计执行,审计也可能全部通过。出问题的是一个设计选择:把估值依据放在了一个操纵成本远低于可借出金额的地方。
它同时踩中三类风险:Oracle(价格来源太薄)、Leverage(可借出的金额远大于操纵成本)、Liquidity(第 15 章那个深度决定一切的结论)。任何一类单独评估都会说「还行」。
若干提供固定收益的中心化平台在几周之内相继暂停提现,随后进入破产程序。事后看,问题不在某一次黑客攻击,而在一条更平常的链:用户的钱被拿去做了杠杆和期限错配的投资,而这些投资和用户的资产暴露在同一轮下跌里。 市场下跌 → 投资亏损 → 赎回加速 → 平台需要卖出资产 → 卖出压低价格 → 亏损扩大。
这条链上没有一行代码出错。它踩的是 Custody(资产在别人那里)、Counterparty(对手方自己在冒险)、Operational(风控与信息披露),以及贯穿全程的 Leverage。
这也是第 5 章那句话代价最高的一次集体演示。 那一章讲的是概念上的所有权,这一次是账面上的:资产还在,只是变成了一张债权人名单上的一行。
有些协议把金库的支配权交给代币投票,规则本身是公开、透明、按设计执行的。问题出在投票权可以被临时获得:市场上能借到大量治理代币,或者创始团队与早期投资人本身就持有多数票。于是「通过一次合法投票转移金库」变成了一笔可以估算成本收益的生意——借票、提案、投票、执行、还票。
防线只有三条,而且必须一起看:投票权分布(前十个地址占多少)、提案到执行的时间锁(够不够人们退出)、紧急通道归谁(谁能跳过流程)。
这类事故的特别之处在于:事后没有人可以说「被黑了」。 每一步都符合规则。所以它也是最难在事前引起重视的一类。
改一个变量
代码层的风险明显下降,这是真实的收益,值得付这笔钱。但三件事没有变:审计只覆盖送审的那个版本,之后的升级不在范围内;审计不评估经济设计,把浅池子当价格来源这类问题通常只会被写成中低危建议;审计完全不覆盖人的层——钥匙在谁手里、投票权怎么分布、团队会不会跑,不在任何审计报告的范围内。
所以「已审计」这三个字的正确读法是:十类风险里的一类被认真检查过了。 它不是一张通行证,是一张单科成绩单。
操纵成本被抬高了不止一个数量级:攻击者现在需要同时推动多个来源,而且要维持足够长的时间让加权窗口跟上,很多原本成立的攻击直接变得不划算。
但这个改动引入了一个方向相反的新问题:时间加权意味着喂价滞后。 在真实的剧烈行情里,协议看到的价格比市场慢一拍,该清算的头寸没有被及时清算,缺口会留在协议里。
这是一个典型的取舍,不是一个升级。 抗操纵和及时性是对立的两端,任何一个参数选择都在这条线上取了一个点。评估一个协议时要问的不是「它抗不抗操纵」,而是「它把这个点取在哪里,为什么」。
这是性价比最高的一类改动,它同时动了两类风险。
Operational Risk 下降:单把私钥泄露不再能动钱,需要同时拿到四把。Governance Risk 下降:48 小时的时间锁意味着任何改动都会先公开,用户有时间撤出——时间锁真正的作用不是阻止改动,是给人逃生的窗口。
代价有两个:紧急情况下修复速度变慢(漏洞公开之后要等 48 小时才能修,这段时间是暴露的);以及多签的七个持有人是不是真的独立——如果七把钥匙在同一个办公室、同一台机器、或者同一个人手上,那么 4/7 只是一个写在文档里的数字。
所以查多签时要多问一句:签名者是谁,他们之间有多独立。
带走的问题
这一章把这一问变成了一份可以填的表:十类风险逐项打勾,然后在打了勾的项之间画箭头。
但真正要追到底的是打勾之后的那一问:出事时,损失按什么顺序由谁承担? 协议金库、存款人、代币持有人、保险基金——顺序写不出来,说明这个协议的风险结构你还没看懂。而这个顺序,通常藏在文档里最没人读的那一节。
这一问在这一章有了一个具体的检查动作:去看这个协议的抵押品清单和价格来源,里面有没有它自己发的东西。
如果有,那么「代币归零」和「协议停摆」就不是两件事,是同一件事的两个说法。这类结构在上行周期里表现得最漂亮,在下行周期里归零得最快。
「Agent 有什么权限」这一问,在这一章有一个人类版本,而且是每个人都该做的:去检查你自己的钱包签过哪些授权,额度是多少,指向的合约能不能被升级。
两者是同一个问题:一个可以动你的钱的东西,它的权限边界在哪里,什么时候到期,你怎么收回。 这一问回答不了,让 Agent 拿钱包这件事就没法安全地开始。Part B 的 T33、T34 会把它工程化。
把这一章的五条资金流出路径套到 AI 上:模型给了一个错误的合约地址、模型看错了价格、模型签了一个不该签的授权——损失谁来承担?
这一章给出的答案框架是一样的:先问谁有权限,再问出事时按什么顺序赔。 在自动化系统里,这两个问题必须在部署之前有书面答案,因为事后没有人可以被追问。T32把这件事做成了一套架构约束。
本章自测
因为审计覆盖的是十类风险里的一类,而且只覆盖送审的那个版本。
它不评估三件事:经济设计(把一个浅池子当作价格来源,通常只会被写成中低危建议)、人的层(钥匙在谁手里、投票权怎么分布、团队会不会跑)、升级之后的版本(审计报告有日期,合约可以在之后被改)。
而这个行业里损失金额最大的几类事故,来源恰好集中在这两层。
正确的读法:「已审计」是一张单科成绩单,不是通行证。看到它之后要继续查的是审计范围、审计版本、高危项修了没有、上线后改过几次。
一条反复出现的链:
- 一个薄池子的价格被操纵 → Oracle Risk
- 协议按这个价格给抵押品估值,放出了远超实际价值的借款 → Smart Contract Risk(代码按设计执行了)
- 价格回落,大批头寸被清算 → Leverage Risk
- 清算卖单打在有限深度上,价格进一步下跌 → Liquidity Risk
- 抵押品卖不掉,缺口留成坏账 → Counterparty Risk
- 紧急治理投票改参数救场,于是「谁能投票」成了新风险 → Governance Risk
关键在于:六环里每一环单独评估都会得到「可控」的结论。 损失来自它们的连接,而不是任何一环本身。
所以十项打勾之后必须再做一步:在打了勾的项之间画箭头。
五条:逻辑被利用、价格被操纵、钥匙被拿走、规则被改掉、你自己签了名。
最后一条完全在你自己这一侧。它不需要任何人攻破任何协议——你几个月前给某个合约签过一次授权,额度是无限的,永久有效,而那个合约后来被升级成了别的样子。
它也是唯一一条你可以单方面关掉的:定期检查并撤销不再使用的授权,大额资产不放在日常交互的钱包里。
值得记住的一句话:你今天的资金安全,取决于你过去所有签过名的合约此刻都还没有出问题。 这个集合只会越来越大,除非你主动清理。
因为它把两件完全不同的事分开了:「我查了,没有问题」和「我没查到」。
一份十项全绿的报告,通常不是因为这个项目没有风险,而是因为写的人没有去查。而读者无法从报告里看出是哪一种——除非写的人诚实标注。
这三个字还有一个作用:它把研究变成了可以增量推进的事。 标了「未评估」的那几项,就是下一次研究的入口;不标的话,你半年后回头看自己的报告,会以为那几项已经查过了。
一句可以当成检验的话:一份风险清单的质量,不取决于它列了多少条,取决于它有多少条诚实地标了「未评估」。
没有标准答案,检查这几件事:
- 十项你是逐条过的,还是只挑看得懂的几项写了?
- 每一项的依据,你写了出处吗?出处是官方文档、链上核对,还是某篇文章?
- 权限那几项(升级权限、多签门槛、时间锁、投票权分布)你是在链上核对的,还是从文档里抄的?文档和链上不一致是很常见的情况。
- 你有没有做第二步——在打了勾的项之间画箭头?
- 「出事时损失按什么顺序由谁承担」这一问,你能写出一个顺序吗?
- 你标了几项「未评估」?一项都没有,几乎肯定说明你漏查了。
一个经验值:第一次认真做,十项里标三到五项「未评估」是很正常的。这不是失败,这是一份诚实的研究应有的样子。
一句话带走
风险不是一种,而是十种,而且事故里它们经常同时发生。