💰

EIP-2981: NFT Royalty Standardを読んでみた

2022/11/14に公開

先週あたりからNFTのロイヤリティ問題が話題ですね。

そんな中、ロイヤリティについての改善提案である EIP-2981 なるものがあることを知り、さっそく読んでみました。

EIP-2981: NFT Royalty Standard

以下、読んだ内容を引用しながらメモしていきたいと思います。

This standard allows contracts, such as NFTs that support ERC-721 and ERC-1155 interfaces, to signal a royalty amount to be paid to the NFT creator or rights holder every time the NFT is sold or re-sold.

この標準により、 ERC-721およびERC-1155インターフェースをサポートする NFT などの契約で、NFT が販売または再販売されるたびに、NFT の作成者または権利所有者に支払われるロイヤルティの額を知らせることができるようになります。

ポイントはロイヤリティの額をマーケットプレイスに知らせるだけ、ということ。

Marketplaces that support this standard SHOULD implement some method of transferring royalties to the royalty recipient.

つまり、ロイヤリティの送金自体はマーケットプレイス側が実装する必要があります。

実装方法

NFT実装者はERC-1155インターフェースをサポートする必要があります。

pragma solidity ^0.6.0;
import "./IERC165.sol";

///
/// @dev Interface for the NFT Royalty Standard
///
interface IERC2981 is IERC165 {
    /// ERC165 bytes to add to interface array - set in parent contract
    /// implementing this standard
    ///
    /// bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a
    /// bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;
    /// _registerInterface(_INTERFACE_ID_ERC2981);

    /// @notice Called with the sale price to determine how much royalty
    //          is owed and to whom.
    /// @param _tokenId - the NFT asset queried for royalty information
    /// @param _salePrice - the sale price of the NFT asset specified by _tokenId
    /// @return receiver - address of who should be sent the royalty payment
    /// @return royaltyAmount - the royalty payment amount for _salePrice
    function royaltyInfo(
        uint256 _tokenId,
        uint256 _salePrice
    ) external view returns (
        address receiver,
        uint256 royaltyAmount
    );
}

interface IERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

実際はOpenZeppelinなどのライブラリを使うと楽かもしれません。

例として、tokenId=1 の NFT が 999 ethで売れた場合を考えてみましょう。

ロイヤリティのパーセンテージ値が 10% の場合は99 ethがクリエイターに送金される必要があるので、そのように実装します。

function royaltyInfo(uint256 tokenId, uint256 value)
        external
        view
        override
        returns (address receiver, uint256 royaltyAmount)
    {
        // tokenId: 1
        // value: 999

        // reciver: クリエイターのwalletアドレス
        // royalAmount: 999の10% = 99
        return (address(0x~), (value * 10) / 100);
    }

注意点として、valueに渡ってきた値と同じ単位でロイヤルティを返さなければなりません。たとえば、valueが ETH の場合、royalAmountも ETH で返す必要があります。

まとめ

EIP-2981 も結局は「ロイヤリティの額はこれくらいだよ」という情報を持つだけの規格で、ロイヤルティを強制するわけではない のですね。

さらに、EIP-2981 に従うかどうかはマケプレ次第…。

ロイヤリティ問題はこの先どうなっていくのか注目したいと思います。

Discussion