I am using ERC721 in my script and have declared a method for transferring the tokens In return for a desired amount of money from the buyer. However, after sending the money by the buyer the execution does not proceed further and stops with a message focusing on that the caller of the function is not the approved nor the owner of the specific token. I think I might be mistaken by the Approve things for the token transfership.

“ERC721: transfer caller is not owner nor approved”

Can anybody make it a little clear for me? Thanks in advance

Here is the struct that I have declared for the tokens prepared for sale

enter image description here

A) Here is my first function that accepts bids ( This should be called and specified by the seller )

enter image description here

B) And this is my second function which is responsible for transferring the agreed amount and token

enter image description here

1 Answer 1


I don't understand the part with accepting bids. When a bid is made, it should be done by the bidder(buyer) and accepted by the seller after which the transferFrom() function is triggered and the exchange is made. Apparently in your function makeOffer() the seller is bidding on himself, approving the tokenId to the contract but never transferring it so the buyer will actually not receive anything. In the buyOffer() function you're transferring a token that does not exist in the exchange contract with an _index value which instead should be the _tokenId. You could do it like this:

  1. add a mapping that will keep count of the number of items `mapping(uint=>forSale) productIdToNFT

  2. add a variable productCount inside the struct forSale that will keep track of the product id and an address nftContract(optional in case you have other ERC721 contract addressess besides the one you implemented). In case you already have an ERC721 contract, you can create an instance of the contract in your market contract and use it like this: nftContractInstance.approve(address(this),_tokenId) and nftContractInstance.safeTransferFrom(//params)

  3. implement the function to add a product:

     function addBidProduct(uint _price, uint_tokenId, address nftContract) public 
      forSale memory product = forSale(productCount, msg.sender, _price, _tokenId);
      IERC721(nftContract).approve(address(this)),_tokenId); //this can only be used with web3 in the front end so in your testing you should explicitly approve it
      IERC721(nftContract).safeTransferFrom(msg.sender, address(this), _tokenId);
  4. Create another struct named Offer with 2 values: uint price and address from and a mapping mapping(uint=> Offer[]) offers that will keep track of the offers made for that specific product based on the product id.

  5. make a function createOffer(address buyer, uint _priceOffer) that will push the offers into the array Offers[] for the mapping offers.

  6. and finally:

     function buyNFT(uint id,address nftContract, uint _tokenId){
     //add requirements for checking
     forSale storage saleProduct = productIdToNFT[id];
     IERC721(nftContract).safeTransferFrom(address(this), msg.sender, _tokenId);


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.