我正在参与「掘金启航方案」

引言

Uniswap协议是一个用来在以太坊区块链上买卖加密钱银(ERC-20代币)的点对合约体系。这个协议经过一个持久化、不行更改的智能合约集合来完成,旨在优先考虑抗审查性、安全性、自我监管, 以及在没有任何或许有挑选地约束访问的可信中介的状况下运转。简单点说就是经过智能合约完成了一个去中心化的ERC-20代币的主动买卖体系。V2版本依据稳定乘积公式的主动做市商(AMM)买卖机制, 由于v2一切的买卖pair悉数放在一个买卖池中进行办理,不便于精细化的活动性办理,一起依据稳定乘积公式的主动做市商(AMM)买卖机制存在资金运用功率低的问题,uniswap团队,2020年5月推出 v2之后的一年后,推出的v3,供给会集活动性机制,供给资金的运用功率,一起增强的oralce,用户不必依据历史区块的价格信息自己核算价格,运用合约的oracle功用,就能够获取依据TWAP的几许算法(v2为算术均匀数)价格,今日咱们一起来看一下v3新特性及相应合约功用架构。

目录

  • 新特性
  • 架构改变
    • ORACLE UPGRADES
  • uniswap体会
  • 会集活动性完成
  • v3合约架构
    • v3-core
    • v3-periphery
  • 总结

新特性

  • 会集活动性:会集活动性进步资金的运用功率,进步流程,防止相似V2资金池中的买卖对,出现极端的状况,导致池活动性见底; 指定报价区间,及区间步长;活动性供给者能够供给一个果断的价格区间;
  • 灵敏的费用:0.05%, 0.30%, and 1%. 活动池创立者,能够指定费用,一起UNI governance能够增加其他的费用到费用集;
  • Improved Price Oracle:供给用户查询最近价格,不依赖与TWAP( time-weighted average price (TWAP))的checkpoint值;
  • Liquidity Oracle:供给依据时刻的均匀活动性预言机合约;

架构改变

  • 多活动池方式,每个买卖对能够一个池,也能够多个买卖对多个池;V2一切的买卖对都在一个池;
  • 买卖token不在单单支撑ERC20, 拓宽至非同质化token; 在Uniswap periphery创立买卖池,能够对ERC20进行包装;
  • governance:每个池有一个owner,能够支撑tick space,一起能够设置没有个tick的fee,一旦设置不行改变;
  • price oracle升级;

ORACLE UPGRADES

v2用户假如需求核算某个period的TWAP,需求追寻从period开端到完毕的checkpoint,V3中不在需求追寻检查点, 能够获取最近period的TWAP,V3会log这些price的checkpoint,答应用户核算TWAP算术均匀值;

Oracle Observations:在v2只会保存最近区块的价格检查点,用户需求机制拉取曾经区块的价格点进行统计。v3中,一切的价格点将会保存一个环形价格检查点中, ,环形中最大能够容纳65,536 checkpoints,当新的检查点发生时,环形中的检查点没有slot,则老的slot的将会被覆盖;

Geometric Mean Price Oracle:V2中,买卖对的token是独自跟踪的,没有关联性,V3将会依据买卖对的在tick中随时刻的token price ratio,核算相应的TWAP;

Liquidity Orace:v3一起每个区块依据秒级的seconds-weighted accumulator, 用于分配活动性奖赏;

uniswap体会

买卖池,咱们以ETH和USDT为例,进入买卖池界面

以太坊的黑丝袜UniswapV3

点击增加活动性,将会跳到增加活动性页面,点击买卖进入swap操作界面

  • 增加活动性

以太坊的黑丝袜UniswapV3
挑选买卖池关联token, 咱们挑选为eth和swap,并挑选活动性价格区间(兑换率)

  • 买卖操作(swap)

以太坊的黑丝袜UniswapV3
输入给定的eth,依据当时买卖池价格swap出相应的USDT。兑换时,前端将会拉取当时买卖池的最优买卖价格(oracle的TWAP),进行swap操作。

  • 买卖列表

以太坊的黑丝袜UniswapV3

会集活动性完成

咱们先来看一下v2的AMM DEX曲线,为下图中的绿色部分。

以太坊的黑丝袜UniswapV3

在uniswap v2,活动性价格能够无限大,当价格趋向于曲线两头的无穷大是,活动性将会削减,没有人愿意运用超越的价格,swap出token,这将导致这个 买卖池的资金运用率不高,为了改进这种状况,v3,将答应用户增加给定价格区间的活动性,如上图中的黄线部分。这样整个买卖池的活动活动性散布将会 如图:

以太坊的黑丝袜UniswapV3

