Uniswap V2 - How to do the math
问题: 如果 reserveA = 1000, reserveB = 2000 所以初始价格 P_A = reseverB / reserveA = 2000/1000 = 2, 即 1A = 2B, 因此如果用户想用 100A 换取 B, 是否应该能换 200B ? 再扣去手续费0.3% 相当于 200 * 99.7%?
回答: “用 100A 换 200B(再扣手续费)”这个计算是线性思维(即假设价格不变),而在 AMM(自动做市商)中,价格会随着交易发生而动态变化,这就是所谓的 滑点(slippage)。
详细推导如下👇:
🔹前提条件
池中初始储备:
- reserveA = 1000
- reserveB = 2000
- 因此初始价格:
$P_A = \frac{reserveB}{reserveA} = \frac{2000}{1000} = 2$,
即 1 A = 2 B
手续费 = 0.3%
手续费后有效输入比例 = 0.997
🔹Uniswap V2 的核心恒等式:
$$
x \times y = k
$$
其中:
- $x$ 是 token A 的储备量
- $y$ 是 token B 的储备量
- $k$ 是常数(交易前后必须保持不变)
🔹用户用 100 A 换 B 的详细过程
1️⃣ 用户输入的 A:
$$
\text{amountIn} = 100
$$
2️⃣ 扣除手续费:
$$
\text{amountInWithFee} = 100 \times 0.997 = 99.7
$$
3️⃣ 新的 A 储备:
$$
x’ = reserveA + amountInWithFee = 1000 + 99.7 = 1099.7
$$
4️⃣ 根据恒定积公式 $x \times y = k$,
交易前 $k = 1000 \times 2000 = 2,000,000$
所以:
$$
y’ = \frac{k}{x’} = \frac{2,000,000}{1099.7} \approx 1818.36
$$
5️⃣ 用户能拿到的 B 数量:
$$
\text{amountOut} = reserveB - y’ = 2000 - 1818.36 = 181.64
$$
✅ 结论
- 用户输入:100 A
- 实际获得:≈ 181.64 B
- 实际价格:$\frac{181.64}{100} = 1.8164$
(低于初始价格 2,原因是滑点)
🔹对比问题中的计算
问题中线性比例算得是:
$$
100A \times 2 = 200B
$$
再扣 0.3% 得 $200 \times 0.997 = 199.4B$。
➡️ 这是静态价格假设下的计算,但 AMM 实际上价格随交易动态变化。
由于用户一次性投入 100 A(池子总量的 10%),对价格影响很大,
所以用户只能拿到 181.64 B,而不是 199.4 B。
🔹总结
| 概念 | 含义 |
|---|---|
| k 恒定积 | 保证池子总流动性恒定:$x \times y = k$ |
| 滑点 | 大额交易导致价格变化,得到的代币变少 |
| 手续费 | 每笔交易收取 0.3%,分给流动性提供者 |
| 价格动态性 | 每次 swap 都会改变 reserve,从而改变价格 |
| 实际输出公式 | $\text{amountOut} = \frac{amountInWithFee \times reserveOut}{reserveIn \times 1000 + amountInWithFee}$ |