Setting ERC2981

Hi everybody
I have taken a look at the royalty contract of an NFT

// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Storage.sol";
import "./IERC2981.sol";

abstract contract ERC2981 is IERC2981, ERC165Storage {
  using SafeMath for uint256;

  // Bytes4 Code for EIP-2981
  bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;

  // Mappings _tokenID -> values
  mapping(uint256 => address) receiver;
  mapping(uint256 => uint256) royaltyPercentage;

  constructor() {

    // Using ERC165Storage set EIP-2981


  // Set to be internal function _setReceiver
  function _setReceiver(uint256 _tokenId, address _address) internal {
    receiver[_tokenId] = _address;

  // Set to be internal function _setRoyaltyPercentage
  function _setRoyaltyPercentage(uint256 _tokenId, uint256 _royaltyPercentage) internal {
    royaltyPercentage[_tokenId] = _royaltyPercentage;

  // Override for royaltyInfo(uint256, uint256)
  // uses SafeMath for uint256
  function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view override(IERC2981) returns (address Receiver, uint256 royaltyAmount) {
    Receiver = receiver[_tokenId];
    royaltyAmount = _salePrice.div(100).mul(royaltyPercentage[_tokenId]);

I was wondering, such is the implementation, should we record in each token about the percentage of royalties and who is the owner of NFT?

Will the token sales platform be in charge of changing the receiver for each sale?


1 Like

Royalty in the EIP-2981 sense is a share of payment owed from each sale to the original author (the creator, the artist; not the first buyer or technical minter) of the NFT; therefore, it does not need to be updated with each sale. The current owner of the NFT is irrelevant, they will not receive royalties and cannot control the royalty percentage.

The original author may want to change the royalty percentage or the royalty receiver address. If you plan on having a contract where NFTs are created by multiple authors AND they can update royalty details after minting, you will need to record the original author of each token.

A couple of side-notes on the implementation, in case you plan to use this code:

  • For precision purposes, it's better to express the royalty percentage as "basis points" (points per 10_000, e.g., 10% = 1000 bps) and compute the amount is (royaltyBps[_tokenId] * _salePrice) / 10000
  • You don't need SafeMath in Solidity >= 0.8.
  • Similarly, no need to register the interface explicitly, see OpenZeppelin ERC165

Oh, thank you very much for all the information.
But the manipulation is still not clear to me. I see two mappings that register the artistic owners, or so I think, of the tokens and another with the percentages of the royalties.

I get the impression that you have to set all this for each mined NFTs.

And in order to apply the royalties of each NFT, apply it manually call the info function and apply the discount manually.

That is, make two non-automatic transactions: A charge to the buyer with the percentage of royalties discounted, and another transaction to the receiver with the percentage discounted.

Is that the operative like this?

I understand your confusion! EIP-2981 specifically points out that it does not define how the royalty is charged or how it is transmitted to the recipient, it only defines the function royaltyInfo which can be used to obtain information.

You are correct that receiver[_tokenId] and royaltyPercentage[_tokenId] must be set for each NFT minted.

In general, marketplaces will deduct the royalty fee from the payment to the seller. E.g., if the NFT is sold for 1 ETH and the royalty fee is 5%, they would send 0.95 ETH to the seller and 0.05 ETH to the royalty receiver. The 0.05 ETH royalty could be sent to the royaltyRecipient right from the marketplace smart contract when the transaction happens, or could be escrowed until further time, or be transmitted in a separate manual transaction — there is no standard for that yet.

Wonderful, now it has become clear to me