Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-6864: 可升级的同质化代币

可升级的同质化代币,是对 ERC-20 的一个简单扩展

Authors Jeff Huang (@jeffishjeff)
Created 2023-04-05
Discussion Link https://ethereum-magicians.org/t/eip-6864-upgradable-fungible-token-a-simple-extension-to-erc-20/13781
Requires EIP-20

摘要

本提案概述了一个智能合约接口,用于升级/降级现有的 ERC-20 智能合约,同时保持用户的余额。该接口本身是对 ERC-20 标准的扩展,以便其他智能合约可以继续与升级后的智能合约交互,而无需更改地址之外的任何内容。

动机

根据设计,智能合约是不可变的,像 ERC-20 这样的代币标准是极简的。虽然这些设计原则在去中心化应用中是根本性的,但在某些合理且实际的情况下,升级 ERC-20 代币的能力是可取的,例如:

  • 解决错误和消除限制
  • 采用新的特性和标准
  • 遵守不断变化的法规

使用 delegatecall 操作码的代理模式提供了一个合理的、通用的解决方案来协调不可变性和可升级性特性,但它也有其自身的缺点:

  • 智能合约必须从一开始就支持代理模式,即它不能用于没有通过代理部署的合约
  • 升级是静默的且不可逆的,即用户没有选择退出的选项

相比之下,通过将范围缩小到专门的 ERC-20 代币,本提案标准化了一个 ERC-20 扩展,它可以与任何现有或未来的 ERC-20 智能合约一起工作,实现和维护起来更简单,可以反转或嵌套,并为任何和所有用户提供双重确认机会以显式选择加入升级。

ERC-4931 试图通过引入第三个“桥”合约来解决相同的问题,以帮助促进升级/降级操作。虽然这种设计将升级/降级逻辑与代币逻辑分离,但 ERC-4931 将要求在目标智能合约上预先铸造代币,并由桥合约拥有,而不是在调用升级时按需进行。它也无法支持如下所述的升级时转移和穿透函数。

规范

本文档中的关键词 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, 和 “OPTIONAL” 按照 RFC 2119 和 RFC 8174 中的描述进行解释。

pragma solidity ^0.8.0;

/**
    @title 可升级的同质化代币
    @dev 参见 https://eips.ethereum.org/EIPS/eip-6864
 */
interface IERC6864 is IERC20 {
    /**
      @dev 当代币被升级时,必须发出
      @param from 基础 ERC-20 代币的先前所有者
      @param to ERC-6864 代币的新所有者
      @param amount 被升级的数量
    */
    event Upgrade(address indexed from, address indexed to, uint256 amount);

    /**
      @dev 当代币被降级时,必须发出
      @param from ERC-6864 代币的先前所有者
      @param to 基础 ERC-20 代币的新所有者
      @param amount 被降级的数量
    */
    event Downgrade(address indexed from, address indexed to, uint256 amount);

    /**
      @notice 将 `msg.sender` 拥有的 `amount` 个基础 ERC-20 代币升级为 `to` 名下的 ERC-6864 代币
      @dev `msg.sender` 必须直接拥有足够的基础 ERC-20 代币
      如果 `to` 是零地址,则必须回退
      如果 `msg.sender` 没有直接拥有 `amount` 个或更多的基础 ERC-20 代币,则必须回退
      @param to 接收 ERC-6864 代币的地址
      @param amount 要升级的基础 ERC-20 代币的数量
    */
    function upgrade(address to, uint256 amount) external;

    /**
      @notice 将 `from` 拥有的 `amount` 个 ERC-6864 代币降级为 `to` 名下的基础 ERC-20 代币
      @dev `msg.sender` 必须直接拥有或被批准花费 `from` 的足够 ERC-6864 代币
      如果 `to` 是零地址,则必须回退
      如果 `from` 没有直接拥有 `amount` 个或更多的 ERC-6864 代币,则必须回退
      如果 `msg.sender` 不是 `from` 且未被批准为 `from` 花费 `amount` 或更多的 ERC-6864 代币,则必须回退
      @param from 释放 ERC-6864 代币的地址
      @param to 接收基础 ERC-20 代币的地址
      @param amount 要降级的 ERC-6864 代币的数量
    */
    function downgrade(address from, address to, uint256 amount) external;

    /**
      @notice 获取基础 ERC-20 智能合约地址
      @return 基础 ERC-20 智能合约的地址
    */
    function baseToken() external view returns (address);
}

透视扩展

透视扩展是 OPTIONAL 的。它允许轻松查看此 ERC-6864 和基础 ERC-20 智能合约之间的组合状态。

pragma solidity ^0.8.0;

