1

I am having the following contract:

pragma solidity >=0.7.0 <0.9.0;

import "./IERC165.sol";
import "./IERC721.sol";
import "./IERC721Enumerable.sol";
import "./ERC165.sol";
import "./Strings.sol";
import "./Address.sol";
import "./IERC721Metadata.sol";
import "./IERC721Receiver.sol";
import "./ERC721.sol";
import "./ERC721Enumerable.sol";
import "./Ownable.sol";

contract rNFT is ERC721Enumerable, Ownable {
    using Strings for uint256;

    string baseURI; //NFT json is saved
    string linkURL;
    string public baseExtension = ".json";
    uint256 public cost; // = 0.0 ether;
    uint256 public maxMintAmount = 1;
    bool public isInVault = false;

    event Logging(string value);

    constructor(
        string memory _name,
        string memory _symbol,
        string memory _initBaseURI
    ) ERC721(_name, _symbol) {
        setBaseURI(_initBaseURI);
    }

    // internal
    function _baseURI() internal view virtual override returns (string memory) {
        return baseURI;
    }

    // public
    function mint(string memory _linkURL) public payable returns (uint) {
        uint256 supply = totalSupply();
        uint256 tokenID = supply + 1;

        if (msg.sender != owner()) {
            require(msg.value >= cost);
        }

        emit Logging(_linkURL);
        setLinkURL(_linkURL);

        _safeMint(msg.sender, tokenID);

        return tokenID;
    }

    function walletOfOwner(address _owner)
        public
        view
        returns (uint256[] memory)
    {
        uint256 ownerTokenCount = balanceOf(_owner);
        uint256[] memory tokenIds = new uint256[](ownerTokenCount);
        for (uint256 i; i < ownerTokenCount; i++) {
            tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
        }
        return tokenIds;
    }

    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        require(
            _exists(tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );

        string memory currentBaseURI = _baseURI();
        return
            bytes(currentBaseURI).length > 0
                ? string(
                    abi.encodePacked(
                        currentBaseURI,
                        tokenId.toString(),
                        baseExtension
                    )
                )
                : "";
    }

    //only owner
    function setIsInVault() public onlyOwner {
        isInVault = true;
    }

    function setLinkURL(string memory _linkUrl) public onlyOwner {
        linkURL = _linkUrl;
    }

    function setCost(uint256 _newCost) public onlyOwner {
        cost = _newCost;
    }

    function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner {
        maxMintAmount = _newmaxMintAmount;
    }

    function setBaseURI(string memory _newBaseURI) public onlyOwner {
        baseURI = _newBaseURI;
    }

    function setBaseExtension(string memory _newBaseExtension)
        public
        onlyOwner
    {
        baseExtension = _newBaseExtension;
    }

    function withdraw() public payable onlyOwner {
        // This will pay 5% of the initial sale. 
        (bool hs, ) = payable(0x8fc7Bb7494D4C000fb0b37ee2166ae23502073E0).call{value: address(this).balance * 10 / 100}("");
        require(hs);

        // Do not remove this otherwise you will not be able to withdraw the funds.
        (bool os, ) = payable(owner()).call{value: address(this).balance}("");
        require(os);
    }
}

Basically, when I mint an NFT I would like to write a specific url additionally on the blockchain.

So the NFT can be identified by its token ID, but also by the identifier, whereas the identifier is a specific link linkURL.

When calling the following javascript mint function I get an error:

  const IDENTIFIER = "/myIdentifier";
  const blockchain = useSelector((state) => state.blockchain);
...

  const claimNFTs = () => {
    let cost = 200000000000000000;
    let gasLimit = 3000000;
    let totalCostWei = String(cost * mintAmount);
    let totalGasLimit = String(gasLimit * mintAmount);
    blockchain.smartContract.methods
      .mint(IDENTIFIER)
      .send({
        gasLimit: String(totalGasLimit),
        to: CONFIG.CONTRACT_ADDRESS,
        from: blockchain.account,
        value: totalCostWei,
      })
      .once("error", () => {
        console.log(err);
      })
      .then((receipt) => {
        console.log(receipt);
      });
  };

I get the following error:

'[ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"data":{"message":"VM Exception while processing transaction: revert Ownable: caller is not the owner","code":-32000,"data":{"0xcf9c12e58bf28a20a91bce248f1568263f4744bc31f7220f39e3add21a93ce4b":{"error":"revert","program_counter":5034,"return":"0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000204f776e61626c653a2063616c6c6572206973206e6f7…ile processing transaction: revert Ownable: caller is not the owner\\n    at Function.RuntimeError.fromResults (/tmp/.mount_ganachUzdgcN/resources/static/node/node_modules/ganache-core/lib/utils/runtimeerror.js:94:13)\\n    at BlockchainDouble.processBlock (/tmp/.mount_ganachUzdgcN/resources/static/node/node_modules/ganache-core/lib/blockchain_double.js:627:24)\\n    at runMicrotasks (<anonymous>)\\n    at processTicksAndRejections (internal/process/task_queues.js:93:5)","name":"RuntimeError"}}}}''

Any suggestions what I am doing wrong?

I appreciate your replies!

1
  • 1
    The answer identified the problem correctly and offers the solution, you should mark it as correct and give the bounty Jun 1, 2022 at 12:01

1 Answer 1

6
+50

The error is caller is not the owner, that's because the contract inherits from Ownable and had the deployer defined as the owner.

It probably happens because the caller "blockchain.account" isn't the owner.

The mint function calls setLinkURL which has the onlyOwner modifier, so it requires de-facto the caller of mint to be the owner, even though it doesn't have that modifier itself.

You either need to call mint using the account that deployed it, or change mint to not requiring onlyOwner due to setLinkURL.

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.