Uniswap V3代碼解析:7個實用合約開發技巧

從 Uniswap 代碼中學到的合約開發小技巧

最近在編寫去中心化交易所開發教程時,參考了 Uniswap V3 的代碼實現,學到了許多寶貴的知識點。作爲一名之前只開發過簡單 NFT 合約的開發者,這次嘗試 Defi 合約開發讓我有了不少新的收獲。相信這些小技巧對想要學習合約開發的新手會很有幫助。

接下來讓我們一起來看看這些實用的開發技巧,其中有些甚至可以稱得上是奇技淫巧。

Web3 新手系列:我從 Uniswap 代碼中學到的合約開發小技巧

可預測的合約部署地址

通常部署合約得到的是一個看似隨機的地址,因爲與 nonce 相關,所以合約地址難以預測。但在某些情況下,我們需要通過交易對和相關信息推斷出合約地址,比如判斷交易權限或獲取池子地址等。

Uniswap 通過添加 salt 參數使用 CREATE2 方式創建合約,使得創建的合約地址可預測。地址生成邏輯爲:新地址 = hash("0xFF",創建者地址, salt, initcode)。

Web3 新手系列:我從 Uniswap 代碼中學到的合約開發小技巧

善用回調函數

Solidity 中合約之間可以互相調用。在某些場景下,A 調用 B 的方法,B 在被調用的方法中回調 A 是很有用的。

Uniswap 中,調用 UniswapV3Pool 合約的 swap 方法交易時,它會回調 swapCallback,回調會傳入計算出的本次交易實際需要的 Token。調用方需要在回調中將交易所需 Token 轉入 UniswapV3Pool,而不是將 swap 方法拆分爲兩部分讓調用方調用。這確保了 swap 方法的安全性,保證整個邏輯被完整執行,無需繁瑣的變量記錄來確保安全性。

用異常傳遞信息,用 try catch 實現交易預估

Uniswap 的某些合約中,將 UniswapV3Pool 的 swap 方法用 try catch 包裹執行。這是爲了模擬 swap 方法來預估交易所需 Token。由於預估時不會實際產生 Token 交換,所以會報錯。Uniswap 通過在交易回調函數中拋出特殊錯誤,然後捕獲該錯誤,從錯誤信息中解析出所需信息。

這種方法看似有些取巧,但很實用。無需爲預估交易需求改造 swap 方法,邏輯也更簡單。

Web3 新手系列:我從 Uniswap 代碼中學到的合約開發小技巧

用大數解決精度問題

Uniswap 代碼中有大量計算邏輯,如根據當前價格和流動性計算交換的 Token。爲避免除法操作導致精度損失,計算過程中經常使用 << FixedPoint96.RESOLUTION 操作,即左移 96 位,相當於乘以 2^96。左移後再進行除法運算,在正常交易不溢出的情況下保證精度。

雖然理論上仍會有精度損失,但通常只是最小單位的損失,可以接受。

用 Share 方式計算收益

Uniswap 中需要記錄 LP(流動性提供者)的手續費收益。顯然不能在每次交易時都給每個 LP 記錄各自的手續費,這會消耗大量 Gas。

Uniswap 的解決方案是在 Position 結構體中定義 feeGrowthInside0LastX128 和 feeGrowthInside1LastX128,記錄每個頭寸上次提取手續費時每個流動性應得的手續費。

簡而言之,只需記錄總手續費和每個流動性應分配的手續費即可。LP 提取手續費時,根據持有的流動性計算可提取的手續費。這類似於持有公司股票,提取股票收益時只需知道公司歷史每股收益和上次提取時的收益。

Web3 新手系列:我從 Uniswap 代碼中學到的合約開發小技巧

不是所有信息都需要從鏈上獲取

鏈上存儲相對昂貴,並非所有信息都需要上鏈或從鏈上獲取。例如,Uniswap 前端網站調用的許多接口是傳統 Web2 接口。

交易池列表、交易池信息等可存儲在普通數據庫中,有些可能需要定期從鏈上同步,但無需實時調用鏈或節點服務提供的 RPC 接口獲取相關數據。

當然,關鍵交易必須在鏈上進行。

學會合約拆分,利用已有標準合約

一個項目可能包含多個實際部署的合約。即使實際部署只有一個合約,我們也可以通過繼承方式將合約拆分爲多個合約來維護。

例如,Uniswap 中的某些合約繼承了多個合約。在實現時,直接使用了 @openzeppelin/contracts/token/ERC721/ERC721.sol 合約,這樣既方便通過 NFT 方式管理頭寸,又可以利用已有標準合約提高開發效率。

總結

親自動手開發比閱讀文章更能加深理解。嘗試實現一個簡易版去中心化交易所的過程能讓你更深入理解 Uniswap 的代碼實現,也能學習到更多實際項目中的知識點。

Web3 新手系列:我從 Uniswap 代碼中學到的合約開發小技巧

查看原文
此页面可能包含第三方内容,仅供参考(非陈述/保证),不应被视为 Gate 认可其观点表述,也不得被视为财务或专业建议。详见声明
  • 讚賞
  • 4
  • 分享
留言
0/400
论坛潜水怪vip
· 07-10 04:37
大佬可否细说这部分技巧
回復0
熊市种菜人vip
· 07-09 08:14
小菜鸟,先从炼丹做起
回復0
难道我又错过空投vip
· 07-09 08:10
又要开卷了?刚卷nft完还不够
回復0
Web3教育家vip
· 07-09 07:53
好的同学们,让我快速讲解一下...
查看原文回復0
交易,隨時隨地
qrCode
掃碼下載 Gate APP
社群列表
繁體中文
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)