一 什么是NFT 版税(Royalty)?
1.1 版税
版税指的是创作者或者拥有者允许其作品在被销售或者别人使用的使用的时候按照约定的比例收取一定的费用,作为创作者或者拥有者的收益。那么这种针对作品收取费用的方式就是版税。
1.2 NFT版税
指的是NFT的拥有者在市场通过出售或者租赁按照约定比例收取一定费用的。这种类型的版税在NFT艺术品和收藏品市场中非常常见。当NFT在次级市场上被转售时,原始创作者可以通过智能合约自动获得销售金额的一定百分比作为版税。这为艺术家和创作者提供了一种持续收益的机会,即使他们的作品已经初次出售。
二 ERC-2981标准提案规范
royaltyInfo
function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view returns (address receiver,uint256 royaltyAmount);
根据销售价格和tokenId计算NFT应该支付多少版税,以及支付给谁
三 ERC-2981手动实现
interface IERC2981 {
struct RoyaltyInfo {
address receiver;
uint96 fraction;
}
/**
* Return the royalty receiver and amount bv salePrice and tokenId
* @param _tokenId the NFT asset id
* @param _salePrice the sale price of the NFT asset
* @return receiver address of who should be sent the royalty payment
* @return royaltyAmount the royalty payment amount
*/
function royaltyInfo(uint256 _tokenId, uint256 _salePrice) external view returns (address receiver,uint256 royaltyAmount);
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "./IERC2981.sol";
import "../ERC165/IERC165.sol";
import "../ERC165/ERC165.sol";
abstract contract ERC2981 is IERC2981 {
uint256 private constant Fee_Denominator = 10000;
RoyaltyInfo private _defaultRoyaltyInfo;
// different royalty against the different token
mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo;
error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);
error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);
error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);
error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);
function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual returns (address, uint256) {
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[tokenId];
if (royalty.receiver == address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (salePrice * royalty.fraction) / Fee_Denominator;
return (royalty.receiver, royaltyAmount);
}
/**
* Set default royalty
* @param receiver address of who accept the royalty
* @param feeNumerator numerator of calculating the royalty
*/
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
if (feeNumerator > Fee_Denominator) {
// Royalty fee will exceed the sale price
revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);
}
if (receiver == address(0)) {
revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));
}
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/
function _deleteDefaultRoyalty() internal virtual {
delete _defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {
if (feeNumerator > Fee_Denominator) {
// Royalty fee will exceed the sale price
revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, Fee_Denominator);
}
if (receiver == address(0)) {
revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));
}
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/
function _resetTokenRoyalty(uint256 tokenId) internal virtual {
delete _tokenRoyaltyInfo[tokenId];
}
}