作者:Trustless Labs

在深入研究BRC-20 代碼和機制後,我們發現轉帳階段有針對huge holder 可能的攻擊手段。為了幫助交易所檢查是否存在流程規範問題,同時也實踐白帽精神,我們嘗試使用測試過的手段鎖定了幣安ORDI 熱錢包資產,導致幣安暫停ORDI 提現。我們第一時間通知了幣安團隊,溝通了操作細節,以幫助幣安盡快恢復提現,三小時後,幣安恢復了ORDI 提現。本文會從BRC-20 的設計原理出發,系統性地分析一下幣安暫停ORDI 提現的原因,幫助大家理解為什麼任何人都可以鎖定你的BRC-20 餘額。

首先我們在UniSat 看一下鏈上都發生了什麼事。

從BRC-20的設計原理出發,分析錢包潛在的攻擊漏洞

這是撰寫本文時UniSat 上展示的幣安ORDI 熱錢包餘額,分為三部分Transferable、Available 和Balance。這裡涉及BRC-20 中的三個基本概念Transferable balance、Available balance 和Overall balance。 Transferable balance 是指可以直接轉出的餘額,Available balance 是指可以變成Transferable balance 的餘額,Overall balance 是前面兩者之和,表示當前地址總餘額。看到這裡大家可能會問了,既然當前幣安ORDI 熱錢包有這麼多餘額,那為什麼還無法提現轉出呢?別急,我們繼續往下看。

BRC-20 的轉帳需要兩步驟操作,第一步先inscribe 一個transfer 的Inscription ,第二步再把這個Inscription 轉給接收方,完成BRC-20 的轉帳。由於Inscription 轉移是基於UTXO 的,也就是說,第一步inscribe 了多少amt 的Inscription ,第二步就只能轉出多少amt 的BRC-20,所以前面提到的Transferable balance 也是基於UTXO 的。舉個例子方便大家理解,假設A 是新建立的位址,然後你mint 了m 個ORDI 到A 位址,或是從其他位址轉了m 個ORDI 到A 位址,這時A 位址的Available balance 和Overall balance都為m ,Transferable balance 為0 。然後我們從A 位址轉n 個ORDI 到B 位址,第一步先inscribe 一個amt 為n 的Inscription 到A 位址(當且僅當n <= m 時,該Inscription 是有效的),此時A 位址的Transferable balance 為n ,Available balance 為m - n ,Overall balance 為m ;第二步再轉移這個amt 為n 的Inscription 到B 位址,此時A 位址的Available balance 和Overall balance 都為m - n ,Transferable balance為0 , B 位址的Available balance 和Overall balance 都為n ,Transferable balance 為0 ,轉帳完成。

從BRC-20的設計原理出發,分析錢包潛在的攻擊漏洞

以UniSat 上展示的幣安ORDI 熱錢包交易列表為例,圖中Method 為inscribe-transfer 的對應上面講到的第一步操作,Method 為receive 或send 的對應第二步,而且圖中最後兩筆交易共同組成了一個完整的BRC-20 轉帳。另外三筆inscribe-transfer 的交易分別inscribe 了amt 為8,210,108 、6,099 、2,683 的三個Inscription,這三個Inscription 共同組成了Transferable balance。所以如果現在要從幣安ORDI 熱錢包轉出ORDI ,只能轉出三筆對應amt 的ORDI ,當然無法滿足用戶多樣的提現需求。

造成這種情況的原因在於,任何人都可以inscribe 一個任意的Inscription 到任意地址,所以任何人都可以透過執行BRC-20 轉帳的第一步操作鎖定任意地址的BRC-20 餘額。那麼幣安該如何解決目前面臨的問題呢?其實很簡單,只要把前面提到的三個Inscription 轉給自己,就可以把Transferable balance 變回Available balance ,然後再根據用戶提現需求inscribe 對應amt 的Inscription 轉出。但這只能解燃眉之急,無法從根本解決問題,只有改進協議本身,解決目前BRC-20 設計上存在的缺陷,方可一勞永逸。