瞭解 Compound 清算的基本概念和流程以及如何設計一個清算機器人。

原文標題:《清算人系列 | 如何設計一個 Compound 清算機器人?》
撰文:王澤政

區塊鏈數字資產和加密貨幣市場已發展成爲一個充滿活力的金融生態系統。但相較於傳統金融市場,絕大多數項目的設計思路都是基於數字資產或加密貨幣在空間上的轉移,而金融本身仍作爲時間定價的工具,塑造了一個關於可量化、可交易的時間維度。Compound 項目在此背景下應運而生,該項目是一種基於供求關係的分佈式協議,設計了一種基於貨幣市場設定利率的算法,實現了用戶無時間摩擦地交易以太坊資產

清算人系列 | 如何設計一個 Compound 清算機器人 ?

本文分爲三部分,第一部分簡要介紹該項目中與清算相關的基本概念,第二部分通過示例講解清算流程,第三部分介紹如何設計一個清算機器人。

清算的基本概念

Compound 項目中與清算相關的基本概念主要包括:cTokenComptrollerLiquidityClose factorLiquidation Incentive

cToken

Compound 協議目前支持 Erc20 和 Ether 兩類基礎資產,cToken 是兩類基礎資產在 Compound 上的集成,轉換公式爲 cToken = 基礎資產 / 當前匯率。cToken 在 Compound 上有兩種作用,分別是作爲利息的衡量標準和貸款的抵押物。有別於傳統銀行的計算方式,利率是通過複利的形式增長的。cToken 在 Compound 協議中作爲度量衡使用。

Comptroller

Comptroller 通過 collateral factor 對 Compound 協議進行風險管理,即 Comptroller 爲協議的風險管理層。每類基礎資產都有相互獨立的 collateral factor,其數值大小根據基礎資產的流動性和市值規模在 0~90% 浮動。流動性越強,市值規模越高數值越大。若 collateral factor 爲 0,該類基礎資產不能用作抵押或者在清算中進行抵扣。Compound 根據 collateral factor 確定用戶所需抵押品價值以及該用戶是否可以被清算。

Liquidity

Liquidity 是 Compound 協議清算的標誌位。當賬戶的 Liquidity 不爲正數時,將被該協議的其他用戶清算,直到將 Liquidity 重新設置爲正數。賬戶 Liquidity 計算由下列公式(1)、(2)、(3)求得:

清算人系列 | 如何設計一個 Compound 清算機器人 ?

其中,tokensToDenom 是將其他資產價格轉換爲 ETH 價格的匯率,oraclePrice 是從預言機中獲得的單價。爲解決在源碼中 Liquidity 是 uint 類型、無法表示負數的問題,源碼中定義 shortfall = sumBorrowPlusEffects – sumCollateral。很多清算程序爲統一表示,將 Compound 協議清算標誌位設爲 health。Health 小於 1,則表示該賬戶需要被清算。

Close Factor

Close factor 是需要被清算的部分佔未償還貸款的百分比,即基礎貸款需要被清算的部分。例,一個需要被清算的賬戶 close factor 爲 0.1,那麼需要清算其貸款的 10%。如果用戶擁有多種借入資產,close factor 是某一資產的屬性,並非該用戶總資產的屬性。

Liquidation Incentive

Liquidation incentive 是爲清算人提供額外的抵押品,以鼓勵清算人對 underwater 賬戶進行清算。例如,Liquidation incentive 爲 1.1,則清算人會獲得借款抵押品 10% 的獎勵。目前 Liquidation incentive 在 1.3~1.5 之間。假設 Liquidation incentive 爲 1.05,可以使用公式(7)計算在清算完成時清算人的收益。

清算人系列 | 如何設計一個 Compound 清算機器人 ?

清算流程

爲保證 Compound 系統平穩運行,該協議設計了一套完備的風險和清算規則。爲了降低貸款風險,Compound 協議在每類資產中增加了 collateral factor 屬性。該屬性定義了某類資產單位抵押物可以借貸其他資產的數量。即,抵押率的一種表示方式。目前的主要借貸協議都是通過超額抵押的方式借款,通常要求抵押率低於 150% ,比如:加入市場的抵押率爲 150%,用戶在 Compound 超額抵押 ETH 借出一筆 DAI 貸款,但不巧的是,在貸款期間恰逢 ETH 的價格大幅下跌,使得該借款人的抵押品價值跌破了對 ETH 要求的抵押品比率 150%。

