3

I have a big contract (more then 1000 strings of code). I deploy it without any problems. When i estimate the gas consumption

let gas_need = Web3Helpers.web3.eth.estimateGas({data: code});
console.log("Gas needed="+gas_need);

I get "Gas needed=1652040". But if I add one more function (any) to contract, that can generate event, when I try to deploy I get an error "The contract code couldn't be stored, please check your gas amount" and the value of gas needed is "Gas needed=1000000000000000000". Can anyone explain what is going on?!

EDIT

  1. I think I get value "Gas needed=1000000000000000000" because I run node with --targetgaslimit 1000000000000000000 parameter.
  2. I've written small test.

"use strict";

let Web3 = require('web3');
let web3;
if (typeof web3 !== 'undefined') {
    web3 = new Web3(web3.currentProvider);
} else {
    web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}


function codeGenerator(functions_count)
{
    let code = `
        pragma solidity ^0.4.0;
        contract Test
        {
            event TestEvent(uint a);
            function Test() {}
        `;
    for (let i=0;i<functions_count;i++)
    {
        code+="\nfunction f"+i+`(uint i)
        {
            TestEvent(i);
        }`;
    }
    code+="\n}";
    return code;
}


let start_functions_count=350;
let end_functions_count=360;

let compileAndCheck = function (i)
{
    let code = codeGenerator(i);
    web3.eth.compile.solidity(
        code,
        function (error, compiled_code) {
            if (error)
            {
                console.log("Compilation error. i="+i+" Error=", error);
                process.exit(0);
            }

            let gas_need = web3.eth.estimateGas({data: compiled_code["<stdin>:Test"].code});
            console.log("Number of functions="+i+". Gas needed="+gas_need);

            if (i<end_functions_count)
                compileAndCheck(i+1);
        });
};

compileAndCheck(start_functions_count);

When I run this script I get output:

    Number of functions=350. Gas needed=1632400
    Number of functions=351. Gas needed=1636991
    Number of functions=352. Gas needed=1641573
    Number of functions=353. Gas needed=1646155
    Number of functions=354. Gas needed=1650737
    Number of functions=355. Gas needed=712069252639603
    Number of functions=356. Gas needed=715552950743727
    Number of functions=357. Gas needed=719053692348094
    Number of functions=358. Gas needed=719053692348094
    Number of functions=359. Gas needed=719053692348094

Can anyone tell what happens when Number of functions=355 ?

EDIT 1 One more surveillance that wil possibly help to understand what is going on. The output when I do mining.

    Number of functions=352. Gas needed=1641573
    Number of functions=353. Gas needed=1646155
    Number of functions=354. Gas needed=1650737
    Number of functions=355. Gas needed=870454639237568800
    Number of functions=356. Gas needed=867906968741702500
    Number of functions=357. Gas needed=864521670116149900
    Number of functions=358. Gas needed=861991364396921200
    Number of functions=359. Gas needed=859468464445823200
    Number of functions=360. Gas needed=856952948587450600

If I do not mining, I get this:

    Number of functions=352. Gas needed=1641573
    Number of functions=353. Gas needed=1646155
    Number of functions=354. Gas needed=1650737
    Number of functions=355. Gas needed=472655063161557060
    Number of functions=356. Gas needed=472655063161557060
    Number of functions=357. Gas needed=472655063161557060
    Number of functions=358. Gas needed=472655063161557060
    Number of functions=359. Gas needed=472655063161557060
    Number of functions=360. Gas needed=472655063161557060

EDIT 2

  1. I use geth VERSION 1.5.9-stable-a07539fb
  2. I start node with comand geth --shh --fakepow --nodiscover --maxpeers 1 --nat none --rpc --rpcapi="db,eth,net,web3,personal,debug" --rpccorsdomain "*" --datadir "/Users/admin/Desktop/etherium-research/private_chain_directory/" --identity "private_node_1" --networkid 19045 console
  3. I tryed to use different solc java script compiler

"use strict";

var solc = require('solc');

let Web3 = require('web3');
let web3;
if (typeof web3 !== 'undefined') {
    web3 = new Web3(web3.currentProvider);
} else {
    web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}


function codeGenerator(functions_count)
{
    let code = `
        pragma solidity ^0.4.0;
        contract Test
        {
            event TestEvent(uint a);
            function Test() {}
        `;
    for (let i=0;i<functions_count;i++)
    {
        code+="\nfunction f"+i+`(uint i)
        {
            TestEvent(i);
        }`;
    }
    code+="\n}";
    return code;
}


let start_functions_count=352;
let end_functions_count=357;



let c_version = 'v0.4.9+commit.364da425';
solc.loadRemoteVersion(c_version, function(err, solcSnapshot) {
    if (err) {
        console.log("Load compiler error="+err);
        process.exit(0);
    }
    compileSolcAndCheck(solcSnapshot);
});


