一 四个对象
关于 2020 年3 月12 日那一天,同期材料里同时出现过四个数:约 400 万,450 万,567 万,832 万美元。
它们并不一定互相矛盾。
因为它们量的是四个不同的对象。
这四个数在同期的报道里经常被互换使用,而互换的后果不只是不精确。它决定了这件事被理解成什么:是一次协议的亏损,还是一批人的财产损失,还是一场拍卖的定价失败。三种理解对应三套完全不同的追问。
是协议亏了钱,那么该问的是资本缓冲够不够。是一批人损失了财产,那么该问的是他们能不能拿回来,找谁拿。是一场拍卖没有定出价,那么该问的是这个机制在什么条件下会失灵。
三个问题都成立,而且指向的是同一批事实。区别在于它们把注意力放在哪一头。
而这三个问题,后来分别走了三条不同的路。
协议那一条走完了,而且走得很快:一个星期之后就用新铸的 MKR 把缺口补上了。
拍卖那一条走了一年多,改了参数,又整个换掉了机制。
而人那一条走到 9 月,在一次只有几十个地址参加的投票里,得到的答案是零。
三条路的速度差别本身就说明了一些东西。缺口是一个可以计算的数,补它有现成的机制,一星期就够。机制要改,涉及参数和代码,一年多。而人要不要被补偿,是一个没有现成机制的问题,于是它被交给了一次投票。
一个是 Vault 被触发清算这件事本身。一个是拍卖的成交质量。一个是协议因此形成的坏账。还有一个是 Vault 所有者没有拿回来的那部分剩余抵押品。
所以最需要避免的一句话是:Maker 在黑色星期四损失了 832 万美元。
那 832 万主要是被近零价拿走的抵押品价值。协议自己没有收回的债务是另一个口径。而 Vault 所有者失掉的剩余权益,是第三个。
上一篇写的是价格从哪里来。
而这一次写的是照着那个价格动手会发生什么。
两篇要连着读,因为中间只隔一步:预言机给出一个数,清算合约照这个数把人的抵押品拿去卖。
而这一步是自动的。没有人批准,没有人复核,没有一个环节可以说等一等。上一篇末尾说过,链验的是有没有人按规矩说过这句话,不验这句话是不是真的。
这一次要看的是:当那句话被说出来之后,照它执行的那台机器会做什么。
二 一次正常的清算
当时的 ETH-A 类型 Vault 采用 150% 的清算率。也就是说,当 Maker 采用的抵押品价格,使抵押品价值与债务之比低于 150% 的时候,这个 Vault 就进入了可以被清算的状态。
而这里最容易被误读的参数是 13% 的清算罚金。
这 13% 是加在需要从拍卖中收回的债务上,不是最多拿走使用者 13% 的 ETH。
如果债务是 D,拍卖需要筹回的目标金额大致是 1.13 倍的 D。
于是有一个可以推出来的理论上限。
假设一个 Vault 恰好在 150% 的时候被触发,而拍卖又能按当时的价格无滑点卖出。那么原抵押品的价值是 1.5 倍的 D,偿还债务加罚金只需要 1.13 倍,理论上还剩 0.37 倍。
也就是原抵押品价值的 24.67%。
Maker 后来的赔偿方案,采用的正是这个 24.67% 作为理论上限。
实际返回的比例可以更低,因为价格在清算之后继续下跌,拍卖成交存在折价,执行存在延迟。
拍卖本身分成两个阶段。
创建拍卖的时候,合约记下本轮抵押品,目标金额,被清算 Vault 的所有者,当前出价,最后出价者,单次出价的计时器,以及整场拍卖的截止时间。
第一个阶段里,抵押品的数量保持不变,竞拍者逐步提高自己愿意付的 DAI。
一旦有人出到了目标金额,就转入第二个阶段。此后 DAI 固定不变,竞争者改为竞相接受更少的抵押品。
拍卖结束之后,最终确定的那部分抵押品给胜者,而没有被卖掉的部分返回给 Vault 的所有者。
第二个阶段的存在,是全篇最要紧的一处。
合约专门设计了一个阶段,用来把多余的抵押品还给被清算的那个人。
这不是事后的解释,是写在代码里的设计意图:清算既要保护协议的偿债能力,也要保护 Vault 所有者的剩余权益。
当时的几个关键参数是这样的。
最低有效加价约 3%,也就是新的出价通常至少要比上一次高出百分之三。
单次出价的计时器是 10 分钟。一旦出现了有效的第一笔出价,十分钟之内没有更高的出价,拍卖就可以结束。
这是后来那件事的核心脆弱点之一。
每一场拍卖的抵押品规模,同期材料把 ETH 拍卖描述为最高或者典型 50 枚一场;事后很快就有提议把它放大到 500 枚。
至于整场拍卖的绝对最长时间,本次取得的一手材料不足以稳妥确认 3 月12 日生产环境里的具体数值,所以不把后来的参数倒填成事发之前的参数。
零出价这个名字本身也要纠正。
代码要求新的出价必须大于旧的出价;而初始出价是 0,所以从合约语义上说,字面意义的 0 DAI 无法成为第一笔有效出价。
学术重建也更谨慎地把这些拍卖描述为以接近零的 DAI 结束。
所以零出价应当理解成当时社区和媒体使用的一种简写,指的是经济意义上的零价或者极小的正数,而不能仅凭标题断言每一笔链上的出价字段严格等于零。
参与者在这个体系里承担两个不同的职能。任何人都可以去触发一个已经不安全的 Vault 的清算;而参与拍卖的人则拿 DAI 竞购抵押品。
当时的系统并没有后来那种明确的固定加比例的启动奖励,主要的经济激励来自以低于可变现市场价的价格取得抵押品。
所以参与者实际计算的是:抵押品的转售价值,减去出价的 DAI,减去 gas,减去滑点,减去持有期间的价格风险,减去融资成本。
在市场正常,网络畅通,参与者足够多的条件下,竞争会把这个利润压薄。
而这正是这套设计对市场化清算价格的核心依赖。
所以一次正常的清算应当是这样走完的:价格更新,Vault 跌破 150%,清算把债务连同罚金形成目标金额,拍卖开始,多个参与者争相提高 DAI,最好筹足目标金额,第二阶段继续压缩胜者可以取得的抵押品,结算,目标金额对应的 DAI 抵消系统债务,胜者得到仅够覆盖清算所需的那一部分,剩余的返回 Vault 所有者。
而那一天真正失效的,是这条链上的哪一段,要说清楚。
不是 Vault 能不能被合约识别为低于清算线那一段。
是多个参与者会及时把拍卖价格竞争到合理水平那一段。
而这两段的性质完全不同。前一段是代码可以验证的:抵押率算得对不对,是一道算术。后一段不是代码可以验证的,它是一个关于外面世界的判断。
而两段被写在同一份合约里,看上去是同一种东西。
三 九十六点八与二十九点六
下面的时间统一使用世界时。价格优先采用从链上日志重建出来的小时级轨迹,因为它代表的是协议能够看到的价格,而不是即时的交易所报价。
那份链上重建显示,绝大部分清算集中在 3 月12 日中午到 3 月13 日凌晨六点的约 18 小时里。作者还明确指出,市场先跌,而 Maker 的清算高峰约晚一小时,这与那个一小时的延迟设计相符。
八点到九点之间,ETH 已经从约 190 美元的区域明显下行,而协议看到的仍是较高的滞后价格。后来赔偿范围的讨论指出,最早的零返还拍卖已经可以追到约八点,而不是某些方案采用的中午起点。
九点起,大量实际上不可能被打包的待处理交易急剧增加,约三十五分钟之后生成速率再翻一倍。这些交易多数只带着约 5 Gwei,而市场当时要求 30 Gwei 以上。
十点到十一点,链上的价格图仍处在约 160 到 170 的区域,而即时市场继续恶化。
十一点到十二点,即时价格进入当日最陡的跌段。全日的 gas 均值接近 80 Gwei,约为平日的六倍;小时均值一度接近 200 Gwei。
十二点到十三点,链上价格开始从 160 多急落到 130 多。触发条件开始批量越线。
而这里要说准:并不是预言机始终没有报价格,而是一小时的设计延迟叠加网络更新不及时,让风险集中到了离散的价格跳变上。
十三点到十四点出现了最尖锐的失真。Maker 的价格来源一度仍在约 166,而它所参照的即时市场价格约 130;等到更新交易入块之后,协议看到的价格一次跳低了 20% 以上。
于是大量此前尚未满足链上清算条件的 Vault,突然同时变成了可以被清算的。
那些依赖逐级价格阈值自动保护 Vault 的工具,也可能被这一次跳变一次越过触发点。
十五点到十六点是最差的拍卖小时之一。链上重建显示,这一个小时里结束的拍卖接近 800 场,而成交的中位数接近零;按分位数判断,至少约四分之三的成交处在接近零的水平。
十六点到十七点,同期的应急记录称,最初约两三个小时里几乎只有一个参与者仍在正常触发清算并以经济上的零价竞拍,随后其他人才陆续回来。
这个两三小时是同期的社区记录,不应该被改写成一个精确的分钟数。
而这一句里最要紧的是那个数量词。不是竞争变弱了,是几乎只剩一个。一场需要至少两个人才能定出价格的拍卖,那几个小时里只有一个人在场。
十七点到二十三点,拍卖竞争一度明显恢复,价格的方差下降,成交水平较为合理。
这一点要写进来:系统不是整日完全停摆。
而 3 月13 日凌晨一点到两点,第二波严重异常出现,成交中位数又一次接近零。
到早上六点前后,极端的集中失败逐渐消退。
现在是那对数字。
在那两天之前,约 96.8% 的拍卖能够进入第二个阶段,也就是能够筹足目标金额,进而开始压缩胜者可取得的抵押品。
而 3 月12 日到 13 日,这个比例是 29.6%。
同一份代码。同一套参数。同一个第二阶段。
变的是外面有没有人来。
这两个百分比是全篇最应该并排看的一对。它们不是两个不同系统的对比,是同一个系统在两个不同日子的表现。
gas 的统计也有几个不能混的口径。一家机构报的是全日均值近 80 Gwei,小时均值峰值近 200;另一家后来回看时给的是交易的分位数:那两天里出价最高的一半超过 60 Gwei,最高的百分之一超过 400。
这不是谁对谁错的问题。均值,小时峰值和横截面的尾部分位数,本来就是三样东西。
四 六个原因
参与者为什么没能把价格顶上去,原始材料支持至少六个互相强化的机制。
第一,gas 估计严重滞后。同期分析称不少自动程序以内存池中间分位数附近的 gas 为依据;而在 gas 瞬时跳升的时候,它们的竞价交易排不到前面。
第二,以太坊交易序号的串行性,会把后续交易一起卡住。有机构事后观察到,一笔早期的低 gas 交易一旦形成序号缺口,后面即使提高 gas 的交易也无法越过前一笔。
第三,DAI 会被并发的拍卖占用。旧的机制里,一笔出价在被更高者替换或者拍卖结束之前会一直占用资金;而几千场拍卖同时发生,就可能让一个参与者不是看不到利润,而是根本没有足够的 DAI 去覆盖新的目标金额。
后来引入的全系统在拍债务总量上限,正是直接针对这个并发资本耗尽的问题。
第四,快速下跌让拍卖本身形成巨大的逆向选择与滑点风险。即使一个参与者有 DAI,从他提交竞价到成交,再到把 ETH 卖回市场之间,价格可能再跌几个百分点。同期的应急帖明确说过,有参与者因为滑点风险和长确认时间停下了活动。
第五,部分参与者自建的节点同步或者运行异常。而当时的应急会议把高 gas,节点同步和竞争不足一并列为一个尚未确认的简单根因。
所以这一条应当保持它原文里的不确认地位,不能改写成已经查明的单一故障。
而这一条的不确认状态本身值得留意。事情过去六年,那一天到底有多少参与者是因为自己的节点出了问题而没能出价,至今没有一份可核的统计。
第六,是后来最有争议的那个解释:有机构称发现了大量低 gas,不断替换,意在占用内存池资源的交易,并称此前几天可能已经有过一次类似的测试。
而它没有证据证明那一天的暴跌本身由这些行为制造。
能够较窄地说的是:它的内存池数据支持一种解释,即人为的流量可能加剧了已有的自然拥堵,并使某些高 gas,近零竞价获得了相对优势。
把这六条放在一起,可以看出一件事。
没有一条在合约里。
它们分别属于:一段自动程序对 gas 的估计方法,以太坊交易序号的排队规则,参与者自己账上有多少 DAI,他对再跌几个百分点的判断,他那台机器的同步状态,以及内存池里当时有多少别人的交易。
六样东西,分布在六个互不相干的地方,而其中没有一样是这套合约可以规定的。
它们唯一的交汇处,是同一个十分钟的窗口。
而那十分钟是合约里唯一一个可以被调的数。事后它被调到了六小时。
合约看不见其中任何一样。它只看得见有没有人在十分钟之内提交了一个更高的出价。
而在它看来,没有人提交更高的出价,和所有人都认为这个价格已经合理,是同一件事。
这一条是自动清算这类机制最深的一处结构问题。
一场拍卖之所以能定出合理的价格,靠的是有人不同意当前的报价。而合约能观察到的只有沉默,它没有办法分辨这个沉默是同意,还是没有人在场。
而这正是上一篇那道缝的另一侧。那一侧的问题是有人说了什么而链不知道真假;这一侧的问题是没有人说话,而链不知道这个沉默意味着什么。
两侧合起来,是同一件事的两种表现:合约能处理的只有已经提交上来的东西,而它面对的世界里,最要紧的信息常常是没有被提交的那一部分。
五 七十四点三七
要看清损失到底是什么,最好的办法是拿一个可以逐项核对的个案。
有一位 Vault 所有者在公开渠道给出了完整的参数:抵押品 355.77 枚 ETH,债务 35,613.38 DAI,他自己界面上显示的清算价格是 143.01 美元。最终返回 0。
按这些数字重算一遍。
目标金额等于 35,613.38 乘以 1.13,约 40,243.12 DAI。
如果按 143.01 一枚无滑点成交,需要卖出约 281.40 枚。
理论上应当剩下约 74.37 枚。
所以他因为拍卖失败而多损失的,不是 355.77 枚。
是那 74.37 枚。
这个例子是理解 13% 罚金最好的一个。他的 355.77 枚不是本来只会损失其中的 13%;那个 13% 乘的是 35,613.38 的债务。即使按他自己给出的清算价格参数,正常的拍卖也要卖掉约 281.4 枚,只应退回约 74.4 枚。
近零成交带来的额外伤害,是这约 74.4 枚的剩余权益也没有回来。
而不是相比完全不被清算损失了 355.77 枚。
这个区分不是替谁开脱。它决定的是赔偿如果要做,该按什么数做。而后来的方案确实是按后一个口径算的。
这也解释了为什么那 832 万美元和赔偿规模不能画等号。
前者包括了本来就应该被卖掉,用于消灭借款和罚金的那一部分抵押品。后者如果按恢复到正常清算结果来算,只涉及正常拍卖之后本应返还而没有返还的那一部分。
Maker 后来的赔偿分析给出的最高理论规模约为 288 万 DAI,而不是 832 万美元。
同期的论坛上专门建立了受影响者的登记帖。下面这些是公开可查的当事人自述,其中 Vault 编号和抵押品可以进一步在链上复核,而生活背景,本应收到多少这一类主张不能自动升级为协议或者法院的认定。
一位所有者写下 109 枚 ETH,清算之后返回 0。他说自己经营一个小型的 GPU 挖矿生意,当时失业,其中一部分 ETH 并非完全属于自己,原本计划参与后来的质押。
另一位写下约 1,000 枚,只返回 2.99 枚。
另一位写下 118 枚,返回 0。
另一位写下约 600 多枚,清算之后余额为零。
另一位写下 52 枚,返回 0,并说此前还追加过 10 枚。
还有一位写下 105 枚,返回 0。他说自己曾经尝试偿还 1,200 DAI,而那笔交易长时间没有确认。
这最后一条不能被用来证明,如果那笔交易及时入块就一定不会被清算。
而它记录下来的是那一天在链外发生的事情:一个人试图救自己的仓位,而他的交易没有进区块。
这一句要停一下,因为它是这一整段材料里唯一一处能看见人在做什么的地方。
链上留下的是抵押品数量,债务金额,拍卖编号和成交价格。而链下发生的是有人在那几个小时里盯着屏幕,凑钱,发交易,然后看着它一直不确认。
后面那一样,链上没有一个字段可以记。
还有两位给出了自己的估算。一位约 579 枚,自述清算价格约 178,最后拿到 55 枚,他估算正常情况下至少应该得到 234 枚。另一位 262 枚,自述清算价格约 173,拿到 13 枚,估算至少应得 63 枚。
这些都是当事人自己的算法,而这些帖子没有给足债务字段,所以这里不从抵押品数量硬算理论剩余。
现在追另一头。
近零价的赢家收到的是拍卖最终确定的那部分 ETH,而它向系统支付的 DAI 在经济意义上接近零。
按代码,第一笔有效出价必须是正数,所以不能笼统写成链上严格支付了零。
而它还必须支付 gas,并且为了抢过堵塞的交易,那个 gas 通常必须足够高。
所以那几个小时里能赢的条件其实很具体:手上有 DAI,程序没有卡住,而且愿意为一笔交易付出远高于平日的手续费。满足这三条的人当时很少,而正是这个少,让它能以那个价格成交。
本次可取得的材料没有形成可靠的赢家地址级 gas 总成本,所以不能把免费理解成零成本。
而赢家到底是谁,现有材料只支持一个相当窄的说法。
Maker 当天说最初只有一个参与者。一家机构随后说出现了模仿者。诉状则主张有两套自动程序大量获胜。另一家机构用复数描述那 1,462 场拍卖。
四种描述,四个不同的时间窗和主体口径。
本次没有取得逐场拍卖到赢家地址到抵押品数量到支付成本的完整原始导出表,所以不把某一个地址写成唯一的攻击者,更不把地址归为具体的自然人。
这不是措辞上的小事。
链上的地址获利是可以验证的事实。
而那是一个人,一个机器人,还是几批人,属于另一层命题,需要另一层证据。
六 三十八个地址
协议的坏账和 Vault 所有者的剩余权益损失,最终走了两条完全不同的路。
先看坏账这一条。
白皮书原本就规定:抵押品拍卖不足以覆盖 Vault 义务的时候,缺口成为协议债务;先与协议盈余抵消,如果仍然不足,就进行债务拍卖,由系统新铸 MKR,竞拍者用 DAI 买入,收到的 DAI 用于消除坏账。
也就是说,MKR 在设计里本来就是协议的尾部资本缓冲。
3 月12 日当天,应急会议明确选择不立即启动紧急关停,一个重要理由是:关停可能把损失直接施加给 DAI 的持有人,而社区所理解的默契是坏账应当首先让 MKR 持有人承担稀释。
这是治理参与者的规范性论证,不是法律上的债权优先顺序认定。
债务拍卖从 3 月19 日上午开始。每一场固定让竞拍者向系统支付 50,000 DAI,竞拍者竞争愿意接受的 MKR 数量越来越少。最终共完成 106 场,合计 530 万 DAI,卖出约 20,980 枚 MKR。
这里有一个数字口径陷阱。一篇二手报道给出的平均价是每枚约 279.93 DAI;而用总额直接算,530 万除以 20,980 约等于 252.62。
前者可能是 106 场清算价格的简单平均,后者是按全部卖出量算出来的加权总均价。两者不是同一种平均,不能只列一个而不写算法。
资金的另一头也很清楚。一家投资机构公开称自己赢了 106 场中的 72 场,约 68%,向系统送回 360 万 DAI。
它在这里是资本提供者和拍卖买家:它少了 DAI,多了新铸的 MKR;而原有的 MKR 持有人因为总供应扩大而承受稀释。
不能把这 360 万说成赔偿了 Vault 所有者,因为这笔钱进入的是协议再资本化的路径。
再看赔偿这一条。
支持赔偿的一侧认为:正常拍卖的意图显然包括把多余抵押品返还给所有者;那一天的参与者市场,gas 参数和十分钟窗口没能做到这一点,所以治理资本不应只补 DAI 的支撑,也应承担异常拍卖给使用者造成的剩余损失。还有人强调,界面长期突出那个 13% 的罚金,容易让人理解为清算损失是有界的。
反对的一侧则提出:所有者自己选择了高杠杆并让仓位到达清算线;市场价格仍在快速变化,不能假定每一个仓位一定可以在理论清算价成交;而协议从来没有承诺拍卖必须返回某一个固定百分比。赔偿还会把市场风险事后转给当时的 MKR 持有人,并建立未来极端事件中的救助先例。
也有折衷的论点认为,治理,参与者的基础设施,以太坊网络和所有者本人各负有不同程度的责任。
四月初的一次信号投票曾经支持继续走赔偿方向,方案文件记载约有 62,000 枚 MKR 支持,33,000 枚反对。
而这只是支持制定赔偿这个方向,不是资金已经发放。
后续方案把理论上的完全恢复定为那个 24.67%,并按不同赔付比例列出所需资金。最高档的测算约为 2,880,324 DAI,按方案假定的汇率相当于 11,522 枚 MKR;更低的几档依次减少。
这些是提案的情景测算,不是实际支付额。
而最终在 2020 年9 月8 日到 22 日举行的正式补偿选择投票中,选项包括多档赔偿以及零。
约 65% 的投票权选择了零。
参与者只有 38 个独立投票地址左右。
这个数不加评论。它只是说明,决定几百个人能不能拿回抵押品的那次表决,实际到场的是这个规模。
而这不是有人操纵了投票。链上治理的参与率长期就是这个量级,那一次并不特别低。
所以治理最终没有从协议层向那批 Vault 所有者发放这笔补偿。
诉讼是另外一件事,必须分开。
2020 年,一位 Vault 持有人对相关实体提起了拟议集体诉讼,主张 Maker 对那个 13% 罚金等风险作了误导性表述,并主张预言机,参与者的参与程度和拍卖设计等问题导致自己和其他持有人损失全部抵押品。
这些是原告的主张,不能写成法院认定 Maker 有设计缺陷。
2023 年2 月22 日,联邦地区法院批准了被告针对第二次修订起诉书的驳回动议,同时允许原告再次修改。法院的理由涉及诉状未充分满足相关请求权的形式要求。
也就是说,这个裁定不是法院证明黑色星期四没有缺陷,也不是法院认定 Maker 有责任。
案件后来转为和解。2024 年2 月,联邦法官批准了约 116 万美元的集体和解。
这意味着治理层面的零赔偿,并不等于所有受影响者在现实世界里最终一分钱都没有拿到。
而这 116 万美元是链外的诉讼和解资金,不是治理后来推翻了 2020 年的投票,也不是债务拍卖对 Vault 所有者的赔偿。和解本身通常也不等同于法院对责任事实作出实体认定。
所以损失最终由谁承担这个问题,答案必须分成五层账。
正常清算本来就应当卖掉的那部分 ETH:少的一侧是所有者的抵押品,多的一侧是拿到 ETH 的竞拍者,而他付的 DAI 用于消灭债务。
异常拍卖造成的额外剩余损失:少的一侧是被近零价拍走的那些所有者,多的一侧是那些赢家,而治理后来没有普遍补回。
没有从抵押品拍卖收回的系统债务:少的一侧是协议的资产负债表,补洞的先是盈余,然后是新铸的 MKR。
债务拍卖本身:少的一侧是既有 MKR 持有人承受的供应稀释,多的一侧是新买家用 530 万 DAI 换到了约 20,980 枚。
链外的诉讼和解:付钱的是被告实体,拿到的是符合条件的集体成员,而这不是链上的治理转账。
所以是 Vault 所有者还是 MKR 持有人承担了损失,这是一个伪二分。
两者承担的是不同层的损失。
所有者首先承担的是异常拍卖没有返还剩余权益的那一部分;而 MKR 持有人通过新增的两万多枚,承担的是协议坏账再资本化的稀释。
DAI 的持有人当时没有通过紧急关停被直接削减。而近零价的赢家获得的,是抵押品成交价与市场价值之间的异常收益。
真实世界那一侧的材料明显比链上材料稀少。除了上面那些自述,以及那场集体诉讼和最后的 116 万美元和解,本次检索没有发现能够可靠量化这一天对就业,某个地区的消费,企业成本或者金融可及性的系统性研究。
这里应当保留为证据缺失,而不是从若干条自述推断宏观影响。
七 每一项改动
事后的改动不是把最低出价从零改成一那么简单,因为真正的问题涉及拍卖窗口,交易吞吐,参与者资本,参与者激励,拍卖形式和治理暂停能力多个层面。
单次出价的计时器从 10 分钟大幅延长到约 6 小时。它修的是:一笔低价出价之后,十分钟里因为区块堵塞没有第二个出价,就能用经济上的零价赢走抵押品。
每场拍卖的抵押品规模从约 50 枚放大到约 500 枚。它针对的是几千个清算同时造成的交易风暴;而代价是每一场所需要的参与者资本更高,可能进一步让参与者集中。
引入全系统同时处于拍卖状态的债务总量上限。它直接针对参与者的 DAI 被同时锁在太多拍卖里,资本耗尽的问题。
扩大可接受的抵押品范围。它针对的是单一资产冲击和 DAI 流动性不足,而不是直接修复拍卖竞争;同时它引入了发行人,冻结和托管这一类新的中心化风险。
这一条值得单独看:它是这一整批改动里唯一一个把新的链外依赖引进来的。为了让一个系统在极端行情下更稳,它接受了一些必须信任发行人的资产。
所以抵押品扩张提高安全性这个说法,需要这一层限定。
而最根本的改动是用荷兰式拍卖取代原来的两阶段竞价。
配套的还有几项:内置的四档停机状态,可以逐级禁止新拍卖直到完全阻止购买,使治理在预言机异常或者拍卖明显错误定价时可以暂停局部清算,而不必马上使用全系统的紧急关停;全局与单一抵押品的吞吐限制,把参与者与市场可吸收的能力作为显式参数,而不是假定无限深度;固定加比例的启动与维护奖励,直接解决旧系统高度依赖外部参与者,而启动和维护拍卖的独立经济激励不足的问题;以及起拍价可以在基准之上加缓冲,拍卖随时间自动降价,超过最长时间或者价格下降阈值可以重置。
最根本的变化,是从多人不断上链竞价,转成价格函数自己下降,任何人在自己愿意接受的价格上直接买走。
这降低了那一个特定的假设:必须在十分钟之内,至少有两名参与者的交易都及时上链。
配合可以在同一笔交易里拿到抵押品,卖出或融资,再偿付的结算方式,参与者还可以不必先持有大量闲置的 DAI。
而这一整套并没有消灭底层的网络与预言机风险。
如果以太坊完全没有足够的区块空间,买单一样上不了链。
如果基准价格本身严重错误,那个缓冲只是围绕一个错误的基准报价。
如果市场没有足够深度,荷兰式的价格最终只能持续下降,直到有人愿意接。
所以后来加进去的,是让故障更可控和可暂停,而不是证明自动清算从此不再依赖市场与网络。
这个区别对于理解机制演进很要紧。
而把这一整节的改动排开看,它们其实分成两类。
一类是放宽约束:把十分钟拉长到六小时,把五十枚放大到五百枚,给参与者加上启动奖励。这一类做的是让那个假设更容易成立。
另一类是承认约束:限制同时在拍的债务总量,设置吞吐上限,加上可以逐级停机的断路器。这一类做的是另一件事预先承认参与者和市场能吸收的量是有限的,并且把这个有限写成一个参数。
后一类比前一类要紧。前一类仍然在指望那个假设,而后一类第一次把它当成一个需要被声明的东西。
八 写不进去的那一句
那一天暴露的并不是某一个协议独有的清算会亏钱。
是自动清算系统对几个外部条件有共同的依赖。
第一是市场深度:它假定在需要出售大量抵押品的时候,外部市场仍然有人能以接近报价的水平把它吸收。
第二是结算资产的流动性:它假定参与者可以迅速获得足够的 DAI。
第三是网络容量:价格更新,补充抵押品,偿债,触发清算,竞拍,这些交易必须在有经济意义的时间窗口里进入区块。
第四是价格的新鲜度:触发清算的价格不能在几个市场状态之间长时间停住,然后突然跳跃。
第五是参与者的多样性与理性:他们不能都使用类似的 gas 估计,同一个软件缺陷或者同一个资金来源。
第六是市场风险与执行风险不高度相关。
那一天恰恰让这六个假设同时朝坏的方向移动。
而它们之间还互相加强。价格跌得越快,清算越多;清算越多,网络越堵;网络越堵,价格更新和参与者越慢;越慢,DAI 越稀缺,拍卖折价越深;折价越深,协议和所有者的损失越大。
这条链上每一步都是别的步骤的后果,而没有一步是设计者意图的一部分。
后来的事件说明,自动清算失灵也不只有一种模式。
2020 年11 月另一个借贷协议出现的异常清算,与它所参照的价格源大幅上冲有关,报道统计约 8,800 万美元。那更接近抵押或者债务资产的价格源异常导致健康账户突然越线,而不是拍卖没有竞争。
两个事件都涉及价格来源,而失效的位置不同。
2021 年5 月另一个协议经历的那一轮大型清算,事后研究显示当时的 gas 环境甚至比 2020 年那一天更激烈:出价最高的一半超过约 100 Gwei,最高的百分之一经常达到 1,000 到 4,000。
而它没有产生同一类结果。
两次的差别不在行情,也不在网络,而在机制本身:一个要求在短窗口里反复提交互相覆盖的出价,另一个不要求。
这个比较说明,gas 比当年更高本身,并不足以推出必然会产生近零价的拍卖。
还取决于清算机制是否要求长时间,多轮的竞争交易,以及参与者的资金与执行设计。
本次检索没有得到一个足够干净的,逐协议统一口径的同日清算与坏账面板,所以不把后来材料里的零散数字拼成一个看似可比的排行榜。
尤其要区分清算的名义规模,清算者的利润,协议的坏账,以及借款人的剩余损失。这四样在数据集里经常不是一回事。
而把它们混起来,恰恰是开头那四个数字之所以互相打架的原因。
现在回到第二节那个第二阶段。
那个把多余抵押品还给被清算者的阶段,是写在代码里的,谁都可以读,而且它此前一直在正常工作。
那两天,它有七成没有走到。
而没有走到的原因,不在它自己身上。要走到第二个阶段,前提是先有人把出价抬到目标金额;而那两天,大多数拍卖连这一步都没有发生。
第一个阶段就停住了,于是第二个阶段根本没有机会开始。
合约那一段完全正常。识别,触发,计算,开拍,结算,每一步都按代码执行,没有一处出错,没有一处被绕过。
失效的是代码之外的那个假设。
会有人来。
余项在这里的位置因此很清楚。
它不是一笔没有被记下来的钱。那 832 万美元的每一枚 ETH 都在链上,可以逐笔追到今天。
它是一条无法被写进合约的前提。
这是这个系列到现在为止,余项最纯粹的一种形态。
前面几篇里,余项是被标准留在管辖之外的,是没有进代码的,是没有人被派去量的,是算得出来的时候还没发生的。而这一次,它是一句在语法上就写不出来的话。
你可以写拍卖持续十分钟。
你写不了十分钟之内会有第二个人来出价。
而整套设计依赖的,正是后面这一句。
这一句之所以写不出来,不是因为语言不够精确,而是因为它描述的不是这个系统内部的状态。它描述的是这个系统之外的一批人在那一刻会不会动手。
合约能规定的是自己的行为。它规定不了别人的。
那两天里,合约执行了四千多次。每一次都算对了,每一次都按规矩走完,每一次都在十分钟之后正确地把抵押品交给了出价最高的那一个。
它不知道那个出价最高的,是唯一一个来了的。
链还在结算,而结算什么还没有共识。
本文依据公开协议文档、链上记录、法院文书、监管文件与同行评议研究写成;文中的数字均保留其统计口径。系列资料截至 2026 年 8 月。