From fedbe0d2bc34560b0e18f39aac9dc1fff085004c Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Wed, 6 Jun 2018 14:37:08 -0500 Subject: [PATCH] first attempt at gas estimation using a 3 round fuzzer and linking it into the profiler Signed-off-by: VoR0220 --- lib/modules/fuzzer/index.js | 5 +++-- lib/modules/gasEstimator/index.js | 37 +++++++++++++++++++++++++++++++ lib/modules/profiler/index.js | 9 +++++--- 3 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 lib/modules/gasEstimator/index.js diff --git a/lib/modules/fuzzer/index.js b/lib/modules/fuzzer/index.js index a38dc89ca..1a173fdc1 100644 --- a/lib/modules/fuzzer/index.js +++ b/lib/modules/fuzzer/index.js @@ -21,10 +21,11 @@ class ContractFuzzer { contract.abiDefinition.filter((x) => x.inputs && x.inputs.length != 0).forEach((abiMethod) => { let name = abiMethod.type === "constructor" ? "constructor" : abiMethod.name; let inputTypes = abiMethod.inputs.map(input => input.type); - fuzzMap[name] = inputTypes.map(input => this.getTypeFuzz(input)); + fuzzMap[name][i] = inputTypes.map(input => this.getTypeFuzz(input)); }); + self.logger.info('\n'); + for (let key in fuzzMap) self.logger.info(key + ":" + fuzzMap[key][i]); } - for (let key in fuzzMap) self.logger.info(key + ":" + fuzzMap[key]); return fuzzMap; } diff --git a/lib/modules/gasEstimator/index.js b/lib/modules/gasEstimator/index.js new file mode 100644 index 000000000..9095937aa --- /dev/null +++ b/lib/modules/gasEstimator/index.js @@ -0,0 +1,37 @@ +const ContractFuzzer = require('../fuzzer'); + +class GasEstimator { + constructor(embark) { + this.embark = embark; + this.logger = embark.logger; + this.events = embark.events; + this.fuzzer = new ContractFuzzer(embark); + } + + estimateGas(contractName) { + let gasMap = {}; + this.logger.info("Generating three rounds of fuzz for contract -- ", contractName); + let fuzzMap = this.fuzzer.generateFuzz(3, contractName); + self.events.request('contracts:contract', contractName, (contract) => { + self.logger.info("-- Beginning gastimation for contract -- " + contractName); + tempGasMap = {}; + fuzzMap.forEach((name) => { + for (let i in fuzzMap[name]) { + tempGasMap[name][i] = contract.methods[name].apply(contract.methods[name], fuzzMap[name][i]).estimateGas(); + } + }); + tempGasMap.forEach((name) => { + if (name === "constructor") { + gasMap[name] = contract.gasEstimates.creation.totalCost; + } else if (tempGasMap[name][0] !== tempGasMap[name][1] && tempGasMap[name][1] !== tempGasMap[name][2]) { + gasMap[name] = 'variable'; + } else { + gasMap[name] = tempGasMap[name][0]; + } + }); + return gasMap; + }); + } +} + +module.exports = GasEstimator; diff --git a/lib/modules/profiler/index.js b/lib/modules/profiler/index.js index f86ad9952..a86f239d2 100644 --- a/lib/modules/profiler/index.js +++ b/lib/modules/profiler/index.js @@ -1,10 +1,12 @@ const asciiTable = require('ascii-table'); +const GasEstimator = require('../gasEstimator'); class Profiler { constructor(embark) { this.embark = embark; this.logger = embark.logger; this.events = embark.events; + this.gasEstimator = new GasEstimator(embark); this.registerConsoleCommand(); } @@ -12,14 +14,15 @@ class Profiler { profile(contractName, contract) { const self = this; let table = new asciiTable(contractName); - table.setHeading('Function', 'Payable', 'Mutability', 'Inputs', 'Outputs'); + table.setHeading('Function', 'Payable', 'Mutability', 'Inputs', 'Outputs', 'Gas Estimates'); + let gastimates = self.gasEstimator.estimateGas(contractName); contract.abiDefinition.forEach((abiMethod) => { switch(abiMethod.type) { case "constructor": - table.addRow("constructor", abiMethod.payable, abiMethod.stateMutability, this.formatParams(abiMethod.inputs), this.formatParams(abiMethod.outputs)); + table.addRow("constructor", abiMethod.payable, abiMethod.stateMutability, this.formatParams(abiMethod.inputs), this.formatParams(abiMethod.outputs), gastimates['constructor']); break; default: - table.addRow(abiMethod.name, abiMethod.payable, abiMethod.stateMutability, this.formatParams(abiMethod.inputs), this.formatParams(abiMethod.outputs)); + table.addRow(abiMethod.name, abiMethod.payable, abiMethod.stateMutability, this.formatParams(abiMethod.inputs), this.formatParams(abiMethod.outputs), gastimates[abiMethod.name]); } }); self.logger.info(table.toString());