title: Error: call revert exception (Flashloan with dydx, Uniswap and Kyber)
body: <p>So I am trying to set up an Ethereum <a href="https://github.com/jklepatch/eattheblocks/tree/master/profitable-flashloans/30-make-arbitrage-script-run-247" rel="nofollow noreferrer">flashloan script</a> on the Kovan test network, partly because of the great amount of funds needed to execute it on Mainnet.</p>
  <p>I have therefore found all the Kovan addresses of the services used (dydx, kyber, the tokens to be exchanged etc.) and made a new key called ‘kovan’ with those addresses within the ‘addresses’ folder.</p>
  <p>I then finally succeeded in deploying the contract on Kovan. And the websocket interaction of getting and displaying the blocks also works.</p>
  <p>I expect it to be error-free while waiting for a transaction to go through. But every time it receives a new block, it gives me an error saying:</p>
  <pre><code>UnhandledPromiseRejectionWarning: Error: call revert exception (method=&quot;decimals()&quot;, errorSignature=null, errorArgs=[null], reason=null, code=CALL_EXCEPTION, version=abi/5.0.1)
  </code></pre>
  <p>This is the whole console log:</p>
  <pre><code>λ node run-arbitrage.js
  {
    kyber: { kyberNetworkProxy: '0x692f391bCc85cefCe8C237C01e1f636BbD70EA4D' },
    uniswap: { router: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D' },
    dydx: { solo: '0x4EC3570cADaAEE08Ae384779B0f3A45EF85289DE' },
    tokens: {
      dai: '0xc4375b7de8af5a38a93548eb8453a498222c4ff2',
      usdc: '0xdcfab8057d08634279f8201b55d311c2a67897d2',
      weth: '0xd0a1e359811322d97991e03f863a0c30c2cf029c'
    }
  }
  web3-shh package will be deprecated in version 1.3.5 and will no longer be supported.
  web3-bzz package will be deprecated in version 1.3.5 and will no longer be supported.
  New block received. Block # 24267204
  (node:20188) UnhandledPromiseRejectionWarning: Error: call revert exception (method=&quot;decimals()&quot;, errorSignature=null, errorArgs=[null], reason=null, code=CALL_EXCEPTION, version=abi/5.0.1)
      at Logger.makeError (C:\Users\Frederik\Rod\m3\node_modules\@ethersproject\logger\lib\index.js:179:21)
      at Logger.throwError (C:\Users\Frederik\Rod\m3\node_modules\@ethersproject\logger\lib\index.js:188:20)
      at Interface.decodeFunctionResult (C:\Users\Frederik\Rod\m3\node_modules\@ethersproject\contracts\node_modules\@ethersproject\abi\lib\interface.js:286:23)
      at Contract.&lt;anonymous&gt; (C:\Users\Frederik\Rod\m3\node_modules\@ethersproject\contracts\lib\index.js:300:56)
      at step (C:\Users\Frederik\Rod\m3\node_modules\@ethersproject\contracts\lib\index.js:46:23)
      at Object.next (C:\Users\Frederik\Rod\m3\node_modules\@ethersproject\contracts\lib\index.js:27:53)
      at fulfilled (C:\Users\Frederik\Rod\m3\node_modules\@ethersproject\contracts\lib\index.js:18:58)
      at processTicksAndRejections (internal/process/task_queues.js:97:5)
  (node:20188) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
  (node:20188) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
  </code></pre>
  <p>And this is my run-arbitrage.js file:</p>
  <pre><code>require(&quot;dotenv&quot;).config()
  const Web3 = require('web3');
  const { ChainId, Token, TokenAmount, Pair } = require('@uniswap/sdk');
  const abis = require('./abis');
  const { kovan: addresses } = require('./addresses');
  console.log(addresses)
  const Flashloan = require('./build/contracts/Flashloan.json');
  
  const web3 = new Web3(
    new Web3.providers.WebsocketProvider(process.env.INFURA_KOVAN_URL)
  );
  const { address: admin } = web3.eth.accounts.wallet.add(process.env.PRIVATE_KEY);
  
  const kyber = new web3.eth.Contract(
    abis.kyber.kyberNetworkProxy,
    addresses.kyber.kyberNetworkProxy
  );
  
  const ONE_WEI = web3.utils.toBN(web3.utils.toWei('1'));
  const AMOUNT_DAI_WEI = web3.utils.toBN(web3.utils.toWei('20000'));
  const DIRECTION = {
    KYBER_TO_UNISWAP: 0,
    UNISWAP_TO_KYBER: 1
  };
  
  const init = async () =&gt; {
    const networkId = await web3.eth.net.getId();
    const flashloan = new web3.eth.Contract(
      Flashloan.abi,
      Flashloan.networks[networkId].address
    );
    
    let ethPrice;
    const updateEthPrice = async () =&gt; {
      const results = await kyber
        .methods
        .getExpectedRate(
          '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 
          addresses.tokens.dai, 
          1
        )
        .call();
      ethPrice = web3.utils.toBN('1').mul(web3.utils.toBN(results.expectedRate)).div(ONE_WEI);
    }
    await updateEthPrice();
    setInterval(updateEthPrice, 15000);
  
    web3.eth.subscribe('newBlockHeaders')
      .on('data', async block =&gt; {
        console.log(`New block received. Block # ${block.number}`);
  
        const [dai, weth] = await Promise.all(
          [addresses.tokens.dai, addresses.tokens.weth].map(tokenAddress =&gt; (
            Token.fetchData(
              ChainId.MAINNET,
              tokenAddress,
            )
        )));
        const daiWeth = await Pair.fetchData(
          dai,
          weth,
        );
  
        const amountsEth = await Promise.all([
          kyber
            .methods
            .getExpectedRate(
              addresses.tokens.dai, 
              '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 
              AMOUNT_DAI_WEI
            ) 
            .call(),
          daiWeth.getOutputAmount(new TokenAmount(dai, AMOUNT_DAI_WEI)),
        ]);
        const ethFromKyber = AMOUNT_DAI_WEI.mul(web3.utils.toBN(amountsEth[0].expectedRate)).div(ONE_WEI);
        const ethFromUniswap = web3.utils.toBN(amountsEth[1][0].raw.toString());
  
        const amountsDai = await Promise.all([
          kyber
            .methods
            .getExpectedRate(
              '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', 
              addresses.tokens.dai, 
              ethFromUniswap.toString()
            ) 
            .call(),
          daiWeth.getOutputAmount(new TokenAmount(weth, ethFromKyber.toString())),
        ]);
        const daiFromKyber = ethFromUniswap.mul(web3.utils.toBN(amountsDai[0].expectedRate)).div(ONE_WEI);
        const daiFromUniswap = web3.utils.toBN(amountsDai[1][0].raw.toString());
  
        console.log(`Kyber -&gt; Uniswap. Dai input / output: ${web3.utils.fromWei(AMOUNT_DAI_WEI.toString())} / ${web3.utils.fromWei(daiFromUniswap.toString())}`);
        console.log(`Uniswap -&gt; Kyber. Dai input / output: ${web3.utils.fromWei(AMOUNT_DAI_WEI.toString())} / ${web3.utils.fromWei(daiFromKyber.toString())}`);
  
        if(daiFromUniswap.gt(AMOUNT_DAI_WEI)) {
          const tx = flashloan.methods.initiateFlashloan(
            addresses.dydx.solo, 
            addresses.tokens.dai, 
            AMOUNT_DAI_WEI,
            DIRECTION.KYBER_TO_UNISWAP
          );
          const [gasPrice, gasCost] = await Promise.all([
            web3.eth.getGasPrice(),
            tx.estimateGas({from: admin}),
          ]);
  
          const txCost = web3.utils.toBN(gasCost).mul(web3.utils.toBN(gasPrice)).mul(ethPrice);
          const profit = daiFromUniswap.sub(AMOUNT_DAI_WEI).sub(txCost);
  
          if(profit &gt; 0) {
            console.log('Arb opportunity found Kyber -&gt; Uniswap!');
            console.log(`Expected profit: ${web3.utils.fromWei(profit)} Dai`);
            const data = tx.encodeABI();
            const txData = {
              from: admin,
              to: flashloan.options.address,
              data,
              gas: gasCost,
              gasPrice
            };
            const receipt = await web3.eth.sendTransaction(txData);
            console.log(`Transaction hash: ${receipt.transactionHash}`);
          }
        }
  
        if(daiFromKyber.gt(AMOUNT_DAI_WEI)) {
          const tx = flashloan.methods.initiateFlashloan(
            addresses.dydx.solo, 
            addresses.tokens.dai, 
            AMOUNT_DAI_WEI,
            DIRECTION.UNISWAP_TO_KYBER
          );
          const [gasPrice, gasCost] = await Promise.all([
            web3.eth.getGasPrice(),
            tx.estimateGas({from: admin}),
          ]);
          const txCost = web3.utils.toBN(gasCost).mul(web3.utils.toBN(gasPrice)).mul(ethPrice);
          const profit = daiFromKyber.sub(AMOUNT_DAI_WEI).sub(txCost);
  
          if(profit &gt; 0) {
            console.log('Arb opportunity found Uniswap -&gt; Kyber!');
            console.log(`Expected profit: ${web3.utils.fromWei(profit)} Dai`);
            const data = tx.encodeABI();
            const txData = {
              from: admin,
              to: flashloan.options.address,
              data,
              gas: gasCost,
              gasPrice
            };
            const receipt = await web3.eth.sendTransaction(txData);
            console.log(`Transaction hash: ${receipt.transactionHash}`);
          }
        }
      })
      .on('error', error =&gt; {
        console.log(error);
      });
  }
  init();
  </code></pre>