全面解析 ERC-4626 与 DeFi

进阶Feb 23, 2024
本文全面剖析ERC-4626的的基本原理以及其在DeFi中的应用。
全面解析 ERC-4626 与 DeFi

转发原文标题:全面解析 ERC-4626 与 DeFi

01什么是 ERC-4626

ERC-4626 是一个使用单一基础 ERC-20 的代币化金库。

Tokenized Vaults with a single underlying EIP-20 token.

首先,它是一个基于 ERC-20 的提案,并与之完全兼容。

其次,理解金库(vault)的概念,它不是国库(treasury)。现在市面上的国库基本上就是一个合约钱包,大多以 Gnosis Safe 为主,主要提供安全的资金出入功能。但是对于一个组织来说,除了资金出入外,还可以让资金流动产生收益。

该提案产生的动机:代币化的金库缺乏标准,导致市场上的很多金库实现细节不一样,比如借贷市场、聚合器、生息代币等。这使得在协议层面的聚合器和插件集成工作变得困难,容易出错和浪费开发资源。

该提案当前状态:Final,意味着是相对比较稳定的标准了。

02规范

遵循 ERC-4626 的代币必须完全实现 ERC-20,用来表示份额(shares)。下面是几个简单的概念。

  • 资产(asset):由金库管理的基础代币(the underlying token),遵循 ERC-20 标准。
  • 份额(share):金库代币,也可以称为 vToken。它跟 asset 有一个比例关系。
  • 费用(fee):在资产或份额发生变化时,金库收取的一个金额。可以是 存款、收益、资产管理、取款等。
  • 滑点(slippage):份额存款和取款的公布价格和实际经济差。下面是关于 DeFi 领域滑点概念的更多解读。

滑点是指交易的预期价格与实际执行价格之间的差异。当下单交易与执行交易之间存在延迟,交易的资产价格发生变化时,滑点就会出现。

例如,你在 AMM 池中发现有 20 个 ETH 和 80 个 USDT,那么你预期的 ETH 价格为 4 USDT/ETH。然而,如果你计划花费 20 个 USDT 在池子里进行 swap,最终只会得到 4 个 ETH,而不是预期的 5 个 ETH,这意味着你遭受了 1 USDT/ETH 的滑点损失。你的实际购买价格将是 5 USDT,而不是预期的 4 USDT。

滑点在快速变化的市场或高波动性资产以及流动性受限的长尾资产中尤其常见。无论如何,它对交易表现有重大影响,在下单交易时考虑滑点非常重要。

03合约分析

合约代码来自 OpenZeppelin 智能合约代码库:

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC4626.sol

ERC-4626 合约继承自 ERC-20,这部分就不概述了,它本身也是一个抽象合约,该合约必须实现的接口如下:

接口还是挺丰富的,大多比较简单,可以分为 read 和 write 2 大类。

Write

写数据接口主要是 deposit、mint、withdraw、redeem。

  • deposit,存款,确定数量 assets 转入金库。同时铸造(mint) shares。可以使用 previewDeposit 方法提前查看可以铸造多少 shares。

  • withdraw,取款,确定数量 assets 转出金库,同时销毁(burn) shares。可以使用 previewWithdraw 方法提前查看销毁了多少 shares。

  • mint ,铸造,使用 shares 参数,实际上这个方法等同于 deposit,以确定铸造的 shares 来计算需要存入的 assets。可以使用 previewMint 方法提前查看取出多少 assets。
  • redeem,赎回,使用 shares 参数,这个方法等同于 withdraw,以确定销毁的 shares 来计算需要转出的 assets。可以使用 previewRedeem 方法提前查看赎回多少 assets。

实际上由于滑点的存在,使用 preview 方法查看预计的数字,可能是不准确的,也是业界常见问题,可能会产生一些安全问题,后面会讲到。

Read

前面讲的几个 preview 方法,和公开的 convertToShares,convertToAssets,实际上内部都是调用了 _convertToShares、_convertToAssets 方法。

