author:Thomas_Xu
Compound系列(3) More
杠杆交易
目前,借贷市场的强需求之一就是为了杠杆交易。但是,将 A 资产抵押到 Compound 再借出 B 资产,之后再到 DEX 平台(如 Uniswap)用 B 资产兑换成 A 资产,又重复投入 Compound,如此反复操作,对用户来说,是非常繁琐的,而且中间多次操作会消耗较多手续费。因此,直接提供杠杆交易服务的产品很受欢迎。
从用户需求层面来说,用户想要的就是做多或做空某种资产。比如,选定 ETH/USDT 交易对,开多的时候,就需要借入 USDT 并兑换成 ETH;开空的时候,则借入 ETH 来兑换 USDT。
当然,用户想要开仓,就需要先抵押资产作为保证金,这样才可借入资产。该逻辑其实和 Compound 的借贷逻辑一样,不同点在于,Compound 属于超额抵押借贷,存入价值 100 美刀的资产,最多只可借出 75 美刀的资产;但杠杆交易则可以借出多倍的资产,比如开 3 倍杠杆时,100 美刀的抵押资产,可以借出 300 美刀的资产来开仓。
这时,大部分人会想到的一个问题就是:抵押 100 美刀,借出 300 美刀,那多出的 200 美刀从哪来呢?这个问题的本质其实是:资金池里的资产从哪来?
Compound 的资金池只有一种流入途径,那就是用户的存款。但杠杆交易的资金池,其实有两种流入途径,一是用户的存款,二是开仓后兑换所得的资产。第二种途径很重要,这是维持资金池流动性很关键的一点。 比如,当用户抵押了 100 美刀的 ETH,开仓时借出了 300 美刀的 USDT,兑换回来了 300 美刀的 ETH,这 300 美刀的 ETH 又流回到资金池里去,因此,资金池的总价值其实没有变化,只是同价值的 A 资产变成了 B 资产。如果兑换后的资产不流回资金池,那资金池很容易就会失衡,导致资金池的流动性不足,甚至枯竭。
多空平衡的情况下,资金池的流动性也会保持平衡。但是,如果出现极端情况,比如,多方远超于空方的时候,就要考虑是否会出现某一资金池枯竭的风险。多方抵押了 ETH,借出了 USDT,兑换回 ETH,随着多方的力量越来越强,那么 ETH 的资金池会越来越多,但 USDT 的资金池则越来越少,那 USDT 的资金池是否就会面临枯竭的风险呢?这种问题,其实在 Compound 中也同样存在,而 Compound 的机制中,降低这种风险的关键点在于利率模型,即资金使用率超过拐点后的利率会非常高,借款利率高涨就会使得用户借款的意愿减低,而存款利率高涨就会促进用户多存款,从而可以让资金池的供需关系又回到一个平衡的位置。
对用户来说,杠杆交易的风险,和中心化的一样,就是存在爆仓的风险。抵押资产的价格变化、借款资产的价格变化、兑换资产的价格变化,以及借款利息的不断增长,都有可能导致爆仓。
借出的资产+利息称为债务,兑换回来的资产称为头寸,那对于每个持仓单,盈亏的计算公式如下:
1 | 盈亏 = 头寸价值 - 债务价值 |
盈亏为正时,表示盈利,那就不会有爆仓的风险。但是,盈亏为负时,就表示亏损了,一旦亏损率(亏损/保证金价值)超过某个阈值时(比如 80%),就需要强制平仓了,即是爆仓,也称为清算。为了避免爆仓,用户可以通过还款降低债务,或追加保证金。
如果用户自己想要止盈或止损了,就可以自己手动平仓了,平仓的逻辑也比较简单,将头寸资产再兑换回所借资产,接着还掉债务。如果兑换回来的资产不足以还债的话,那可能需要用部分抵押资产来兑换成所借资产并还债。
杠杆挖矿
自从 2020 年 6月 Compound 开启流动性挖矿(Yield Farming)以来,这一产业就迅速风靡,很多玩家都当起「农民」,通过为各种 DeFi 产品提供流动性来获得收益,收益一般为治理代币或交易费,或两者都有。比如,在 Compound 存款和借款都能挖到其治理代币 COMP;在 Uniswap 投入流动性得到 LP Token 可挖矿手续费;在 Uniswap 质押 LP Token 能挖到 UNI 代币和手续费。LP Token 本质上就类似于 cToken,不同交易对池子有不同的 LP Token。
杠杆挖矿则是将用户本金加杠杆,达到放大本金的效果,从而为用户提高挖矿的效率。目前大部分杠杆挖矿产品主要都是投入到如 Uniswap、SushiSwap、PancakeSwap 等 DEX 平台进行挖矿。
以 Alpha Homora 为例,矿池可分为两大类,一类称为 liquidity providing pools,另一类称为 yield farming pools。 liquidity providing pools 只是投入流动性到 DEX 平台得到 LP Token,从而赚取 DEX 平台的手续费和 Alpha 代币;而 yield farming pools 则会将 LP Token 质押到 DEX 平台,从而,除了赚取 DEX 平台的手续费和 Alpha 代币,还能赚到 DEX 的平台代币。两者的主要区别就在于是否将 LP Token 进行质押。
而用户要参与杠杆挖矿,首先选定要参与的一个池子,比如选定 Uniswap 的 UNI/ETH 池子。之后,用户需要投入本金,本金可以是 UNI、ETH 或这个交易对的 LP Token,可以投入这三种 Token 中的一种或多种。接着,用户就可以选定杠杆倍数和想要借的币种和数量,本金和杠杆倍数决定了最多可以借多少,借款币种可以是 UNI 和 ETH 中的一种或两种,一般只借一种。最后,用户再次确定各种数据,没问题就可以提交开仓了。开仓时,智能合约就会根据 Uniswap 上该池子的兑换率自动将部分资产兑换成另一种,让两种资产的数量能满足添加流动性的匹配要求,然后就投入到 Uniswap UNI/ETH 的资金池里,得到该池子的 LP Token。如果用户选择的是 liquidity providing pool,那流程到此就算完成了;如果用户选择的是 yield farming pool,那还会自动将 LP Token 质押到 Uniswap。
其他杠杆挖矿产品的逻辑也是大同小异,较大的不同在于其他杠杆挖矿产品大多只有 yield farming pools,并没有 liquidity providing pools。
那么,杠杆挖矿的风险又如何呢?
首先,在没杠杆的情况下,用户往 AMM 模式的 DEX 提供流动性时,参与挖矿的两个币种一旦出现汇率变化,就会产生无常损失(Impermanent loss,也称“非永久性损失”),价格波动越大,无常损失越大;而加了杠杆之后,放大了本金,也同样放大了无常损失。通常,无常损失需要靠手续费分成和质押 LP Token 的收益所得来填补。所以,用户平仓时,如果已经赚取的收益不能覆盖无常损失,那用户其实就是亏损的。当然,这还没算上借贷的利息。
另外,用户进行杠杆挖矿,还存在被清算的风险。借贷资产+利息就是债务,LP Token 的价值就是头寸,当债务比率(债务/头寸)达到清算线时,就会进行清算。为了避免清算,用户可以通过还款降低债务,或追加 LP Token 增加头寸。
杠杆挖矿最大的风险应该是资金池枯竭的风险,因为用户投入的本金和借贷的资产全都流入到 DEX 平台了,只有等到平仓后资产才会重新流回资金池。那么,如果没有足够的存款支撑,就难以维系下去。因此,需要大力吸引用户来存款,利率会远比 Compound、Aave 等借贷平台高得多,且通常采用三级利率模型,才可以较好地均衡资金池的资金使用率。比如,Alpaca(羊驼)的利率模型如下:
- 资金使用率 0% - 50% 时,利率 = 0.4 × 资金使用率
- 资金使用率 50% - 90% 时,利率 = 20%(恒定)
- 资金使用率 90% - 100% 时,利率 = 13 × 资金使用率 - 11.5
操纵预言机攻击
操控预言机所依赖的信息源进行短时间的价格操纵以达成误导链上价格是典型的预言机攻击,其本质是对预言机进行操控,造成内外价格差并利用闪电贷等新型金融工具从中套利。
Compound 曾在 2020 年 11 月 26 日遭受过价格预言机操纵攻击,导致价值高达八千多万美元的加密资产被系统强制清算。
因为 Compound 使用的是自己设计研发的预言机系统 Open Price Feed,且使用的价格数据只依赖 Coinbase 这个中心化的交易所来提供。而当日下午,Coinbase 交易所稳定币 DAI 价格出现剧烈波动,一度暴涨超 30% 至 1.34 美元,后又快速回落。这一剧烈波动,就让很多借贷了 DAI 的用户资产触发了清算。
事实上,除了 Compound,Harvest Finance、Value DeFi、Cheese Bank、Origin Protocol 等都先后遭到类似预言机的攻击,MakerDAO 和 Aave 历史上也都因此发生过大规模清算。
针对此类攻击,安全建议如下:
- 接入 Chainlink 等完善的第三方价格预言机对所有代币价格提供实时价格数据
- 在智能合约内部建立细致的价格监控程序,对任何可能产生巨大波动的交易进行管制或者阻止
目前第三方价格预言机主要有:Chainlink、NEST、Band、DOS、Tellor、MakerDao 等。其中,龙头当属 Chainlink 了。Chainlink 使用链上聚合模式,节点将数据提交到链上合约,在合约内进行数据聚合,获得最终数据。
另外,随着 DEX 的发展,直接使用 DEX 的链上价格做为预言机也是一个很有潜力的方向,这需要 DEX 具有足够的深度,能够抵抗价格操纵,或者对价格进行加权等操作,来规避价格操纵攻击。这块目前应用最广泛的就是 Uniswap TWAP(Time-Weighted Average Price),即时间加权平均价格,可通过查看官方文档了解其机制:
如果还需要再进一步提高安全性,可以选择多个预言机进行加权平均计算,推荐 3 家第三方预言机 + 3 家 DEX 组合,比如选择 Chainlink、NEST、Band、Uniswap、SushiSwap、Bancor,每家可设置不同的权重值,计算时,获取到六家价格后,去掉最高价和最低价,剩下的再进行加权平均计算作为最后的实际价格。另外,在同个区块内,也无需每次交易都计算出实时价格,只要计算出一个合理价格后,整个区块内的交易都可直接使用该价格,这样,利用闪电贷操纵价格的手段也造不成威胁了。
EIP712
摘要
这个EIP旨在提高链下消息签名对链上的可用性。我们可以看到,因为节省gas以及减少链上交易的原因,采用链下消息签名的需求日益增长。现在已经被签名的消息,展示给用户的是一串难以理解的16进制的字符串,附带一些组成这个消息的项目的上下文。
EIP-712: Typed structured data hashing and signing (ethereum.org)
在使用EIP712之前的签名信息:
在使用EIP712之后的签名信息:
实现方法
下面我们以一个拍卖场景为例,看看如何在产品中把 EIP712 用起来。
定义数据结构
首先,用 JSON 格式列出用户所要签名的数据。 比如作为一个拍卖应用,需要签名的就是下面的投标数据:
1 | { |
然后,我们可以从上面的代码片段中提炼出两个数据结构: 竞标 Bid,它包括以 ERC20 代币资产和拍卖 id 确定的出价金额,以及身份 Identity,它指定了用户 id 和 用户钱包地址。
下一步,将 Bid 和 Identity 定义为结构体,就可以写出下面的 solidity 合约代码了。 可以通过 EIP712 协议草案查看 EIP712 所支持的完整数据类型列表,比如地址、 bytes32、 uint256等。
1 | Bid: { |
设计域分隔符
主要防止一个 DApp 的签名还能在另一个 DApp 中工作,从而导致签名冲突。拿拍卖为例子的话,一个拍卖应用里的投标请求竟然在另外一个拍卖应用里也能执行成功,可能会就导致不必要的损失。
具体来说,域分隔符就是下面这样的结构和数据:
1 | { |
使用签名实现委托
按照EIP-712 规范定义的结构化数据签名方式,COMP代币持有者可以委托给任何一个以太坊地址。任何用户只要有已签名的委托交易,都可以调用COMP智能合约中delegateBySig 函数
这种方式的使用场景可能是,一个委托者希望联合其他COMP持有者将他们的投票委托给被委托人,并希望以非常低的成本来完成这项工作。
被委托者可以创建一个网页,让用户通过Metamask和私钥完成delegateBySig 交易,这样被委托者就能收集到签名信息。之后,被委托者可以将签名信息打包,批量一次写入到以太坊中,再执行delegateBySig函数就可以正式的收集到用户的投票权利。
通过签名投票
delegateBySig一样,用户也可以委托第三方给 Compound治理提案投票。任何用户只要有已签名的委投票交易,都可以调用智能合约中castVoteBySig 函数
第三方提交用户签名交易和delegateBySig的情况是一样的,但是投票权利仅限于一个提案,并非无限制的提案。在第三方正式将投票交易发送到以太坊之前,原有的用户依然保留自主投票的权利。
重放攻击注意点
这个标准只是关于对消息签名和验证签名。在很多实际应用中,已签名的消息被用来授权一个动作,例如token交换。使用者需要确保当应用程序看到两笔一模一样的已签名消息时依然可以做出正确的行为,这一点十分重要。举个例子,重复的消息需要被拒绝,或者授权的行为应当是幂等的(注:一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同)。至于这是如何实现的,要视特定应用而定,并且超出了本标准的范围。
有关交易重放,我正打算整理一下写一篇文章
true
...
...
This is copyright.