@@ -61,7 +61,7 @@ pub(crate) struct GasEscalatorMiddlewareInternal<M> {
61
61
62
62
#[ derive( Debug , Clone , PartialEq , Eq ) ]
63
63
pub struct MonitoredTransaction {
64
- hash : TxHash ,
64
+ hash : Option < TxHash > ,
65
65
inner : TypedTransaction ,
66
66
creation_time : Instant ,
67
67
block : Option < BlockId > ,
@@ -205,23 +205,30 @@ where
205
205
) -> Result < PendingTransaction < ' _ , M :: Provider > , GasEscalatorError < M > > {
206
206
let tx = tx. into ( ) ;
207
207
208
- let pending_tx = self
209
- . inner
210
- . send_transaction ( tx. clone ( ) , block)
211
- . await
212
- . map_err ( GasEscalatorError :: MiddlewareError ) ?;
213
-
214
- tracing:: debug!( tx = ?tx, tx_hash = ?pending_tx. tx_hash( ) , "Sent tx, adding to gas escalator watcher" ) ;
215
- // insert the tx in the pending txs
216
- let mut lock = self . txs . lock ( ) . await ;
217
- lock. push ( MonitoredTransaction {
218
- hash : * pending_tx,
219
- inner : tx,
220
- creation_time : Instant :: now ( ) ,
221
- block,
222
- } ) ;
223
-
224
- Ok ( pending_tx)
208
+ match self . inner . send_transaction ( tx. clone ( ) , block) . await {
209
+ Ok ( pending_tx) => {
210
+ tracing:: debug!( tx = ?tx, tx_hash = ?pending_tx. tx_hash( ) , "Sent tx, adding to gas escalator watcher" ) ;
211
+ let mut lock = self . txs . lock ( ) . await ;
212
+ lock. push ( MonitoredTransaction {
213
+ hash : Some ( * pending_tx) ,
214
+ inner : tx,
215
+ creation_time : Instant :: now ( ) ,
216
+ block,
217
+ } ) ;
218
+ Ok ( pending_tx)
219
+ }
220
+ Err ( err) => {
221
+ tracing:: warn!( tx = ?tx, "Failed to send tx, adding to gas escalator watcher regardless" ) ;
222
+ let mut lock = self . txs . lock ( ) . await ;
223
+ lock. push ( MonitoredTransaction {
224
+ hash : None ,
225
+ inner : tx,
226
+ creation_time : Instant :: now ( ) ,
227
+ block : None ,
228
+ } ) ;
229
+ Err ( GasEscalatorError :: MiddlewareError ( err) )
230
+ }
231
+ }
225
232
}
226
233
}
227
234
@@ -279,11 +286,11 @@ impl<M, E: Clone> EscalationTask<M, E> {
279
286
err_message : String ,
280
287
old_monitored_tx : MonitoredTransaction ,
281
288
new_tx : TypedTransaction ,
282
- ) -> Option < ( H256 , Instant ) > {
289
+ ) -> Option < ( Option < H256 > , Instant ) > {
283
290
if err_message. contains ( "nonce too low" ) {
284
291
// may happen if we try to broadcast a new, gas-escalated tx when the original tx
285
292
// already landed onchain, meaning we no longer need to escalate it
286
- tracing:: warn!( err = err_message, ?old_monitored_tx. hash , ?new_tx, "Nonce error when escalating gas price. Tx may have already been included onchain. Dropping it from escalator" ) ;
293
+ tracing:: warn!( err = err_message, ?old_monitored_tx, ?new_tx, "Nonce error when escalating gas price. Tx may have already been included onchain. Dropping it from escalator" ) ;
287
294
None
288
295
} else if RETRYABLE_ERRORS . iter ( ) . any ( |err_msg| err_message. contains ( err_msg) ) {
289
296
// if the error is one of the known retryable errors, we can keep trying to escalate
@@ -311,21 +318,15 @@ impl<M, E: Clone> EscalationTask<M, E> {
311
318
///
312
319
/// **Returns** a tx hash to monitor and the time it was created, unless the tx was already
313
320
/// included or an unknown error occurred
314
- async fn broadcast_tx_if_escalated (
321
+ async fn broadcast_tx (
315
322
& self ,
316
323
old_monitored_tx : MonitoredTransaction ,
317
324
new_tx : TypedTransaction ,
318
- ) -> Option < ( H256 , Instant ) >
325
+ ) -> Option < ( Option < H256 > , Instant ) >
319
326
where
320
327
M : Middleware ,
321
328
E : GasEscalator ,
322
329
{
323
- // gas price wasn't escalated
324
- // keep monitoring the old tx
325
- if old_monitored_tx. inner . eq ( & new_tx) {
326
- return Some ( ( old_monitored_tx. hash , old_monitored_tx. creation_time ) ) ;
327
- }
328
-
329
330
// send a replacement tx with the escalated gas price
330
331
match self . inner . send_transaction ( new_tx. clone ( ) , old_monitored_tx. block ) . await {
331
332
Ok ( new_tx_hash) => {
@@ -338,7 +339,7 @@ impl<M, E: Clone> EscalationTask<M, E> {
338
339
) ;
339
340
// Return the new tx hash to monitor and the time it was created.
340
341
// The latter is used to know when to escalate the gas price again
341
- Some ( ( new_tx_hash, Instant :: now ( ) ) )
342
+ Some ( ( Some ( new_tx_hash) , Instant :: now ( ) ) )
342
343
}
343
344
Err ( err) => Self :: handle_broadcast_error ( err. to_string ( ) , old_monitored_tx, new_tx) ,
344
345
}
@@ -360,34 +361,41 @@ impl<M, E: Clone> EscalationTask<M, E> {
360
361
tracing:: trace!( ?monitored_txs, "In the escalator watcher loop. Monitoring txs" ) ;
361
362
}
362
363
let mut new_txs_to_monitor = vec ! [ ] ;
363
- for monitored_tx in monitored_txs {
364
- let receipt = self
365
- . inner
366
- . get_transaction_receipt ( monitored_tx. hash )
367
- . await
368
- . map_err ( GasEscalatorError :: MiddlewareError ) ?;
369
-
370
- tracing:: trace!( tx_hash = ?monitored_tx. hash, "checking if exists" ) ;
364
+ for old_monitored_tx in monitored_txs {
365
+ let receipt = if let Some ( tx_hash) = old_monitored_tx. hash {
366
+ tracing:: trace!( tx_hash = ?old_monitored_tx. hash, "checking if exists" ) ;
367
+ self . inner
368
+ . get_transaction_receipt ( tx_hash)
369
+ . await
370
+ . map_err ( GasEscalatorError :: MiddlewareError ) ?
371
+ } else {
372
+ None
373
+ } ;
371
374
372
- if receipt . is_some ( ) {
375
+ if let Some ( receipt ) = receipt {
373
376
// tx was already included, can drop from escalator
374
- tracing:: debug!( tx = ?monitored_tx . hash , "Transaction was included onchain, dropping from escalator" ) ;
377
+ tracing:: debug!( tx = ?receipt . transaction_hash , "Transaction was included onchain, dropping from escalator" ) ;
375
378
continue ;
376
379
}
377
- let Some ( new_tx) = monitored_tx . escalate_gas_price ( self . escalator . clone ( ) ) else {
378
- tracing:: error!( tx=?monitored_tx . hash, "gas price is not set for transaction, dropping from escalator" ) ;
380
+ let Some ( new_tx) = old_monitored_tx . escalate_gas_price ( self . escalator . clone ( ) ) else {
381
+ tracing:: error!( tx=?old_monitored_tx . hash, "gas price is not set for transaction, dropping from escalator" ) ;
379
382
continue ;
380
383
} ;
381
384
382
- let maybe_tx_to_monitor =
383
- self . broadcast_tx_if_escalated ( monitored_tx. clone ( ) , new_tx. clone ( ) ) . await ;
385
+ // gas price wasn't escalated
386
+ // keep monitoring the old tx
387
+ let maybe_tx_to_monitor = if old_monitored_tx. inner . eq ( & new_tx) {
388
+ Some ( ( old_monitored_tx. hash , old_monitored_tx. creation_time ) )
389
+ } else {
390
+ self . broadcast_tx ( old_monitored_tx. clone ( ) , new_tx. clone ( ) ) . await
391
+ } ;
384
392
385
393
if let Some ( ( new_txhash, new_creation_time) ) = maybe_tx_to_monitor {
386
394
new_txs_to_monitor. push ( MonitoredTransaction {
387
395
hash : new_txhash,
388
396
inner : new_tx,
389
397
creation_time : new_creation_time,
390
- block : monitored_tx . block ,
398
+ block : old_monitored_tx . block ,
391
399
} ) ;
392
400
}
393
401
}
0 commit comments