Alert Source Discuss
Standards Track: ERC

ERC-5585: ERC-721 NFT 授权

允许 NFT 持有者授权其他用户使用他们的 NFT。

Authors Veega Labs (@VeegaLabsOfficial), Sean NG (@ngveega), Tiger (@tiger0x), Fred (@apan826), Fov Cao (@fovcao)
Created 2022-08-15
Requires EIP-721

摘要

此 EIP 将 ERC-721 NFT 的商业使用权与其所有权分离,以允许对这些权利进行独立管理。

动机

大多数 NFT 都有一个简化的所有权验证机制,只有一个 NFT 的所有者。在这种模式下,其他权利,如展示、创作衍生作品或分发,都无法授予,从而限制了 NFT 的价值和商业化。因此,分离 NFT 的所有权和使用权可以提高其商业价值。

商业权利是一个基于版权的广泛概念,包括复制、展示、分发、出租、商业使用、修改、复制和再许可等的权利。随着 Metaverse 的发展,NFT 变得更加多样化,出现了新的用例,如数字收藏品、虚拟房地产、音乐、艺术、社交媒体和各种数字资产。基于 NFT 的版权和授权正在成为一种潜在的商业形式。

规范

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

合约接口

interface IERC5585 {

    struct UserRecord {
        address user;
        string[] rights;
        uint256 expires;
    }

    /// @notice 获取此 NFT 项目的所有可用权利
    /// @return 可以授权给用户的所有权利
    function getRights() external view returns(string[]);

    /// @notice NFT 持有者将 NFT 的所有权利授权给用户指定的时间段
    /// @dev 零地址表示没有用户
    /// @param tokenId 被授权的 NFT
    /// @param user 被授权 NFT 的用户
    /// @param duration 授权持续的时间段
    function authorizeUser(uint256 tokenId, address user, uint duration) external;

    /// @notice NFT 持有者将特定权利授权给用户指定的时间段
    /// @dev 零地址表示没有用户。当权利未由此 NFT 项目定义时,将抛出异常
    /// @param tokenId 被授权的 NFT
    /// @param user 被授权 NFT 的用户
    /// @param rights 授权给用户的权利,例如租赁、分发或展示等
    /// @param duration 授权持续的时间段
    function authorizeUser(uint256 tokenId, address user, string[] rights, uint duration) external;
    
    /// @notice NFT 的用户将其权利转移给新用户
    /// @dev 零地址表示没有用户
    /// @param tokenId 此 NFT 的权利已转移给新用户
    /// @param newUser 新用户
    function transferUserRights(uint256 tokenId, address newUser) external;

    /// @notice NFT 持有者延长授权的持续时间
    /// @dev 零地址表示没有用户。当权利未由此 NFT 项目定义时,将抛出异常
    /// @param tokenId 已被授权的 NFT
    /// @param user 已被授权 NFT 的用户
    /// @param duration 授权的新持续时间
    function extendDuration(uint256 tokenId, address user, uint duration) external;

    /// @notice NFT 持有者更新授权的权利
    /// @dev 零地址表示没有用户
    /// @param tokenId 已被授权的 NFT
    /// @param user 已被授权 NFT 的用户
    /// @param rights 授权给用户的新权利
    function updateUserRights(uint256 tokenId, address user, string[] rights) external;

    /// @notice 获取指定 NFT 和用户的授权到期时间
    /// @dev 零地址表示没有用户
    /// @param tokenId 要获取用户到期时间的 NFT
    /// @param user 已被授权的用户
    /// @return 授权到期时间
    function getExpires(uint256 tokenId, address user) external view returns(uint);

    /// @notice 获取指定 NFT 和用户的权利
    /// @dev 零地址表示没有用户
    /// @param tokenId 要获取权利的 NFT
    /// @param user 已被授权的用户
    /// @return 已被授权的权利
    function getUserRights(uint256 tokenId, address user) external view returns(string[]);

    /// @notice 合约所有者可以更新每个 NFT 可以授权的用户数量
    /// @param userLimit 仅由运营商设置的用户数量限制
    function updateUserLimit(uint256 userLimit) external onlyOwner;

    /// @notice resetAllowed 标志可以由合约所有者更新,以控制是否可以撤销授权
    /// @param resetAllowed 这是一个布尔标志
    function updateResetAllowed(bool resetAllowed) external onlyOwner;

