[Ethereum] Using web3.eth.estimateGas cause “gas required exceeds allowance or always failing transaction”

solidityweb3js

In solidity code I have function addPhase and it works well. The code below also works well

for (let j = 0; j < companies[i].phases.length; j++) {
    transactions.push(
        this.contract.addPhase(
            companies[i].phases[j].start_time,
            companies[i].phases[j].prices_in_wei,
            companies[i].phases[j].prices_in_wei_ends,
            companies[i].phases[j].tokens_count,
            companies[i].phases[j].min_tokens_to_sell,
            Web3Helpers.sender_envelope(sender,10000000000)));
}

But if I try to estimate gas consumption

for (let j = 0; j < companies[i].phases.length; j++) {
    let call_data_phase = this.contract.addPhase.getData(
        companies[i].phases[j].start_time,
        companies[i].phases[j].prices_in_wei,
        companies[i].phases[j].prices_in_wei_ends,
        companies[i].phases[j].tokens_count,
        companies[i].phases[j].min_tokens_to_sell
    );
    let gas_needed_phase = Web3Helpers.web3.eth.estimateGas({
        data: call_data_phase,
        to: this.contract.address,
        from: sender
    });
    console.log("Gas estimation=" + gas_needed_phase);

    transactions.push(
        this.contract.addPhase(
            companies[i].phases[j].start_time,
            companies[i].phases[j].prices_in_wei,
            companies[i].phases[j].prices_in_wei_ends,
            companies[i].phases[j].tokens_count,
            companies[i].phases[j].min_tokens_to_sell,
            Web3Helpers.sender_envelope(sender,10000000000)));
}

I get error gas required exceeds allowance or always failing transaction. I use similar code for other functions and gas estimation works well.

Has anybody seen something like this and what could it be?

Best Answer

After looking at the source code for this, you'll notice that it's failing because the gas allowance does not result in an executable transaction. EstimateGas function executes the requested code against the currently pending block/state and returns the used amount of gas (or error in your case). But, it can also fail if the transaction is ill-formed.

var errGasEstimationFailed = errors.New("gas required exceeds allowance or always failing transaction")

// Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap {
    if !executable(hi) {
        return nil, errGasEstimationFailed
    }
}

It looks like you may be incorrectly passing arguments to getData and thus in turn estimateGas.

Update: Please try below code.

let call_data_phase = this.contract.addPhase.getData(
        companies[i].phases[j].start_time,
        companies[i].phases[j].prices_in_wei,
        companies[i].phases[j].prices_in_wei_ends,
        companies[i].phases[j].tokens_count,
        companies[i].phases[j].min_tokens_to_sell,
        {from: sender, gas: 10000000000}

    );

web3.eth.estimateGas({data: call_data_phase, from: sender})

Hope this helps.

Related Topic