【漏洞分析】ReflectionToken BEVO代幣攻擊事件分析

阿菜ACai發表於2023-05-09

前言

BEVO代幣是一種Reflection Token(反射型代幣),並且擁有通縮的特性。關於Reflection Token更為詳細的說明可參考這篇文章。然後目前瀏覽到的很多分析報告沒有指出其漏洞產生的真正原因,所以就自己試著去做一下分析吧。

相關資訊

攻擊過程分析

image

整個攻擊過程很簡單:

  1. 首先閃電貸借出大量的WBNB
  2. 透過池子換出大量BEVO
  3. 呼叫deliver函式消耗所有的BEVO
  4. 呼叫skim函式,獲得比在deliver函式中所消耗的更多的BEVO
  5. 呼叫swap函式獲得超額的WBNB

每一步都是正常的操作,但是最後的結果就是攻擊者成功獲利了。背後漏洞的成因還有點繞,接下來詳細分析。

函式流程對比

由於BEVOToken是基於ReflectionToken進行修改的版本,而原版的反射代幣執行這個簡單的deliver+skim操作是安全的。那麼我們將原版的ReflectionToken與魔改後的BEVOToken的_transferStandard函式進行一個對比(該函式在transfer的過程中要用到)。

REFLECT.sol(Original)

_transferStandard 流程

  1. 透過_getValues函式,基於tAmount計算出所有後續要用到的tAmount和rAmount,包括Fee和TransferAmount
  2. 登記rTransferAmount的轉賬:sender賬戶減少,recipient賬戶增加。
  3. 然後將Fee燃燒掉:從rTotal中減去rFee

CoinToken.sol(BEVO)

_transferStandard 流程

  1. 透過_getValues函式,基於tAmount計算出所有後續要用到的tAmount和rAmount,包括Fee,Burn,Charity和TransferAmount
  2. 透過_standardTransferContent函式,登記rTransferAmount的轉賬:sender賬戶減少,recipient賬戶增加。
  3. 呼叫_sendToCharity函式,將Charity值增加到FeeAddress賬戶中
  4. 呼叫_reflectFee函式,從rTotal中減去rCharity,rFee,rBurn。從tTotal中減去tBurn。

BEVO機制漏洞

盈利的條件

先來了解一個前置條件,假設不收取任何費用的情況下,要透過deliver+skim這兩個操作進行盈利,則需要要求skim得到的rAmount大於deliver掉的rAmount值。表示為rSkim > rDeliver。
公式推導為:

  1. [1]rPair = tPair * (rTotal / tTotal)
  2. deliver操作
  3. [2]rPair2 = tPair * (rTotal - rDeliver) / tTotal
  4. [3]rSkim = rPair2 - rPair
  5. 若要求[4]rSkim > rDeliver,將公式1,2,3代入公式4
  6. 得[5]rDeliver > rTotal - rPair

而正常情況下,rTotal作為所有rAmount值的總和,自然可得rTotal >= rDeliver + rPair,調整後得[6]rDeliver <= rTotal - rPair。顯然,公式5中的條件並不能滿足,無法實現透過deliver+skim這兩個操作進行盈利的目的。

那究竟發生了什麼,打破了這種安全的場景。

奇怪的計算

在函式流程對比這一章節中有提到,BEVO呼叫_transferStandard轉賬的時候,會收取一個叫Charity的費用(1%)。收取這個費用的時候會將rCharity和tCharity增加到FeeAddress賬戶中,並且從rTotal中減去rCharity。

這裡就出現了問題:

  1. 如果BEVO只是將rCharity從rTotal中減去,則效果類似於deliver和Fee的燃燒。
  2. 如果BEVO只是將rCharity和tCharity增加到FeeAddress賬戶中,則效果類似於轉賬。

但是它既將rCharity從rTotal中減去,又將rCharity和tCharity增加到FeeAddress賬戶中,這使得從rTotal的數值是不包括rAmount[FeeAddress]的,而FeeAddress地址上確實存在有一筆rAmount。這就有點像一筆本該銷燬的資金,被FeeAddress偷偷藏了起來,這筆資金從rTotal賬面上來看是銷燬了,但是卻被FeeAddress揣在了口袋裡。

然後,如果這筆資金凍結在FeeAddress地址中不再流轉,那麼也不會對整個經濟模型進行影響(就相當於deliver了)。但是,FeeAddress會用它手中的BEVO從Pair裡兌換WBNB。這就使得了這筆不在rTotal範圍內的資金流入了Pair地址中。

這會造成什麼影響?

漏洞的成因

前面提到,FeeAddress會用它手中不合規的BEVO從Pair裡兌換WBNB,從而使這筆不在rTotal範圍內的資金rFeeAddress流入了Pair地址中。此時,將Pair池中的rAmount從新定義為[7]rPair2 = rPair + rFeeAddress

這筆不在rTotal累加範圍內的資金加入,使得代表盈利條件的公式5能夠實現,由rDeliver > rTotal - rPair2,將公式7代入後調整可得[8]rDeliver + rFeeAddress > rTotal - rPair

所以,攻擊者首先借助閃電貸借出大量的BEVO代幣,透過deliver操作,使得Pair中屬於rFeeAddress的那部分的代幣份額增大,從而執行skim操作的時候就能拿到超額的BEVO代幣。最後歸還閃電貸跑路。

後語

最近在學習ReflectionToken的相關內容,瞭解到了BEVO代幣的安全事件,打算跟著網上的分析文章把細節摸清一下。但很可惜發現網上的分析文章都是淺嘗輒止,一副懂的都懂不懂的我也不多說了的樣子,看到攻擊者deliver+skim獲利了就斷定是deliver導致rTotal減少,從而rate增大就獲得了套利機會(其實賺不了)。然後我按照文章中的思路計算了兩天死活就算不出來盈利(就讓我多吐槽幾句吧因為我真的手算了好多頁紙硬是沒算出來)。所以自己摸索著搞了一份分析,因為小老弟也是在學習的過程中,所以文章有可能有錯的地方,還請各位師傅多多指點。感謝閱讀!

相關文章