23

What I have done
a) When I use web3.eth.estimateGas to estimate the cost of a contract creation constructor with no parameters, the estimate is correct.

b) If the contract is already deployed then estimating the gas cost of a contract function with parameters, it works fine. (contract.myMethod.estimateGas() using the web3 api )

Issue
a) When I estimate gas in a contract on contract creation time (contractObject.new) with a parameterized constructor then it gives an incorrect estimation of gas cost. (web3.eth.estimateGas of web3 api)

What I want
a) When I estimate gas with multiple parameter constructor of contract then it should estimate correct gas. (contractObject.new for calling constructor)

b) Browser-soldity gives right gas estimation of contract with parametrized constructor --> before contract create/deploy (like transaction cost or execution cost, how can I use their algorithm with web3 api to estimate gas correct way?)

2
  • How are you using .estimateGas()? With .getData()? Commented Jan 2, 2017 at 17:11
  • Matthew Schmidt i am using estimateGas() function with method of contract to estimatote gas. i am not using any .getData() method. for example:- contractInstance.myMethod.estimateGas method give right result. but i want to estimate contractInstance.new for constructor calling with parametrized . when i estimateGas of contractInstance.new.estimateGas , it give's error, that method does not exist. how to fix it
    – Imroz
    Commented Jan 4, 2017 at 7:24

5 Answers 5

18

Try using .getData().

.getData() returns the encoded parameters of a function in order to send the transaction manually. You can then stick this in web3.eth.estimateGas() (the one on web3.eth, not on a given method.) to simulate sending the transaction.

Here's an untested example, but hopefully it can help you on your way:

var contractData = contractObject.new.getData(someparam, another, {data: contractBytecode});
var estimate = web3.eth.estimateGas({data: contractData})

References:

web3.eth.estimateGas()

An example of using .getData() (It's the fourth option.)

3
  • 1
    What does 'contractCode' refer to in your first example line?
    – user339946
    Commented May 18, 2018 at 4:13
  • 1
    Whoops! Should have been a bit clearer. That's the contract bytecode--what you get from solc --bin I'll edit my answer. Commented May 19, 2018 at 11:13
  • These method seems to not work with web3 version 1.0 since there is no getData()? Edit: Found this question which says to use encodeABI() instead of getData(). Commented Nov 15, 2018 at 15:40
3

When working with web3.js version 1.2.x, there is not .getData method. The solution I found was to estimate of gas of the .deploy() method, which effectively returns the cost of contract creation.

The sequence of operations is:

let contractJSON = // JSON compiled contract
const contractABI = contractJSON.abi;
const bytecode = contractJSON.bytecode;
const contract = new web3.eth.Contract(contractABI);
let options = {
    arguments: [ arg1, arg2,... ],
    data: bytecode
}
const estimatedGas = await contract.deploy(options).estimateGas();
1

With web3js, it's pretty easy. First you need to create your contract. After creation, you'll have contractABI and the contract address like this:

let contractABI = [ { "constant": true, "inputs": [ { "name": "", "type": "bytes32" }, { "name": "", "type": "uint256" } ], "name": "verify", "outputs": [ { "name": "", "type": "address", "value": "0x" } ], "payable": false, "type": "function" }, { "constant": false, "inputs": [ { "name": "document", "type": "bytes32" } ], "name": "sign", "outputs": [], "payable": false, "type": "function" } ]
let contractAddress = '0xaEC9eCDAFAf2404F824B4b7087e9E4F90C77D082'

With these informations, just create the contract proxy contractInstance and estimate a tx on a sign method:

const web3conn = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'))
const contract = web3conn.eth.contract(contractABI)
const contractInstance = contract.at(contractAddress)
let estimatedGas = contractInstance.sign.estimateGas('arg of my function', { from: '0xAddress' })

The proxy is a special object (use a console.log to see all methods) to facilitate contract usage. If you have a sign method, you can create a Tx to sign:

let txHash = contractInstance.sign(param, { from: config.ethereum.identity, gas: estimatedGas })

if you use wan't to call a function (without transaction):

contractInstance.sign.call(param)
1
  • 3
    Question is about gas estimate on contact creation.
    – Alex
    Commented Jul 6, 2018 at 5:34
0

Web3 allows this:

const MyContract = artifacts.require('MyContract');

...

const gas = await MyContract.new.estimateGas(arg1, arg2, arg3);
0
let contract = new web3.eth.Contract(contractABI);
const bytecodeWithEncodedParameters = contract
    .deploy({
        data: contractByteCode,
        arguments: [?, ?, ?],
    })
    .encodeABI();

const estimateGas = await web3.eth.estimateGas({
    data: bytecodeWithEncodedParameters,
});

Try like this for new contract deployment. It works for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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