供给不同深度的活动性,供给资金的运用功率;用户自己能够恣意价格区间的活动性,将会存在精度问题:

价格精度问题 由于用户能够在恣意 [P0,P1] 价格区间内供给活动性,Uniswap v3 需求保存每一个用户供给活动性的鸿沟价格,即 P0 和 P1。这样就引入了一个新的问题,假设两个用户供给的活动性价格下限别离是 5.00000001 和 5.00000002,那么 Uniswap 需求标记价格为 5.00000001 和 5.00000002 的对应的活动性巨细。一起当买卖发生时,需求将 [5.00000001,5.00000002] 作为一个独自的价格区间进行核算。这样会导致:

几乎很难有两个活动性设置相同的价格鸿沟,这样会导致耗费很多合约存储空间保存这些状况, 当进行买卖核算时,价格改变被切分红很多个小的规模区间,需求逐个分段进行核算,这会耗费很多的 gas,并且假如规模的价差太小,或许会引发核算精度的问题, Uniswap v3 处理这个问题的方法是,将 [Pmin,Pmax] 这一段连续的价格规模为,切割成有限个离散的价格点。每一个价格对应一个 tick,用户在设置活动性的价格区间时,只能挑选这些离散的价格点中的某一个作为活动性的鸿沟价格。

Uniswap v3 采用了等比数列的方式确认价格数列,公比为 1.0001。即下一个价格点为当时价格点的 100.01%;如此一来 Uniswap v3 能够供给比较细粒度的价格挑选规模(每个可选价格之间的差值为 0.01%),一起又能够将核算的复杂度控制在一定规模内。

v3中心思路

  1. 将活动池的tick化,每个tick粒度,默认为0.01;pool将会追寻没有tick的每秒的sqrt价格;在初始化时,tick没有暂用的状况下,能够初始化;
  2. pool初始化时,会设置tickSpacing,只有tickSpacing答应的规模内,才能增加到pool中,比方假如tickSpacing设为2,则(…-4, -2, 0, 2, 4…)方式的tick才能够初始化,用户增加活动性, 只能增加tick规矩答应的价格区间;
  3. 为了确保正确数量的活动性的参加和退出,pool合约将会追寻pool的大局状况,每个tick及每个方位的状况;

Global State

| Type | Variable Name | Notation |
| —- | —- |
| uint128 | liquidity | |
| uint160 | sqrtPriceX96| sqrt() |
| int24 | tick | |
| uint256 | feeGrowthGlobal0X128| ,0 |
| uint256 | feeGrowthGlobal1X128 | ,1 |
| uint128 | protocolFees.token0 | ,0 |
| uint128 | protocolFees.token1 | ,1 |

pair(token x, token y) :
L=sqrt(xy);     
sqrt(p)=sqrt(y/x);    
x=L/sqrt(p);    
y=L/sqrt(p);    
tick(ic)= log(sqrt[basePrice]^sqrt[p]);

咱们运用L和sqrt(p)跟踪活动性,首要是由于在每个tick,任何时刻swap的发生,将会导致sqrt(p)的变动;

[,0/,1]为swap的大局token0, token1费用, 收费时,以(0.0001%)为基点进行收费;

[,0/,1]为协议token0, token1费用,具体到买卖池;

Tick-Indexed State

| Type | Variable Name | Notation |
| —- | —- |
| int128 | liquidityNet | |
| uint128 | liquidityGross | |
| uint256 | feeGrowthOutside0X128 | ,0 |
| uint256 | feeGrowthOutside1X128 | ,1 |
| uint256 | secondsOutside | |
| uint256 | tickCumulativeOutside | |
| uint256 | secondsPerLiquidityOutsideX128 | o |

liquidityNet():每个tick内的活动性; liquidityGross():用于判断当活动性不在给定的规模内时,是否需求更新ticks bitMap; [,0/,1]:用于追寻token0, token1在给你定规模外的fee; secondsOutside, tickCumulativeOutside,secondsPerLiquidityOutsideX128:用于核算合约外部的更细粒度的收益;

Position-Indexed State

| Type | Variable Name | Notation |
| —- | —- |
| uint128 | liquidity | |
| uint256 | feeGrowthInside0LastX128 | ,0 (0) |
| uint256 | feeGrowthInside1LastX128 | ,1 (0) |

liquidity (): 用于表明前次方位点的虚拟活动性; [,0 (0) / ,1 (0)]:用于核算token0, token1的uncollected fees;

处理会集活动性,触及每个tick内的买卖fee,现已跨tick的买卖费用,比方或许大于tick的上限,也或许小于tick的下限,或许不在整个tick的bit map规模之内,需求核算相应的费用; 针对虚拟活动性,有些活动性不能反映从合约创立时的fee,咱们称为uncollected fees, 咱们经过Position-Indexed State能够核算相应的uncollected fees。

