​SharkTeam:UniswapV4 Hook最佳安全實踐
SharkTeam
2023-08-08 03:59
本文约5316字,阅读全文需要约21分钟
​近期Uniswap Lab 官宣了下一代AMM Uniswap V4 的開發進展,並公開了白皮書和代碼倉庫。這次V4 的白皮書僅僅只有3 頁,原因是V4並沒有對AMM 的核心算法邏輯做太多修改,而是在V3 的基礎上,增加了一些新的特性,以滿足更多的場景需求。 SharkTeam 將基於目前已開源的代碼,來看看V4 帶來了哪些新的特性,並針對V4推出的重要特性Hook 分析最佳應用實踐。

一級標題

二級標題


1.1 AMM

一級標題

一級標題

在AMM 算法層面,Uniswap V4 並沒有對V3 做修改,依然使用基於恆定乘積x*y=k 的流動性算法。

二級標題

1.2 Hooks

在Uniswap V3,每一個交易對可以有4 個池子(原本是3 個,後來增加了一個新的1 bp pool),分別代表0.01% , 0.05% , 0.3% , 1% 費率的池子,這些池子對應的tick space 也各不相同,在創建池子的時候,只能選擇這4 種中的任一個。


  • beforeInitialize

  • afterInitialize

  • beforeModifyPosition

  • afterModifyPosition

  • beforeSwap

  • afterSwap

  • beforeDonate

  • afterDonate


在Uniswap V4,每一個交易對理論上可以有任意數量的pool,並且每一個pool 的fee rate 也可以是任意值,這些pool 的tick space 也可以是任意值。

二級標題

二級標題

Hooks 是一組由第三方或者Uniswap 官方開發的合約,在創建pool 的時候,pool 可以選擇綁定一個hook. 之後在交易的特定階段,pool 都會自動調用與之綁定的Hook 合約。 Uniswap V4 一共定義了這些可以執行hook 合約代碼的階段:

可以看出,Hook 地址的前8 bit 都別用來標記在特定階段此Hook 是否需要執行的flag.

二級標題

因此,Hook 的開發者需要在部署合約的時候,產生出滿足Pool 要求的地址,這通常需要使用Create 2 + 計算隨機Salt 來實現。


以下是白皮書中關於Hook 執行的一個例子:

二級標題

除了可以在特定階段執行代碼之外,Hook 還可以決定某一個pool 的swap fee 費率,和withdraw 費率。 withdraw 費率指的是用戶在移除流動性時需要向Hook 支付的費率。除此之外,Hook 還可以指定在swap fee 中抽成一部分給自己。

二級標題

在創建pool 時,需要使用fee 參數(uint 24)前4 個bit 來標記此pool 是否使用動態fee,以及是否啟動hook swap fee 和withdraw fee:


如果啟動了動態fee,那麼pool 會在每次swap 之前,調用Hook 合約來獲取當前的swap fee ratio. Hook 合約需要實現getFee() 函數,返回當前的swap fee ratio.

另外,使用Singleton 合約的好處是,可以減少交易過程中token 的轉賬,因為所有的pool 都在同一個合約中,所以可以直接在合約內部完成跨pool 的swap,而在V3 中,跨pool 的swap會需要將token 在不同pool 中轉來轉去,這會增加gas.

二級標題

1.5 extload


二級標題

1.6 Flash Accounting


二級標題

二級標題

二級標題

二級標題

為了減少跨pool swap 的token 轉賬,V4 同時使用被稱為Flash Accounting 的方法,將swap, add/remove liquidity/flash loan 的過程都標準化成一種類似閃電貸的過程:

(3)用戶所有操作所產生的token 轉賬都會被記錄在lock 中

二級標題

1.7 ERC 1155 mint/burn


(4)所有操作結束後,用戶可以取走他獲得的token,同時需要支付lock 中記錄他需要支付的token.

這些過程需要發生在一個交易中。

使用ERC 1155 burn 可以將保存在V4 合約中的token 取出。

一級標題

二級標題


一級標題


一級標題

二級標題

二級標題

Alice 想在區塊鏈上購買價值1 億美元的以太幣。在現有的自動做市商(AMM)平台(例如Uniswap)上執行這麼大規模的訂單將非常昂貴,因為這些平台可能會向Alice 收取高昂的費用,以防止她利用內幕消息獲取更好的價格。

2.1.1 原理

為了獲得更好的價格,Alice 的最佳選擇是手動將訂單拆分成幾個較小的子訂單,並在幾個小時內逐步執行它們。這樣做的目的是讓市場有足夠的時間來意識到她沒有內幕消息,從而給予她更好的價格。但是,即使她發送幾個較大的子訂單,每個子訂單仍然會對價格產生重大影響,同時還容易受到敵對交易者的“三明治攻擊”。

TWAMM 通過代表Alice 進行交易來解決這個問題。它將她的訂單分解為無限多個微小的虛擬訂單,以確保在時間上平滑地執行。同時,TWAMM 利用嵌入式AMM 協議的特殊數學關係,能夠在這些虛擬訂單中分攤Gas 成本。由於TWAMM 在區塊之間處理交易,因此也不容易受到“三明治攻擊”。

總的來說,TWAMM 為Alice 提供了一種更高效的方式來進行大規模交易,避免了高昂的手續費和潛在的市場操縱。

2.1.1 原理

TWAMM 有一個內置的AMM,這個AMM 和其他的AMM 並沒有什麼不同,用戶可以通過這個AMM 直接進行現貨交易,也可以向其中添加流動性。但是TWAMM 同時還有兩個TWAP order pool,分別用來執行兩個方向的TWAP order,用戶提交order 時,指定交易的token input 數量和時長,TWAMM 會將相同交易方向的order 放入對應的pool中,並按照指定的交易速度自動進行交易。當用戶的order 被完全執行後,用戶就可以拿出交易得到的token。當然,在用戶的order 在被執行完成之前,用戶也可以提前取消order 或者修改order 需要交易的token 數量。

