Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-7802: 具有跨链 Mint/Burn 权限的代币

允许授权的合约在跨链传输期间铸造和销毁代币表示

Authors skeletor (@skeletor-spaceman), parti (@0xParticle), joxes (@Joxess), ng (@0xng), agus duha (@agusduha), disco (@0xDiscotech), gotzen <gotzen@defi.sucks>, 0age <0age@uniswap.org>, Mark Tyneway <mark@oplabs.co>, Zain Bacchus <zain@oplabs.co>, Matt Solomon <msolomon@oplabs.co>, Maurelian <maurelian@protonmail.ch>, Blaine Malone (@blmalone)
Created 2024-10-30
Discussion Link https://ethereum-magicians.org/t/erc-7802-crosschain-token-interface/21508
Requires EIP-165, EIP-5679

摘要

本标准引入了一个最小且可扩展的接口 IERC7802,用于代币以实现标准化的跨链通信。该接口包含两个函数 crosschainMintcrosschainBurn,允许授权的桥合约在跨链传输期间铸造和销毁代币表示。这些函数充当桥逻辑的进入点,从而实现跨链代币供应的一致处理。

该接口还定义了两个标准化的事件 CrosschainMintCrosschainBurn,它们发出元数据,包括目标地址、代币数量和调用者。这些事件有助于链下代理(例如索引器、分析工具和审计员)对跨链活动进行确定性索引和监控。

IERC7802 有意保持轻量级,确保实现的最小开销。其模块化设计实现了可扩展性,允许在不修改基本接口的情况下,在顶部添加其他功能,例如 mint/burn 限制、交易费用或桥特定的访问控制机制。

动机

所有 Rollup 和多个重要的侧链都实现了规范桥,这些桥将其安全性嵌入到网络的某些核心架构中。这些桥没有对原始代币的 mint/burn 权限,所以它们通常锁定(解锁)原生链上的流动性,然后在另一条链上 mint(burn)一个非等效的表示。使用 mint/burn 是因为原生代币在该侧链上不存在,因此它们必须创建一个新的表示。然而,每个桥都为非原生链上的 minting/burning 实现了不同的接口。

这种接口碎片化是跨链通信中通过第三方桥或未来规范解决方案在链之间的一个巨大问题。在这一点上,每座桥梁都将受益于针对已 mint/burn 代币的标准化接口,这一点显而易见。

过去曾有不同的尝试来标准化代币桥接接口。然而,第三方提供商也在开发跨链代币框架。每个框架都定义了其功能,例如速率限制和费用开关,并实现了其 mint 和 burn 版本。由此产生的接口变得高度具体,缺乏命名约定和结构。

所提出的接口包括大多数这些标准使用的最相关和最小的操作集。与设置速率限制相反,这些操作也不需要任何治理或所有者参与。

规范

此 ERC 引入 IERC7802 接口。

接口标识

IERC7802 的接口标识符是 0x33331994,根据 ERC-165 计算得出,即接口中两个函数的函数选择器的 XOR:

bytes4 constant INTERFACE_ID_IERC7802 = 
        bytes4(keccak256("crosschainMint(address,uint256)")) ^
        bytes4(keccak256("crosschainBurn(address,uint256)"));

或通过 Solidity 表示为

type(IERC7802).interfaceId

实施者必须确保 ERC-165 的 supportsInterface 方法为此接口 ID 返回 true,以表明支持 IERC7802

方法

crosschainMint

_amount 的代币 mint 给地址 _account

此函数用作桥合约的 minting 入口点。

function crosschainMint(address _account, uint256 _amount) external;

为了符合 ERC-20 关于代币创建的不变性,实现应在调用 crosschainMint 时发出 Transfer(address(0), _to, _amount)

crosschainBurn

从地址 _account 销毁 _amount 的代币。

此函数用作桥合约的 burning 入口点。

function crosschainBurn(address _account, uint256 _amount) external;

为了符合 ERC-5679,实现可能考虑在调用 crosschainBurn 时发出 Transfer(_from, address(0), _amount)

事件

CrosschainMint

当成功调用 crosschainMint 时必须触发。 _sender 参数必须设置为调用函数时 msg.sender 的值。

event CrosschainMint(address indexed _to, uint256 _amount, address indexed _sender);

CrosschainBurn

当成功调用 crosschainBurn 时必须触发。 _sender 参数必须设置为调用函数时 msg.sender 的值。

