作者:Trustless Labs
在深入研究 BRC-20 代码和机制后,我们发现转账阶段存在针对 huge holder 可能的攻击手段。为了帮助交易所检查是否存在流程规范问题,同时也践行白帽精神,我们尝试使用测试过的手段锁定了币安 ORDI 热钱包资产,导致币安暂停 ORDI 提现。我们第一时间通知了币安团队,沟通了操作细节,以帮助币安尽快恢复提现,三小时后,币安恢复了 ORDI 提现。本文会从 BRC-20 的设计原理出发,系统性地分析一下币安暂停 ORDI 提现的原因,帮助大家理解为什么任何人都可以锁定你的 BRC-20 余额。
首先我们在 UniSat 上看一下链上都发生了什么。
这是撰写本文时 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 ,转账完成。
以 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 设计上存在的缺陷,方可一劳永逸。