2018 年底给大家介绍了 Uniswap V1,一个基于简单数学公式的去中心化交易所(V1 版本介绍文章)。如今 V1 版本已经在以太坊上运行了一载有余,证明了这种数学公式兑换模型的可行性和实用性。2020 年 3 月 23 号,官方发布文章介绍即将问世的 V2 版本。那么 V2 有什么改进和突破呢?就让我们来瞧一瞧(官方博客:Uniswap V2)。
本文主要从技术角度介绍 V2 的一些特性,分析这些新特性可能带来的改进和影响。这些特性包括:ERC20/ERC20 供给池、价格预言机和闪电兑换。其中关于预言机和闪电兑换会做一些的思考,欢迎有识之士来探讨这些问题。对某项特性感兴趣的读者可直接跳到指定章节。
ERC20/ERC20 供给池
V1 版本只能通过 ERC20 和 ETH 建立供给池。如果我们使用 DAI 去兑换 ETH,那就可以直接使用 DAI/ETH 的供给池获得兑换。当我们要进行 DAI 到 USDC 的兑换时,V1 版本是将 DAI 兑换成 ETH,再使用 ETH 去 USDC/ETH 的供给池进行“二次”兑换,最终完成 USDC 到 DAI 的整个兑换过程。
DAI to USDCV2 的供给池,可以使用任意两种 ERC20 代币构成。这样做的一个好处是可以降低兑换汇率的滑点,因为每个供给池都会收取一定的费用作为兑换手续费,通过两个供给池兑换那就是两倍的费用。V2 对 ERC20/ERC20 供给池的支持,使 DAI 兑换 USDC 的时候不再需要向两个供给池进行兑换,减少了一半的费用,兑换汇率滑点也会更低。
如果两种 ERC20 Token 之间没有直接的供给池,V2 的路由协议可以在多个供给池之间找到一条优化的兑换路径,在多个供应池之间完成兑换。为了实现 A 到 D 的兑换,可以通过 A 兑换到 B,B 兑换到 C,C 兑换到 D 来完成。
目前代码中的路由协议是 01 版本,需要在链下计算好路径提交给路由协议进行处理。
价格预言机
随着 DeFi 应用的兴起,预言机变得越来越重要,区块链应用对预言机的依赖和要求越来越高。
对预言机感兴趣的读者可以阅读上一篇文章,专门介绍了以太坊上最大的预言机项目 Chainlink(Chainlink 链接区块和“万物”)。
但在预言机的发展和探索道路上,可谓事故频发,造成的经济损失不计其数。早有 Synthetix 由于预言机的错误喂价导致 3500 万的 sETH 损失;最近的 bZx 闪电贷套利事件,也是由于平台使用了 Uniswap 作为价格预言机造成了经济损失。
bZx 闪电贷事件中,攻击者使用借出的资金对 Uniswap 进行砸盘,导致其价格剧烈变化。此时,使用 Uniswap 作为预言机的平台由于读取了当前砸盘后的价格,出现了巨大的套利空间。套利完成后,攻击者归还在闪电贷中借出的资金,完成交易。而整个交易过程都在一个区块的一个交易中一次性完成,是为“闪电贷”。
可以发现在 bZx 事件中,由于平台使用了 Uniswap 最后时点的执行价格产生了不符合预期的喂价。尽管这个价格在 Uniswap 是真实的,但和其他平台是价格存在很大的偏差。由于闪电贷在一个区块中迅速完成所有的操作,Uniswap 的执行价格没有和其他平台进行套利拉平的机会,可以认为是一个不符合预期的价格。
V2 的改进是历史将价格保存在链上,并加上了时间权重。它的存储方式是在链上保存了一个累积价格,通过使用两个累积价格的差值和时间差,可以计算出一个具有时间权重的平均价格。
我们知道 Uniswap 的价格变动是跟随交易变化的。如果一直没有交易,那么这个价格会是一个固定的值。假设两次交易的间隔 10 秒,第一次交易后产生的价格 P1 会持续存在,直到第二次交易的发生(10 秒后)才变为 P2。因此 P1 的累积值就是 P1 * 10
。累积价格(priceCumulative)即价格和时间差的乘积。在无数次的价格变动中,其中每次的时间间隔分别是 T1、T2、T3...,就有:
priceCumulative = P1 * T1 + P2 * T2 + P3 * T3 + ...
有了累积价格,使用累积价格除以时间就可以得到一个基于时间权重的平均价格。
具体实现如下图:
cumulative区块 122,供给池被创建后累积价格(priceCumulative)初始值为 0,此时只是发生了交易,产生了一个截止价格,而累积价格并未产生。
区块 123 的中发生的第一笔交易会更新累积价格,区块 123 和上一个区块的时间差为 7 秒,因此累积价格就是 10.2 * 7,即 71.4。
区块 124 和上一次区块的时间差为 8 秒,使用上一次的截止价格计算的累积值为 10.3 * 8,即 82.4,加上之前的累积值即为 153.8。计算过程以此类推。
当我们知道每个区块的累积价格时,可以通过公式获得任意时间范围内的,带有时间权重的平均价格:
时间权重的平均价格 = (当前累积价格 - 上一次累积价格)/(当前时间戳 - 上一次时间戳)
计算过程中,累积价格包含了上一次交易区块中发生的截止价格,但不会将当前区块中的最新截止价格计算进去,这个计算要等到后续区块的交易发生时进行。因此累积价格永远都比当前区块的最新价格(执行价格)慢那么一个区块。由于慢了一个区块,闪电贷在同一个区块里进行的砸盘价格就不能立即生效。当恶意砸盘发生时,不会影响当前的预言机价格,但是执行价格会立即降低,发现价格变动的套利者会在下一个区块将价格缺口补平。采用这样的机制,使预言机具备了防范闪电贷中恶意砸盘行为的能力。同时,恶意砸盘产生的价格会被套利者发现并迅速补平缺口,由于快速的套利会使砸盘价格存在的时间权重较低,也能极大的提高预言机的准确性。
闪电兑换
也许是得益于闪电贷的启发,V2 版本也将提供闪电兑换的功能。该功能同闪电贷异曲同工,无需任何抵押(空手套白狼),就可以借出 Uniswap 供给池中的 Token,这些 Token 用于“闪电”业务,只要在业务处理完成后,将 Token 即刻归还,就可以完成一笔闪电兑换。
V2 的闪电兑换有一个特点,归还的时候支持使用供给池中的两种不同的 Token。
V2 核心合约 Pair (即供给池)的 swap 函数中实现了 calldata 调用,并且可以让用户先兑后还。假设有一个支持 DAI/ETH 的 Pair(供给池),一开始 ETH 会从 Pair 借出到外部套利合约,然后 Pair 会去调用套利合约实现的 uniswapV2Call 接口。uniswapV2Call 中可以完成一系列的“闪电”业务,之后 uniswapV2Call 再将相应的 ETH 或者 DAI 返还给 Pair。Pair 对 uniswapV2Call 调用结束后,会进行最终的账目核对。如果 Pair 没有收到足够的 ETH 或者 DAI,那么整个交易都将回滚。因此对于套利者,借出一笔 ETH 后,必须在该原子交易结束前再将 ETH 或 DAI 返还(并付上 0.3% 的费率),才能保证整个闪电兑换的成功。
flash swap反观最近发生的 bZx 事件,它可能不算是一种攻击,而是多种 DeFi 金融工具结合涌现出的一种“平仓”操作。这样的操作或许会使价值更接近本质。区块链上的价值,会以自动化算法为驱动,在整个区块链网络中以更加迅速的方式流动,bZx 的闪电贷就是一种很好的体现,在一个原子交易中抹平价值和信息的差距。
闪电贷、闪电兑换应该会成为一种常态,拥有专业能力的人,在没有资本的前提下,亦可以捕获价值信息的不对称,从价值转化中获取利益。在传统领域,这必须是具有庞大资本的机构才能完成的操作。
结语
Uniswap 上线之初,就不是一个能使项目方自己赚得金银满钵的项目,他的供给池是由无数的个人用户组成。只要你拥有 ETH 和 token 既可以存储在供给池中获利。通过简单的算法,供给池在交易的过程中持续的增长,最终这些收益又回馈到供给池的提供者们身上。它以低廉的成本,通过区块链完成了一种自组织、盈利和分配的机制,这种机制不会使垄断机构获取暴利,而是按照每个人所提供的资本进行平等分配,是一种真正透明、公正可持续化的机制。
在整个去中心化组织的发展历程中,由于机制的先进性和早期的不完善,不免产生各种新的问题,甚至造成巨大的经济损失。Uniswap V1 作为预言机存在一定的问题,但从 V2 的升级中我们可以看到机制的进一步完善,使之前的问题被化解。同时,闪电兑换的创新,开放了Uniswap 的供给池,为那些缺乏资本拥有能力的专业人士创造了机会。通过这些持续不断的创造和改进,自组织形式在快速的发展和完善。
网友评论