合約部署的虛幻大gas消耗
我有一份大契約(超過 1000 串程式碼)。我部署它沒有任何問題。當我估算耗氣量時
let gas_need = Web3Helpers.web3.eth.estimateGas({data: code}); console.log("Gas needed="+gas_need);
我得到“需要的氣體=1652040”。但是,如果我在合約中添加一個可以生成事件的函式(任何),當我嘗試部署時,我會收到一個錯誤“無法儲存合約程式碼,請檢查你的 gas 量”,需要的 gas 值為“需要的氣體=1000000000000000000”。誰能解釋發生了什麼?!
編輯
- 我想我得到值“需要的氣體 = 1000000000000000000”,因為我使用 –targetgaslimit 1000000000000000000 參數執行節點。
- 我寫了小測試。
"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
4. 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
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.