2

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

5
  • 1
    can you verify your contracts on BSC testnet, please? it would get great if you can add the router and factory address on which your script worked (possibly included successful txn id as well)
    – hack3r-0m
    Apr 18, 2021 at 22:26
  • Would recommend you to get your contracts verified and deployed on the bsc testnet and also add it to tenderly (tenderly.co) and debug the failed tx there you will get the point of failure
    – viraj
    Apr 22, 2021 at 7:34
  • @hack3r_0m this is the address of verified pancake factory testnet.bscscan.com/address/… and the address of the verified pancake router testnet.bscscan.com/address/….
    – mzaidi
    Apr 25, 2021 at 16:04
  • check my edited question for more details
    – mzaidi
    Apr 25, 2021 at 16:13
  • 1
    can you verify the router & factory involved successful transaction as well? I will update my answer accordingly in the future if I find anything suspicious.
    – hack3r-0m
    Apr 26, 2021 at 5:21

2 Answers 2

2

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.

1
  • I calculated the init_hash now and added it to the pancake library and deployed and verified the new router again. Then called liquidity function and it still gave me the same error. This is the failed transaction 0x8090a672625fa79932d617ec460ae17a7ea975389604753804ed
    – mzaidi
    Apr 26, 2021 at 10:47
1

Okay after spending days on this issue I came to know that I was just changing the init_hash once before multiple deployments over testnet. The init_hash changes everytime, so you have to copy the init_hash from pancake pair file into pancake library each time. After doing so I was able to successfully add liquidity using my own router and factory address over bsc testnet.

2
  • I think I am running into the same issue as you. Can you explain a bit more where this init_hash is? I looked in PancakePair.sol but I cannot find it
    – mch56
    May 26, 2021 at 17:15
  • 1
    The init_hash is located in your PancakeFactory.sol file first you will deploy it and note down the value of hash. Then you will paste this hash value in PancakeLibrary.sol which is located in libraries folder of the periphery repo.
    – mzaidi
    May 27, 2021 at 6:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.