# Uniswap V2

Original: <https://lifelonglearn.ing/uniswap-v2>

Author: [奶爸](https://lifelonglearn.ing/users/3b04650c-8231-499b-8ef0-381fc4d7efb0)

Published: 2024-04-24T15:15:37Z

Updated: 2026-09-27T06:57:43Z

Version: 1

Uniswap 使用恒定乘积函数来确定不同加密货币的价格。它就像一个跷跷板，让一切保持平衡。这种方法可以用方程 x*y=k 来概括，其中 x 是流动性池中代币 A 的数量，y 是流动性池中代币 B 的数量，k 是常数。

Uniswap V2 合约分为 `v2-core` 主要是 Factory 负责创建和管理 Pair，和 `v2-periphery` 主要是 Router 合约，是 swap 及询价入口

## 添加流动性

当前池子里有 2ETH，5000USDT，用户输入了添加 500USDT，如何计算ETH数量？

添加流动性时保障 x/y 的比例不变
(∆x + x) / (∆y + y) = x/y
∆y = (∆x + x) * y / x - y
∆y = (∆x * y + x * y)/x - y
∆y = ∆x * y / x + y - y
∆y = ∆x * y / x
∆ETH = ∆USDT * 2ETH / 5000USDT
∆ETH = 0.2 ETH

算出需要同投入 0.2 ETH 可以平衡流动性

@startuml skinparam backgroundColor #ffffff00 skinparam DefaultFontColor #DodgerBlue skinparam handwritten true  skinparam sequence { ArrowColor LightSkyBlue ActorBorderColor LightSkyBlue LifeLineBorderColor LightSkyBlue LifeLineBackgroundColor #A9DCDF  ParticipantBorderColor LightSkyBlue ParticipantBackgroundColor DodgerBlue ParticipantFontName Impact ParticipantFontSize 17 ParticipantFontColor #A9DCDF  ActorBackgroundColor aqua ActorFontColor LightSkyBlue ActorFontSize 17 ActorFontName Impact }  actor User participant "Router" as A participant "Factory" as B participant "Pair" as C  User -> A: addLiquidity 添加/创建流动性 activate A  A -> B: 查找 Pair activate B  B -> A: getPair 获取 Pair 地址 deactivate B  A --> B: createPair 如果未创建先创建 activate B  B --> C: deploy 部署 Pair 合约 deactivate B  A -> C: 读取 reserves activate C C -> A: 返回 reserve0/reserve1，可能与余额不同 deactivate C  note over A: 通过 reserve0/reserve1 的比例计算需要添加的\\ntokenA、tokenB 的数量  A -> C: 转账 tokenA / tokenB 给 pair  A -> C: mint LP token activate C  note over C: 这里有两种情况，\\n1)之前流动性为0，则 mint √∆x∆y 数量 LP\\n2)如果是增加流动性则 mint totalSupply \* min(∆x / x, ∆y / y) 数量流动性  C -> User: mint deactivate C  A --> User: 添加完成 deactivate A  @enduml

## Swap

比如当前池子里有 2ETH，5000USDT，用户卖出 500USDT，如何计算买入的ETH数量？

(x + ∆x) * (y - ∆y) = k 在 swap 时，需保证 k（也就是 x * y ）值不变
y - ∆y = x*y / (x + ∆x)
∆y = y∆x / (x + ∆x)
∆ETH =  2 * 500 / (5000 + 500)
∆ETH = 0.181818182 ETH

算出卖出 500 USDT 会获得 0.1994 ETH

@startuml skinparam backgroundColor #ffffff00 skinparam DefaultFontColor #DodgerBlue skinparam handwritten true  skinparam sequence { ArrowColor LightSkyBlue ActorBorderColor LightSkyBlue LifeLineBorderColor LightSkyBlue LifeLineBackgroundColor #A9DCDF  ParticipantBorderColor LightSkyBlue ParticipantBackgroundColor DodgerBlue ParticipantFontName Impact ParticipantFontSize 17 ParticipantFontColor #A9DCDF  ActorBackgroundColor aqua ActorFontColor LightSkyBlue ActorFontSize 17 ActorFontName Impact }  actor User participant "Router" as A participant "Factory" as B participant "Pair" as C  User -> A: swap 进行交易 activate A  A -> B: 查找 Pair activate B  B -> A: getPair 获取 Pair 地址 deactivate B  A -> C: 读取 reserves activate C C -> A: 返回 reserve0/reserve1，可能与余额不同 deactivate C  note over A: 通过 reserve0/reserve1 数量计算 outputAmount  A -> C: 调用 Pair 的 swap 方法\\n更新 Pair 中的 reverse0/reverse1 记账 activate C  C -> User: token 转账 deactivate C  A --> User: Swap 完成 deactivate A  @enduml

在 Uniswap V2 中最重要的就是 Pair 中 reverse0/reverse1 的记账和 x · y=k 这个公式了。
