Skip to content

Commit 785fef3

Browse files
authored
Merge pull request #872 from MetaMask/i868-estimateGasTooHigh
Improve gas estimation logic
2 parents b9d73a4 + 49a1f43 commit 785fef3

File tree

2 files changed

+50
-29
lines changed

2 files changed

+50
-29
lines changed

app/scripts/lib/idStore.js

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -260,24 +260,51 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone
260260

261261
function estimateGas(cb){
262262
var estimationParams = extend(txParams)
263-
// 1 billion gas for estimation
264-
var gasLimit = '0x3b9aca00'
265-
estimationParams.gas = gasLimit
266-
query.estimateGas(estimationParams, function(err, result){
267-
if (err) return cb(err.message || err)
268-
if (result === estimationParams.gas) {
269-
txData.simulationFails = true
270-
query.getBlockByNumber('latest', true, function(err, block){
271-
if (err) return cb(err)
272-
txData.estimatedGas = block.gasLimit
273-
txData.txParams.gas = block.gasLimit
263+
query.getBlockByNumber('latest', true, function(err, block){
264+
if (err) return cb(err)
265+
// check if gasLimit is already specified
266+
const gasLimitSpecified = Boolean(txParams.gas)
267+
// if not, fallback to block gasLimit
268+
if (!gasLimitSpecified) {
269+
estimationParams.gas = block.gasLimit
270+
}
271+
// run tx, see if it will OOG
272+
query.estimateGas(estimationParams, function(err, estimatedGasHex){
273+
if (err) return cb(err.message || err)
274+
// all gas used - must be an error
275+
if (estimatedGasHex === estimationParams.gas) {
276+
txData.simulationFails = true
277+
txData.estimatedGas = estimatedGasHex
278+
txData.txParams.gas = estimatedGasHex
279+
cb()
280+
return
281+
}
282+
// otherwise, did not use all gas, must be ok
283+
284+
// if specified gasLimit and no error, we're done
285+
if (gasLimitSpecified) {
286+
txData.estimatedGas = txParams.gas
274287
cb()
275-
})
288+
return
289+
}
290+
291+
// try adding an additional gas buffer to our estimation for safety
292+
const estimatedGasBn = new BN(ethUtil.stripHexPrefix(estimatedGasHex), 16)
293+
const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(block.gasLimit), 16)
294+
const estimationWithBuffer = self.addGasBuffer(estimatedGasBn)
295+
// added gas buffer is too high
296+
if (estimationWithBuffer.gt(blockGasLimitBn)) {
297+
txData.estimatedGas = estimatedGasHex
298+
txData.txParams.gas = estimatedGasHex
299+
// added gas buffer is safe
300+
} else {
301+
const gasWithBufferHex = ethUtil.intToHex(estimationWithBuffer)
302+
txData.estimatedGas = gasWithBufferHex
303+
txData.txParams.gas = gasWithBufferHex
304+
}
305+
cb()
276306
return
277-
}
278-
txData.estimatedGas = self.addGasBuffer(result)
279-
txData.txParams.gas = txData.estimatedGas
280-
cb()
307+
})
281308
})
282309
}
283310

@@ -302,12 +329,11 @@ IdentityStore.prototype.checkForDelegateCall = function (codeHex) {
302329
}
303330
}
304331

305-
IdentityStore.prototype.addGasBuffer = function (gas) {
306-
const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16)
307-
const five = new BN('5', 10)
308-
const gasBuffer = bnGas.div(five)
309-
const correct = bnGas.add(gasBuffer)
310-
return ethUtil.addHexPrefix(correct.toString(16))
332+
IdentityStore.prototype.addGasBuffer = function (gasBn) {
333+
// add 20% to specified gas
334+
const gasBuffer = gasBn.div(new BN('5', 10))
335+
const gasWithBuffer = gasBn.add(gasBuffer)
336+
return gasWithBuffer
311337
}
312338

313339
// comes from metamask ui

test/unit/idStore-test.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,9 @@ describe('IdentityStore', function() {
152152

153153
const gas = '0x01'
154154
const bnGas = new BN(gas, 16)
155-
const result = idStore.addGasBuffer(gas)
156-
const bnResult = new BN(result, 16)
155+
const bnResult = idStore.addGasBuffer(bnGas)
157156

158157
assert.ok(bnResult.gt(gas), 'added more gas as buffer.')
159-
assert.equal(result.indexOf('0x'), 0, 'include hex prefix')
160158
})
161159

162160
it('buffers 20%', function() {
@@ -173,13 +171,10 @@ describe('IdentityStore', function() {
173171
const correctBuffer = bnGas.div(five)
174172
const correct = bnGas.add(correctBuffer)
175173

176-
const result = idStore.addGasBuffer(gas)
177-
const bnResult = new BN(ethUtil.stripHexPrefix(result), 16)
174+
const bnResult = idStore.addGasBuffer(bnGas)
178175

179-
assert.equal(result.indexOf('0x'), 0, 'included hex prefix')
180176
assert(bnResult.gt(bnGas), 'Estimate increased in value.')
181177
assert.equal(bnResult.sub(bnGas).toString(10), correctBuffer.toString(10), 'added 20% gas')
182-
assert.equal(result, '0x' + correct.toString(16), 'Added the right amount')
183178
})
184179
})
185180

0 commit comments

Comments
 (0)