在以太坊中,智能合約只能由EOA 地址主動發起交易觸發執行,而不能自動執行。因此TWAMM 需要由EOA 賬戶定期發送交易來結算其order pool 中待交易的token,這樣就需要一個keeper 賬號來執行這些交易。

當然,也可以讓TWAMM 在每次有用戶與其交互時,自動結算order pool,這樣就省去了keeper 的開銷,這也是DeFi 協議處理流式數據常用的方式。

2.1.2 為什麼說這種交易模式很難被三明治攻擊?

這種攻擊很難實施,由於一個區塊內timestamp 不會改變,攻擊者必須要在一個區塊的最後一個交易中,將pool 的價格拉高,這樣下一個區塊中的TWAMM 結算才會受到影響。這就要求三明治攻擊發生在多個區塊中,這無疑會給攻擊者帶來很大的風險,因為其他套利者有可能在中間介入,導致攻擊者遭受損失。

同時,因為套利者的存在,這樣的價格操縱注定無法持久,由於TWAP order 的特性它並不會在短時間內交易太多的token,因此大部分情況損失也一定是有限的。

2.1.3 V4中的TWAMM 工作流程

(1)此Hook 維護兩個TWAP order pool,分別表示兩個交易方向的TWAP order

(2)用戶可以通過此Hook 提交TWAP order,需要指定交易的token,數量以及時間長度

(3)此Hook 註冊beforeSwap 和beforeModifyPosition,每次用戶交易或者調整倉位時,都會觸發此Hook

(4)被觸發後,Hook 負責對2 個TWAP order pool 進行結算

(5)用戶也可以在任意時刻手動觸發結算

(6)用戶可以取消或者修改TWAP order 中的token 數量

2.1.4 實例詳解

在用戶將自己需要執行的訂單添加進合約後,在pool 每次進行swap 和modifyPosition 操作時,都會自動進行order 的執行。

二級標題

2.2 Limit Order


每有用戶調用v4的swap 函數進行交易或modifyPosition 函數更改倉位,都會觸發TWAMM 中的執行函數,函數中會調用內部函數_executeTWAMMOrders 繼續進行此前未完成order 的執行。

_executeTWAMMOrders 函數"二級標題"二級標題

例如,假設ETH 目前在ETH/DAI 池中的交易價格為1 ETH = 1500 DAI。用戶可以下一個止盈訂單,主要內容是

2.2.1 原理

如果1 ETH = 2000 DAI,賣出我所有的ETH

。如果達到這個價格,用戶的ETH 將自動以去中心化的方式完全在鏈上交換為DAI。

在Uniswap 以前的版本中,限價訂單實際上是不可能的。大多數AMM 只允許市場買入和賣出。而在V4版本中,由於hook 的強大特性和可擴展性,讓限價單在v4中存在了實現的基礎。

2.2.1 原理

limit order 的設計原理相比於twamm 來說,更加簡單一些,目前實現了有關添加流動性的限價單,交易的限價單實現起來也會比較容易。

由於v4中存在tickLower 和tickUpper,並根據池子的交易情況變化,lower 和upper 會發生改變,用戶在進行添加流動性時並不想在當前價格進行添加,這時就可以利用limit Order hook 來執行此需求,在hook 中設定對應的價格,在每次swap 結束後,hook 會對當前pool 的價格做判斷,若達到了設定的價格,則將對應的流動性進行添加獲取收益。

2.2.2 V4 中的Limit Order 工作流程

1. limit 維護著多個epoch,作為不同lower 和交易方向的限價單。

2. 用戶通過這個hook,提交自己的價格lower 和交易方向,將限價單加入合約。

3. 此Hook 註冊afterSwap,只在每次swap 結束後價格發生變動時觸發

4. 被觸發後,Hook 校驗當前價格區間,並從epoch 中查驗當前價格是否存在需要進行添加流動性的限價單。

5. 用戶可以在任何時刻提款或直接添加流動性

2.2.3 實例詳解

合約註冊兩個階段觸發hook,在Pool 初始化後對hook 初始化,並在每次兌換結束後觸發hook 邏輯。

用戶調用place 函數傳入想要添加流動性的數量,價格以及交易方向,hook 會先將用戶想要添加的流動性加入pool 中保存,隨後為用戶創建對應的限價單。

在每次swap 結束後都會觸發此hook,根據當前價格區間將區間價格內存在的限價單完成添加流動性的操作。

LP 复投:用戶可利用hook 來進行流動性的添加,修改和移除,hook 可註冊afterSwap 和afterModifyPosition 來進行調用。由於用戶統一使用hook 來進行流動性的添加,所以在poolManager 中添加流動性的地址只有hook, hook 可在每次觸發時查驗當前時間,每經過一定時間段後,選擇提取流動性獎勵並將獲得的lp 代幣再次到pool 中添加流動性,從而自動化優化用戶收益。

一級標題

二級標題


一級標題


一級標題

二級標題

二級標題

減少require 和revert 的使用

避免使用自毀函數

做好防重入限制

避免在hook 中使用selfdestruct 函數,如果hook 中調用到了自毀函數,不僅會導致hook 中的邏輯出現問題,並且會導致pool 中的功能也無法正常進行,使整個pool 池中的資產丟失並且功能無法正常進行。

合約升級控制

一級標題

About Us


官網:

官網:https://www.sharkteam.org

Twitter:https://twitter.com/sharkteamorg

Discord:https://discord.gg/jGH9xXCjDZ

Telegram:https://t.me/sharkteamorg


SharkTeam
作者文库