Alert Source Discuss
🚧 Stagnant Standards Track: ERC

ERC-5334: EIP-721 用户、过期时间和级别扩展

为 EIP-721 代币添加具有受限权限的限时角色(`user`)。

Authors Yan (@yan253319066)
Created 2022-07-25
Discussion Link https://ethereum-magicians.org/t/erc-721-user-and-expires-and-level-extension/10097
Requires EIP-165, EIP-721

摘要

EIP-721 扩展,它添加了一个可以授予给地址的附加角色(user),以及角色自动撤销的时间(expires)和(level)。user 角色表示“使用” NFT 的权限,但不表示转移它或设置用户的能力。

动机

一些 NFT 具有某些效用。 例如,虚拟土地可以“使用”来构建场景,而代表游戏资产的 NFT 可以在游戏中“使用”。 在某些情况下,所有者和用户可能并不总是相同的。 可能存在一个 NFT 的所有者将其出租给“用户”。 “用户”应该能够对 NFT 执行的操作与“所有者”不同(例如,“用户”通常不应该能够出售 NFT 的所有权)。 在这些情况下,拥有单独的角色来识别地址是代表“所有者”还是“用户”,并相应地管理执行操作的权限是有意义的。

一些项目已经以不同的名称(例如“operator”或“controller”)使用这种设计方案,但随着它变得越来越普遍,我们需要一个统一的标准来促进所有应用程序之间的协作。

此外,这种模型的应用(例如租赁)通常要求用户地址只能临时访问使用 NFT。 通常,这意味着所有者需要提交两次链上交易,一次是在持续时间开始时将新地址列为新的用户角色,一次是在结束时回收用户角色。 这在人工和 gas 方面都是低效的,因此引入了“expires”和“level”函数,这将有助于自动结束使用期限,而无需进行第二次交易。

以下是此标准解决的一些问题:

明确的权利分配

通过双重“所有者”和“用户”角色,管理贷方和借方可以对 NFT 做什么和不能做什么(换句话说,他们的权利)变得更加容易。 此外,所有者可以控制谁是用户,其他项目也很容易将他们自己的权利分配给所有者或用户。

简单的链上时间管理

一旦租借期结束,用户角色需要重置,“用户”必须失去使用 NFT 的权利。 这通常通过第二次链上交易来完成,但这在 gas 方面效率低下,并且可能导致复杂情况,因为它不精确。 借助 expires 函数,无需进行另一次交易,因为“用户”在持续时间结束后会自动失效。

简单的第三方集成

本着无需许可的互操作性的精神,该标准使第三方协议更容易管理 NFT 使用权,而无需 NFT 发行者或 NFT 应用程序的许可。 一旦项目采用了额外的 user 角色和 expireslevel,任何其他项目都可以直接与这些功能交互并实现他们自己的交易类型。 例如,使用此标准的 PFP NFT 可以集成到租赁平台(用户可以在其中租用 NFT 30 天)和抵押贷款平台(用户可以在最终通过分期付款购买 NFT 所有权的同时使用该 NFT)。 这都无需原始 PFP 项目的许可即可完成。

规范

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

合约接口

带有 NatSpec 和 OpenZeppelin v4 接口的 Solidity 接口(也可在 IERC5334.sol 中获得):

interface IERC5334 {

    // Logged when the user of a NFT, expires, or level is changed
    /// @notice Emitted when the `user` of an NFT or the `expires` of the `user` is changed or the user `level` is changed
    /// @notice 当 NFT 的 `user`、`expires` 或 `level` 更改时触发
    /// The zero address for user indicates that there is no user address
    /// @dev 用户的零地址表示没有用户地址
    event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires, uint8 level);

    /// @notice set the user and expires and level of a NFT
    /// @notice 设置 NFT 的用户、过期时间 (expires) 和级别 (level)
    /// @dev The zero address indicates there is no user
    /// @dev 零地址表示没有用户
    /// Throws if `tokenId` is not valid NFT
    /// @dev 如果 `tokenId` 不是有效的 NFT 则抛出
    /// @param user  The new user of the NFT
    /// @param user  NFT 的新用户
    /// @param expires  UNIX timestamp, The new user could use the NFT before expires
    /// @param expires  UNIX 时间戳,新用户可以在过期时间之前使用 NFT
    /// @param level user level
    /// @param level 用户级别
    function setUser(uint256 tokenId, address user, uint64 expires, uint8 level) external;

    /// @notice Get the user address of an NFT
    /// @notice 获取 NFT 的用户地址
    /// @dev The zero address indicates that there is no user or the user is expired
    /// @dev 零地址表示没有用户或用户已过期
    /// @param tokenId The NFT to get the user address for
    /// @param tokenId 要获取用户地址的 NFT
    /// @return The user address for this NFT
    /// @return 此 NFT 的用户地址
    function userOf(uint256 tokenId) external view returns(address);

    /// @notice Get the user expires of an NFT
    /// @notice 获取 NFT 的用户过期时间
    /// @dev The zero value indicates that there is no user
    /// @dev 零值表示没有用户
    /// @param tokenId The NFT to get the user expires for
    /// @param tokenId 要获取用户过期时间的 NFT
    /// @return The user expires for this NFT
    /// @return 此 NFT 的用户过期时间
    function userExpires(uint256 tokenId) external view returns(uint256);

    /// @notice Get the user level of an NFT
    /// @notice 获取 NFT 的用户级别
    /// @dev The zero value indicates that there is no user
    /// @dev 零值表示没有用户
    /// @param tokenId The NFT to get the user level for
    /// @param tokenId 要获取用户级别的 NFT
    /// @return The user level for this NFT
    /// @return 此 NFT 的用户级别
    function userLevel(uint256 tokenId) external view returns(uint256);
}

userOf(uint256 tokenId) 函数可以实现为 pureview

userExpires(uint256 tokenId) 函数可以实现为 pureview

userLevel(uint256 tokenId) 函数可以实现为 pureview

setUser(uint256 tokenId, address user, uint64 expires) 函数可以实现为 publicexternal

当用户地址更改或用户过期时间更改或用户级别更改时,必须发出 UpdateUser 事件。

原理

待定

向后兼容性

如规范部分所述,通过添加扩展函数集,此标准可以完全与 EIP-721 兼容。

此外,此标准中引入的新函数与 EIP-721 中的现有函数有很多相似之处。 这使开发人员可以轻松快速地采用该标准。

参考实现

可以在 assets 文件夹中找到此标准的参考实现。

安全注意事项

此 EIP 标准可以完全保护所有者的权利,所有者可以随时更改 NFT 用户、过期时间和级别。

版权

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

Citation

Please cite this document as:

Yan (@yan253319066), "ERC-5334: EIP-721 用户、过期时间和级别扩展 [DRAFT]," Ethereum Improvement Proposals, no. 5334, July 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5334.