How can I ensure that any user can buy NFT's that the owner sells and keep royalties fixed?

Hi

Here is my code:

pragma solidity ^0.8.7;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/interfaces/IERC2981.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@limitbreak/creator-token-contracts/contracts/erc721c/ERC721C.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "./SSTORE2.sol";
import "./Base64.sol";

contract SVGEditorNFTV3 is ERC721C, IERC2981, Ownable {
    using Strings for uint256;
    
    struct TokenData {
        uint256 royalties;
        address royaltyRecipient;
        address attributesPointer;
    }

    mapping(uint256 => TokenData) private _tokenData;

    uint96 private _platformRoyalty = 69;
    uint256 private _payment = 96000000000000000;
    bool public paused = false;
    uint256 private _currentTokenId = 0;

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

    mapping(address => bool) private _marketplaces;

    // Modifier to check if the operator is either the owner or an approved marketplace
    modifier onlyOwnerOrMarketplace(address owner, address operator) {
        require(
            owner == operator || _marketplaces[operator],
            "Operator not approved"
        );
        _;
    }

    // Override isApprovedForAll to check for the modifier
    function isApprovedForAll(address owner, address operator)
        public
        view
        override(ERC721)
        onlyOwnerOrMarketplace(owner, operator)
        returns (bool)
    {
        return super.isApprovedForAll(owner, operator);
    }

    // Function to add a marketplace to the approved list
    function addMarketplace(address marketplace) public onlyOwner {
        _marketplaces[marketplace] = true;
    }

    // Function to remove a marketplace from the approved list
    function removeMarketplace(address marketplace) public onlyOwner {
        _marketplaces[marketplace] = false;
    }

    modifier whenNotPaused() {
        require(!paused, "Contract is paused.");
        _;
    }

    // Implement the _requireCallerIsContractOwner function
    function _requireCallerIsContractOwner() internal view override {
        require(owner() == _msgSender(), "Caller is not the contract owner");
    }

    function setPayment(uint256 x) external onlyOwner whenNotPaused {
        _payment = x;
    }

    function returnPayment() external view returns (uint256) {
        return _payment;
    }

    function setPlatformRoyalty(uint96 x) external onlyOwner whenNotPaused {
        _platformRoyalty = x;
    }

    function platformRoyalty() external view returns (uint96) {
        return _platformRoyalty;
    }

    function _setTokenRoyalty(uint256 tokenId, address recipient, uint256 royaltyPercentage) internal whenNotPaused {
        require(royaltyPercentage <= 10000, "NFT: Royalty percentage must not exceed 10000");
        _tokenData[tokenId].royalties = royaltyPercentage;
        _tokenData[tokenId].royaltyRecipient = recipient;
    }

    function division(uint256 decimalPlaces, uint256 numerator, uint256 denominator) pure public returns(string memory result) {
        uint256 factor = 10**decimalPlaces;
        uint256 quotient  = numerator / denominator;
        bool rounding = 2 * ((numerator * factor) % denominator) >= denominator;
        uint256 remainder = (numerator * factor / denominator) % factor;
        if (rounding) {
            remainder += 1;
        }
        result = string(abi.encodePacked(quotient.toString(), '.', numToFixedLengthStr(decimalPlaces, remainder)));
    }

    function numToFixedLengthStr(uint256 decimalPlaces, uint256 num) pure internal returns(string memory result) {
        bytes memory byteString;
        for (uint256 i = 0; i < decimalPlaces; i++) {
            uint256 remainder = num % 10;
            byteString = abi.encodePacked(remainder.toString(), byteString);
            num = num/10;
        }
        result = string(byteString);
    }

    function mint(
        string calldata svg,
        string calldata name,
        uint96 percent
    ) external whenNotPaused {
        _currentTokenId++;
        uint256 newTokenId = _currentTokenId;
        _safeMint(msg.sender, newTokenId);
        _setTokenRoyalty(newTokenId, 0xbe94F301cDb6eD1aFae186D79631B112129de041, _platformRoyalty);
        // Convert percentage to string and append "%"
        string memory percentString = division(2,percent,100);
        //string memory percentWithSymbol = string(abi.encodePacked(percentString, "%"));
        _tokenData[newTokenId].attributesPointer = SSTORE2.write(abi.encode(svg, name, percentString, msg.sender));
    }

    function tokenURI(uint256 tokenId) public whenNotPaused view virtual override returns (string memory) {
        (string memory svg, string memory name, string memory percent, address minter) = abi.decode(SSTORE2.read(_tokenData[tokenId].attributesPointer), (string, string, string, address));

        // Convert minter address to string
        string memory minterString = _toString(minter);

        string memory json = Base64.encode(
            abi.encodePacked(
                '{"name":"', name, '",',
                '"image_data":"', svg, '",',
                '"attributes":[{"trait_type":"Minter Fees (%)", "value": "', percent, '"},',  // Notice that I've added double quotes around the value.
                '{"trait_type":"Minter","value":"', minterString, '"}]',
                '}'
            )
        );
        return string(abi.encodePacked("data:application/json;base64,", json));
    }

    // Function to convert address to string
    function _toString(address _addr) private pure returns(string memory) {
        bytes32 value = bytes32(uint256(uint160(_addr)));
        bytes memory alphabet = "0123456789abcdef";

        bytes memory str = new bytes(42);
        str[0] = '0';
        str[1] = 'x';
        for (uint256 i = 0; i < 20; i++) {
            str[2+i*2] = alphabet[uint8(value[i + 12] >> 4)];
            str[3+i*2] = alphabet[uint8(value[i + 12] & 0x0f)];
        }
        return string(str);
    }

    function royaltyInfo(uint256 tokenId, uint256 value) external view virtual override returns (address receiver, uint256 royaltyAmount) {
        receiver = _tokenData[tokenId].royaltyRecipient;
        royaltyAmount = value * _tokenData[tokenId].royalties / 10000;
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721C, IERC165) returns (bool) {
        return super.supportsInterface(interfaceId) || interfaceId == type(IERC2981).interfaceId;
    }


    function pause() external onlyOwner {
        paused = !paused;
        emit Paused(paused);
    }

    event Paused(bool isPaused);
}