    /// @notice 检查 token 是否可用于授权
    /// @dev 如果 tokenId 不是有效的 NFT,则抛出异常
    /// @param tokenId 要检查可用性的 NFT
    /// @return true 或 false,表示 NFT 是否可用于授权
    function checkAuthorizationAvailability(uint256 tokenId) public view returns(bool);

    /// @notice 清除指定用户的授权
    /// @dev 零地址表示没有用户。当 resetAllowed 为 true 时,该函数有效,当为 false 时,将抛出异常
    /// @param tokenId 授权基于的 NFT
    /// @param user 将清除授权的用户
    function resetUser(uint256 tokenId, address user) external;


    /// @notice 当 NFT 的用户更改或授权到期时间更新时发出
    /// param tokenId 授权基于的 NFT
    /// param indexed user 被授权 NFT 的用户
    /// @param rights 授权给用户的权利
    /// @param expires 授权的到期时间
    event authorizeUser(uint256 indexed tokenId, address indexed user, string[] rights, uint expires);

    /// @notice 当每个 NFT 可以授权的用户数量更新时发出
    /// @param userLimit 仅由运营商设置的用户数量限制
    event updateUserLimit(uint256 userLimit);
}

getRights() 函数 MAY 被实现为 pure 和 view。

authorizeUser(uint256 tokenId, address user, uint duration) 函数 MAY 被实现为 publicexternal

authorizeUser(uint256 tokenId, address user, string[] rights; uint duration) 函数 MAY 被实现为 publicexternal

transferUserRights(uint256 tokenId, address newUser) 函数 MAY 被实现为 publicexternal

extendDuration(uint256 tokenId, address user, uint duration) 函数 MAY 被实现为 publicexternal

updateUserRights(uint256 tokenId, address user, string[] rights) 函数 MAY 被实现为 publicexternal

getExpires(uint256 tokenId, address user) 函数 MAY 被实现为 pureview

getUserRights(uint256 tokenId, address user) 函数 MAY 被实现为 pure 和 view。

updateUserLimit(unit256 userLimit) 函数 MAY 被实现为 publicexternal

updateResetAllowed(bool resetAllowed) 函数 MAY 被实现为 publicexternal

checkAuthorizationAvailability(uint256 tokenId) 函数 MAY 被实现为 pureview

resetUser(uint256 tokenId, address user) 函数 MAY 被实现为 publicexternal

当 NFT 的用户更改或授权到期时间更新时,必须发出 authorizeUser 事件。

当每个 NFT 可以授权的用户数量更新时,必须发出 updateUserLimit 事件。

理由

首先,NFT 合约所有者可以设置每个 NFT 的最大授权用户数,以及 NFT 所有者是否可以随时取消授权,以保护相关方的利益。

其次,有一个 resetAllowed 标志,用于控制合约所有者在 NFT 所有者和用户之间的权利。如果该标志设置为 true,则 NFT 所有者可以随时禁用所有授权用户的使用权。

第三,用户记录结构中的权利用于存储 NFT 所有者已授权给用户的权利,换句话说,NFT 所有者可以授权用户特定的权利,并在必要时更新它。

最后,这种设计可以与第三方无缝集成。它是 ERC-721 的扩展,因此可以轻松集成到新的 NFT 项目中。其他项目可以直接与这些接口和函数交互,以实现他们自己的交易类型。例如,公告平台可以使用此 EIP 允许所有 NFT 所有者随时进行授权或取消授权。

向后兼容性

此标准与 ERC-721 兼容,因为它它是它的扩展。

安全注意事项

resetAllowed 标志为 false 时,这意味着在授权期间 NFT 所有者无法撤销授权,EIP 的用户需要确保如果 NFT 出售给新的持有者,可以公平地分配授权费用。

以下是可供参考的解决方案:用户支付的授权费用可以保存在一个托管合约中一段时间,具体取决于授权的持续时间。例如,如果授权持续时间为 12 个月,总费用为 10 ETH,那么如果在 3 个月后转移 NFT,则只会发送 2.5 ETH,剩余的 7.5 ETH 将被退还。

版权

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

Citation

Please cite this document as:

Veega Labs (@VeegaLabsOfficial), Sean NG (@ngveega), Tiger (@tiger0x), Fred (@apan826), Fov Cao (@fovcao), "ERC-5585: ERC-721 NFT 授权," Ethereum Improvement Proposals, no. 5585, August 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5585.