Draining Connection. 4040

2021-11-30T08:56:45.285696+00:00 app[arbitrage.1]:     at WebSocketConnection.emit (events.js:400:28)

2021-11-30T08:56:45.285696+00:00 app[arbitrage.1]:     at WebSocketConnection.handleSocketClose (/app/node_modules/websocket/lib/WebSocketConnection.js:389:14)

2021-11-30T08:56:45.285697+00:00 app[arbitrage.1]:     at TLSSocket.emit (events.js:412:35)

2021-11-30T08:56:45.285697+00:00 app[arbitrage.1]:     at net.js:686:12

2021-11-30T08:56:45.285698+00:00 app[arbitrage.1]:     at TCP.done (_tls_wrap.js:564:7) {

2021-11-30T08:56:45.285698+00:00 app[arbitrage.1]:   code: 4040,

2021-11-30T08:56:45.285698+00:00 app[arbitrage.1]:   reason: 'Draining connection'

2021-11-30T08:56:45.285699+00:00 app[arbitrage.1]: }

2021-11-30T08:56:45.498389+00:00 heroku[arbitrage.1]: Process exited with status 0

2021-11-30T08:56:45.571632+00:00 heroku[arbitrage.1]: State changed from up to crashed

2021-11-30T10:11:35.303205+00:00 heroku[arbitrage.1]: State changed from crashed to starting

2021-11-30T10:11:39.218702+00:00 heroku[arbitrage.1]: Starting process with command `node bscFlashArb1.js`

2021-11-30T10:11:39.788533+00:00 heroku[arbitrage.1]: State changed from starting to up

2021-11-30T10:16:37.187777+00:00 heroku[arbitrage.1]: Process exited with status 0

2021-11-30T10:16:37.289534+00:00 heroku[arbitrage.1]: State changed from up to crashed

2021-11-30T10:16:37.018779+00:00 app[arbitrage.1]: Error: CONNECTION ERROR: The connection got closed with the close code `4040` and the following reason string `Draining connection`

2021-11-30T10:16:37.018791+00:00 app[arbitrage.1]:     at Object.ConnectionError (/app/node_modules/web3-core-helpers/lib/errors.js:66:23)

2021-11-30T10:16:37.018791+00:00 app[arbitrage.1]:     at Object.ConnectionCloseError (/app/node_modules/web3-core-helpers/lib/errors.js:53:25)

2021-11-30T10:16:37.018792+00:00 app[arbitrage.1]:     at /app/node_modules/web3-core-requestmanager/lib/index.js:119:50

2021-11-30T10:16:37.018792+00:00 app[arbitrage.1]:     at Map.forEach (<anonymous>)

2021-11-30T10:16:37.018793+00:00 app[arbitrage.1]:     at WebsocketProvider.disconnect (/app/node_modules/web3-core-requestmanager/lib/index.js:118:37)

2021-11-30T10:16:37.018793+00:00 app[arbitrage.1]:     at WebsocketProvider.emit (/app/node_modules/eventemitter3/index.js:181:35)

2021-11-30T10:16:37.018793+00:00 app[arbitrage.1]:     at WebsocketProvider._onClose (/app/node_modules/web3-providers-ws/lib/index.js:152:10)

2021-11-30T10:16:37.018794+00:00 app[arbitrage.1]:     at W3CWebSocket._dispatchEvent [as dispatchEvent] (/app/node_modules/yaeti/lib/EventTarget.js:115:12)

2021-11-30T10:16:37.018794+00:00 app[arbitrage.1]:     at W3CWebSocket.onClose (/app/node_modules/websocket/lib/W3CWebSocket.js:228:10)

2021-11-30T10:16:37.018794+00:00 app[arbitrage.1]:     at WebSocketConnection.<anonymous> (/app/node_modules/websocket/lib/W3CWebSocket.js:201:17)

2021-11-30T10:16:37.018795+00:00 app[arbitrage.1]:     at WebSocketConnection.emit (events.js:400:28)

2021-11-30T10:16:37.018795+00:00 app[arbitrage.1]:     at WebSocketConnection.handleSocketClose (/app/node_modules/websocket/lib/WebSocketConnection.js:389:14)

2021-11-30T10:16:37.018795+00:00 app[arbitrage.1]:     at TLSSocket.emit (events.js:412:35)