如果沒有補足或者出售抵押品,就會觸發清算程序,此外,借款人還要繳納清算罰金,這個時候清算人可以觸發 Compound 清算程序,可以以低於市場價格 3% -5% 的折扣獲得 ETH 抵押品,這部分差價便是 Liquidation Incentive 的由來。由此,借款人償還了 Compound 系統的貸款,避免 Compound 平臺出現債務和壞賬,維持了系統的償付能力,同時,清算人也獲得了單筆 3%~5% 的收益,類似於礦工費,清算人獲得了收益,平臺也行以正常運行。

在 Compound 的清算機制中,只要清算人通過監控合約發現借款人的抵押率過低,一旦觸發清算程序,清算人就會立刻啓動清算。

如何設計清算機器人?

清算機器人的總體設計原則爲更快地發現 Liquidation incentive 高、且需要被清算的 underwater accounts,從而獲得更高的清算收益

如何發現 underwater accounts

Account API 能夠實現與 Compound 協議交互各種賬戶信息,可以使用此 API 按地址檢索特定用戶的數據,或獲取 unhealthy accounts 列表。Compound 協議 API 的輸入輸出格式是由 Protocol Buffers 指定的。與典型的 protobufs 不同的是,Compound 除了支持 protobufs 二進制格式外,還支持 JSON 格式。若在輸入輸出中都使用 JSON 格式,需要在請求中標明「Content-Type: application / json」和「Accept: application / json」。

決定清算人清算的因素

  • 必須有 unhealthy accounts 才能進行清算,這是清算的前提條件。
  • 在清算時,應儘量選擇可在交易所輕鬆清算的抵押品作爲抵押的賬戶進行清算。流動性高的抵押品更容易實現數字資產的貨幣化;
  • 應儘量選擇抵押品和債務集中在少數幾類資產的 unhealthy accounts 進行清算。若 unhealthy accounts 的抵押品和債務分散在衆多資產上,每次調用 liquidateBorrow 交易時都需指定一個 debt contract 和一個 collateral contract,以至於需要多次調用才能完成清算,增加清算的成本;
  • Ethereum 虛擬機 (EVM) 是一個全局狀態機,必須按順序處理 liquidateBorrow 事務。因此,清算人要想獲得更高收益,需要更快地發現並清算 unhealthy accounts;
  • 假設某個 unhealthy accounts 全局 close factor 爲 0.5,並擁有 N 個債務和 M 個抵押資產,要最大程度地增加清算量。這是一個揹包問題的具體應用,即將每個項目建模爲元組,項目總數爲 N * M。債務權重必須小於等於 close factor,且最大化抵押物價值。

尋找 unhealthy accounts 速度的決定性因素

  • 網絡延遲和硬件速度
  • Gas 花費
  • 使用高 Gas 花費來廣播一條清算交易優於廣播多條。若同時廣播多條清算交易,可能某一清算交易已經在以太坊的有效塊中,從而導致區塊鏈打包失敗;
  • 應選擇擁有足夠抵押品的 unhealthy accounts 進行清算,如抵押品價值不足將導致交易失敗;
  • 建立鏈下緩存程序,該程序將 health 值小於 1.2 的賬戶標記爲存在清算風險的賬戶,進行重點監控。一旦滿足清算要求第一時刻發起清算交易,減少與 Compound 協議交互次數。

執行清算的成本

  • 執行清算是一項資金密集型操作,爲清算 100 萬美元的貸款,清算人需要有 100 萬美元的資金;
  • 清算交易是一個高度週期性交易行爲。幣值市場的重大波動會造成清算交易集中式爆發,從而增加交易成本,並導致短期內大量被清算人走向破產,進而影響整個 Compound 項目的平穩運行;
  • 爲加快發現 unhealthy accounts,需要一個監控程序對可能被清算的賬戶進行監控,增加了准入的技術門檻;
  • Gas 的費用可能會對最終收益產生巨大影響。所有交易的基礎成本爲 21000 Gas,若與合約進行交互會增加相應的 Gas。因此,清算程序需要預先計算預期收益。

清算與收取抵押物最大值計算方式

某些賬戶的抵押品價值可能少於最大清算金額,如果最大清算量或最大可收集抵押品價值小於交易所花費的 Gas 乘以 Gas 的單價,那麼清算交易永遠不可能獲利。計算最大清算數量和抵押品最大收取量公式如下:

清算人系列 | 如何設計一個 Compound 清算機器人 ?

需要注意的是 sum (token_borrow_balance_underlying_in_eth) != total_borrow_value_in_eth。通過調用 Account API 可以獲得更加準確的 Oracle Price,但會降低運算速度。爲了優化速度,在可以接受的誤差範圍內犧牲準確性,使用近似價格計算。通過 PriceOracle 可以獲取 cToken 的 getUnderlyingPrice 和 liquidateCalculateSeizeTokens,通過 cUSDC 合約獲取 exchangeRateStored。通過匯率計算便可以快速、近似地計算出所需收取抵押物的數量。