去中心化金融笔记(二)—— Uniswap V2 详解

5 篇文章 0 订阅
4 篇文章 0 订阅

加粗为自己添加的内容
配套课程视频:【01 区块链金融课程简介】- B站
课程实验以及讲义:liangpeili/defi-practices - Github
完成的实验代码:
https://github.com/DestinyWei/defi-practices
https://github.com/DestinyWei/defi-theory
若有任何问题或错误,可在Notion评论或直接评论
完整笔记请查看 Notion 链接:https://dune-marten-78b.notion.site/85b1d29c86344112a886fcfb2ea1c44c?pvs=4

个人博客:Howe的个人博客

Uniswap V2

手续费的计算机制

  1. 手续费全给项目方

因为项目方在池子中并没有 share,所以需要进行增发即 S m S_m Sm 部分

S 1 S_1 S1:LP 提供流动性得到的 share 数量 S m S_m Sm:系统按手续费比例增发的 share 数量

k 1 \sqrt{k_1} k1 :添加流动性对应的 k 值 k 2 \sqrt{k_2} k2 :添加流动性加上增发的 share 所对应的 k 值

图1

由上面可得,

S m S 1 + S m = k 2 − k 1 k 2 S m ∗ k 2 = S 1 ∗ k 2 + S m ∗ k 2 − S 1 ∗ k 1 − S m ∗ k 1 ( 化简 ) S m = k 2 − k 1 k 1 ∗ S 1 \begin{aligned} \frac{S_m}{S_1+S_m}&=\frac{\sqrt{k_2}-\sqrt{k_1}}{\sqrt{k_2}} \\ S_m*\sqrt{k_2}&=S_1*\sqrt{k_2}+S_m*\sqrt{k_2}-S_1*\sqrt{k_1}-S_m*\sqrt{k_1}(化简) \\ S_m&=\frac{\sqrt{k_2}-\sqrt{k_1}}{\sqrt{k_1}}*S_1 \end{aligned} S1+SmSmSmk2 Sm=k2 k2 k1 =S1k2 +Smk2 S1k1 Smk1 (化简)=k1 k2 k1 S1

  1. 手续费全给 Liquidity Provider

LP 的手续费并不是给 LP 增发新的 share 即 S m = 0 S_m=0 Sm=0,而是仍然是 S 1 S_1 S1 的数量,但随着手续费的累积,k 值会变大(此时可以理解为,LP 的 share 数量没有变化,在没有手续费收入的时候只共享 S 1 S_1 S1 价值,在有手续费收入的时候则共享 S 1 + 手续费 S_1+手续费 S1+手续费 价值 )

图2
所以,LP 为 0,项目方为 0

例子:最开始有100 DAI:1 ETH (k 值为 100 \sqrt{100} 100 ),经过一系列的交换,此时池子中有 96 DAI:1.5 ETH (k 值为 144 \sqrt{144} 144 )

  1. 项目方拿取一定比例(用 ϕ \phi ϕ 表示,为 S m S_m Sm 占整个增发部分的比例)的手续费

图3

由上面可得,

S m S m + S 1 = k 2 − k 1 k 2 ∗ ϕ \frac{S_m}{S_m+S_1}=\frac{\sqrt{k_2}-\sqrt{k_1}}{\sqrt{k_2}}*\phi Sm+S1Sm=k2 k2 k1 ϕ

S m S m + S 1 \frac{S_m}{S_m+S_1} Sm+S1Sm 表示的是项目方增发的比例, k 2 − k 1 k 1 \frac{\sqrt{k_2}-\sqrt{k_1}}{\sqrt{k_1}} k1 k2 k1 表示的是 LP 增加的比例

由此可以推导出

