Pancakeswap – Failed to Add Liquidity in Pancakeswap

contract-developmentgo-ethereumsoliditytruffleuniswap

I am trying to make a few transactions on binance test net using a script in solidity and truffle which is a clone of PANCAKESWAP. I was able to successfully compile and execute the script once. When I tried to do it again on different addresses for router and factory it gave me the following error:

StatusError: Transaction: 0xc94424b8c6037e75e0eaf5f21982e2f73f88e71e18e0e5e783c642d6210e686f exited with an error (status 0). 
    at module.exports (D:\Blockchain\pancake\createpool\scripts\deploypool.js:18:18)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5) {
  tx: '0xc94424b8c6037e75e0eaf5f21982e2f73f88e71e18e0e5e783c642d6210e686f',
  receipt: {
    blockHash: '0xc4bea040096811e809c18216d85fc82813b60db9545d4e1bf6ab7c4dd344fe87',
    blockNumber: 8023495,
    contractAddress: null,
    cumulativeGasUsed: 699140,
    from: '0xe95745a8f4e3cdb1cf5bffd4a94f0b249e99f489',
    gasUsed: 29046,
    logs: [],
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    status: false,
    to: '0x7632ae832440032fb4ca93e56873a92a01b06e13',
    transactionHash: '0xc94424b8c6037e75e0eaf5f21982e2f73f88e71e18e0e5e783c642d6210e686f',
    transactionIndex: 2,
    rawLogs: []
  },
  reason: undefined,
  hijackedStack: 'StatusError: Transaction: 0xc94424b8c6037e75e0eaf5f21982e2f73f88e71e18e0e5e783c642d6210e686f exited with an error (status 0). \n' +
    '     Please check that the transaction:\n' +
    '     - satisfies all conditions set by Solidity `require` statements.\n' +
    '     - does not trigger a Solidity `revert` statement.\n' +
    '\n' +
    '    at Object.receipt (C:\\Users\\DELL\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\packages\\contract\\lib\\handlers.js:124:1)\n' +
    '    at runMicrotasks (<anonymous>)\n' +
    '    at processTicksAndRejections (internal/process/task_queues.js:97:5)\n' +
    '    at Function.start (C:\\Users\\DELL\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\packages\\contract\\lib\\override.js:49:1)'

My truffle-config.js:

//SPDX-License-Identifier: MIT 
require('dotenv').config();
var HDWalletProvider = require("truffle-hdwallet-provider");

const infuraKey = process.env.infuraKey;
const mnemonic = process.env.mnemonic;

module.exports = {

  networks: {
    // Useful for testing. The `development` name is special - truffle uses it by default
    // if it's defined here and no other network is specified at the command line.
    // You should run a client (like ganache-cli, geth or parity) in a separate terminal
    // tab if you use this network and you must also set the `host`, `port` and `network_id`
    // options below to some value.
    //
    development: {
      host: "127.0.0.1",     // Localhost (default: none)
      port: 8545,            // Standard Ethereum port (default: none)
      network_id: "*",       // Any network (default: none)
    },
    rinkeby: {
      provider: function () {
        return new HDWalletProvider(mnemonic, "https://rinkeby.infura.io/v3/" + infuraKey);
      },

      network_id: 4,
      gas: 4500000,
      gasPrice: 10000000000,
    },

    bscTestnet: {
      provider: () => new HDWalletProvider(
        mnemonic,
        'https://data-seed-prebsc-1-s1.binance.org:8545'
      ),
      from: '0xe95745a8F4E3cDb1cF5bfFD4A94F0B249e99f489',
      network_id: 97,
      gas: 4500000,
      gasPrice: 10000000000,
      skipDryRun: true
    },
    mainnet: {
      provider: () => new HDWalletProvider(
        mnemonic,
        'https://bsc-dataseed.binance.org/'
      ),
      network_id: 56,
      gas: 4500000,
      gasPrice: 10000000000,
      skipDryRun: true
    }

  },

  mocha: {
    // timeout: 100000
  },

  // Configure your compilers
  compilers: {
    solc: {
      version: "0.8.0",    // Fetch exact version from solc-bin (default: truffle's version)
      // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
      // settings: {          // See the solidity docs for advice about optimization and evmVersion
      //  optimizer: {
      //    enabled: false,
      //    runs: 200
      //  },
      //  evmVersion: "byzantium"
      // }
    },
  },
};

When i tried to do the same using a truffle command instead of the script it gave me the same error. The truffle command was:

pool.addLiquidity("0x84D2A9d0D51fd578c76908603bfdd91417F54915","0x22E692b514690757Bc26DE1C01d4Fc7207d30f90",4000,4000,7000,7000,"0xe95745a8F4E3cDb1cF5bfFD4A94F0B249e99f489",Math.floor(Date.now() / 1000) + 60 * 10).then(function(r){console.log(r);});

My liquidity functions are below:
I have even tried remove the assert statement and replacing it with an if but face the same error.

// **** ADD LIQUIDITY ****
    function _addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin
    ) private returns (uint amountA, uint amountB) {
        // create the pair if it doesn't exist yet
        if (INiftFactory(factory).getPair(tokenA, tokenB) == address(0)) {
            INiftFactory(factory).createPair(tokenA, tokenB);
        }
        (uint reserveA, uint reserveB) = NiftLibrary.getReserves(factory, tokenA, tokenB);
        if (reserveA == 0 && reserveB == 0) {
            (amountA, amountB) = (amountADesired, amountBDesired);
        } else {
            uint amountBOptimal = NiftLibrary.quote(amountADesired, reserveA, reserveB);
            if (amountBOptimal <= amountBDesired) {
                require(amountBOptimal >= amountBMin, 'NiftRouter: INSUFFICIENT_B_AMOUNT');
                (amountA, amountB) = (amountADesired, amountBOptimal);
            } else {
                uint amountAOptimal = NiftLibrary.quote(amountBDesired, reserveB, reserveA);
                assert(amountAOptimal <= amountADesired);
                require(amountAOptimal >= amountAMin, 'NiftRouter: INSUFFICIENT_A_AMOUNT');
                (amountA, amountB) = (amountAOptimal, amountBDesired);
            }
        }
    }
    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external override ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) {
        (amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
        address pair = NiftLibrary.pairFor(factory, tokenA, tokenB);
        TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA);
        TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB);
        liquidity = INiftPair(pair).mint(to);
    }
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external override payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
        (amountToken, amountETH) = _addLiquidity(
            token,
            WETH,
            amountTokenDesired,
            msg.value,
            amountTokenMin,
            amountETHMin
        );
        address pair = NiftLibrary.pairFor(factory, token, WETH);
        TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken);
        IWETH(WETH).deposit{value: amountETH}();
        assert(IWETH(WETH).transfer(pair, amountETH));
        liquidity = INiftPair(pair).mint(to);
        if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH); // refund dust eth, if any
    }