event CrosschainBurn(address indexed _from, uint256 _amount, address indexed _sender)

原理

设计理念

此最小接口背后的核心设计决策是

  • 桥不可知性。
  • 扩展性。

桥不可知性 此接口的设计使得桥(而不是代币)包含处理跨链操作的逻辑。通过保持这种关注点分离,代币合约保持简单,从而减少了它们的攻击面,并简化了审计和可升级性。将跨链复杂性卸载到桥合约可确保代币不嵌入特定的桥逻辑。

通过实现提议的接口,不同的桥设计可以支持代币:

  • 锁定/解锁桥仍然可以运行,并且不需要任何代币修改。
  • Burn/mint 桥现在可以使用通用的和最小的代币接口,因此它们不需要引入桥特定的表示,从而提高了跨链同质化。

扩展性 最小接口充当其他标准可以构建的基础层。 代币发行者或桥合约可以通过添加 mint/burn 限制、跨链转账费用等功能来扩展功能,而无需更改核心接口。

该接口有意保持中立,并且不对以下方面施加条件:

  • 访问控制:代币发行者确定谁有权调用 crosschainMint()crosschainBurn()
  • 零数量调用:代币发行者决定是允许还是还原零数量调用。

本地和跨链 Minting/Burning 的分离

不同的操作

本地 minting 和 burning 从根本上不同于跨链 minting 和 burning。

  • 在跨链操作中,预计所有链上的总循环供应量将保持不变,因为代币是在链之间转移,而不是孤立地创建或销毁。
  • 在跨链传输中 mint 和 burn 代币的代理从根本上不同于代币所有者。让这两个参与者拥有不同的权限是有意义的。

因此,对于跨链操作,有不同的检查、访问控制和逻辑(例如 mint/burn 限制)是合理的。

关注点分离

将本地和跨链 minting/burning 合并到相同的函数中可能会导致复杂的实现,从而将不同的操作逻辑交织在一起。 通过分成两个,关注点保持分离,从而使代码库更简洁且更易于维护。

这种关注点分离对于以下方面尤其重要

  • 升级:访问控制、限制或逻辑的任何更改只会影响单独的跨链函数(crosschainMintcrosschainBurn),而不会更改标准的本地 mint 和 burn 实现。
  • 与不同链的集成:为了使 ERC-20 跨链兼容,发行者只需实现 ERC-7802 扩展,并为每个链提供相应的访问控制。例如,在与 Optimism 集成时,ERC-20 将授予对 Optimism 桥的访问权限;在与 Arbitrum 集成时,它将授予对 Arbitrum 桥的访问权限。本地 mint 和 burn 函数保持不变。使用专用函数进行跨链操作提供了一种更模块化的方法,避免了为每个链修改基本实现的需求。

专用事件

类似的推理适用于拥有专用的跨链特定事件。这种分离极大地促进了索引器、分析工具和审计员的工作。它允许直接跟踪跨链活动、检测异常情况和监控桥操作。如果跨链和本地事件无法区分,则链下代理必须实现复杂的逻辑来区分它们,从而增加了出错和效率低下的可能性。

ERC-165 接口

包含 ERC-165 为集成商提供了额外的安全检查。通过 supportsInterface 方法提供接口标识符,调用者可以以编程方式确认代币是否符合 IERC7802 接口。 此验证确保代币支持 crosschainMintcrosschainBurn 函数,从而避免仅实现一个函数的情况。这种不完整的实现可能会导致诸如用户销毁代币以桥接出去,但无法在返回时 mint 它们的问题,从而导致跨链操作失败。

重要的是要注意,此检查只能在代币合约所在的链上本地执行。不能保证接收链上的代币也支持 IERC7802 接口。确保接口支持的跨链一致性是桥实现者的责任。

向后兼容性

此提案与 ERC-20 完全向后兼容。

正如在“动机”部分中讨论的那样,需要一个最小的、灵活的跨链标准接口。随着部署更多没有标准化格式的代币,问题变得越来越大。

  • 可升级代币可以升级以实现新接口。
  • 不可升级代币无法在代币本身上实现该接口。它们仍然可以使用 xERC-20 提议的锁定机制迁移到符合标准的版本。其想法是锁定不可 mint 的代币并 mint 相同数量的符合接口的代币。桥合约可以在原生链上充当锁定库。

桥合约还需要升级才能与接口集成。

参考实现

// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.25;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";


