Revert ERC721: transfer caller is not owner nor approved

    mapping(uint => uint) public starsForSale;


   function _make_payable(address account_)  internal pure returns(address payable) { 
      return payable(account_);
    }

    function buyStar(uint256 tokenId_) public payable {
      require(starsForSale[tokenId_] > 0, "The star should be up for sale"); 
      uint256 starCost = starsForSale[tokenId_];
      address ownerAddress = ownerOf(tokenId_);
      require(msg.value >= starCost, "Your ETH balance must be >= the price of star");
      safeTransferFrom(ownerAddress, msg.sender, tokenId_);
      address  payable payableOwnerAddress = _make_payable(ownerAddress);
      address payable payableMsgSender = _make_payable(msg.sender);
      payableOwnerAddress.transfer(starCost);
      if(msg.value > starCost) {
        payableMsgSender.transfer(msg.value - starCost);
      }
      emit Transfer(ownerAddress, msg.sender, tokenId_);
    }
}

Just started learning solidity and I intend to create an NFT marketplace. Each time I attempt to execute buyStar() using a different address, I get the following error:

Error: Returned error: VM Exception while processing transaction: revert ERC721: transfer caller is not owner nor approved -- Reason given: ERC721: transfer caller is not owner nor approved.

1 Like

If you read this line carefully, it means msg.sender asks the ownerAddress to make a safe transfer of token tokenId_ to the recipient msg.sender. However, the owner of token is not msg.sender, then msg.sender must be approved by ownerAddress first to make this function valid.

thanks @maxareo for your answer. Any idea where i could set approval. I have a function putStarUpForSale where the owner puts i the star tem up for sale. Is this the best place to set this approval?

  function putStarUpForSale(uint _tokenId, uint _price) public {
        require(_tokenId > 0, "tokenId must not be zero");
        require(_price > 0, "token price must not be zero");
      require(ownerOf(_tokenId) == msg.sender, "Only token owner can put up token for sell");
    
      setApprovalForAll(to_, true);
      starsForSale[_tokenId] = _price;

    }
1 Like

@_dav what if you call approve() instead of setApprovalForAll. If you've noticed, the Metamask throws the alert message in case of setApprovalForAll