这 2 个核心方法就是计算资产和份额的比例关系的,这里面涉及到的变量有份额供应量、当前总资产、小数点位数、小数点取整方式。

以上是 ERC-4626 抽象合约的基本实现,实际的金库合约要比它复杂的多。

对于金库合约,有 2 个比较重要的功能实现,一个是存取功能,assets 和 shares 的换算;另一个是获得收益的方式。下面我们会举例讲解。

04 生态和应用

类似其它一些热门的 EIP,ERC-4626 也有一个专门人维护的联盟生态(https://erc4626.info/),收集了目前市面上已经兼容 ERC-4626 的一些借贷协议和应用,另外还有新闻、开源库、安全等信息。如果你的金库适配了 ERC-4626,也可以在上面提交申请。

下面我们分析一个应用例子,Aladdin DAO 的 AladdinCRVV2 金库(https://concentrator.aladdin.club/vaults/)。Aladdin DAO 有很多个金库合约,这只是其中一个比较活跃的。

AladdinCRVV2 金库

该金库通过质押 cvxCRV 代币,来获得收益。

  • 该金库合约是一个可升级合约

https://etherscan.io/address/0x2b95A1Dcc3D405535f9ed33c219ab38E8d7e0884),通过github 代码可以查到之前版本是不兼容 ERC-4626 的

  • 该金库 assets 是cvxCRV

https://etherscan.io/address/0x62B9c7356A2Dc64a1969e19C23e4f579F9810Aa7)。cvxCRV 可以在 Curve 旗下的 Convex 上通过质押 CVX 获得,也可以使用 CRV 转换 cvxCRV(过程不可逆)

  • 实际上存款和取款,有多种操作选择,还是挺方便的,节约 gas。代码太多,这里就不贴出来了。
    • 存款,默认将 cvxCRV 代币存入金库。另外还有 depositWithCRV 方便 CRV 也可以存款
    • 取款时,默认将 cvxCRV 代币取出,销毁 shares。另外还可以在取款时,自己再质押,将 cvxCRV 转换成 CVX ,将 cvxCRV 转换成 ETH

以上就是对该金库合约的基本解析,功能还是比较丰富的,它的本质就是 assets 质押生息,为什么要这样设计呢,主要还在在于 cvxCrvStaking 合约的设计,质押 cvxCRV 收益描述“By staking cvxCRV, you’re earning the usual rewards from veCRV (3crv governance fee distribution from Curve + any airdrop), plus a share of 10% of the Convex LPs’ boosted CRV earnings, and CVX tokens on top of that.”,而一起通过金库质押的代币数量越多时,获得的收益也越大。

安全

对于 ERC-4626 金库来说,最主要的安全问题在于防通货膨胀攻击(Inflation attack)。

当用户存入代币时,根据份额计算公式(shares = assets * totalSupply / totalAssets),计算结果是有小数点的,一般是向下取整。

通过下图可以看到,在用户存入 500 代币的资产时,小数取整所损失的资产取决于汇率(每股和代币资产对应关系)。如果汇率是橙色曲线的汇率,我们得到的不到 1 股,损失了100%。但是,如果汇率是绿色曲线的汇率,得到 5000 股,四舍五入损失限制在最多 0.02%。

那如果我们专注于将损失限制在最大 0.5%,我们需要获得至少 200 股。绿色汇率只需要 20 个代币,但橙色汇率需要 200000 个代币。

通过几上例子可以分析出,蓝色和绿色曲线对比黄色和橙色曲线更安全,是设计更加安全的金库。

所以通货膨胀攻击的主要方式就是,通过某些手段将利率曲线向右移动,让少量存款者损失份额,达到攻击目的。

攻击方式

Inflation attack 主要是通过捐赠(donate)。

  1. 攻击者先存入 1 个代币到金库合约。这时他所获得的 shares 是 1 ,totalSupply 为 1。
  2. 攻击者直接向金库合约发送 1e5 个代币。这时 totalAssets 发生了变化,为 1e5 + 1,而 totalSupply 并没有发生变化。
  3. 在受害者存入少于 1e5 个代币时(x),所获得的 shares 为: x * 1 / (1e5 + 1),也就是说只要 x 小于 1e5,根据小数向下取整原则,受害者所获得的 shares 为 0 。即使存入的代币大于 1e5,因为攻击者之前所占份额为 100%,那么受害者所获得的 shares 也会大大减少。

抵御攻击

抵御攻击的措施有 3 种:

  1. 设置滑点。在前面我们介绍了滑点的概念,通过设置滑点容忍范围(slippage tolerance)如果它在某个滑点容忍范围内没有收到预期的数量,则撤销(revert)交易。这是处理滑点问题的标准范式。
  2. 向金库增加足够多的初始资产,增加攻击成本。这种方式笔者在 Blast 质押合约中见到过,初始化质押时,合约要求 ETH 和 USD 数量不少于 1000。
  3. 将“虚拟流动性”添加的金库,让价格计算行为跟金库中有足够多的资产一样。抵御方式分为 2 部分:
    • 在 shares 和 assets 之间做精度偏移。
    • 将虚拟 shares 和 虚拟 assets 纳入到汇率计算中。

具体实现就是重写由 OpenZeppelin 提供的标准库代码 _decimalsOffset() 方法,这种方式即不用设置滑点,也不用注入足够初始资金,是非常好的抵御通胀攻击方式。

05扩展

RC-4626 作为一个比较基础的金库提案,不可能满足所有需求,有一些提案也对止做出了扩展,比如 ERC-7535、EIP-7540。

ERC-7535

前面提到 ERC-4626 只能使用 ERC-20 作为基础资产,这个提案主要是将原生资产(native asset)也可以作为基础资产(underlying asset),比如 ETH 在金库中使用。

EIP-7540

这个对 ERC-4626 的扩展引入了对异步存款和赎回过程(称为”请求”)的支持。它包括了用于启动和检查这些请求状态的新方法。现有的从 ERC-4626 中使用的方法,如存款、铸币、提取和赎回,被用于执行可认领的请求。关于是否添加存款、赎回或两者的异步流程,由实现者自行决定。

潜在用例:

  1. 异步存款和赎回流程:通过引入“请求”概念,可以实现异步的存款和赎回过程,提供更灵活的操作方式。
  2. 用户体验改善:该提案强调了用户体验的重要性,并建议引入标准的发现机制,帮助用户和前端应用程序更好地了解异步操作的持续时间和延迟。
  3. 功能扩展:EIP-7540 通过添加新的方法,扩展了 ERC-4626 的功能,使得可以异步请求存款和赎回,并能查看这些请求的状态。

06总结

以上,就是关于 ERC-4626 相关的全部解析。

因为历史原因,当前市面上有很多金库并不遵循 ERC-4626的,依然在运作,比如 dForce,但没法应用更广。也有一些金库已经升级为遵循 ERC-4626,比如 Aladdin DAO 的一些合约(https://github.com/AladdinDAO/deployments/blob/main/deployments.mainnet.md)。

金库应用除了质押生息外,还可以将 shares 做为抵押物借出或者再质押,从而产生收益。另外通过金库来募资也是一个比较好的应用场景,它的一些基础功能就可以提供很好的支持。

该提案的推出,本质是为了提升金库与 DeFi 生态集成效率,减少开发成本。而金库本身的作用,随着 DeFi 市场的增长,还有更多挖掘的空间。

声明:

  1. 本文转载自[LXDAO],原文标题“全面解析 ERC-4626 与 DeF”,著作权归属原作者[Kahn],如对转载有异议,请联系Gate Learn团队,团队会根据相关流程尽速处理。
  2. 免责声明:本文所表达的观点和意见仅代表作者个人观点,不构成任何投资建议。
  3. 文章其他语言版本由Gate Learn团队翻译, 在未提及Gate.io的情况下不得复制、传播或抄袭经翻译文章。
即刻开始交易
注册并交易即可获得
$100
和价值
$5500
理财体验金奖励!
立即注册