ERC-5585 NFT rights delegation standard (ERC-721 NFT Authorization)
Final · NFTs & multi-token · created 2022-08-15
An ERC-721 extension standard that separates NFT ownership from commercial usage rights, allowing an owner to delegate specific rights to other users for a set period.
Why it is needed
Most NFTs have a simple ownership structure with only one owner. In this structure there is no way to grant other rights separately, such as exhibition, derivative works, and distribution, which limits the value and commercialization of NFTs. A commercial right is a broad concept based on copyright, and includes reproduction, exhibition, distribution, rental, commercial use, modification, and sublicensing. As the metaverse develops, NFTs are diversifying into all kinds of digital assets, such as digital collectibles, virtual real estate, music, art, and social media, and copyright and licensing based on NFTs can become a new form of business. Separating ownership from usage rights so that each can be managed independently can therefore increase the commercial value of NFTs.
What to implement
function getRights() external view returns(string[]);: Returns the list of all rights that this NFT project can delegate to users.function authorizeUser(uint256 tokenId, address user, uint duration) external;: The NFT holder delegates all of the NFT's rights to a user for a specified period.function authorizeUser(uint256 tokenId, address user, string[] rights, uint duration) external;: The NFT holder delegates only selected rights, such as rental, distribution, or exhibition, to a user for a specified period. An exception is thrown if a right is not defined in the project.function transferUserRights(uint256 tokenId, address newUser) external;: A user of the NFT passes the rights delegated to them on to a new user.function extendDuration(uint256 tokenId, address user, uint duration) external;: The NFT holder extends the duration of rights that have already been delegated.function updateUserRights(uint256 tokenId, address user, string[] rights) external;: The NFT holder updates the rights delegated to a user with a new list of rights.function getExpires(uint256 tokenId, address user) external view returns(uint);: Returns the delegation expiry time for the specified NFT and user.function getUserRights(uint256 tokenId, address user) external view returns(string[]);: Returns the list of rights delegated for the specified NFT and user.function updateUserLimit(uint256 userLimit) external onlyOwner;: The contract owner updates the number of users to whom each NFT can be delegated.function updateResetAllowed(bool resetAllowed) external onlyOwner;: The contract owner updates the resetAllowed flag, which indicates whether a delegation can be cancelled midway.function checkAuthorizationAvailability(uint256 tokenId) public view returns(bool);: Returns true or false for whether the NFT is currently in a state where it can be delegated. An exception is thrown if the NFT is not valid.function resetUser(uint256 tokenId, address user) external;: Revokes the delegation for the specified user. It works only when resetAllowed is true, and throws an exception when it is false.event authorizeUser(uint256 indexed tokenId, address indexed user, string[] rights, uint expires);: An event emitted when the user of an NFT changes or the delegation expiry time is updated.event updateUserLimit(uint256 userLimit);: An event emitted when the number of users an NFT can be delegated to is updated.
In depth
The UserRecord struct and the rights model
Delegation information is stored in the UserRecord struct. user is the address of the delegated user, rights is an array of strings for the delegated rights, and expires is the expiry time. Rights are expressed as strings such as rental, distribution, and exhibition, and the full list of rights defined by a project can be queried with getRights(). Attempting to delegate an undefined right throws an exception. In all functions, the zero address means there is no user. An NFT owner can delegate only selected rights and update them with updateUserRights() when needed.
Two overloads of authorizeUser
authorizeUser(uint256 tokenId, address user, uint duration) delegates all of the NFT's rights for the specified period, and authorizeUser(uint256 tokenId, address user, string[] rights, uint duration) delegates only specific rights. Both functions can be implemented as public or external. After delegation, the duration can be extended with extendDuration() and the rights can be changed with updateUserRights(), and a user can transfer their rights to a new user with transferUserRights().
Contract owner controls
The contract owner manages two global settings. updateUserLimit(uint256 userLimit) sets the number of users to whom each NFT can be delegated, and updateResetAllowed(bool resetAllowed) sets whether a delegation can be cancelled midway. Both functions carry the onlyOwner restriction. If resetAllowed is true, the NFT owner can release the usage rights of all delegated users at any time with resetUser(), and if it is false, calling resetUser() throws an exception. This is a design to protect the interests of the parties involved.
Event emission rules
The authorizeUser event MUST be emitted when the user of an NFT changes or the delegation expiry time is updated, with tokenId and user recorded as indexed and rights and expires included. The updateUserLimit event MUST be emitted when the number of users an NFT can be delegated to is updated. The query functions getExpires(), getUserRights(), getRights(), and checkAuthorizationAvailability() can be implemented as pure or view.
Compatibility as an ERC-721 extension
This standard is an extension of ERC-721, so it is compatible with ERC-721 and can be easily integrated into new NFT projects. Other projects can interact directly with this interface to implement their own forms of transactions. As an example, the original text describes a case where a notice platform uses this standard to let any NFT owner delegate and revoke at any time. This proposal is a finalized standard in Final status.
Things to watch out for
- Settling delegation fees when resetAllowed is false: When resetAllowed is false, the NFT owner cannot cancel a delegation during the delegation period. If the NFT is then sold to a new holder, a way is needed to fairly split the delegation fee the user paid. The original text suggests an escrow contract as a reference solution. Fees are held in escrow according to the delegation period. For example, if the delegation period is 12 months and the fee is 10 ETH in total, and the NFT is transferred after 3 months, only 2.5 ETH is paid out and the remaining 7.5 ETH is refunded.