From d37b71fe8ab707f756c12f6ebb188826fbc4a294 Mon Sep 17 00:00:00 2001
From: Silas Lenihan <sjl@lenihan.net>
Date: Mon, 25 Mar 2024 13:56:39 -0400
Subject: [PATCH] Extracted fee limit multiplier out of indivudal gas
 estimators, into WrappedEvmEstimator

---
 core/chains/evm/gas/arbitrum_estimator.go     |  4 +-
 .../chains/evm/gas/arbitrum_estimator_test.go |  4 +-
 core/chains/evm/gas/helpers_test.go           |  4 ++
 core/chains/evm/gas/models.go                 | 11 ++++-
 core/chains/evm/gas/models_test.go            | 42 +++++++++++--------
 .../evm/gas/suggested_price_estimator.go      | 12 +-----
 .../evm/gas/suggested_price_estimator_test.go | 12 +++---
 core/chains/evm/txmgr/broadcaster_test.go     |  7 ++--
 core/chains/evm/txmgr/confirmer_test.go       |  8 ++--
 9 files changed, 56 insertions(+), 48 deletions(-)

diff --git a/core/chains/evm/gas/arbitrum_estimator.go b/core/chains/evm/gas/arbitrum_estimator.go
index 050fb425a59..52b091e92d9 100644
--- a/core/chains/evm/gas/arbitrum_estimator.go
+++ b/core/chains/evm/gas/arbitrum_estimator.go
@@ -17,7 +17,6 @@ import (
 	"github.com/smartcontractkit/chainlink-common/pkg/services"
 	"github.com/smartcontractkit/chainlink-common/pkg/utils"
 
-	commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
 	feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
 	"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
 	evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
@@ -136,8 +135,7 @@ func (a *arbitrumEstimator) GetLegacyGas(ctx context.Context, calldata []byte, l
 			}
 		}
 		perL2Tx, perL1CalldataUnit := a.getPricesInArbGas()
-		originalGasLimit := l2GasLimit + uint64(perL2Tx) + uint64(len(calldata))*uint64(perL1CalldataUnit)
-		chainSpecificGasLimit, err = commonfee.ApplyMultiplier(originalGasLimit, a.cfg.LimitMultiplier())
+		chainSpecificGasLimit = l2GasLimit + uint64(perL2Tx) + uint64(len(calldata))*uint64(perL1CalldataUnit)
 		if err != nil {
 			return
 		}