2021-11-30T10:16:37.018795+00:00 app[arbitrage.1]:     at net.js:686:12

2021-11-30T10:16:37.018796+00:00 app[arbitrage.1]:     at TCP.done (_tls_wrap.js:564:7) {

2021-11-30T10:16:37.018796+00:00 app[arbitrage.1]:   code: 4040,

2021-11-30T10:16:37.018797+00:00 app[arbitrage.1]:   reason: 'Draining connection'

2021-11-30T10:16:37.018797+00:00 app[arbitrage.1]: }

2021-11-30T10:16:37.024479+00:00 app[arbitrage.1]: Error: CONNECTION ERROR: Couldn't connect to node on WS.

2021-11-30T10:16:37.024480+00:00 app[arbitrage.1]:     at Object.ConnectionError (/app/node_modules/web3-core-helpers/lib/errors.js:66:23)

2021-11-30T10:16:37.024480+00:00 app[arbitrage.1]:     at Object.InvalidConnection (/app/node_modules/web3-core-helpers/lib/errors.js:36:21)

2021-11-30T10:16:37.024481+00:00 app[arbitrage.1]:     at /app/node_modules/web3-providers-ws/lib/index.js:161:37

2021-11-30T10:16:37.024481+00:00 app[arbitrage.1]:     at Map.forEach (<anonymous>)

2021-11-30T10:16:37.024481+00:00 app[arbitrage.1]:     at WebsocketProvider._onClose (/app/node_modules/web3-providers-ws/lib/index.js:160:28)

2021-11-30T10:16:37.024482+00:00 app[arbitrage.1]:     at W3CWebSocket._dispatchEvent [as dispatchEvent] (/app/node_modules/yaeti/lib/EventTarget.js:115:12)

2021-11-30T10:16:37.024483+00:00 app[arbitrage.1]:     at W3CWebSocket.onClose (/app/node_modules/websocket/lib/W3CWebSocket.js:228:10)

2021-11-30T10:16:37.024483+00:00 app[arbitrage.1]:     at WebSocketConnection.<anonymous> (/app/node_modules/websocket/lib/W3CWebSocket.js:201:17)

2021-11-30T10:16:37.024483+00:00 app[arbitrage.1]:     at WebSocketConnection.emit (events.js:400:28)

2021-11-30T10:16:37.024484+00:00 app[arbitrage.1]:     at WebSocketConnection.handleSocketClose (/app/node_modules/websocket/lib/WebSocketConnection.js:389:14)

2021-11-30T10:16:37.024484+00:00 app[arbitrage.1]:     at TLSSocket.emit (events.js:412:35)

2021-11-30T10:16:37.024485+00:00 app[arbitrage.1]:     at net.js:686:12

2021-11-30T10:16:37.024486+00:00 app[arbitrage.1]:     at TCP.done (_tls_wrap.js:564:7) {

2021-11-30T10:16:37.024486+00:00 app[arbitrage.1]:   code: 4040,

2021-11-30T10:16:37.024487+00:00 app[arbitrage.1]:   reason: 'Draining connection'

2021-11-30T10:16:37.024487+00:00 app[arbitrage.1]: }

Disconnected from log stream. There may be events happening that you do not see here! Attempting to reconnect...

2021-11-30T10:16:37.024483+00:00 app[arbitrage.1]:     at WebSocketConnection.emit (events.js:400:28)

2021-11-30T10:16:37.024484+00:00 app[arbitrage.1]:     at WebSocketConnection.handleSocketClose (/app/node_modules/websocket/lib/WebSocketConnection.js:389:14)

2021-11-30T10:16:37.024484+00:00 app[arbitrage.1]:     at TLSSocket.emit (events.js:412:35)

2021-11-30T10:16:37.024485+00:00 app[arbitrage.1]:     at net.js:686:12

2021-11-30T10:16:37.024486+00:00 app[arbitrage.1]:     at TCP.done (_tls_wrap.js:564:7) {

2021-11-30T10:16:37.024486+00:00 app[arbitrage.1]:   code: 4040,

2021-11-30T10:16:37.024487+00:00 app[arbitrage.1]:   reason: 'Draining connection'

2021-11-30T10:16:37.024487+00:00 app[arbitrage.1]: }

2021-11-30T10:16:37.187777+00:00 heroku[arbitrage.1]: Process exited with status 0

