Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-7561: 简化的 NFT,简化的 ERC-721

专为合约钱包设计,从 ERC-721 中移除 safeTransferFrom、approve、setApprovalForAll、getApproved、isApprovedForAll 函数

Authors Xiang (@wenzhenxiang), Ben77 (@ben2077), Mingshi S. (@newnewsms)
Created 2023-10-29
Discussion Link https://ethereum-magicians.org/t/erc-7561-simple-nft/16695
Requires EIP-721

摘要

此 ERC 是一种基于用户合约钱包(包括账户抽象)设计的新型 NFT 资产,并且向前兼容 ERC-721。为了保持 NFT 资产的简单性,此 ERC 移除了 ERC-721 的 approvesetApprovalForAllgetApprovedisApprovedForAllsafeTransferFrom 函数。

动机

ERC-721 定义了基于以太坊的标准 NFT,可以进行交易和转移,但 ERC-721 的本质是基于外部拥有账户 (EOA) 钱包的设计。EOA 钱包没有状态和代码存储,智能合约钱包则不同。

几乎所有与 NFT 相关的 ERC 都是添加函数,但我们的观点恰恰相反。我们认为 NFT 合约应该更简单,更多功能由智能合约钱包负责。

我们的建议是基于智能合约钱包设计一种更简单的 NFT 资产。

它旨在实现以下目标:

  1. 保持 NFT 合约的简单性,仅负责 transferFrom 函数。
  2. approvegetApprovedsetApprovalForAllisApprovedForAll 函数不由 NFT 合约管理。相反,这些权限在用户级别进行管理,从而为用户提供更大的灵活性和控制权。此更改不仅增强了用户的自主权,还减轻了与 ERC-721 合约实施这些函数相关的一些风险。
  3. 移除 safeTransferFrom 函数。调用对方 NFT 资产的更好方法是访问对方自己的合约,而不是直接访问 NFT 资产合约。
  4. 与 ERC-721 的向前兼容性意味着所有 NFT 都可以与此提案兼容。

规范

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

兼容的合约必须实现以下接口:

pragma solidity ^0.8.20;

/**
 * @title ERC7561 简单 NFT 接口
 * @dev 查看 https://ercs.ethereum.org/ERCS/erc-7561
 */
interface IERC7561 {
    /**
     * @notice 用于通知转移 NFT。
     * @param from 来源地址
     * @param to 接收地址
     * @param tokenId 交易 token id
     */
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    /**
     * @notice 统计分配给所有者的所有 NFT
     * @param owner 所有者的地址
     * @return `owner` 拥有的 NFT 数量,可能为零
     */
    function balanceOf(address owner) 
        external
        view
        returns (uint256);

    /**
     * @notice 查找 NFT 的所有者
     * @param tokenId NFT 的标识符
     * @return NFT 所有者的地址
     */
    function ownerOf(uint256 tokenId) 
        external  
        view
        returns (address);
	  

    /**
     * @notice 转移 NFT 的所有权
     * @param from 来源地址
     * @param to 目的地址
     * @param tokenId 要转移的 NFT
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

}

原理

该提案旨在通过移除 approvesetApprovalForAllgetApprovedisApprovedForAllsafeTransferFrom 函数来简化 NFT 标准。这种简化旨在提高安全性、降低复杂性和提高效率,使该标准更适合智能合约钱包环境,同时保持基本功能。

向后兼容性

正如一开始所提到的,此 ERC 向前兼容 ERC-721,ERC-721 向后兼容此 ERC。

参考实现

向前兼容 ERC-721

pragma solidity ^0.8.20;

import "./IERC7561.sol";
import "../../math/SafeMath.sol";

/**
 * @title 标准 ERC7561 NFT
 * @dev 注意:此接口的 ERC-165 标识符为 0xc1b31357
 * @dev 基本标准 NFT 的实现。
 */
contract ERC7561 is IERC7561 {

    // Token 名称
    string private _name;

    // Token 符号
    string private _symbol;

    mapping(uint256 tokenId => address) private _owners;

    mapping(address owner => uint256) private _balances;

    uint256 private _totalSupply;

    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address owner) public view  returns (uint256) {
        require (owner != address(0));
        
        return _balances[owner];
    }

    function ownerOf(uint256 tokenId) public view  returns (address) {
        return _requireOwned(tokenId);
    }


    function transferFrom(address from, address to, uint256 tokenId) public  {

        require(from == msg.sender);

        require (to != address(0) );

        address previousOwner = _update(to, tokenId);

        require(previousOwner == from);
    }


    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    function _requireOwned(uint256 tokenId) internal view returns (address) {
        address owner = _ownerOf(tokenId);
        require(owner != address(0));
            
        return owner;
    }

    function _update(address to, uint256 tokenId) internal virtual returns (address) {
        address from = _ownerOf(tokenId);

        
        // 执行更新
        if (from != address(0)) {         

            unchecked {
                _balances[from] -= 1;
            }
        }

        if (to != address(0)) {
            unchecked {
                _balances[to] += 1;
            }
        }

        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        return from;
    }

}

安全注意事项

应该注意的是,此 ERC 与 ERC-721 不向后兼容,因此会与现有的 dapps 不兼容。

版权

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

Citation

Please cite this document as:

Xiang (@wenzhenxiang), Ben77 (@ben2077), Mingshi S. (@newnewsms), "ERC-7561: 简化的 NFT,简化的 ERC-721 [DRAFT]," Ethereum Improvement Proposals, no. 7561, October 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7561.