diff --git a/core/chains/evm/gas/arbitrum_estimator_test.go b/core/chains/evm/gas/arbitrum_estimator_test.go
index 2d19903b243..a26346d61ae 100644
--- a/core/chains/evm/gas/arbitrum_estimator_test.go
+++ b/core/chains/evm/gas/arbitrum_estimator_test.go
@@ -90,7 +90,7 @@ func TestArbitrumEstimator(t *testing.T) {
 		require.NoError(t, err)
 		// Expected price for a standard l2_suggested_estimator would be 42, but we add a fixed gasPriceBufferPercentage.
 		assert.Equal(t, assets.NewWeiI(42).AddPercentage(gasPriceBufferPercentage), gasPrice)
-		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), chainSpecificGasLimit)
+		assert.Equal(t, gasLimit, chainSpecificGasLimit)
 	})
 
 	t.Run("gas price is lower than user specified max gas price", func(t *testing.T) {
@@ -222,7 +222,7 @@ func TestArbitrumEstimator(t *testing.T) {
 		require.NotNil(t, gasPrice)
 		// Again, a normal l2_suggested_estimator would return 42, but arbitrum_estimator adds a buffer.
 		assert.Equal(t, "63 wei", gasPrice.String())
-		assert.Equal(t, uint64(float32(expLimit)*limitMultiplier), chainSpecificGasLimit, "expected %d but got %d", expLimit, chainSpecificGasLimit)
+		assert.Equal(t, expLimit, chainSpecificGasLimit, "expected %d but got %d", expLimit, chainSpecificGasLimit)
 	})
 
 	t.Run("limit exceeds max", func(t *testing.T) {
diff --git a/core/chains/evm/gas/helpers_test.go b/core/chains/evm/gas/helpers_test.go
index 908674bbeeb..420c5060a90 100644
--- a/core/chains/evm/gas/helpers_test.go
+++ b/core/chains/evm/gas/helpers_test.go
@@ -147,6 +147,10 @@ type MockGasEstimatorConfig struct {
 	ModeF               string
 }
 
+func NewMockGasConfig() *MockGasEstimatorConfig {
+	return &MockGasEstimatorConfig{}
+}
+
 func (m *MockGasEstimatorConfig) BumpPercent() uint16 {
 	return m.BumpPercentF
 }
diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go
index ae041615f53..8d1de9fe599 100644
--- a/core/chains/evm/gas/models.go
+++ b/core/chains/evm/gas/models.go
@@ -95,7 +95,7 @@ func NewEstimator(lggr logger.Logger, ethClient evmclient.Client, cfg Config, ge
 			return NewFixedPriceEstimator(geCfg, bh, lggr)
 		}
 	}
-	return NewWrappedEvmEstimator(lggr, newEstimator, df, l1Oracle)
+	return NewWrappedEvmEstimator(lggr, newEstimator, df, l1Oracle, geCfg)
 }
 
 // DynamicFee encompasses both FeeCap and TipCap for EIP1559 transactions
@@ -166,17 +166,19 @@ type WrappedEvmEstimator struct {
 	EvmEstimator
 	EIP1559Enabled bool
 	l1Oracle       rollups.L1Oracle
+	geCfg          GasEstimatorConfig
 }
 
 var _ EvmFeeEstimator = (*WrappedEvmEstimator)(nil)
 
-func NewWrappedEvmEstimator(lggr logger.Logger, newEstimator func(logger.Logger) EvmEstimator, eip1559Enabled bool, l1Oracle rollups.L1Oracle) EvmFeeEstimator {
+func NewWrappedEvmEstimator(lggr logger.Logger, newEstimator func(logger.Logger) EvmEstimator, eip1559Enabled bool, l1Oracle rollups.L1Oracle, geCfg GasEstimatorConfig) EvmFeeEstimator {
 	lggr = logger.Named(lggr, "WrappedEvmEstimator")
 	return &WrappedEvmEstimator{
 		lggr:           lggr,
 		EvmEstimator:   newEstimator(lggr),
 		EIP1559Enabled: eip1559Enabled,
 		l1Oracle:       l1Oracle,
+		geCfg:          geCfg,
 	}
 }
 
@@ -246,6 +248,7 @@ func (e *WrappedEvmEstimator) GetFee(ctx context.Context, calldata []byte, feeLi
 	if e.EIP1559Enabled {
 		var dynamicFee DynamicFee
 		dynamicFee, chainSpecificFeeLimit, err = e.EvmEstimator.GetDynamicFee(ctx, feeLimit, maxFeePrice)
+		chainSpecificFeeLimit = uint64(float32(chainSpecificFeeLimit) * e.geCfg.LimitMultiplier())
 		fee.DynamicFeeCap = dynamicFee.FeeCap
 		fee.DynamicTipCap = dynamicFee.TipCap
 		return
@@ -253,6 +256,8 @@ func (e *WrappedEvmEstimator) GetFee(ctx context.Context, calldata []byte, feeLi
 
 	// get legacy fee
 	fee.Legacy, chainSpecificFeeLimit, err = e.EvmEstimator.GetLegacyGas(ctx, calldata, feeLimit, maxFeePrice, opts...)
+	chainSpecificFeeLimit = uint64(float32(chainSpecificFeeLimit) * e.geCfg.LimitMultiplier())
+
 	return
 }
 
@@ -290,6 +295,7 @@ func (e *WrappedEvmEstimator) BumpFee(ctx context.Context, originalFee EvmFee, f
 				TipCap: originalFee.DynamicTipCap,
 				FeeCap: originalFee.DynamicFeeCap,
 			}, feeLimit, maxFeePrice, attempts)
+		chainSpecificFeeLimit = uint64(float32(chainSpecificFeeLimit) * e.geCfg.LimitMultiplier())
 		bumpedFee.DynamicFeeCap = bumpedDynamic.FeeCap
 		bumpedFee.DynamicTipCap = bumpedDynamic.TipCap
 		return
@@ -297,6 +303,7 @@ func (e *WrappedEvmEstimator) BumpFee(ctx context.Context, originalFee EvmFee, f
 
 	// bump legacy fee
 	bumpedFee.Legacy, chainSpecificFeeLimit, err = e.EvmEstimator.BumpLegacyGas(ctx, originalFee.Legacy, feeLimit, maxFeePrice, attempts)
+	chainSpecificFeeLimit = uint64(float32(chainSpecificFeeLimit) * e.geCfg.LimitMultiplier())
 	return
 }
 
diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go
index 76666143189..debce987fe5 100644
--- a/core/chains/evm/gas/models_test.go
+++ b/core/chains/evm/gas/models_test.go
@@ -28,6 +28,8 @@ func TestWrappedEvmEstimator(t *testing.T) {
 		FeeCap: assets.NewWeiI(20),
 		TipCap: assets.NewWeiI(1),
 	}
+	limitMultiplier := float32(1.5)
+
 	est := mocks.NewEvmEstimator(t)
 	est.On("GetDynamicFee", mock.Anything, mock.Anything, mock.Anything).
 		Return(dynamicFee, gasLimit, nil).Twice()
@@ -38,6 +40,8 @@ func TestWrappedEvmEstimator(t *testing.T) {
 	est.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
 		Return(legacyFee, gasLimit, nil).Once()
 	getRootEst := func(logger.Logger) gas.EvmEstimator { return est }
+	geCfg := gas.NewMockGasConfig()
+	geCfg.LimitMultiplierF = limitMultiplier
 
 	mockEstimatorName := "WrappedEvmEstimator"
 	mockEvmEstimatorName := "WrappedEvmEstimator.MockEstimator"
@@ -46,13 +50,13 @@ func TestWrappedEvmEstimator(t *testing.T) {
 	t.Run("L1Oracle", func(t *testing.T) {
 		lggr := logger.Test(t)
 		// expect nil
-		estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, false, nil)
+		estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, false, nil, nil)
 		l1Oracle := estimator.L1Oracle()
 		assert.Nil(t, l1Oracle)
 
 		// expect l1Oracle
 		oracle := rollupMocks.NewL1Oracle(t)
-		estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, false, oracle)
+		estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, false, oracle, geCfg)
 		l1Oracle = estimator.L1Oracle()
 		assert.Equal(t, oracle, l1Oracle)
 	})
@@ -62,20 +66,20 @@ func TestWrappedEvmEstimator(t *testing.T) {
 		lggr := logger.Test(t)
 		// expect legacy fee data
 		dynamicFees := false
-		estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil)
+		estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil, geCfg)
 		fee, max, err := estimator.GetFee(ctx, nil, 0, nil)
 		require.NoError(t, err)
