@@ -125,7 +125,7 @@ async fn test_l1_sync_batch_commit() -> eyre::Result<()> {
125125 let mut fixture = TestFixture :: builder ( )
126126 . followers ( 1 )
127127 . skip_l1_synced_notifications ( ) // Prevents automatic L1Synced, simulates initial sync
128- . with_anvil ( None , Some ( 22222222 ) , None , None )
128+ . with_anvil ( None , None , Some ( 22222222 ) , None , None )
129129 . build ( )
130130 . await ?;
131131
@@ -193,7 +193,7 @@ async fn test_l1_sync_batch_finalized() -> eyre::Result<()> {
193193 let mut fixture = TestFixture :: builder ( )
194194 . followers ( 1 )
195195 . skip_l1_synced_notifications ( )
196- . with_anvil ( None , Some ( 22222222 ) , None , None )
196+ . with_anvil ( None , None , Some ( 22222222 ) , None , None )
197197 . build ( )
198198 . await ?;
199199
@@ -296,28 +296,94 @@ async fn test_l1_sync_batch_finalized() -> eyre::Result<()> {
296296 Ok ( ( ) )
297297}
298298
299- /// Test: `BatchRevert` events correctly roll back the safe head after `L1Synced`.
299+ /// Test: `BatchRevert` events are ignored before `L1Synced`.
300300///
301301/// # Test Flow
302- /// 1. Start node in syncing state
302+ /// 1. Start node in syncing state (skip automatic L1Synced notifications)
303303/// 2. Send `BatchCommit` transactions (batches 0-6) to L1
304- /// 3. Complete L1 sync and verify safe head advanced
304+ /// 3. Verify safe head remains at genesis (events are buffered during sync)
305305/// 4. Send a `BatchRevert` transaction to revert some batches
306- /// 5. Verify safe head decreased to reflect the reverted state
306+ /// 5. Verify safe head still remains unchanged
307+ ///
308+ /// # Expected Behavior
309+ /// During initial sync (before `L1Synced`), `BatchRevert` events should be indexed but
310+ /// NOT processed. The safe head should remain at genesis until L1 sync completes.
311+ /// This prevents the node from processing revert events out of order during catchup.
312+ #[ tokio:: test]
313+ async fn test_l1_sync_batch_revert_before_l1_synced ( ) -> eyre:: Result < ( ) > {
314+ reth_tracing:: init_test_tracing ( ) ;
315+
316+ // Step 1: Setup node in syncing state
317+ let mut fixture = TestFixture :: builder ( )
318+ . followers ( 1 )
319+ . skip_l1_synced_notifications ( )
320+ . with_anvil ( None , None , Some ( 22222222 ) , None , None )
321+ . build ( )
322+ . await ?;
323+
324+ // Record initial state
325+ let initial_status = fixture. get_status ( 0 ) . await ?;
326+ let initial_safe = initial_status. l2 . fcs . safe_block_info ( ) . number ;
327+ assert_eq ! ( initial_safe, 0 , "Initial safe head should be at genesis (block 0)" ) ;
328+
329+ // Step 2: Send BatchCommit transactions (batches 0-6) to L1
330+ for i in 0 ..=6 {
331+ let commit_batch_tx = read_test_transaction ( "commitBatch" , & i. to_string ( ) ) ?;
332+ fixture. anvil_inject_tx ( commit_batch_tx) . await ?;
333+ }
334+ for _ in 1 ..=6 {
335+ fixture. expect_event ( ) . batch_commit_indexed ( ) . await ?;
336+ }
337+
338+ // Verify safe head advanced after processing commits
339+ let new_status = fixture. get_status ( 0 ) . await ?;
340+ assert_eq ! (
341+ initial_safe,
342+ new_status. l2. fcs. safe_block_info( ) . number,
343+ "Safe head should not advance after BatchCommit before L1Synced"
344+ ) ;
345+
346+ // Step 4: Send BatchRevert transaction to revert some batches
347+ let revert_batch_tx = read_test_transaction ( "revertBatch" , "0" ) ?;
348+ fixture. anvil_inject_tx ( revert_batch_tx) . await ?;
349+
350+ fixture. expect_event ( ) . batch_reverted ( ) . await ?;
351+
352+ // Step 5: Verify safe head decreased after revert
353+ let revert_status = fixture. get_status ( 0 ) . await ?;
354+ assert_eq ! (
355+ revert_status. l2. fcs. safe_block_info( ) . number,
356+ new_status. l2. fcs. safe_block_info( ) . number,
357+ "Safe head should not change after BatchRevert before L1Synced"
358+ ) ;
359+
360+ Ok ( ( ) )
361+ }
362+
363+ /// Test: `BatchRevert` events correctly roll back the safe head after `L1Synced`.
364+ ///
365+ /// # Test Flow
366+ /// 1. Start node in syncing state
367+ /// 2. Send `BatchCommit` transactions (batches 0-6) to L1 and wait for indexing
368+ /// 3. Complete L1 sync by sending `L1Synced` notification
369+ /// 4. Verify safe head advances after processing buffered commits
370+ /// 5. Send a `BatchRevert` transaction to revert some batches
371+ /// 6. Verify safe head decreases to reflect the reverted state
307372///
308373/// # Expected Behavior
309- /// When a `BatchRevert` event is detected on L1 (after `L1Synced`), the node should
310- /// roll back its safe head to the last valid batch before the reverted batches.
311- /// This ensures the L2 state remains consistent with the canonical L1 state.
374+ /// After `L1Synced`, when a `BatchRevert` event is detected on L1, the node should
375+ /// immediately roll back its safe head to the last valid batch before the reverted
376+ /// batches. This ensures the L2 state remains consistent with the canonical L1 state
377+ /// and handles L1 sequencer coordinator initiated reverts correctly.
312378#[ tokio:: test]
313- async fn test_l1_sync_batch_revert ( ) -> eyre:: Result < ( ) > {
379+ async fn test_l1_sync_batch_revert_after_l1_synced ( ) -> eyre:: Result < ( ) > {
314380 reth_tracing:: init_test_tracing ( ) ;
315381
316382 // Step 1: Setup node in syncing state
317383 let mut fixture = TestFixture :: builder ( )
318384 . followers ( 1 )
319385 . skip_l1_synced_notifications ( )
320- . with_anvil ( None , Some ( 22222222 ) , None , None )
386+ . with_anvil ( None , None , Some ( 22222222 ) , None , None )
321387 . build ( )
322388 . await ?;
323389
@@ -394,7 +460,7 @@ async fn test_l1_reorg_batch_commit() -> eyre::Result<()> {
394460 let mut fixture = TestFixture :: builder ( )
395461 . followers ( 1 )
396462 . skip_l1_synced_notifications ( )
397- . with_anvil ( None , Some ( 22222222 ) , None , None )
463+ . with_anvil ( None , None , Some ( 22222222 ) , None , Some ( 32 ) )
398464 . build ( )
399465 . await ?;
400466
@@ -435,7 +501,6 @@ async fn test_l1_reorg_batch_commit() -> eyre::Result<()> {
435501
436502 // Step 4: Perform L1 reorg to remove batches 4-6 (reorg depth 3)
437503 fixture. anvil_reorg ( 3 ) . await ?;
438- tokio:: time:: sleep ( tokio:: time:: Duration :: from_secs ( 3 ) ) . await ;
439504
440505 // Wait for reorg detection
441506 fixture. expect_event ( ) . l1_reorg ( ) . await ?;
@@ -478,7 +543,7 @@ async fn test_l1_reorg_batch_finalized() -> eyre::Result<()> {
478543 let mut fixture = TestFixture :: builder ( )
479544 . followers ( 1 )
480545 . skip_l1_synced_notifications ( )
481- . with_anvil ( None , Some ( 22222222 ) , None , None )
546+ . with_anvil ( None , None , Some ( 22222222 ) , None , None )
482547 . build ( )
483548 . await ?;
484549
@@ -557,7 +622,7 @@ async fn test_l1_reorg_batch_revert() -> eyre::Result<()> {
557622 let mut fixture = TestFixture :: builder ( )
558623 . followers ( 1 )
559624 . skip_l1_synced_notifications ( )
560- . with_anvil ( None , Some ( 22222222 ) , None , None )
625+ . with_anvil ( None , None , Some ( 22222222 ) , None , None )
561626 . build ( )
562627 . await ?;
563628
0 commit comments