简体   繁体   中英

ERC721: transfer caller is not owner nor approved

I have a nftToken Contract that mints token to msg.sender, then I have a function in a market contract that transfers the nft from owner to market contract. However, I am getting an error that says: ERC721: transfer caller is not owner nor approved.

here is my nftContract (nft) function snippet:

function createToken(string memory tokenURI) public returns (uint) {
  _tokenIds.increment();
  uint256 newItemId = _tokenIds.current();

  _mint(msg.sender, newItemId);
  _setTokenURI(newItemId, tokenURI);
  setApprovalForAll(contractAddress, true);
  return newItemId;
}

here is my market code (stripeMarket Contract) function snippet:

function createItem(
    address nftContract,
    uint256 tokenId
    ) public payable{
     address _owner = IERC721(nftContract).ownerOf(tokenId);
     IERC721(nftContract).transferFrom(_owner, address(this),tokenId);
      IERC721(nftContract).approve(address(this),tokenId);    
}

and here I am trying to call it from the frontend with web3:

const getItems=async()=>{
      await contracts.nft.methods.createToken("https://i.ytimg.com/vi/nYxGhQYi0s4/maxresdefault.jpg").send({from: accounts[0]});
      const owners = await contracts.nft.methods.ownerOf(1).call({from:accounts[0]});
      await contracts.stripeMarket.methods.createItem(contracts.nft._address,1).send({from: {owners}}); 
}

But I am getting the error:

ERC721: transfer caller is not owner nor approved.

When the nftContract executes the setApprovalForAll(contractAddress, true) , it allows the contractAddress (the Market contract) to operate all of the nftContract 's tokens .

But the newly minted token is owned by the msg.sender - not by the nftContract . So the approval does not apply to this token.


Depending on your use case, you can

  1. Mint the new token to the nftContract (instead of the msg.sender ) so that the Market contract is allowed to operate it. Or mint it to the Market contract directly.

     // the owner is the `nftContract` _mint(address(this), newItemId); // the Market contract is allowed to operate the `nftContract`'s tokens setApprovalForAll(contractAddress, true);
  2. Have the msg.sender (the token owner) execute approve(marketAddress, tokenId) on the nftContract before executing the createItem() .

    This will give the Market contract approval to operate this particular token owned by the msg.sender . (Assuming it's the same address as the _owner - otherwise it will fail.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM