Foresight News

Posted on Jun 14, 2023Read on Mirror.xyz

Web3 青年学者计划 | 基于 AMM 的去中心化预言机设计原理及攻击成本分析

PoS 机制对预言机的安全性造成了很大的不确定性,提高预言机攻击者的操纵成本是主要防御措施之一。

嘉宾:XIN Wan,Uniswap Labs 科学家 整理:aididiaojp.eth,Foresight News

大家好,我是 XIN Wan,现在是一名 Uniswap Labs 研究员,曾做过量化交易领域的课题,再之前做过衍生品交易。今天的话题相对比较学术,我尽可能多做一些背景介绍。

首先什么是 Uniswap?简单来说就是在链上可以交易任何两种加密货币或者凭证的平台,可以理解为是一个线上纽交所或者类似市场。市场交易就会产生价格信息,而价格信息本身是有价值的。第二个问题什么是预言机?区块链本身是没有任何途径可以去了解区块链以外的数据,或者说区块链本身没有办法知道区块链之外发生了什么。举个简单例子,以太坊公链在运行时是无法得知苹果股票股价,但可能对于大部分人来讲上网查一下就很容易知道。对于自成一体的区块链来说,想要知道区块链之外的事情是非常困难。一种方法是喂价,假设 Chainlink 或者任何一个人值得信任,就可以通过具有完全控制权的智能合约单向输入价格数据。其他人就可以用这个智能合约读取数据,这就可以理解为是一种预言机。存在的风险就是输入数据的人要完全值得信任,否则他可能会因为自己的利益而操纵价格,所以一个好的预言机是比较难做的。

这就牵涉到 Uniswap 为什么可以做预言机,因为其上面的价格信息本身趋近于市场价格。只要存在不一致的价格,就会有专门从事套利的人通过套利行为将价差缩小至零。这本身是一个比较可靠的喂价行为,你可以把它当成是一个预言机,这个预言机是你不需要相信任何一个专门的人,你只要相信这个市场还是在运作的,那么这个价格就会相对的准确。 

我们今天要讨论的是你什么时候可以相信这个市场是正常运作,什么时候是需要怀疑的。假设我们有一个 Uniswap 的 TWAP,这时候有什么人会有动机尝试去操纵这个价格?操纵的方式具体是什么样?他在操作的时候,他自己面临什么样的风险?同时我们又能以什么方式预防或者至少提高操纵成本。首先需要知道什么是 TWAP,全称是 Time Weighted Average Price,简单来说就是取过去 X 分钟,把这分钟里面所有的价格取加权平均。

为什么我们会需要用到预言机?比如在任何借贷的协议中,当你抵押一种资产,借出另一种资产的时候,你需要知道你抵押的资产相对于你借出的资产的比例是多少?如果你抵押的资产不及你借出的资产多,借贷的人存在不想要还的动机。他能用一块钱借出十块钱,他就拿着十块钱跑路就可以,他不需要再把这十块钱还给你换回他自己的一块钱。所以这时我们需要预言机告诉我们说你放进来的钱比你借走的钱要多。

很多借贷协议会用 Chainlink,因为它是一个相对比较稳定的预言机,总归是你相信它背后的人。当然即使用了 Chainlink,不代表它就是完全安全的。

我们需要分析假设我作为潜在的攻击者,我经过一番计算,发现我操纵价格的成本和风险远小于我的收益时,我就会有动机去攻击预言机。所以我们作为设计者就是需要反过来思考,我怎样增加他攻击的成本,使得他一开始不会去尝试攻击预言机。

还要补充一个点是我们当时写这篇论文时,一个最大的原因是因为以太坊合并,它改变了以太坊的共识机制。在合并之前,以太坊出块时,每一个区块具体由以太坊哪个节点出是不确定的。这个事情对一般人来说不太相关。但对于攻击者来说这是非常重要的一点。

攻击者能够非常明确地得知和控制哪一个区块出块是非常重要的,以太坊合并让这件事情变得比原来容易很多。在 PoW 共识机制中,下一个区块被谁挖出来,其实是概率事件,就是你只能从概率上说我有 30% 的可能性挖出下一个以太坊区块,但是在 PoS 里面,从现在开始往后多达 32 个区块由具体哪一个验证者打包是提前知道的,这就产生一个很大的问题。

首先较大的验证者比如 Coinbase 等很有可能连续掌控多个出块权。比如说 Coinbase 可能一次性控制了 N+5、N+6 和 N+7 个出块权,或者他也可以通过和其他大型验证者合作获取连续的出块机会。那么在这些区块里面我去操纵预言机是无风险的。因为我控制了这么多个区块,在操纵的池子中我是可以拒绝和接受交易请求,这就大大降低了攻击池子的成本。因为它可以非常确定地知道没有人会干扰被他操纵偏离市场价格的池子。

现在要分析的是操纵池子要花多少钱?这取决于多个因素。首先取决于你要操纵哪一个池子。如果池子的流动性很深,有大量的资金质押在这个池子里面,那么你为了把价格从 A 推向 B,同样的价差可能要花更多的钱。当然另外一方面,一个池子里面 TVL 越大,那就相应代表具有交大的资金量,那么如果你成功操纵价格,你获利的机会可能更多。

另一个取决于你想要移动偏离的市场百分比。如果你一次想要移动 20% 的价差,同时它又是一个 30 分钟的 TWAP,就代表着你需要让它现在的价格变得非常多。可能你控制三个区块,提供三个数据点,但是过去的 30 分钟有比如说 150 个数据点,这三个数据点要改变 150 个数据点的平均数,就代表着这三个数据点本身要非常离谱。

为了简化所有的价格偏移,我们就看一个非常简单的例子。我有一个 30 分钟的 TWAP。每一个区块每 12 秒我取一个读数,然后我做这件事情持续 30 分钟,我把这 30 分钟的所有读数加起来做一个几何平均。我现在控制以下若干个区块,想要让 30 分钟的价格偏离现在市场价格的 20%。我现在就要去计算具体要花多少钱才能实现。同时的话,Uniswap 有很多不同的流动性池,每个流动性池价格都是不一样的。我们就取最主流的以太坊和 USDC 的流动性池。

刚刚我举的例子是说你控制 N+1 到 N+K 个区块,这个 K 是一个可以变的数,比如说如果你只控制一个区块,你要用一个观测值使 150 个观测值的平均数发生偏移,这是非常困难的。如果你控制 25 个区块,这个事情就变得容易很多。具体的数学过程我就不讲了,我就说一下计算结果。你需要使现在的价格偏移 250 个 Ticks 才能实现 20% 的价格偏差。每推一个 Tick,就代表着使价格偏离万分之一,比如说现在是 1 万块,推一个 Tick 就是 10001 块。那么再推一个 Tick 不是 10002,而是 10001 乘以 1.0001。如果你要推 250 个 Ticks,这将是一个非常大的数。

我们可以把数学公式以图象的形式呈现,图上日期是在不停变化的。随着日期的变化,这个图里面的流动性也在不断变化。对于一个攻击者来说,他要关注的是中间不停移动的竖线,其实是当下的中位数价格。如果你要去操纵这个流动性池,就代表着你要把中位数价格往两边发生偏移。那么你的成本是比如说要把这个线往右推,其实是要把右边所有的 ETH 都给买下来,然后在你买这些 ETH 的时候,价格会变得越来越高的。你从 4000 的时候开始买,然后你一直买到 5000 时,现在当前的市场价可能一个 4000 块钱,你买到 5000 的时候,一个 ETH 就是 5000 了。然后中间所有的这些交易量都是需要以你实际交易交易量乘以池子的费率去做结算的,你在买的过程中还要付手续费,手续费可以说是最主要的攻击成本。

