KeyringController - estimateGas->analyzeGasUsage fix gasLimit + detect OOG

feature/default_network_editable
kumavis 8 years ago
parent 4669f262e2
commit bc39cd7b89
  1. 66
      app/scripts/keyring-controller.js
  2. 1
      package.json

@ -1,4 +1,5 @@
const async = require('async') const async = require('async')
const bind = require('ap').partial
const ethUtil = require('ethereumjs-util') const ethUtil = require('ethereumjs-util')
const ethBinToOps = require('eth-bin-to-ops') const ethBinToOps = require('eth-bin-to-ops')
const EthQuery = require('eth-query') const EthQuery = require('eth-query')
@ -362,7 +363,7 @@ module.exports = class KeyringController extends EventEmitter {
// calculate metadata for tx // calculate metadata for tx
async.parallel([ async.parallel([
analyzeForDelegateCall, analyzeForDelegateCall,
estimateGas, analyzeGasUsage,
], didComplete) ], didComplete)
// perform static analyis on the target contract code // perform static analyis on the target contract code
@ -385,14 +386,69 @@ module.exports = class KeyringController extends EventEmitter {
} }
} }
function estimateGas (cb) { function analyzeGasUsage (cb) {
query.estimateGas(txParams, function (err, result) { query.getBlockByNumber('latest', true, function (err, block) {
if (err) return cb(err) if (err) return cb(err)
txData.estimatedGas = self.addGasBuffer(result) async.waterfall([
cb() bind(estimateGas, txData, block.gasLimit),
bind(checkForGasError, txData),
bind(setTxGas, txData, block.gasLimit),
], cb)
}) })
} }
function estimateGas(txData, blockGasLimitHex, cb) {
const txParams = txData.txParams
// check if gasLimit is already specified
txData.gasLimitSpecified = Boolean(txParams.gas)
// if not, fallback to block gasLimit
if (!txData.gasLimitSpecified) {
txParams.gas = blockGasLimitHex
}
// run tx, see if it will OOG
query.estimateGas(txParams, cb)
}
function checkForGasError(txData, estimatedGasHex) {
txData.estimatedGas = estimatedGasHex
// all gas used - must be an error
if (estimatedGasHex === txData.txParams.gas) {
txData.simulationFails = true
}
cb()
}
function setTxGas(txData, blockGasLimitHex) {
const txParams = txData.txParams
// if OOG, nothing more to do
if (txData.simulationFails) {
cb()
return
}
// if gasLimit was specified and doesnt OOG,
// use original specified amount
if (txData.gasLimitSpecified) {
txData.estimatedGas = txParams.gas
cb()
return
}
// if gasLimit not originally specified,
// try adding an additional gas buffer to our estimation for safety
const estimatedGasBn = new BN(ethUtil.stripHexPrefix(txData.estimatedGas), 16)
const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16)
const estimationWithBuffer = self.addGasBuffer(estimatedGasBn)
// added gas buffer is too high
if (estimationWithBuffer.gt(blockGasLimitBn)) {
txParams.gas = txData.estimatedGas
// added gas buffer is safe
} else {
const gasWithBufferHex = ethUtil.intToHex(estimationWithBuffer)
txParams.gas = gasWithBufferHex
}
cb()
return
}
function didComplete (err) { function didComplete (err) {
if (err) return cb(err) if (err) return cb(err)
configManager.addTx(txData) configManager.addTx(txData)

@ -33,6 +33,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"ap": "^0.2.0",
"async": "^1.5.2", "async": "^1.5.2",
"bip39": "^2.2.0", "bip39": "^2.2.0",
"browserify-derequire": "^0.9.4", "browserify-derequire": "^0.9.4",

Loading…
Cancel
Save