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?)

Daniel Que
  • 783
  • 7
  • 21
Imroz
  • 871
  • 2
  • 7
  • 11
  • How are you using .estimateGas()? With .getData()? – Matthew Schmidt Jan 02 '17 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 Jan 04 '17 at 07:24

5 Answers5

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.)

Matthew Schmidt
  • 7,290
  • 1
  • 24
  • 35
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)
Ellis
  • 2,354
  • 14
  • 14
0

Web3 allows this:

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

...

const gas = await MyContract.new.estimateGas(arg1, arg2, arg3);

k06a
  • 3,016
  • 2
  • 21
  • 35
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.