S m ∗ k 2 = S m ∗ k 2 ∗ ϕ + S 1 ∗ k 2 ∗ ϕ − S m ∗ k 1 ∗ ϕ − S 1 ∗ k 1 ∗ ϕ S m = ( k 2 − k 1 ) ∗ S 1 ( 1 ϕ − 1 ) k 2 + k 1 \begin{aligned} S_m*\sqrt{k_2} &= S_m*\sqrt{k_2}*\phi + S_1*\sqrt{k_2}*\phi - S_m*\sqrt{k_1}*\phi - S_1*\sqrt{k_1}*\phi \\ S_m &= \frac{(\sqrt{k_2}-\sqrt{k_1})*S_1}{(\frac{1}{\phi}-1)\sqrt{k_2}+\sqrt{k_1}} \end{aligned} Smk2 Sm=Smk2 ϕ+S1k2 ϕSmk1 ϕS1k1 ϕ=(ϕ11)k2 +k1 (k2 k1 )S1

ϕ = 1 \phi=1 ϕ=1 时,则为手续费全给项目方时所得到的公式

Spot Price

在使用 x 交换成 y 的时候,显示的价格为 P 0 = y x P_0=\frac{y}{x} P0=xy,但实际成交价格为 P 1 = Δ y Δ x P_1=\frac{\Delta y}{\Delta x} P1=ΔxΔy P 0 P_0 P0 P 1 P_1 P1 之间的差值就是所谓的滑点

Spot Price

x ∗ y = ( x + Δ x ) ∗ ( y − Δ y ) Δ y Δ x = y x + Δ x \begin{aligned} x*y &= (x+\Delta x)*(y-\Delta y) \\ \frac{\Delta y}{\Delta x} &= \frac{y}{x+\Delta x} \end{aligned} xyΔxΔy=(x+Δx)(yΔy)=x+Δxy

Δ x \Delta x Δx 较小时,我们可以理解为是在计算 lim ⁡ Δ x → 0 y x + Δ x \lim_{\Delta x \to 0}\frac{y}{x+\Delta x} limΔx0x+Δxy

Price Oracle

TWAP (Time Weighted Average Price) 时间权重的平均价格

P n P_n Pn 是在 t n t_n tn 时间点的价格

Price Oracle1

由上面可得,

∑ i = 0 n − 1 P i ∗ ( T i + 1 − T i ) \sum_{i=0}^{n-1}P_i*(T_{i+1}-T_i) i=0n1Pi(Ti+1Ti)

假如我们想要从 t k t_k tk 计算,而不是从 0 计算

Price Oracle2

由上面可得,

P = ∑ i = k n − 1 P i ∗ ( T i + 1 − T i ) T n − T k = ∑ i = 0 n − 1 P i ∗ ( T i + 1 − T i ) − ∑ i = 0 k − 1 P i ∗ ( T i + 1 − T i ) T n − T k \begin{aligned} P &= \frac{\sum_{i=k}^{n-1}P_i*(T_{i+1}-T_i)}{T_n-T_k} \\ &= \frac{\sum_{i=0}^{n-1}P_i*(T_{i+1}-T_i) - \sum_{i=0}^{k-1}P_i*(T_{i+1}-T_i)}{T_n-T_k} \end{aligned} P=TnTki=kn1Pi(Ti+1Ti)=TnTki=0n1Pi(Ti+1Ti)i=0k1Pi(Ti+1Ti)

通过这个公式,我们可以计算比如一个代币在一小时里的平均价格

如何计算 Uniswap V2 的无常损失

无常损失是出现在添加/移除流动性的情况下,而滑点是出现在两个代币交换的情况下

