Alert Source Discuss
🚧 Stagnant Standards Track: ERC

ERC-5560: 可兑换 NFT

使 NFT 可以兑换实物

Authors Olivier Fernandez (@fernandezOli), Frédéric Le Coidic (@FredLC29), Julien Béranger (@julienbrg)
Created 2022-08-30
Discussion Link https://ethereum-magicians.org/t/eip-redeemable-nft-extension/10589
Requires EIP-165, EIP-721

摘要

该 EIP 是一个可兑换 NFT 扩展,它向 EIP-721 添加了一个 redeem 函数。当 NFT 发行者希望将其 NFT 兑换为实物时,可以实现它。

动机

越来越多的 NFT 发行者,如艺术家、美术馆、拍卖行、品牌等,希望向给定 NFT 的持有者提供实物。这个标准允许 EIP-721 NFT 发出可兑换的信号。

规范

本文档中使用的关键词“必须”,“禁止”,“需要”,“应该”,“不应该”,“推荐”,“可以”和“可选”按照 RFC 2119 中的描述进行解释。

符合 EIP-721 的合约可以实现此 EIP,以提供接收有关可兑换性的信息的标准方法。

NFT 发行者必须决定谁可以兑换 NFT,并相应地限制对 redeem() 函数的访问。

任何人可以访问 isRedeemable() 函数来检查可兑换状态:当 NFT 可兑换时,它返回 true,当已经兑换时,返回 false

支持此标准的第三方服务可以使用 Redeem 事件来监听 NFT 的可兑换状态的变化。

此标准的实现者必须具有以下所有功能:

import '@openzeppelin/contracts/utils/introspection/ERC165.sol';

/**
 * @dev 可兑换 ERC-721 的实现
 *
 */

interface IRedeemable is ERC165 {
	/*
	 * ERC165 字节添加到接口数组 - 在实现此标准的父合约中设置
	 *
	 * bytes4 private constant _INTERFACE_ID_ERC721REDEEM = 0x2f8ca953;
	 */
	 
	/// @dev 当 token 被兑换时,会发出此事件。
	event Redeem(address indexed from, uint256 indexed tokenId);
	 
	/// @notice 返回 token 的兑换状态
	/// @param tokenId Token 的标识符。
	function isRedeemable(uint256 _tokenId) external view returns (bool);

	/// @notice 兑换 token
	/// @param tokenId 要兑换的 Token 的标识符
	function redeem(uint256 _tokenId) external;
}

当调用 redeem() 函数时,会发出 Redeem 事件。

当使用 0x2f8ca953 调用时,supportsInterface 方法必须返回 true

理由

当部署 NFT 合约时,isRedeemable() 函数默认返回 true

默认情况下,redeem() 函数的可见性是 public,因此任何人都可以触发它。推荐添加一个 require 来限制访问:

require(ownerOf(tokenId) == msg.sender, "ERC721Redeemable: You are not the owner of this token");

在触发 redeem() 函数后,isRedeemable() 函数返回 false

Redeem 事件

当触发 redeem() 函数时,必须发出以下事件:

event Redeem(address indexed from, uint256 indexed tokenId);

向后兼容性

此标准与 EIP-721 兼容。

参考实现

这是一个包含可兑换扩展的 EIP-721 示例:

contract ERC721Redeemable is ERC721, Redeemable {

	constructor(string memory name, string memory symbol) ERC721(name, symbol) {
	}

	function isRedeemable(uint256 tokenId) public view virtual override returns (bool) {
		require(_exists(tokenId), "ERC721Redeemable: Redeem query for nonexistent token");
		return super.isRedeemable(tokenId);
	}

	function redeem(uint256 tokenId) public virtual override {
		require(_exists(tokenId), "ERC721Redeemable: Redeem query for nonexistent token");
		require(ownerOf(tokenId) == msg.sender, "ERC721Redeemable: You are not the owner of this token");
		super.redeem(tokenId);
	}

	function supportsInterface(bytes4 interfaceId) public view override(ERC721, Redeemable) returns (bool) {
		return super.supportsInterface(interfaceId);
	}
}

安全考虑

需要讨论。

版权

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

Citation

Please cite this document as:

Olivier Fernandez (@fernandezOli), Frédéric Le Coidic (@FredLC29), Julien Béranger (@julienbrg), "ERC-5560: 可兑换 NFT [DRAFT]," Ethereum Improvement Proposals, no. 5560, August 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5560.