@@ -28,27 +28,55 @@ func NewTxManager(l2Client *client.L2Client) *TxManager {
2828
2929// SendTransaction sends a transaction in a thread-safe manner
3030// It ensures only one transaction is sent at a time to avoid nonce conflicts
31+ // Before sending, it checks if there are any pending transactions by comparing nonces
3132func (m * TxManager ) SendTransaction (ctx context.Context , txFunc func (* bind.TransactOpts ) (* types.Transaction , error )) (* types.Receipt , error ) {
3233 m .mu .Lock ()
3334 defer m .mu .Unlock ()
3435
36+ fromAddr := m .l2Client .WalletAddress ()
37+
38+ // Check if there are pending transactions by comparing nonces
39+ confirmedNonce , err := m .l2Client .GetClient ().NonceAt (ctx , fromAddr , nil )
40+ if err != nil {
41+ return nil , fmt .Errorf ("failed to get confirmed nonce: %w" , err )
42+ }
43+
44+ pendingNonce , err := m .l2Client .GetClient ().PendingNonceAt (ctx , fromAddr )
45+ if err != nil {
46+ return nil , fmt .Errorf ("failed to get pending nonce: %w" , err )
47+ }
48+
49+ if pendingNonce > confirmedNonce {
50+ // There are pending transactions, don't send new one
51+ log .Warn ("Found pending transactions, skipping this round" ,
52+ "address" , fromAddr .Hex (),
53+ "confirmed_nonce" , confirmedNonce ,
54+ "pending_nonce" , pendingNonce ,
55+ "pending_count" , pendingNonce - confirmedNonce )
56+ return nil , fmt .Errorf ("pending transactions exist (confirmed: %d, pending: %d)" , confirmedNonce , pendingNonce )
57+ }
58+
59+ log .Info ("No pending transactions, proceeding to send" ,
60+ "address" , fromAddr .Hex (),
61+ "nonce" , confirmedNonce )
62+
3563 // Get transaction options (returns a copy)
3664 auth := m .l2Client .GetOpts ()
3765 auth .Context = ctx
38-
66+
3967 // First, estimate gas with GasLimit = 0
4068 auth .GasLimit = 0
4169 auth .NoSend = true
4270 tx , err := txFunc (auth )
4371 if err != nil {
4472 return nil , fmt .Errorf ("failed to estimate gas: %w" , err )
4573 }
46-
74+
4775 // Use 1.5x of estimated gas as the actual gas limit
4876 estimatedGas := tx .Gas ()
4977 auth .GasLimit = estimatedGas * 3 / 2
5078 log .Info ("Gas estimation completed" , "estimated" , estimatedGas , "actual_limit" , auth .GasLimit )
51-
79+
5280 // Now send the actual transaction
5381 auth .NoSend = false
5482 tx , err = txFunc (auth )
@@ -58,16 +86,18 @@ func (m *TxManager) SendTransaction(ctx context.Context, txFunc func(*bind.Trans
5886
5987 log .Info ("Transaction sent" ,
6088 "tx_hash" , tx .Hash ().Hex (),
89+ "nonce" , tx .Nonce (),
6190 "gas_limit" , tx .Gas ())
6291
63- // Wait for transaction to be mined with custom timeout and retry logic
92+ // Wait for transaction to be mined with timeout and retry logic
6493 receipt , err := m .waitForReceipt (ctx , tx .Hash (), 60 * time .Second , 2 * time .Second )
6594 if err != nil {
6695 log .Error ("Failed to wait for transaction receipt" ,
6796 "tx_hash" , tx .Hash ().Hex (),
6897 "error" , err )
6998 return nil , err
7099 }
100+
71101 return receipt , nil
72102}
73103
0 commit comments