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.