手续费计算机制
1. 手续费全部分给项目方
$S_1$:池子中的lp Token
$S_m$:手续费的增量,增发给项目方的lp Token,项目方可以通过它将自己的手续费提取出来
$\sqrt{k_1}$:最开始池子中流动性的表示
$\sqrt{K_2}$:变化后池子中流动性的表示
由此:
$$\frac{S_m}{S_1+S_m}=\frac{\sqrt{k_2}-\sqrt{k_1}}{\sqrt{k_2}}$$
可以计算出:
$$S_m=\frac{\sqrt{k_2}-\sqrt{k_1}}{\sqrt{k_2}}·S_1$$
2. 手续费全部分给Liquidity Provider(更正:lp Token不会增发)
情况与第一种类似,lp的
$$S_m=\frac{\sqrt{k_2}-\sqrt{k_1}}{\sqrt{k_2}}·S_1$$(理论上总价值增发,实际上是lp Token更值钱了)
项目方的手续费则为0。
3. 项目方拿去一定比例($\phi$)的手续费
图中的手续费增量则是$\frac{S_m}{\phi}$
所以:
$$\frac{S_m}{S_1+S_m}=\frac{\sqrt{k_2}-\sqrt{k_1}}{\sqrt{k_2}}·\phi$$
也可以理解为,“项目方增发lp Token”比上“现在池子中的lp Token”等于“流动性增量”比上“现在池子中的流动性”乘以“项目方增发的比例”。
由此计算:
$$S_m=\frac{(\sqrt{k_2}-\sqrt{k_1})·S_1}{(\frac{1}{\phi}-1)·\sqrt{k_2}+\sqrt{k_1}}$$
对Uniswap来说,这里的$\phi$是$\frac{1}{6}$
所以,公式:
$$S_m=\frac{(\sqrt{k_2}-\sqrt{k_1})·S_1}{5\sqrt{k_2}+\sqrt{k_1}}$$
Spot Price
$$P_0 = \frac{y}{x}$$
$$P_1 = \frac{\Delta y}{\Delta x}$$
$P_0$是Uniswap报出的价格,$P_1$是实际成交价格,$P_0$与$P_1$之间的差距就是“滑点”。
$$\frac{\Delta y}{\Delta x} = \frac{y}{x + \Delta x}$$
当$\Delta x$趋近于零的时候,$P_0$与$P_1$是非常接近的,滑点也是约等于0。
Price Oracle
Uniswap本身也提供一个价格预言机,TWAP(time weighted average price)
$$P=\frac{\sum_{i=0}^{N-1} P_i(T_{i+1}-T_i)}{T_n}$$
这是计算的从零到$T_n$时间段的TWAP,但一般情况下,我们可能会更多的计算中间某一段时间的TWAP,也就是在0到$T_n$间存在$T_k$,此时,我们计算的TWAP为:
$$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}$$
相比前一个公式,后一个公式明显更适合在合约层面实现。
计算无常损失
无常损失就是对用户做lp损失的一个量化。
现假设一个不收手续费的场景,初试lp 100DAI:1ETH 此时k=100,$P_E=100$,添加部分的总价值$P_{tol}=200$
1:ETH涨价 120DAI:0.83ETH
此时$P_E=144.58$,$P_{tol}=240$
看似$P_{tol}$已经变得更高,但从另一个方向,也就是不添加lp时。
因为ETH涨价预期的价值$P_{pre}=100 + 144.58 = 244.58$,此时因为添加流动性而导致用户“少赚”的这部分“钱”就是无常损失,而这里的无常损失$loss=4.58$
2:ETH降价 80DAI:1.25ETH
此时$P_E=64$,$P_{tol}=160$
相同的,在不添加流动性的情况下,因为ETH降价预期的价值$P_{pre}=100 + 64 = 164$,此时因为添加流动性而导致用户“多亏”的这部分“钱”就是目前的无常损失,而这里的无常损失$loss=4$
量化
引入一个价格变化因子d,用公式$P_1= P_0·d$表示价格由$P_0$到$P_1$的变化。
此时定义
$$ \begin{cases} ETH:x \\ DAI:y \\ \end{cases} $$
$$P=y/x$$
由此可以推导出
$$x=\sqrt{k} / \sqrt{k} $$
$$y=\sqrt{k} · \sqrt{k} $$
现在定义初始变量$$t_0, x_0, y_0, P_0=y_0/x_0$$
无手续费添加流动性后为$$t_1, x_1, y_1, P_1=y_1/x_1$$
不添加流动性,也就是“hodl”时$$t_{hodl}, x_0, y_0, P_1=y_1/x_1$$
定义无常损失公式
$$f(d) = \frac{做lp的损失}{拿住之后的价值} = \frac{V_1-V_{hodl}}{V_{hodl}}$$
可以计算
$$V_1=y_1+x_1 · P_1=2\sqrt{k_1} · \sqrt{P_1}$$
$$V_{hodl}=y_0+x_0 · P_1=(1+d)\sqrt{k_0} · \sqrt{P_0}$$
$$f(d) = \frac{V_1}{V_{hodl}} - 1 = \frac{2\sqrt{k_1} · \sqrt{P_1}}{(1+d)\sqrt{k_0} · \sqrt{P_0}} - 1 = \frac{2\sqrt{d}}{1+d}-1$$
下面是Uniswap官方的无常损失函数图像。
官方也有弥补用户无常损失的方法,比如farms、pools(pancake Uniswap)
Flash Swaps
基本原理图示如下:
第一种情况不使用Flash Swaps,也就是用户必须持有加密货币,通过在Uniswap pool中置换出DAI,来满足用户自己的需求。
而第二种情况,主要发生在用户“不持有”加密货币,但用户发现了一个可以“套利”的机会,用户就可以通过Flash Swaps“借贷”出相应数量的DAI,并在使用完成后返回相应数额。
使用Flash Swaps加杠杆
例如以下案例:
其中左边的步骤为一般操作,右边则是使用Flash Swaps进行加杠杆。
注意,“借出”来的ETH并不需要一定“返还”ETH,如最后一步“返还”DAI同样可以。
V2代码结构
注意,Uniswap浏览器的数据很多都是通过The graph来查询实现的,官方网站也有说明。