计算操纵费用不是一个特别容易的东西,这个图是假设的结果。因为首先你要弄明白这个图它是不停的变。同时你要想办法去阻止其他人进行套利,不然你可能 5000 块钱的价格买了 1 万个 ETH,然后当前价格是 4000 块,那么别人就会进来疯狂的卖 ETH,你可能最后就需要花更多的钱。假设你只控制区块。然后硬是要把 30 分钟的 TWAP 推离 20%,你需要买多少个 ETH 来做这件事情。我们计算的结果就是随着池子的流动性不停的变,这个费用也是在不停的变。可以看到除了这个池子刚建立的时候没有什么流动性,但是越到后面就越高。

下面我讲一下具体有哪一些比较好的预防措施。当然每一个具体的措施需要根据自己的情况去具体分析,但是有一些比较通用的方式。

Benevolent Liquidity Provision 其实就是说如果你是一个项目方,然后你的项目代币或者你要用到的代币有一个自己的池子,同时你又有一些代币质押在这个池子里面,那么你可以有策略性地把它们部署在一些奇怪的地方,然后这些奇怪的地方可能就让攻击者的成本非常高。

具体有哪些奇怪的地方,比如说我举一个简单例子,刚刚讲到假设你要阻止如说 20% 的价格偏差,你觉得说不可能有人一次性控制五个以上的区块,也就是说我们刚刚做的计算当中超过连续五个区块的情况不考虑。那你可以在很远的地方部署一些订单限制。这些人在到一个很离谱的价格购买时,他不得不在同样的价格以非常离谱的价格把东西卖给你。例如如果现在 ETH 是 1800U,他可能要以 8U 的价格卖给你。或者由 10000U 的价格从你那买 ETH。攻击者他可能就不得不直接承担价格损失,而不是它可以通过其他市场进行交易来赎回资金。还有一种你在很远的地方部署一下流动性资金,那么如果攻击者想要使价格偏移到相应价格,光是手续费的成本就是巨大的。

从预言机使用者的角度来说。一种最明显的解决方法就是你自己在池子里面放一些流动性资金,让别人不好去操纵。

最简单的就是我们可以在 Uniswap 部署 Truncated TWAP Oracles,比如说代币价格从 N 到 N+1 个区块内,我们认为资产的价格应该变动不可能超过 100 倍,即使它发生了我也可以认为这是错误的。所以一种是我在计算预言机的时候,我就把这些异常值直接排除掉。如果不进行排除,我们可以以一种比较平缓的方式把这些异常值的数据点慢慢加到加权平均当中。

第二种方式是我可以允许这种 Single-sided limit orders,也就是说允许一些人在很远的地方发出买入或者卖出订单,然后同时它是不可逆转的,目前所有 Uniswap 的头寸都是在一个区块以内进行交易的。或者说不管是不是一个区块以内,只要它在过去和回来的过程中,你没有机会去移除你的流动性。我们加一个单边限制的话,一旦这个东西过去,你的流动性自动移除,这就可以对预言机的安全性有比较大的加强。

另外一种主要的考量是移动平均价格还是受到异常值的影响,你可以有很多平缓的点,然后如果有一个特别高的点,这个时候整个平均数都变大了。如果你有很多个小点,然后有一个特别大的点,这个中位数完全没有变,它还在中间。所以这也是一种新的的计算方式叫做 Medianized TWAP Oracles。

简单总结一下,我们介绍了 PoS 机制对预言机的安全性造成了很大的不确定性。对于大的流动性池来说,想要操纵其价格几乎是不可能实现的,但是较小的流动性池就不好说了。协议开发者可以部署一些预防性流动性资金,也可以在预言机设计时,部署一些防范性机制。其实防范性机制最主要的是具体问题进行具体分析。

 

如果你在考虑做一个项目,你有一个预言机需求,首先你需要有一个客观的目标,不同的目标,容错量不一样。在明确目标之后,你需要知道你自己安全边际。比如你自己有多少资金可以部署到池子里,以及市场会在你的池子里面部署多少流动性。攻击者需要花多少钱才能操纵预言机,因为攻击者只有在他能挣钱的时候会进行攻击。所以你是需要去计算进行攻击需要花多少钱。第三点就是你假设只要有任何的套利空间,预言机就一定会被攻击。这三点加起来,你就可以制定防范机制了。

Web3