I’m struggling to understand how to correctly implement royalties using the ERC2981 standard in my NFT marketplace. After going through various tutorials and documentation, I’m still confused about some key concepts.
My main question is about the feeNumerator parameter in the _setDefaultRoyalty(address recipient, uint96 feeNumerator) function. What exactly should this value represent? Is it the actual NFT price or the royalty percentage?
Here’s my current marketplace contract implementation. Could someone review it and let me know if I’m handling the royalty setup correctly?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/common/ERC2981.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract AudioNFT is ERC721URIStorage, ERC2981, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _itemCounter;
Counters.Counter private _tokenCounter;
struct AudioItem {
address creator;
address currentOwner;
string itemTitle;
string itemDetails;
uint256 salePrice;
uint256 royaltyRate;
uint256 tokenId;
bool isActive;
}
mapping(uint256 => AudioItem) public audioItems;
constructor() ERC721("Audio NFT Collection", "AUDIO") {}
function createToken(
string memory metadataURI,
string memory _title,
string memory _details,
uint256 _price,
uint256 _royalty) external returns(uint256) {
require(_price > 0, "Price must be greater than zero");
require(_royalty > 0 && _royalty <= 25, "Royalty must be between 1 and 25 percent");
_itemCounter.increment();
_tokenCounter.increment();
uint256 newTokenId = _tokenCounter.current();
_safeMint(msg.sender, newTokenId);
_setTokenURI(newTokenId, metadataURI);
audioItems[_itemCounter.current()] = AudioItem(
msg.sender,
msg.sender,
_title,
_details,
_price,
_royalty,
newTokenId,
false
);
return newTokenId;
}
function activateForSale(uint256 _itemId) external {
require(msg.sender == audioItems[_itemId].currentOwner, "Only token owner can activate sale");
audioItems[_itemId].isActive = true;
approve(address(this), audioItems[_itemId].tokenId);
setApprovalForAll(address(this), true);
_setDefaultRoyalty(audioItems[_itemId].creator, uint96(audioItems[_itemId].royaltyRate));
}
}
Am I calling the royalty function at the right time and with correct parameters? Any guidance would be appreciated!