2018-06-12 17:16:19 +00:00
|
|
|
/*global web3*/
|
2018-06-08 17:46:57 +00:00
|
|
|
const async = require('async');
|
|
|
|
const _ = require('underscore');
|
2018-06-06 19:37:08 +00:00
|
|
|
const ContractFuzzer = require('../fuzzer');
|
|
|
|
|
|
|
|
class GasEstimator {
|
|
|
|
constructor(embark) {
|
|
|
|
this.embark = embark;
|
|
|
|
this.logger = embark.logger;
|
|
|
|
this.events = embark.events;
|
|
|
|
this.fuzzer = new ContractFuzzer(embark);
|
|
|
|
}
|
|
|
|
|
2018-06-08 17:46:57 +00:00
|
|
|
estimateGas(contractName, cb) {
|
2018-06-06 20:30:29 +00:00
|
|
|
const self = this;
|
2018-06-06 19:37:08 +00:00
|
|
|
let gasMap = {};
|
|
|
|
self.events.request('contracts:contract', contractName, (contract) => {
|
2018-06-06 20:30:29 +00:00
|
|
|
self.logger.info("Generating three rounds of fuzz for contract -- ", contractName);
|
|
|
|
let fuzzMap = self.fuzzer.generateFuzz(3, contract);
|
2018-06-06 19:37:08 +00:00
|
|
|
self.logger.info("-- Beginning gastimation for contract -- " + contractName);
|
2018-06-07 20:23:54 +00:00
|
|
|
let contractObj = new web3.eth.Contract(contract.abiDefinition, contract.deployedAddress);
|
2018-06-12 17:10:35 +00:00
|
|
|
async.each(contract.abiDefinition.filter((x) => x.type !== "event"),
|
2018-06-08 19:26:32 +00:00
|
|
|
(abiMethod, gasCb) => {
|
2018-06-08 17:46:57 +00:00
|
|
|
let name = abiMethod.name;
|
|
|
|
if (abiMethod.type === "constructor") {
|
|
|
|
// already provided for us
|
2018-06-12 17:10:35 +00:00
|
|
|
gasMap['constructor'] = contract.gasEstimates.creation.totalCost.toString();
|
|
|
|
gasCb(null);
|
2018-06-12 15:31:26 +00:00
|
|
|
} else if (abiMethod.type === "fallback") {
|
2018-06-12 17:10:35 +00:00
|
|
|
gasMap['fallback'] = contract.gasEstimates.external[""].toString();
|
|
|
|
gasCb(null);
|
2018-06-12 15:31:26 +00:00
|
|
|
} else if (abiMethod.inputs === null || abiMethod.inputs === undefined || abiMethod.inputs.length === 0) {
|
2018-06-08 17:46:57 +00:00
|
|
|
// just run it and register it
|
|
|
|
contractObj.methods[name]
|
|
|
|
.apply(contractObj.methods[name], [])
|
2018-06-08 19:26:32 +00:00
|
|
|
.estimateGas((err, gasAmount) => {
|
2018-06-12 17:10:35 +00:00
|
|
|
if (err) {
|
|
|
|
return gasCb(err);
|
|
|
|
} else {
|
|
|
|
gasMap[name] = gasAmount;
|
|
|
|
gasCb(null, gasAmount, name);
|
|
|
|
}
|
2018-06-08 17:46:57 +00:00
|
|
|
});
|
2018-06-08 19:26:32 +00:00
|
|
|
} else {
|
|
|
|
// async concatenate all the fuzz values and their gas cost outputs and check for equality
|
|
|
|
async.concat(fuzzMap[name], (values, getVarianceCb) => {
|
2018-06-12 17:10:35 +00:00
|
|
|
contractObj.methods[name].apply(contractObj.methods[name], values)
|
2018-06-08 19:26:32 +00:00
|
|
|
.estimateGas((err, gasAmount) => {
|
2018-06-12 17:52:23 +00:00
|
|
|
getVarianceCb(err, gasAmount);
|
2018-06-08 19:26:32 +00:00
|
|
|
});
|
|
|
|
}, (err, variance) => {
|
|
|
|
if (err) {
|
2018-06-12 17:10:35 +00:00
|
|
|
return gasCb(err);
|
2018-06-12 15:31:26 +00:00
|
|
|
} else if (_.isEqual(variance[0], variance[1]) && _.isEqual(variance[1], variance[2])) {
|
2018-06-08 19:26:32 +00:00
|
|
|
gasMap[name] = variance[0];
|
|
|
|
} else {
|
2018-06-12 17:10:35 +00:00
|
|
|
gasMap[name] = 'infinite';
|
2018-06-08 19:26:32 +00:00
|
|
|
}
|
|
|
|
gasCb();
|
|
|
|
});
|
2018-06-12 15:39:45 +00:00
|
|
|
}
|
2018-06-08 17:46:57 +00:00
|
|
|
},
|
2018-06-08 19:26:32 +00:00
|
|
|
(err) => {
|
2018-06-08 17:46:57 +00:00
|
|
|
if (err) return cb(err);
|
2018-06-08 19:26:32 +00:00
|
|
|
cb(null, gasMap);
|
2018-06-06 19:37:08 +00:00
|
|
|
}
|
2018-06-08 19:26:32 +00:00
|
|
|
);
|
2018-06-06 19:37:08 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = GasEstimator;
|