Uniswap学习

uniswap v2

uniswap 的交互流程

比如Alice想要把tokenA兑换成tokenB,与合约的交互流程大体如下:

  1. Approve:Alice批准uniswap使用tokenA合约的金额
  2. Swap:Alice调用uniswap进行兑换
    1. 把Alice的tokenA转给LP
    2. 把LP的tokenB转给Alice

还有一种情况是Bob使用ETH兑换SHIB(用eth兑换token),流程如下:
  1. Bob调用uniswap进行swap,并把ETH转给Uniswap合约
  2. uniswap把收到的ETH转给WETH合约,并且uniswap获得了相同金额的WETH(这一步是把ETH兑换成符合ERC20标准的WETH)
  3. uniswap调用WETH合约把相同金额的WETH转给ETH-SHIB-LP(流动池)
  4. ETH-SHIB-LP调用SHIB合约把相应金额的SHIB转给Bob

![image-20210514162529644](/Users/apple/Library/Application Support/typora-user-images/image-20210514162529644.png)

uniswap v2的的LP是如何赚钱的?年化多少?是否稳定?

  • 收益来自于交易,如果没有交易则LP无法赚钱,不稳定

他们标得APY是如何计算的?

uniswap v2的一些资源

info.uniswap可以根据合约搜索token的数据

一些细节问题

路径上的每次计算都要收取手续费

如果我想要用tokenA换tokenC,但是LP中只有tokenA-tokenB和tokenB-tokenC,因此在兑换路径会变成tokenA->tokenB->tokenC。在使用这样的路径兑换时tokenA->tokenB和tokenB->tokenC都会收取手续费(千分之3)

手续费每次都是收取前面的token的千分之3,如上面例子的兑换路径会收取tokenA和tokenB的千分之3

新建流动性是有最小流动性限制的

如果当前LP池中没有tokenA-tokenZ交易对,那么在第一次创建这个交易对时是需要满足tokenA

Liquidity Providers在提供了流动性之后得到的是什么

会得到交易对对应的ERC20的份额

无常损失:

因为价格变动导致添加到LP中的资产的价格少于不提供流动性的价格。

部分代码理解

swap时,根据输入tokenA的值获取应该兑换的tokenB的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
// x * y = x' * y' = k; x = reserveIn, y = reserveOut
// x‘ = amountIn的千分之997
uint amountInWithFee = amountIn.mul(997);
// numerator = x' * y
uint numerator = amountInWithFee.mul(reserveOut);
// denominator = x + x'
uint denominator = reserveIn.mul(1000).add(amountInWithFee);
// amountOut = (x' * y) / (x + x');推导公式如下:
// (x + x') * (y - y') = x * y
// y - y' = x * y / (x + x')
// y' = y - x * y / (x + x')
// y' = (y(x + x') - x * y) / (x + x')
// y' = (y * x + y * x' - x * y) / x + x'
// y' = (y * x') / (x + x')
// amountOut = (x' * y) / (x + x')
amountOut = numerator / denominator;
}

uniswap中的其他技术学习

Canonical WETH

什么是WETH,原文内容总结如下:

  1. ETH是以太坊上的本地代币,而不是ERC20标准代币
  2. 因此在DApp操作符合ERC20规范的代币时,如果涉及到了ETH操作起来会比较麻烦
  3. 为了方便,DApp的开发者做了符合ERC20标准的代币来代替ETH
  4. WETH是目前比较安全和社区支持较高的ERC20标准的ETH代币
  5. mainnet合约地址

Uniswap V3

存入资金池的数量和兑换的价格是不一样的

如下图,当前ETH的价格是3942.1,如果加入资金池的比例是1个ETH对应1953.42个USDT。

审核

trailofbits在审核uniswap时考虑了什么方面:

  • 代码是否遵循最佳实践
  • 单元测试覆盖率
  • 白皮书的完成程度,以及白皮书中的内容是否有错误
  • 访问控制
  • 算数运算
  • 代码结构
  • 可升级性
  • 验证和测试

限价单

审核时提到的一些技术或工具

UniswapV2和V3版本比较

  1. V3版本增加了“集中流动性”概念,LP可以只在一定的价格范围内提供流动性
    1. 这样可以避免太多的无常损失
    2. 可以提高资金利用率
  2. V3版本的交易费用不再重新复投到LP池中,需要LP提供者手动“收割”
  3. V3版本支持单一资产存入LP池,条件是设置的价格范围不在当前的市场价格范围内;(这样可以允许你设置一个期望的价格来达成交易,如下图的限价单,你可以在价格为3987.2时指定在4498~4460之间提供流动性,这样在价格到达这个范围时就会把ETH兑换成DAI)
    1. 这是一个好用的功能,但是你必须密切注意价格,如果你想要DAI则需要在到达这个区间时手动退出,即不再提供流动性

限价单