function compileSolcAndCheck(complier) {
   console.log("Compiler version="+complier.version());
    for (let i=start_functions_count; i <=end_functions_count; i++)
    {
        let code = codeGenerator(i);
        console.log("Compiling for functions count="+i);
        let compiled_code = complier.compile(code,1);
        console.log("Estimating gas usage for functions count="+i);
        let gas_need = web3.eth.estimateGas({data: "0x"+compiled_code.contracts[':Test'].bytecode});
        console.log("Number of functions="+i+". Gas needed="+gas_need);
    }
}

Results:

Compiler version=0.4.9+commit.364da425.Emscripten.clang
Compiling for functions count=352
Estimating gas usage for functions count=352
Number of functions=352. Gas needed=1641573
Compiling for functions count=353
Estimating gas usage for functions count=353
Number of functions=353. Gas needed=1646155
Compiling for functions count=354
Estimating gas usage for functions count=354
Number of functions=354. Gas needed=1650737
Compiling for functions count=355
Estimating gas usage for functions count=355
Number of functions=355. Gas needed=8029590240010579
Compiling for functions count=356
Estimating gas usage for functions count=356
Number of functions=356. Gas needed=7557625396430654
Compiling for functions count=357
Estimating gas usage for functions count=357
Number of functions=357. Gas needed=7106455114351858
Compiler version=0.4.10+commit.f0d539ae.Emscripten.clang
Compiling for functions count=352
Estimating gas usage for functions count=352
Number of functions=352. Gas needed=1641573
Compiling for functions count=353
Estimating gas usage for functions count=353
Number of functions=353. Gas needed=1646091
Compiling for functions count=354
Estimating gas usage for functions count=354
Number of functions=354. Gas needed=1650737
Compiling for functions count=355
Estimating gas usage for functions count=355
Number of functions=355. Gas needed=15512687238849220
Compiling for functions count=356
Estimating gas usage for functions count=356
Number of functions=356. Gas needed=14501360678935126
Compiling for functions count=357
  1. If optimization is disabled gas grow event happens earlier, don't know when exactly

EDIT 3

It seems the problem appears when bytecode size is more 48 Kb. I tried different compilers and different solidity source code, with and without optimization. Using optimization just makes code size smaller (I mentioned about optimization above)

Mon Mar 27 2017 18:35:41 GMT+0300 (MSK) Compiling for functions count=181
Mon Mar 27 2017 18:36:16 GMT+0300 (MSK) Code compiled. 
Byte code size=49140(47.98828125 KB)
Estimating gas usage for functions count=181
Number of functions=181. Gas needed=1650521

Mon Mar 27 2017 18:36:21 GMT+0300 (MSK) Compiling for functions count=182
Mon Mar 27 2017 18:36:56 GMT+0300 (MSK) Code compiled. 
Byte code size=49410(48.251953125 KB)
Estimating gas usage for functions count=182
Number of functions=182. Gas needed=2508197197101
  • Interesting, what if you manually set the gas amount to a little bit more than the previous estimation? Would that go through well? – Yuanfei Zhu Mar 24 '17 at 8:24
  • @yuanfei-zhu When I realy deploy contract I always send gas: 100000000. I do not use Web3Helpers.web3.eth.estimateGas. I did it just to show the estimation. Moreover, a tryed to create simple contract with one event and many functions with different names that just call the event. When the number of theese functions become enough big (now try to determine exactly) - the problem appers. – Alexey Barsuk Mar 24 '17 at 8:52
  • When a it says that it will take the maximum possible gas, it usually means that the contract just threw an exception (which uses up all of the remaining gas). I'd guess that you're running out of stack space during deployment or something. It may also just be a poorly behaved edge-case in the compiler. – Tjaden Hess Mar 24 '17 at 14:25
  • Why do you need that many functions anyway? – Tjaden Hess Mar 24 '17 at 14:25
  • @tjaden-hess I do not realy need so many functions. I'm using modifiers in my contract, that generate events for debug purposes (they will throw in release). I tryed to add 1 more function with modifier and got the error. When I commented event call in modifier - problem disapeared. The code above shows the problem. It seems for me that when the contract has more code then some threshold - this problem happens. I was able to repeat problem with lots of empty functions and with only one function with lots of of events inside it. When i'm out of stack space the compiler throws error, isn't it? – Alexey Barsuk Mar 24 '17 at 16:13
4

Compiled (binary) contract code can not exceed 24576 bytes (48Kb in HEX encoded). See https://github.com/ethereum/EIPs/issues/170 for details. Thanks to https://github.com/fjl for pointing.

  • I was looking for this answer. This is right, I think. I think this was part of Spurious Dragon. – Thomas Jay Rush May 2 '17 at 15:34

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.