Uniswap V2
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 这个公式了。