Uniswap v4:新機能とUniswap v3からの連続性
目次
- はじめに
- 新機能の紹介
- 注目機能:フックについて
(1) アクションフック(Action Hooks)
(2) フック管理手数料(Hook-managed fees) - その他の変更点
(1) ガス代の節約
(2) 手数料に対するガバナンス
(3) donate機能 - おわりに
1. はじめに
Uniswap v4の概要が2023年6月13日に発表され、同時にWhitepaperのドラフトが公開された。現段階で3枚以内で収まる程度に短く、Uniswap v3との連続性が強く意識せられる内容になっている。本レポートでは、Uniswap v4の英語版Whitepaper(公表:2023/6/13)を元に新機能の概要を紹介する。
2. 新機能の紹介
本章は、Uniswap v4の変更点について紹介する。Uniswap v4の大きな特徴は高い拡張性とデザインパターンの変更である。AMMモデル自体に大きな変更はなく、以前のバージョンと同様ノンカストディアル・ノンアップグレイダブル・パーミッションレスなDEXである。つまり、ユーザーがプールに預けた資金はスマートコントラクト内で保管され、どのトレーダーでもその流動性を使用し、トークンをスワップできる。また、スマートコントラクトデプロイ後は機能の変更や更新はできない。
次に、過去バージョンのUniswapの特徴と課題について整理する。Uniswap v1とUniswap v2はどちらもCPMM型のAMMであり、それぞれERC20<>ETHとERC-20<>ERC-20のスワップが可能であった。Uniswap v3では集中流動性を導入することで資金効率の改善がなされた。さらに同じ通貨ペアに対し複数の手数料率のプールが用意され、流動性供給者は市場の状況に応じた柔軟なプール選択が可能となった。Uniswap v2で導入された価格オラクルによりインテグレーターがオンチェーンで価格データを使用できるようになったものの、オラクル処理はガス代が高く追加機能の実装・運用は難しい。またプール毎にコントラクトの作成が必要であり、初期コスト・運用コストが高いなどの課題があった。これらの課題を解決するために、Uniswap v4では以下の変更がなされた。
- フック(Hooks)の導入
- 一連のライフサイクルの重要なポイントで実行される処理をフックコントラクトとして実装可能
- フックにより、プールのスワップ手数料や流動性出金手数料の設定など拡張性の高いプールが作成可能
- シングルトン(Singleton)型への変更
- デザインパターンをファクトリ型からシングルトン型へ変更。つまり、プール毎にコントラクトが分かれているのではなく1つのコントラクトで全プールを管理する
- シングルトン型により、プール作成時のコスト削減や複数プールに跨るマルチホップ型取引が可能
3. 注目機能:フックについて
前章でUniswap v4の変更点について説明したが、3章では特に注目されているフックについて説明する。フックとは、Uniswap v4が提供するAMM処理とは別にプール作成者が自由に処理を追加実装できる仕組みである。
3.(1) アクションフック(Action Hooks)
ユーザーは、Uniswap v4で流動性プールを作成し、追加機能をアクションフックとして実装することでプール内の処理をカスタマイズすることができる。フックによる追加機能の実装案としては以下が候補として考えられている。
- TWAMM[1]によるトークン取引の大型発注
- 指値注文
- ボラティリティに基づく動的スワップ手数料の変更
- 範囲外の流動性をレンディングプロトコルなどで運用
- 流動性供給による収益の複利運用
- 流動性供給者のためにMEV対応機能
- 価格の中央値や切り捨てなどを導入したオラクル価格のカスタム
フックは、フックコントラクトのアドレスをコールバックとしてプールに設定することで、プールから呼び出され実行される。フックコントラクトにより、追加機能の実装がAMMの主要ロジックやライフサイクルとは疎結合になるため、コードの可読性や再利用性が高まり、かつ動作テストが容易になる。ライフサイクル内の割り込み可能なポイントとしては、Initialize・ModifyPosition・Swap・Donateの4つがあり、それぞれ前後で割り込みが可能である。図1はSwapフックのフローチャートを表している。S1のExecute Swapの前後(S0、S2)でフックが登録されている場合、フック処理(H1、H2)を実行する。
afterSwap フックによる指値注文の実装例を下記コードで紹介する。まず、スワップによる価格変化をtickデータを元に算出する。そして、その価格幅にブッキングされている指値注文を取得・実行する。
function afterSwap(
address,
IPoolManager.PoolKey calldata key,
IPoolManager.SwapParams calldata params,
BalanceDelta
) external override poolManagerOnly returns (bytes4) {
//swap前後で交差したtickの下限、上限を取得取得
(int24 tickLower, int24 lower, int24 upper) = _getCrossedTicks(key.toId(), key.tickSpacing);
//....
bool zeroForOne = !params.zeroForOne;
for (; lower <= upper; lower += key.tickSpacing) {
//epochが存在するか判定(交差したtick内に該当する指値注文が登録されているか確認)
Epoch epoch = getEpoch(key, lower, zeroForOne);
if (!epoch.equals(EPOCH_DEFAULT)) {
EpochInfo storage epochInfo = epochInfos[epoch];
...
// lockを取得した後ポジションを更新(指値注文を実行)
(uint256 amount0, uint256 amount1) = abi.decode(
poolManager.lock(
abi.encodeCall(this.lockAcquiredFill, (key, lower, -int256(uint256(epochInfo.liquidityTotal))))
),
(uint256, uint256)
);
...
//指値注文の結果得られたトークン数量を保存
unchecked {
epochInfo.token0Total += amount0;
epochInfo.token1Total += amount1;
}
...
}
}
...
}
3.(2) フック管理手数料(Hook-managed fees)
Uniswap v4では手数料をトークンスワップ時だけでなく、流動性供給者がプールから資産を引き出す時に徴収することができる。スワップ手数料は必須項目であるが、フックコントラクトにより手数料は固定・変動のいづれかで定義でき、また、プールの作成者自身が一部の手数料を徴収するように設定することもできる。一方で、流動性供給者が資産引き出し時に徴収する手数料は標準で設定されておらずフックにより追加定義できる。徴収した手数料を他の流動性供給者、トレーダー、フック作成者など、様々なプレイヤーに割り当てることができる。
手数料の設定例
- スワップ手数料を固定、または、変動に設定
- スワップ手数料の一部をプール作成者に分配
- 流動性解約時に徴収する手数料と分配先の設定
Uniswap v3では流動性の分断を避けるために手数料の階層を4種類(0.01%、0.05%、0.30%、1.00%)に制限していたが、Uniswap v4では任意のスワップ手数料設定や手数料の動的変更ができる。
4. その他の変更点
4.(1) ガス代の節約
4.(1).① シングルトン型とフラッシュ・アカウンティング
既存のUniswapはファクトリ型のデザインパターン[2]を採用しているが、Uniswap v4からシングルトン型に変更される。そのため、1つのコントラクト上で全てのプールが管理され、新規プール毎にコントラクトをデプロイする必要がなくなる。フックの導入により今後多数のプールが誕生することが想定されるので、流動性の分散による取引執行コスト増に対応できるシングルトン型の設計はかなり効果的である。
シングルトン型のメリットとして、異なるプールに跨るスワップにおいてプール間でトークンを移動させる必要がなくなり、マルチホップ・ルートでの取引が容易になることが挙げられる(図2)。マルチホップ・ルートにおいてスワップ手数料はdeltaというパラメータにより管理され、流動性供給者への支払い余力が担保される仕様となっている。また、従来では難しかった異なるブロックチェーン間での資産の交換や流動性の追加(Atomic Swapping/Adding)などへの応用も期待される。
さらに単一コントラクトが全プールの状態を管理するため、残高データのスナップショット取得が容易になり、インデックス業者やデータ分析者がデータを管理しやすくなる。
4.(1).② ネイティブETHの復活
Uniswap v4ではプールの通貨ペアにETHを使用する際、ネイティブETHを使用できる仕様に戻した。Uniswap v2からETH固有の実装を排除することやWETHとETHの両方が存在することによる流動性の分散を排除する目的から、ERC-20規格の通貨ペアで流動性供給が行われる仕様となった。しかし、Uniswap v4ではシングルトン型とフラッシュ・アカウンティングを導入したことで、プール間を跨ぐ取引の執行コストが低減されたため、ネイティブETH対応を復活させた。実際、ネイティブETHの取引執行時のガス代はERC-20規格のものと比較すると約半分となる。
4.(1).③ ガス代を節約する実装
Uniswap v4ではガス代を節約する工夫が随所に施されている。例えば、フックのコントラクトアドレス自体にフラグ情報を持たせている点などが挙げられる(コード2)。AFTER_SWAP_FLAGは155ビット目が1でそれ以外が0の定数である。フックのコントラクトアドレスの155ビット目をフラグとして使用する。つまり、155ビット目が1なら自身はAfterSwapフックコントラクト、0ならそうでないことを意味する。これらのアドレス自体のフラグ化により、AND演算子による条件確認が可能となり、メモリアクセスよりも処理コストが低くガス代が節約されている。
uint256 internal constant AFTER_SWAP_FLAG = 1 << 154;
...
function validateHookAddress(IHooks self, Calls memory calls) internal pure {
if (
...
calls.afterSwap != shouldCallAfterSwap(self)
...
) {
revert HookAddressNotValid(address(self));
}
}
function shouldCallAfterSwap(IHooks self) internal pure returns (bool) {
return uint256(uint160(address(self))) & AFTER_SWAP_FLAG != 0;
}
4.(1).④ ERC1155 Accounting
Uniswap v4ではERC-1155規格のトークンの発行・償却に対応する。ERC-20規格のようにトークン毎にコントラクトの転送処理する必要がなくなり、ヘビーユーザーには大きな取引コスト削減になる。
4.(2) 手数料に対するガバナンス
Uniswap v4ではこれまで同様、ガバナンスが各プールで徴収するスワップ手数料の上限を設定できる。さらに、フックにより流動性解約時に徴収する手数料についても上限を設定できる。一方で、Uniswap v3でガバナンスによって管理されているスワップ手数料の種類(Fee Tier)やティック間隔(Tick Spacing)については設定を行えない。
4.(3) donate機能
donateはユーザー・integrator・フックが流動性供給者にトークンを譲渡する機能である。この機能によりレンジ内の流動性供給者への直接的な手数料の支払いやLPポジションの貸し借りと貸借料の支払い、インセンティブを用いた流動性の外部コントールなど様々な実装が可能で、持続可能なDEX設計が期待される。
5. おわりに
Uniswap v4の新機能の中でも特に注目すべきは、ユーザーがカスタムプールの作成を可能にするフック機能である。これにより、従来のトレーダーや流動性供給者に加え、カスタムプールの作成者や管理者といった新たなプレイヤーが誕生する。今後これらプレイヤーがエコシステムにどのような影響を及ぶすか、そしてUniswap v4がDeFiエコシステムにどのように貢献するかは引き続き注目が必要である。
参考文献
[1]: Dave White, Dan Robinson, Hayden Adams., TWAMM, 2021, https://www.paradigm.xyz/2021/07/twamm
[2]: Erich Gamma, Richard Helm, Ralph Johson, John Vlissides., Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley Professional., 1994