My deploypool.js file:

const Factory = artifacts.require('Factory.sol');
const Router = artifacts.require('Router.sol');
const Pair = artifacts.require('Pair.sol');
const Token1 = artifacts.require('token1.sol');
const Token2 = artifacts.require('token2.sol');

module.exports = async done => {
  try {
    //const [admin, _] = await web3.eth.getAccounts();
    const factory = await Factory.at('0x81338c4e7a7f30297aF1dd1dBF02Fc1299b0EA12');
    const router = await Router.at('0x73D58041eDdD468e016Cfbc13f3BDc4248cCD65D');
    const token1 = await Token1.new();
    const token2 = await Token2.new();
    const pairAddress = await factory.createPair.call(token1.address, token2.address);
    const tx = await factory.createPair(token1.address, token2.address);
    await token1.approve(router.address, 10000);
    await token2.approve(router.address, 10000);
    await router.addLiquidity(
      token1.address,
      token2.address,
      9000,
      9000,
      10000,
      10000,
      'mymetamaskaddress',
      Math.floor(Date.now() / 1000) + 60 * 10
    );
    const pair = await Pair.at(pairAddress);
    const balance = await pair.balanceOf("0xe95745a8F4E3cDb1cF5bfFD4A94F0B249e99f489");
    console.log(`balance LP: ${balance.toString()}`);
  } catch (e) {
    console.log(e);
  }
  done();
};

Address of verified router https://testnet.bscscan.com/address/0x73D58041eDdD468e016Cfbc13f3BDc4248cCD65D#code

Address of verified factory
https://testnet.bscscan.com/address/0x81338c4e7a7f30297af1dd1dbf02fc1299b0ea12#code

Previous Successful transaction with a different factory and router address
https://testnet.bscscan.com/tx/0x9ca6e07ffcc0ab50c2f181783a14a17e850ad16dbd15c1590e4f2321cc9d44b5

Best Answer

your deploy script fails at:

await router.addLiquidity(...)

while making a call to addLiquidity(), when it reaches:

(uint reserveA, uint reserveB) = PancakeLibrary.getReserves(factory, tokenA, tokenB);

which in turn fails at:

(uint reserve0, uint reserve1,) = IPancakePair(pairFor(factory, tokenA, tokenB)).getReserves();

here the output of pairFor for tokenA and tokenB is 0x78715162d94936c07d811a03e3e0411a4270bf6c while your tokens pair is deployed at 0xb8c774F637C2B40d2a834Bb6c1EecD7c96166Cf9. _addLiquidity fucntion of router creates the pair if it doesn't exists (checks by calling getPair() == 0x000...0) and if pair exists then calls getReserves() which in turn calls pairFor(). If you have made changes to PancakePair then init_hash might change and address calculated by pairFor() to find pair might be different. You can try removing createPair call to factory and check without it.

Related Topic