Author: Chung Fu-Chuan, NTU PPM
Published on 1st Dec.
感謝 ChiHaoLu review 此篇文章。
目錄
- 前言
- HTLC intro
- An Example of HTLC-based Swap
- 實作看看
- 優缺點
- 結語
前言
本系列文章想簡介「跨鏈交易」的基礎觀念。在前一篇文章中介紹了一種使用以 Trusted Relayer 作為鏈與鏈之間訊息傳遞者的 — XY Protocol,並提到在使用者只能完全信任 Relayer 的情況是「不安全且具風險性」的。
而此篇文章想要介紹一種在跨鏈交易中不須透過「第三方介入」的跨鏈方式 — HTLC。
HTLC intro
HTLC 的全名為 Hashed Time-Locked Contract,中文被稱為哈希時間鎖定合約,最早出現於比特幣的閃電網路,是一種可以實現 Atomic Swap (一種不經由第三方完成,安全可靠的跨鏈交易)的技術。
Atomic Swap
譯為原子交換,概念是將每一筆交易當成最小且無法分割之單位,只會有成功或者失敗兩個選項,不具有中間值。此特性是當雙方互相約定好,便可以安全且順利的完成跨鏈的交易,但是若有一方無法完成條件,便會將原本投入的資產物歸原主。也就是原子交換只會有雙方同時成功跨鏈交易,或是雙方都退回資產的結果,不會有任一方捲款潛逃的結果。
Drill into more details
在此技術中,雙方的鏈上各會擁有一個智能合約,雙方會將想轉換的資產鎖定在該智能合約中。
這個過程會有兩個重要元素:
- Hashlock: 使用密碼學製作出的密鑰,用來讓對方得到權限取得資產。
- Timelock: 將資產鎖入智能合約後,經過一段時間讓對方輸入密碼。
- 正確:可以成功的交換(將鎖定在合約的資產 transfer 到指定的地址)。
- 錯誤:交換失敗(將鎖定在合約的資產將歸還原主)。
An Example of HTLC-based Swap
這邊會敘述一個關於 HTLC 的例子,會依循著 fig.2 來做說明。
前提:
小明想要跟小華進行交易,這筆交易預計可以將 x 枚的 token A 轉換成 y 枚的 token B。
- token A:存在 A 鏈上的資產。
- token B:存在 B 鏈上的資產。
地址:
- AA:小明在 A 鏈上的地址。
- AB:小明在 B 鏈上的地址。
- BA:小華在 A 鏈上的地址。
- BB:小華在 B 鏈上的地址。
秘密:
- s:一段秘密(可以是一段 string)。
- hash():雜湊函式,不同的 input 會造成不同但是長度相同的 output,並且不能(難以)從 output 回推成 input。
- h = hash( s )
- 小明利用 AA ,送入秘密 s 部署了一段 HTLC 合約稱為【 A 】。
* 合約中會將 s 經過 hash() 產生一段哈希值 h。
* 同時會規定一個在 A 鏈上的地址,只有他可以領取其中的資產。
2. 小華得到【A】與 h,並透過 BB 將 h 部署合約於合約【 B 】中。
3. 小明使用 AA 發起一筆交易,將 x 枚 token 鎖定在【 A 】中。
* 時長為 ∆ta 的 timeout 會開始計時。(實際上是設定一個時間點)
4. 小華看到小明將他的錢鎖定在【 A 】中。
5. 小華使用 BB 發起另一筆交易,將 y 枚 token B 鎖定在【 A 】中。
* 時長為 ∆tb 的 timeout 會開始計時。
6. 小明使用 AB 去戳【 B 】上的 claim()
函式,這個函式可以驗證密碼,並將錢轉給 AB。
7. 小明 claim()
時,同時會把 s 廣播在區塊鏈中,小華可以從這筆交易得到 s。
8. 小華使用 BA 去戳【 A 】上的 claim()
函式,若驗證成功後合約會將錢轉給 BA。
以下為 timeout 時沒有將 s 傳給 claim 的結果。(即交易失敗的情況)
- 若在 ∆tb 前,小明並沒有提供正確的 s 給【 B 】上的
claim()
,【 B 】則會將鎖定在它身上的 y 枚 token B 退還給 BB。 - 同理,若在 ∆ta 前,小華並沒有提供正確的 s 給【 A 】上的
claim()
,【 A 】則會將鎖定在它身上的 x 枚 token A 退還給 AA。
實作看看
在網路上查詢資料的時候,發現實作 HTLC 的合約非常少,大部分只有解釋他的邏輯而已。因此接下來我想要實作一個在 Goerli 上與 Polygon 上執行的 HTLC,並使用 Chainlink 的 Upkeep 來執行「戳合約歸還資產」的動作。
這個合約是一份點對點的合約,使用過一次便會失效。
我按照上述的邏輯來實作一份 solidity 的合約,主要的邏輯非常簡單。
- 在
constructor()
中傳入s
、目標地址(對方的地址),並更新到h
與targetAddress
中。
2. 將資產鎖進合約中:
- 使用的是
lockAssets()
讓使用者可以把錢送進去。 - 設定
lockedTime
,以計算 timeout。 - 將
hasLocked
改成 true,代表已存入。
3. claim()
:
- 確認傳入密碼與地址正確才可以成功提款。
- 只能提款一次:透過
hasClaimed
來限制。 - 如果 timeout 之後才提款也會失敗。
4. 如果超過時間:
- Chainlink 的 Upkeeper 會透過 EOA 去戳我們函式中的
ckeckUpkeep()
並回傳一個UpkeepNeeded
。(timeout 並且尚未提款時回傳 true) - 如果
UpkeepNeeded
是 true 時會再去戳performUpkeep()
,並將放在裡面的資產歸還。
上述只提到了其中一方(以 fig.2 為例就是小明那一方)的合約,另一方的合約則需要做一些更改。
- 通常另一方的 timeout (∆tb) 會設置成 1/2(∆ta),這是為了確保 a 方提款後要確保 b 方有足夠的時間提款,否則就會被 a 方拿走全部的資產。
- b 方不知道秘密 s,因此只能從公開的資訊直接設置 h。
若對程式碼有興趣的可見此
優缺點 — 優點
資訊透明
相較於上次提到的 XY Protocol,HTLC 的優點就是可以安全的交易,因為兩邊的資訊都是公開在區塊鏈上。
公平性
除了安全以外,HTLC 的方式其實也蠻公平的。不會有一方拿到錢但是另一方沒有拿到的問題,且若對方沒有將錢拿走,還是可以將鎖進合約中的資產拿回。
除了有一方忘記 claim()
,不過應該很少人會這麼做。
安全性佳
HTLC 除了透過雜湊函式來驗證秘密 s,也限制只有規定的使用者可以提取資產,就算擁有 s 也無法代替他人來 claim()
,或是透過 h 回推 s 的機率也非常低,因此可說是十分安全的。
優缺點 —缺點
使用者體驗差
同樣比較上次的 Protocol,可以發現 HTLC 的缺點是使用者體驗頗差。雙方一定要等到對方 deploy 合約後才能進行 claim()
,若對方沒有提領,還需要等到 timeout 後才能退款。
手續費
在鏈上 deploy 就必須要花費一筆手續費了,此外以我上述實作的例子中,Chainlink 的 Upkeeper 也需要花錢。
且 HTLC Swap 方式都是在區塊鏈上與合約進行互動,因此手續費也會隨著鏈上 gas fee 不同而調整,雖然不一定會比透過 Relayer 的手續費貴,但是也不穩定。
匯率問題
由於資產需要鎖定在合約中一段時間,可能會發生匯率產生劇烈變化時造成重大損失的問題。
或是攻擊者會透過這點進行攻擊:攻擊者 (B) 可以一筆匯率 A / B = x 的交易對其他人 (A) 發起交易,在對方鎖定資產後不立即交易,而是先等待時機,待市場上匯率 A / B = y < x 的時候才發起交易(也就是比市場還便宜的價格買走商品),賺取與市場的差價。
結語
無論是中心化或去中心化的跨鏈方式都有其優缺點,例如使用 Trusted Relayer 的協議則使用者體驗較佳,並可以獲得相對於市場上較佳的匯率,但是安全性則可能具有風險;而使用 HTLC 的方式的安全性則較佳,但是使用者體驗差,無法快速兌換並且可能會產生與市場有差異的兌換價格。(其他跨鏈橋的比較可見 Nic 的文章)
其實各有各的好壞,使用者可以選擇自己想要使用何者來進行跨鏈交易。不過還是同一句話,我認為使用者有「監管自己資產」的責任,在使用任何產品之前都需要思考可能存在的風險。
歡迎 donate