BSC – Fixing ‘TransferHelper: TRANSFER_FROM_FAILED’ Error Even After Approval

bscerc-20-approvepancakeswaptransferfrom

I'm rying to swap some BNB -> Token, then swap it back, all in one solidity function. Here's my code:

interface IERC20 {
    function approve(address spender, uint256 value) external returns (bool);
}

interface IPancakeSwapRouter {
    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function swapExactTokensForETH(
        uint256 amountIn, 
        uint256 amountOutMin, 
        address[] calldata path, 
        address to, 
        uint256 deadline
    ) external returns (uint[] memory amounts);

    function WETH() external pure returns (address);
    function factory() external pure returns (address);
}

interface IPancakeFactory {
    function getPair(address tokenA, address tokenB) external view returns (address pair);
}

contract Test {

    receive() external payable { }
    fallback() external payable { }

    function BuySell(address token_out, uint value) public payable {

        address swap_router_addr = address(0x10ED43C718714eb63d5aA57B78B54704E256024E); //Pancake router
        IPancakeSwapRouter swap = IPancakeSwapRouter(swap_router_addr);

        uint deadline = block.timestamp + 1200;

        address[] memory path_buy = new address[](2);
        path_buy[0] = swap.WETH();
        path_buy[1] = token_out;

        // 1. try buy 0.001
        uint256[] memory amounts;

        amounts = swap.swapExactETHForTokens { value: msg.value } (
            0, path_buy, address(this), deadline
        );

        // 2. try to sell 
        // approve first
        IERC20 token_dest = IERC20(token_out);
        address pair = IPancakeFactory(swap.factory()).getPair(swap.WETH(), token_out);
        token_dest.approve(pair, amounts[1]); // approve WBNB/Token pair
        token_dest.approve(swap_router_addr, amounts[1]); // approve PancakeSwap Router

        // sell
        address[] memory path_sell = new address[](2);
        path_sell[0] = path_buy[1];
        path_sell[1] = path_buy[0];

        swap.swapExactTokensForETH(
            amounts[1], 0, path_sell, address(this), deadline);
    }
}

I can confirm the error occurs at the last line swapExactTokensForETH, it says "TRANSFER_FROM_FAILED", I guess it's about approve(), but I already approved the token for PancakeRoute before the swap.

Some failed tx sample: https://bscscan.com/tx/0x3feaa9c746ee4458d073a0311b90fb8658d45ed7bac4877bc2934f7e05c4c538

Why the error?

Best Answer

The issue is that you need to approve the pair and not the router. Looking at the transaction you linked you can see that it revert on the transfer from 0xa89C6f52Ce3Ce1BFF6CAac1E1c98b4f9b3AA5f63 (your contract) to 0x4a1a7f263b49dA21fBeD0907317233AA06AdF0dF (PancakePair). Therefore this is also the account that you need to approve.

The address of the PancakePair contract can be loaded from the PancakeFactory by calling getPair(tokenA, tokenB). The factory address can be loaded from the router via factory().

Edit:

The token that you are using enforces a transfer fee. For this you cannot use swapExactTokensForETH, you need to use swapExactTokensForTokensSupportingFeeOnTransferTokens.

Related Topic