Here is my coding:
// SPDX-License-Identifier: MIT
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") {}
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, 69);
// 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);
}
I have minted several times and still failed to enforce the royalties on OpenSea meaning they should not be optional whenever I want to sell them. Is there anyway to help me with the code please?
Current Output:
Expected Output: