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}$