diff --git a/src/providers/eth-estimate-gas-provider.ts b/src/providers/eth-estimate-gas-provider.ts index 0fdc24bf5..8a6cf545e 100644 --- a/src/providers/eth-estimate-gas-provider.ts +++ b/src/providers/eth-estimate-gas-provider.ts @@ -12,6 +12,7 @@ import { BEACON_CHAIN_DEPOSIT_ADDRESS, log } from '../util'; import { calculateGasUsed, initSwapRouteFromExisting, + logGasEstimationVsSimulationMetrics, } from '../util/gas-factory-helpers'; import { IPortionProvider } from './portion-provider'; @@ -125,6 +126,9 @@ export class EthEstimateGasSimulator extends Simulator { this.provider, providerConfig ); + + logGasEstimationVsSimulationMetrics(route, estimatedGasUsed, this.chainId); + return { ...initSwapRouteFromExisting( route, diff --git a/src/providers/tenderly-simulation-provider.ts b/src/providers/tenderly-simulation-provider.ts index b78d63dac..b9abee7f8 100644 --- a/src/providers/tenderly-simulation-provider.ts +++ b/src/providers/tenderly-simulation-provider.ts @@ -29,6 +29,7 @@ import { APPROVE_TOKEN_FOR_TRANSFER } from '../util/callData'; import { calculateGasUsed, initSwapRouteFromExisting, + logGasEstimationVsSimulationMetrics, } from '../util/gas-factory-helpers'; import { EthEstimateGasSimulator } from './eth-estimate-gas-provider'; @@ -690,6 +691,9 @@ export class TenderlySimulator extends Simulator { this.provider, providerConfig ); + + logGasEstimationVsSimulationMetrics(swapRoute, estimatedGasUsed, chainId); + return { ...initSwapRouteFromExisting( swapRoute, diff --git a/src/util/gas-factory-helpers.ts b/src/util/gas-factory-helpers.ts index d95e0efa2..7a4869108 100644 --- a/src/util/gas-factory-helpers.ts +++ b/src/util/gas-factory-helpers.ts @@ -19,6 +19,8 @@ import { GasModelProviderConfig, getQuoteThroughNativePool, MethodParameters, + metric, + MetricLoggerUnit, MixedRouteWithValidQuote, RouteWithValidQuote, SwapOptions, @@ -690,3 +692,60 @@ export const calculateL1GasFeesHelper = async ( return calculateArbitrumToL1FeeFromCalldata(data, gasData, chainId); } }; + +// Logs metrics about the diff between original estimatedGasUsed based on heuristics and the simulated gas used. +// This will help us track the quality of our gas estimation quality per chain. +export const logGasEstimationVsSimulationMetrics = ( + route: SwapRoute, + simulationGasUsed: BigNumber, + chainId: ChainId +) => { + try { + // Log the diff between original estimatedGasUsed and the simulated gas used + const estimatedGasUsed = route.estimatedGasUsed.toNumber(); + const simulatedGasUsed = simulationGasUsed.toNumber(); + const diff = estimatedGasUsed - simulatedGasUsed; + const absDiff = Math.abs(estimatedGasUsed - simulatedGasUsed); + const misEstimatePercent = (diff / estimatedGasUsed) * 100; + const misEstimateAbsPercent = (absDiff / estimatedGasUsed) * 100; + + log.info( + { + estimatedGasUsed: estimatedGasUsed, + simulatedGasUsed: simulatedGasUsed, + absDiff: absDiff, + diff: diff, + }, + 'Gas used diff between estimatedGasUsed and simulatedGasUsed' + ); + log.info( + { + misEstimateAbsPercent: misEstimateAbsPercent, + }, + 'Gas used mis-estimate percent' + ); + + metric.putMetric( + `TenderlySimulationGasUsed_AbsDiff_Chain_${chainId}`, + absDiff, + MetricLoggerUnit.Count + ); + metric.putMetric( + `TenderlySimulationGasUsed_MisEstimateAbsPercent_Chain_${chainId}`, + misEstimateAbsPercent, + MetricLoggerUnit.Count + ); + + const label = diff >= 0 ? 'OverEstimate' : 'UnderEstimate'; + metric.putMetric( + `TenderlySimulationGasUsed_${label}Percent_Chain_${chainId}`, + misEstimatePercent, + MetricLoggerUnit.Count + ); + } catch (err) { + log.error( + { err: err }, + 'Failed to log diff between original estimatedGasUsed and the simulated gas used' + ); + } +}; diff --git a/test/unit/providers/simulation-provider.test.ts b/test/unit/providers/simulation-provider.test.ts index 0b201117a..92d09aecf 100644 --- a/test/unit/providers/simulation-provider.test.ts +++ b/test/unit/providers/simulation-provider.test.ts @@ -69,6 +69,7 @@ jest.mock('../../../src/util/gas-factory-helpers', () => ({ quoteGasAdjusted, }; }, + logGasEstimationVsSimulationMetrics: jest.fn(), })); const provider = new JsonRpcProvider();