Implementing EIP-2981 Royalties

September 2nd, 2021

Implementing EIP-2981 Royalties

The crazyness of this year NFT market has been a wild ride. Artists have being creating amazing work, collectors speculation has been wild, the trend and price evolution of artworks buying and selling. But here, the artists yet gets nothing from future sales.

The goal somehow of EIP-2981 it to fix this. It's a standard that lets NFT contracts communicate royalty information to marketplaces. When someone resells your NFT, you automatically get a percentage. No begging, no legal battles, no complex agreements. Just code that works. But, there are important details.

The Problem with Current Systems

Most NFT marketplaces handle royalties in their own way. Some respect them, some don't. Some have complex fee structures that eat into creator profits. Others just ignore royalties entirely because there's no standard way to implement them, no enforcement.

This creates a fragmented mess where creators have to:

  • Trust each marketplace to implement royalties correctly
  • Hope that buyers and sellers will honor royalty agreements
  • Deal with different royalty structures across platforms

It's broken. And it's not sustainable for creators who want to build long-term careers in digital art.

How EIP-2981 Works

EIP-2981 is simple. It adds one function to your NFT contract: royaltyInfo. This function takes a token ID and sale price, then returns who should get the royalty and how much.

function royaltyInfo(uint256 tokenId, uint256 salePrice) 
    external view returns (address receiver, uint256 royaltyAmount)

That's it. No complex logic, no multiple functions, no confusing interfaces. Just one function that tells marketplaces exactly what they need to know.

Implementation

Here's how to implement it in your NFT contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/interfaces/IERC2981.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

contract DigitalArtNFT is ERC721, IERC2981, ERC165 {
    address private _royaltyRecipient;
    uint256 private _royaltyPercentage; // e.g., 500 for 5%
    
    constructor(
        string memory name,
        string memory symbol,
        address royaltyRecipient,
        uint256 royaltyPercentage
    ) ERC721(name, symbol) {
        _royaltyRecipient = royaltyRecipient;
        _royaltyPercentage = royaltyPercentage;
    }
    
    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC165)
        returns (bool)
    {
        return
            interfaceId == type(IERC2981).interfaceId ||
            super.supportsInterface(interfaceId);
    }
    
    function royaltyInfo(uint256, uint256 salePrice)
        external
        view
        override
        returns (address receiver, uint256 royaltyAmount)
    {
        receiver = _royaltyRecipient;
        royaltyAmount = (salePrice * _royaltyPercentage) / 10000;
    }
    
    function mint(address to, uint256 tokenId) public {
        _mint(to, tokenId);
    }
}

The key parts:

  • Royalty recipient: The address that receives the royalty payments
  • Royalty percentage: Stored as basis points (500 = 5%)
  • Interface support: Tells other contracts that this NFT supports royalties

Use Case: Digital Art Marketplace

Let's say you're building a digital art marketplace. An artist mints an NFT with a 10% royalty. Here's what happens:

  1. Artist mints NFT: Sets 10% royalty (1000 basis points)
  2. First sale: NFT sells for 1 ETH, artist gets 1 ETH
  3. Secondary sale: NFT resells for 5 ETH
  4. Automatic royalty: Artist gets 0.5 ETH (10% of 5 ETH) automatically

The marketplace doesn't need to know anything about the artist's preferences. It just calls royaltyInfo and gets the exact information it needs.

Why This Matters

This standard creates a level playing field, but its main issue is the lack of enforcement for the royalty fee. Since enforcement depends on the marketplace, creators are subject to the competitive incentives of platforms offering better terms to end users. There's always the possibility of bypassing the fee, if a marketplace enforces royalties, it may lose users to other platforms that don't, making enforcement a non-trivial decision. As a result, the incentive is often not to enforce royalties.

We still need a better royalty standard for transactions.