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 的 approve
、setApprovalForAll
、getApproved
、isApprovedForAll
和 safeTransferFrom
函数。
动机
ERC-721 定义了基于以太坊的标准 NFT,可以进行交易和转移,但 ERC-721 的本质是基于外部拥有账户 (EOA) 钱包的设计。EOA 钱包没有状态和代码存储,智能合约钱包则不同。
几乎所有与 NFT 相关的 ERC 都是添加函数,但我们的观点恰恰相反。我们认为 NFT 合约应该更简单,更多功能由智能合约钱包负责。
我们的建议是基于智能合约钱包设计一种更简单的 NFT 资产。
它旨在实现以下目标:
- 保持 NFT 合约的简单性,仅负责
transferFrom
函数。 approve
、getApproved
、setApprovalForAll
和isApprovedForAll
函数不由 NFT 合约管理。相反,这些权限在用户级别进行管理,从而为用户提供更大的灵活性和控制权。此更改不仅增强了用户的自主权,还减轻了与 ERC-721 合约实施这些函数相关的一些风险。- 移除
safeTransferFrom
函数。调用对方 NFT 资产的更好方法是访问对方自己的合约,而不是直接访问 NFT 资产合约。 - 与 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;
}
原理
该提案旨在通过移除 approve
、setApprovalForAll
、getApproved
、isApprovedForAll
和 safeTransferFrom
函数来简化 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.