-		assert.Equal(t, gasLimit, max)
+		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max)
 		assert.True(t, legacyFee.Equal(fee.Legacy))
 		assert.Nil(t, fee.DynamicTipCap)
 		assert.Nil(t, fee.DynamicFeeCap)
 
 		// expect dynamic fee data
 		dynamicFees = true
-		estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil)
+		estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil, geCfg)
 		fee, max, err = estimator.GetFee(ctx, nil, 0, nil)
 		require.NoError(t, err)
-		assert.Equal(t, gasLimit, max)
+		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max)
 		assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap))
 		assert.True(t, dynamicFee.TipCap.Equal(fee.DynamicTipCap))
 		assert.Nil(t, fee.Legacy)
@@ -85,12 +89,12 @@ func TestWrappedEvmEstimator(t *testing.T) {
 	t.Run("BumpFee", func(t *testing.T) {
 		lggr := logger.Test(t)
 		dynamicFees := false
-		estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil)
+		estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil, geCfg)
 
 		// expect legacy fee data
 		fee, max, err := estimator.BumpFee(ctx, gas.EvmFee{Legacy: assets.NewWeiI(0)}, 0, nil, nil)
 		require.NoError(t, err)
-		assert.Equal(t, gasLimit, max)
+		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max)
 		assert.True(t, legacyFee.Equal(fee.Legacy))
 		assert.Nil(t, fee.DynamicTipCap)
 		assert.Nil(t, fee.DynamicFeeCap)