/// @title IERC7802
/// @notice 定义跨链 ERC20 转账的接口。
interface IERC7802 is IERC165 {
    /// @notice 当跨链传输 mint 代币时发出。
    /// @param to       要为其 mint 代币的帐户地址。
    /// @param amount   mint 的代币数量。
    /// @param sender   调用 crosschainMint 的调用者 (msg.sender) 的地址。
    event CrosschainMint(address indexed to, uint256 amount, address indexed sender);

    /// @notice 当跨链传输 burn 代币时发出。
    /// @param from     从中 burn 代币的帐户地址。
    /// @param amount   burn 的代币数量。
    /// @param sender   调用 crosschainBurn 的调用者 (msg.sender) 的地址。
    event CrosschainBurn(address indexed from, uint256 amount, address indexed sender);

    /// @notice 通过跨链传输来 Mint 代币。
    /// @param _to     要 Mint 代币的地址。
    /// @param _amount 要 Mint 的代币数量。
    function crosschainMint(address _to, uint256 _amount) external;

    /// @notice 通过跨链传输来Burn 代币。
    /// @param _from   从中 Burn 代币的地址。
    /// @param _amount 要 Burn 的代币数量。
    function crosschainBurn(address _from, uint256 _amount) external;
}

contract CrosschainERC20 is ERC20, IERC7802 {
    /// @notice 允许 Mint/Burn 代币的 TOKEN_BRIDGE 合约的地址。
    address public immutable TOKEN_BRIDGE;

    /// @notice 用于未经授权访问的自定义错误。
    error Unauthorized();

    /// @notice 用于设置 TOKEN_BRIDGE 地址的构造函数。
    /// @param _tokenBridge TOKEN_BRIDGE 的地址。
    constructor(address _tokenBridge, string memory name, string memory symbol) ERC20(name, symbol) {
        require(_tokenBridge != address(0), "Invalid TOKEN_BRIDGE address");
        TOKEN_BRIDGE = _tokenBridge;
    }

    /// @notice 一个只允许 TOKEN_BRIDGE 调用的修饰符
    modifier onlyTokenBridge() {
        if (msg.sender != TOKEN_BRIDGE) revert Unauthorized();
        _;
    }

    /// @notice 允许TOKEN_BRIDGE Mint 代币。
    /// @param _to     要 Mint 代币的地址。
    /// @param _amount 要 Mint 的代币数量。
    function crosschainMint(address _to, uint256 _amount) external onlyTokenBridge {
        _mint(_to, _amount);
        emit CrosschainMint(_to, _amount, msg.sender);
    }

    /// @notice 允许TOKEN_BRIDGE Burn 代币。
    /// @param _from   从中 Burn 代币的地址。
    /// @param _amount 要 Burn 的代币数量。
    function crosschainBurn(address _from, uint256 _amount) external onlyTokenBridge {
        _burn(_from, _amount);
        emit CrosschainBurn(_from, _amount, msg.sender);
    }

    function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
        return interfaceId == type(IERC7802).interfaceId || interfaceId == type(IERC165).interfaceId;
    }
}

安全考虑

权限

代币发行者负责控制哪些合约有权调用 crosschainMint()crosschainBurn() 函数。有缺陷或恶意的授权调用者可能会不正确地 mint 或 burn 代币,从而损害代币持有者并破坏集成。

正如 xERC-20 提议的那样,一种最大限度地减少潜在损失的方法是引入 mint/burn 限制。这些功能与提议的接口完全兼容。

封装的原生代币

此标准不应用于封装的原生代币(如 WETH),因为如果桥无法控制底层资产,则可能导致无抵押的 minting。

唯一的安全例外是当桥可以在两条链上对称地 burn 和 mint 原生代币时,从而确保适当的抵押。

版权

版权和相关权利通过 CC0 放弃。

Citation

Please cite this document as:

skeletor (@skeletor-spaceman), parti (@0xParticle), joxes (@Joxess), ng (@0xng), agus duha (@agusduha), disco (@0xDiscotech), gotzen <gotzen@defi.sucks>, 0age <0age@uniswap.org>, Mark Tyneway <mark@oplabs.co>, Zain Bacchus <zain@oplabs.co>, Matt Solomon <msolomon@oplabs.co>, Maurelian <maurelian@protonmail.ch>, Blaine Malone (@blmalone), "ERC-7802: 具有跨链 Mint/Burn 权限的代币 [DRAFT]," Ethereum Improvement Proposals, no. 7802, October 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7802.