[Ethereum] ethers gasLimit gasPrice

bscethers.jsjavascriptuniswap

I am a noob.. I am trying to set gasPrice and gasLimit since I am getting a gas estimation error.

I just don't understand where/how to insert it into the transaction. This is on the BSC network.

Error message:

ERROR:
reason: 'cannot estimate gas; transaction may fail or may require manual gas limit',
    code: 'UNPREDICTABLE_GAS_LIMIT',
    error: Error: gas required exceeds allowance (3807079) or always failing transaction 
  const tx = await router.swapExactTokensForTokens(
    amountIn,
    amountOutMin,
    [tokenIn, tokenOut],
    addresses.recipient,
    Date.now() + 1000 * 60 * 3 //3 minutes
  );
  const receipt = await tx.wait(); 
  console.log('Transaction receipt');
  console.log(receipt);

Best Answer

Let's break this into two parts, with the caveat that you should look at the second before doing anything about the first.

Setting the gasLimit and gasPrice in Ethers

Here's the relevant part in the docs, but let's explain it. Whenever you make a transaction through Ethers, you can set overrides in an object after your arguments. In this case, this is your original contract call:

const tx = await router.swapExactTokensForTokens(
    amountIn,
    amountOutMin,
    [tokenIn, tokenOut],
    addresses.recipient,
    Date.now() + 1000 * 60 * 3 //3 minutes
  );

So if you wanted to set a gasPrice of 100 and a gasLimit of 9M, you'd put:

const tx = await router.swapExactTokensForTokens(
    amountIn,
    amountOutMin,
    [tokenIn, tokenOut],
    addresses.recipient,
    Date.now() + 1000 * 60 * 3, //3 minutes
    {
        gasPrice: 100,
        gasLimit: 9000000
    }
  );

and that's it!

Note: there is no reason to set a high gasPrice in this case. The problem here is that there either isn't enough gas or an internal error, not that you aren't paying enough for gas. In general, though only in general, low gas prices won't make your transactions fail, just make them take a long time to get mined. gasLimit is what regulates how much gas you can spend, so increasing it can theoretically help (though probably not in this case, see below).

Digging into the error

But before you run off to set a high gasLimit, let's look at that error:

ERROR:
reason: 'cannot estimate gas; transaction may fail or may require manual gas limit',
    code: 'UNPREDICTABLE_GAS_LIMIT',
    error: Error: gas required exceeds allowance (3807079) or always failing transaction 

the error lists two possible causes:

  1. the gas limit is too low (gas required exceeds allowance)
  2. there is an error (always failing transaction)

You get how to fix the first, but how do you know if it's the first or the second? There is a hint here - the estimator tells you what it set the gasLimit at: 3807079. Taking a quick look at GasNow it looks like Uniswap v2 (which is the basis for the code for the exchange on BSC that you're using) is ~34.5K gas. This is a hint that something else is wrong.

It's worth spelling this out because the state of accurate error messages is not so developed currently, so you can run into errors like this a lot, and it's good to know how to look at them and get clues.

So the gas hints at another error. Looking at the code you supplied, and comparing it to code in the Uniswap docs (I used a snippet on this page for reference), it looks like there's one big difference between their code and yours in the deadline parameter. Your code:

Date.now() + 1000 * 60 * 3, //3 minutes

Theirs:

Math.floor(Date.now() / 1000) + 60 * 20 // 20 minutes from the current Unix time

The big difference is that they're using Math.floor() to ensure they don't have any decimals. You are most likely putting a float as the deadline arg, and there is a good chance that it's causing things to fail. (They also divide by 1000 as opposed to adding it, which means that your amount isn't 3 minutes like you thought - Date.now returns the time in milliseconds (Source.) Try wrapping that line in Math.floor (and dividing by 1000 instead adding).

Hope that helps!

Related Topic