v3合约架构

以太坊的黑丝袜UniswapV3

v3合约作最重要的两个模块买卖池中心v3-core和外围的swap路由模块v3-periphery

v3-core

供给买卖池的创立,买卖相关的中心操作,比方增加活动mint,swap操作等,办理价格tick map,用户的方位信息,买卖池状况,及oralce, 首要有以下几个合约:

  • IUniswapV3PoolImmutables:买卖池常量,比方:工厂地址、买卖pair, token0,token1的地址,及tickspacing和每个池的最大活动性;
  • IUniswapV3PoolState:用户记载买卖池的状况,比方tick的费用信息,以及tick的oracle追寻信息(observations);
  • IUniswapV3PoolActions:首要用于初始化买卖池,供给与买卖中心操作,比方mint,burn,swap,flash等操作以及记载买卖池快照信息increaseObservationCardinalityNext;
  • IUniswapV3PoolOwnerActions:供给设置买卖协议费用和搜集协议费用
  • IUniswapV3Factory:创立买卖池(买卖池token pair,及tick买卖费用);
  • UniswapV3Pool:供给mint,burn,swap,flash,及collect(毁掉活动性之后提取自己财物及fee收益)等中心完成,别的还有oralce的调查点记载; Oracle供给的价格信息,能够体用第三方DEX,进行清算;

UniswapV3Pool维护者买卖者池的状况Slot0, 当时活动性,token0和token1的当时累计费用,tick信息,tick bitMap信息,用户活动性方位信息,及oralce调查点信息;

  1. 买卖者池的状况Slot0:首要有当时价格sqrt(x*y),tick,最近调查点索引,当时存储调查点数量,下次需求存储的调查点索引,协议费用以及买卖池是否锁住;
  2. tick信息: 维护每个tick的信息,首要有当时tick活动性,活动性网格数量,tick规模外的token0和token1的fee,相对于当时tick外的每个活动性单元运转时刻seconds,当时tick外的花费总时刻seconds;
  3. tick bitMap信息:每个tick的状况等信息;
  4. 用户活动性方位信息:用户在tick上线限之间的活动,token0和token1收益, 及活动性fee

以太坊的黑丝袜UniswapV3

每个买卖池依据token0和token1的地址及买卖费fee来创立,相同token0和token1,fee不同的,则会重建一个新的买卖池;在同一个买卖池,不同的用户能够增加自己的活动性价格区间方位,每个买卖池 会将一切的用户方位价格区间别离以tick进行切割,买卖池的活动一切的ticks运用TickBitMap进行办理;用户swap时将会依据用户的约束价格和买卖池slot0状况价格,从买卖池的TickBitMap中筛选出最优的tick的活动区间进行swap,假如tick的活动性区间属于某个用户,则将买卖费直接给相应的用户,否则将费用均匀分配给覆盖tick的方位的用户(???),并更新用户的方位费用信息。

如上图所示在同一个买卖池内,用户A增加价格区间方位活动性Pab,活动性为400;用户B增加增加价格区间方位活动性Pcd,活动性为300; 在tick1到tick4(Pa-Pc)区间活动为用户A增加的活动性为400,在tick4到tick5(Pc-Pb)区间活动性为用户A,用户B活动性的叠加为700,在tick5-tick7(Pb-Pd)区间活动性为用户B供给的活动性为300;

v3-periphery

供给swap相关的路由操作,并在没有swap相应的依据用户方位信息的NFT,假如mint操作的买卖池不存在,则创立相应的买卖池;首要有几个合约

  • NonfungiblePositionManager:非同质方位办理器,供给活动mint,增加,削减操作,以及收益费用的搜集;在mint活动性时,一起会创立依据方位的NFT;
  • NonfungibleTokenPositionDescriptor:供给生成方位NFT描绘URL;
  • SwapRouter: swap操作:依据输入token,swap出尽或许大的另一个token;swap评价操作:依据输入的token数量,需求输入的最小别的一个token的数量,并付出相应的费用到收费账户;

针对用户swap的tokenIn和tokenOut买卖池不存在时,uniswap前端将会生成相应的途径,托付给SwapRouter进行swap操作; 多途径的的状况编码为:token0+fee01+token1+fee12+token2+fee23+token3+fee34+token4+…, 这种是针对swap是假如没有对应的买卖对pair,则从不同的 买卖池进行swap, 比方运用token0,想swap token3,整个swap的途径为(token0+fee01+token1,token1+fee12+token2,token2+fee23+token3),运用token0从 pool01中swap出token1,运用swap出的token1从pool12中swap出token2, 运用swap出的token2从pool23中swap出token3; 具体途径编码如下:

以太坊的黑丝袜UniswapV3

  • V3Migrator: 从V2活动性,搬迁到V3,能够指定搬迁活动性百分比,没有搬迁的将会退回给;

合约东西库

  1. Path:买卖池途径东西,途径实践编码为token0地址+fee+token1地址 ;
  2. PoolAddress:买卖池地址东西,依据买卖池key,包含token0地址,token1地址,fee,生成买卖池地址;
  3. PeripheryPaymentsWithFee:供给带续费费用的付出,支撑eth和token;
  4. PeripheryPayments:供给付出操作,支撑eth和token;
  5. Multicall:批量调用代理合约;

总结

uniswapV3首要是处理uniswapV2依据常量的AMM极端状况下的活动性不足的问题,提出依据tick的会集流程性,一起参加的买卖池的概念;v2中一切的买卖对在一个池中,v3能够自己运用买卖pair,创立买卖池池,自己设置买卖费用,及活动性tick区间;并改进的oracle,用户不必自己 核算依据TWAP( time-weighted average price (TWAP)),运用合约获取最近的period的TWAP,并答应用户核算TWAP算术均匀值;

处理会集活动性,触及每个tick内的买卖fee,现已跨tick的买卖费用,比方或许大于tick的上限,也或许小于tick的下限,或许不在整个tick的bit map规模之内,需求核算相应的费用。 V3经过 Global State和Tick-Indexed State来处理这些问题;

针对虚拟活动性,有些活动性不能反映从合约创立时的fee,咱们称为uncollected fees, V3经过Position-Indexed State能够核算相应的uncollected fees。

v3-core供给买卖池的创立,买卖相关的中心操作,比方增加活动mint,swap操作等,办理价格tick map,用户的方位信息,买卖池状况,及oralce;

v3-periphery供给swap相关的路由操作,并在没有swap相应的依据用户方位信息的NFT,假如mint操作的买卖池不存在,则创立相应的买卖池。 UniswapV3Pool维护者买卖者池的状况Slot0, 当时活动性,token0和token1的当时累计费用,tick信息,tick bitMap信息,用户活动性方位信息,及oralce调查点信息;

  1. 买卖者池的状况Slot0:首要有当时价格sqrt(x*y),tick,最近调查点索引,当时存储调查点数量,下次需求存储的调查点索引,协议费用以及买卖池是否锁住;
  2. tick信息: 维护每个tick的信息,首要有当时tick活动性,活动性网格数量,tick规模外的token0和token1的fee,相对于当时tick外的每个活动性单元运转时刻seconds,当时tick外的花费总时刻seconds;
  3. tick bitMap信息:每个tick的状况等信息;
  4. 用户活动性方位信息:用户在tick上线限之间的活动,token0和token1收益, 及活动性fee

每个买卖池依据token0和token1的地址及买卖费fee来创立,相同token0和token1,fee不同的,则会重建一个新的买卖池;在同一个买卖池,不同的用户能够增加自己的活动性价格区间方位,每个买卖池 会将一切的用户方位价格区间别离以tick进行切割,买卖池的活动一切的ticks运用TickBitMap进行办理;用户swap时将会用户的约束价格和买卖池slot0状况价格,从买卖池的TickBitMap中筛选出最优的tick的活动区间进行swap,假如tick的活动性区间属于某个用户,则将买卖费直接给相应的用户,否则将费用均匀分配给覆盖tick的方位的用户(???),并更新用户的方位费用信息。

针对用户swap的tokenIn和tokenOut买卖池不存在时,uniswap前端将会生成相应的途径,托付给SwapRouter进行swap操作;

多途径的的状况编码为:token0+fee01+token1+fee12+token2+fee23+token3+fee34+token4+…, 这种是针对swap是假如没有对应的买卖池,则从不同的 买卖池进行swap, 比方运用token0,想swap token3,整个swap的途径为(token0+fee01+token1,token1+fee12+token2,token2+fee23+token3),运用token0从 pool01中swap出token1,运用swap出的token1从pool12中swap出token2, 运用swap出的token2从pool23中swap出token3;

uniswap pools
Uniswap v2-core
Uniswap v2-periphery
Uniswap lib
一文看懂Uniswap和Sushiswap
Uniswap深度科普
去中心化买卖所:Uniswap v2白皮书中文版
Uniswap v3 规划详解
Uniswap V3 到底是什么鬼?一文带你了解V3新特性
Uniswap v3 详解(一):规划原理 uniswap – V3源代码导读 Uniswap V3 白皮书 uniswap-v3 blog jit-liquidity
graphical-guide-for-understanding-uniswap
什么是DeFi中的闪电贷?