Solidity – How to Call SafeTransferFrom on an Arbitrary IERC721 in a Smart Contract

erc-721ethers.jssolidity

I am trying to build an dApp that allows users to transfer their ERC721 token to my smart contract, and then at a later time, send to another user. Here is my contract code:

contract HoldNFT is ERC721, IERC721Receiver, ERC721Holder, Ownable{
    using Counters for Counters.Counter;
    Counters.Counter public _tokenIDs;
    constructor() ERC721("HoldNFT", "HOLDNFT") {
        _tokenIDs.increment();
    }
    function send(IERC721 tokenAddress, uint256 tokenId) public {
        uint256 current = _tokenIDs.current();
        tokenAddress.safeTransferFrom(msg.sender, address(this), tokenId); 
        _safeMint(recipient, current);
        _tokenIDs.increment();  
    }
}

When I call on this function, I get the errow message "Revert ERC721: transfer caller is not owner or approved". My understanding is that this occurs because I am calling the safeTransferFrom function from a smart contract, so the msg.sender in the IERC721 contract (tokenAddress argument) is my smart contract instead of the user, who actually owns the token. I want to know if there is a way around this. I know that you can call the safeTransferFrom function or approve function from JavaScript so the msg.sender is the user. However, I don't think this will work in my particular case because the tokenAddress is arbitary (decided by the user) so I do not have access to the ABI in development. What should I do?

P.S. The template I used for this project was from a dApp called nftysanta (0x1f4E4eF54dB90934DE8fB2d68438C68660099Ad4). It seems to use the same implementation as far as I can see? And I assumed that it works because it's a verified contract on mainnet.

Best Answer

Call approve(yourContractAddress, tokenId) function first with your user, then your contract will be able to transfer the token himself.

Related Topic