@@ -101,7 +105,7 @@ func TestWrappedEvmEstimator(t *testing.T) {
 			DynamicTipCap: assets.NewWeiI(0),
 		}, 0, nil, nil)
 		require.NoError(t, err)
-		assert.Equal(t, gasLimit, max)
+		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max)
 		assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap))
 		assert.True(t, dynamicFee.TipCap.Equal(fee.DynamicTipCap))
 		assert.Nil(t, fee.Legacy)
@@ -123,18 +127,20 @@ func TestWrappedEvmEstimator(t *testing.T) {
 
 		// expect legacy fee data
 		dynamicFees := false
-		estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil)
+		estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil, geCfg)
 		total, err := estimator.GetMaxCost(ctx, val, nil, gasLimit, nil)
 		require.NoError(t, err)
 		fee := new(big.Int).Mul(legacyFee.ToInt(), big.NewInt(int64(gasLimit)))
+		fee, _ = new(big.Float).Mul(new(big.Float).SetInt(fee), big.NewFloat(float64(limitMultiplier))).Int(nil)
 		assert.Equal(t, new(big.Int).Add(val.ToInt(), fee), total)
 
 		// expect dynamic fee data
 		dynamicFees = true
-		estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil)
+		estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil, geCfg)
 		total, err = estimator.GetMaxCost(ctx, val, nil, gasLimit, nil)
 		require.NoError(t, err)
 		fee = new(big.Int).Mul(dynamicFee.FeeCap.ToInt(), big.NewInt(int64(gasLimit)))
+		fee, _ = new(big.Float).Mul(new(big.Float).SetInt(fee), big.NewFloat(float64(limitMultiplier))).Int(nil)
 		assert.Equal(t, new(big.Int).Add(val.ToInt(), fee), total)
 	})
 
@@ -147,7 +153,7 @@ func TestWrappedEvmEstimator(t *testing.T) {
 
 		estimator := gas.NewWrappedEvmEstimator(lggr, func(logger.Logger) gas.EvmEstimator {
 			return evmEstimator
-		}, false, oracle)
+		}, false, oracle, geCfg)
 
 		require.Equal(t, mockEstimatorName, estimator.Name())
 		require.Equal(t, mockEvmEstimatorName, evmEstimator.Name())
@@ -164,13 +170,13 @@ func TestWrappedEvmEstimator(t *testing.T) {
 		oracle.On("Close").Return(nil).Once()
 		getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator }
 
-		estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil)
+		estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil, geCfg)
 		err := estimator.Start(ctx)
 		require.NoError(t, err)
 		err = estimator.Close()
 		require.NoError(t, err)
 
-		estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle)
+		estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle, geCfg)
 		err = estimator.Start(ctx)
 		require.NoError(t, err)
 		err = estimator.Close()
@@ -186,11 +192,11 @@ func TestWrappedEvmEstimator(t *testing.T) {
 		oracle.On("Ready").Return(nil).Once()
 		getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator }
 
