Alert Source Discuss
🚧 Stagnant Standards Track: ERC

ERC-5143: Tokenized Vault 的滑点保护

EIP-4626 的扩展,支持改进的 EOA 交互。

Authors Hadrien Croubois (@amxx)
Created 2022-06-09
Discussion Link https://ethereum-magicians.org/t/eip-5143-slippage-protection-for-tokenized-vaults/9554
Requires EIP-20, EIP-4626

摘要

以下标准使用专门用于 EOA 和 vault 之间在价格受滑点影响时的安全交互的函数,扩展了 EIP-4626 Tokenized Vault 标准。

动机

EIP-4626 安全注意事项部分指出:

“如果实施者打算直接支持 EOA 帐户访问,他们应该考虑为 deposit/mint/withdraw/redeem 添加一个额外的函数调用,并采用适当的方式来适应滑点损失或意外的 deposit/withdraw 限制,因为如果无法达到确切的输出量,他们没有其他方法可以回滚交易。”

然而,EIP-4626 并未标准化相应的函数签名和行为。 为了提高互操作性,并更好地获得钱包的支持,此可选函数也必须进行标准化。

规范

此 ERC 是 EIP-4626 的扩展。 任何实现它的合约也必须实现 EIP-4626。

方法

deposit

ERC-4626 的 deposit 的重载版本。

通过精确地存储 assets 数量的基础代币,将 shares 数量的 Vault 份额铸造给 receiver

必须发出 Deposit 事件。

必须支持 EIP-20 approve / transferFromasset 上作为 deposit 流程。 MAY 支持一个额外的流程,其中基础代币在 deposit 执行之前由 Vault 合约拥有,并在 deposit 期间被统计。

如果所有 assets 无法存储(由于达到存储限制、滑点、用户未向 Vault 合约批准足够的基础代币等),则必须回滚。 如果存储 assets 数量的基础资产铸造的份额少于 minShares,则必须回滚。

请注意,大多数实现都需要预先使用 Vault 的基础 asset 代币批准 Vault。

- name: deposit
  type: function
  stateMutability: nonpayable

  inputs:
    - name: assets
      type: uint256
    - name: receiver
      type: address
    - name: minShares
      type: uint256

  outputs:
    - name: shares
      type: uint256

mint

ERC-4626 的 mint 的重载版本。

通过存储 assets 数量的基础代币,将精确的 shares 数量的 Vault 份额铸造给 receiver

必须发出 Deposit 事件。

必须支持 ERC-20 approve / transferFromasset 上作为 mint 流程。 MAY 支持一个额外的流程,其中基础代币在 mint 执行之前由 Vault 合约拥有,并在 mint 期间被统计。

如果无法铸造所有 shares(由于达到存储限制、滑点、用户未向 Vault 合约批准足够的基础代币等),则必须回滚。 如果铸造 shares 数量的份额花费的基础代币多于 maxAssets,则必须回滚。

请注意,大多数实现都需要预先使用 Vault 的基础 asset 代币批准 Vault。

- name: mint
  type: function
  stateMutability: nonpayable

  inputs:
    - name: shares
      type: uint256
    - name: receiver
      type: address
    - name: maxAssets
      type: uint256

  outputs:
    - name: assets
      type: uint256

withdraw

ERC-4626 的 withdraw 的重载版本。

owner 处销毁 shares 数量的份额,并将精确的 assets 数量的基础代币发送给 receiver

必须发出 Withdraw 事件。

必须支持 withdraw 流程,其中份额直接从 owner 处销毁,其中 ownermsg.sendermsg.sender 拥有对 owner 的份额的 ERC-20 approve 权限。 MAY 支持一个额外的流程,其中份额在 withdraw 执行之前被转移到 Vault 合约,并在 withdraw 期间被统计。

如果无法 withdraw 所有 assets(由于达到 withdraw 限制、滑点、所有者没有足够的份额等等),则必须回滚。 如果 withdraw assets 数量的基础代币需要销毁多于 maxShares 数量的份额,则必须回滚。

请注意,某些实现将要求在执行 withdraw 之前预先向 Vault 发出请求。 这些方法应分开执行。

