Solidity – Does Function Revert If ERC20 or ERC721 transferFrom Fails?

erc-20erc-721solidity

I'm having some security doubts and confusion about the case of reverts. As I found, the whole changes of a function are reverted if the native transfer function fails. But what about the ERC721 and ERC20's transfer, transferFrom, safeTransferFrom?

For example:

  1. If (1) or (2) fails, does the function breaks out and revert the offer.isAccepted?

  2. If (2) fails, is weth transfer and therefore the whole function reverted?

    function acceptBid(uint256 _offerId) public nonReentrant {
    Offer storage offer = offers[_offerId];
    
    IERC20 weth = IERC20(0xc778417E063141139Fce010982780140Aa0cD5Ab);
    IERC721 nftContract = IERC721(offer.nftContractAddress);
    
    address nftOwner = nftContract.ownerOf(offer.tokenId);
    
    offer.isAccepted = true; // *
    weth.transferFrom(
        address(offer.userAddress),
        payable(msg.sender),
        offer.price
    ); // (1)
    
    nftContract.transferFrom(
        address(this),
        offer.userAddress,
        offer.tokenId
    ); // (2)
    
    emit AcceptedOffer();}
    

Best Answer

The smart contract methods are executed in a transactional way. This means, if any of revert, require or failed assert is executed, then the whole transaction is meaned to revert, rolling back any changes made.

So:

  • When weth.transferFrom reverts, offer.isAccepted will be cleared
  • When nftContract.transferFrom reverts, weth.transferFrom will be rolled back and offer.isAccepted will be cleared.
Related Topic