interface IERC6864SeeThrough is IERC6864 {
  /**
    @notice 获取此 ERC-6864 和基础 ERC-20 智能合约之间的组合代币总供应量
    @return 组合代币总供应量
  */
  function combinedTotalSupply() external view returns (uint256);

  /**
    @notice 获取 `account` 在此 ERC-6864 和基础 ERC-20 智能合约之间的组合代币余额
    @param account 拥有代币的地址
    @return 组合代币余额
  */
  function combinedBalanceOf(address account) external view returns (uint256);

  /**
    @notice 获取 `spender` 可以为 `owner` 花费的、在此 ERC-6864 和基础 ERC-20 智能合约之间的组合授权额度
    @param owner 拥有代币的地址
    @param spender 被批准花费代币的地址
    @return 组合花费授权额度
  */
  function combinedAllowance(address owner, address spender) external view returns (uint256);
}

理由

扩展 ERC-20 标准

本提案的目标是在不影响用户余额的情况下进行升级,因此利用现有的数据结构和方法是工程工作量最小的方式,也是互操作性最强的方式。

支持降级

降级能力使得在同一个基础 ERC-20 智能合约上的多个 IERC-6864 实现之间移动成为可能。如果发现 ERC-6864 智能合约存在错误或限制,或者用户只是改变了主意,它也提供了一种退出方式。

可选透视扩展

虽然这些函数在许多情况下都很有用,但它们实现起来很简单,并且可以通过其他公共函数计算结果,因此决定将它们包含在一个可选扩展中,而不是核心接口中。

向后兼容性

ERC-6864 通常与 ERC-20 标准兼容。唯一的注意事项是,一些智能合约可能会选择实现 transfer 以处理整个组合余额(这减少了用户摩擦,请参阅参考实现),而不是标准的 balanceOf 金额。在这种情况下,建议此类合约实现 totalSupplybalanceOf 以返回此 ERC-6864 和基础 ERC-20 智能合约之间的组合金额

参考实现

import {IERC20, ERC20} from "@openzeppelin-contracts/token/ERC20/ERC20.sol";

contract ERC6864 is IERC6864, ERC20 {
  IERC20 private immutable s_baseToken;

    constructor(string memory name, string memory symbol, address baseToken_) ERC20(name, symbol) {
        s_baseToken = IERC20(baseToken_);
    }

    function baseToken() public view virtual override returns (address) {
        return address(s_baseToken);
    }

    function upgrade(address to, uint256 amount) public virtual override {
        address from = _msgSender();

        s_baseToken.transferFrom(from, address(this), amount);
        _mint(to, amount);

        emit Upgrade(from, to, amount);
    }

    function downgrade(address from, address to, uint256 amount) public virtual override {
        address spender = _msgSender();

        if (from != spender) {
            _spendAllowance(from, spender, amount);
        }
        _burn(from, amount);
        s_baseToken.transfer(to, amount);

        emit Downgrade(from, to, amount);
    }

    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address from = _msgSender();
        uint256 balance = balanceOf(from);

        if (balance < amount) {
            upgrade(from, amount - balance);
        }

        _transfer(from, to, amount);
        return true;
    }

    function totalSupply() public view virtual override returns (uint256) {
        return super.totalSupply() + s_baseToken.totalSupply() - s_baseToken.balanceOf(address(this));
    }

    function balanceOf(address account) public view virtual override returns (uint256) {
        return super.balanceOf(account) + s_baseToken.balanceOf(account);
    }
}

安全考虑

  • 选择升级基础 ERC-20 代币的用户必须首先 approve ERC-6864 智能合约来花费它们。因此,用户有责任验证 ERC-6864 智能合约是健全和安全的,并且他或她批准的金额是适当的。这代表了与任何 approve 操作相同的安全考虑。
  • ERC-6864 智能合约可以为升级/降级实现任何适当的转换函数:1 对 1、线性、非线性。在非线性转换函数的情况下,upgradedowngrade 可能容易受到抢先交易或三明治攻击(无论是否对攻击者有利)。这代表了与任何使用类似非线性曲线进行转换的自动做市商 (AMM) 相同的安全考虑。
  • ERC-6864 智能合约可能会要求用户批准无限额度,和/或尝试在 transfer 期间自动升级(请参阅参考实现)。这消除了用户三重确认其升级意图的机会(approve 是双重确认)。
  • 多个 IERC-6864 实现可以应用于同一个基础 ERC-20 代币,并且 ERC-6864 智能合约可以嵌套。这将增加代币的复杂性,并可能导致现有仪表板报告不正确或不一致的结果。

版权

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

Citation

Please cite this document as:

Jeff Huang (@jeffishjeff), "ERC-6864: 可升级的同质化代币 [DRAFT]," Ethereum Improvement Proposals, no. 6864, April 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6864.