1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Refactor simple send gas estimation (#8484)

The simple send gas estimation has been moved out of the gas estimation
module, and into the transaction controller. This was done in an effort
to limit the number of places where `txMeta` is mutated while the
default gas parameters are being set.
This commit is contained in:
Mark Stacey 2020-04-30 19:50:12 -03:00 committed by GitHub
parent 118bddd71a
commit afa2ff65b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 42 deletions

View File

@ -35,6 +35,9 @@ import {
} from './enums'
import { hexToBn, bnToHex, BnMultiplyByFraction } from '../../lib/util'
import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys'
const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send.
/**
Transaction Controller is an aggregate of sub-controllers and trackers
@ -258,7 +261,9 @@ export default class TransactionController extends EventEmitter {
*/
async addTxGasDefaults (txMeta, getCodeResponse) {
const txParams = txMeta.txParams
// ensure value
txParams.value = txParams.value ? ethUtil.addHexPrefix(txParams.value) : '0x0'
txMeta.gasPriceSpecified = Boolean(txParams.gasPrice)
let gasPrice = txParams.gasPrice
@ -266,8 +271,33 @@ export default class TransactionController extends EventEmitter {
gasPrice = this.getGasPrice ? this.getGasPrice() : await this.query.gasPrice()
}
txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16))
// set gasLimit
return await this.txGasUtil.analyzeGasUsage(txMeta, getCodeResponse)
if (
txParams.to &&
txMeta.transactionCategory === SEND_ETHER_ACTION_KEY &&
!txParams.gas
) {
// if there's data in the params, but there's no contract code, it's not a valid transaction
if (txParams.data) {
const err = new Error('TxGasUtil - Trying to call a function on a non-contract address')
// set error key so ui can display localized error message
err.errorKey = TRANSACTION_NO_CONTRACT_ERROR_KEY
// set the response on the error so that we can see in logs what the actual response was
err.getCodeResponse = getCodeResponse
throw err
}
// This is a standard ether simple send, gas requirement is exactly 21k
txParams.gas = SIMPLE_GAS_COST
txMeta.estimatedGas = SIMPLE_GAS_COST
txMeta.simpleSend = true
txMeta.gasLimitSpecified = Boolean(txParams.gas)
return txMeta
}
return await this.txGasUtil.analyzeGasUsage(txMeta)
}
/**

View File

@ -2,11 +2,6 @@ import EthQuery from 'ethjs-query'
import { hexToBn, BnMultiplyByFraction, bnToHex } from '../../lib/util'
import log from 'loglevel'
import { addHexPrefix } from 'ethereumjs-util'
import { SEND_ETHER_ACTION_KEY } from '../../../../ui/app/helpers/constants/transactions.js'
const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send.
import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys'
/**
tx-gas-utils are gas utility methods for Transaction manager
@ -25,11 +20,11 @@ export default class TxGasUtil {
@param {Object} txMeta - the txMeta object
@returns {Object} - the txMeta object with the gas written to the txParams
*/
async analyzeGasUsage (txMeta, getCodeResponse) {
async analyzeGasUsage (txMeta) {
const block = await this.query.getBlockByNumber('latest', false)
let estimatedGasHex
try {
estimatedGasHex = await this.estimateTxGas(txMeta, block.gasLimit, getCodeResponse)
estimatedGasHex = await this.estimateTxGas(txMeta, block.gasLimit)
} catch (err) {
log.warn(err)
txMeta.simulationFails = {
@ -38,10 +33,6 @@ export default class TxGasUtil {
debug: { blockNumber: block.number, blockGasLimit: block.gasLimit },
}
if (err.errorKey === TRANSACTION_NO_CONTRACT_ERROR_KEY) {
txMeta.simulationFails.debug.getCodeResponse = err.getCodeResponse
}
return txMeta
}
this.setTxGas(txMeta, block.gasLimit, estimatedGasHex)
@ -54,7 +45,7 @@ export default class TxGasUtil {
@param {string} blockGasLimitHex - hex string of the block's gas limit
@returns {string} - the estimated gas limit as a hex string
*/
async estimateTxGas (txMeta, blockGasLimitHex, getCodeResponse) {
async estimateTxGas (txMeta, blockGasLimitHex) {
const txParams = txMeta.txParams
// check if gasLimit is already specified
@ -65,34 +56,6 @@ export default class TxGasUtil {
return txParams.gas
}
const recipient = txParams.to
const hasRecipient = Boolean(recipient)
// see if we can set the gas based on the recipient
if (hasRecipient) {
// For an address with no code, geth will return '0x', and ganache-core v2.2.1 will return '0x0'
const categorizedAsSimple = txMeta.transactionCategory === SEND_ETHER_ACTION_KEY
if (categorizedAsSimple) {
// if there's data in the params, but there's no contract code, it's not a valid transaction
if (txParams.data) {
const err = new Error('TxGasUtil - Trying to call a function on a non-contract address')
// set error key so ui can display localized error message
err.errorKey = TRANSACTION_NO_CONTRACT_ERROR_KEY
// set the response on the error so that we can see in logs what the actual response was
err.getCodeResponse = getCodeResponse
throw err
}
// This is a standard ether simple send, gas requirement is exactly 21k
txParams.gas = SIMPLE_GAS_COST
// prevents buffer addition
txMeta.simpleSend = true
return SIMPLE_GAS_COST
}
}
// fallback to block gasLimit
const blockGasLimitBN = hexToBn(blockGasLimitHex)
const saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20)
@ -114,7 +77,7 @@ export default class TxGasUtil {
// if gasLimit was specified and doesnt OOG,
// use original specified amount
if (txMeta.gasLimitSpecified || txMeta.simpleSend) {
if (txMeta.gasLimitSpecified) {
txMeta.estimatedGas = txParams.gas
return
}