時間:2021-12-24|瀏覽:337
代碼的升級是一件痛苦且脆弱的事。尤其是在本就十分復雜的代碼大廈上,任何微小的改動,都可能因為某些邊界條件的疏忽而造成崩塌,Compound最近就遇到了這事
背景介紹
Compound是一個老牌的去中心化借貸平臺
Q1: 為什么要有借貸這回事兒?
在區(qū)塊鏈上,所有的資產(chǎn)都是代幣化的。我們看好一個項目,但是卻沒有這個項目發(fā)行的代幣。這時最簡單的方法就是去交易所用手里有的幣來換。但是,如果我們又不舍得自己手里的幣,該怎么辦呢。這時可以去借,抵押品便是我們擁有的幣。如果這個項目漲了,獲得收益的同時,還可以贖回曾經(jīng)抵押的幣。
交易會發(fā)生所有權(quán)的轉(zhuǎn)移,而借貸不發(fā)生所有權(quán)的轉(zhuǎn)移,只是被暫時鎖在合約中
同時,由于借貸的引入,我們可以操控更大的資金敞口,實現(xiàn)杠桿交易...
Q2:Compound的運作流程?
和AMM類似,在區(qū)塊鏈上實現(xiàn)自動化的借貸,首先要做的便是吸引資金(流動性),而用戶所以能將錢存在一個平臺,必然是受到利益的驅(qū)使。AMM通過交易費來激勵用戶添加流動性,而借貸平臺的手段便是借款利息
由于存在借貸這一需求,總會有人愿意付出利息來借幣。而有了利息的激勵,也有人愿意將閑錢拿來提供流動性。此外,借貸平臺通過利率模型參數(shù)的動態(tài)調(diào)整,可以維持整個系統(tǒng)的供給平衡與風險
Q3: 如何與Compound交互?
用戶與Compound的交互接口主要是CToken/CEther合約(這些合約本身就是一種代幣), CToken 相當于 Compound這一平臺的"入場券"。通過向不同CToken合約質(zhì)押其底層代幣(underlying token)便可以獲得相應的CToken
這一操作,表現(xiàn)在代碼層面就是 ctoken.mint(amount),比方說:我手里有1000個ETH,便可以調(diào)用cEth.mint(1000) 來向cEth池中 "注入流動性"
要注意的是,cToken和底層代幣并不是1:1的兌換關(guān)系,當?shù)案庠阶鲈酱髸r,cToken所能換出的底層代幣也就越多。這和LP token的類似,利息便是以這種形式來發(fā)放的
那有了cToken以后,我們可以做什么呢?
最簡單的便是借錢,因為cToken代表用戶質(zhì)押在Compound的資產(chǎn),因此可以通過"過抵押"的方式來借出Compound擁有的代幣。Compound會先計算用戶擁有所有cToken的價值(可能來自于不同的池),根據(jù)抵押率來計算用戶的流動性(Liquidity)
表現(xiàn)在代碼層面就是 ctoken.borrow(amount),比方說:我通過 ceth.mint(1000) 質(zhì)押了 1000 個 ETH,如果我想借 Dai 的話,需要調(diào)用 cDai.borrow(x) 這里的 x 最多價值750 ETH (抵押率75%)
這些都是以美元計算的,再根據(jù)Oracle來換算成不同的Token數(shù)量
而Comptroller這一合約是一個中間層,它所做的事情,便是交互前的一些計算與驗證工作,類似銀行的審計員。比方說:張三借了多少錢,欠了多少錢,這小子又來借1000個ETH還能不能借給他
表現(xiàn)在代碼層面就是:getHypotheticalAccountLiquidityInternal()、borrowAllowed()、mintAllowed() ...
Q4: COMP代幣與Compound的關(guān)系?
COMP代幣是Compound發(fā)行的平臺代幣,可以用于管理。因為Compound采用DAO的治理模式。對Compound所有的操作,都需要通過投票來決定,提案(proposals)通過后由一個特權(quán)合約來執(zhí)行寫在提案中的操作。通過COMP可以獲得投票的權(quán)重
詳情見:https://compound.finance/governance
當然只能用來投票顯然還是缺少些吸引力的,COMP本質(zhì)上就是Compound發(fā)行的股票,擁有更多的COMP,可以享受更優(yōu)的利率,隨著Compound的發(fā)展,COMP帶來的價值也會越來越大,因此COMP值錢(目前 $300 左右)
同時,為了激勵用戶使用Compound,無論是向Compound提供流動性,還是從Compound借出資產(chǎn),都會獲得一定的COMP獎勵,這些獎勵以區(qū)塊為單位計算(劃重點:這里與本次事件相關(guān))
修了東墻又補西墻
事故1:Bug的原理
事情的起因是這樣的:
2021年9月31日,Compound DAO出現(xiàn)這樣一條提案(Proposals 62: https://compound.finance/governance/proposals/62):
該提案提出更新 Comptroller 合約以修復一些 Bug
這里我們可以看出 Bug 和 CompSpeed 有關(guān),CompSpeed 這個變量代表是每個區(qū)塊可以挖出的 COMP 數(shù)量
這里以 mint 為例簡單介紹Bug的原理:
ctoken 的 mint 函數(shù)的調(diào)用鏈為:mint → mintInternal → mintFresh
可以看到,在 mintFresh 中,會先調(diào)用 Comptroller 的 mintAllowed 函數(shù),再更新用戶 ctoken 的余額
而 mintAllowed 中,會先調(diào)用 updateCompSupplyIndex,再調(diào)用 distributeSupplierComp
前者會更新借貸池的獎勵狀態(tài),主要是 compSupplyState
這一結(jié)構(gòu)體中,block字段記錄了更新時的區(qū)塊號,index字段記錄的是更新時的獎勵指數(shù)
**什么是獎勵指數(shù)(index)呢?**這是一個隨時間不斷累加的值,其公式為
表示的是一個借貸池,隨著時間的推移,向每個cToken分發(fā)的COMP數(shù)量。因此,其差值可以簡單理解為,這段時間內(nèi)一個cToken可以獲得的COMP數(shù)量