-		estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil)
+		estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil, geCfg)
 		err := estimator.Ready()
 		require.NoError(t, err)
 
-		estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle)
+		estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle, geCfg)
 		err = estimator.Ready()
 		require.NoError(t, err)
 	})
@@ -209,13 +215,13 @@ func TestWrappedEvmEstimator(t *testing.T) {
 		oracle.On("HealthReport").Return(map[string]error{oracleKey: oracleError}).Once()
 		getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator }
 
-		estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil)
+		estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil, geCfg)
 		report := estimator.HealthReport()
 		require.True(t, pkgerrors.Is(report[evmEstimatorKey], evmEstimatorError))
 		require.Nil(t, report[oracleKey])
 		require.NotNil(t, report[mockEstimatorName])
 
-		estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle)
+		estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle, geCfg)
 		report = estimator.HealthReport()
 		require.True(t, pkgerrors.Is(report[evmEstimatorKey], evmEstimatorError))
 		require.True(t, pkgerrors.Is(report[oracleKey], oracleError))
diff --git a/core/chains/evm/gas/suggested_price_estimator.go b/core/chains/evm/gas/suggested_price_estimator.go
index 53d71107731..b54a9c033da 100644
--- a/core/chains/evm/gas/suggested_price_estimator.go
+++ b/core/chains/evm/gas/suggested_price_estimator.go
@@ -16,7 +16,6 @@ import (
 	bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math"
 
 	"github.com/smartcontractkit/chainlink/v2/common/fee"
-	commonfee "github.com/smartcontractkit/chainlink/v2/common/fee"
 	feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types"
 	"github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"
 	evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client"
@@ -167,10 +166,7 @@ func (*SuggestedPriceEstimator) BumpDynamicFee(_ context.Context, _ DynamicFee,
 }
 
 func (o *SuggestedPriceEstimator) GetLegacyGas(ctx context.Context, _ []byte, GasLimit uint64, maxGasPriceWei *assets.Wei, opts ...feetypes.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) {
-	chainSpecificGasLimit, err = commonfee.ApplyMultiplier(GasLimit, o.cfg.LimitMultiplier())
-	if err != nil {
-		return
-	}
+	chainSpecificGasLimit = GasLimit
 	ok := o.IfStarted(func() {
 		if slices.Contains(opts, feetypes.OptForceRefetch) {
 			err = o.forceRefresh(ctx)
@@ -198,10 +194,7 @@ func (o *SuggestedPriceEstimator) GetLegacyGas(ctx context.Context, _ []byte, Ga
 // The only reason bumping logic would be called on the SuggestedPriceEstimator is if there was a significant price spike
 // between the last price update and when the tx was submitted. Refreshing the price helps ensure the latest market changes are accounted for.
 func (o *SuggestedPriceEstimator) BumpLegacyGas(ctx context.Context, originalFee *assets.Wei, feeLimit uint64, maxGasPriceWei *assets.Wei, _ []EvmPriorAttempt) (newGasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) {
-	chainSpecificGasLimit, err = commonfee.ApplyMultiplier(feeLimit, o.cfg.LimitMultiplier())
-	if err != nil {
-		return
-	}
+	chainSpecificGasLimit = feeLimit
 	ok := o.IfStarted(func() {
 		// Immediately return error if original fee is greater than or equal to the max gas price
 		// Prevents a loop of resubmitting the attempt with the max gas price
@@ -231,7 +224,6 @@ func (o *SuggestedPriceEstimator) BumpLegacyGas(ctx context.Context, originalFee
 	// If the new suggested price is less than or equal to the max and the buffer puts the new price over the max, return the max price instead
 	// The buffer is added on top of the suggested price during bumping as just a precaution. It is better to resubmit the transaction with the max gas price instead of erroring.
 	newGasPrice = assets.NewWei(bigmath.Min(bufferedPrice, maxGasPriceWei.ToInt()))
-
 	// Return the original price if the refreshed price with the buffer is lower to ensure the bumped gas price is always equal or higher to the previous attempt
 	if originalFee != nil && originalFee.Cmp(newGasPrice) > 0 {
 		return originalFee, chainSpecificGasLimit, nil
diff --git a/core/chains/evm/gas/suggested_price_estimator_test.go b/core/chains/evm/gas/suggested_price_estimator_test.go
index f37249f9d0d..a76563c61c5 100644
--- a/core/chains/evm/gas/suggested_price_estimator_test.go
+++ b/core/chains/evm/gas/suggested_price_estimator_test.go
@@ -48,7 +48,7 @@ func TestSuggestedPriceEstimator(t *testing.T) {
 		gasPrice, chainSpecificGasLimit, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice)
 		require.NoError(t, err)
 		assert.Equal(t, assets.NewWeiI(42), gasPrice)
-		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), chainSpecificGasLimit)
+		assert.Equal(t, gasLimit, chainSpecificGasLimit)
 	})
 
 	t.Run("gas price is lower than user specified max gas price", func(t *testing.T) {
@@ -133,7 +133,7 @@ func TestSuggestedPriceEstimator(t *testing.T) {
 		gasPrice, chainSpecificGasLimit, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(10), gasLimit, maxGasPrice, nil)
 		require.NoError(t, err)
 		assert.Equal(t, assets.NewWeiI(44), gasPrice)
-		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), chainSpecificGasLimit)
+		assert.Equal(t, gasLimit, chainSpecificGasLimit)
 	})
 
 	t.Run("calling BumpLegacyGas on started estimator returns new price buffered with bumpMin", func(t *testing.T) {
@@ -149,7 +149,7 @@ func TestSuggestedPriceEstimator(t *testing.T) {
 		gasPrice, chainSpecificGasLimit, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(10), gasLimit, maxGasPrice, nil)
 		require.NoError(t, err)
 		assert.Equal(t, assets.NewWeiI(41), gasPrice)
-		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), chainSpecificGasLimit)
+		assert.Equal(t, gasLimit, chainSpecificGasLimit)
 	})
 
 	t.Run("calling BumpLegacyGas on started estimator returns original price when lower than previous", func(t *testing.T) {
@@ -164,7 +164,7 @@ func TestSuggestedPriceEstimator(t *testing.T) {
 		gasPrice, chainSpecificGasLimit, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(10), gasLimit, maxGasPrice, nil)
 		require.NoError(t, err)
 		assert.Equal(t, assets.NewWeiI(10), gasPrice)
-		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), chainSpecificGasLimit)
+		assert.Equal(t, gasLimit, chainSpecificGasLimit)
 	})
 
 	t.Run("calling BumpLegacyGas on started estimator returns error, suggested gas price is higher than max gas price", func(t *testing.T) {
@@ -197,7 +197,7 @@ func TestSuggestedPriceEstimator(t *testing.T) {
 		gasPrice, chainSpecificGasLimit, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(10), gasLimit, assets.NewWeiI(40), nil)
 		require.NoError(t, err)
 		assert.Equal(t, assets.NewWeiI(40), gasPrice)
-		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), chainSpecificGasLimit)
+		assert.Equal(t, gasLimit, chainSpecificGasLimit)
 	})
 
 	t.Run("calling BumpLegacyGas on started estimator if initial call failed returns error", func(t *testing.T) {
@@ -227,6 +227,6 @@ func TestSuggestedPriceEstimator(t *testing.T) {
 		gasPrice, chainSpecificGasLimit, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(10), gasLimit, maxGasPrice, nil)
 		require.NoError(t, err)
 		assert.Equal(t, assets.NewWeiI(44), gasPrice)
-		assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), chainSpecificGasLimit)
+		assert.Equal(t, gasLimit, chainSpecificGasLimit)
 	})
 }
diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go
index 9547f7ee00e..d9e9364fdf0 100644
--- a/core/chains/evm/txmgr/broadcaster_test.go
+++ b/core/chains/evm/txmgr/broadcaster_test.go
@@ -63,9 +63,10 @@ func NewTestEthBroadcaster(
 
 	lggr := logger.Test(t)
 	ge := config.EVM().GasEstimator()
+
 	estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator {
 		return gas.NewFixedPriceEstimator(config.EVM().GasEstimator(), ge.BlockHistory(), lggr)
-	}, ge.EIP1559DynamicFees(), nil)
+	}, ge.EIP1559DynamicFees(), nil, ge)
 	txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, keyStore, estimator)
 	ethBroadcaster := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(config.EVM().GasEstimator()), config.EVM().Transactions(), config.Database().Listener(), keyStore, txBuilder, nonceTracker, lggr, checkerFactory, nonceAutoSync)
 
@@ -1152,7 +1153,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) {
 				t.Run("callback set by ctor", func(t *testing.T) {
 					estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator {
 						return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), evmcfg.EVM().GasEstimator().BlockHistory(), lggr)
-					}, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil)
+					}, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil, evmcfg.EVM().GasEstimator())
 					txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator)
 					localNextNonce = getLocalNextNonce(t, nonceTracker, fromAddress)
 					eb2 := txmgr.NewEvmBroadcaster(txStore, txmClient, txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), evmcfg.Database().Listener(), ethKeyStore, txBuilder, lggr, &testCheckerFactory{}, false)
