title: Solidity function implementing `public onlyOwner` cannot be called even by the owner
body: <p>I am following along the documentation here: <a href="https://docs.alchemyapi.io/alchemy/tutorials/how-to-create-an-nft/how-to-mint-a-nft" rel="noreferrer">https://docs.alchemyapi.io/alchemy/tutorials/how-to-create-an-nft/how-to-mint-a-nft</a>. And have a smart contract of form:</p>
  <pre><code>pragma solidity ^0.8.0;
  import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
  import &quot;@openzeppelin/contracts/utils/Counters.sol&quot;;
  import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;
  
    contract NFTA is ERC721, Ownable {
  
       using Counters for Counters.Counter;
       Counters.Counter public _tokenIds;
       mapping (uint256 =&gt; string) public _tokenURIs;
       mapping(string =&gt; uint8) public hashes;
  
       constructor() public ERC721(&quot;NFTA&quot;, &quot;NFT&quot;) {}
  
       function mintNFT(address recipient, string memory tokenURI)
            public onlyOwner
            returns (uint256)
        {
            _tokenIds.increment();
  
            uint256 newItemId = _tokenIds.current();
            _mint(recipient, newItemId);
            _setTokenURI(newItemId, tokenURI);
  
            return newItemId;
       }
  
       /**
        * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
        *
        * Requirements:
        *
        * - `tokenId` must exist.
        */
       function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
          require(_exists(tokenId), &quot;ERC721URIStorage: URI set of nonexistent token&quot;);
          _tokenURIs[tokenId] = _tokenURI;
       }    
  
    }
  </code></pre>
  <p>When I attempt to estimate the gas cost of <code>minting</code> with this:</p>
  <pre><code>    const MY_PUBLIC_KEY  = '..'
      const MY_PRIVATE_KEY = '..'
  
      const ALCHEMY = {
          http: '',
          websocket:'',
      }
  
      const { createAlchemyWeb3 } = require(&quot;@alch/alchemy-web3&quot;);
      const web3 = createAlchemyWeb3(ALCHEMY.http);
  
      const NFTA = require(&quot;../artifacts/contracts/OpenSea.sol/NFTA.json&quot;);
      const address_a   = '0x...';
      const nft_A = new web3.eth.Contract(NFTA.abi, address_a);
  
  
      async function mint({ tokenURI, run }){
  
          const nonce = await web3.eth.getTransactionCount(MY_PUBLIC_KEY, 'latest'); 
          const fn  = nft_A.methods.mintNFT(MY_PUBLIC_KEY, '')
  
          console.log( 'fn: ', fn.estimateGas() )
      }
  
      mint({ tokenURI: '', run: true })
  </code></pre>
  <p>I receive error:</p>
  <pre><code>(node:29262) UnhandledPromiseRejectionWarning: Error: Returned error: execution reverted: Ownable: caller is not the owner
  </code></pre>
  <p>Presumably because <code>mintNFT</code> is <code>public onlyOwner</code>. However, when I check Etherscan, the <code>From</code> field is the same as <code>MY_PUBLIC_KEY</code>, and I'm not sure what else can be done to sign the transaction as from <code>MY_PUBLIC_KEY</code>. The easy way to solve this is to remove the <code>onlyOwner</code> from <code>function mintNFT</code>, and everything runs as expected. But suppose we want to keep <code>onlyOwner</code>, how would I sign the transaction beyond what is already written above.</p>
  <p>Note I'm using <code>hardHat</code> to compile the contracts and deploying them. That is:
  npx hardhat compile
  npx hardhat run scripts/deploy.js</p>
  <p>=============================================</p>
  <p>addendum</p>
  <p>The exact code given by alchemy to deploy the mint is:</p>
  <pre><code>async function mintNFT(tokenURI) {
    const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, 'latest'); //get latest nonce
  
    //the transaction
    const tx = {
      'from': PUBLIC_KEY,
      'to': contractAddress,
      'nonce': nonce,
      'gas': 500000,
      'data': nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI()
    };
  </code></pre>
  <p>Note in the transaction the <code>from</code> field is <code>PUBLIC_KEY</code>, the same <code>PUBLIC_KEY</code> that deployed the contract, and in this case the <code>nftContract</code> has <code>public onlyOwner</code> specified. This is exactly what I have done. So conceptually who owns this NFT code? On etherscan is it the <code>to</code> address ( the contract address ), or the <code>from</code> address, which is my public key, the address that deployed the contract, and the one that is calling mint, which is now failing with caller is not the owner error. <a href="https://i.stack.imgur.com/GbbrU.png" rel="noreferrer"><img src="https://i.stack.imgur.com/GbbrU.png" alt="enter image description here" /></a></p>
  <p>Search the internet, I see others have encountered this problem here: <a href="https://ethereum.stackexchange.com/questions/94114/erc721-testing-transferfrom">https://ethereum.stackexchange.com/questions/94114/erc721-testing-transferfrom</a>, for <code>Truffle</code> you can specify the caller with extra field:</p>
  <pre><code> await nft.transferFrom(accounts[0], accounts[1], 1, { from: accounts[1] })
  </code></pre>
  <p>Extra parameters is not an option here because I'm using hardhat.</p>