2021-11-30T10:16:37.289534+00:00 heroku[arbitrage.1]: State changed from up to crashed

2021-11-30T10:50:55.859675+00:00 heroku[arbitrage.1]: State changed from crashed to starting

2021-11-30T10:50:58.714643+00:00 heroku[arbitrage.1]: Starting process with command `node bscFlashArb1.js`

2021-11-30T10:50:59.312175+00:00 heroku[arbitrage.1]: State changed from starting to up
I created a flashloan bot for arbitrage (on bsc) and deployed it to heroku. The bot keeps crashing with the same error (draining connection error 400). 
Here is the hole script:

require('dotenv').config();
const Web3 = require('web3');
const abis = require('./abis');
const { mainnet: addresses } = require('./addresses');

const web3 = new Web3(
    new Web3.providers.WebsocketProvider(process.env.MORALIS_WSS_URL)
);

// const web3 = new Web3(
//     new Web3.providers.WebsocketProvider(process.env.BSC_WSS_URL)
// );


const { address: admin } = web3.eth.accounts.wallet.add(process.env.PRIVATE_KEY);

const AMOUNT_DAI_WEI = web3.utils.toBN(web3.utils.toWei('THE_AMOUNT_YOU_WANT_TO_BORROW'));

const init = async () => {

    const BscFlashArb1 = new web3.eth.Contract(
        abis.bscFlashArb1.abi,
        addresses.bscFlashArb1.addr
    );

    const PancakeSwap = new web3.eth.Contract(
        abis.pancakeSwap.router,
        addresses.pancakeSwap.router
    );

    const BakerySwap = new web3.eth.Contract(
        abis.bakerySwap.router,
        addresses.bakerySwap.router
    );

    web3.eth.subscribe('newBlockHeaders')
    .on('data', async block => {
        try {

            // borrow DAI from pancakeswap and sell it on
            // bakeryswap. Repay in WBNB. Keep the profit in WBNB
            const [amountsIn1, amountsOut1] = await Promise.all([
                PancakeSwap.methods
                .getAmountsIn(
                    AMOUNT_DAI_WEI,
                    [addresses.tokens.WBNB, addresses.tokens.DAI]
                ).call(),
                BakerySwap.methods
                .getAmountsOut(
                    AMOUNT_DAI_WEI,
                    [addresses.tokens.DAI, addresses.tokens.WBNB]
                ).call()
            ]);

            const profit_in_WBNB = web3.utils.toBN(amountsOut1[1]).sub(web3.utils.toBN(amountsIn1[0]));

             // borrow WBNB from pancakeswap and sell it on
             // bakeryswap. Repay in DAI. Keep the profit in DAI
            const AMOUNT_WBNB_WEI = await PancakeSwap
                .methods
                .getAmountsOut(
                    AMOUNT_DAI_WEI,
                    [addresses.tokens.DAI, addresses.tokens.WBNB]
                ).call();

             
            const [amountsIn2, amountsOut2] = await Promise.all([            
              PancakeSwap
                .methods
                .getAmountsIn(
                    AMOUNT_WBNB_WEI[1],
                    [addresses.tokens.DAI, addresses.tokens.WBNB]
                ).call(),
              BakerySwap
                .methods
                .getAmountsOut(
                    AMOUNT_WBNB_WEI[1],
                    [addresses.tokens.WBNB, addresses.tokens.DAI]
                ).call()
            ]);

            const profit_in_DAI = web3.utils.toBN(amountsOut2[1]).sub(web3.utils.toBN(amountsIn2[0]));

            // arbitrage borrowing DAI
            if (profit_in_WBNB > 0) { 

                const tx = BscFlashArb1.methods.startArbitrage(
                  addresses.tokens.DAI,
                  addresses.tokens.WBNB,
                  AMOUNT_DAI_WEI,
                  0
                );

                const [gasPrice, gasCost] = await Promise.all([
                    web3.eth.getGasPrice(),
                    tx.estimateGas({from: admin})
                ]);

                const gas =  web3.utils.toBN(gasCost).add(
                    web3.utils.toBN(gasCost).div(web3.utils.toBN('20'))
                );

                const txCost = gas.mul(web3.utils.toBN(gasPrice));
                const profit = profit_in_WBNB.sub(txCost);

                if(profit.gte(txCost)) {

                    console.log('Arb opportunity found. Borrow DAI. Repay in WBNB!');
                    console.log(`Expected profit: ${web3.utils.fromWei(profit)} Dai`);

                    const data = tx.encodeABI();
                          const txData = {
                            from: admin,
                            to: addresses.bscFlashArb1.addr,
                            data,
                            gas,
                            gasPrice
                    };

                    const receipt = await web3.eth.sendTransaction(txData);
                    console.log(`Transaction hash: ${receipt.transactionHash}`);
                }
            }

            // arbitrage borrowing WBNB
            if (profit_in_DAI > 0) {

                const tx = BscFlashArb1.methods.startArbitrage(
                  addresses.tokens.DAI,
                  addresses.tokens.WBNB,
                  0,
                  AMOUNT_WBNB_WEI
                );

                const [gasPrice, gasCost] = await Promise.all([
                    web3.eth.getGasPrice(),
                    tx.estimateGas({from: admin})
                ]);

                const gas =  web3.utils.toBN(gasCost).add(
                    web3.utils.toBN(gasCost).div(web3.utils.toBN('20'))
                );

                const txCost = gas.mul(web3.utils.toBN(gasPrice));
                const txCost_in_Dai = web3.utils.toBN(amountsOut2[1]).mul(txCost).div(AMOUNT_WBNB_WEI[1]);
                const profit = profit_in_DAI.sub(txCost_in_Dai);

                if(profit.gte(web3.utils.toBN('0'))) {

                    console.log('Arb opportunity found. Borrow WBNB. Repay in DAI!');
                    console.log(`Expected profit: ${web3.utils.fromWei(profit)} Dai`);

                    const data = tx.encodeABI();
                          const txData = {
                            from: admin,
                            to: addresses.bscFlashArb1.addr,
                            data,
                            gas,
                            gasPrice
                    };

                    const receipt = await web3.eth.sendTransaction(txData);
                    console.log(`Transaction hash: ${receipt.transactionHash}`);
                }

            }

            // console.log('running...')
        } catch (error) {
            console.error(error);
        }
    })
    .on('error', error => {
        console.log(error);
    });

}
init();

I noticed that most of time the app runs well. It crashes only when there is an arbitrage opportunity (when the code in one of the main if statments runs). I can’t figure out why It happens.
I made some research about draining connections. AWS uses it a lot. If the moralis servers are hosted on AWS, maybe this errore comes frome AWS servers configurations.

from what I know DRAINING CONNECTION error should happen when the node that you are connecting to will go offline

you mean that the error comes when you try to send a transaction?

or you can not even connect to web socket at that time?

‘Whole script’ instead of “hole script”

I lose the connection at that time. It disconnects.

It happens even before I try to send the transaction. i.e., when I try to estimate the gas price and the gas cost.

ok, can you try to estimate the gas price and gas cost separately to see if it works without problems?

I tried and I got the following error:

Error: Returned error: execution reverted: Unauthorized

here is the full log:

Error: Returned error: execution reverted: Unauthorized
    at Object.ErrorResponse (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/web3-core-helpers/lib/errors.js:28:19)
    at Object.callback (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/web3-core-requestmanager/lib/index.js:302:36)
    at /home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/web3-providers-ws/lib/index.js:114:45
    at Array.forEach (<anonymous>)
    at WebsocketProvider._onMessage (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/web3-providers-ws/lib/index.js:102:69)
    at W3CWebSocket._dispatchEvent [as dispatchEvent] (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/yaeti/lib/EventTarget.js:115:12)
    at W3CWebSocket.onMessage (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/websocket/lib/W3CWebSocket.js:234:14)
    at WebSocketConnection.<anonymous> (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/websocket/lib/W3CWebSocket.js:205:19)
    at WebSocketConnection.emit (events.js:400:28)
    at WebSocketConnection.processFrame (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/websocket/lib/WebSocketConnection.js:554:26)
    at /home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/websocket/lib/WebSocketConnection.js:323:40
    at processTicksAndRejections (internal/process/task_queues.js:77:11) {
  data: '0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c556e617574686f72697a65640000000000000000000000000000000000000000'
}

I was able to run eth_estimateGas call for test now with different parameters, what function did you call there in particular?

In my script, I’m not using moralis SDK. I’m using just the web soket to connect the bsc.
Here is the lines I used now to estimate gas price and gas cost, separately:

