I am trying to implement this coding to allow 2 different royalties (e.g. An NFT to have a 2.5% royalty to one address and 3% to another address) to be added to the same token ID. I have researched online and looked at common tokens using the following hyperlink but nothing seems to work.

_setTokenRoyalty twice on the same Token ID just overwrites it. All I want is for 2 royalties on same NFT with same token ID.

Is there any way that you can help me out on this please? Thank you.


pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/common/ERC2981.sol";

library Base64 {
    string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    bytes  internal constant TABLE_DECODE = hex"0000000000000000000000000000000000000000000000000000000000000000"

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return '';

        // load the table into memory
        string memory table = TABLE_ENCODE;

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((data.length + 2) / 3);

        // add some extra buffer at the end required for the writing
        string memory result = new string(encodedLen + 32);

        assembly {
            // set the actual output length
            mstore(result, encodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 3 bytes at a time
            for {} lt(dataPtr, endPtr) {}
                // read 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // write 4 characters
                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(        input,  0x3F))))
                resultPtr := add(resultPtr, 1)

            // padding with '='
            switch mod(mload(data), 3)
            case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
            case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }

        return result;

contract SVGEditorNFTV2 is ERC721, ERC721Enumerable, ERC2981 {
    mapping(string => bool) private takenNames;
    mapping(uint256 => Attr) public attributes;
    uint96 meshp = 250;

    struct Attr {
        string svg;
        string name;
        string artist;

    constructor() ERC721("svg", "SVG") {}

    function _beforeTokenTransfer(address from, address to, uint256 tokenId)
        override(ERC721, ERC721Enumerable)
        super._beforeTokenTransfer(from, to, tokenId);

    function _burn(uint256 tokenId) internal override(ERC721) {

    function supportsInterface(bytes4 interfaceId)
        override(ERC721, ERC721Enumerable, ERC2981)
        returns (bool)
        return super.supportsInterface(interfaceId);

    function setPlatformRoyalty(uint96 x) public {
        meshp = x;

    function returnPlatformRoyalty() public view returns (uint96) {
        return meshp;

    function mint(
        address to, 
        uint256 tokenId,
        string memory _svg, 
        string memory _name,
        string memory _artist,
        uint96 percent) 
    public {
        _safeMint(to, tokenId);
        _setTokenRoyalty(tokenId, to, percent);
        _setTokenRoyalty(tokenId, 0xbe94F301cDb6eD1aFae186D79631B112129de041, meshp);
        attributes[tokenId] = Attr(_svg, _name, _artist);

    function tokenURI(uint256 tokenId) override(ERC721) public view returns (string memory) {
        string memory json = Base64.encode(
                    '{"name": "', attributes[tokenId].name, '",',
                    '"image_data": "', attributes[tokenId].svg, '",',
                    '"attributes": [{"trait_type": "Artist", "value": "', attributes[tokenId].artist, '"}',
        return string(abi.encodePacked('data:application/json;base64,', json));

1 Answer 1


Each ERC721 token can only have one royalty set. That's why you get the first royalty overwritten by the second one.

In order to have multiple receivers of the royalty, you need to deploy a payment splitter and use that contract address for the NFT royalty instead.

You can read more about payment splitter here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.