The Way to Uniswap
中心化交易所通常采用「订单薄」(Order Book)模式撮合交易,其中存在「做市商」(Market Maker)这一角色,它起到增加交易所订单「深度」的作用。
区块链 TPS 远低于中心化交易所,且交易手续费不菲,再这样的一种新兴平台上传统做市商很难高频地调整买单和卖单以提供做市服务。
- 传统做市商具体如何赚钱?
区块链生态中与传统做市商对应的是「自动做市商」(Automated Market Maker, AMM),这是一种去中心化交易所(Decentralized Exchange, DEX),通常采用一个简洁的「恒定乘积方程」(constant product formula, $$x * y = k$$)作为数学模型为资产定价。用户可以创建新的流动性池(Liquid Pool)或者为已有的流动性池提供流动性,这样的用户就成了流动性提供者(Liquid Providers, LPs)。
- 用户执行兑换交易的交易对象是流动性池(不是其它交易者),每个流动性池由两种资产组成。
- AMM 会对兑换交易收取手续费,用户为流动性池提供流动性的动机就是赚取这部分手续费。
恒定乘积方程
恒定乘积方程 $$x * y = k$$ 中:
- x 和 y 是两种资产的数量,不论 x 和 y 如何变化,最终要模型维持 x 和 y 的乘积恒定。
- 不考虑兑换手续费时,x 和 y 的兑换公式是 $$∆y = (∆x * y) / (x + ∆x)$$,对于深度足够的流动性池来说可以忽略分母中 $$+ ∆x$$ 部分,公式可以简化为 $$∆y = (∆x * y) / x$$,即 $$\frac{∆y}{∆x} = \frac{y}{x}$$。这意味着 x 和 y 组成的交易对的边际价格可以由流动性池中 x 和 y 的数量的比率来反映。
- 假设 $$x = 10, y = 1000$$,则兑换 1 个 x 约能得到 100 个 y,即 x 的价格约为 y 的 100 倍。
- A liquidity pool determines the price of its assets from the assets’ ratio in the pool.
- 这一模型假设了流动性池中两种资产的兑换率与市场价出现偏差时,套利者(arbitrage traders)会通过 Swap 操作来搬平:从流动性池换走在其中价格被低估的资产、换来在其中价格被高估的资产,直到两者的兑换率重新回归市场价。
无常损失
「无常损失」(Impermanent Loss)的定义是相较于只是持有资产,用户用这些资产为流动性池提供流动性且因为资产的价格发生波动而带来的资产缩水。
- 只要流动性池中的资产发生价格波动(无论上涨还是下跌),就会产生无常损失,且价格波动越大无常损失也越大。
- The only thing impermanent loss cares about is the price ratio relative to the time of deposit.
- 场景分析(不考虑手续费和 DAI 的价格波动):由 ETH/DAI 组成的流动性池,市场价 1 DAI 等于 1 USD,1 ETH 等于 100 USD,此时 Alice 按照流动性池对应的 exchange 合约计算出的比率存入 1 ETH 和 100 DAI 为其提供流动性(总价值 200 USD);在 Alice 存入后,流动性池包含 10 ETH 和 1000 DAI,其中 Alice 占了 10% 的份额;恒定乘积等于 10000。
- ETH 市场价从 100 USD 涨至 400 ETH;
- 1 ETH 的市场价有 400 DAI,而流动性池中 1 ETH 只有 100 DAI,流动性池中的 ETH 的价格被低估,成为套利的目标(被换走)。
- 套利者用 DAI 来 Swap 流动性池中所有价格低于 400 USD 的 ETH,直到流动性池中的 ETH 价格也是 400 USD。
- 套利者搬平兑换率差后,流动性池中的 ETH 的价格是 DAI 的 400 倍,也就是说 DAI 的数量是 ETH 的 400 倍,根据恒定乘积方程可以算出此时 ETH 数量是 5,DAI 数量是 2000。
- 假设 Alice 移除流动性时,她可以拿到 $$5 * 10\% = 0.5$$ 个 ETH 和 $$2000 * 10\% = 200$$ 个 DAI,总价值 400 USD;若 Alice 没有提供流动性池,此时她的 1 ETH 和 100 DAI 的总价值 500 USD,中间相差的 100 USD 就是无常损失(20%)。
- ETH 市场价从 100 USD 跌至 25 USD(流动性池中 )。
- 1 ETH 的市场价只有 25 DAI,而流动性池中 1 ETH 等于 100 DAI,流动性池中的 DAI 的价格被低估,成为套利的目标(被换走)。
- 套利者用 ETH 来兑换 DAI,套利的结果是 ETH 数量是 20,DAI 数量是 500。
- 假设 Alice 移除流动性,它可以拿到 2 ETH 和 50 DAI,总价值 100 USD;若 Alice 没有提供流动性,此时她的 1 ETH 和 100 DAI 的总价值是 125 USD,中间相差的 25 USD 就是无常损失(20%)。
- 如果把作为 LPs 赚取的手续费考虑在内,一定程度上可以补偿无常损失。
- ETH 市场价从 100 USD 涨至 400 ETH;
- 无常损失是可逆的,即非永久的,只有当出现无常损失且用户移除了流动性,无常损失才变成确实的损失。
滑点
滑点(slippage):因流动性不足造成的实际成交价格和期望成交价格之间的不理想的价差。
出现滑点的主要原因有:
- 交易所缺乏流动性;
- 市场上资产价格波动大。
V1 白皮书
Uniswap 是典型的基于恒定乘积模型的 AMM。
- 用户提供流动性后,组成该流动性的两种资产被锁定到相关的合约中,成为 LP 的用户获得相应比例的 UNI token 作为提供流动性的凭证。
- 这些 UNI token 被铸造出来,发放到 LP 的地址。
- 获得的 UNI token 的数量在当下已发放了的所有 UNI token 的数量里的占比和当下该用户提供的资产在流动性池中的资产总数里的占比相同。
- 用户用 UNI token 移除流动性时,这部分的 UNI token 被燃烧掉,换回对应的两种资产。
- 可以赎回的两种资产在流动性池中的占比和当下这部分 UNI token 在 UNI token 的总发放量里的占比相同。
- 每执行一次 Swap,增加的资产的数量是足额的,由于手续费的存在,因兑换而减少的另一种资产实际减少的数量却略少一些,结果是“恒定”乘积每次 Swap 后都会增大一点。
要点:
- V1 中协议没有抽取手续费,所有手续费(0.3%)收入都归属流动性提供者。
- 只有 ETH 和 ERC20 token 能组成流动性池;ERC20 之间的交换需要以 ETH 作为中介(收两次手续费)。
- 每个 exchange 合约实现了 ERC20 接口,代币是
UNI-V1
,持有者和持有数量的关系通过self.balances
这一 map 来维护;self.token
保存了在此 exchange 上交易的 ERC20 token 的合约地址。
V1 core 代码分析
创建 ERC20/ETH 交易对合约
V1 用工厂合约为每个 ERC20 token 和 ETH 组成的交易对部署一个独立的合约(exchange contract)。
|
|
- 一种 ERC20 token 只能创建一个 exchange。
- 每个 exchange 都实现了 ERC20 接口和事件(
totalSupply
,balanceOf
,transfer
,transferFrom
,approve
,allowance
,Transfer
,Approval
),token 是UNI-V1
。
ETH 换 ERC20 token
|
|
- 计算公式:
- $$ethAmountBeforeSwap × erc20TokenAmountBeforeSwap = invariant$$
- $$erc20TokenAmountBeforeSwap - \frac{ ethAmountBeforeSwap × erc20TokenAmountBeforeSwap }{ ethAmountBeforeSwap + ethAmountToSwap × 0.997 } = \frac{ethAmountToSwap × 0.997 × erc20TokenAmountBeforeSwap}{ethAmountBeforeSwap + ethAmountToSwap × 0.997} = \frac{ethAmountToSwap × 997 × erc20TokenAmountBeforeSwap}{ethAmountBeforeSwap × 1000 + ethAmountToSwap × 997}$$
- 与 Formalized Model 中的计算公式 $$∆y = (997 * ∆x * y) / (1000 * x + 997 * ∆x)$$ 一致。
- $$10_{ETH} * 500_{OMG} = 5000$$
- $$1 * 997.5 * 500 / (10 * 1000 + 1 * 997.5) = 45.35$$
- $$11_{ETH} * 454.65_{OMG} = 5001.15$$
- 0.3% 的 ETH 作为手续费自动进到了
self.balance
中,成了 LPs 共享的收益。
合约的逻辑使得以下方程得以满足:
$$(x_1 - 0.003 \cdot x_{in}) \cdot y_1 >= x_0 \cdot y_0$$
- 这里描述的的 $$x$$ 兑换 $$y$$ 的;$$x_1$$ 中包含了 $$x_{in}$$。
ERC20 token 换 ETH
|
|
tokens_sold
的 99.7% 被兑换成 ETH,但 100% 的tokens_sold
都进入了self.token.balanceOf(self)
,多出的 0.3% 的 ERC20 token 是由 LPs 共享的收益。
ERC20 token 互换
|
|
- 向 ETH-tokenA 的 exchange 发起 tokenA 兑换 tokenB 的交易。
- 调用了两次
getInputPrice
,收两次手续费。
提供流动性
|
|
移除流动性
|
|
References
- Improving front running resistance of x*y=k market makers
- Uniswap Whitepaper V1
- https://github.com/Uniswap/v1-contracts
- Uniswap Whitepaper V3
- https://github.com/Uniswap/v3-core
- https://www.bilibili.com/video/BV1Qr4y1w7QV/?spm_id_from=333.337.search-card.all.click&vd_source=5a04c0ee9b45b14a43a08bdfe9e00e2c
- https://www.bilibili.com/video/BV1RU4y1B7cz/?share_source=copy_web&vd_source=da31e68296661b22b34150fe9fb4e8ae&t=1430
- Binance Academy: Impermanent Loss Explained
- Binance Academy: What Is an Automated Market Maker (AMM)?
- Binance Academy: What is slippage in trading?
- Binance Academy: What Are Flash Loans in DeFi?