简体   繁体   中英

Web3/nodejs not working with swapExactTokensForEth on Pancakeswapv2

I'm having real issues selling a token BUNNY for BNB on BSC. Here's what I know IS working

  1. checking the allowance shows I have approval to trade BUNNY on the PCSv2 router
  2. increasing the allowance also works
  3. Spending BNB to buy BUNNY works also (swapExactETHforTokens)
  4. manually writing into the contract on BSC scan also works

what doesn't work is swapExactTokensForETH - it spends some gas but throws up: "TRANSFER FROM FAILED"... reason: 'transaction failed', code: 'CALL_EXCEPTION' here's the failed transaction from the node.js script https://bscscan.com/tx/0x55d45e5f1e937fcd55294fa3e4d8c4c24d9c578b7ba8361fb12b2a017d7e7a4b

now all of the research i've done says it's because i need to approve the spender - I've done that... how do I know? well the function I wrote says it's fine as does querying BUNNY directly the other odd thing is that this worked perfectly (with no additional approval) - see screenshot

BSCScan Write Contract that works

here's the success transaction from the BSCscan write part of the router contract https://bscscan.com/tx/0xc8d2b999c08cef6ecceecf4bc5d6242bcd43571164016a8372bbf0c02d1a6185

If anyone can work out why this error is being thrown that would be a massive help tyvm in advance Here's the code:

const ethers = require('ethers');
const Web3 = require('web3');
const abi = require('human-standard-token-abi');
const {ChainId, Token, TokenAmount, Fetcher: v2Fetcher, Pair, Route, Trade, TradeType, Percent} = require('@pancakeswap-libs/sdk-v2');

const {JsonRpcProvider} = require("@ethersproject/providers");
const url = 'https://bsc-dataseed1.binance.org/';
const provider = new JsonRpcProvider('https://bsc-dataseed1.binance.org/');
const web3 = new Web3(url);

const secretKey = process.env.SECRETKEY;
const walletAddress = process.env.WALLETADDRESS;
const wallet = ethers.Wallet.fromMnemonic(secretKey);
const account = wallet.connect(provider);

const pcsRouterV2 = Web3.utils.toChecksumAddress('0x10ED43C718714eb63d5aA57B78B54704E256024E'); //v2 router
const routerV2 = new ethers.Contract (pcsRouterV2, [
    'function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts)',
    'function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts)',
    'function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)',
    'function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)'
    ], account );

const bunnyAddress = Web3.utils.toChecksumAddress('0xc9849e6fdb743d08faee3e34dd2d1bc69ea11a51');
const wbnbAddress = Web3.utils.toChecksumAddress('0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c'); // WBNB

const gasApprovalLimit = 100000;
const gasTradingLimit = 250000;
const gasPrice = 5;

const getAllowance = async (tickerTokenAddress, thisWalletAddress, liquidtyPoolRouter) => {
    var contract = new web3.eth.Contract(abi, tickerTokenAddress);
    let approvalLimit = await contract.methods.allowance(thisWalletAddress, liquidtyPoolRouter).call();
    let decimals = await contract.methods.decimals().call();
    // this comes back with 3 variables, an approval, an approval in token units and the decimals
    return [approvalLimit, approvalLimit / (10 ** decimals), decimals];
}

const getApproval = async (thisTokenAddress, approvalAmount, thisDecimals, walletAccount, liquidtyPoolRouter, thisGasPrice = gasPrice, thisGasLimit = gasApprovalLimit)  => {
    console.log(`getting approval`);
    let contract = new ethers.Contract(thisTokenAddress, abi, walletAccount);
    let approveResponse = await contract.approve(
        liquidtyPoolRouter, 
        ethers.utils.parseUnits(approvalAmount.toString(), thisDecimals),
        {
            gasLimit: thisGasLimit, 
            gasPrice: ethers.utils.parseUnits(thisGasPrice.toString(), 'gwei')
        });
    console.log(approveResponse);
}

const swapExactBNBForTokens = async (buyAddress, buyDecimals, tokensIn, tradeSlippage, thisGasPrice = gasPrice, thisGasLimit = gasTradingLimit) => {
    let amountIn = ethers.utils.parseUnits(tokensIn.toString(), buyDecimals);
    let amounts = await routerV2.getAmountsOut(amountIn, [wbnbAddress, buyAddress]);
    let amountOutMin = amounts[1].sub(amounts[1].mul(tradeSlippage).div(100));
    let tx = await routerV2.swapExactETHForTokens(
        amountOutMin,
        [wbnbAddress, buyAddress],
        walletAddress,
        Date.now() + 1000 * 60 * 10,
        {
            value: amountIn,
            gasLimit: thisGasLimit, 
            gasPrice: ethers.utils.parseUnits(thisGasPrice.toString(), 'gwei')
        }
    )
    console.log(`Transaction Submitted...`);
    let receipt = await tx.wait();
    console.log(receipt);
}

const swapExactTokensForBNB = async (sellAddress, sellDecimals, tokensIn, tradeSlippage, thisGasPrice = gasPrice, thisGasLimit = gasTradingLimit) => {
    let amountIn = ethers.utils.parseUnits(tokensIn.toString(), sellDecimals);
    let amounts = await routerV2.getAmountsOut(amountIn, [sellAddress, wbnbAddress]);
    let amountOutMin = amounts[1].sub(amounts[1].mul(tradeSlippage).div(100));

    let tx = await routerV2.swapExactTokensForETH(
        amountIn, 
        amountOutMin,
        [sellAddress, wbnbAddress],
        walletAddress,
        Date.now() + 1000 * 60 * 10,
        {
            gasLimit: thisGasLimit, 
            gasPrice: ethers.utils.parseUnits(thisGasPrice.toString(), 'gwei')
        }
    )
    console.log(`Transaction Submitted...`);
    let receipt = await tx.wait();
    console.log(receipt);
}

// USAGE
// swapExactBNBForTokens(bunnyAddress, 18, 0.3, 2); // spending 0.3 BNB to buy BUNNY
// swapExactTokensForBNB(bunnyAddress, 18, 3, 2); // spending 3 BUNNY to buy BNB
getAllowance(bunnyAddress, walletAddress, pcsRouterV2).then((value) => {console.log('V2 ' + value);});

This is the amountIn you supplied in failed tx: 329971861416174 6000 .

This is the amountIn you supplied in successful tx: 329971861416174 5787 , and it's less.

So I assume you've provided incorrect amountIn, that is greater than your balance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM