讀Uniswap程式碼學到的那些合約開發技巧,比教科書有意思多了



最近在做去中心化交易所的開發教學時,深入研究了Uniswap V3的實現方式,才發現有些寫法真的很妙。之前只寫過簡單的NFT合約,這次算是第一次認真啃DeFi合約的代碼,發現了不少東西值得分享給想學習uniswap教學的朋友。

先說一個我最驚訝的——合約地址居然可以預測?

一般部署合約得到的地址看起來都是隨機的,但Uniswap用了一個聰明的辦法。它透過在建立合約時加入salt參數,使用CREATE2操作碼,讓生成的地址變成可預測的。具體做法是「pool = address(new UniswapV3Pool{salt: keccak256(abi.encode(token0, token1, fee))}());」這樣的程式碼。這樣做的好處是,只要知道交易對和手續費信息,就能推算出池子的合約地址,不用真的部署後才知道。這在驗證交易權限或快速定位池子時特別有用。

回調函數的設計也挺精妙的。

在Uniswap中,當你呼叫swap方法進行交易時,它會回呼swapCallback函數,把計算好的所需Token數量傳回來,然後你在回調裡把Token轉入。這樣的好處是整個交易邏輯被完整執行,不需要拆成多步或用複雜的變量記錄來確保安全性。簡單來說就是A呼叫B,B在被呼叫時又呼叫A,形成一個閉環。

預估交易的方法也挺Hack的——用異常來傳遞信息。

因為預估交易時並不會真的產生Token交換,所以會報錯。Uniswap的做法是在回調中拋出特殊錯誤,然後用try-catch捕獲,從錯誤信息中解析出需要的資料。看起來有點野蠻,但確實很實用,不用特別改造swap方法就能實現預估功能。

精度問題的解決方案值得學習。

在計算交換Token時,如果直接做除法會丟失精度。Uniswap的做法是先左移96位(相當於乘以2^96),然後再做除法運算,最後在計算過程中把2^96約掉。這樣在uint256的範圍內既能保證精度,又不會溢位。程式碼中的sqrtRatioAX96和sqrtRatioBX96就是這個思路,看起來複雜但邏輯清晰。

手續費收益的計算方式也很聰明。

與其在每次交易時都給每個LP記錄手續費(這樣會消耗大量Gas),不如記錄總手續費和每個流動性應該分配的比例。LP提取時只需要用自己持有的流動性乘以歷史每股手續費就能算出收益,就像持股人按照每股收益來提取分紅一樣。這個Share計算方式在很多項目中都有應用。

不是所有信息都要上鏈這點也很重要。

交易池的清單、基本信息等完全可以存在傳統資料庫中,定期從鏈上同步就行,不需要即時呼叫RPC介面。現在很多區塊鏈服務商都提供了高級接口,讓你能更快速便宜地獲取數據,這就是同樣的思路。

最後是代碼組織的方式。

一個複雜項目通常會把合約拆分成多個部分來維護,Uniswap就繼承了很多合約。同時也要善用已有的標準合約,比如直接使用OpenZeppelin的ERC721來管理頭寸,這樣既能提高開發效率,也能保證代碼質量。

說實話,看再多文章不如自己動手。在實現一個簡易版去中心化交易所的過程中,你才能真正理解Uniswap為什麼要這樣設計。WTF-DApp課程就是基於這個想法,帶你一步步完成uniswap教學的實戰項目,相信會對你的合約開發有不少幫助。
此頁面可能包含第三方內容,僅供參考(非陳述或保證),不應被視為 Gate 認可其觀點表述,也不得被視為財務或專業建議。詳見聲明
  • 打賞
  • 回覆
  • 轉發
  • 分享
回覆
請輸入回覆內容
請輸入回覆內容
暫無回覆