I'm completely new to web3, and I do realise that there is small portion of information on the web3 for developers, especially when it comes to debugging and issue solving.
My main goal is just to succeed in calling a swap function "swapExactTokensForTokens" on PancakeSwapV2 Testnet on Binance Testnet (chain 97).
I was getting "execution_reverted" for all my transactions even tho passed in parameters shown in bscscan were correct. I though that perhaps it is an issue with parameters, so I tried other method "getAmountsOut" and still got error:
Then I tried calling "EstimateGasAsync" and still got same error "execution reverted: eth_estimateGas".
I have absolutely 0 ideas left what the actual issue could be since it gives absolute 0 information on why it fails and the only way I can try figuring it out is by doing shotgun testing which is stupid…
I feel like there is an issue with some of contract addresses/abi or I'm incorrectly instantiating "Web3". But I know that an issue is basically in first lines of code and not in functions or core logic itself.
Code you can use in playground (only private key needs to be added):
using Nethereum.Contracts;
using Nethereum.Hex.HexTypes;
using Nethereum.RPC.Eth.DTOs;
using Nethereum.Util;
using Nethereum.Web3;
using Nethereum.Web3.Accounts;
using System.Numerics;
using System.Threading.Tasks;
class PancakeSwapExample
{
// ready-to-run code
static async Task Main(string[] args)
{
var pancakeSwapRouterAddressTestnet = "0xdc4904b5f716Ff30d8495e35dC99c109bb5eCf81";
var tBNBToken = "0x24942357E3A688ACE7C39710aA6d3C91BA1FAC39";
var CAKEToken = "0xFa60D973F7642B748046464e165A65B7323b0DEE";
var binanceTestnetNode = "https://data-seed-prebsc-1-s1.binance.org:8545/";
var binanceChainId = 97;
var amount = 0.01M; // tBNB
var abi = @"[{""inputs"":[{""internalType"":""address"",""name"":""_factory"",""type"":""address""},{""internalType"":""address"",""name"":""_WETH"",""type"":""address""}],""stateMutability"":""nonpayable"",""type"":""constructor""},{""inputs"":[],""name"":""WETH"",""outputs"":[{""internalType"":""address"",""name"":"""",""type"":""address""}],""stateMutability"":""view"",""type"":""function""},{""inputs"":[{""internalType"":""address"",""name"":""tokenA"",""type"":""address""},{""internalType"":""address"",""name"":""tokenB"",""type"":""address""},{""internalType"":""uint256"",""name"":""amountADesired"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountBDesired"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountAMin"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountBMin"",""type"":""uint256""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""addLiquidity"",""outputs"":[{""internalType"":""uint256"",""name"":""amountA"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountB"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""liquidity"",""type"":""uint256""}],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""address"",""name"":""token"",""type"":""address""},{""internalType"":""uint256"",""name"":""amountTokenDesired"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountTokenMin"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountETHMin"",""type"":""uint256""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""addLiquidityETH"",""outputs"":[{""internalType"":""uint256"",""name"":""amountToken"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountETH"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""liquidity"",""type"":""uint256""}],""stateMutability"":""payable"",""type"":""function""},{""inputs"":[],""name"":""factory"",""outputs"":[{""internalType"":""address"",""name"":"""",""type"":""address""}],""stateMutability"":""view"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountOut"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""reserveIn"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""reserveOut"",""type"":""uint256""}],""name"":""getAmountIn"",""outputs"":[{""internalType"":""uint256"",""name"":""amountIn"",""type"":""uint256""}],""stateMutability"":""pure"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountIn"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""reserveIn"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""reserveOut"",""type"":""uint256""}],""name"":""getAmountOut"",""outputs"":[{""internalType"":""uint256"",""name"":""amountOut"",""type"":""uint256""}],""stateMutability"":""pure"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountOut"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""}],""name"":""getAmountsIn"",""outputs"":[{""internalType"":""uint256[]"",""name"":""amounts"",""type"":""uint256[]""}],""stateMutability"":""view"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountIn"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""}],""name"":""getAmountsOut"",""outputs"":[{""internalType"":""uint256[]"",""name"":""amounts"",""type"":""uint256[]""}],""stateMutability"":""view"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountA"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""reserveA"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""reserveB"",""type"":""uint256""}],""name"":""quote"",""outputs"":[{""internalType"":""uint256"",""name"":""amountB"",""type"":""uint256""}],""stateMutability"":""pure"",""type"":""function""},{""inputs"":[{""internalType"":""address"",""name"":""tokenA"",""type"":""address""},{""internalType"":""address"",""name"":""tokenB"",""type"":""address""},{""internalType"":""uint256"",""name"":""liquidity"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountAMin"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountBMin"",""type"":""uint256""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""removeLiquidity"",""outputs"":[{""internalType"":""uint256"",""name"":""amountA"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountB"",""type"":""uint256""}],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""address"",""name"":""token"",""type"":""address""},{""internalType"":""uint256"",""name"":""liquidity"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountTokenMin"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountETHMin"",""type"":""uint256""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""removeLiquidityETH"",""outputs"":[{""internalType"":""uint256"",""name"":""amountToken"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountETH"",""type"":""uint256""}],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""address"",""name"":""token"",""type"":""address""},{""internalType"":""uint256"",""name"":""liquidity"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountTokenMin"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountETHMin"",""type"":""uint256""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""removeLiquidityETHSupportingFeeOnTransferTokens"",""outputs"":[{""internalType"":""uint256"",""name"":""amountETH"",""type"":""uint256""}],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""address"",""name"":""token"",""type"":""address""},{""internalType"":""uint256"",""name"":""liquidity"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountTokenMin"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountETHMin"",""type"":""uint256""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""},{""internalType"":""bool"",""name"":""approveMax"",""type"":""bool""},{""internalType"":""uint8"",""name"":""v"",""type"":""uint8""},{""internalType"":""bytes32"",""name"":""r"",""type"":""bytes32""},{""internalType"":""bytes32"",""name"":""s"",""type"":""bytes32""}],""name"":""removeLiquidityETHWithPermit"",""outputs"":[{""internalType"":""uint256"",""name"":""amountToken"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountETH"",""type"":""uint256""}],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""address"",""name"":""token"",""type"":""address""},{""internalType"":""uint256"",""name"":""liquidity"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountTokenMin"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountETHMin"",""type"":""uint256""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""},{""internalType"":""bool"",""name"":""approveMax"",""type"":""bool""},{""internalType"":""uint8"",""name"":""v"",""type"":""uint8""},{""internalType"":""bytes32"",""name"":""r"",""type"":""bytes32""},{""internalType"":""bytes32"",""name"":""s"",""type"":""bytes32""}],""name"":""removeLiquidityETHWithPermitSupportingFeeOnTransferTokens"",""outputs"":[{""internalType"":""uint256"",""name"":""amountETH"",""type"":""uint256""}],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""address"",""name"":""tokenA"",""type"":""address""},{""internalType"":""address"",""name"":""tokenB"",""type"":""address""},{""internalType"":""uint256"",""name"":""liquidity"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountAMin"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountBMin"",""type"":""uint256""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""},{""internalType"":""bool"",""name"":""approveMax"",""type"":""bool""},{""internalType"":""uint8"",""name"":""v"",""type"":""uint8""},{""internalType"":""bytes32"",""name"":""r"",""type"":""bytes32""},{""internalType"":""bytes32"",""name"":""s"",""type"":""bytes32""}],""name"":""removeLiquidityWithPermit"",""outputs"":[{""internalType"":""uint256"",""name"":""amountA"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountB"",""type"":""uint256""}],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountOut"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""swapETHForExactTokens"",""outputs"":[{""internalType"":""uint256[]"",""name"":""amounts"",""type"":""uint256[]""}],""stateMutability"":""payable"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountOutMin"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""swapExactETHForTokens"",""outputs"":[{""internalType"":""uint256[]"",""name"":""amounts"",""type"":""uint256[]""}],""stateMutability"":""payable"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountOutMin"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""swapExactETHForTokensSupportingFeeOnTransferTokens"",""outputs"":[],""stateMutability"":""payable"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountIn"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountOutMin"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""swapExactTokensForETH"",""outputs"":[{""internalType"":""uint256[]"",""name"":""amounts"",""type"":""uint256[]""}],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountIn"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountOutMin"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""swapExactTokensForETHSupportingFeeOnTransferTokens"",""outputs"":[],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountIn"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountOutMin"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""swapExactTokensForTokens"",""outputs"":[{""internalType"":""uint256[]"",""name"":""amounts"",""type"":""uint256[]""}],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountIn"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountOutMin"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""swapExactTokensForTokensSupportingFeeOnTransferTokens"",""outputs"":[],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountOut"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountInMax"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""swapTokensForExactETH"",""outputs"":[{""internalType"":""uint256[]"",""name"":""amounts"",""type"":""uint256[]""}],""stateMutability"":""nonpayable"",""type"":""function""},{""inputs"":[{""internalType"":""uint256"",""name"":""amountOut"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amountInMax"",""type"":""uint256""},{""internalType"":""address[]"",""name"":""path"",""type"":""address[]""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""}],""name"":""swapTokensForExactTokens"",""outputs"":[{""internalType"":""uint256[]"",""name"":""amounts"",""type"":""uint256[]""}],""stateMutability"":""nonpayable"",""type"":""function""},{""stateMutability"":""payable"",""type"":""receive""}]";
var yourWalletPrivateKey = "YOUR_WALLET_KEY_FOR_BSC_TESTNET"; // Only this needs to be changed
Account account = new Account(yourWalletPrivateKey, binanceChainId);
Web3 web3 = new Web3(account, binanceTestnetNode);
Contract smartContract = web3.Eth.GetContract(abi, pancakeSwapRouterAddressTestnet);
Function swapExactTokensForTokensFunction = smartContract.GetFunction("swapExactTokensForTokens");
var amountIn = Web3.Convert.ToWei(amount, UnitConversion.EthUnit.Ether);
var amountOutMin = Web3.Convert.ToWei(0.05, UnitConversion.EthUnit.Ether);
var path = new[] { tBNBToken, CAKEToken };
object[] parametersForSwap = new object[4] { amountIn, amountOutMin, path, account.Address };
BigInteger wei = Web3.Convert.ToWei(amount);
HexBigInteger value = new HexBigInteger(wei);
// Fails here
HexBigInteger estimatedGas = await swapExactTokensForTokensFunction.EstimateGasAsync(account.Address, null, value, parametersForSwap);
// My goal is to succeed in this transaction, so it would not be in 'Fail' state
TransactionReceipt transactionReceiptForSwap = await swapExactTokensForTokensFunction.SendTransactionAndWaitForReceiptAsync(account.Address, estimatedGas, value, null, parametersForSwap);
}
}
ANY help is much appreciated.
Best Answer
Jesus christ, I finally managed to make it work, HUGE thanks to @tqdpham96 for pointing out to root cause... I believe I wouldn't be able to find this somewhere else as there is absolutely NO information, and no one is talking that you should APPROVE coin for swap before doing actual swap.
So, basically, in details - before doing any swap, you make one-time approval for coin to swap from, you have to call
approve()
function on that coin. For example, if you're willing to swap from WBNB to CAKE then you have to approve WBNB, so that PancakeSwap would be able (had permission) to withdraw your WBNB in order to do swap for CAKE. And vice-verse, if you're willing to do swap from CAKE to WBNB, then you have to do everything the same - approve for CAKE, so that PancakeSwap had permission to withdraw your CAKE and deposit WBNB.Here is FULLY working code on PancakeSwapV2Router for C#, which does
approve()
for initial coin (WBNB), and then does swap WBNB to CAKE, just provide private key and you are ready to go:Please note, that code runs against Mainnet, not Testnet. I wish there was more information for C# developers on web3 for things like that... Hope this gonna save time to someone.