- name: withdraw
  type: function
  stateMutability: nonpayable

  inputs:
    - name: assets
      type: uint256
    - name: receiver
      type: address
    - name: owner
      type: address
    - name: maxShares
      type: uint256

  outputs:
    - name: shares
      type: uint256

redeem

ERC-4626 的 redeem 的重载版本。

owner 处销毁精确的 shares 数量的份额,并将 assets 数量的基础代币发送给 receiver

必须发出 Withdraw 事件。

必须支持 redeem 流程,其中份额直接从 owner 处销毁,其中 ownermsg.sendermsg.sender 拥有对 owner 的份额的 ERC-20 approve 权限。 MAY 支持一个额外的流程,其中份额在 redeem 执行之前被转移到 Vault 合约,并在 redeem 期间被统计。

如果无法 redeem 所有 shares(由于达到 withdraw 限制、滑点、所有者没有足够的份额等等),则必须回滚。 如果 redeem shares 数量的份额向 receiver 发送的基础代币少于 minAssets,则必须回滚。

请注意,某些实现将要求在执行 withdraw 之前预先向 Vault 发出请求。 这些方法应分开执行。

- name: redeem
  type: function
  stateMutability: nonpayable

  inputs:
    - name: shares
      type: uint256
    - name: receiver
      type: address
    - name: owner
      type: address
    - name: minAssets
      type: uint256

  outputs:
    - name: assets
      type: uint256

原理

此 ERC 的函数不会替换 ERC-4626 等效机制。 它们是旨在保护与 vault 交互的 EOA 的附加(重载)方法。

当智能合约与 ERC-4626 vault 交互时,它们可以在执行操作之前使用专用函数预览任何操作。 这可以原子地完成,没有价格变化的风险。 EOA 并非如此,它将在 UI 上预览其操作、签署交易并在稍后进行挖掘。 在预览和执行交易之间,区块链状态可能会发生变化,从而导致意想不到的结果。 尤其是,抢先交易使 EOA 与 ERC-4626 vault 的交互可能存在风险。

DeFi 空间中的其他项目(例如去中心化交易所)已经包括类似的机制,因此如果用户认为产生的汇率不够好,则可以请求其交易回滚。

在此 ERC 的基础上实现 ERC-4626 合约可以非常轻松地完成。 它只需要调用相应的 ERC-4626 函数,并在返回值上添加回滚检查。

替代方法

此 ERC 旨在解决 vault 级别的安全问题(在动机部分中描述)。 为了完整起见,我们必须提到这些问题也可以使用通用的 ERC-4626 路由器来解决,类似于 Uniswap V2 和 V3 如何使用路由器在 Uniswap 交易对之上提供良好的用户工作流程。 路由器方法可能更加通用,并为发展留出更多空间(路由器可以在任何时候被替换),但它也会导致更昂贵的操作,因为路由器需要临时保管进入 vault 的代币。

参考实现

给定一个现有的 ERC-4626 实现

contract ERC5143 is ERC4626 {
    function deposit(uint256 assets, address receiver, uint256 minShares) public virtual returns (uint256) {
        uint256 shares = deposit(assets, receiver);
        require(shares >= minShares, "ERC5143: deposit slippage protection");
        return shares;
    }
    function mint(uint256 shares, address receiver, uint256 maxAssets) public virtual returns (uint256) {
        uint256 assets = mint(shares, receiver);
        require(assets <= maxAssets, "ERC5143: mint slippage protection");
        return assets;
    }
    function withdraw(uint256 assets, address receiver, address owner, uint256 maxShares) public virtual returns (uint256) {
        uint256 shares = withdraw(assets, receiver, owner);
        require(shares <= maxShares, "ERC5143: withdraw slippage protection");
        return shares;
    }
    function redeem(uint256 shares, address receiver, address owner, uint256 minAssets) public virtual returns (uint256) {
        uint256 assets = redeem(shares, receiver, owner);
        require(assets >= minAssets, "ERC5143: redeem slippage protection");
        return assets;
    }
}

安全注意事项

此 ERC 解决了 ERC-4626 提出的安全注意事项之一。 其他注意事项仍然适用。

版权

CC0 下放弃版权及相关权利。

Citation

Please cite this document as:

Hadrien Croubois (@amxx), "ERC-5143: Tokenized Vault 的滑点保护 [DRAFT]," Ethereum Improvement Proposals, no. 5143, June 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5143.