UniswapV2のドキュメントを読んでみよう!
はじめに
初めまして。
CryptoGamesというブロックチェーンゲーム企業でエンジニアをしている cardene(かるでね) です!
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。
代表的なゲームはクリプトスペルズというブロックチェーンゲームです。
今回はUniswapV2について公式ドキュメントを翻訳・補足しながらまとめていきたいと思います。
公式ドキュメントは以下になります。
概要
UniswapV2は、分散型取引所プロトコルのバージョン2であり、その詳細なコンセプトと技術的な情報が含まれています。
以下がWhite Paperになります。
開発者向けリンクとして、UniswapV2プロトコルは以下の2つのリポジトリに分かれています。
uniswap-v2-core
uniswap-v2-periphery
さらに、UniswapV2プロトコルと連携する際に開発者を支援するためのSDKも利用可能です。
uniswap-sdk
uniswap-sdk-core
コンセプト
プロトコル概要
Uniswapの仕組み
引用: https://docs.uniswap.org/contracts/v2/concepts/protocol-overview/how-uniswap-works
Uniswapは、定数乗算式を利用した自動化された流動性プロトコルであり、非アップグレード可能なスマートコントラクトの体系を使用して、Ethereumブロックチェーン上に実装されています。
Uniswapは信頼できる仲介業者の必要性を排除し、分散化、検閲耐性、セキュリティを優先しています。
このプロトコルはGPLライセンスの下でオープンソースソフトウェアとして提供されています。
各Uniswapスマートコントラクト、またはペアは、2つのERC20トークンのリザーブからなる流動性プールを管理しています。
誰でも、プールトークンと引き換えに、同価値の2つのトークンを預け入れることで、そのプールの流動性プロバイダー(LP)になることができます。
預け入れたトークンの投資割合に応じたLPシェアを得て、いつでも預け入れたトークンと交換することができます。
引用: https://docs.uniswap.org/contracts/v2/concepts/protocol-overview/how-uniswap-works
Uniswapのペアは、自動的な市場メーカーとして機能し、ペアのリザーブ残高の「定数積公式」式が保持される限り、片方のトークンをもう片方のトークンと引き換え可能です。
この式は、簡単にx * y = k
と表され、取引がペアのリザーブ残高の積(k
)を変更してはならないことを示しています。
k
は取引の基準から変わらないため、不変量(invariant
)とも呼ばれます。
この式は、リザーブに対する取引が大きい場合、小さい取引に比べて指数関数的に悪いレートで実行されるという望ましい性質を持っています。
実際には、Uniswapは取引に0.30%
の手数料を適用し、これはリザーブに追加されます。
その結果、各取引は実際にはk
を増加させます。
これは流動性プロバイダー(LPs)への支払いとして機能し、彼らはプールトークンを燃やして総リザーブの一部を引き出す際に実現されます。
将来的には、この手数料は0.25%
に削減され、残りの0.05%
はプロトコル全体の手数料として差し引かれるかもしれません。
つまり、Uniswapのペアは自動的な市場メーカーとして動作し、リザーブ残高の積を一定に保つという基本原則に基づいています。
取引に手数料が適用され、この手数料はLPsへの支払いとなります。
また、どこかのタイミングで手数料が変更される可能性もあります。
引用: https://docs.uniswap.org/contracts/v2/concepts/protocol-overview/how-uniswap-works
Uniswapは、トークン同士の交換が流動性プール内で行われるため、トークンペアの価格は取引を通じて変動します。
もしUniswapの価格が外部の市場価格と異なる場合、その価格差を利用して利益を得る「裁定取引」の機会が生まれます。
これにより、Uniswapの価格は常に市場の均衡価格に近づくように調整される仕組みです。
具体的には、Uniswapのトークン交換の仕組みやスワップのライフサイクルについて詳しく理解したい場合は、「Swaps」を読んでみることをおすすめします。
また、流動性プールの仕組みについて知りたい場合は、「Pools」を確認することで理解を深めることができます。
Uniswapプロトコルは、Ethereum上で実行されるスマートコントラクトコードによって動作しています。
これらのスマートコントラクトは、取引や流動性プールの管理などを自動化する役割を果たしています。スマートコントラクトが設計された仕組みを理解したい場合は、「Smart Contracts」を読むことで詳細を把握できます。
結局のところ、Uniswapは取引を通じて価格が調整され、市場の均衡価格に向かう仕組みを持っています。
これによって、流動性プール内のトークンの価格が適切に維持され、裁定取引の機会が最小限に抑えられるのです。
エコシステムの参加者
引用: https://docs.uniswap.org/contracts/v2/concepts/protocol-overview/ecosystem-participants
Uniswapのエコシステムは、主に3つのタイプのユーザーから成り立っています。
- 流動性プロバイダー
- トレーダー
- 開発者
流動性プロバイダーは、ERC20トークンを共通の流動性プールに提供することを推奨されます。
トレーダーは、これらのトークンを固定の0.30%
の手数料でお互いに交換できます(この手数料は流動性プロバイダーに支払われます)。
開発者は、Uniswapのスマートコントラクトと直接統合して、トークン、取引インターフェース、小売体験などとの新しい興奮するような相互作用を実現できます。
これらのユーザークラス間の相互作用は、共通の言語を定義し、トークンをプールし、取引し、使用する方法を通じてデジタル経済を推進するポジティブフィードバックループを作成します。
流動性プロバイダー
流動性プロバイダー(LP)は、単一の均質なグループではありません。
さまざまなタイプのLPが存在し、それぞれ異なる目標やアプローチを持っています。
パッシブLP
トークンを所有している人々のうち、収益を積極的に得ることを希望する人々です。
彼らはトレード手数料を積み立てて、資産を収益化することを目指しています。
プロフェッショナルLP
マーケットメーキングを専門的な戦略として採用している人々です。
通常、彼らはさまざまなDeFiプロジェクトの間で流動性ポジションを効果的に管理するためのカスタムツールや方法を開発します。
トークンプロジェクト
一部のトークンプロジェクトは、自身のトークンの流動性を提供するためにLPとなることを選択することがあります。
これにより、トークンの取引が容易になり、Uniswapを通じて他のDeFiプロジェクトとの連携が促進されます。
DeFiのパイオニア
一部のDeFiの先駆者たちは、インセンティブ付きの流動性提供や流動性を担保とする方法など、複雑な流動性提供戦略を探求しています。
Uniswapは、このような新しいアイデアや実験を試すための理想的なプロトコルとなっています。
これらの異なるLPの存在によって、流動性が確保され、市場がより効率的に機能することが可能となっています。
異なるタイプのLPが共同してUniswapのエコシステムを形成し、トークンの取引と利用を可能にするのです。
トレーダー
Uniswapのプロトコルエコシステム内には、さまざまなタイプのトレーダーが存在します。
それぞれのトレーダーは、異なる方法でUniswapを活用しています。
スペキュレーター
スペキュレーターは、Uniswapプロトコルから引き出した流動性を活用して、トークンの交換を行います。
彼らはコミュニティが提供するさまざまなツールや製品を使用して、トークン間の価格変動を利用し、利益を追求します。
アービトラージボット
アービトラージボットは、異なるプラットフォーム間の価格を比較して利益を追求します。
これにより、異なる場所での価格の差異を利用して利益を得ることができます。
この取引は広範なEthereum市場全体で価格の均一化を促進し、公正な状態を保つのに役立ちます。
DAPPユーザー
DAPPユーザーは、Uniswapを使用してトークンを購入し、他のEthereumアプリケーションで使用するために活用します。
これにより、ユーザーは便利にさまざまなアプリケーションでトークンを活用することができます。
スマートコントラクト
スマートコントラクトは、Uniswapのプロトコル上で取引を実行するために活用されます。
これには、DEXアグリゲーターやカスタムのSolidityスクリプトなどが含まれます。
スマートコントラクトを介して自動的にトークンの交換が行われ、市場の流動性が向上します。
どのトレーダータイプも、プロトコル上で同じフラット手数料が適用されるため、価格の精度が向上し、流動性の提供に対するインセンティブが生まれます。
これにより、市場の均衡が保たれ、効率的なトークンの取引が実現されます。
開発者/プロジェクト
Uniswapは、広範なEthereumエコシステム内でさまざまな方法で活用されており、その数は数え切れないほどです。
以下はその一部の例です。
オープンソースかつアクセス可能な性質
Uniswapのオープンソースかつアクセス可能な性質により、無数のUXやフロントエンドが構築され、Uniswapの機能へのアクセスが提供されています。
多くの主要なDeFiダッシュボードプロジェクトにおいても、Uniswapの機能が組み込まれています。
また、コミュニティによって開発されたUniswap固有のツールも多数存在します。
ウォレット
多くのウォレットは、トークンのスワップや流動性の提供機能を自社製品の中核として統合しています。
ユーザーはウォレットを通じて簡単にUniswapを使用し、トークンを交換したり流動性を提供したりすることができます。
DEX(分散型取引所)アグリゲーター
DEXアグリゲーターは、多くの流動性プロトコルから流動性を引き出し、トレーダーに最良の価格を提供します。
トレーダーの取引を分割して最良の価格を提供するため、Uniswapはこれらのプロジェクトにおいて最大の分散型流動性ソースとなっています。
スマートコントラクト開発者
スマートコントラクト開発者は、利用可能な関数群を活用して新しいDeFiツールやさまざまな実験的なアイデアを生み出しています。
UnisocksやZoraなどのプロジェクトを例に挙げると、さまざまな実験が行われています。
Uniswapチームとコミュニティ
Uniswapチームと広範なコミュニティは、プロトコルとエコシステムの開発を推進しています。
彼らの協力によってUniswapは成長し、進化しています。
スマートコントラクト
UniswapV2は、バイナリ型のスマートコントラクトシステムです。
コアコントラクトは、Uniswapと対話するすべての関係者に基本的な安全性を提供します。
パリフェリーコントラクトは1つ以上のコアコントラクトと対話しますが、それ自体はコアの一部ではありません。
コア
コアは、シングルトンファクトリーと多数のペアから成ります。
ファクトリーはこれらのペアを作成および索引付けする責任を持っています。
これらのコントラクトは非常に最小限のもので、無骨なデザインです。
これは、サイズの小さいコントラクトは理論的に理解しやすく、バグも少なく、より機能的に優れたものとなるからです。
このデザインの最大の利点の1つは、システムの多くの望ましい特性がコード内で直接アサートされることで、エラーの余地がほとんどないことです。
ただし、一方でコアコントラクトはユーザーフレンドリーではありません。
実際には、これらのコントラクトと直接対話することは、ほとんどのユースケースでは推奨されません。
代わりに、パリフェリーコントラクトを使用するべきです。
-
ファクトリー
- ファクトリーはペアを動かすための汎用バイトコードを保持します。
- その主な役割は、ユニークなトークンペアごとに1つだけスマートコントラクトを作成することです。
- また、プロトコル料金を課すためのロジックも含まれています。
-
ペア
- 自動的な市場メーカーとしての役割と、プールトークンの残高を追跡する役割を持っています。
- また、分散型価格オラクルを構築するために使用できるデータも公開されています。
パリフェリー
パリフェリーは、コアと特定のドメイン間の対話をサポートするためのスマートコントラクトの集合体です。
Uniswapの権限のない性質から、以下に説明するコントラクトは特別な権限を持たず、実際には可能なパリフェリーの一部です。
ただし、これらはUniswapV2と安全かつ効率的に対話する方法の例です。
- ライブラリ
- ライブラリは、データや価格情報を取得するための便利な関数を提供します。
- ルーター
- ルーターは、ライブラリを使用して、トレーディングや流動性管理機能を提供するフロントエンドの基本要件を完全にサポートします。
- 特に、複数のペアでのトレード(例:xからyへからzへ)、ETHをファーストクラスのアセットとして扱う機能、流動性を削除するためのメタトランザクションなどをネイティブでサポートしています。
デザインの決定事項
以下のセクションでは、UniswapV2で行われた注目すべきデザインの決定事項について説明します。
これらは、V2がどのように機能するかの深い技術的理解を得ること、またはスマートコントラクトの統合を行う際に関心がある場合を除いてはスキップしても構いません。
- トークンの送信
- 通常、トークンを使用して何らかの機能を実行するスマートコントラクトは、トークンコントラクト上で承認を行った後、そのトークンコントラクト上で
transferFrom
を呼び出すことを必要とします。 - しかし、V2ペアはトークンを受け入れる方法が異なります。
- ペアは対話の度にトークン残高をチェックし、次の対話の始まりで現在の残高と格納された値との差分を計算し、現在の対話者が送信したトークンの量を決定します。
- この方法の詳細はホワイトペーパーに記載されています。
- 通常、トークンを使用して何らかの機能を実行するスマートコントラクトは、トークンコントラクト上で承認を行った後、そのトークンコントラクト上で
- WETH
- UniswapV1とは異なり、V2ペアはETHを直接サポートしないため、ETH⇄ERC20のペアはWETHを使用してエミュレートする必要があります。
- この選択の背後にある動機は、コア内のETH固有のコードを削除し、コードベースをスリムにすることです。
- ただし、エンドユーザーはパリフェリー内でETHをラップ/アンラップするだけで、この実装の詳細を完全に無視できます。
- 最小流動性
- 最初の流動性提供時に最小ティックサイズ(価格変動の最小単位)を調整するために、最初のMINIMUM_LIQUIDITYプールトークンを燃やす仕組みが導入されています。
- 最小ティックサイズを調整し、取引の正確性と流動性提供の品質を向上させることができます。
- ほとんどのペアにとって、これは取るに足らない値を表します。
- 燃焼は最初の流動性提供の際に自動的に行われ、その後
totalSupply
は永遠に制限されます。
用語
自動市場メーカー
自動市場メーカーは、Ethereum上のスマートコントラクトであり、オンチェーンの流動性リザーブを保持します。
ユーザーは、このリザーブに対して自動市場メーキングの公式で設定された価格で取引を行うことができます。
定数積公式
Uniswapで使用される自動市場メーキングアルゴリズム。
ERC20
ERC20トークンは、Ethereum上の代替可能なトークンです。
Uniswapはすべての標準的なERC20実装をサポートしています。
Factory
ERC20/ERC20トレーディングペアごとに独自のスマートコントラクトを展開するスマートコントラクトです。
Pair
UniswapV2 Factoryから展開されるスマートコントラクトで、2つのERC20トークン間での取引を可能にします。
Pool
ペア内の流動性は、すべての流動性プロバイダー間でプールされます。
Liquidity provider / LP
流動性プロバイダーは、2つのERC20トークンの同等価値を流動性プールに預け入れる人物です。
流動性プロバイダーは価格リスクを負い、手数料で報酬を受け取ります。
Mid price
特定の瞬間にユーザーがトークンを購入または売却できる価格の中間点です。
Uniswapでは、これは2つのERC20トークンリザーブの比率です。
Price impact
取引の実行価格と中間価格の差です。
Slippage
トランザクションが提出されてから実行されるまでの間に、トレーディングペアの価格が移動する量です。
Core
Uniswapの存在に不可欠なスマートコントラクトです。
新しいバージョンのコアへのアップグレードには、流動性の移行が必要です。
Periphery
Uniswapの存在には必要ありませんが、有用な外部スマートコントラクトです。
新しいペリフェリーコントラクトは、流動性を移行せずに常に展開できます。
Flash swap
購入するトークンを支払う前に使用する取引のことです。
x * y = k
定数乗算公式です。
Invariant
定数乗算公式におけるk
の値です。
コアコンセプト
スワップ
引用: https://docs.uniswap.org/contracts/v2/concepts/core-concepts/swaps
Uniswapのトークンスワップは、あるERC20トークンを別のトークンと交換する簡単な方法です。
ユーザーにとって、スワップは直感的です。
ユーザーは入力トークンと出力トークンを選択し、入力量を指定します。
プロトコルは出力トークンの受け取り量を計算し、ユーザーはクリックひとつでスワップを実行し、即座に出力トークンをウォレットに受け取ります。
このガイドでは、Uniswapのプロトコルレベルでのスワップ時の動作について詳しく見ていき、Uniswapの動作原理を深く理解します。
Uniswapのスワップは、従来のプラットフォームでの取引とは異なります。
Uniswapは、流動性や価格を表すためにオーダーブックを使用しません。
代わりに、Uniswapは自動市場メーカーメカニズムを使用して、レートやスリッページに対する即時のフィードバックを提供します。
概要部分で説明しているように、Uniswapの各ペアは実際には流動性プールによって支えられています。
流動性プールは、2つのユニークなトークンの残高を保持し、それらの預け入れと引き出しに関するルールを適用するスマートコントラクトです。
このルールは定数積公式です。
片方のトークンが引き出される(購入される)場合、もう片方のトークンが同じ比率で預けられる(売却される)必要があり、これにより定数が保たれます。
スワップの構造
基本的なレベルでは、UniswapV2のすべてのスワップは、swap
という関数内で行われます。
この関数は以下のように定義されています。
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data);
トークンの受け取り
関数のシグネチャから明らかなように、Uniswapはスワップ呼び出し元に、amount{0,1}Out
パラメータを介して受け取りたい出力トークンの量を指定するよう求めています。
これはtoken{0,1}
の希望の量に対応しています。
トークンの送信
少しわかりにくいのは、Uniswapがスワップの対価としてどのようにトークンを受け取るかです。
通常、トークンが機能を実行するために必要なスマートコントラクトは、トークンコントラクトで最初に承認を行い、次にトークンコントラクトでtransferFrom
関数を呼び出すよう要求します。
これはV2ペアがトークンを受け入れる方法ではありません。
代わりに、ペアはすべての処理の最後にトークンの残高をチェックします。
次の処理の開始時に、現在の残高が格納された値との差を計算して、処理を実行しているユーザーが送信したトークンの量を決定します。
詳しくは、ホワイトペーパーを参照してください。
ポイントは、スワップが呼び出される前にトークンをペアに送信する必要があるということです(このルールの唯一の例外はFlash Swaps
です)。
したがって、安全にスワップ関数を使用するには、別のスマートコントラクトから呼び出す必要があります。
代替方法(トークンをペアに送信し、それからスワップを呼び出す)は、非アトミックに実行されるため、送信されたトークンは裁定取引の対象になる可能性があるため、安全ではありません。
プール
引用: https://docs.uniswap.org/contracts/v2/concepts/core-concepts/pools
はじめに
Uniswapの各流動性プールは、2つのERC20トークンのペアの取引場です。
プールコントラクトが作成されると、各トークンの残高は0
になります。
プールが取引を開始するためには、最初に各トークンの初期預け入れでプールに資金を供給する必要があります。
最初の流動性プロバイダーは、プールの初期価格を設定する人です。
彼らは、両方のトークンに等しい価値をプールに預け入れるインセンティブがあります。
なぜかというと、最初の流動性プロバイダーが現在の市場レートと異なる比率でトークンを預け入れる場合、すぐに有利な裁定取引の機会が生まれ、外部の者によって取引される可能性が高いからです。
他の流動性プロバイダーが既存のプールに資金を追加する場合、現在の価格に比例してペアトークンを預け入れる必要があります。
そうしないと、追加した流動性も裁定取引の対象になる可能性があります。
現在の価格が正しくないと考える場合、彼らはそれを望むレベルまで裁定取引を行い、その価格で流動性を追加することができます。
プールトークン
引用: https://docs.uniswap.org/contracts/v2/concepts/core-concepts/pools
流動性がプールに預けられると、流動性プロバイダーのアドレスに流動性トークンと呼ばれるユニークなトークンが発行され送られます。
これらのトークンは、特定の流動性プロバイダーがプールへの貢献を表します。
プールに提供された流動性の割合は、プロバイダーが受け取る流動性トークンの数を決定します。
新しいプールを作成している場合、受け取る流動性トークンの数は、提供された各トークンの量を示すx
とy
がsqrt(x * y)
に等しい値となります。
取引が発生するたびに、トランザクションの送信者に0.3%
の手数料が請求されます。
この手数料は、取引が完了した際にプール内のすべての流動性プロバイダーに比例して分配されます。
流動性プロバイダーが元の流動性と蓄積された手数料を取り戻すには、流動性トークンを「燃やす」必要があります。
これにより、流動性プールの一部と手数料割り当ての比例分が交換されます。
流動性トークン自体も取引可能な資産であるため、流動性プロバイダーは、自分の判断で流動性トークンを売却、送信、または他の方法で使用することができます。
なぜプールが必要か?
Uniswapは、資産の価格を導出したりトークンの買い手と売り手をマッチングしたりするために、オーダーブックを使用しません。
代わりに、Uniswapは「流動性プール」と呼ばれる仕組みを使用します。
通常、流動性は中央で運営されるオーダーブックに個々の参加者が配置した離散的な注文で表現されます。
流動性を提供したり市場を作ったりする参加者は、自分の注文を積極的に管理し、市場内の他者の活動に応じて注文を継続的に更新する必要があります。
オーダーブックは金融に基本的な要素であり、特定のユースケースには適していますが、いくつかの重要な制約があります。
特に分散型やブロックチェーンネイティブな環境での適用では、これらの制約が顕著になります。
オーダーブックは注文ブックをホストし、注文をマッチングするための中間インフラストラクチャを必要とします。
これにより制御ポイントが生まれ複雑さが増します。
また、市場メーカーによる積極的な参加と管理が必要であり、通常は高度なトレーダーに限られます。
オーダーブックは、少数のアセットが取引されている状況で発明されたため、自分のトークンを作成し、それらのトークンの流動性が通常低いというエコシステムには適していないことが多いです。
要するに、Ethereumのようなプラットフォームが提供するインフラストラクチャのトレードオフを考えると、オーダーブックはブロックチェーン上の流動性プロトコルを実装するためのネイティブなアーキテクチャではありません。
Uniswapは、Ethereumの強みに注目し、トークンのスワップを根本から再考することで新たな方法を提供します。
ブロックチェーンネイティブな流動性プロトコルは、信頼できるコード実行環境、自律的かつ永続的に稼働する仮想マシン、そして指数的に成長する仮想アセットのエコシステムを生み出すオープンで許可されているアクセスモデルを活用すべきです。
重要なのは、プールは単なるスマートコントラクトであり、ユーザーがそれを呼び出すことで操作されます。
トークンのスワップは、プールコントラクトのインスタンスでswap
を呼び出すことで行われます。
一方、流動性を提供する際は、deposit
を呼び出すことになります。
Uniswapプロトコルに対してエンドユーザーがインターフェースを介して対話するように、開発者も中間業者に依存せず、許可を必要とせずに直接スマートコントラクトと対話し、Uniswapの機能を自分のアプリケーションに統合することができます。
フラッシュスワップ
Uniswapのフラッシュスワップは、Uniswap上の任意のERC20トークンプール内の全供給量を引き出し、前払いなしで任意のロジックを実行することができる仕組みです。
ただし、トランザクションの最後までに次のいずれかを行う必要があります。
- 引き出したERC20トークンを対応するペアトークンで支払う。
- 引き出したERC20トークンを少額の手数料と一緒に返却する。
フラッシュスワップは非常に便利で、Uniswapを使用した多段階の取引における前払い資本要件や不必要な手順の制約を排除します。
例
フリーキャピタル・アービトラージ
フラッシュスワップの特に興味深い用途の1つは、フリーキャピタル・アービトラージです。
Uniswapの設計の一部として、アービトラージャーがUniswap価格を「公正な」市場価格に調整するためのインセンティブを作成することは広く知られています。
ただし、ゲーム理論的には適切ですが、この戦略にはアービトラージ機会を活用する十分な資本を持っている人だけがアクセスできます。
フラッシュスワップはこの障壁を完全に取り除き、実質的にアービトラージを民主化します。
UniswapからETHを引き出す
まず、フリーキャピタルを得るためにUniswapから1
ETHを引き出します。
これはアービトラージを実行するための資本として使用します。
このシナリオでは、以下の仮定がされているとします。
-
1
ETHは事前に計算された利益最大化の取引。 - 計算後にUniswapまたはOasisの価格が変わっていない
- 実行時にオンチェーンで利益最大化の取引を計算する必要があるかもしれません。
- これは実行される戦略によってはやや複雑になる場合がありますが、一般的な戦略の1つは、固定の外部価格に対してできるだけ効率的に取引することです。 (この価格は、Oasisの1つ以上の注文の平均実行価格などであるかもしれません。)
- Uniswapの市場価格がこの外部価格より十分に高いか低い場合、こちらの例には最大利益を得るためのUniswapでの取引額を計算するコードが含まれています。
外部取引所で取引
Uniswapから一時的なキャピタルとして1
ETHを得たら、これをOasisで220
DAIにトレードできます。
DAIを受け取った後、Uniswapに返済する必要があります。
1
ETHをカバーするために必要な金額は200
DAIであることを前述しました。
そのため、200
DAIをUniswapペアに送金した後、20
DAIの利益が残ります。
インスタントレバレッジ
フラッシュスワップは、レンディングプロトコルとUniswapを使用してレバレッジを高める効率を向上させるために使用できます。
単純な形式のMakerを考えてみましょう。
ETHを担保として受け入れ、その価値がDAIの価値の150%を下回らないようにしながら、DAIを担保として発行するシステムです。
このシステムを使用して3
ETHの元本を預け、最大量のDAIを発行します。
1 ETH / 200 DAI
の価格で、400
DAIを受け取ります。
原則として、このポジションをDAIを売却してETHをもっと購入することでレバレッジアップすることができます。
その後、このETHを預け入れ、最大量のDAIを発行します(今回は少なくなります)、そしてこれを繰り返し、所望のレバレッジレベルに達するまで続けることができます。
UniswapをDAIからETHへの流動性ソースとして使用するのは非常に簡単です。
ただし、プロトコルをループさせることはあまり洗練されておらず、ガスが多く必要です。
幸い、フラッシュスワップを使用すると、最初に全額のETHを引き出すことができます。
3
ETHの元本に対して2倍のレバレッジを得たい場合、単純に3
ETHをフラッシュスワップでリクエストし、6
ETHをMakerに預け入れるだけで済みます。
これにより、800
DAIを発行することができます。
フラッシュスワップをカバーするために必要な分だけ発行し、残りは価格変動に対する安全マージンとして機能します。
オラクル
はじめに
価格オラクル(Price Oracle)は、特定の資産に関する価格情報を表示するために使用されるツールです。
例えば、スマートフォンで株価を確認する際、そのスマートフォンは価格オラクルとして機能しています。
同様に、スマートフォンのアプリケーションは、価格情報を取得するために複数のデバイスを使用し、それらの情報を集約して表示します。
これらも価格オラクルです。
DeFiプロトコルと統合するスマートコントラクトを構築する際、開発者は価格オラクルの問題に遭遇することがあります。
特定の資産の価格をオンチェーンでどのように取得するのが最適な方法でしょうか?
Ethereum上での多くのオラクル設計は、分散度やセキュリティの程度が異なる形でアドホックな基盤で実装されてきました。
このため、エコシステムではオラクルの実装が主要な攻撃ベクトルとなる高プロファイルのハッキング事件が多数発生しています。
いくつかの脆弱性についてここで議論されています。
1つの解決策がすべてに適しているわけではありませんが、UniswapV2は開発者が高度に分散化され、操作に対抗できるオンチェーンの価格オラクルを構築できるようにするものであり、堅牢なプロトコルを構築するために必要な要件の多くを満たす可能性があります。
UniswapV2の解決策
UniswapV2は、操作に対抗しやすい公開価格フィードをサポートするためのいくつかの改善策を提供しています。
まず、各ペアは各ブロックの開始時に市場価格を測定(保存はしない)し、どの取引も行われる前に設定します。
この価格は操作が難しくなるように設計されており、前のブロックでの最後のトランザクション(mint
、swap
、burn
など)によって設定されます。
この測定価格をグローバルな市場価格とずらすために、攻撃者は前のブロックの終わりに悪いトレードを行わなければならず、通常は次のブロックでその逆取引をアービトラージする保証はありません。
攻撃者は2つのブロックを連続して「自己中心的に」マイニングしなければならない場合があります。
この種の攻撃はいくつかの課題を抱えており、これまでに観察されたことはありません。
残念ながら、これだけでは十分ではありません。
このメカニズムから得られた価格に基づいて価値が確定する場合、攻撃の利益は損失を上回る可能性があります。
そのため、UniswapV2は、このブロックの終わりの価格をコアコントラクト内の単一の累積価格変数に加算します。
この変数は、コントラクトの全履歴の中での各秒におけるUniswap価格の合計を重み付けて表します。
引用: https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles
この変数は、外部のスマートコントラクトが任意の時間間隔で正確な時間加重平均価格(TWAP
)を追跡するために使用できます。
TWAP
は、所望の間隔の開始時と終了時にERC20トークンのペアの累積価格を読み取ることで構築されます。
この累積価格の差を間隔の長さで割ることで、その期間のTWAP
が作成されます。
引用: https://docs.uniswap.org/contracts/v2/concepts/core-concepts/oracles
TWAP
(時間加重平均価格)は、必要に応じて直接使用するか、移動平均(EMAsおよびSMAs)の基盤として使用できます。
いくつかの注意点があります。
- 10分のTWAPの場合、10分ごとにサンプリングします。
- 1週間のTWAPの場合、1週間ごとにサンプリングします。
- 単純なTWAPの場合、Uniswapの流動性と平均する期間の長さに応じて操作のコストが増加します(おおよそ線形)。
- 攻撃のコストは比較的簡単に推定できます。
- 1時間のTWAPで価格を
5%
動かすことは、1時間の各ブロックで価格を5%
動かす際のアービトレージと手数料の損失とほぼ同じです。
- 1時間のTWAPで価格を
UniswapV2をオラクルとして使用する際、特に操作抵抗性に関するいくつかのニュアンスに注意することが良いでしょう。
白書にはそれに関する詳細な説明があります。
追加のオラクルに関する開発者向けガイドとドキュメントも近日中に公開される予定です。
操作抵抗性
特定の時間期間に価格を操作するコストは、全期間にわたって毎ブロックでアービトレージと手数料を失う量としておおよそ推定できます。
流動性プールが大きく、時間が長いほど、この攻撃は実用的ではなく、通常、操作のコストが関与する価値を上回ります。
ネットワークの混雑など、他の要因によって攻撃のコストが減少することもあります。
アドバンストピック
手数料
流動性提供者の手数料
トークンのスワップには0.3%
の手数料がかかります。
この手数料は、流動性提供者にその流動性準備への寄与に比例して分配されます。
スワップ手数料は直ちに流動性準備に入金されます。
これにより、流動性トークンの価値が増加し、プールのシェアに比例したすべての流動性提供者への支払いとして機能します。
手数料は流動性トークンを焼却して基礎の準備の比例シェアを削除することで収集されます。
手数料が流動性プールに追加されるため、不変量は各取引の終了時に増加します。
単一のトランザクション内で、不変量は前のトランザクションの終了時におけるtoken0_pool / token1_pool
を表します。
多くのコミュニティ開発のツールを使用してリターンを計算することができます。
また、LP(流動性プロバイダー)のリターンについての考え方については、ドキュメントを読むこともできます。
プロトコル手数料
現時点ではプロトコル手数料はありません。
ただし、将来的に0.05%
の手数料が導入される可能性があります。
将来のプロトコル手数料に関する詳細情報は、こちらで確認できます。
プロトコルチャージの計算
将来的には、取引ごとに0.05%
のプロトコル全体の手数料が発生する可能性があります。
これは0.30%
の手数料の1/6(16.6̅%)
に相当します。
feeTo
がaddress(0)
(0x0000000000000000000000000000000000000000
)でない場合、feeTo
はそのチャージの受取人を示しており、手数料が適用されています。
この額はトレーダーが支払う手数料には影響を与えませんが、流動性提供者が受け取る金額には影響を与えます。
すべてのユーザーのガスコストを大幅に増加させることになるスワップ時にこの手数料を計算する代わりに、この手数料は流動性が追加または削除された際に計算されます。
詳細についてはホワイトペーパーを参照してください。
価格
価格の決定方法
プロトコルの概要で学んだように、Uniswapの各ペアは実際には流動性プールによって支えられています。
流動性プールは、2つの異なるトークンの残高を保持し、それらを預け入れおよび引き出すためのルールを強制するスマートコントラクトです。
主なルールは定数積公式です。
トークンが引き出される(買われる)場合、一定の比率で預金(売られる)されなければなりません。
プール内のトークンの比率と定数積公式は、最終的にスワップの実行価格を決定します。
Uniswapが価格をどのように処理するか
UniswapV1では、取引は常に実行時に計算される「最良の可能な」価格で実行されます。
やや混乱することに、この計算は実際には2つの異なる式のうちの1つを使用して行われます。
取引が正確な入力または出力量を指定するかどうかに応じて、計算式が異なります。
機能的には、これらの2つの関数の違いは微小ですが、違いの存在自体が概念的な複雑さを増加させます。
V2でこれらの関数をサポートする初期の試みは不適切であることがわかり、コアでの価格設定関数は提供しないことになりました。
代わりに、ペアは各取引の後に(手数料を考慮に入れて)不変量が満たされたかどうかを直接チェックします。
これは、不変量も確保するための価格設定関数に依存する代わりに、V2ペアが自らの安全性を簡潔かつ透明に保証するもので、関心の良い分離です。
これにより、V2ペアは他の取引のバリエーション(例:実行時の特定の価格への取引)をより自然にサポートできるようになります。
UniswapV2では、取引はルーターと関連するスマートコントラクトで価格が設定される必要があります。
良いニュースは、ライブラリがこれを非常に簡単にするためのさまざまな関数を提供しており、ルータのすべてのスワップ関数はこれを考慮に入れて設計されていることです。
取引の価格設定
Uniswapでトークンをスワップする際には、正確な入力量に対してできるだけ多くの出力トークンを受け取るか、正確な出力量に対してできるだけ少ない入力トークンを支払うことが一般的です。
これらの金額を計算するには、コントラクトはペアの現在の準備を調べて、現在の価格が何であるかを理解する必要があります。
ただし、外部価格にアクセスしない限り、この検索を実行して結果に頼ることは安全ではありません。
たとえば、スマートコントラクトが単純に現在のリザーブ比率に基づいて10
DAIをDAI/WETHペアに送信し、できるだけ多くのWETHを受け取ることを望む場合を考えてみましょう。
これを呼び出す際、単純なスマートコントラクトは単に現在の価格を調べ、取引を実行しますが、これはフロントランニングの攻撃に対して脆弱であり、経済的な損失を被る可能性があります。
なぜなら、トランザクションが完了する前に攻撃者がそのトランザクションを見ることができる場合、単純なスワップが実行される前にDAI/WETHの価格を劇的に変更するスワップを実行し、単純なスワップが不利なレートで実行されるのを待ち、その後、単純なスワップが実行される前の価格に価格を変更するスワップを実行できるからです。
この攻撃は比較的安価で低リスクであり、通常は利益を上げることができます。
このような攻撃を防ぐためには、スワップがスワップが実行されるべき「公正な」価格に関する知識にアクセスできるようにすることが不可欠です。
言い換えれば、スワップはオラクルへのアクセスが必要であり、Uniswapから得られる最良の実行価格がオラクルが「真の」価格と考える価格に十分に近いことを確認する必要があります。
これは複雑に聞こえるかもしれませんが、オラクルは単にペアの現在の市場価格のオフチェーン観測として単純である場合があります。
アービトラージのため、通常、ペアのブロック内準備比率は「真の」市場価格に近い場合があります。
したがって、ユーザーがこの知識を持って取引を提出する場合、フロントランニングによる損失をしっかりと制限できます。
これが、たとえば、Uniswapフロントエンドが取引の安全性を確保する方法です。
観測されたブロック内価格に基づいて最適な入力/出力量を計算し、ルータを使用してスワップを実行することで、スワップが観測されたブロック内レートよりも少なくともx%
悪いレートで実行されることを保証します。
ここで、x
はユーザー指定のスリッページ許容度(デフォルトで0.5%
)です。
もちろん、V2ネイティブのオラクルなど、他のオラクルのオプションもあります。
正確な入力
できるだけ多くの出力トークンを受け取るために正確な入力トークン量を送信したい場合は、getAmountsOut
を使用します。
SDKの等価な関数はgetOutputAmount
、またはスリッページ計算のためのminimumAmountOut
です。
正確な出力
できるだけ少ない入力トークンで正確な出力トークン量を受け取りたい場合は、getAmountsIn
を使用します。
SDKの等価な関数はgetInputAmount
、またはスリッページ計算のためのmaximumAmountIn
です。
特定の価格へのスワップ
このより高度なユースケースについては、ExampleSwapToPrice.solを参照してください。
リターンを理解する
Uniswapは、ユーザーがトレーディングプールに流動性を提供することで、そのプールで他のユーザーが取引する際に生成される手数料でプロバイダーに報酬を与えることで、ユーザーに流動性の提供を奨励します
ただし、市場メーキングは一般的に複雑な活動です。
資産の価格が大きく持続的に変動する場合、資産を保持するだけと比較して資金を失うリスクがあります。
リスク
流動性の提供に関連するリスクを理解するためには、流動性ポジションの概念化方法を詳しく見るために、https://medium.com/@pintail/uniswap-a-good-deal-for-liquidity-providers-104c0b6816f2を読むことをお勧めします。
記事の例
流動性プロバイダーが10,000 DAIと100 WETHをプールに追加した場合を考えてみましょう(合計価値は20,000ドル)。この場合、流動性プールの総額は100,000 DAIと1,000 ETHになります。提供された金額は総流動性の10%に等しいため、コントラクトは市場メーカーに「流動性トークン」を生成して送信します。これらのトークンは取引に使用されるものではなく、流動性プロバイダーがいくら支払われるかを追跡するための会計上のツールです。他の人がトークンを追加したり引き出したりすると、新しい流動性トークンが生成/焼却され、各プロバイダーの流動性プールでの相対的な割合が同じままであるようにします。
さて、Coinbaseでの価格が100ドルから150ドルに変動した場合を考えてみましょう。Uniswapのコントラクトはこの変化を反映するはずで、アービトラージを行った後に変更されます。トレーダーはDAIを追加し、ETHを引き出して、新しい比率が150:1になるようにします。
流動性プロバイダーに何が起こるか? コントラクトは、122,400 DAIと817 ETHに近い値を反映するはずです(これらの数値が正確であることを確認するには、122,400 * 817 = 100,000,000(定数の積)および122,400 / 817 = 150(新しい価格)です)。提供された流動性の10%を引き出すと、12,240 DAIと81.7 ETHが得られます。ここでの総市場価値は24,500ドルです。市場メーキングによる約500ドルの利益が逃げてしまったと言えます。明らかに、誰も無償で流動性を提供したくありませんし、収益は良い取引から脱却する能力に依存していません(脱却はありません)。代わりに、すべての取引量の0.3%が流動性プロバイダーに比例して分配されます。デフォルトでは、これらの手数料は流動性プールに戻されますが、いつでも集めることができます。収益と方向性の動きからの損失のトレードオフは、間のトレードの量を知ることが難しいです。振り子運動が多いほど良いです。
なぜ自分の流動性が入金額よりも少ないのですか?
流動性プロバイダーのステークの価値が手数料からの収入にもかかわらず減少する理由を理解するには、Uniswapが取引を制御するために使用する公式をもう少し詳しく見る必要があります。この公式は非常にシンプルです。手数料を無視すると、次のようになります:
- eth_liquidity_pool * token_liquidity_pool = constant_product
つまり、トレーダーがETHとトークンを交換する際に受け取るトークンの数量とその逆が、取引後に二つの流動性プールの積が取引前と同じであるように計算されます。この公式の結果、流動性プールのサイズと比べて非常に小さな価値の取引では、次のようになります:
eth_price = token_liquidity_pool / eth_liquidity_pool
これらの二つの式を結合すると、定数の総流動性を仮定して任意の価格で各流動性プールのサイズを計算できます:eth_liquidity_pool = sqrt(constant_product / eth_price)
token_liquidity_pool = sqrt(constant_product * eth_price)
では、価格変動が流動性プロバイダーにどのような影響を及ぼすかを見てみましょう。事を簡単にするために、流動性プロバイダーがUniswap DAI取引所に1 ETHと100 DAIを供給し、100 ETHと10,000 DAIを含む流動性プールの1%を所有していると想像してみましょう。これは1 ETH = 100 DAIの価格を意味します。手数料を無視したまま、価格が変わったとしましょう。1 ETHの価値は現在120 DAIです。流動性プロバイダーのステークの新しい価値は何ですか? これらの数値を上記の公式に代入すると、次のようになります:eth_liquidity_pool = 91.2871
dai_liquidity_pool = 10954.4511
「流動性プロバイダーが流動性トークンの1%を持っているため、これは今、流動性プールから0.9129 ETHと109.54 DAIを請求できることを意味します。ただし、DAIはほぼUSDに相当するため、価格変更の全体的な影響を理解するために、この金額をすべてDAIに変換したいかもしれません。したがって、現在の価格では、私たちの流動性の総額は219.09 DAIです。流動性プロバイダーが最初のETHとDAIを保持し続けた場合はどうでしょうか? それでは、新しい価格での総額が220 DAIであることがすぐにわかります。したがって、流動性プロバイダーは、初期のETHとDAIを保持する代わりにUniswapに流動性を提供することで0.91 DAIの損失を出しました。」「もちろん、価格が流動性プロバイダーが流動性を供給したときと同じ値に戻ると、この損失は消えます。そのため、これを一時的な損失と呼ぶことができます。上記の式を使用して、流動性が供給されたときと今との価格比率に基づいて一時的な損失のサイズを導出できます。次のようになります。」
「一時的な損失 = 2 * sqrt(price_ratio) / (1+price_ratio) — 1」
「これをプロットして、異なる価格比率での一時的な損失のスケールの一般的な感覚を得ることができます。」
「別の言い方をすると:」
- 「価格が1.25倍に変化すると、HODLに対して0.6%の損失が生じます。」
- 「価格が1.50倍に変化すると、HODLに対して2.0%の損失が生じます。」
- 「価格が1.75倍に変化すると、HODLに対して3.8%の損失が生じます。」
- 「価格が2倍に変化すると、HODLに対して5.7%の損失が生じます。」
- 「価格が3倍に変化すると、HODLに対して13.4%の損失が生じます。」
- 「価格が4倍に変化すると、HODLに対して20.0%の損失が生じます。」
- 「価格が5倍に変化すると、HODLに対して25.5%の損失が生じます。」
「注:損失は価格変化がどの方向で発生しても同じです(つまり、価格が倍になる場合と半分になる場合の損失は同じです)。」
引用: https://pintail.medium.com/uniswap-a-good-deal-for-liquidity-providers-104c0b6816f2
最後に
今回はUniswapのドキュメントをまとめてきました!
技術的な部分は除いているので、技術者以外の方も概要を把握できると思います。
普段はブログやQiitaでブロックチェーンやAIに関する記事を挙げているので、よければ見ていってください!
Discussion