@@ -51,11 +51,8 @@ func (c *evmTxAttemptBuilder) NewTxAttempt(ctx context.Context, etx Tx, lggr log
5151// NewTxAttemptWithType builds a new attempt with a new fee estimation where the txType can be specified by the caller
5252// used for L2 re-estimation on broadcasting (note EIP1559 must be disabled otherwise this will fail with mismatched fees + tx type)
5353func (c * evmTxAttemptBuilder ) NewTxAttemptWithType (ctx context.Context , etx Tx , lggr logger.Logger , txType int , opts ... fees.Opt ) (attempt TxAttempt , fee gas.EvmFee , feeLimit uint64 , retryable bool , err error ) {
54- keySpecificMaxGasPriceWei := c .feeConfig .PriceMaxKey (etx .FromAddress )
55- if etx .MaxGasPrice != nil {
56- keySpecificMaxGasPriceWei = assets .NewWei (etx .MaxGasPrice ) // give prefence to max gas price from tx request
57- }
58- fee , feeLimit , err = c .EvmFeeEstimator .GetFee (ctx , etx .EncodedPayload , etx .FeeLimit , keySpecificMaxGasPriceWei , & etx .FromAddress , & etx .ToAddress , opts ... )
54+ maxGasPrice := c .getEffectiveMaxGasPrice (etx )
55+ fee , feeLimit , err = c .EvmFeeEstimator .GetFee (ctx , etx .EncodedPayload , etx .FeeLimit , maxGasPrice , & etx .FromAddress , & etx .ToAddress , opts ... )
5956 if err != nil {
6057 return attempt , fee , feeLimit , true , pkgerrors .Wrap (err , "failed to get fee" ) // estimator errors are retryable
6158 }
@@ -67,9 +64,9 @@ func (c *evmTxAttemptBuilder) NewTxAttemptWithType(ctx context.Context, etx Tx,
6764// NewBumpTxAttempt builds a new attempt with a bumped fee - based on the previous attempt tx type
6865// used in the txm broadcaster + confirmer when tx ix rejected for too low fee or is not included in a timely manner
6966func (c * evmTxAttemptBuilder ) NewBumpTxAttempt (ctx context.Context , etx Tx , previousAttempt TxAttempt , priorAttempts []TxAttempt , lggr logger.Logger ) (attempt TxAttempt , bumpedFee gas.EvmFee , bumpedFeeLimit uint64 , retryable bool , err error ) {
70- keySpecificMaxGasPriceWei := c .feeConfig . PriceMaxKey (etx . FromAddress )
67+ maxGasPrice := c .getEffectiveMaxGasPrice (etx )
7168 // Use the fee limit from the previous attempt to maintain limits adjusted for 2D fees or by estimation
72- bumpedFee , bumpedFeeLimit , err = c .EvmFeeEstimator .BumpFee (ctx , previousAttempt .TxFee , previousAttempt .ChainSpecificFeeLimit , keySpecificMaxGasPriceWei , newEvmPriorAttempts (priorAttempts ))
69+ bumpedFee , bumpedFeeLimit , err = c .EvmFeeEstimator .BumpFee (ctx , previousAttempt .TxFee , previousAttempt .ChainSpecificFeeLimit , maxGasPrice , newEvmPriorAttempts (priorAttempts ))
7370 if err != nil {
7471 return attempt , bumpedFee , bumpedFeeLimit , true , pkgerrors .Wrap (err , "failed to bump fee" ) // estimator errors are retryable
7572 }
@@ -92,8 +89,8 @@ func (c *evmTxAttemptBuilder) NewPurgeTxAttempt(ctx context.Context, etx Tx, lgg
9289 gasLimit := c .feeConfig .LimitDefault ()
9390 // Transactions being purged will always have a previous attempt since it had to have been broadcasted before at least once
9491 previousAttempt := etx .TxAttempts [0 ]
95- keySpecificMaxGasPriceWei := c .feeConfig . PriceMaxKey (etx . FromAddress )
96- bumpedFee , _ , err := c .EvmFeeEstimator .BumpFee (ctx , previousAttempt .TxFee , etx .FeeLimit , keySpecificMaxGasPriceWei , newEvmPriorAttempts (etx .TxAttempts ))
92+ maxGasPrice := c .getEffectiveMaxGasPrice (etx )
93+ bumpedFee , _ , err := c .EvmFeeEstimator .BumpFee (ctx , previousAttempt .TxFee , etx .FeeLimit , maxGasPrice , newEvmPriorAttempts (etx .TxAttempts ))
9794 if err != nil {
9895 return attempt , fmt .Errorf ("failed to bump previous fee to use for the purge attempt: %w" , err )
9996 }
@@ -348,3 +345,19 @@ func newEvmPriorAttempts(attempts []TxAttempt) (prior []gas.EvmPriorAttempt) {
348345 }
349346 return
350347}
348+
349+ // getEffectiveMaxGasPrice returns the effective maximum gas price to use for a transaction.
350+ // It takes the minimum of the key-specific configured max and the transaction's MaxGasPrice (if set).
351+ // This ensures that per-transaction spend limits from billing are respected while still honoring
352+ // the node's configured maximum gas price.
353+ func (c * evmTxAttemptBuilder ) getEffectiveMaxGasPrice (etx Tx ) * assets.Wei {
354+ keySpecificMaxGasPriceWei := c .feeConfig .PriceMaxKey (etx .FromAddress )
355+ if etx .MaxGasPrice != nil {
356+ txMaxGasPrice := assets .NewWei (etx .MaxGasPrice )
357+ // Only use tx request's MaxGasPrice if it's more restrictive (lower) than the key-specific max
358+ if txMaxGasPrice .Cmp (keySpecificMaxGasPriceWei ) < 0 {
359+ return txMaxGasPrice
360+ }
361+ }
362+ return keySpecificMaxGasPriceWei
363+ }
0 commit comments