diff --git a/EIPS/eip-2981.md b/EIPS/eip-2981.md index 1e8c9168..5c4ad3ed 100644 --- a/EIPS/eip-2981.md +++ b/EIPS/eip-2981.md @@ -12,24 +12,24 @@ requires: 165 ## Simple Summary -A standardized way to handle royalty payments for ERC-721 tokens, including publicly viewable royalty information and notification using a royalty payment event. +A standardized way to retrieve royalty payment information for ERC-721 tokens to enable universal support for royalty payments in all NFT marketplaces and ecosystem participants. ## Abstract -This standard extends the [ERC-721 specification](./eip-721.md) to enable setting a royalty amount paid to the NFT creator or rights holder every time an NFT is sold and re-sold. This is intended for NFT marketplaces that want to support the ongoing funding of artists and other NFT creators. The royalty payment must be voluntary as required by the EIP-721 standard, as `transferFrom()` includes NFT transfers between wallets, and executing `transferFrom()` does not always imply a sale occurred. Marketplaces and individuals implement this standard by retrieving the royalty payment information with `royaltyInfo()`, paying the proper royalty amount to the royalty recipient address, and calling `onRoyaltiesReceived()` to notify the NFT contract of the royalty payment. Payments are simple and sent only to a single address. This ERC should be considered a minimal, gas-efficient building block for further innovation in NFT royalty payments. +This standard extends the [ERC-721 specification](./eip-721.md) to enable setting a royalty amount paid to the NFT creator or rights holder every time an NFT is sold and re-sold. This is intended for NFT marketplaces that want to support the ongoing funding of artists and other NFT creators. The royalty payment must be voluntary as required by the EIP-721 standard, as `transferFrom()` includes NFT transfers between wallets, and executing `transferFrom()` does not always imply a sale occurred. Marketplaces and individuals implement this standard by retrieving the royalty payment information with `royaltyInfo()`, which specifies how much to pay to which address for a given sale price. The exact mechanism for paying and notifying the recipient will be defined in future EIPs. This ERC should be considered a minimal, gas-efficient building block for further innovation in NFT royalty payments. ## Motivation -There are many marketplaces for NFTs with multiple unique royalty payment implementations that are not easily compatible or usable by other marketplaces. Just like the early days of ERC-20 tokens, ERC-721 marketplace smart contracts are varied by ecosystem and not standardized. This EIP enables all marketplaces to pay the royalties that NFT creators specify and are entitled to, enabling accurate royalty payments regardless of which marketplace the NFT is sold or re-sold at. +There are many marketplaces for NFTs with multiple unique royalty payment implementations that are not easily compatible or usable by other marketplaces. Just like the early days of ERC-20 tokens, ERC-721 marketplace smart contracts are varied by ecosystem and not standardized. This EIP enables all marketplaces to retrieve royalty payment information that NFT creators specify and are entitled to, enabling accurate royalty payments regardless of which marketplace the NFT is sold or re-sold at. -Many of the largest ERC-721 marketplaces have implemented royalty payments that are incompatible with other platforms and therefore make it much harder to enforce when the NFT is sold on another marketplace, not fulfilling the potential of any implemented royalty system. This standard is a way to implement royalties that can be accepted across any type of NFT marketplace. This minimalist proposal allows for standardized royalties to be accepted on all marketplaces - leaving the actual funds transfer up to the marketplace itself, and only providing a means to fetch the royalty amounts and an event to be emitted when the transfer has happened. +Many of the largest ERC-721 marketplaces have implemented royalty payments that are incompatible with other platforms and therefore make it much harder to enforce when the NFT is sold on another marketplace, not fulfilling the potential of any implemented royalty system. This standard implements standardized royalty information retrieval that can be accepted across any type of NFT marketplace. This minimalist proposal leaves the actual funds transfer up to the marketplace itself, and only provides a mechanism to fetch the royalty amounts. Future EIPs may build on this ERC to implement payment notifications and other features. -This standard extends the [ERC-721 specification](./eip-721.md) to enable setting a royalty amount paid to the NFT creator or rights holder every time an NFT is sold and re-sold. If a marketplace chooses *not* to implement this EIP, then obviously no funds are paid for secondary sales. But as most NFT marketplaces have developed some unique royalty system themselves - and all of them are singular and only work within their own contracts - there should be an accepted standard for paying royalties, if the creator chooses to set royalties on their NFTs. We believe the NFT marketplace ecosystem will voluntarily implement royalty payments to provide ongoing funding for artists and other creators, and NFT buyers will assess the royalty payment as a factor when making NFT purchasing decisions. +This standard extends the [ERC-721 specification](./eip-721.md) to enable setting a royalty amount paid to the NFT creator or rights holder every time an NFT is sold and re-sold. If a marketplace chooses *not* to implement this EIP, then obviously no funds are paid for secondary sales. But as most NFT marketplaces have developed some unique royalty system themselves - and all of them are singular and only work within their own contracts - there should be an accepted standard for royalty payment information (if the creator chooses to set royalties on their NFTs). We believe the NFT marketplace ecosystem will voluntarily implement royalty payments to provide ongoing funding for artists and other creators, and NFT buyers will assess the royalty payment as a factor when making NFT purchasing decisions. Without an agreed royalty payment standard, the NFT ecosystem will lack an effective means to collect royalties across all marketplaces and artists and other creators will not receive ongoing funding. This will hamper the growth and adoption of NFTs and demotivate artists and other NFT creators from minting new and innovative tokens. *"Yes we have royalties, but if your NFT is sold on another marketplace, we cannot provide royalties" ... "But can't I sell my NFT anywhere with a click of my wallet?" ... "Yes... but we don't have a standard for royalties so you'll lose out."* -This EIP fixes this issue, enabling all NFT marketplaces to unify on a single royalty payment standard and benefiting the entire NFT ecosystem. +This EIP fixes this issue, enabling all NFT marketplaces to unify on a single royalty payment information standard and benefiting the entire NFT ecosystem. ## Specification @@ -38,17 +38,13 @@ NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119. -**ERC-721 compliant contracts MAY implement this ERC for royalties to provide a standard method of accepting royalty payments and receiving royalty information.** +**ERC-721 compliant contracts MAY implement this ERC for royalties to provide a standard method of specifying royalty payment information.** -The `amount` returned by `royaltyInfo()` **MUST** be a percentage fixed point with a scaling factor of 100000 `(X/100000)` - such as "500000" - for 5% (i.e. 5 decimals). This is **REQUIRED** to maintain uniformity across the standard. The max and min values would be 10000000 (100%) and 1 (0.00001%). This fits snugly into the `uint24` type to minimize storage costs, and can easily be cast to other `uint` types as needed (i.e. `uint256(0x1234)`). +Marketplaces that support this standard **SHOULD** implement some method of transferring royalties to the royalty recipient. Standards for the actual transfer and notification of funds will be specified in future EIPs. -Marketplaces that support this standard **MAY** implement any method of calculating or transferring royalties to the royalty recipient. +Implementers of this standard **MUST NOT** use the `_data` parameter and `_royaltyPaymentData` return value. These are intended for future EIPs that extend this ERC with additional features. -Marketplaces that support this standard **MUST** call the `onRoyaltiesReceived()` function on the NFT contract after sending a payment, which will automatically emit the `RoyaltiesReceived` event. - -Implementers of this standard **MUST** emit the `RoyaltiesReceived` event when `onRoyaltiesReceived()` is called. Implementers may do any other logic inside of this call, provided the `RoyaltiesReceived` event is emitted. - -Implementers of this standard **MUST** have all of the following events and functions: +Implementers of this standard **MUST** have all of the following functions: ```solidity pragma solidity ^0.6.0; @@ -61,48 +57,23 @@ interface IERC2981 is ERC165 { /// ERC165 bytes to add to interface array - set in parent contract /// implementing this standard /// - /// bytes4(keccak256("royaltyInfo(uint256)")) == 0xcef6d368 - /// bytes4(keccak256("onRoyaltiesReceived(address,address,uint256,address,uint256,bytes32)")) == 0xe8cb9d99 - /// bytes4(0xcef6d368) ^ bytes4(0xe8cb9d99) == 0x263d4ef1 - /// bytes4 private constant _INTERFACE_ID_ERC721ROYALTIES = 0x263d4ef1; + /// bytes4(keccak256("royaltyInfo(uint256,uint256,bytes)")) == 0x6057361d + /// bytes4 private constant _INTERFACE_ID_ERC721ROYALTIES = 0x6057361d; /// _registerInterface(_INTERFACE_ID_ERC721ROYALTIES); - /// @notice Called to return both the creator's address and the royalty percentage + /// @notice Called with the sale price to determine how much royalty + // is owed and to whom. /// @param _tokenId - the NFT asset queried for royalty information - /// @return receiver - address of who should be sent the royalty payment - /// @return amount - a percentage calculated as a fixed point - /// with a scaling factor of 100000 (5 decimals), such that - /// 100% would be the value 10000000, as 10000000/100000 = 100. - /// 1% would be the value 100000, as 100000/100000 = 1 - function royaltyInfo(uint256 _tokenId) external returns (address receiver, uint24 amount); - - /// @notice Called when royalty is transferred to the receiver. This - /// emits the RoyaltiesReceived event as we want the NFT contract - /// itself to contain the event for easy tracking by royalty receivers. - /// @param _royaltyRecipient - The address of who is entitled to the - /// royalties as specified by royaltyInfo(). - /// @param _buyer - If known, the address buying the NFT on a secondary - /// sale. 0x0 if not known. - /// @param _tokenId - the ID of the ERC-721 token that was sold - /// @param _tokenPaid - The address of the ERC-20 token used to pay the - /// royalty fee amount. Set to 0x0 if paid in the - /// native asset (ETH). - /// @param _amount - The amount being paid to the creator using the - /// correct decimals from _tokenPaid's ERC-20 contract - /// (i.e. if 7 decimals, 10000000 for 1 token paid) - /// @param _metadata - Arbitrary data attached to this payment - /// @return `bytes4(keccak256("onRoyaltiesReceived(address,address,uint256,address,uint256,bytes32)"))` - function onRoyaltiesReceived(address _royaltyRecipient, address _buyer, uint256 _tokenId, address _tokenPaid, uint256 _amount, bytes32 _metadata) external returns (bytes4); - - /// @dev This event MUST be emitted by `onRoyaltiesReceived()`. - event RoyaltiesReceived( - address indexed _royaltyRecipient, - address indexed _buyer, - uint256 indexed _tokenId, - address _tokenPaid, - uint256 _amount, - bytes32 _metadata - ); + /// @param _value - the sale price of the NFT asset specified by _tokenId + /// @param _data - information used by extensions of this ERC. + /// Must not to be used by implementers of EIP-2981 + /// alone. + /// @return _receiver - address of who should be sent the royalty payment + /// @return _royaltyAmount - the royalty payment amount for _value sale price + /// @return _royaltyPaymentData - information used by extensions of this ERC. + /// Must not to be used by implementers of + /// EIP-2981 alone. + function royaltyInfo(uint256 _tokenId, uint256 _value, bytes calldata _data) external returns (address _receiver, uint256 _royaltyAmount, bytes memory _royaltyPaymentData); /// @notice Informs callers that this ERC721 supports ERC2981 /// @dev If `_registerInterface(_INTERFACE_ID_ERC721ROYALTIES)` is called @@ -119,7 +90,7 @@ interface IERC2981 is ERC165 { This standard being used on an ERC-721 during deployment: -#### Deploying an ERC-721 and setting the royalty amount and creator +#### Deploying an ERC-721 and signaling support for ERC-2981 ```solidity constructor (string memory name, string memory symbol, string memory baseURI) public Royalties(royalty_amount, msg.sender) { @@ -141,57 +112,30 @@ Note: using address.call() is completely **OPTIONAL** and is just one method. ```solidity function checkRoyalties(address _token) internal returns (bool) { - (bool success) = address(_token).call(abi.encodeWithSignature("royaltyInfo(uint256)")); + (bool success) = address(_token).call(abi.encodeWithSignature("royaltyInfo(uint256,uint256,bytes)")); return success; } ``` -**Transferring funds (ETH) and calling function to emit the RoyaltiesReceived event inside the NFT contract** - -```solidity - _recipient.transfer(amount); - IERC2981(_tokenAddress).onRoyaltiesReceived(_recipient, _buyer, _tokenId, address(0), amount, _metadata); -``` - -**Transferring funds (USDC) and calling function to emit the RoyaltiesReceived event inside the NFT contract** - -```solidity - IERC20(0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48).transfer(_recipient, amount); - IERC2981(_tokenAddress).onRoyaltiesReceived(_recipient, _buyer, _tokenId, address(0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48), amount, _metadata); -``` - ## Rationale ### Optional royalty payments -It is impossible to know which NFT transfers are the result of sales, and which are merely wallets moving or consolidating their NFTs. Therefore, we cannot force every `transferFrom()` call to involve a royalty payment, as not every transfer is a sale that would require such payment. We believe the NFT marketplace ecosystem will voluntarily implement this royalty payment standard to provide ongoing funding for artists and other creators, and NFT buyers will assess the royalty payment percentage as a factor when making NFT purchasing decisions. +It is impossible to know which NFT transfers are the result of sales, and which are merely wallets moving or consolidating their NFTs. Therefore, we cannot force every `transferFrom()` call to involve a royalty payment, as not every transfer is a sale that would require such payment. We believe the NFT marketplace ecosystem will voluntarily implement this royalty payment standard to provide ongoing funding for artists and other creators, and NFT buyers will assess the royalty payment as a factor when making NFT purchasing decisions. ### Simple royalty payments to a single address -It is impossible to fully know and efficiently implement all possible types of royalty payments and logic, so it is on the royalty payment receiver to implement all additional complexity and logic for fee splitting, multiple receivers, taxes, accounting, etc. in their own receiving contract or off-chain. If we attempted to do this as part of this standard, it would dramatically increase the implementation complexity, increase gas costs, and could not possibly cover every potential use-case. Therefore, implementers desiring more complex royalty payment logic should create their own smart contract that implements their own requirements upon the receipt of ETH or ERC20 tokens and / or the execution of `onRoyaltiesReceived()`. This ERC should be considered a minimal, gas-efficient building block for further innovation in NFT royalty payments. +This EIP does not specify the manner of payment to the royalty recipient. Furthermore, it is impossible to fully know and efficiently implement all possible types of royalty payments logic, so it is on the royalty payment receiver to implement all additional complexity and logic for fee splitting, multiple receivers, taxes, accounting, etc. in their own receiving contract or off-chain. If we attempted to do this as part of this standard, it would dramatically increase the implementation complexity, increase gas costs, and could not possibly cover every potential use-case. This ERC should be considered a minimal, gas-efficient building block for further innovation in NFT royalty payments. Future EIPs can specify more details regarding payment transfer and notification. -### Fixed percentage to 10^5 (100000) +### Royalty payment amounts over percentages -Having the flexibility to set any percentage a creator likes is important - although the reality of having users want a 0.00000000001% fee is not very likely. Instead the value can be limited to 5 decimal places with the lowest percentage being 0.00001% and the cap at 100%. It also allows us to store the value in a `uint24`, reducing storage costs. +This EIP does not specify how the `_royaltyAmount` is calculated from the sale price `_value`. Many NFT contracts may follow a fixed-percentage royalty that is the same regardless of price. However, EIP-2981 implementers may choose whatever logic they want to calculate the `_royaltyAmount` - this EIP does not mandate a fixed-percentage fee model. -### Emitting event for payment on the NFT contract itself +Additionally, we return a specific `_royaltyAmount` so there is no dispute with a marketplace over how much is owed for a given sale price. -Choosing to emit an event for payment is important as each NFT contract is standalone, and while a marketplace contract can emit events that an NFT is sold, the royalty recipient might not be aware or watching the marketplace for a secondary sale of their NFT and therefore would never know they received a payment except for having an increased amount of ETH or ERC20 tokens in their wallet randomly. Watching for a royalty event only on the contract of the NFT being sold is an easy way for the recipient to check on payments received by their secondary sales without needing to watch every marketplace contract in existence. - -### Structure of the RoyaltiesReceived event - -The `RoyaltiesReceived` event will help future-proof this standard and allow potential enhancements in future EIPs. - -`royaltyRecipient` allows multiple royalty recipients to exist in the same ERC-721 contract, and indexing it allows a receiver to track payments to themselves easily. - -`buyer` enables tracking specific buyers of NFTs for analytics purposes. - -`tokenId` allows easy tracking of specific NFT sales. - -`tokenPaid` enables ERC-20 tokens to be used in addition to native ETH. - -`metadata` helps more advanced use-cases, perhaps described in future EIPs. `onRoyaltiesReceived()` is assumed to be called within the same transaction of the royalty payment, making the knowledge of the transaction hash and total amount of the sale easy to know. But if there are many small sales, sending many tiny transfers of ERC-20 tokens and calling `onRoyaltiesReceived()` for each could get expensive. This field could potentially enable a batched payment standard (monthly, quarterly, etc.), with some sort of data stored here that helps identify which sales this payment was for. +### Unused data parameters in function signature +This EIP mandates the inclusion of the `_data` parameter and the `_royaltyPaymentData` return value, and also mandates that these are unused. The purpose of this is to have a seamless path to build on this ERC by further EIP standards that specify payment notifications, fee splitting, and other advanced use cases. ## Backwards Compatibility