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) to0x4a1a7f263b49dA21fBeD0907317233AA06AdF0dF
(PancakePair). Therefore this is also the account that you need to approve.The address of the
PancakePair
contract can be loaded from thePancakeFactory
by callinggetPair(tokenA, tokenB)
. Thefactory
address can be loaded from the router viafactory()
.Edit:
The token that you are using enforces a transfer fee. For this you cannot use
swapExactTokensForETH
, you need to useswapExactTokensForTokensSupportingFeeOnTransferTokens
.