1

I'm trying to write this function in solidity that resells an NFT that someone has purchased, and I keep getting the aforementioned error. I'm not exactly sure what the issue is, cause this function is almost similar to another one that lists the NFT originally after minting.

Also do I need the first require statement at all? Or does the transfer have a way to check if its the NFT owner?

Everything else I've been reading, such as approving the token for transfer, hasn't been working. In fact if I try and approve first from the token instance, it throws an error saying "approval for owner" or something like that. Thanks in advance still very new to solidity.

function marketItemResell(
        address nftContract,
        uint256 itemId,
        uint256 price
    ) public payable nonReentrant {
        // require(
        //     IERC721(nftContract).ownerOf(itemId) == msg.sender,
        //     "Only the owner can list an NFT for sale"
        // );
        require(price > 0, "Price must be at least 1 wei");
        require(
            msg.value == listingPrice,
            "Price must be equal to listing price"
        );

        uint256 tokenId = idToMarketItem[itemId].tokenId;

        IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);

        idToMarketItem[itemId].seller = payable(msg.sender);
        idToMarketItem[itemId].owner = payable(address(0));
        idToMarketItem[itemId].price = price;
        idToMarketItem[itemId].sold = false;

        _itemsSold.decrement();

        emit ItemListed(
            itemId,
            nftContract,
            tokenId,
            msg.sender,
            address(0),
            price,
            false
        );
    }

3 Answers 3

1

In ERC721 specification (https://eips.ethereum.org/EIPS/eip-721#specification), it state that the transferFrom function must have this property

/// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
///  TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
///  THEY MAY BE PERMANENTLY LOST
/// @dev Throws unless `msg.sender` is the current owner, an authorized
///  operator, or the approved address for this NFT. Throws if `_from` is
///  not the current owner. Throws if `_to` is the zero address. Throws if
///  `_tokenId` is not a valid NFT.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;

and the approve function:

    /// @notice Change or reaffirm the approved address for an NFT
    /// @dev The zero address indicates there is no approved address.
    ///  Throws unless `msg.sender` is the current NFT owner, or an authorized
    ///  operator of the current owner.
    /// @param _approved The new approved NFT controller
    /// @param _tokenId The NFT to approve
    function approve(address _approved, uint256 _tokenId) external payable;

In the dev, it says that the 'msg.sender' has to be the current owner of the nft token. But the smart contract that make the call is not the owner of the token.

So to solve this the owner of the token must first approve the smart contract address to have the right modify the token and only then can he modify the token. Or the owner can call approvalForAll on the erc721 to give the smart contract the right to modify every asset that they own.

3
  • Hey so I had a chance to sit down and look at this again. I believe I already give the erc721 setApprovalForAll access in the actual NFT contract. The code I posted before was the market contract. Here is the createToken function I currently have that does this: function createToken(string memory tokenURI) public returns (uint256) { _tokenIds.increment(); uint256 newItemId = _tokenIds.current(); _mint(msg.sender, newItemId); _setTokenURI(newItemId, tokenURI); setApprovalForAll(contractAddress, true); return newItemId; } Commented Jan 5, 2022 at 0:31
  • But on a side note, when I do try to implement approval, or setApproval to the marketItemResell function it throws either: revert ERC721: approval to current owner or revert ERC721: approve to caller respectfully Commented Jan 5, 2022 at 0:43
  • @SalvatoreArgentieri did you ever find a solution? Finding same errors
    – hammies
    Commented May 18, 2022 at 18:49
0

Hey so thanks again Haxerl for the assistance, it did help me figure out what's going on. Essentially I need to make another call from the ERC721 contract to allow this contract the right to sell on its behalf. So the issue wasn't really in this contract, it was due to a lack of understanding on my end. I think I understand a lot more now that I have experienced this.

3
  • I am having the same problem. Can you share where and how were you able to give the contract the approval ? Thanks
    – Ege
    Commented Feb 16, 2022 at 17:11
  • Hey there Ege, I definitely share that in the above comment but to re-iterate, and further break it down here it is: I have two smart contracts, one contract for the ERC721 tokens(NFTs), and the other contract to sell these tokens. Upon minting the ERC721 contract allows the market sale the right to perform transfer actions. When reselling we need to re-approve the market contract the right to sell these NFTs. I made a custom function on the ERC721 contract that is call to transfer approvalForAll to the market place. This function checks the owner of the NFT is calling it Commented Feb 17, 2022 at 20:51
  • This may be superfluous, but better safe then sorry IMO. The contract code looks like this: ``` function giveResaleApproval(uint256 tokenId) public { require( ownerOf(tokenId) == msg.sender, "You must own this NFT in order to resell it" ); setApprovalForAll(contractAddress, true); return; } ``` On the front end, call this function, pass ID of the token you want to resell, then try and relist it thru the marketContract via the above function Commented Feb 17, 2022 at 20:54
0

If you are reselling an nft, you should satisfy those conditiions:

// if the owner of the token is the sender of the transaction
require(ERC721.ownerOf(tokenId)==msg.sender,"You are not the owner of the Nft");
// make sure nft item is not already listed. Because when someone buys nft it should be delisted. 
require(nftItemInMapping[tokenId].isListed==false,"Item is already on sale");
require(msg.value==listingPrice,'Price must be equal to listing price');

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.