Fix gas estimation (#1944)
* Fix gas estimation for threshold > 4 * Update gas estimation to be more precise * Add threshold gas costs on transaction creation estimation Co-authored-by: Daniel Sanchez <daniel.sanchez@gnosis.pm>
This commit is contained in:
parent
ce1ab8b039
commit
b4de1b669a
|
@ -5,6 +5,7 @@ import {
|
||||||
estimateGasForTransactionCreation,
|
estimateGasForTransactionCreation,
|
||||||
estimateGasForTransactionExecution,
|
estimateGasForTransactionExecution,
|
||||||
MINIMUM_TRANSACTION_GAS,
|
MINIMUM_TRANSACTION_GAS,
|
||||||
|
GAS_REQUIRED_PER_SIGNATURE,
|
||||||
} from 'src/logic/safe/transactions/gas'
|
} from 'src/logic/safe/transactions/gas'
|
||||||
import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue'
|
import { fromTokenUnit } from 'src/logic/tokens/utils/humanReadableValue'
|
||||||
import { formatAmount } from 'src/logic/tokens/utils/formatAmount'
|
import { formatAmount } from 'src/logic/tokens/utils/formatAmount'
|
||||||
|
@ -229,12 +230,13 @@ export const useEstimateTransactionGas = ({
|
||||||
safeTxGas,
|
safeTxGas,
|
||||||
approvalAndExecution,
|
approvalAndExecution,
|
||||||
})
|
})
|
||||||
|
|
||||||
const gasPrice = manualGasPrice ? web3.utils.toWei(manualGasPrice, 'gwei') : await calculateGasPrice()
|
const gasPrice = manualGasPrice ? web3.utils.toWei(manualGasPrice, 'gwei') : await calculateGasPrice()
|
||||||
const gasPriceFormatted = web3.utils.fromWei(gasPrice, 'gwei')
|
const gasPriceFormatted = web3.utils.fromWei(gasPrice, 'gwei')
|
||||||
const estimatedGasCosts = gasEstimation * parseInt(gasPrice, 10)
|
const estimatedGasCosts = gasEstimation * parseInt(gasPrice, 10)
|
||||||
const gasCost = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals)
|
const gasCost = fromTokenUnit(estimatedGasCosts, nativeCoin.decimals)
|
||||||
const gasCostFormatted = formatAmount(gasCost)
|
const gasCostFormatted = formatAmount(gasCost)
|
||||||
const gasLimit = (gasEstimation * 2 + MINIMUM_TRANSACTION_GAS).toString()
|
const gasLimit = (gasEstimation * 2).toString()
|
||||||
|
|
||||||
let txEstimationExecutionStatus = EstimationStatus.SUCCESS
|
let txEstimationExecutionStatus = EstimationStatus.SUCCESS
|
||||||
|
|
||||||
|
@ -257,7 +259,7 @@ export const useEstimateTransactionGas = ({
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(error.message)
|
console.warn(error.message)
|
||||||
// We put a fixed the amount of gas to let the user try to execute the tx, but it's not accurate so it will probably fail
|
// We put a fixed the amount of gas to let the user try to execute the tx, but it's not accurate so it will probably fail
|
||||||
const gasEstimation = MINIMUM_TRANSACTION_GAS
|
const gasEstimation = MINIMUM_TRANSACTION_GAS + (threshold || 1) * GAS_REQUIRED_PER_SIGNATURE
|
||||||
const gasCost = fromTokenUnit(gasEstimation, nativeCoin.decimals)
|
const gasCost = fromTokenUnit(gasEstimation, nativeCoin.decimals)
|
||||||
const gasCostFormatted = formatAmount(gasCost)
|
const gasCostFormatted = formatAmount(gasCost)
|
||||||
setGasEstimation({
|
setGasEstimation({
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { BigNumber } from 'bignumber.js'
|
import { BigNumber } from 'bignumber.js'
|
||||||
|
|
||||||
import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts'
|
import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts'
|
||||||
import { calculateGasOf, EMPTY_DATA } from 'src/logic/wallets/ethTransactions'
|
import { calculateGasOf, EMPTY_DATA } from 'src/logic/wallets/ethTransactions'
|
||||||
import { getWeb3, web3ReadOnly } from 'src/logic/wallets/getWeb3'
|
import { getWeb3, web3ReadOnly } from 'src/logic/wallets/getWeb3'
|
||||||
|
@ -12,6 +13,8 @@ import { sameString } from 'src/utils/strings'
|
||||||
|
|
||||||
// 21000 - additional gas costs (e.g. base tx costs, transfer costs)
|
// 21000 - additional gas costs (e.g. base tx costs, transfer costs)
|
||||||
export const MINIMUM_TRANSACTION_GAS = 21000
|
export const MINIMUM_TRANSACTION_GAS = 21000
|
||||||
|
// Estimation of gas required for each signature (aproximately 7800, roundup to 8000)
|
||||||
|
export const GAS_REQUIRED_PER_SIGNATURE = 8000
|
||||||
|
|
||||||
// Receives the response data of the safe method requiredTxGas() and parses it to get the gas amount
|
// Receives the response data of the safe method requiredTxGas() and parses it to get the gas amount
|
||||||
const parseRequiredTxGasResponse = (data: string): number => {
|
const parseRequiredTxGasResponse = (data: string): number => {
|
||||||
|
@ -177,9 +180,10 @@ const calculateMinimumGasForTransaction = async (
|
||||||
estimateData: string,
|
estimateData: string,
|
||||||
txGasEstimation: number,
|
txGasEstimation: number,
|
||||||
dataGasEstimation: number,
|
dataGasEstimation: number,
|
||||||
|
fixedGasCosts: number,
|
||||||
): Promise<number> => {
|
): Promise<number> => {
|
||||||
for (const additionalGas of additionalGasBatches) {
|
for (const additionalGas of additionalGasBatches) {
|
||||||
const amountOfGasToTryTx = txGasEstimation + dataGasEstimation + additionalGas
|
const amountOfGasToTryTx = txGasEstimation + dataGasEstimation + fixedGasCosts + additionalGas
|
||||||
console.info(`Estimating transaction creation with gas amount: ${amountOfGasToTryTx}`)
|
console.info(`Estimating transaction creation with gas amount: ${amountOfGasToTryTx}`)
|
||||||
try {
|
try {
|
||||||
const estimation = await getGasEstimationTxResponse({
|
const estimation = await getGasEstimationTxResponse({
|
||||||
|
@ -224,7 +228,13 @@ export const estimateGasForTransactionCreation = async (
|
||||||
return gasEstimationResponse
|
return gasEstimationResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const threshold = await safeInstance.methods.getThreshold().call()
|
||||||
|
|
||||||
const dataGasEstimation = parseRequiredTxGasResponse(estimateData)
|
const dataGasEstimation = parseRequiredTxGasResponse(estimateData)
|
||||||
|
// We add the minimum required gas for a transaction
|
||||||
|
// TODO: This fix will be more accurate when we have a service for estimation.
|
||||||
|
// This fix takes the safe threshold and multiplies it by GAS_REQUIRED_PER_SIGNATURE.
|
||||||
|
const fixedGasCosts = MINIMUM_TRANSACTION_GAS + (Number(threshold) || 1) * GAS_REQUIRED_PER_SIGNATURE
|
||||||
const additionalGasBatches = [0, 10000, 20000, 40000, 80000, 160000, 320000, 640000, 1280000, 2560000, 5120000]
|
const additionalGasBatches = [0, 10000, 20000, 40000, 80000, 160000, 320000, 640000, 1280000, 2560000, 5120000]
|
||||||
|
|
||||||
return await calculateMinimumGasForTransaction(
|
return await calculateMinimumGasForTransaction(
|
||||||
|
@ -233,6 +243,7 @@ export const estimateGasForTransactionCreation = async (
|
||||||
estimateData,
|
estimateData,
|
||||||
gasEstimationResponse,
|
gasEstimationResponse,
|
||||||
dataGasEstimation,
|
dataGasEstimation,
|
||||||
|
fixedGasCosts,
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.info('Error calculating tx gas estimation', error.message)
|
console.info('Error calculating tx gas estimation', error.message)
|
||||||
|
|
Loading…
Reference in New Issue