I'd like to estimate the gas of a simple ERC20 transfer between two addresses. The web3.js docs on estimateGas are admittedly confusing:

// using the callback
myContract.methods.myMethod(123).estimateGas({gas: 5000000}, function(error, gasAmount){
    if(gasAmount == 5000000)
        console.log('Method ran out of gas');

The myMethod(123) is what I find confusing. What is that for? The following is what I'm currently thinking, but I'm getting TypeError: contract.methods.send is not a function. What should I substitute for myMethod(123)?

   .estimateGas({ gas: 60000 }, (error, gasAmount) => {
      return gasAmount;

const obj = myContract.methods.myMethod(123);

The variable obj is an object in your client-side script which represents a function-call.

In this specific example, it is the function-call myMethod(123) on contract myContract.

You can use this object for any of the following:

  1. obj.encodeABI()
  2. obj.call(options)
  3. obj.send(options)
  4. obj.estimateGas(options)

Where options is an object with any combination of the following fields:

  • from
  • gas
  • gasPrice
  • value

If the function does not change the state of the contract (i.e., it is either pure or view), then call is pretty much the only thing that you want to do with it, for example:

const retVal = await obj.call({from: x});

If the function does change the state of the contract (i.e., it is neither pure nor view), then all the others (encodeABI, estimateGas and send) are useful, for example:

const encodedData = obj.encodeABI();
const requiredGas = await obj.estimateGas({from: x});
const txReceipt = await obj.send({from: x, gas: requiredGas});

In your specific case, the function-call whose gas consumption you want to estimate would be:

myContract.methods.transfer(to, amount)


  • to is a string which represents an address value
  • amount is a string which represents a uint256 value
  • Thanks. I just don't understand myMethod(123). Is this just a placeholder for another function I'm supposed to call? My inclination is to just call myContract.methods.estimateGas(options). – slider Apr 15 '20 at 7:54
  • @slider: Oh, forgot to refer to your specific request about ERC20-transfer, one sec... – goodvibration Apr 15 '20 at 7:55
  • @slider: Please see updated answer. – goodvibration Apr 15 '20 at 7:59
  • Ah, that makes plenty of sense. In this case, is there any difference between valid to addresses, assuming it is simply a wallet address? – slider Apr 15 '20 at 8:09
  • @slider: You're asking if there could be different gas-estimations for different inputs. The answer is yes, depending on what the contract function does with these inputs. In fact, you could get different gas-estimations even for the same input. It depends on the current state of your contract. For example, suppose you have function set(uint _x) public {x = _x;}, then myContract.methods.set(5).estimateGas() would return a large value the first time you call it, and a much smaller value the second time you call it. – goodvibration Apr 15 '20 at 8:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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