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
/ transferFrom
在 asset
上作为 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
/ transferFrom
在 asset
上作为 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
处销毁,其中 owner
为 msg.sender
或 msg.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
处销毁,其中 owner
为 msg.sender
或 msg.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.