How to fix 'TransferHelper: ETH_TRANSFER_FAILED' when interacting with Uni V2
Asked Answered
C

3

5

I'm dealing with a strange issue with the safeTransferETH helper function in Uniswap V2's router contract.

I'm trying to swap tokens held by the contract to Uniswap for Ether, using the swapExactTokensForETH function provided by the Uniswap V2 router. (The function code is present on Uniswap's github in router1). The function being called is:

function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        override
        ensure(deadline)
        returns (uint[] memory amounts)
    {
        require(path[path.length - 1] == WETH, 'UniswapV2Router: INVALID_PATH');
        amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
        TransferHelper.safeTransferFrom(path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]);
        _swap(amounts, path, address(this));
        IWETH(WETH).withdraw(amounts[amounts.length - 1]);
        TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
    }

The only part of this code that is throwing an error is the TransferHelper.safeTransferETH function, which is:

function safeTransferETH(address to, uint value) internal {
    (bool success,) = to.call{value:value}(new bytes(0));
    require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}

My code is:

function uniV2ReceiveETH(address _token0, uint _amount0) public payable returns (uint[] memory amountsReceived) {
        require(_amount0 > 0, "Must provide tokens if we want tokens in return!");
        address[] memory path = new address[](2);
        path[0] = _token0;
        path[1] = WETH;

        IERC20 token;
        token = IERC20(_token0);

        if (token.balanceOf(address(this)) > 0) {
            _amount0 = token.balanceOf(address(this));
        }

        require(token.approve(address(uniV2Router), _amount0 + 10000), "approval failed");

        // Swap logic
        uint amountOutMin = UniswapV2Library.getAmountsOut(address(uniV2Factory), _amount0, path)[1];
        amountsReceived = uniV2Router.swapExactTokensForETH(_amount0, amountOutMin, path, address(this), deadline);
        uint endBalance = address(this).balance;

        // Let everyone know we're done!
        emit Swap(msg.sender, _amount0, endBalance);
}

A few other notes are:

  1. The contract does receive ETH from other addresses without issue.
  2. I am using hardhat, and a forked version of the mainnet to test.
  3. The contract also works with the Uniswap router's other swap functions, including SwapExactETHForTokens and SwapExactTokensForTokens.
Clackmannan answered 21/12, 2021 at 20:48 Comment(3)
why on the line when you call swapExactTokensForETH you write amountOutMin fixed to 1? you calculated it just before, use it. it can give error if the actual amountOut is less than 1Planar
Apologies, it is supposed to be AmountOutMin, I was just testing to see if that had anything to do with it. I've updated it in the provided code.Clackmannan
By the way, it's probably easier to get answers to questions like these on Ethereum.Term
L
10

I solved this issue by having a payable fallback function by defining it as:

fallback() external payable { }

inside my smart contract.

Limbus answered 14/2, 2022 at 4:27 Comment(0)
W
1

I solved this issue by having a payable receive() function because the contract isn't be able to receive ether without this function:

receive() external payable {}

"If you are using Solidity 0.6.0 or later, it is recommended to use the receive() function to explicitly handle plain Ether transfers. If you are working with an older version of Solidity, you can use the fallback() function to handle both Ether transfers and calls with data."

fallback() external payable {}

Walhalla answered 6/6, 2023 at 6:11 Comment(0)
Q
0

Add to your contract.

receive() external payable {}
fallback() external payable {}
Quiet answered 8/7, 2022 at 13:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.