很多 DeFi 事故报告里有一句让外行困惑的结论:攻击者用闪电贷把某个池子的价格在一个区块里推高,然后按这个价格从另一个协议借走了钱。这笔账能成立的支点,是后者取用了「可以当场被操纵的历史价格」。这一篇把这个支点拆开。
历史价格取数有三种常见形态,脆弱性各不相同。第一种是快照式:直接读某个交易所池子当前(或上一秒)的储备量,把即时兑换价当市场价。这是最脆弱的——价格就是此刻池子里两堆币的比例,任何能临时搬动其中一堆的资金(闪电贷放大弹药,同区块内借还)都能让「市场价」按攻击者的剧本走。第二种是短窗口均值:对最近若干个数据点或短时段取平均,抗操纵能力取决于窗口长度加样本数——窗口再短,只要一笔交易也在样本里,同区块闪电贷仍能偏转均值,只是偏转幅度被摊薄。第三种是长窗口或外部推送的聚合价:时间加权均值拉长到小时级、或喂价网络用多方签名与中位数跨多个交易所聚合,单笔现货操纵的影响被稀释到攻击成本之上。
攻击方的成本账因此很清晰:目标协议用哪一层取数,决定了操纵一笔价格需要多少资金、多长窗口,以及是否要在多个市场同时动手。防守方的演进也全部沿这条线:把「即时价」换成「均值」,把「单源均值」换成「多源中位数」,再加两道闸门——喂价超时则拒绝读写(staleness 检查)、单周期价格变动超阈值则触发熔断,从「事后取均价」升级为「当场不认账」。近年的事件里还出现过混合形态:一部分资产用操纵成本高的主流池子定价,长尾资产却仍允许即时读取,攻击就集中在长尾一侧。
普通用户能核验哪几层?协议文档和合约是公开材料:抵押品估值用的是哪种函数名(直接现货、均值函数还是外部喂价调用),决定了你的清算线跟着什么价格走。实操上记住三条:热门大资产与长尾小资产的估值防御经常不在一个档次;闪电贷把价格推一个来小时的均值,成本随窗口指数上升,所以「越冷门的资产越要警惕短窗口」;如果你的仓位允许设置提醒,优先订阅的应是喂价异常与熔断事件,而非仅仅价格本身。防御永远是攻防竞赛而非终点,任何协议都不能承诺价格不可操纵。本文全部内容不构成投资建议。
最后补一层用户侧的防御清单,全部无需写代码即可执行。第一,查仓位协议文档中的价格源章节,确认抵押估值与清算判定分别用哪一类取数函数,两类函数不一致时以保守的一方做自己的监控。第二,为长尾资产仓位设置双阈值提醒:价格本身一条线,喂价超时或更新异常一条线,后者优先级更高,因为价格没更新比价格跌了更接近机制失灵。第三,大额仓位分散在不同取数结构的协议之间——全部押在同一类均值函数上,等于把清算线系在同一根绳上。第四,读一下所用协议的应急参数:偏差熔断阈值、极端行情下的降级模式,这些参数在平静期毫无存在感,在事故当天就是决定你按哪个价格被处置的那行代码。防御核验是一次性成本,事故后的追查不是。
补一个观察角度:攻防双方都在为时间付费。防御方把窗口拉长,是用 gas 和延迟换不可操纵性;攻击方压缩成本,靠的是在最短窗口内完成借贷、操纵、取数、还款的闭环,任何一环超时都会让整笔攻击反转为自损。所以读事故复盘时,真正有信息量的不是损失数字,而是攻击者在哪个取数点完成了闭环——那个点就是同类协议普遍还亮着的门,也是你自己仓位估值最可能出问题的位置。

发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。