This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
Uniswapソースコードの秘密:7つのコントラクト開発テクニックがDefi初心者を月へ助ける
コントラクト開発のテクニック共有:Uniswapのソースコードから学ぶ
最近、分散型取引所の開発チュートリアルを書いているときに、Uniswap V3のコード実装を参考にし、多くの価値ある知識を学びました。Defi契約の開発を初めて試みる開発者として、これらのテクニックは契約開発を学びたい初心者にとって非常に役立つでしょう。
以下は、中から学んだいくつかの小技を共有しますが、その中には奇抜な技と呼べるものもあります。
! Web3ビギナーシリーズ:Uniswapコードから学んだ契約開発のヒント
予測可能な契約デプロイ先アドレス
通常、デプロイ契約で得られるのは、一見ランダムなアドレスです。これはnonceに関連しているため、契約アドレスは予測が難しいです。しかし、特定のシナリオでは、取引ペアや関連情報を通じて契約アドレスを導き出す必要があります。これは、取引の権限を判断したり、プールのアドレスを取得したりする場合に非常に役立ちます。
Uniswapは、saltパラメータを追加することで、CREATE2の方法を使用して契約を作成し、作成された契約アドレスを予測可能にします。アドレス生成ロジックは次のとおりです: 新しいアドレス = hash("0xFF", 作成者アドレス, salt, initcode)。
! Web3ビギナーシリーズ:Uniswapコードから学んだ契約開発のヒント
コールバック関数の巧妙な使い方
特定のシナリオでは、契約Aが契約Bのメソッドを呼び出し、Bが呼び出されたメソッド内でAをコールバックするという方法は非常に実用的です。
例えば、UniswapでUniswapV3Poolコントラクトのswapメソッドを呼び出して取引を行う際、swapCallbackが呼び出され、計算された今回の取引に実際に必要なトークンが渡されます。呼び出し元は、コールバック内で取引に必要なトークンをUniswapV3Poolに転送する必要があり、swapメソッドを二つの部分に分けて呼び出し元に呼び出させることはありません。これにより、swapメソッドの安全性が確保され、全体のロジックが完全に実行されることが保証され、セキュリティを確保するための煩雑な変数記録は不要になります。
例外を使用して情報を渡し、catch を試してトランザクションを推定します
UniswapのQuoterコントラクトでは、UniswapV3Poolのswapメソッドをtry catchでラップして実行します。これは、swapメソッドをシミュレートして取引に必要なTokenを推定するためです。推定時には実際にTokenの交換が行われないため、エラーが発生します。Uniswapはトランザクションのコールバック関数内で特別なエラーをスローし、その後そのエラーをキャッチして、エラーメッセージから必要な情報を解析します。
この方法は一見近道のようですが、非常に実用的です。取引の需要を予測するためにスワップ方法を改造する必要はなく、論理がよりシンプルです。
! Web3ビギナーシリーズ:Uniswapコードから学んだ契約開発のヒント
大きな数を使用して精度の問題を解決する
Uniswapコードには、現在の価格と流動性に基づいてトークンを交換する計算ロジックが多数含まれています。除算操作の際の精度の損失を避けるために、計算過程では"<< FixedPoint96.RESOLUTION"操作、すなわち96ビット左シフトがよく使用されます。左シフト後に除算を行うことで、通常の取引でオーバーフローが発生しない限り、精度が保証されます。
シェア方式で収益を計算する
Uniswapでは、流動性提供者(の手数料収益を記録する必要があります。明らかに、各取引で各LPに手数料を記録することはできず、これは大量のガスを消費します。
Uniswapの解決策は、Position構造体にfeeGrowthInside0LastX128とfeeGrowthInside1LastX128を記録し、各ポジションの最後の手数料引き出し時に各流動性が得るべき手数料を示すことです。総手数料と各流動性が分配されるべき手数料を記録するだけで、LPが引き出す際に保有している流動性に基づいて引き出せる手数料を計算します。これは、会社の株を保有しているのに似ており、利益を引き出す際には会社の歴史的な1株あたりの利益と最後の引き出し時の利益を知っていれば十分です。
! [Web3ビギナーシリーズ:Uniswapコードから学んだ契約開発のヒント])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
必要のない情報はチェーンから取得する必要はありません
オンチェーンストレージは相対的に高価であり、すべての情報をオンチェーンにする必要はなく、またはオンチェーンから取得する必要はありません。たとえば、Uniswapのフロントエンドサイトが呼び出す多くのインターフェースは従来のWeb2インターフェースです。
取引プールのリスト、取引プールの情報などは通常のデータベースに保存できますが、一部は定期的にブロックチェーンから同期する必要がありますが、リアルタイムでブロックチェーンやノードサービスのRPCインターフェースを呼び出して関連データを取得する必要はありません。
もちろん、重要な取引はチェーン上で行う必要があります。
契約を合理的に分割し、既存の標準契約を活用する
プロジェクトには、複数の実際に展開されたコントラクトが含まれる可能性があります。実際に展開されるコントラクトが1つだけであっても、コードは継承の方法を通じて複数のコントラクトに分割して維持することができます。
例えば、UniswapのNonfungiblePositionManagerコントラクトは複数のコントラクトを継承しています。ERC721Permitコントラクトの実装を確認すると、それは直接@openzeppelin/contracts/token/ERC721/ERC721.solコントラクトを使用していることがわかります。これにより、NFT方式でポジションを管理することが容易になり、既存の標準コントラクトを利用して開発効率を向上させることができます。
サマリー
実践は最良の学習方法です。簡易版の分散型取引所を自分で実装してみることで、Uniswapのコード実装をより深く理解し、実際のプロジェクトでの知識をもっと学ぶことができます。
! [Web3ビギナーシリーズ:Uniswapコードから学んだ契約開発のヒント])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(