Keegan小钢

Posted on Nov 22, 2023Read on Mirror.xyz

剖析DeFi交易产品之UniswapV4:概述篇

UniswapV4UniswapV3 相比,算法上并没有什么改变,依然还是采用集中流动性模型,但架构上变化很大,包括功能架构,也包括技术架构。相比之前的版本,UniswapV4 最大的创新主要包括四点:

  1. 引入 Hooks

  2. 改用单例模式

  3. 采用闪电记账

  4. 支持原生 ETH

Hooks

引入 Hooks 机制是最核心的变动点,也大大扩展了其灵活性,使得定制化池成为了可能。

Hooks 本质上就是一个定制化的合约,当初始化一个交易池的时候,需要指定该池子所用的 Hooks 合约地址。Hooks 合约需要实现一系列回调函数:

  • beforeInitialize / afterInitialize

  • beforeModifyPosition / afterModifyPosition

  • beforeSwap / afterSwap

  • beforeDonate / afterDonate

其实就是分别在 initialize、modifyPosition、swap、donate 这几个关键操作执行前和执行后都可以添加自定义逻辑。

以 swap 操作为例,加上 Hooks 的 swap 流程如下图所示:

其他操作流程也是同理。

V4 的白皮书中有列举出了可以使用 Hooks 实现的一些示例功能:

  • 通过 TWAMM 随时间执行大额订单

  • 按指定价格成交的链上限价单

  • 随波动率变化的动态费用

  • 为流动性提供者内化 MEV 的机制

  • 中位数、截断或其他自定义预言机实现

目前,UniswapV4 官方也已经提供了几个参考实现,包括 TWAMM、LimitOrder、FullRange、VolatilityOracle、GeomeanOracle。之后的文章我们会一一剖析讲解这几个示例实现。

Hooks 除了可以实现这些功能之外,还可以管理池的 swap 费用,以及还可以向流动性提供者收取提款费用。

对于费用的管理,不只是可以设置为静态费用,还可以设置为动态费用。支持动态费用的话,那就可以实现和中心化交易所一样,按用户的不同等级设置不同的费率。还可以把费用分配给不同的人,比如添加邀请分佣机制,手续费部分分配给邀请人。

总而言之,Hooks 大大提高了 Uniswap 的可扩展性。

单例和闪电记账

Uniswap 以前的版本,每个池子都是单独的合约,是通过工厂合约来创建每个池子合约的。而 UniswapV4 改为了使用单例模式,所有池子全都由单个合约进行管理,即 PoolManager 合约进行统一管理。

使用单例模式,那新建池子时,就不再需要部署新合约实例,可以大大降低创建池子的成本。

另外,单例模式还结合了另一个机制叫闪电记账,以及结合使用了 EIP-1153 中提议的瞬态存储操作码。EIP-1153 会在坎昆升级中支持,这就是 UniswapV4 到目前还没有发布上线的主要原因,在等坎昆升级完成。

在以前的版本中,每次交易都需要计算所有相关仓位的余额,尤其涉及跨池交易,还需要在多个池子间多次执行 transfer,交易成本其实挺高的。而闪电记账机制,每个操作前会先做一个锁定,锁定期间只会更新一个称为 delta 的内部净余额,仅在锁定结束时才进行外部转账,这就大大节省了交易成本。

不过,在当前执行环境中,闪电记账架构其实是挺昂贵的,因为需要在每次余额变化时进行存储更新。但是,由于余额必须在事务结束时为 0,因此可以使用瞬态存储实现对这些余额的记账,从而减少 gas 消耗。

瞬态存储操作码是专门用来解决区块内部通讯的解决方案。瞬态存储不改变现有操作的语义,瞬态存储的数据在每次交易后会被丢弃,不会访问服务器磁盘,使用后也无需清除存储槽,客户端也不需要加载原始数据。因此,相对来说,使用瞬态存储解决区块内部之间通讯问题的优势在于 Gas 较低,且未来的以太坊数据存储设计中不需要考虑因临时存储而产生的操作费用退费的情况。

简而言之,使用瞬态存储,可以用低 gas 解决临时存储的问题。

原生 ETH 和其他

支持原生 ETH 是说,在底层池子里就支持原生 ETH 和其他代币之间的直接交易。

其实在 UniswapV1 版本也是支持原生 ETH 的,但那时候的池子严格限制了只能是 ETH 和另一个 ERC20 代币配对组成的,ERC20 代币之间是通过跨池交易的。但从 UniswapV2 开始,支持任意 ERC20 代币配对,但由于实施的复杂性,以及在 WETH 和 ETH 配对之间的流动性碎片化的担忧,底层池子统一只支持 ERC20 代币,只在上层合约里实现 ETH 和 WETH 的自动互换。增加了 ETH 和 WETH 互换的逻辑,其实增加了交易成本。如果只用原生 ETH 转账的话,gas 成本只约为 ERC20 转账的一半(ETH 为 21k gas,ERC20 约为 40k gas)。

现在,UniswapV4 因为使用了单例和闪电记账模式,又能很好地支持原生 ETH 了,而且还允许同时支持 ETH 和 WETH 的配对。

UniswapV4 还引入了 ERC1155 代币用于额外的代币记账。用户可以将代币保留在单例合约中,避免 ERC20 频繁转入和转出合约。这一点对于频繁交易者或流动性提供者非常有价值,因为他们会在多个区块或交易中连续使用相同的代币。

引入了 Hooks 机制之后,像 UniswapV2 和 UniswapV3 内嵌的价格预言机也变得不再必要了,因此,在 PoolManager 中再见不到价格预言机相关的数据存储和逻辑处理了。因为预言机可以通过 Hooks 合约定制化实现了。

donate() 函数是 V4 新增的操作,允许用户、集成者和 Hooks 直接支付给特定范围内的流动性提供者,支付的方式可以是池中的任意一种或两种代币。

总结一下,UniswapV4 算法上并没有改变,依然还是采用集中流动性,但通过 Hooks 实现了可定制的池,单例合约和闪电记账大幅度降低了 gas 成本,对原生 ETH 的支持也同样减少了 gas,还有对动态费用的支持、ERC1155 的支持等,都大大提高了 Uniswap 的灵活性、可扩展性。