I have a simple code using web3.py that sells BEP20 tokens:
deadline = int(time.time()) + 1200;
nonce = w3.eth.get_transaction_count(w3.eth.default_account)
sellTxn = self.web3Context.routerContract.functions.swapExactTokensForETHSupportingFeeOnTransferTokens(amountToSell, 1000000000000000,
[self.tokenAddress, self.web3Context.wrappedEthAddress],
account.address, deadline).buildTransaction({
'chainId': self.web3Context.chainId,
'nonce': nonce,
'gas': w3.toHex(500000),
'gasPrice': w3.toHex(int(w3.eth.gasPrice*2)),
})
signed_sellTxn = account.signTransaction(sellTxn)
sell_txid = w3.toHex(self.web3Context.w3.eth.sendRawTransaction(signed_sellTxn.rawTransaction))
sellReceipt = w3.eth.wait_for_transaction_receipt(sell_txid)
...
It's all uses pancakeswap V2 stuff, like router address, WBNB address, etc.
It does work with majority of tokens I tried it with. However, occasionally it fails with
Fail with error 'TransferHelper: TRANSFER_FROM_FAILED'
The token is approved before hand. This code is not called if a token is not approved, and I also checked that the transaction to approve it was confirmed before the above code was executed.
If it happens with a particular token, it will be failing no matter how many times I try to run it. However, if I sell manually using Pancakeswap, it works.
I compared the data I send with the data Pancakeswap sends, and I do not see any difference except in amountOutMin
. When it works, however, I can even pass 0
.
So, here is an example when the transaction fails:
Function: swapExactTokensForETHSupportingFeeOnTransferTokens(uint256 amountIn, uint256 amountOutMin, address[] path, address to, uint256 deadline)
0 amountIn uint256 1001887138366157231924
1 amountOutMin uint256 1000000000000000
2 path address[] ef155b9bcdbf4bd54143cf2ec7e47045cbbd2ebb
bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c
3 to address 3c94454135e91ab01bb4c1b816d4d6f9399b9a7d
And this is the transaction when it's submitted from Pancakeswap, and it works:
Function: swapExactTokensForETHSupportingFeeOnTransferTokens(uint256 amountIn, uint256 amountOutMin, address[] path, address to, uint256 deadline)
0 amountIn uint256 1004644755416763858179
1 amountOutMin uint256 24525898036735865
2 path address[] ef155b9bcdbf4bd54143cf2ec7e47045cbbd2ebb
bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c
3 to address 3c94454135e91ab01bb4c1b816d4d6f9399b9a7d
So, the only difference is the amountOutMin
value.
What is the best way to troubleshoot or debug this? Is there anything specific to look for in the token's contract?
So far I've seen it with handful of tokens: https://bscscan.com/address/0x0952ddffde60786497c7ced1f49b4a14cf527f76 https://bscscan.com/address/0x35ca09d3c28c24f1f32742ab91d794d2a524519e https://bscscan.com/address/0xd55eb92c40b8e19f5ff97cbbbdb721889a7b034a https://bscscan.com/address/0xd9f21eb27474981f419a0845ddfccc14e3fd4ecc https://bscscan.com/address/0xe68efedf3e1c08af12de6bdec585f89794a75c52 https://bscscan.com/address/0xef155b9bcdbf4bd54143cf2ec7e47045cbbd2ebb
Thanks!