Uniswap v4をざっと見たメモ

Shuhei Hiya
Jun 13, 2023

--

Uniswap v4について、とりあえず個人的に必要なことだけ調べました。基本のAMMの仕組みは、v3とほとんど変わっていないと思われます。しかしhooksコントラクトによってプールの機能を拡張することができるようになっており、コントラクトの外側からでは追加できなかった機能を実現できるようになっています。急いで書いたので、間違っていたらすみません。

プールのIDについて

何故いきなりIDの話からスタートするかというと、プールと手数料率、hooksの関係性を明確にしたいからです。

Uniswapのプールを特定するためのIDは、PoolKeyというデータ構造をシリアライズして作ります。PoolKeyの属性には、v3から比べてtickSpacingとhooksのアドレスが追加されました。このどれかの値が異なれば、別のプールとして作成されます。

struct PoolKey {
Currency currency0;
Currency currency1;
uint24 fee;
int24 tickSpacing;
IHooks hooks;
}

実際には、feeはdynamic feeかstatic feeかの選択肢があります。例えば、30bps pool, 5bps pool, dynamic fee poolは、それぞれ別に存在し得ます。

またhooksコントラクトが異なれば、別のプールとして存在することになります。同じETH-DAIプールでも、異なるhooksコントラクトに依存するプールが、別々に存在できると思われます。

hooksについて

v4の大きな特徴として、プール初期化時にhooksコントラクトを設定できる点があります。hooksコントラクトは、Uniswap本体の以下の操作に対するフック関数を追加することができます。

  • Initialize
  • ModifyPosition
  • Swap
  • Donate

以下のように、使用するhook関数を設定します。ちなみにModifyPositionというのは、LP資金を追加したり、引き出したりする関数です。

function getHooksCalls() public pure override returns (Hooks.Calls memory) {
return Hooks.Calls({
beforeInitialize: true,
afterInitialize: false,
beforeModifyPosition: true,
afterModifyPosition: false,
beforeSwap: true,
afterSwap: false,
beforeDonate: false,
afterDonate: false
});
}

既にLimitOrderTWAMMFullRangeLPのような、hooksコントラクトのサンプルコードがあります。

Swap直後にフックを追加できることで、あるtickで交換が実行された直後に、自動でLP資金を抜くことができます。これ以外にも、交換をトリガーにさらに交換を行うことで、逆指値のような複雑な注文も実装できるのではないかと思いました。(本当にできるかはわかりません)幾何平均価格やボラティリティの計算などのオラクル周りのカスタムも可能になります。

一方で複雑なhooksが増えることで、プールによって取引コストが大きくなったり、v3のQuoterコントラクトで行っていたような見積もり処理が難しくなってしまうのではないかとも感じました。hooks毎にプールが分かれてしまった場合の、プール同士の競合なども起こるのではないでしょうか。

donate関数が少し面白くて、単純にLPに手数料を払うための関数です。例えば、hooks内でLPポジションを借りて、追加の金利をdonateでLPに払うこともできるのでは?と思いました。例えばpanopticみたいな仕組みがhooksで実装できたら面白いですね。

手数料について

v4は手数料周りも大きく変わっているようです。hooksコントラクトは、トレーダーが支払う交換手数料と自身の取り分を設定できるようになっています。動的な設定と静的な設定があります。またLPが資金を引き出す場合の引き出し手数料を、hooksコントラクト内で設定できます。これらのhooksコントラクトの手数料は、0に設定することもできます。設定可能な最大値はコントラクトで決まっているようです。

hooksコントラクトが設定できる手数料率は、以下の3つです。

  • トータルの交換手数料率
  • hooksコントラクトへの交換手数料率
  • 引き出し手数料率

トータルの交換手数料=交換量 * トータルの交換手数料率

hooksコントラクトが得る交換手数料=トータルの交換手数料 * hooksコントラクトへの交換手数料率

プロトコルが得る手数料=トータルの交換手数料 * プロトコルの手数料率

交換においてLPが得る手数料は、以下のようになります。

LPが得る手数料=トータルの交換手数料 — hooksコントラクトが得る交換手数料 — プロトコルが得る手数料

引き出し手数料については、以下のようになっているようです。

トータルの引き出し手数料=引き出し量*引き出し手数料率

プロトコルが得る引き出し手数料=トータルの引き出し手数料*プロトコルの引き出し手数料率

hooksコントラクトが得る引き出し手数料 = トータルの引き出し手数料 — プロトコルが得る引き出し手数料

動的な手数料設定もあるので、volatilityなどのパラメータを元に手数料を設定するプールも作れそうです。

ガス代まわり

ホワイトペーパーによると、プール作成のガス使用量は99%減るようです。これはシングルコントラクトになって、プール毎に新しいコントラクトを作らないことの影響です。スワップ周りのガスは、トークンの受け渡しが減ったことと、TWAPオラクルをhooksに移動させたことで、感覚的には10-20%くらい減るのではないでしょうか。一方で結局メジャーなプールにhooksを使用してTWAPが実装されるのであれば、実はガス使用量の変化は少ないのではないとも考えられます。この辺りは最終的なトランザクションの状態を見なければわからないので、なんとも言えません。

終わりに

Swapの直後にフックを追加できるようになったことで、開発できる機能がかなり増えると思います。またオラクルの計算についても、hooksとして外部に出したのは、計算コストの観点でかなりプラスだと思います。

全体的に、利便性やガスコスト、手数料率のトレードオフなどの決定を、プール作成者に委ねる設計にしたように思います。

プール作成者は、人ではなくプロトコルである可能性もあります。そうなっていくことで、Uniswapと他のプロトコルはより密接になり、逆に言うとLPだけでなくプロトコルの競争が、Uniswapのプール上で繰り広げられるのではないでしょうか。v4はドラフトということなので、皆様もぜひコードを見てみてください。

v4 core: https://github.com/Uniswap/v4-core

hooksのサンプル: https://github.com/Uniswap/v4-periphery/tree/main/contracts/hooks/examples

--

--