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:
- Artist mints NFT: Sets 10% royalty (1000 basis points)
- First sale: NFT sells for 1 ETH, artist gets 1 ETH
- Secondary sale: NFT resells for 5 ETH
- 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.