Implementing royalty fees for an NFT collection

I’m working on an NFT project and I’ve got the minting process down. But I’m stuck on how to add royalty fees for my artwork. I’ve heard about two ways to do this:

  1. Putting the royalty fee in the smart contract
  2. Setting it up through OpenSea

Which method is better? I want to make sure it’s secure. I’m using the Rinkeby test network so I can change the contract as much as I need.

Here’s a simplified version of my current contract:

pragma solidity ^0.8.0;

import '@openzeppelin/contracts/token/ERC721/ERC721.sol';
import '@openzeppelin/contracts/access/Ownable.sol';

contract ArtCollection is ERC721, Ownable {
    uint256 public mintPrice = 0.05 ether;
    uint256 public maxSupply = 1000;
    bool public isSaleActive = false;
    
    constructor() ERC721('MyArt', 'ART') {}
    
    function mint(uint256 quantity) external payable {
        require(isSaleActive, 'Sale must be active');
        require(quantity > 0 && quantity <= 5, 'Invalid quantity');
        require(totalSupply() + quantity <= maxSupply, 'Would exceed max supply');
        require(msg.value >= mintPrice * quantity, 'Insufficient payment');
        
        for (uint256 i = 0; i < quantity; i++) {
            uint256 tokenId = totalSupply() + 1;
            _safeMint(msg.sender, tokenId);
        }
    }
    
    function toggleSale() external onlyOwner {
        isSaleActive = !isSaleActive;
    }
}

Can someone help me figure out the best way to add royalties?

hey there creativePainter45! i’m really curious about your nft project, it sounds so cool! :blush:

i’ve been dabbling in nfts too and had the same question about royalties. from what i’ve learned, putting the royalty fee in the smart contract is generally considered more secure and reliable. it ensures that the royalty is enforced at the blockchain level, which is pretty awesome.

have you looked into EIP-2981? it’s a standard for nft royalties that might be perfect for what you’re trying to do. you could implement it in your contract like this:

import '@openzeppelin/contracts/token/common/ERC2981.sol';

contract ArtCollection is ERC721, Ownable, ERC2981 {
    // ... your existing code ...

    constructor() ERC721('MyArt', 'ART') {
        _setDefaultRoyalty(msg.sender, 250); // 2.5% royalty
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) {
        return super.supportsInterface(interfaceId);
    }
}

what do you think about this approach? have you considered any specific royalty percentage for your artwork? i’d love to hear more about your project and how you’re planning to use the royalties!

Implementing royalties in the smart contract is indeed the more robust approach. It ensures consistency across all marketplaces that support the EIP-2981 standard, which is becoming increasingly common.

However, be aware that not all platforms fully support on-chain royalties yet. You might want to consider a hybrid approach: implement EIP-2981 in your contract, but also set up royalties on major platforms like OpenSea as a fallback.

For your contract, consider adding a function to update the royalty info:

function setRoyaltyInfo(address receiver, uint96 feeNumerator) external onlyOwner {
    _setDefaultRoyalty(receiver, feeNumerator);
}

This allows you to adjust royalties or change the receiving address if needed. Just remember to thoroughly test on Rinkeby before deploying to mainnet.