1

I am using web3.js v1 in order to sign and send transactions:

async function signAndSend(transaction) {
    let options = {
        to  : transaction._parent._address,
        data: transaction.encodeABI(),
        gas : SOME_GAS_AMOUNT
    };
    let signedTransaction = await web3.eth.accounts.signTransaction(options, PRIVATE_KEY);
    return await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction);
}

In order to compute how many gas units were used, I do:

let gasPrice = new BigNumber(await web3.eth.getGasPrice());
let bgnBalance = new BigNumber(await web3.eth.getBalance(PUBLIC_KEY));
await signAndSend(myTransaction);
let endBalance = new BigNumber(await web3.eth.getBalance(PRIVATE_KEY));
console.log(`Total cost: ${bgnBalance.minus(endBalance).div(gasPrice)} gas units`);

I observe the following:

  • When SOME_GAS_AMOUNT is too low, I get base fee exceeds gas limit
  • When SOME_GAS_AMOUNT is high enough, I always get the same total cost

My conclusion is, just use a large enough (hard-coded) value.

Am I right?

If yes, then what's the point in this parameter to begin with?

The docs for function signTransaction say:

gas - String: The gas provided by the transaction.

What does "gas provided by the transaction" even mean? I thought that I was the one providing gas for the transaction to take place!

By the way, initially, I used to set the gas parameter as follows:

gas: await transaction.estimateGas({from: PUBLIC_KEY});

However, this occasionally gave me the base fee exceeds gas limit error.

So I figured I was kind of on the wrong track with that one.

In short, any clarifications on the gas parameter would be highly appreciated.

Thank you very much for you help!

UPDATE:

I am not asking about the meaning of the term "gas".

Please refer to my observation (quoting from above):

I observe the following:

  • When SOME_GAS_AMOUNT is too low, I get base fee exceeds gas limit
  • When SOME_GAS_AMOUNT is high enough, I always get the same total cost

My conclusion is, just use a large enough (hard-coded) value.

Am I right?

If yes, then what's the point in this parameter to begin with?

If no, what exactly should I set this parameter to?

I initially used to set the gas parameter as follows:

gas: await transaction.estimateGas({from: PUBLIC_KEY});

However, this occasionally gave me the base fee exceeds gas limit error.

So I figured I was kind of on the wrong track with that one.

goodvibration
  • 26,003
  • 5
  • 46
  • 86
  • @smarx: Your proposed duplicate does not answer my inline questions. Moreover, it states something opposite to my observation: "If you set a very high gas price, you will end up paying lots of ether for only a few operations". Here, I explicitly stated that I see the same total cost no matter how high I set the gas parameter. I would be happy(ier) if you could refer to the specific doubts expressed in my question. I am not asking about the general meaning of the term "gas". Thank you. – goodvibration Aug 16 '18 at 12:53
  • When code asserts or executes some other invalid opcode, all remaining gas is consumed. So if you set the gas limit too high, you're losing more ether. Your call to estimateGas doesn't have the right transaction details. (E.g. it's missing the to and data fields.) – user19510 Aug 16 '18 at 12:59
  • @smarx: So you reckon fixing my call to estimateGas will solve the base fee exceeds gas limit error??? – goodvibration Aug 16 '18 at 13:01
  • You also have to have enough ether to cover gasLimit * gasPrice, even if you end up not needing to use all that gas. There's also a block gas limit, and miners may not attempt to run your transaction if it looks like it could exceed the limit for the block. So just using a really big number isn't a great strategy, though for transactions you know will exceed, aiming just a little high is usually fine. – user19510 Aug 16 '18 at 13:01
  • When you use multiple question marks like that, it looks (to me) like you're yelling. One question mark is sufficient to indicate a question. And yes, if you fix your estimateGas call, you should get the correct gas estimate, which will let you pass the right gasLimit. – user19510 Aug 16 '18 at 13:02
  • @smarx: Awesome, thanks, I will give it a try (was using the multiple question marks as an expression of surprise, not yelling). – goodvibration Aug 16 '18 at 13:50
  • @smarx: I'm looking at the docs for function estimateGas, and I see no such parameters to and data. There are from (which I pass in my code), gas and value. Can you please explain your suggestion? – goodvibration Aug 16 '18 at 14:46
  • Sorry, I guess I don't know what transaction is? Based on the documentation you pointed to, I assume you're using web3.js 1.0-beta, and transaction is the result of passing some arguments to a method on your contract (but before calling send on it). E.g. contract.methods.foo(bar, baz).estimateGas({ from: ... })? I was assuming you were just calling eth_estimateGas, which requires the full transaction details, but I think I was mistaken. – user19510 Aug 16 '18 at 14:52
  • If my assumption above is correct, then your call to estimateGas() looks good to me. If that's returning an amount that's too low, you might consider that the gas cost of the transaction has changed between when you estimated the cost and when you sent the transaction, or perhaps it's dependent on the sender of the transaction and your from in the estimateGas() call doesn't match that. It's impossible to debug further without knowing the details of the transaction (and the contract source code if it's not on mainnet), the return value of estimateGas(), etc. – user19510 Aug 16 '18 at 14:55
  • @smarx: No, transaction here (as shown in the code at the top of my question) is the "promise" returns from calling a contract method via web3 (referring to you previous comment). – goodvibration Aug 16 '18 at 14:56
  • @smarx: I don't see how the cost has changed, because I (used to) call estimateGas right before calling signTransaction and sendSignedTransaction (as shown at the top of my question). Will it help if I publish an MVP of the contract + web3 code in a separate question? – goodvibration Aug 16 '18 at 14:59
  • A Promise doesn't have a method called estimateGas(), so I don't think that's correct. It doesn't matter how quickly you call sendSignedTransaction() after estimateGas(). A transaction that is mined before yours (even earlier in the same block) can change the state of the contract. – user19510 Aug 16 '18 at 15:01
  • Yes, sharing your code would help. – user19510 Aug 16 '18 at 15:01
  • @smarx: Calling myContract.methods.func() returns a promise. I use this as the transaction in my code above. I will shortly post a base fee exceeds gas limit question. Thank you. – goodvibration Aug 16 '18 at 15:13
  • "myContract.methods.func() returns a promise." Citation needed. :-) (If you think it's a Promise, try calling .then() on it.) – user19510 Aug 16 '18 at 15:19
  • @smarx: Posted the question here. – goodvibration Aug 16 '18 at 15:28
  • @smarx: And here is your citation in the docs. Of course, I was slightly inaccurate (or wrong) calling it "a promise", as you get a promise only when you invoke transaction.call or transaction.send. But that's not my main issue here anyway, and I'd be happy if you could take a look at my other question. Thank you. – goodvibration Aug 16 '18 at 15:30
  • That's the documentation for myContract.methods.func().call(), which does return a Promise. EDIT Correct. (Just got your edit.) – user19510 Aug 16 '18 at 15:32
  • @smarx: Yes, I just extended my previous comment to mention that. – goodvibration Aug 16 '18 at 15:33

0 Answers0