SSRN 7157638 · Aave v3 即時帳簿研究
已發表 · SSRNLiquidation Without Loss
A Live-Book Decomposition of Aave v3
把循環帳簿的風險數字讀成損失,會無上限地誇大一個借貸協議的曝險。本文將壓力測試壓縮成單一數字的三個量分開,推導出成交量可能轉為損失的深度,並量化真正促成轉換的各個管道。以下全部跑在以太坊的單一即時區塊上:17,419 名借款人、65 億美元債務。
資料夥伴
Bitquery 提供事件日誌與借款人列舉,包含用於樣本外檢定的 Aave v2 事件前帳簿。CoinGecko Pro 提供共變異數籃與事件重建背後的每日價格標記。兩者皆以本研究贊助者的身分提供 API 存取。
本文確立了什麼
結果
13.8 億符合條件,0 損失
1,437 個部位的流動性質押切片在 5% 脫錨下,有 13.8 億美元被標記為符合清算條件。其中約一半確實成交,而在引擎沿路徑推演的 13.57 億美元純循環核心上,沒有任何一分是協議損失的資本。
機制
LT(1+b) < 1
當一個類別的清算門檻乘上其獎勵仍小於一,跨越 HF = 1 的循環倉位會在抵押品仍足以覆蓋含獎勵債務時被移除。Aave 在八個上線的 e-mode 類別中全部滿足此條件。
控制項
破壞路徑,而非深度
損失需要離散跳空、過時的預言機,或深度不足以吸收沒收量的資金池。單靠深度不會產生損失。因此槓桿在預言機邊界與供給上限,而不是清算門檻。
是三個量,不是一個
壓力測試印出一個數字,風險部門把它讀成損失。在循環帳簿裡,它既不是成交的量,也不是協議損失的資本;一旦讓帳簿沿真實價格路徑推演,而非在單一低點做標記,這三者就會清楚分開。
符合條件的債務,是指健康因子跨越一的部位所持有的債務。在部分關閉係數下,部位是分批被清算的:一次呼叫償還當前債務的一部分,沒收使其重新回到門檻之上,之後仍可能再次跨越。因此符合條件的債務約為實際償還額的兩倍,而在這個即時叢集中沒有任何一個部位被完全關閉。
為什麼循環倉位對所有人都在測的那個衝擊是避險的
循環倉位存入一項資產、借出一項相關資產,再重新存入。壓力引擎以抵押品對債務的加權變動來縮放每個部位鏈上的真實健康因子,其中每個 u 是該腿的美元價值,而鏈上的 HF₀ 已經內含協議的 e-mode 門檻。寫成比率形式時,它假設各抵押腿共用單一清算門檻,這對純循環核心成立;明確的逐資產形式則把每一腿自己的門檻放進抵押品加總之內:
機制在比率中一目了然。當抵押品類別等於債務類別,(1 + 變動) 因子相互約去,全市場下跌幾乎不改變健康因子,循環倉位存活下來。而方向性部位的穩定幣債務腿保持不動、抵押品下跌,變動就完整落在它身上。
def shocked_hf(position, moves): """Scale the real on-chain HF by a collateral-vs-debt weighted move. We never re-derive a loan-to-value: HF0 is read from the chain and so already embeds whichever e-mode liquidation threshold the account selected. """ coll = sum(u * (1 + moves[a]) for a, u in position.collateral.items()) debt = sum(u * (1 + moves[a]) for a, u in position.debt.items()) coll_w = coll / sum(position.collateral.values()) debt_w = debt / sum(position.debt.values()) return position.hf0 * (coll_w / debt_w) # liquidatable iff < 1 # A loop holds the same class on both legs, so the move divides out:# hf0 * (1 + m) / (1 + m) == hf0 -> survives a market crash# A directional position holds a stable debt leg, so it does not:# hf0 * (1 + m) / (1 + 0) == hf0*(1+m) -> liquidated這正是為什麼統一化儀表板對循環帳簿報出的數字是一種淨額慣例,而不是帳簿的性質。對照一個正確做淨額的機構,相關性模型與同類別對照在每個嚴重度上都吻合到 8% 以內,在 −5% 時為 0.92×。較大的 6.53× 與 9.13× 衡量的是淨額遺漏的大小。而這種抵銷不是資產分組方式的產物:打亂抵押品與債務的配對後,比率從 9.13× 崩落到約 1.3×,兩種方案下 p = 0.0002。
讓清算不產生損失的那個不變量
循環倉位是依其所處模式的參數被清算的,而解讀在這裡最容易出錯:即時叢集位於與 ETH 相關的 e-mode,其類別獎勵是 1%,不是 wstETH 準備金的 6% 獎勵。從 Pool 合約讀取,這組參數是 LT 0.95 搭配 b = 0.01。
清算人沒收的抵押品價值等於償還額乘上獎勵,且以該部位仍持有的抵押品為上限。因此只有當抵押品不再足以覆蓋這筆含獎勵的沒收時,缺口才可能出現,這直接給出條件:
在 LT 0.95 下,要進入跨越即虧損的區間,獎勵必須高於 5.26%,是 Aave 設定值的五倍。八個上線的 e-mode 類別全部落在 0.876 到 0.960 之間,wstETH 準備金組合為 0.859。這不是刀鋒上的平衡,也正因如此,這個 0 美元是結構性的,而不是一項實證穩健性發現。
成交量在哪裡可能轉為損失
成交量與損失之間的落差,只有在能指出它止於何處時才具備可操作性。一個以門檻 LT 存入抵押品 C、對應債務 D 的循環倉位,其鏈上健康因子為 HF₀ = C·LT/D,而深度 f 的脫錨會相對於維持不動的債務腿把抵押品向下標記。有兩個深度是關鍵,斷點取其中較大者:
第一項是健康因子達到一、清算開始符合條件的位置。第二項是含獎勵的沒收再也無法被覆蓋、協議壞帳開始出現的位置。損失不可能在循環倉位尚未可被清算之前就開始,因此 D* 取最大值。以槓桿表示時,兩者都隨槓桿升高而縮小。
def d_star(leverage, lt, bonus): """Depth at which a de-peg stops being volume and can become loss. f_hf the loop becomes liquidation-eligible (HF reaches 1) f_exh collateral stops covering the bonus-grossed seizure """ hf0 = lt * leverage / (leverage - 1) f_hf = 1 - 1 / hf0 # == 1 - (L-1)/(L*LT) f_exh = 1 - (1 + bonus) * lt / hf0 # == 1 - (1+b)(L-1)/L return max(f_hf, f_exh), f_hf, f_exh # The live ETH-correlated e-mode anchor: ~12x leverage, LT 0.95, 1% bonusd, f_hf, f_exh = d_star(12, 0.95, 0.01)# f_hf = 0.0351 eligible at a 3.5% de-peg# f_exh = 0.0742 loss cannot begin before 7.4%# d = 0.0742 -> a 3.9-point band of pure liquidation volume對於約 12× 槓桿的即時 e-mode 錨點,循環倉位在 3.5% 時符合清算條件,但直到 7.4% 才開始虧損:中間有 3.9 個百分點的區間,脫錨在其中只產生純粹的成交流量。整個即時切片的中位數為 6.9%,以債務加權為 8.8%。封閉形式在所有檢查點上都重現了級聯引擎的起始點,誤差在一個格點之內,最多 0.02%。
真正把成交量轉成損失的是什麼
因為每個上線的循環倉位都處在有償付餘裕的區間,更深的連續脫錨並不會把成交量轉為損失。循環倉位在自己的跨越點被移除,且仍具償付能力,無論深度多少。沿連續滑降推演時,錨點循環倉位從 2% 到 20% 都記錄 0 美元。真正造成轉換的是路徑的破裂,而每一個管道都能在同一個引擎上被量化。
最先咬人的管道不是最戲劇性的那個。寬到足以跳過邊界的離散跳空,到 8% 之前都不記錄任何損失。在有限資金池中的部分清算,於 5% 跳空時記錄 301 萬美元,而在深度充足的池中做完整清算則記錄零,因為該部位在數輪之間持續處於水下,而每一次強制賣出都為下一輪壓低價格。這個數字是該管道的上界:Aave 在健康因子低於某門檻時會把關閉係數提升到 100%,而單次完整關閉可避免多輪壓價。以 2022 年 6 月實測的預言機過時程度計算,8% 跳空的損失會從 58 萬美元放大到深度過時尾端的 513 萬美元。
# One liquidation call, inside the cascade to a fixed point.# Two caps carry the whole result. # Aave's cap. Note close_factor is promoted to 1.0 below a health-factor# threshold, so the partial-round case below is the worst case, not the only one.repay = position.debt * close_factorseize_value = repay * (1 + bonus) # bonus-grossed # A position cannot be seized for more collateral than it still holds,# so a loop liquidated over several rounds never over-seizes.available = position.collateral - position.seizedseized = min(seize_value, available) position.debt -= repayposition.seized += seized # Loss is the residual, and it only opens once the grossed seizure# stops being covered: bad_debt = D - C(1 - f)/(1 + b)if seized < seize_value: bad_debt += repay - seized / (1 + bonus) # Selling the seized collateral into a finite x*y=k pool moves the mark# for the next round. With close_factor < 1 the position sits underwater# across rounds, and that is the channel that books loss at gaps a# deep-pool boundary treats as harmless.price *= constant_product_impact(seized, pool_reserves)次級市場深度決定量級,並使起始點提前:對於分散的叢集,起始點從對上無限深池的 6.05% 降到池為有限時的 2.10%,而在固定 15% 跳空下,已實現損失從 3,020 萬美元上升到對上 10 億美元池的 6.957 億美元。循環倉位不是因為被清算而虧損。它們虧損,是因為被清算進去的市場太薄,吸收不了那筆沒收量。
當強制賣出本身推動了錨定價格
把 13.8 億美元讀成成交量,最尖銳的反駁是:這假設賣壓能在不移動錨定價格的情況下被消化。對流動性質押代幣而言,錨定價格就是次級市場價格,因此被拋出的抵押品會壓低正是用來標記它的那個比率。在即時叢集上把這個回路內生化,並讓提款佇列處於凍結狀態,一個超過最高槓桿循環倉位 0.19% 觸發點的衝擊,會把錨定價格帶到約面值的 3%,相當於約 97% 的脫錨。
即使在那裡,協議記錄的仍是 0 美元,因為每個循環倉位都在錨定價格跑過它之前,於自己仍具償付能力的跨越點被移除。缺少後備機制時的危險,是該代幣市場本身的崩塌,受害的是它的持有人,而不是協議資產負債表上的破洞。佇列運作正常時,贖回套利會把脫錨完全限制在失控區間之下。
這對參數委員會意味著什麼改變
本文的建議沿著「哪些參數才真正適用」這條軸線一分為二。在與 ETH 相關類別下持有的 wstETH 部位,受類別門檻管轄,因此變更準備金門檻碰不到它。持有 wstETH 抵押品的 1,723 個帳戶中,有 56 個處在只有該類別才能達到的有效門檻上;其餘 1,667 個依準備金定價。
- 把準備金門檻從 0.81 下調到 0.59,會使準備金模式帳戶在 5% 脫錨下的風險部位從 1,690 萬美元升到 1.441 億美元,增加八倍,卻沒有消除任何已實現損失。該區段裡本來就沒有可消除的損失。
- 尾端風險住在 e-mode 類別裡,而在那裡的操作性控制是供給上限與運作中的提款後備機制,兩者都不是門檻變更所能提供的。
- 預言機偏離與心跳邊界管轄跳空與延遲管道,而損失實際上是從那裡進來的。
- 依次級市場深度設定的供給上限,管轄部分清算管道,也就是在深池邊界視為無害的跳空處仍會記錄損失的那一個。
直說了:清算門檻不是那根槓桿。它決定成交量從哪裡開始,而成交量並不是讓協議賠錢的東西。
為什麼可以信任引擎給出的零
一個恰好為零的結果,會引出「這個引擎究竟能不能記錄任何損失」的疑問。它能,而本文用了相當篇幅去證明這件事,而不只是宣稱。
- 同一個引擎在路徑被破壞時會記錄巨額已實現損失:賣進 20 億美元的有限資金池,分散叢集從約 3% 脫錨起就記錄 2.03 億美元。請注意它越過的是哪一條邊界。它越過的是有限池的 2.10% 起始點,而不是深池的 D* 6.05%,因為有限池會使起始點提前。所以那個 0 美元是曲線在其斷點以下的取值,不是程式碼跳不出去的地板。
- 三個真實事件重建到同一個位置。最嚴苛的一個是 Aave v2 的 stETH 事件前帳簿,取自 2022 年 6 月脫錨之前的歸檔狀態,並沿真實的錨定價格路徑推演:它記錄 0 美元,對應協議可忽略的已實現損失。同一事件另有一份以清算收據為基礎的重建,在路徑上同樣記錄 0 美元,而在那份重建上,單一低點快照會發出 2,510 萬美元的假警報。本文把這兩種構造分開處理,而它們在零這一點上一致。
- 2023 年 3 月的 USDC 反事實情境在 26 個部位上標記 30 萬美元,對應已實現 0 美元,而那 26 個部位與預言機定錨重建完全對得上。
- 熱路徑核心以 Rust 實作,另有 Python 參考版與 Numba 孿生版,三者在 1e-9 之內數值等價;在 300 個案例的煙霧測試中,觀測到的最大絕對差約為 2.3e-13。
- 隨機種子固定為 20260609,並在匯入 numpy 之前把 BLAS 執行緒數固定為一。置換方案、強化檢定及其判定規則都寫在一份以雜湊鎖定的分析計畫中。本文對這件事能保證什麼很謹慎:雜湊證明的是計畫的完整性,而不是它在時間上的先後,因為鎖定日期是自行宣告的,檔案在四天後才進入 git 歷史。事件前帳簿檢定是在鎖定之後追加的,並已如此標註。
同一個引擎,用在一筆真的發生過的損失上
2022 年 11 月,一個帳戶以 USDC 作為抵押品借入 9,200 萬 CRV,而該部位反轉。當該代幣被向上擠壓時,清算來不及把債務清掉:清算人償還了 8,960 萬 CRV,抵押品用盡,還剩下 239 萬 CRV 的債務未清。本文刻意不為這個事件發布任何深度或滑價數字,因為擠壓期間的價格衝擊擬合出現負的 R²,而一個連常數都比不過的數字,比沒有數字更糟。
這筆殘餘以當時 0.693 美元計價,就是損失:模型算出 165 萬美元,對應鏈上已實現的約 160 萬美元,誤差 3.4%。這是脫錨結果的鏡像,而且出自同一個核心。當清掉部位的成本超過清算獎勵,清算就停滯,殘餘便成為協議的損失。一個引擎同時重現了一個真實的 160 萬美元破洞,和一個真實的 0 美元。
這個 0 美元涵蓋什麼、不涵蓋什麼
- 嚴格的主張適用於 13.57 億美元的純循環核心。其餘 1.76% 是混合抵押部位,其他腿帶著自己的參數;不變量使 0 美元同樣是那部分的預期結果,但這一點是被揭露出來,而不是併入計算。
- 即時快照帶有每個帳戶的有效清算門檻,但沒有它所選的 e-mode 類別,因此類別歸屬是由有效 LT 推得。兩群之間有很寬的空隙,切分乾淨,但它畢竟是一個代理變數。
- 協議壞帳為零,不等於經濟成本為零。同樣這些清算仍會把獎勵付給清算人,對被清算的借款人造成實質損失,並可能觸發 DAO 的補償。這個主張講的是協議的資產負債表。
- 準備金門檻掃描是把較低的門檻套用在今天這本凍結的帳簿上,因此它量到的是一次性的過渡成本,而不是永久調低門檻後會落到的穩態。
如何重現
引擎、Rust 核心、資料取得腳本、對等性測試框架、凍結的 fixtures 與預先登記全部完整公開。市場資料不做再散布:即時狀態來自公開的歸檔 RPC,事件日誌來自 Bitquery,價格標記來自 CoinGecko Pro,憑證皆從環境變數讀取。所有主要數字都跑在一份固定且經雜湊的快照上,因此這些主張是可以對著輸入資料查核的,而不是要從一份沒有金鑰的複本重新抓取。 github.com/DaruFinance/defi-param-stress
引用
相關研究
The de-peg engine’s credibility checks fit peaks-over-threshold GPD tails and a tail-dependence coefficient χ. That is the same machinery, implemented and demonstrated on its own, in Peaks-over-threshold and pairwise tail-coupling.