@@ -1738,7 +1739,7 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) {
 
 	estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator {
 		return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), evmcfg.EVM().GasEstimator().BlockHistory(), lggr)
-	}, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil)
+	}, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil, evmcfg.EVM().GasEstimator())
 	checkerFactory := &testCheckerFactory{}
 
 	ge := evmcfg.EVM().GasEstimator()
diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go
index d00b2d9ae3d..8868a769f68 100644
--- a/core/chains/evm/txmgr/confirmer_test.go
+++ b/core/chains/evm/txmgr/confirmer_test.go
@@ -125,7 +125,7 @@ func TestEthConfirmer_Lifecycle(t *testing.T) {
 	newEst := func(logger.Logger) gas.EvmEstimator { return estimator }
 	lggr := logger.Test(t)
 	ge := config.EVM().GasEstimator()
-	feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil)
+	feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil, ge)
 	txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, feeEstimator)
 	ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), config.Database(), ethKeyStore, txBuilder, lggr)
 	ctx := testutils.Context(t)
@@ -1645,7 +1645,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing
 		newEst := func(logger.Logger) gas.EvmEstimator { return estimator }
 		estimator.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, uint64(0), pkgerrors.Wrapf(commonfee.ErrConnectivity, "transaction..."))
 		ge := ccfg.EVM().GasEstimator()
-		feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil)
+		feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil, ge)
 		txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator)
 		addresses := []gethCommon.Address{fromAddress}
 		kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe()
@@ -1693,7 +1693,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing
 		newEst := func(logger.Logger) gas.EvmEstimator { return estimator }
 		// Create confirmer with necessary state
 		ge := ccfg.EVM().GasEstimator()
-		feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil)
+		feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil, ge)
 		txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator)
 		addresses := []gethCommon.Address{fromAddress}
 		kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe()
@@ -3132,7 +3132,7 @@ func newEthConfirmer(t testing.TB, txStore txmgr.EvmTxStore, ethClient client.Cl
 	ge := config.EVM().GasEstimator()
 	estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator {
 		return gas.NewFixedPriceEstimator(ge, ge.BlockHistory(), lggr)
-	}, ge.EIP1559DynamicFees(), nil)
+	}, ge.EIP1559DynamicFees(), nil, ge)
 	txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ks, estimator)
 	ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), config.Database(), ks, txBuilder, lggr)
 	ec.SetResumeCallback(fn)