@@ -398,67 +398,32 @@ impl ProofAggregator {
398398 }
399399 Ok ( SubmitOutcome :: Pending ( tx_hash) ) => {
400400 warn ! (
401- "Attempt {} timed out waiting for receipt; storing pending tx and continuing " ,
402- attempt + 1
403- ) ;
401+ "Attempt {} timed out waiting for receipt; storing pending tx" ,
402+ attempt + 1
403+ ) ;
404404 pending_hashes. push ( tx_hash) ;
405-
406405 last_error = Some (
407406 AggregatedProofSubmissionError :: SendVerifyAggregatedProofTransaction (
408407 "Timed out waiting for receipt" . to_string ( ) ,
409408 ) ,
410409 ) ;
411-
412- if attempt < max_retries - 1 {
413- info ! ( "Retrying with bumped gas fees and same nonce {}..." , nonce) ;
414- tokio:: time:: sleep ( Duration :: from_millis ( 500 ) ) . await ;
415- }
416410 }
417411 Err ( err) => {
418412 warn ! ( "Attempt {} failed: {:?}" , attempt + 1 , err) ;
419413 last_error = Some ( err) ;
420-
421- if attempt < max_retries - 1 {
422- info ! ( "Retrying with bumped gas fees and same nonce {}..." , nonce) ;
423-
424- tokio:: time:: sleep ( Duration :: from_millis ( 500 ) ) . await ;
425- } else {
426- warn ! ( "Max retries ({}) exceeded" , max_retries) ;
427- }
428414 }
429415 }
430- }
431416
432- // After exhausting all retry attempts, we iterate over every pending transaction hash
433- // that was previously submitted with the same nonce but different gas parameters.
434- // One of these transactions may have been included in a block while we were still
435- // retrying and waiting on others. By explicitly checking the receipt for each hash,
436- // we ensure we don't "lose" a transaction that was actually mined but whose receipt
437- // we never observed due to timeouts during earlier attempts.
438- for ( i, tx_hash) in pending_hashes. into_iter ( ) . enumerate ( ) {
439- match self
440- . proof_aggregation_service
441- . provider ( )
442- . get_transaction_receipt ( tx_hash)
443- . await
444- {
445- Ok ( Some ( receipt) ) => {
446- info ! ( "Pending tx #{} confirmed; returning receipt" , i + 1 ) ;
447- return Ok ( receipt) ;
448- }
449- Ok ( None ) => {
450- warn ! (
451- "Pending tx #{} still no receipt yet (hash {})" ,
452- i + 1 ,
453- tx_hash
454- ) ;
455- }
456- Err ( err) => {
457- warn ! ( "Pending tx #{} receipt query failed: {:?}" , i + 1 , err) ;
458- }
417+ // Check if any pending tx was confirmed before retrying
418+ if let Some ( receipt) = self . check_pending_txs_confirmed ( & pending_hashes) . await {
419+ return Ok ( receipt) ;
459420 }
421+
422+ info ! ( "Retrying with bumped gas fees and same nonce {}..." , nonce) ;
423+ tokio:: time:: sleep ( Duration :: from_millis ( 500 ) ) . await ;
460424 }
461425
426+ warn ! ( "Max retries ({}) exceeded" , max_retries) ;
462427 Err ( RetryError :: Transient ( last_error. unwrap_or_else ( || {
463428 AggregatedProofSubmissionError :: SendVerifyAggregatedProofTransaction (
464429 "Max retries exceeded with no error details" . to_string ( ) ,
@@ -571,6 +536,26 @@ impl ProofAggregator {
571536 }
572537 }
573538
539+ // Checks if any of the pending transactions have been confirmed.
540+ // Returns the receipt if one is found, otherwise None.
541+ async fn check_pending_txs_confirmed (
542+ & self ,
543+ pending_hashes : & [ TxHash ] ,
544+ ) -> Option < TransactionReceipt > {
545+ for tx_hash in pending_hashes {
546+ if let Ok ( Some ( receipt) ) = self
547+ . proof_aggregation_service
548+ . provider ( )
549+ . get_transaction_receipt ( * tx_hash)
550+ . await
551+ {
552+ info ! ( "Pending tx {} confirmed before retry" , tx_hash) ;
553+ return Some ( receipt) ;
554+ }
555+ }
556+ None
557+ }
558+
574559 // Updates the gas fees of a `TransactionRequest` using EIP-1559 fee parameters.
575560 // Intended for retrying an on-chain submission after a timeout.
576561 //
@@ -613,8 +598,8 @@ impl ProofAggregator {
613598
614599 // Calculate priority fee: suggested * (attempt + 1), capped at max
615600 let priority_fee_multiplier = ( attempt + 1 ) as u128 ;
616- let max_priority_fee_per_gas = ( suggested_priority_fee * priority_fee_multiplier )
617- . min ( max_priority_fee_upper_limit) ;
601+ let max_priority_fee_per_gas =
602+ ( suggested_priority_fee * priority_fee_multiplier ) . min ( max_priority_fee_upper_limit) ;
618603
619604 // Calculate max fee with cumulative bump per attempt to ensure replacement tx is accepted
620605 let max_fee_multiplier = 1.0 + max_fee_bump_percentage as f64 / 100.0 ;
0 commit comments