Every time I mint an NFT and sell it, users (not the owner) cannot seem to buy them. Every them they do they get errors saying "Operator not approved".

I am testing this on the goerli testnet and I do not know what the operator address for the goerli testnet is. I asked ChatGPT and they do not seem to give me an answer.

My intended output is that when someone makes a sale the royalties set stay fixed meaning not optional and not changeable and that all users can buy.

Is there anything that you can do to help me? Am I missing something?

Well your contract has no sale function, so I have to assume you are leaving out some important details. Also you have not posted any call information or transaction history. So it’s rather hard to help without the required information.

Here is the link to one of the NFT's I am selling: https://testnets.opensea.io/assets/goerli/0x24b6f5bcab44d71d804b696b787f32bdccbd3b60/1

When I click continue in the buy button it gets execution reverted error message popping up. I tested by adding the mainnet Ethereum address in _marketplaces and it would not sort out the error.

This might help:

I am still struggling. Whenever I ran the isApprovedForAll method after setApprovedForAll it keeps returning false. I have set the operator address to the OpenSea address 0x7Be8076f4EA4A4AD08075C2508e481d6C946D12b but it does not seem to work for the Goerli testnet Opensea.

My intention is to ensure that when people mint their NFT's and sell them. Then it allows everyone to buy what is being sold and not get the operator not approved error.

On mainnet, this address seems to be an OpenSea contract.

On goerli, this address seems to be an externally-owned account.

I have decided to test using this address 0x00000000006c3852cbEf3e08E8dF289169EdE581 (address used in goerli testnet sales) on the goerli testnet but operator still won't approve for the buyer to buy the NFT. Is that the particular address used for the goerli testnet?

https://goerli.etherscan.io/tx/0x570c7d7b3686b51b683d331c4c6f2070486617de2266f30680f11cda9b840ad6 (Example of sale)

I have discovered that setApprovalForAll(operator,true) only allows isApprovalForAll(owner,operator) to be true but isApprovalForAll(buyer,operator) set to false.

I partially updated this code:
```modifier onlyOwnerOrMarketplace(address owner, address operator) {
require(
owner == operator || _marketplaces[operator] || super.isApprovedForAll(owner, operator),
"Operator not approved"
);
_;
}

function isApprovedForAll(address owner, address operator)
    public
    view
    override(ERC721)
    onlyOwnerOrMarketplace(owner, operator)
    returns (bool)
{
    return true;
}```

Now when I made the sale the royalties are now optional (should be mandatory)

Output Now:

Intended Output:

Is that a question?
I'm asking, because I don't see any question mark.
If it is a question - is it related to the previous question?
If not, then you would best post it separately (and when you do so, try to minimize it to the actual specific problem that you're experiencing rather than a general illustration of your entire system).