假设我们有一个初始 LP 为:100DAI:1ETH,此时 K = 100, P E = 100 1 = 100 P_E=\frac{100}{1}=100 PE=1100=100,两个代币总价值为 100 + 100 = $200

  • 当 ETH 涨价时,LP 为:120DAI:0.83ETH,此时 K 不变, P E = 120 0.83 = 144.58 P_E=\frac{120}{0.83}=144.58 PE=0.83120=144.58,两个代币总价值为 120 + 120 = $240,但如果我们并没有添加流动性而是拿住最开始的 100DAI 和 1ETH,两个代币总价值为 100 + 1 * 144.58 = $244.58,那么 244.58 与 240 的差值就是无常损失的值
  • 当 ETH 降价时,LP 为:80DAI:1.25ETH,此时 K 不变, P E = 80 1.25 = 64 P_E=\frac{80}{1.25}=64 PE=1.2580=64,两个代币总价值为 80 + 80 =$160,但如果我们并没有添加流动性而是拿住最开始的 100DAI 和 1ETH,两个代币总价值为 100 + 1 * 64 = $164,那么 164 与 160 的差值就是无常损失的值

即在添加流动性所产生的无常损失会导致 ETH 涨价时相比拿住赚得更少,ETH 降价时相比拿住亏得更多

通过上面的例子我们可以抽象出更通用的模型,我们可以列出下面这三个公式, P i P_i Pi 表示在 i 时刻某个代币的价格,d 表示价格变化的因素 (当 0 < d < 1 0 \lt d \lt 1 0<d<1 时表示降价, d = 1 d=1 d=1 时表示价格不变, d > 1 d \gt 1 d>1 时表示涨价)

P 1 = P 0 ∗ d x ∗ y = k P = y x \begin{align} P_1 &= P_0*d \\ x*y &= k \\ P &= \frac{y}{x} \end{align} P1xyP=P0d=k=xy

由 (2) (3) 可以计算得到 x 和 y 用价格P 和流动性k 的表达式

x = k y ⇒ k y = y P ⇒ y 2 = k ∗ P ⇒ y = k ∗ P x = y P = k ∗ P P = k P \begin{align} x=\frac{k}{y} \Rightarrow \frac{k}{y}=\frac{y}{P} \Rightarrow y^2 &= k*P \Rightarrow y = \sqrt{k}*\sqrt{P} \\ x &= \frac{y}{P}=\frac{\sqrt{k}*\sqrt{P}}{P}=\frac{\sqrt{k}}{\sqrt{P}} \end{align} x=ykyk=Pyy2x=kPy=k P =Py=Pk P =P k

假设一开始为 t 0 t_0 t0 x 0 x_0 x0 y 0 y_0 y0 P 0 = y 0 x 0 P_0=\frac{y_0}{x_0} P0=x0y0

添加流动性(无手续费)之后为 t 1 t_1 t1 x 1 x_1 x1 y 1 y_1 y1 P 1 = y 1 x 1 P_1=\frac{y_1}{x_1} P1=x1y1

拿住为 t h o d l t_{hodl} thodl x 0 x_0 x0 y 0 y_0 y0 P 1 = y 1 x 1 P_1=\frac{y_1}{x_1} P1=x1y1

将无常损失与价格变化之间的关系函数设为 f ( d ) f(d) f(d),V 表示为代币的 value,则

f ( d ) = 做 L P 的损失 拿住之后的价值 = V 1 − V h o d l V h o d l = V 1 V h o d l − 1 f(d)=\frac{做LP的损失}{拿住之后的价值}=\frac{V_1-V_{hodl}}{V_{hodl}}=\frac{V_1}{V_{hodl}}-1 f(d)=拿住之后的价值LP的损失=VhodlV1Vhodl=VhodlV11

由 (4) (5) 可以计算出 V 1 V_1 V1 V h o d l V_{hodl} Vhodl

