How to send NFT from contract to wallet address in Solidity

I have an NFT stored in my smart contract that implements IERC721Receiver. Now I want to create a function that lets me send this NFT to any wallet address.

Here’s my current code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

contract MyNFTHolder is IERC721Receiver {
  // other contract code here

  function withdrawNFTToWallet(
        address tokenContract,
        uint256 nftId,
        address recipient
    ) external onlyOwner {
        IERC721(tokenContract).safeTransferFrom(
            address(this),
            recipient,
            nftId,
            "0x"
        );
  }
}

The idea is simple - as the contract owner I want to transfer an NFT that the contract holds to someone else’s address. I pass in the NFT contract address, the token ID, and where to send it.

But I’m getting this error:

Member "safeTransferFrom" not found or not visible after argument-dependent lookup in contract IERC721. solidity(9582)

What am I doing wrong here? How can I fix this transfer function?

looks like you’re missing the safeTransferFrom function in IERC721 interface. try using regular transferFrom instead or import IERC721 from a newer openzeppelin version that includes safeTransferFrom. also make sure your contract actually owns the nft before transfering it

Interesting challenge! I’m curious about something though - are you sure you want to stick with just the basic IERC721 interface?

What if you imported the full ERC721 interface that actually has the safeTransferFrom function? You could try importing @openzeppelin/contracts/token/ERC721/ERC721.sol instead and then cast to that. Something like:

ERC721(tokenContract).safeTransferFrom(
    address(this),
    recipient, 
    nftId
);

this way you get the safety checks that come with safeTransferFrom rather than the basic transferFrom. Have you considered what happens if the recipient address can’t handle nfts properly? thats where safeTransferFrom really shines since it checks if the receiving contract implements the proper interface.

Also im wondering - do you have any events in your function to track these transfers? might be useful for debugging and monitoring. What kind of nfts are you planning to transfer with this function?

The error occurs because the standard IERC721 interface only includes transferFrom and approve functions, not safeTransferFrom. You need to cast to the full ERC721 contract or use the basic transferFrom method instead. Replace your safeTransferFrom call with IERC721(tokenContract).transferFrom(address(this), recipient, nftId) and it should work. I had this exact same issue when building my marketplace contract last year. The safeTransferFrom function exists in the actual ERC721 implementation but not in the interface definition. Also add a check that address(this) actually owns the token before attempting transfer to avoid reverts.