出典:Gryphsis Academy
この研究論文は、UniswapV2プロトコルの仕組み、構成、ソースコードの分析方法について詳しく説明したものです。 UniswapV2の動作原理は主に自動マーケットメイカー(AMM)に関連しており、流動性プールの作成と管理のプロセス、流動性を提供することで手数料を得る方法について説明しています。 プロジェクト構成のセクションでは、主なコントラクト(ファクトリーコントラクト、エクスチェンジコントラクトなど)とその機能を含むUniswapV2のアーキテクチャの概要を説明し、ソース分析のセクションでは、UniswapV2のスマートコントラクトのソースコードを分析し、主要な機能を説明しています。また、ソース分析では、UniswapV2のスマートコントラクトのソースコードを分析し、主要な機能とデータ構造の設計コンセプトを説明します。
1.プロトコルの紹介
UniswapV2は、Etherブロックチェーンをベースとした分散型取引所プロトコルであり、ユーザーは仲介者を信頼することなく暗号通貨を取引することができます。従来の中央集権型の取引所とは異なり、UniswapV2はスマートコントラクトを通じて取引と流動性プールを管理する自動マーケットメーカー(AMM)モデルを使用することで、完全に分散化されています。
UniswapV2の中核は定積式(x * y = k)で、x とy は流動性プール内の2つの異なる資産の量を表し、k は定数です。この式は、各取引後にプール内の資産の割合がリバランスされることを保証し、ユーザーに流動性を提供します。この設計により、取引プロセスが透明かつ公平になり、ユーザーはいつでも流動性を追加または削除でき、取引手数料を通じて収益を得ることができます。
UniswapV2プロトコルは複数のスマートコントラクトで構成されており、特にファクトリーコントラクトとエクスチェンジコントラクトが有名です。ファクトリーコントラクトは流動性のプールの作成と管理を担当し、各エクスチェンジコントラクトは特定の取引ペア(ETH/DAIなど)に対応しています。
さらに、UniswapV2はルーターコントラクトとライブラリ機能を導入し、トランザクションの効率とセキュリティを向上させます。UniswapV2は、その前身であるUniswapV1と比較していくつかの重要な改善をもたらします。1つ目はライトニングスワップ機能で、ユーザーは1回の取引で資産を借り、取引終了前に返却することができます。次に、価格予測機能があり、価格の時間加重平均(TWAP)を蓄積することで、より信頼性の高い価格データを提供します。
さらに、UniswapV2は、イーサを仲介することなく、あらゆるERC-20トークンの直接取引をサポートしています。UniswapV2の成功は、その技術革新だけでなく、オープン性とコミュニティ主導の開発モデルにもあります。誰でも自由にUniswapプロトコルを使用し、拡張することができるため、分散型金融(DeFi)のエコシステムに無限の可能性が広がります。融資プラットフォームやステーブルコイン・プロトコルなど、他の多くのDeFiプロジェクトはUniswapの上に構築され、盛んなエコシステムを作り出している。
全体として、UniswapV2はその革新的なプロトコル設計と分散型運営モデルを通じて暗号通貨の取引方法に革命をもたらし、DeFi空間の重要な礎石となっています。技術が進化し続け、コミュニティが革新を続けるにつれて、UniswapV2のリーチはさらに拡大し、世界中のユーザーにより多くの金融の自由と機会をもたらすでしょう。
2.プロトコルの特徴
2.1 ERC-20ペア
Uniswapv1は移行通貨としてイーサ(ETH)を使用します。つまり、ユーザーがTokenAをTokenBに交換したい場合、まずTokenAをETHに交換し、後でETHをTokenBに交換する必要があります。この措置は流動性の分断を減らす一方で、流動性プロバイダーに大きなコスト圧力をかける。各流動性プロバイダーはETHと交換するためのインターフェイスを持たなければなりませんが、一方で流動性プロバイダーの保有資産の価値はETHの価格変動に伴って変動し、大きな損失につながる可能性があります。
ABCとXYZという2つの資産に相関関係がある場合(たとえば、どちらもUSDのステーブルコイン)、Uniswap上の流動性プロバイダーは通常、ABC/ETHやXYZ/ETHのペアに比べて、ABC / XYZのペアでは永続的な損失が小さくなります。さらに、ETHを必須移行通貨として使用すると、トレーダーのコストが増加します。トレーダーは、ABC/XYZペアをそのまま購入する場合の2倍を支払い、2つのスリッページポイントを被ります。
UniswapV2では、流動性プロバイダーは任意の2つのERC-20トークンのペア契約を作成することが許可されています。任意のERC-20トークン間の取引ペアの急増は、特定の資産取引へのパスを見つけることを複雑にするかもしれませんが、この問題は(オフチェーンまたはオンチェーンルーターまたはアグリゲーターを介した)より高度なルーティングで解決できます。
2.2 価格予測
UniswapV1の価格は、時間tにおいて、Uniswapが提供する限界価格(手数料を除く)が以下のように計算されます。資産aの積立金を資産bの積立金で割る。正確な計算式は以下の通りです。
しかし、UniswapV1は非常に操作しやすいため、オンチェーン価格予測マシンとして使うのは安全ではありません。UniswapV2は価格蓄積メカニズムを導入しており、第三者が一定間隔の平均価格を使用できるため、価格操作のリスクが大幅に高まります。
Uniswap V2は、価格操作の難易度を大幅に高め、操作を実体のないものにする価格累積メカニズムを導入しています。
具体的には、Uniswap v2は、各ブロックの開始時に価格の累積和を記録することで、契約と人間の対話によって価格を累積します。各価格は、ブロックのタイムスタンプに基づき、最後のブロック更新からの経過時間に応じて重み付けされます。つまり、(更新後の)任意の時点で、アキュムレーターの値は、コントラクトの履歴の毎秒のスポット価格の合計になるはずです。
時刻t₁ からt₂までの時間加重平均価格を推定するには、外部呼び出し元は、t₁でアキュムレータ値をチェックし、次にt₂で再びチェックし、最初の値を減算し、次に次のようにします。を経過秒数で割る。(コントラクト自体は、このアキュムレータの履歴値を保存しないことに注意する。呼び出し側は、この値を読み出して保存するために、サイクルの開始時にコントラクトを呼び出さなければならない)。
Prognosticator のユーザーは、サイクルの開始と終了のタイミングを選択できます。より長い期間を選択することで、攻撃者が時間加重平均価格(TWAP)を操作するコストが高くなりますが、その結果、価格が最新でなくなります。平均化の結果、ある間隔におけるA/BとB/Aの平均はもはや反比例の関係ではなくなるため、Uniswap V2は両方の価格を提供します。
2.3価格計算の精度
Solidityは非整数の数値データ型をサポートしていないため、UniswapV2は価格計算の精度を向上させるためにUQ112.112データ形式を使用し、uint112でペアのアセット数を、32ビットで現在のブロックの作成時刻を記録します。この方法で時間を記録すると、100年後、つまり2106年2月7日にUnixのタイムスタンプがオーバーフローしてしまいます。これはUnixのタイムスタンプが1ビットに基づいているためです。これはUnixのタイムスタンプが1ビットに基づくためです。Unixのタイムスタンプは1970年1月1日(Unixのエポックとして知られています)から経過した秒数で時間を表し、uint32が表すことのできる範囲は0から2^{32} - 1秒までで、これは約136年に相当します。
システムが2106年2月7日以降も動作することを保証するために、UniswapV2は、オーバーフロー周期(約136年)ごとに少なくとも1回、予言者が価格をチェックすることを要求するように設計されました。この設計では、タイムスタンプがオーバーフローしても、価格の累積方法はオーバーフローセーフのままであり、取引がオーバーフロー間隔をまたいだとしても、価格の変化を正しく計算することができるからである。このようにして、システムは長期間にわたって正確さと信頼性を保つことが保証される。
2.4 ライトニング取引所
ライトニング取引所は、ブロックチェーンプラットフォーム上のインスタント暗号通貨取引所の一種であり、ユーザーは複数のブロック確認を待つことなく、異なる暗号通貨間の取引を迅速に完了することができます。このような取引は通常、スマートコントラクトによって自動的に実行され、このスマートコントラクトによって取引の両当事者が同時に交換の約束を果たすことが保証されるため、取引リスクが軽減され、効率が向上する。つまり、フラッシュ取引所とは、返済される前に債務を負う取引であり、フラッシュ取引所を通じてゼロコスト裁定取引を実現することができます。
実例を通してフラッシュ・エクスチェンジを説明しましょう。 UniswapV2にA/Bのペアがあると仮定すると、私たちはAを借りてUniswapからBを取得し、Bを使って別の分散型取引所からA0を取得し、その後同量のAをUniswapに返すことができます。このプロセスにより、A0-Aのスプレッドを0コストで裁定取引できる。資本は必要なく、ガス料金を支払うだけです。もしチェーン上の他のデックス間のスプレッドを見つけたら、同じようにしてコストゼロで裁定取引を行うことができる。
2.5プロトコル手数料
UniswapV2では、オン・オフが可能な0.05%のプロトコル手数料を導入しています。オンにした場合、この手数料はファクトリー契約で指定された feeTo アドレスに送信される。初期状態では、feeTo は未設定であるため課金されない。事前に指定されたアドレス、feeToSetterは、feeToを異なる値に設定するために、UniswapV2ファクトリー契約のsetFeeTo関数を呼び出すことができます。feeToSetterは、feeToSetterアドレス自体を変更するために、setFeeToSetterを呼び出すこともできます。
feeToアドレスが設定されると、プロトコルは5ベーシス・ポイントの手数料を課金し始めますが、これは流動性プロバイダーが獲得する30ベーシス・ポイントの˶frac{1}{6}です。つまり、トレーダーは全取引手数料の0.30%を支払い続け、そのうち83.3% (つまり0.25%)が流動性プロバイダーに支払われ、16.6% (つまり0.05%)がfeeToアドレスに支払われる。各取引にこの0.05%の手数料を課すと、追加のガスコストがかかる。これを避けるため、累積手数料は流動性が入金または出金されたときにのみ請求される。コントラクトは累積手数料を計算し、トークンが鋳造されるか破棄される直前に、手数料の受益者に新しい流動性トークンを鋳造します。
累積手数料は、最後に手数料が請求されてからの√kの成長(すなわち√(x-y))を測定することで計算できます。この式は、t₁とt₂ の間の累積手数料を、t₂ におけるフロープールの流動性のパーセンテージとして与えます:
t₁ より前に手数料が有効化された場合、feeToアドレスは、以下のようになるはずです。が有効化された場合、feeToアドレスは t₁ から t₂ までの間に蓄積された手数料をⅹに取り込む必要があります。したがって、Φ-f₁,₂ (Φ=ⅹ)のプールを表す新しい流動性トークンをfeeToアドレスに造幣したい。
つまり、私たちは以下の関係を満たすようにsm_20を選びたいのですが、ここでs₁は時刻 t₁ における流通株式総数です:
f₁,₂を1-
に置き換えたり、sₘ について解いたりするなどのいくつかの算術の後、これを次のように書き換えることができる:
Φを ⅙に設定すると、次の式が得られます
ここで、具体例で説明しよう。最初の入金者が100DAIと1ETHをペアに入金し、10株を受け取ったとします。一定期間後(他の入金者がペアに関与していない時)、彼らは資金を引き出そうとし、その時点でペアには96DAIと1.5ETHが存在します。 これらの値を上記の式に代入すると、以下のようになります:
2.6取引手数料の計算
UniswapV1の取引手数料は、以下の式で計算されます
この式は、定積を実行する前に、まず支払い回数を減らせばよいことを意味しています。UniswapV2のリリースでは、フラッシュスワップの仕組みのため、取引手数料の計算式は、
2.7 sync () およびskim()
sync()は、主にアンバランスで流動性プロバイダーが存在しない状況で、契約に保有されている資産数を実際の現在価値に更新するために使用されます。skim()は、契約に含まれる特定の資産数がuint112の最大値を超える場合に使用され、ユーザーはuint112の最大値を超える資産部分を引き出すことができます。
2.8非標準的で使用頻度の低いトークンの取り扱い
標準的なERC20トークンコントラクトは、トークンを転送した後に転送が成功したかどうかを示すブール値を返す必要がありますが、すべてのトークンがこれを行うわけではありません。一部のトークンは値を返しません。UniswapV1では、戻り値のないトークン移転はデフォルトで失敗とみなされ、トランザクション全体がリセットされる。Uniswap V2では、戻り値のないトークン転送は成功とみなされます。
さらに、UniswapV1はトークン転送がペアの再入力をトリガーしないことを前提としていますが、ERC777フックをサポートする一部のERC20トークンはこの前提を破ります。これらのトークンをサポートするために、UniswapV2はすべてのパブリックステート変数変更関数に再入力防止ロックを追加し、フラッシュスワップにおけるユーザー定義コールバックの再入力をブロックします。
2.9流動性の初期化設定
ユーザーがすでに存在する取引ペアA/Bに流動性を提供する場合、AとBの現在の比率に基づいて、AとBをどれだけ提供するかを計算することが可能です。しかし、ペアが初期化されたとき、参照する比率はありません。UniswapV1のバージョンでは、新しい流動性プロバイダーが既存のUniswapトークン・ペアにトークンを入金する場合、流動性トークンの鋳造数は既存のトークンの数に基づいて計算されます。計算式は以下の通りです:
最初の流動性プロバイダーの場合、計算式はXstarting at 0となります。この場合、トークンの鋳造数は既存のトークン数に基づいて計算されます。この初期流動性提供の問題点は、ペアの価値が初期流動性比率によって決定されるが、この比率が真の値であることを保証するメカニズムがないことである。UniswapV2では、流動性の初期化は次の式を使用して行うことができます
この式は、Smintedを意味し、これは渡される流動性トークンの数です。数量、Xdepositedこれは最初に入金したトークンの数量です。例えば、ETHを入金した場合、Xdeposited は入金したETHの量です。 Ydeposited これは2番目に入金したトークンの量です。
例えば、あなたがDAIを預けた場合、 Ydepositedはあなたが預けたDAIの量です。この式により、流動性プールのシェアがプールの幾何平均を下回ることはありませんが、プール内のトークン数が変化すると、この式の値も変化します。 プール内のトークン数の変化の影響を減衰させるため、UniswapV2は初期の1e- ¹⁵ 流動性を破棄し、最小流動性1e- ¹⁵ 流動性の値とします。の値は最小流動性である1e-¹⁸ の1000倍です。これはどの取引ペアにとっても些細なことですが、このメカニズムから利益を得る攻撃者のコストを大幅に増加させます。
2.10WETH
イーサのネイティブ通貨であるETHを取引するためのインターフェイスは、ERC20トークンを取引するためのインターフェイスとは異なるため、多くのプロトコルはETHを直接サポートせず、代わりに代替のWETH(パッケージ化されたETHトークン)を使用しています。ETHと直接取引することができます。しかし、Uniswap V2はあらゆるERC20トークン間のペアをサポートするように設計されており、ETHを直接サポートすることはシステムを複雑にし、リスクを増大させます。
そのため、UniswapV2ではETHは直接サポートされておらず、ユーザーはペアを使用する前にETHをWETHに変換する必要があります。実際、UniswapV2は内部的にユーザーが提供したETHをWETHに自動的に変換するため、ユーザーのプロセスを簡素化し、ETHをWETHに手動で変換する必要がなくなります。この変換はどの取引ペアにとっても些細なことですが、システムの安全性とシンプルさを効果的に向上させています。
2.11決定論的ペアアドレス
UniswapV1でもUniswapV2でも、すべてのペアは単一のファクトリー契約を使用して作成されます。UniswapV1では、createオペコードが使用され、ペア契約のアドレスは、それが作成される順序によって影響を受けます。UniswapV2では、新しいオペコードcreate2が使用され、このメソッドによって生成されるアドレスは決定論的である。これは、チェーンの状態を問い合わせる必要なく、ペアのアドレスをオフチェーンで前もって計算できることを意味する。
2.12トークンの最大数
予言マシンの機能を効率的に実装するために、Uniswap V2はトークンの数を保持するためにuint112を使用します。トークンの精度が 18 の場合、この値で十分であり、約 5192296858534828 (5.19e¹⁵) トークン、つまり 5.19 兆トークンである。コントラクトに記録された値がこの上限を超えると、取引は失敗しリセットされる。前述したように、誰でもskim()関数を使用してこの状態から回復することができ、流動性プールから過剰な資産を取り除くことで問題を解決します。
3.UniswapV2の原理の説明
Uniswapは定積式を動力とする自動流動性プロトコルで、イーサブロックチェーン上のスケーラブルでないスマートコントラクトシステムに実装されています。信頼できる仲介者の必要性を排除し、分散化、検閲耐性、セキュリティを優先しています。Uniswapの各スマートコントラクトや通貨ペアは、2つのERC-20トークン準備の流動性プールを管理します。誰でもプールトークンと引き換えに各基本トークンの等価価値を預けることで、プールの流動性プロバイダー(LP)になることができます。これらのトークンは、プール全体におけるLPの比例シェアを追跡し、いつでも原資産と交換することができます。
まず最初に、Uniswapの自動マーケットメーカー(AMM)メカニズムについて紹介します。 以下はUniswapV2の自動マーケットメーカー(AMM)モデルの機能イメージで、以下の式に基づいています:
ここで、x はトークンAの数を表し、y はトークンBの数を表し、k はプール内の2つのトークンの数の積が一定であることを示す定数です。トレーダーは、Uniswap での取引時にトークンをプールに追加または削除することで、プール内のトークン数を変更します。定積の公式に従って、積k を一定に保つために、もう一方のトークンのトークン数もそれに応じて変化します。この変化が取引価格を決定します。
たとえば、トレーダーがトークンAとトークンBを交換したい場合、一定量のトークンAをプールに追加する必要があり、これによってプール内のトークンBの量が減少し、価格が変化します。トレーダーの行動はこの曲線に沿って移動し、トークンの数と価格を変化させる。曲線上のどの点でも、定積関係が満たされる。
UniswapV2の仕組みは大まかに3つの部分、流動性プロバイダー、Uniswapプール、Uniswapプールに分けられます。ユニスワップ・プール、そしてトレーダー。流動性プロバイダーの役割は、流動性プロバイダーが2つのトークン(例えばトークンAとトークンB)をユニスワップ・プールに預けることです。
図の例では、流動性プロバイダーはトークンAを10枚、トークンBを1枚預けます。
ユニスワップ・プールにはトークンがストックされ、例えばトークンAが100枚、トークンBが10枚となります;トレーダートレーダーはトークンをプールに投入し、必要な別のトークンと交換することができます。例えば、トレーダーはトークンAを10枚預け、0.3%の手数料を支払うことで、プールからトークンBを1枚入手することができます。
流動性プロバイダー(LP)がどのように流動性を提供するのかを見てみましょう。流動性を提供する方法を見てみましょう。下にあるように、LPはUniswapプールにトークンを預けることで流動性を追加します。
例えば、この図ではLPがトークンAを3枚、トークンBを1枚預けています。流動性供給者がトークンを預けると、流動性のシェアを表すプールトークンを受け取ります。図では、流動性プロバイダーは12.4プールトークンを受け取ります。プールトークンプールは増加し、例えば図ではプールトークンプールは1210トークンAと399トークンBになる。流動性が高まることで、価格のスリッページが減り、取引がより安定します。
Uniswap は定積式 x - y = k を使って価格曲線を決定します。追加された流動性は低スリッページ領域を拡大し、取引の価格安定性を向上させます。流動性プロバイダーはトークンを預けることでプール内の流動性を高め、その見返りとして対応する流動性トークンを受け取ります。これにより、トレーダーはより安定した価格を達成できるだけでなく、流動性プロバイダーは取引手数料という形で収益を得ることができます。
次に、トレーダーがどのようにトークンを交換し、取引行動がUniswapプールにどのような影響を与えるのか、トレーダーの視点から見てみましょう。
下図に示すように、トレーダーはUniswapでトークンを交換したいと考えています。たとえば、図では、トレーダーは3トークンAを交換するつもりです。トレーダーは3 Token Aを入力し、0.3%の手数料を支払います。最終的に、トレーダーは出力として約0.997 Token Bを受け取ります。この取引によってプール内の準備金のバランスが変化し、その結果、新しい価格が発生する。取引前、プールには1200 Token Aと400 Token Bがありました。
定積の式x-y = k に基づいて、トレード後のプールにはトークンAが約1203.009個、トークンBが約399.003個存在します。Uniswapは定積の式x-y = k を使って価格曲線を定義します。トレーダーが操作を交換すると、プール内のトークン数が変化し、価格曲線が新しい価格を決定するために調整されます。
4. ソースコードの分析
<
4.1コア操作のフローチャート分析
このセクションでは、UniswapV2で使用される3つの最も一般的な操作、すなわち流動性の追加、流動性の削除、トークンの交換を紹介します。UniswapV2のソースコードをより深く理解するために、それらが呼び出すコントラクトと関数をフローチャートを通して分析します。
4.1.1流動性の追加
ユーザーが流動性を追加するとき、ユーザーは最初にUniswapV2Router.solコントラクトを呼び出し、トークンAとトークンBの量を提供します。UniswapV2Router.solコントラクトのaddLiquidity関数は、ユーザーのリクエストを受け取り、それを処理します。
addLiquidity関数はさらにUniswapV2Pair.solコントラクトを呼び出し、そこでmint関数が実際の流動性追加操作を実行するために呼び出されます。(ユーザーから提供されたトークン A とトークン B の数に基づいて、mint 関数は鋳造すべき流動性トークン (LP トークン) の数を計算し、これらの LP トークンをユーザーに割り当てます。 流動性追加操作が完了すると、mint 関数は _update 関数を呼び出してリザーブを更新します。
4.1.2 トークンの交換
ユーザーがトークンを交換したい場合、まずUniswapV2Router.solコントラクトを呼び出します。sol契約を呼び出し、入力トークンの数と出力トークンの最小数を提供する。
その後、UniswapV2Router契約のswapExactTokensForTokens関数がユーザーの要求を受け取って処理し、swapExactTokensForTokens関数はさらにUniswapV2Pair.sol契約を呼び出して、入力トークン数と最小出力トークン数を提供する。UniswapV2Pair.solコントラクトでは、実際のトークン交換を実行するためにswap関数が呼び出されます。swap関数は、入力トークンとリザーブ量に応じて出力されるトークン数を計算し、交換を実行します。交換が完了すると、swap関数は_update関数を呼び出してリザーブ量と累積手数料を更新します。
4.1.3 流動性の引き出し
ユーザーはまずUniswapV2Routerを呼び出します。UniswapV2Router.solコントラクトのremoveLiquidity関数は、ユーザーのリクエストを受け取って処理し、removeLiquidity関数はさらにUniswapV2Pair.solコントラクトを呼び出します。sol契約では、実際の流動性引き出しを実行するためにburn関数が呼び出され、burn関数は提供されたLPトークンの数に基づいて返却されるべきトークンAとトークンBの量を計算し、それらのトークンをユーザーに返します。
4.2 コアコントラクト
UniswapV2コアコントラクトは、分散型取引プラットフォームであるUniswapの中核であり、自動マーケットメーカー(AMM)機能の実装を担っています。(AMM)機能の実装を担います。従来のオーダーブックとは異なり、ユニスワップは流動性プールとx-y = kという定積式を通じて取引を可能にします。流動性プロバイダーは2つのトークンをプールに預け入れ、クレデンシャルとして流動性トークンを受け取ります。ユーザーが取引を行うと、コントラクトはプール内のトークン数と定積式に基づいて取引価格を計算します。 uniswapV2では、直接取引用のERC20ペア、価格予測マシンの改善、フラッシュクレジット、契約手数料の調整など、多くの機能強化が導入されています。 コア コントラクトのコアコンポーネントは、以下の3つのファイルで構成されています。paddingleft-2">
UniswapV2Pair.sol : 各ペアの流動性プールを管理し、トークンのスワップ、流動性の追加と削除を処理する
UniswapV2Factory.sol : ペアの作成と管理を担当する
UniswapV2ERM : ペアの作成と管理を担当する
UniswapV2ERM>UniswapV2ERC20.sol : 流動性提供者の株式を表す、流動性トークンの標準実装
4.2.1UniswapV2 Factory.sol
UniswapV2Factoryコントラクトの役割は、取引ペア(流動性プール)の作成と管理を行うことです。このコントラクトにより、ユーザーは新しい取引ペアを作成し、作成されたすべての取引ペアを追跡することができます。UniswapV2Factory.solには5つの関数があり、それぞれを見てみましょう
constructor function: コンストラクタ関数。UniswapV2Factoryコントラクトを初期化するために使用されるコンストラクタ関数です。入力は取引手数料セッターアドレス_feeToSetterで、出力はなしです。
allPairsLength関数:作成されたすべてのペアの数を返します。
createPair関数:新しいペアを作成します。入力はtokenAとtokenBのアドレス、出力は作成されたペアのアドレスです。
setFeeTo関数:手数料受付アドレスを設定します。 入力は新しい取引手数料受付アドレス_feeTo、出力はなし。
setFeeToSetter関数:新しい取引手数料設定者アドレスを設定します。入力は新しい取引手数料設定者アドレス_feeToSetter、出力はなし。
具体的なコードは以下のように解析されます:
createPair関数
createPair関数の機能は、TokenAとTokenBのペアを作成することです。 TokenAとTokenBがフロントエンドに入力された後、TokenAとTokenBが同じ通貨であるかどうかがチェックされ、その後、TokenAとTokenBが同じ通貨であるかどうかがチェックされます。TokenAとTokenBは単純なソートを行い、次にToken0のアドレスをチェックし、Token0のアドレスが0であることはできません;
その後、それはrequire(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS') ;を介して、TokenAとTokenBのアドレスをチェックし、次にToken0のアドレスをチェックします。EXISTS') ;このトークンペアが存在するかどうかをチェックし、存在する場合にのみ処理を進めます。その後、creationCodeを通してUniswapV2Pairコントラクトの生成バイトコードを取得します。
その後、token0とtoken1のハッシュ値をソルトとして使用し、各トークンペアのアドレスが一意であることを確認します。トークン・ペアのアドレスが一意でない場合、流動性を追加するトレーダーが間違ったプールに追加する可能性があるからです。その後、インライン・アセンブリのcreate2命令を使ってコントラクトを作成し、コントラクトのアドレスの一意性と予測可能性を確保します。
その後、新しく作成したトークン・ペアのコントラクトを初期化し、マッピング・テーブルを更新してこのトークン・ペアのコントラクトのアドレスを記録し、新しく作成したペアのコントラクトのアドレスをすべてのペアのコントラクトに追加します。アドレスがすべてのペアのリストに追加され、最後にPairCreatedイベントがトリガーされ、新しいペアが作成されたことが外部に通知されます。
4.2.2 UniswapV2 ERC20.sol
UniswapV2ERC20.solの主な機能は、ERC-20トークンを実装することです。これは、UniswapV2流動性プール専用のERC20標準トークン機能を実装しています。コントラクトには、造幣、焼却、承認、移転などの基本操作が含まれます。さらに、トークンの移転を承認するために署名を使用できるpermit機能もサポートしています。
constructor function: コントラクトを初期化し、permit関数に使用するDOMAIN_SEPARATORを設定する。入力なし、出力なし。
_mint関数:新しいトークンを造幣する、入力は受信アドレス "to "と造幣量 "value"、出力はなし
_burn関数:トークンを破棄する。トークンの破棄、入力は破棄アドレス "to "と破棄量 "value"、出力はなし。
_approve関数:トークン譲渡の承認、所有者アドレスはowner、承認アドレスはspender、承認数量はvalue、出力はなし。
_transfer関数:トークンの転送、入力はfrom、to、value、出力はなし。
_approve関数:公開承認関数、役割は_approve関数を呼び出すこと、入力はapprove関数によって公開された承認関数、出力は操作の成功を示すブール値trueを返すことです。
transfer関数:役割は_transfer関数を呼び出すことであり、入力はアドレスtoを受け入れ、値の数を転送することであり、出力は操作が成功したことを示す真偽値を返すことである
transferFrom関数:公開の関数の転送の承認。入力はfrom、to、valueで、出力は操作の成功を示すブール値trueです
permit関数:トークンの転送を承認するために署名を使用し、署名を検証し、_approve関数を呼び出し、入力は所有者、支出者、値、期限、署名で、出力は操作の成功を示すブール値trueです
transferFrom関数:パブリックの認可転送関数。入力は所有者アドレス、承認アドレス支出者、承認量値、期限、署名パラメータv、r、s、出力はなし。
公式ソースコードの解析結果を以下に示します:
4.2.3 UniswapV2 Pair.sol
取引ペア契約であるUniswapV2Pairは、以下のコア機能を実装しています。各取引ペアの流動性プールを管理・操作する。このコントラクトはトークンの交換、流動性の追加と削除、価格累積の計算を処理します。UniswapV2Pair.solは、各取引の後にペアの準備金と価格情報が更新されるようにし、適切なイベント通知をトリガーします。 UniswapV2Pair.solには11の関数があり、以下の表にリストアップされています:
<
公式のUniswapV2Pair.solのコードとコメントは以下の通りです:
UniswapV2Pair は IUniswapV2Pair, UniswapV2ERC20 から継承している。まず、IUniswapV2Pairのソースコードを見て、IUniswapV2Pairがどのようにインターフェイスを定義しているかを見てみよう。
グローバル変数と修飾子はその後に定義する
上記のMINIMUM_LIQUIDITYは、流動性枯渇を避けるために流動性プロバイダーが常に少なくとも一定量のトークンを保持することを保証するために、流動性プールに保持されなければならない流動性トークンの最小数を設定する定数で、10の3乗の値を持ち、初期流動性を提供するときに燃え尽きます。SELECTORはトークン移転関数のABI(Application Binary Interface)セレクタを格納します。これはスマートコントラクト内の他のコントラクトの移転関数を正確に識別して呼び出すために使用され、トークン移転の実行時に正しい関数シグネチャが使用されるようにします。Uniswap V2ファクトリーはコントラクトのアドレスを格納するために使用され、Token0とToken1はトークンのアドレスを格納するために使用され、3つの状態変数reserve0、reserve1、blockTimestampLastは最新の定積の2つの資産の数と、トランザクション時にブロックが作成された時間を記録する;
そしてprice0CumulativeLast変数とprice1CumulativeLast変数は、ペアの2つの価格の累積値を記録するために使用され、kLastは、流動性プールの価格の安定性を維持するための重要なパラメータとして、UniswapV2ペアの2つのトークンリザーブの積の最新の状態を追跡し、トランザクション手数料を計算するために使用されます。チーム手数料の計算に使用されます。
以下のモディファイアは、再入力攻撃を防ぐためのロック機構を提供し、以下のように分解されます:
上記のコード内の_;は、変更される関数本体を表しています。このコードの一般的なロジックは、ロック修飾子を定義し、ロック解除された変数の状態を変更することで、変更された関数の実行中にコントラクトが再入力されないようにすることで、再入力攻撃や競合状態を防ぐというものです。
以下のgetReserves関数の目的は、UniswapV2ペア契約の2つの現在のトークンリザーブと最終更新タイムスタンプに関する情報を公に照会して返す方法を提供することです。
_safeTransfer関数はスマートコントラクト内でトークン転送を実行し、転送が成功したかどうかをチェックし、失敗した場合は例外をスローします。7249613_image3.png">
次のコンストラクタは、単にファクトリを初期化するために使用されます:
initialise関数のは、ペア契約に関与する2つのトークンのアドレスを設定するために使用され、ペアを展開するファクトリー契約によってのみ呼び出され、ペアの初期化が安全かつ制御されることを保証します。
_update関数の主な目的は、現在のブロックのタイムスタンプと最後の更新のタイムスタンプを比較することで、ペア契約の準備金と価格のアキュムレータが最新の状態を反映するようにすることです。現在のブロックのタイムスタンプと最後の更新のタイムスタンプを比較する。update関数の4つの入力パラメータは、ペア内の2つのトークンの現在の残高を表すbalance0とbalance1、関数が呼び出される前の2つのトークンのリザーブを表す_reserve0と_reserve1です。update関数がどのように実装されているかを箇条書きで説明します:
balanceの値がオーバーフローを引き起こす可能性があるかどうかをチェックする: require文を使って、balance0とbalance1の値がuint112の最大値を超えていないことを確認します。なぜなら、reserve0とreserve1はuint112型を使って格納され、データ型変換のために安全である必要があるからです。
現在のブロック時刻の記録:現在のブロックのタイムスタンプを取得し、blockTimestampLastでmodulo-2^32演算を行い、blockTimestampを取得します。この操作は、イーサネットのブロック・タイムスタンプが32ビットであり、絶対時間ではなくブロック内の時間差にしか関心がないために行われます。
時間差の計算: 現在のブロック時刻と最終更新時刻timeElapsedの差を計算します。timeElapsedが0の場合、同じブロック内で連続した呼び出しであるため、価格累積値は更新されないことを意味します。
価格累積更新: timeElapsedが0より大きく、reserveが0でない場合、固定小数点数学ライブラリUQ112x112を使用して価格比率を計算し、price0CumulativeLastとprice1CumulativeLastを更新します。ここで「決してオーバーフローしない」とは、時間間隔timeElapsedがuint32型であるため、これに価格累積値(uint224)を乗じてもオーバーフローしないことを意味します。また、"+ overflow is desired "は、価格計算が絶対値ではなくデルタを使用するため、価格累積値のオーバーフローが許容され、オーバーフローがあっても平均価格の計算に使用される変化量は正確であることを意味します。
準備金の更新: reserve0とreserve1に新しい残高を割り当てると、流動性プールの準備金が更新されます。
タイムスタンプの更新:次の更新に備えて、現在のブロックのタイムスタンプをblockTimestampLastに割り当てます。
Syncイベントをトリガーする: リザーブが更新されたことを外部のリスナーに通知するために、emitキーワードを介してSyncイベントを発行します。
この設計により、UniswapV2は大量のトランザクションを処理する際に価格の連続性と正確性を維持し、ブロックタイムスタンプや価格累積値からオーバーフローする可能性がある場合でも、変化量から平均トランザクション価格を正確に計算することができます。これは、固定小数点演算と時間差分を巧みに利用することで実現されています。
UniswapV2 では、ユーザーは次のようになります。UniswapV2では、ユーザーは取引ごとに0.3%の手数料を請求されます。この手数料の6分の1は開発チームに割り当てられ、残りの6分の5は報酬として流動性プロバイダーに渡されます。しかし、手数料が取引ごとに1回計算されるのであれば、ユーザーのガス代が増えるのは避けられない。
そこでUniswapV2では、手数料を積み立て、流動性が変化したときだけ手数料を配分するようにしました。mintFee関数はまず、取引手数料がオンになっているかどうかをチェックし、手数料の受け取りアドレスを決定します。取引手数料がオンになっておらず、以前に手数料がキャストされたことがある場合(_kLastが0でない場合)、kLast値はリセットされます。この手数料キャストメカニズムはUniswapV2の一部であり、流動性プロバイダーに追加のインセンティブを提供するために使用されます。取引手数料がオンになっている場合、手数料の値は以下の式に従って計算されます。Sₘ は鋳造されるべき手数料流動性トークンの数を表し、k₁は最後の流動性イベントk後の準備金の積を表し、k₂は現在の準備金の積kを表し、S₁は最後の流動性イベント後の流動性トークンの総供給量を表す。
4.3 周辺契約4.3 周辺コントラクト
UniswapV2の周辺コントラクトは、外部アカウントとコアコントラクトの橋渡しの役割を果たし、インターフェイス定義、ツールライブラリ、ルーター、サンプル実装の4つの部分で構成されています。
4.3.1 Libraries
Libraries フォルダには4つのファイルがあります
SafeMath.sol
UniswapV2Library.sol
UniswapV2LiquidityMathLibrary.sol
UniswapV2OracleLibrary.sol
これら4つのsolファイルをそれぞれ詳しく分析していきます
SafeMath.sol
。SafeMath.solは、特にブロックチェーンやスマートコントラクトの開発において、整数のオーバーフローやアンダーフローのエラーを避けるために重要な、オーバーフローセーフな数学演算を実行するために使用されます。主に3つの関数が含まれています。
add 関数:2つの符号なし整数の加算を安全に実行するために使用されます
sub 関数:2つの符号なし整数の減算を安全に実行するために使用されます
mul 関数:2つの符号なし整数の乗算を安全に実行するために使われます
具体的なコードコメントは以下の通りです。
UniswapV2Library.sol
UniswapV2Library.solは、Uniswap v2のスワップペア(pairs)を操作するためのユーティリティ関数を多数提供しています。
これらの関数は主に、トレードパスの計算、リザーブの取得、価格の計算、連鎖計算の実行に使用されます。このライブラリは、SafeMathと呼ばれるライブラリを使用して、数学演算が整数のオーバーフローやアンダーフローから安全であることを保証します。
sortTokens 関数:2つのトークンアドレスをアドレスでソートして返します。入力は2つのトークンアドレスtokenAとtokenBです。出力はソートされたトークンアドレスtoken0とtoken1です。
pairFor関数:与えられたファクトリーアドレスと2つのトークンアドレスのペアのアドレスを外部呼び出しなしで計算します。入力はファクトリーアドレスfactory、2つのトークンアドレスtokenAとtokenBです; 出力はペアペアのアドレス
getReserves関数:ペアのリザーブを取得しソートします。入力はファクトリーのアドレス、2つのトークンのアドレスtokenAとtokenB; 出力は2つのトークンのリザーブreserveAとreserve Bのリザーブ
quote関数:与えられた資産額とペアのリザーブに基づいて、別の資産の相当額を返す。入力: 資産の量 amountA 、準備金 reserveA と reserveB。
getAmountOut関数: 入力された資産額とペアの準備金をもとに、別の資産の最大出力額を返します。 入力は、入力資産の量、amountIn、および準備金のreserveInとreserveOutです。出力は、出力資産の量、amountOutです。
getAmountIn関数: 出力資産の量とペアの準備金に基づいて、入力される別の資産の必要量を返します。
getAmountsOut関数:任意の数のペアに対して連鎖的にgetAmountsOut計算を実行します。入力は、ファクトリーアドレスfactory、入力資産量amountIn、パスpath、出力は各パスです。
getAmountsIn関数:任意の数のペアに対して連鎖的にgetAmountsIn計算を実行し、入力はfactory address factory、出力はassets amountOut、path pathです。出力は各パスノードの資産量の配列
UniswapV2Librayのソースコードは以下のように詳細にコメントされています:
UniswapV2OracleLibrary.sol
UniswapV2OracleLibrary.solというファイルは、平均価格操作の予測計算と関連して使用するための多数のヘルパーメソッドを提供しています。操作に使用するための多くのヘルパー・メソッドを提供しています。このライブラリには、現在のブロック・タイムスタンプを取得するメソッドと、ガス・コストを節約し、頻繁な同期呼び出しを回避するための累積価格を計算するメソッドが含まれています。
currentBlockTimestamp function: 現在のブロックタイムスタンプを返します。 入力はなし、出力は現在のブロック・タイムスタンプで、型はuint32です。
currentCumulativePrices関数:累積価格を計算して返す。入力はペアのアドレス、出力は累積価格price0Cumulativeとprice1Cumulativeと現在のブロックタイムスタンプblockTimestampです。
UniswapV2OracleLibrary.sol 公式ソースコードの詳細は以下のようにコメントされています。
UniswapV2LiquidityMathLibrary.sol
UniswapV2LiquidityMathLibrary.solの公式ソースコードは以下の通りです。
computeProfitMaximisingTrade関数:利益を最大化するための取引の方向とサイズを計算します。
getReservesAfterArbitrage関数:観察された「実価格」での裁定取引後の流動性プールの準備金を取得します。
computeLiquidityValue関数:流動性プールのすべてのパラメータを与えて、流動性の値を計算します。
getLiquidityValue関数:現在のすべてのパラメータを取得し、流動性量の値を計算します。
getLiquidityValueAfterArbitrageToPrice関数:2つのトークンとその「実際の価格」、および流動性量が与えられた場合、流動性の値を返します。
AfterArbitrageToPrice 関数。
UniswapV2Router02.sol
UniswapV2Router02のソースコードを見てみましょう。コンストラクタとモディファイア、ETHを受け入れる関数、流動性の追加、流動性の削除、トークンのスワッピング、ライブラリ関数の6つの主要セクションに大別できます。
コンストラクタとモディファイア
constructor(address _factory, address _WETH): ファクトリーのコントラクトアドレスとWETHのコントラクトアドレスを初期化します。
modifier ensure(uint deadline): トランザクションが期限までに完了することを保証する。
ETHを受け取る関数
addLiquidity
_addLiquidity: 流動性を追加する内部関数で、既存の準備金に基づいて最適なトークン数を計算します。
addLiquidity:2つのERC-20トークンの流動性を追加します。
addLiquidityETH:ERC-20トークンとETHの流動性を追加します。
removeLiquidity
removeLiquidity: 両方のERC-20トークンの流動性を削除します。
removeLiquidityETH:ERC-20トークンとETHの両方から流動性を削除します。
removeLiquidityWithPermit:両方のERC-20トークンの流動性をpermitで削除します。
removeLiquidityETHWithPermit:許可を得て、ERC-20トークンとETHの流動性を削除します。
removeLiquidityETHSupportingFeeOnTransferTokens:手数料トークンをサポートするERC-20トークンとETHの流動性を削除します。
removeLiquidityETHWithPermitSupportingFeeOnTransferTokens:ERC-20トークンとETHの流動性を許可付きで削除し、フィートークンをサポートします。
Token Swap
_swap: トークンのスワップロジックを実行する内部関数。
swapExactTokensForTokens: 正確な数のトークンを別のトークンと交換します。
swapTokensForExactTokens: トークンを別のトークンの正確な量と交換します。
swapExactETHForTokens:トークンを正確な量のETHと交換します。
swapTokensForExactETH:正確な量のETHとトークンをスワップする。
swapExactTokensForETH:正確な量のETHとトークンをスワップする。swapETHForExactTokens:正確な数のトークンをETHと交換します。
swapExactTokensForTokensSupportingFeeOnTransferTokens:正確な数のトークンを別のトークンと交換します。
swapExactETHForTokensSupportingFeeOnTransferTokens:トークンを正確な数のETHトークンと交換します。
swapExactTokensForETHSsupportingFeeOnTransferTokens:トークンの正確な量を使用してトークンとETHを交換します。
Library Functions
quote: 指定されたトークン数Aに対応するトークン数Bをリザーブに基づいて計算します。
getAmountOut:投入数とリザーブが与えられた場合に得られるアウトプットの量を計算します。
getAmountIn:出力数とリザーブから必要な入力数を計算します。
getAmountsOut:経路と入力数に基づいて出力数を計算します。
getAmountsIn: 経路と出力数に基づいて入力数を計算します。
具体的には次のようになる。以下の関数ごとに見ていくと、UniswapV2Router02.solの契約は、以下のコード部分を通してIUniswapV2Router02から継承されています。UniswapV2Router02コントラクトはIUniswapV2Router02インターフェイスを実装し、以下の主要な機能を提供します:
Adding Liquidity: Liquidity Providerトークンと引き換えに、ユーザーが2つのトークンをLiquidity Poolに追加できるようにします。
モビリティの削除:モビリティプロバイダーがモビリティプロバイダーのトークンを2トークンと交換できるようにします。
取引:ユーザーがトークン間で取引できるようにし、直接取引と複数のペアの経路を介した取引の両方をサポートします。
見積もり計算:与えられた入力または出力量に対する取引の詳細を計算する一連の関数を提供します。
secure qualifierは、現在のブロックタイムが最新のトランザクションタイムを超えているかどうかをチェックするために使われます。ブロック時間が最新のトランザクション時間を超えているかどうかをチェックし、ユーザー指定のトランザクションがタイムアウトによって失敗しないことを保証し、トランザクションのセキュリティと信頼性を向上させるのに役立つ。
コンストラクタはプロジェクトのコントラクトアドレスとウェスのコントラクトアドレスを初期化します。
Receive Function (受信関数)は通常、コントラクトが関数を呼び出すのではなく、直接イーサを受け取るために使われます。この例では、assert文によってWETHコントラクトだけがイーサを送れるようにしています。
_addLiquidity関数の目的は、ユーザーが流動性を追加する際に預ける必要がある、両方のトークンの最適な量を計算することです。tokenAとtokenBは流動性に追加する2つのトークンのアドレス、amountADesiredとamountBDesiredはユーザーが追加したい2つのトークンの初期量、amountAMinとamountBMinはスリッページを防ぐために流動性に追加するためにユーザーが受け入れることができる最小量です。この関数は2つのパラメータを返します。amountAとamountBは、実際に追加されたトークンの数です。
この計算では、ユーザーによって追加された流動性が均衡するように、流動性プールにすでにあるトークンの量を考慮します。流動性プールが新しく、既存のリザーブがない場合、ユーザーは単純に希望する量を追加できます。プールにすでにリザーブがある場合、この関数は現在の比率に基づいて追加する最適な量を計算し、流動性が追加された後もプール内のトークンの比率が変わらないようにします。
addLiquidityのパブリック関数は、トークンを指定された2つのトークンの流動性プールに追加します。2つのトークン(tokenAとtokenB)の流動性プール
addLiquidityETH関数は、ユーザーがUniswapV2の流動性プールに非EtherトークンとEtherトークンを追加できるようにします。この関数には6つのパラメータがあり、tokenは流動性を追加する非Etherトークンのアドレス、mountTokenDesiredはユーザーが追加したい非Etherトークンの数、mountTokenMinはユーザーがプールに追加することを受け入れることができる非Etherトークンの最小数です。mountETHMinは追加できるEtherトークンの最小数で、これもスリッページが低くなりすぎるのを防ぐために使用されます。
この関数は3つのパラメータを返します。amountTokenとamountETHは実際に流動性プールに追加された非イーサトークンとイーサトークンの数で、liquidityは新しく鋳造された流動性トークンの数です。
removeLiquidity 関数により、ユーザーは流動性から流動性を削除することができます。removeLiquidity関数は、ユーザーが以前追加した流動性をプールから削除し、比例した量の両方のトークンを受け取ることを可能にします。burn関数は、実際の流動性破壊とトークン割り当て操作を実行するIUniswapV2Pair流動性プールコントラクトの基礎となる関数です。
removeLiquidityETH 機能は、ユーザーが以前に追加した流動性を削除することで、UniswapV2流動性プールから削除することを可能にします。Etherで追加した流動性を削除し、対応する非EtherコインとEtherコインをそれぞれ取得します。この関数は、まずremoveLiquidityを呼び出し、次にsafeTransferを介して対応するトークンを抽出し、次に燃えている流動性から抽出されたWETHをETHと交換し、変換されたETHを受信者に転送します。
removeLiquidityWithPermit関数は、ユーザーがECDSA署名で承認することを可能にし、ユーザーが事前にapprove関数で承認することなく、コントラクトがユーザーに代わって流動性を削除することを可能にします。
removeLiquidityETHWithPermit関数は、removeLiquidityETHとpermit認可メカニズムを組み合わせて、ユーザーが標準のapproveモードを使用することなく、1回限りの認可契約に署名することで流動性を除去できるようにします。これは、より良いユーザーエクスペリエンスとセキュリティを提供しながら、トランザクションのガスコストを削減します。
removeLiquidityETHSupportingFeeOnTransferTokens関数により、ユーザーは特定のトークンとイーサリアムに関連付けられた以前に追加したトークンを、UniswapV2 Liquidity Poolおよびイーサ流動性から、一部のトークンが転送時に手数料を請求する可能性があることを考慮して削除することができます。
この関数は、まずremoveLiquidityを呼び出して流動性の除去を実行し、次にトークンの転送を処理してユーザーが権利を持つトークン数を受け取れるようにし、最後にWETHをイーサに戻してユーザーに転送します。すべてのプロセスは、ユーザーが指定した取引期限までに完了する必要があります。
removeLiquidityETHWithPermitSupportingFeeOnTransferTokens関数は、removeLiquidityETHWithPermitSupportingFeeOnTransferTokens関数を組み合わせたものです。関数は、removeLiquidityETHSupportingFeeOnTransferTokensとpermit認可メカニズムを組み合わせ、ユーザーが1回限りの認可契約に署名することで流動性を除去できるようにする一方で、移転時に手数料が発生する可能性のあるトークンを扱うことができます。
このアプローチは、承認モードを使用することなく、ユーザーの資産を操作する契約を承認する方法を提供し、ガスコストを削減し、ユーザーエクスペリエンスを向上させます。
_swap関数は次のような内部関数です。内部関数で、一連のトークン交換操作を実行する。指定されたパスとトークンの数に従って、最後のトークンに到達するまで、あるトークンから別のトークンにスワップします。この関数はリクイディティプールとのやりとりの核となる部分で、トークンのスワップとリクイディティプールの更新を実装するために使用されます。
swapExactTokensForTokens関数はUniswapV2ルーターの重要な機能で、ユーザーは少なくとも最小量の出力トークンに対して正確な量の入力をスワップすることができます。この関数はまず、交換経路全体の出力を計算し、最終的な出力がユーザーの最小要件を満たすことを確認した後、ユーザーから流動性プールへトークンを安全に転送し、交換操作を実行します。
swapTokensForExactTokens関数は、ユーザーが受け取りたいトークンの量を指定し、交換するトークンの最大量以上を提供しないようにします。この関数はまず、amountOutを得るために必要な最大投入量を計算し、この投入量がユーザーによって指定されたamountInMaxを超えないようにします。
swapExactETHForTokens関数は、ユーザーが正確な量のETHを少なくとも一定量の別のトークンと交換することを可能にします。この関数は、まずスワップパスが有効であることを確認し、次に必要なWETHの量を計算し、ETHをWETHコントラクトに入金し、次にスワップを実行し、その結果トークンをユーザーが指定したアドレスに送信します。すべてのプロセスは、ユーザーが指定した取引期限までに完了する必要があります。
swapExactETHForTokens関数は、設定された量のETHを他のトークンと交換するために使用されます。
次に、UniswapV2Library.getAmountsOut関数を使用して出力額を計算します。この関数は、ユーザーから送信されたETHの量、msg.この関数は、ユーザーから送信されたETHの量、msg.valueとトークンのパスパスに基づいて値を計算し、ユーザーが取得できる各トークンの量を計算し、その結果をmounts配列に格納します。次のステップはWETHトークンコントラクトのデポジット関数を呼び出すことで、msg.valueのETHをWETHコントラクトにデポジットし、WETHコントラクトがamounts[0]分のWETHを指定されたカウンターパーティコントラクトのアドレスに送金することを確認します。実際のトークン交換処理を行うswap。
swapTokensForExactETHは、一定量のETHのために他のトークンを売却するプロセスです。 この関数は、取得するETHの予想量、amountOut、ユーザーが提供することを望んでいるトークンの最大量、amountInMax、トークン交換のパス、ETHを受け取るアドレス、およびトランザクションの期限を含む5つのパラメータを受け取ります。次に入力量の計算です。UniswapV2Library.getAmountsIn関数を使用して、amountOutのETH量を取得するために計算します。UniswapV2Library.getAmountsIn関数を使用して、ETHのamountOut量を取得するためにユーザーが提供する必要があるトークンの量を計算します。提供されるトークンの計算された量が、ユーザーによって設定された最大量を超えないことを確認します。
次に_swap関数が呼び出されます。swapExactTokensForETH関数は、固定数のトークンを少なくともamountOutMinのETH量と交換するために使用されます。 この関数は、ユーザーが提供する意思のあるトークン量、amountIn、期待するETHの最小量、amountOutMin、トークン交換パス、ETHを受け取るアドレス、およびトランザクションアドレスを含む5つのパラメータを受け取ります。この関数は、ユーザーが提供する意思のあるトークンの量、期待されるETHの最小量、トークンを受け取るパス、ETHが交換されるアドレス、およびトランザクションの期限を含む5つのパラメータを受け取ります。
ユーザーがETHを使って固定数のトークンを交換できるswapETHForExactTokens関数は、上記のswapExactTokensForETH、swapTokensForExactETHと同様のロジックで実装されています。
_swapSuportingFeeOnTransferTokens関数は、トークンのパスをトラバースし、各流動性プールに対してスワップする必要があるトークン数を計算することで、トランザクション手数料のためのトークンスワップのロジックをサポートします。を計算し、交換操作を実行します。
swapExactTokensForTokensSupportingFeeOnTransferTokens取引手数料トークンのケースを処理しながら、一定数のトークンを少なくとも希望する数の別のトークンと正確に交換する。
swapExactETHForTokensSupportingFeeOnTransferTokens は、特定の数のETHと他のトークンとの交換を実装します。
swapExactTokensForETHSupportingFeeOnTransferTokens 関数を使用すると、ユーザーは以下のことが可能になります。取引手数料トークンのケースを処理し、ETHが正確に転送されるようにしながら、一定数のトークンを少なくとも希望する量のETHと正確に交換することができます。
Quote 関数は、以下の機能を実装しています。この関数は、ユーザーが指定したトークン数と流動性プール内の2つのトークンの準備量に基づいて、ユーザーが別のトークンと交換できるトークン数を計算して返します。
getAmountOut関数は、getAmountOut関数と同じです。getAmountOut関数とgetAmountsOut関数はどちらも定積アルゴリズムに基づいています。getAmountOut関数を定義して、与えられた入力金額とリザーブの後にユーザーが得ることができる出力金額を計算します。getAmountsOut関数を定義して、与えられた入力金額と交換パスの後にユーザーが得ることができる一連の出力金額を計算します。
getAmountInとgetAmountsInの計算原理は、定積アルゴリズムに基づいており、購入する資産額が与えられた場合に、売却する資産額を計算することができます。
4.3.2 UniswapV2 Migrator.sol
UniswapV2Migrator.solは、Uniswap v1からUniswap v2へ流動性を移行するために使用されます。この契約にはETHを受け取る機能が含まれており、Uniswap v1とv2のルーターと取引所契約を使用して移行を実行します。これにより、ユーザーはUniswap v1からUniswap v2へ安全に流動性を移行することができます。
constructor function: UniswapV2Migrator契約を初期化するコンストラクタ関数です。入力はv1ファクトリーアドレス_factoryV1とv2ルーターアドレス_router、出力はなし
receive関数:コントラクトが任意のv1スイッチとルーターからETHを受信できるようにするETH受信関数。
migrate関数:入力はトークンアドレスtoken、最小トークン量amountTokenMin、最小ETH量amountETHMin、受信先アドレス、期限、出力はなし
です。UniswapV2Migratorの公式ソースコードを詳細に分析すると以下のようになります。
4.3.3 interfacesフォルダ
4.3.3 interfacesフォルダには、interfacesフォルダと通信するためのファイル群が含まれています。interfacesフォルダには、UniswapV1およびV2スイッチ、ルーター、ファクトリー、WETHおよびERC20コントラクトと相互作用するためのインターフェース定義が含まれています。主な機能には、流動性の管理と移行、トークン取引の処理、流動性の追加と削除、ETHのラッピングとアンラッピングが含まれます。これらのインターフェースは、コントラクト間の標準化された相互作用を保証します。それぞれのドキュメントを詳しく見てみよう。
IUniswapV1Exchange.sol
このファイルは、UniswapV1取引所コントラクトとやり取りするために使用されるインターフェース、IUniswapV1Exchangeを定義しています。取引所コントラクトは、トークンとETHの間のトランザクションと流動性管理を処理する責任があります。
balanceOf関数:取引所コントラクト内のアドレスの残高を返します。
transferFrom関数:あるアドレスから別のアドレスにトークンを転送します。
tokenToEthSwapInput関数:トークンをイーサにスワップするために使用されます。
ethToTokenSwapInput関数:イーサをトークンにスワップします。
IUniswapV1Factory.sol
IUniswapV1Factory.sol UniswapV1のファクトリーコントラクトとやり取りするために使用します。コードは以下のように解析されます:
IERC20.sol
IERC20.sol は、以下のようなインターフェースを定義しています。これはイーサネット・トークン・スタンダード(ERC-20)に従っている