V 1 = y 1 + x 1 ∗ P 1 = k 1 ∗ P 1 + k 1 P 1 ∗ P 1 = 2 ∗ k 1 ∗ P 1 V h o d l = y 0 + x 0 ∗ P 1 = k 0 ∗ P 0 + k 0 P 0 ∗ P 0 ∗ d = ( 1 + d ) ∗ k 0 ∗ P 0 \begin{aligned} V_1=y_1+x_1*P_1 = \sqrt{k_1}*\sqrt{P_1}+\frac{\sqrt{k_1}}{\sqrt{P_1}}*P_1 &= 2*\sqrt{k_1}*\sqrt{P_1} \\ V_{hodl} = y_0+x_0*P_1=\sqrt{k_0}*\sqrt{P_0}+\frac{\sqrt{k_0}}{\sqrt{P_0}}*P_0*d &= (1+d)*\sqrt{k_0}*\sqrt{P_0} \end{aligned} V1=y1+x1P1=k1 P1 +P1 k1 P1Vhodl=y0+x0P1=k0 P0 +P0 k0 P0d=2k1 P1 =(1+d)k0 P0

所以

f ( d ) = 2 ∗ k 1 ∗ P 1 ( 1 + d ) ∗ k 0 ∗ P 0 − 1 = 2 ∗ k 1 ∗ P 0 ∗ d ( 1 + d ) ∗ k 0 ∗ P 0 − 1 ( 因为无手续费,所以 k 1 和 k 0 相同 ) = 2 ∗ d 1 + d − 1 \begin{aligned} f(d) &= \frac{2*\sqrt{k_1}*{\sqrt{P_1}}}{(1+d)*\sqrt{k_0}*{\sqrt{P_0}}}-1 \\ &= \frac{2*\sqrt{k_1}*{\sqrt{P_0*d}}}{(1+d)*\sqrt{k_0}*{\sqrt{P_0}}}-1(因为无手续费,所以k_1和k_0相同) \\ &=\frac{2*\sqrt{d}}{1+d}-1 \end{aligned} f(d)=(1+d)k0 P0 2k1 P1 1=(1+d)k0 P0 2k1 P0d 1(因为无手续费,所以k1k0相同)=1+d2d 1

Uniswap 官方文档中给出的无常损失与价格变化的关系曲线

无常损失

Flash Swap

Flash Swap

传统的借贷需要用户先超额抵押才能借出代币

闪电交换是指用户无需质押一分钱即可借出一定数量的代币,例如当你发现有一个套利机会但没有足够的资金去进行超额抵押借贷时,我们可以通过闪电借贷借出 100 个 DAI,然后将这些 DAI 进行一系列的投资等去获取收益如变为 110 个 DAI,此时我们在把借出的 100 个 DAI 及其利息归还,剩下的收益就是自己的也就是 7 个 DAI

使用 Flash Swap 加杠杆

用户持有 3 个 ETH,每个 ETH 的价格为 200 DAI,抵押率为 150%。用户想要 2 倍杠杆

传统借贷

  1. 添加 3 ETH 到 Maker Vault
  2. 借出 400 DAI 出来
  3. 在 Uniswap 把 DAI 换成 ETH
  4. 重复 1-3 步

闪电借贷

  1. 跟 Uniswap 借 3 个 ETH
  2. 把用户的 3 个 ETH 和借的 3 个 ETH 抵押到 Maker Vault
  3. 借出 800 个 DAI 出来
  4. 还给 Uniswap 600 DAI

Uniswap V2 代码结构

代码结构

Uniswap V2 的核心合约就只有三个,分别是 Router、Factory 和 Pair 合约

图中的三个操作分别为 ① add liquidity ② swap ③ remove liquidity

用户通过前端页面即页面右边的长方块进行上述的三种操作时,会通过 Router 合约来判断执行的操作并调用相关合约的函数,在路由时合约会判断当前用户执行操作所对应的 Pair 是否已创建,若没有则会先创建一个 Factory 合约来创建相关的 Pair 合约,若有则直接调用对应 Pair 合约的函数

Uniswap V2 总结

一个核心:CPAMM

三个操作:添加流动性 / 加密资产交易 / 移除流动性

几个概念:手续费 / Price Oracle / TWAP / Falsh Swap / 无常损失 / 滑点等


后续笔记会在之后发布,让我们尽情期待,您也可以关注我的推特账号(@weihaoming)以获取更多笔记资源……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值