本文僅作爲技術分享,不構成任何投資建議。
BTC 上也要有自己的智能合約了?
最近比特幣生態上,Fractal BTC 在經歷了多次測試網之後,終於在 9 月份上線主網。Fractal 的一大特點就是具備「智能合約」的能力,並且幾乎在推出主網的同時,上線了一個新的代幣協議 CAT20。CAT20 有什麼技術上的巧妙設計呢?我們又可以學到什麼?
Fractal Bitcoin
在瞭解 CAT20 之前我們需要簡單瞭解一下 Fractal Bitcoin,他們的關係就像 ERC20 和 ETH 一樣,CAT20 協議是部署在 Fractal Bitcoin 上的。
Fractal Bitcoin 又稱作分形比特幣,是一個完全兼容 BTC 的「二層」網絡。相比於 BTC,它的區塊確認時間更快,僅需要 1 分鐘。它的基本原理簡單來說就如它的名字所言,就是將 BTC 網絡複製了幾份,每條鏈都會處理交易,可以處理交易的節點多了,速度也就自然快了。不過具體的細節比如不同鏈之間是如何通信的目前還不是很清楚,官方也沒有對應的技術文檔可以參考。
如果只是一個二層鏈交易更快,似乎沒有讓人興奮的點。但是,在 Fractal 中啓用了 BTC 很久之前就因爲安全原因棄用的操作碼 OP_CAT,讓 Fractal Bitcoin 的能力上升了一個臺階,有人說 OP_CAT 能讓 BTC 具有智能合約的能力,這樣的話可以遐想的空間就更多了。
現在,就有人在 Fractal Bitcoin 上實現了一個類似 ERC20 的協議。
關於 OP_CAT 爲什麼棄用以及爲什麼又可以在 Fractal Bitcoin 上使用,後續可以展開講講,這裏我們關注 CAT20。
CAT Protocol
以下內容參考白皮書:Introduction | CAT Protocol ( https://catprotocol.org/)
以及 github 倉庫:
GitHub - CATProtocol/cat-token-box: A monorepo for packages implementing CAT protocol ( https://github.com/CATProtocol/cat-token-box)
有了底層的 OP_CAT 支持,很快就有了對應的協議,CAT Protocol。目前一個已經在實際跑的協議是 CAT20 協議,在 Unisat 上也新增了對應的面板:https://explorer.unisat.io/fractal-mainnet/cat20。
看到 CAT20 的名字大家應該也能反應過來,它應該和 ERC20 比較像。相比於成熟的 ERC20 協議,大家部署一個 Token 已經非常的方便,CAT20 是如何實現 ERC20 類似的生命週期呢。
Deploy
在部署之前,用戶需要指定自己的錢包地址以及代幣的基本信息,代幣的基本信息和 ERC20 的類似:
會有一些不同點 CAT20 可以設置預挖和每次 Mint 的數量限制。當然 ERC20 可以通過合約的能力也可以實現這些能力。
在部署階段,會發起兩筆交易,可以認爲是兩個階段:「 commit 」和「 reveal 」。引用官方上的圖,部署的階段如下:
在「 commit 」階段,交易的輸出腳本中會將代幣的基本信息寫入,比如代幣的名稱、符號等。在「 commit 」階段發起的交易 hashId 會作爲該代幣的標誌,用於區分其他代幣。
可以看到這筆交易「 bc1pucq...ashx 」這個 utxo 就是對應了 commit。然後剩下的兩筆指向「 bc1pszp...rehc4 」的交易,第一筆是用於支付下面「 reveal 」階段的 gas 費,另一筆則是找零。
在「 reveal 」階段,可以看到有兩筆 utxo 輸入,對應了之前 commit 階段的前兩個輸出。這筆交易首先會輸出一個 OP_RETURN,在 OP_RETURN 中會保存 CAT20 的初始狀態的 Hash。之後會再輸出一個 Minter,它會在後續的 Mint 過程中發揮重要作用,用來維護 Mint 過程的狀態變化。
回過頭看整個 Deploy 的過程,「 commit 」和「 reveal 」遵循了區塊鏈上常用的提交和揭示兩個步驟,是一種比較常見的部署項目的方式,項目的一些數據只在「 reveal 」階段纔會揭露出來。
Mint
我們先看一下 Mint Token 的時候,交易是這麼樣的。
在上圖中可以看到,Mint 的過程有以下幾個特徵。
mint 的輸入是一個 minter,最開始是由 deploy 的時候生成的。
每一次 mint 都有且只有一個 minter 作爲輸入,有任意個 minter 作爲輸出(有點點問題)
每一次 mint 都有且只有一個 token(有點點問題)
輸出的順序是有要求的,minter 後面必須是 token
知道了 Mint 的過程,其實我們可以發現一些特殊情況,會讓整個 Mint 的過程變得有趣。
比如,minter 作爲 mint 交易的輸出,他可以是 1 個、多個甚至是 0 個。如果每次 Mint 的時候都設置爲 1 個,那麼整個網絡中可以使用到的 minter 數量就會保持不變(1 個),這會讓 Mint 變得擁擠,大家都需要搶這個 minter,爲了避免這種情況,是需要將每次輸出的 minter 數量設置爲大於 1 ,這樣 mint 之後,大家可以使用的 minter 就會越來越多。
不過,每多輸出一個 minter 意味這你需要多支付一筆 utxo,出於經濟考慮,更多的人會樂意將 minter 設置爲 0,就會不可避免的讓 minter 變得通縮,這就需要一些人來進行奉獻了,自願支付多出來的 minter。
在 V2 版本,默認是生成兩個 Minter,並且兩個 Minter 的狀態會盡可能相近。
交易的構建
可能有小夥伴發現了一個問題,那就是爲什麼可以使用 minter 的 utxo 進行交易的構建?想要了解這個問題就需要對“合約”的源碼進行分析。
1、reveal utxo
首先我們對 reveal 過程中的交易進行分析,我們發現他使用了前一個交易的輸出 commit 作爲輸入。爲什麼可以拿一個不是我們地址的 utxo 構建交易的輸入呢?
按照常理,一個私鑰對應一個公鑰,公鑰派生出地址。當驗證一個輸入的 utxo 是否有效的時候,一般是通過比較簽名用公鑰解密之後是否和原本的交易一致來確定。這部分的邏輯是寫在比特幣腳本中的。所以我們可以巧妙的改寫腳本的邏輯,在腳本中寫的公私鑰對是我們自己地址的,這樣我們就可以控制兩個不同地址的 utxo 了。
看源碼我們就能知道發生了什麼:
這裏還會有一個問題,就是一個私鑰對應一個公鑰,那麼爲什麼生成的 commit 地址會和我們地址不一樣呢?這裏從源碼中可以看到
也就是說,我們的私鑰會根據一個 ISSUE_PUBKEY 來調整公鑰,這也是 P2TR 地址的一個特性。
2、minter utxo
reveal 過程中,我們使用不同的 utxo 的作爲輸入,但其實加密的密鑰是同一把,也就是部署者的私鑰。但是在 minter 階段,所有的人都可以使用這些 utxo 作爲輸入,這又是怎麼做到的呢?
這部分我猜測是之前說的 OP_CAT 的能力,也就是智能合約的能力,每一個 minter 就是一個智能合約。不過目前這部分的源碼沒有公開,暫時不知道具體的實現是怎麼樣的。
交易的狀態(V2)
在 minter 中,還保留了狀態。這個狀態存在兩個地方:一個是交易輸出的 OP_RETURN 中,另外就是存儲在智能合約中,也就是上述提到的 Minter 以及 Token。
在 OP_RETURN 中存儲的是當前交易輸出狀態的 Hash,在合約中會存儲 Token 剩餘的 Mint 次數。每次 Mint 之後,新生成的 Minter 的 mint 數量會等於剩餘可以 mint 的數量除以二。用圖表示:
最後打完的時候,所有 Minter 的剩餘數量爲 0。
回到最開始的那張圖上,除了 Minter 是一個智能合約之外,生成的 Token 也是智能合約,也就是 CAT20。CAT20 有兩個基本的狀態:數量以及 Token 的歸屬者地址。可以看到不像之前的 BRC20 或者銘文,你的 CAT20 並不是在你地址的 UTXO 上。
Transfer
Transfer 的時候,構建交易的輸入和輸出的 token 其裏面的數量需要保持一致。當然同一筆交易裏面可以有多個不同的 token,只需要不同 token 的其輸入輸出的數量保持一致就行。
Burn
想要燃燒掉 Token 的話,只需要將 Token 轉到一個普通地址上即可。
總結
可以看到,所有的操作都是由用戶自己去構建,靈活性非常大,所以在合約部分需要做很多的校驗邏輯。目前爆出的一些漏洞也是因爲校驗邏輯出現了疏忽。
這樣的設計可以有一些好處:
如果想要查找所有的 Token 的持有情況,只需要查一下 token 的 utxo 就行,不需要繼續往上查。
如果想要查看 mint 的當前情況,可以搜索 OP_RETURN 中數據帶有 cat 的交易就好。
ZAN 無門檻領水來啦!
Tip:每 24 小時可領取一次 0.01 ETH free testnet token,以支持您在以太坊生態內體驗和測試 Web3 項目,點擊馬上領取: https://zan.top/faucet?chInfo=ch_WZ
更多公鏈即將支持~
本文由 ZAN Team(X 賬號 @zan_team) 的 Yeezo(X 賬號 @GaoYeezo75065)撰寫