const tx = BscFlashArb1.methods.startArbitrage(
                  addresses.tokens.DAI,
                  addresses.tokens.WBNB,
                  AMOUNT_DAI_WEI,
                  0
                );

                const gasPrice = await web3.eth.getGasPrice();

                const gasCost = await tx.estimateGas({from: admin});

                console.log(`gas price: ${gasPrice}, gas cost: ${gasCost}`);

this is on a lower level than what you have there, it is not Moralis SDK :slight_smile:

on what line it fails?
web3.eth.getGasPrice() or tx.estimateGas ?

It estimates gas price correctly.
It fails to estimate the gas cost and returns an error: Error: Returned error: execution reverted: Unauthorized

what kind of web socket url are you using? archive, non archive?
that Unauthorized error sounds like it is trying to run a node command that is not on a whitelist of supported commands

I’m using a non archive node.

and you are doing this on bsc, right?
if you use process.env.BSC_WSS_URL for gas estimation then it works?

I tried it now: same error! :open_mouth:
I really didn’t expect that.
I will try to make a transaction to see the actual gas cost. Then I will increase it by some percentage and hard code it in the script to see what will happen.
Thank you for your help. I’m very grateful.

in the script I made a mistake. in the ```
// arbitrage borrowing WBNB

AMOUNT_WBNB_WEI is an array. the wright value is AMOUNT_WBNB_WEI[1]

also having the same issue here, let me know if you find out the solution

thanks

I found out that the issue depends on BSC. No matter which wss you are using you will always have that issue.
In the binance chain (not binance smart chain but binance chain) documentation there is some thing similar. When you are connected to binance chain via wss, you will be disconnected after 30 minutes. If you want to maintain the connection you have to include in your code a line of code they provided, to ask every 30 minutes to maintain the connection.
I guess, they imported this future or issue into BSC.
The solution I found is to create a reset function which will reconnect when the connection fails.

2 Likes

can you share with me this reset function? thank you

1 Like

can you please share us the line of code and where to place it on the flashloan arbitrage script

`require(“dotenv”).config();
const Web3 = require(“web3”);
const abis = require("./abis");
const { mainnet: addresses } = require("./addresses");
// const { testnet: addresses } = require("./addresses"); added for testing on testnet
const Flashloan = require("./build/contracts/FlashSwap.json");

const web3 = new Web3(
new Web3.providers.WebsocketProvider(process.env.WSS_URL)
);

const provider = new Web3.providers.WebsocketProvider(process.env.WSS_URL);
provider.on(‘error’, e => console.error(‘WSS Error’, e));
provider.on(‘end’, e => console.error(‘WSS End’, e));

const { address: admin } = web3.eth.accounts.wallet.add(
process.env.PRIVATE_KEY
);

const flashloanBUSD = “50000”;
const flashloanWBNB = “500”;
const amountInBUSD = web3.utils.toBN(web3.utils.toWei(flashloanBUSD));
const amountInWBNB = web3.utils.toBN(web3.utils.toWei(flashloanWBNB));

const ApeSwap = new web3.eth.Contract(
abis.apeSwap.router,
addresses.apeSwap.router
);

const PancakeSwap = new web3.eth.Contract(
abis.pancakeSwap.router,
addresses.pancakeSwap.router
);

