Uniswap V4 发布,这次又更新了个啥 ?
6月13号,Uniswap Labs,也就是Uniswap团队发布了Uniswap V4版本,并在推特和官网Blog(https://blog.uniswap.org/uniswap-v4)上进行了宣发。
Uniswap 是当前TVL 最高的Dex,目前总的协议的tvl 高达(3.88billions) ,约占整个Defi整体tvl中的9%(一个非常高的比例]。目前整个Defi中的tvl大概为43.14billions (数据来源于defillama.com)。
而从Uniswap 发布以来,总的交易量可以达到超过1.5 trillion
如果与国家比较,这个数字相当于2021年澳大利亚的全年GDP
如果与Crypto行业比较,这个数字比BTC在2021.11月的FDV($65000*18.89millions)还要高
与大企业相比,相当于最近最火的NVIDIA(刚刚突破万亿美元),的1.5倍
所以,Uniswap的每次发布,每次更新,都是一个非常"震惊"的消息。
Uniswap团队在Blog中的介绍中说,这次发了一些新的一些特点,比如Hooks,TWAMM 计价模型,单例合约,闪电记账,链上限价单,Gas 优化等等,下面也会逐步介绍这些新的功能。
1. Uniswap协议的更新进程与当前面临的问题
首先来细数一下Uniswap 协议发展的整个进程
2018.11.2号 Uniswap V1 发布,支持任意ERC20 和ETH直接组成池子,进行swap
2020.5月 Uniswap V2 发布,支持了任意的ERC20直接组成交易对(CPMM constant product market maker s)
2021.5.5日,Uniswap V3发布,引入了流动性区间的概念,使用集中流动性,和费率等级(fee tier)增强了资金的使用效率
虽然V3的一个流动性区间和费率等级增加了LP的灵活性 ,并不足以支持AMMs和市场演变所发明的新功能。
比如
从V2引入的价格Oracle,允许整合优化链上价格数据,但同时也增加了Swap的gas 消耗。
TWAP效率不够高,使用新的TWAMM增强价格Oracle使用的效率。
新的功能(限价单,动态费率)无法直接整合到V3中。
之前的版本,每次创造新池子都需要部署新的合约,在多个Uniswap池进行交易涉及到在多个合约之间进行转移和大量冗余的状态更新。
从V2以来,在Uniswap 中流通的ETH 均为打包好的WETH,而非原生的ETH。
2. V4 hooks
这里的hook的概念有点像在写React前端中用到的钩子,即
组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来。
在V4中实现了可定制化的集中流动性,创建者只需要创建某个自定义函数(钩子)的交易池(组件),在每次与池子(组件)交互的时候,便会自动执行钩子函数。
通过Hook,可以实现这些功能
通过TWAPMM(time-weighted average market maker)来执行大订单,减小滑点
满足价格要求的时候,自动执行链上的限价单
波动性转移动态资金费用
为LP 内部聚合了一个同样的MEV机制
自定义oracle的实现逻辑
Hook的本质是一本合约,在V4-Peryphery代码中中介绍了hook 的一些基本使用方法(https://github.com/Uniswap/v4-periphery)
如何触发hook钩子
Hook的维护是由这个strruct来维护的,当前V4 支持的也是这8个hook
初始化前/初始化后
移动仓位前/移动仓位后
swap交易前/ swap交易后
捐赠前/ 捐赠后
实现一个hook合约,只需要继承 `BaseHook.sol` 合约,然后在自己的合约中,实现对应自己想要在上面的这几个位置实现的逻辑。
这个struct的中的每一个判断都是一个bool值,分别在一笔交易的过程中进行判断。
如下图(来源于V4 白皮书 v4-core/whitepaper-v4-draft.pdf at main · Uniswap/v4-core · GitHub)
用户触发一笔Swap Token的逻辑
判断beforeSwap的Flag
若为true,则执行beforeSwap的hook
若为false, 不执行beforeSwap的钩子
执行swap的逻辑
swap 完成后,判断afterSwapFlag
若为true,则执行afterSwap的钩子
若为false, 则不执行
结束一笔swap的操作
捐赠,其实很简单,用户/ 一个钩子Hook,可以直接向Lp支付一点Token。内部维护的记账系统会记录这个数据,本质就是给Lp 提供一点小费。
通过Hook来管理收费
在V4 中,Swap的手续费(之前为千分之三),现在可以通过动态的方式来管理手续费。
V4 hook 运行可以在池子收到Swap以及退出LP的时候,收取一定的比例的费用。
比如在一个Hook 例子中,可以通过时间的延长,线性拉长手续费收取的比例。
3. Singleton 单例模式
Uniswap 之前的合约例子统为工厂模式,当前V4 版本使用单例模式,即,使用单本合约来管理所有的池子。
那么,所有池子的状态数据,现在都由PoolManager.sol
这一本合约来进行管理,这一方式,可以使每一次创建新池的成本降99% (由部署一本合约的gas, 到执行合约中的一个方法的gas) 。
同样,在多池之间的路由(Route)也是非常消耗gas的,在一本合约中管理这些Token,大大减少了token 从合约间转账的gas 消耗。
4. Flash Accounting 闪电记账
根据单个合约管理的模式, 可想而知,之前每一笔交易都是从合约之间不断转账,花费了大量的gasFee。
而在V4中,每个操作只更新一个合约内部维护的 delta,通过这个delta的记录,那么用户便可以在每次交易的时候,直接更新账本中的数据(更新delta)。
take() 和settle() 是一些新的方法,可以在交易的过程中(lock状态),向池中借出来( delta为正 ),或者向池中存进去(delta 为负)Token。
通过要求在调用结束时,池管理者或调用者不欠任何代币,从而保证了池的偿付能力。
/// used to borow fund from the pool
function take(Currency currency, address to, uint256 amount) external override noDelegateCall onlyByLocker {
_accountDelta(currency, amount.toInt128());
reservesOf[currency] -= amount;
currency.transfer(to, amount);
}
/// @inheritdoc IPoolManager
/// used to deposit fund back to the pool
function settle(Currency currency) external payable override noDelegateCall onlyByLocker returns (uint256 paid) {
uint256 reservesBefore = reservesOf[currency];
reservesOf[currency] = currency.balanceOfSelf();
paid = reservesOf[currency] - reservesBefore;
// subtraction must be safe
_accountDelta(currency, -(paid.toInt128()));
}
5. NativeETH
V4版本,重新把V1中的native ETH 带回来,而不再使用WETH重新做一层包装。
Native ETH 的转账也是比ERC20之间的转账更能够节省一波Gas Fee ( ETH transfer 21000, Token Transfer 40000 )。
我看到当前对CurrencyLibrary.sol
代币操作的代码也做了更新。
6.支持ERC1155的记录
在PoolManager.sol
合约中,也增加了对于ERC1155 合约接受的支持。
每当符合erc1155标准的合约转入到这本合约中,便会自动burn 掉,并在合约中计入这个token的delta 。
8.TWAMM介绍
关于TWAMM的最详细的介绍在Paradigm发的这篇文章中(https://www.paradigm.xyz/2021/07/twamm)
TWAMM的核心就是把一个大的订单分成很多很多小的订单。举个例子 比如说Alice想要把手中 一个亿的USDC变成一个亿的等值的ETH,但是链上池子是其实是不够这么大的。
这个单子一下子就会把池子中的(ETH/USDC)比例变掉,自己却swap不出来等值的ETH。
一个好的方式则是把这么大的单子变成很多很多小单子,一点点交易,可这样又容易被监控池子的MEV进行三明治攻击,而且这么多笔交易,又会因此更多的支付大量的gas Fee。
这个时候,TWAMM就出来了,TWAMM把这个单子变成很多很多小的虚拟订单,即保证单子能够以正常价格执行,又不用支付很多很多笔swap的手续费。
AMM机制与AMM遇到的问题
举个例子,当前ETH价格2000$。
我使用1个ETH 和2000 USDC,放到交易对中做LP,此刻AMM (x * y = k)机制算出我的 k = 2000。
当发生一笔小的swap的时候(10 usdc ),按照价格,可以买到 (10 / 2000 =0.005 ETH ),不考虑手续费,真实换到的是 (1-y)*(2000+10) = 2000 ,即大概0.004975个ETH, 与理想状态差别不大。
可如果来一个稍微大一点的,我想使用2000USDC来购买ETH
最终,我只买到了0.5ETH,合着我的价值直接翻倍,成了4000Usdc/ETH 。
按照市价,我应该买到 1个ETH
而根据AMM机制
( 1-y )(2000 + 2000) = 2000
,y= 0.5传统金融的做法与TWAP
如何我在传统金融(证券交易所)面对这个问题,一笔大订单,直接抛向市场,一定会使此资产买压急剧升高,从而造成我的买入价会变得很高。
所以我想买入一大笔的股票的话,抽取一段时间(Tj求和) ,取得加权平均价格 (Twap)。
比如苹果stock早晨9:30开盘到12点价格为$100,12点到16点价格为 $120,取得TWAP价格为(2.5*100+4*120) /6.5 = 112.3。
则使用这个价格来对应购买苹果股票。
TWAMM的实现
TWAMM 把这样一个大单子,切成很多很多的小单子来在很多块之间执行完成。
比如,我用一个亿的USDC,购买成ETH,在接下来的10000个块中完成这笔交易,那么每个块只需swap 10000USDC,对池子深度的影响并不大。
在每个块执行完成的时候,都会有套利者(Arbitrageur)来进行套利,填平交易对与真实世界资产的价格的间隙。
当10000个块执行完成的时候(大概33个小时),可能拿到一个理想状态的损失 最少的收益。
9.条款使用
在Web3中,所有的代码都是开源的。像Uniswap V3的商业原始许可证( Business Source License ) BSL ,限制了使用(copy)v3 代码 2年。
而这次,对于商业/生产使用的V4代码,限制为4年。