const init = async () => {
const networkId = await web3.eth.net.getId();
const flashloan = new web3.eth.Contract(
Flashloan.abi,
Flashloan.networks[networkId].address
);

web3.eth
.subscribe(“newBlockHeaders”)
.on(“data”, async (block) => {
console.log(New block received. Block # ${block.number});

  const amountsOut1 = await ApeSwap.methods
  .getAmountsIn(amountInBUSD, [
    addresses.tokens.WBNB,
    addresses.tokens.BUSD,
  ])
  .call();
const amountsOut2 = await ApeSwap.methods
  .getAmountsOut(amountInBUSD, [
    addresses.tokens.BUSD,
    addresses.tokens.WBNB,
  ])
  .call();

const amountsOut3 = await PancakeSwap.methods
  .getAmountsIn(amountInBUSD, [
    addresses.tokens.WBNB,
    addresses.tokens.BUSD,
  ])
  .call();
const amountsOut4 = await PancakeSwap.methods
  .getAmountsOut(amountInBUSD, [
    addresses.tokens.BUSD,
    addresses.tokens.WBNB,
  ])
  .call();

const amountsOut5 = await ApeSwap.methods
  .getAmountsIn(amountInWBNB, [
    addresses.tokens.BUSD,
    addresses.tokens.WBNB,
  ])
  .call();
const amountsOut6 = await ApeSwap.methods
  .getAmountsOut(amountInWBNB, [
    addresses.tokens.WBNB,
    addresses.tokens.BUSD,
  ])
  .call();

const amountsOut7 = await PancakeSwap.methods
  .getAmountsIn(amountInWBNB, [
    addresses.tokens.BUSD,
    addresses.tokens.WBNB,
  ])
  .call();
const amountsOut8 = await PancakeSwap.methods
  .getAmountsOut(amountInWBNB, [
    addresses.tokens.WBNB,
    addresses.tokens.BUSD,
  ])
  .call();

const aperesults = {
  buy: amountsOut1[0] / 10 ** 18,
  sell: amountsOut2[1] / 10 ** 18,
};
const aperesults2 = {
  buy: amountsOut5[0] / 10 ** 18,
  sell: amountsOut6[1] / 10 ** 18,
};

const pancakeresults = {
  buy: amountsOut3[0] / 10 ** 18,
  sell: amountsOut4[1] / 10 ** 18,
};
const pancakeresults2 = {
  buy: amountsOut7[0] / 10 ** 18,
  sell: amountsOut8[1] / 10 ** 18,
};

console.log(`ApeSwap ${flashloanBUSD} BUSD/WBNB `);
console.log(aperesults);

console.log(`PancakeSwap ${flashloanBUSD} BUSD/WBNB`);
console.log(pancakeresults);

console.log(`ApeSwap ${flashloanWBNB} WBNB/BUSD`);
console.log(aperesults2);

console.log(`PancakeSwap${flashloanWBNB} WBNB/BUSD `);
console.log(pancakeresults2);

  //Payback fee calc

  const pancakeBnbPrice =
    (pancakeresults.buy + pancakeresults.sell) / flashloanWBNB / 2;
  const apeswapBnbPrice =
    (aperesults.buy + aperesults.sell) / flashloanWBNB / 2;

  let pancakePaybackCalcBusd = (pancakeresults.buy / 0.997) * 10 ** 18;
  let apeswapPaybackCalcBusd = (aperesults.buy / 0.997) * 10 ** 18;
  let apePaybackCalcWbnb = (aperesults2.buy / 0.997) * 10 ** 18;
  let pancakePaybackCalcWbnb = (pancakeresults2.buy / 0.997) * 10 ** 18;

  let repayBusdPancakeFee =
    pancakePaybackCalcBusd / 10 ** 18 - pancakeresults.buy;
  let repayBusdApeswapFee =
    apeswapPaybackCalcBusd / 10 ** 18 - aperesults.buy;
  let repayWbnbPancakeFee =
    (pancakePaybackCalcWbnb / 10 ** 18 - pancakeresults2.buy) *
    pancakeBnbPrice;
  let repayWbnbApeswapFee =
    (apePaybackCalcWbnb / 10 ** 18 - aperesults2.buy) * apeswapBnbPrice;

  const gasPrice = await web3.eth.getGasPrice();
  const txCost =
    ((330000 * parseInt(gasPrice)) / 10 ** 18) * pancakeBnbPrice;

  //Profit Calc
  const profit1 =
    aperesults.sell - pancakeresults.buy - txCost - repayBusdApeswapFee;
  const profit2 =
    pancakeresults.sell - aperesults.buy - txCost - repayBusdPancakeFee;
  const profit3 =
    pancakeresults2.sell - aperesults2.buy - txCost - repayWbnbPancakeFee;
  const profit4 =
    aperesults2.sell - pancakeresults2.buy - txCost - repayWbnbApeswapFee;

  if (profit1 > 0 && profit1 > profit2) {
    console.log("Arb opportunity found!");
    console.log(`Flashloan WBNB on Apeswap at ${aperesults.buy} `);
    console.log(`Sell WBNB on PancakeSwap at ${pancakeresults.sell} `);
    console.log(`Expected cost of flashswap: ${repayBusdPancakeFee}`);
    console.log(`Expected Gas cost: ${txCost}`);
    console.log(`Expected profit: ${profit1} BUSD`);

    let tx = flashloan.methods.startArbitrage(
      addresses.tokens.WBNB, //token1
      addresses.tokens.BUSD, //token2
      amountInWBNB.toString(), //amount0
      0, //amount1
      addresses.apeSwap.factory, //apefactory
      addresses.pancakeSwap.router, //pancakerouter
      pancakePaybackCalcBusd.toString()
    );

    const data = tx.encodeABI();
    const txData = {
      from: admin,
      to: flashloan.options.address,
      data,
      gas: "330000",
      gasPrice: gasPrice,
    };
    const receipt = await web3.eth.sendTransaction(txData);
    console.log(`Transaction hash: ${receipt.transactionHash}`);
  }

  if (profit2 > 0 && profit2 > profit1) {
    console.log("Arb opportunity found!");
    console.log(`Buy WBNB from PancakeSwap at ${pancakeresults.buy} `);
    console.log(`Sell WBNB from ApeSwap at ${aperesults.sell}`);
    console.log(`Expected cost of flashswap: ${repayBusdApeswapFee}`);
    console.log(`Expected Gas cost: ${txCost}`);
    console.log(`Expected profit: ${profit2} BUSD`);

    let tx = flashloan.methods.startArbitrage(
      addresses.tokens.WBNB, //token1
      addresses.tokens.BUSD, //token2
      amountInWBNB.toString(), //amount0
      0, //amount1
      addresses.pancakeSwap.factory, //pancakefactory
      addresses.apeSwap.router, // aperouter
      apeswapPaybackCalcBusd.toString()
    );

    const data = tx.encodeABI();
    const txData = {
      from: admin,
      to: flashloan.options.address,
      data,
      gas: "330000",
      gasPrice: gasPrice,
    };
    const receipt = await web3.eth.sendTransaction(txData);
    console.log(`Transaction hash: ${receipt.transactionHash}`);
  }

  if (profit3 > 0 && profit3 > profit4) {
    console.log("Arb opportunity found!");
    console.log(`Flashloan BUSD on Apeswap at ${aperesults2.buy} `);
    console.log(`Sell BUSD on PancakeSwap at ${pancakeresults2.sell} `);
    console.log(`Expected cost of flashswap: ${repayWbnbApeswapFee}`);
    console.log(`Expected Gas cost: ${txCost}`);
    console.log(`Expected profit: ${profit3} WBNB`);

    let tx = flashloan.methods.startArbitrage(
      addresses.tokens.BUSD, //token1
      addresses.tokens.WBNB, //token2
      0, //amount0
      amountInBUSD.toString(), //amount1
      addresses.apeSwap.factory, //apefactory
      addresses.pancakeSwap.router, //pancakerouter
      apePaybackCalcWbnb.toString()
    );

    const data = tx.encodeABI();
    const txData = {
      from: admin,
      to: flashloan.options.address,
      data,
      gas: "330000",
      gasPrice: gasPrice,
    };
    const receipt = await web3.eth.sendTransaction(txData);
    console.log(`Transaction hash: ${receipt.transactionHash}`);
  }

  if (profit4 > 0 && profit4 > profit3) {
    console.log("Arb opportunity found!");
    console.log(`Flashloan BUSD on PancakeSwap at ${pancakeresults2.buy} `);
    console.log(`Sell BUSD on  at Apeswap ${aperesults2.sell} `);
    console.log(`Expected cost of flashswap: ${repayWbnbPancakeFee}`);
    console.log(`Expected Gas cost: ${txCost}`);
    console.log(`Expected profit: ${profit4} WBNB`);

    let tx = flashloan.methods.startArbitrage(
      //token1
      addresses.tokens.WBNB,
      addresses.tokens.BUSD, //token2
      0, //amount0
      amountInBUSD.toString(), //amount1
      addresses.pancakeSwap.factory, //pancakeFactory
      addresses.apeSwap.router, //apeRouter
      pancakePaybackCalcWbnb.toString()
    );

    const data = tx.encodeABI();
    const txData = {
      from: admin,
      to: flashloan.options.address,
      data,
      gas: "330000",
      gasPrice: gasPrice,
    };
    const receipt = await web3.eth.sendTransaction(txData);
    console.log(`Transaction hash: ${receipt.transactionHash}`);
  }
})
.on("error", (error) => {
  console.log(error);
});

};
init();`