@@ -224,7 +224,7 @@ func TestContractEvent(t *testing.T) {
224224
225225// TestWithdrawalSafetyAllInvariants ... Tests the E2E flow of a withdrawal
226226// safety heuristic session. This test ensures that an alert is produced in the event
227- // of a highly suspicious withdrawal.
227+ // of a highly suspicious withdrawal at every step of the withdrawal flow .
228228func TestWithdrawalSafetyAllInvariants (t * testing.T ) {
229229 ts := e2e .CreateSysTestSuite (t , "" )
230230 defer ts .Close ()
@@ -259,6 +259,22 @@ func TestWithdrawalSafetyAllInvariants(t *testing.T) {
259259 core .L2ToL1MessagePasser : fakeAddr .String (),
260260 },
261261 },
262+ {
263+ Network : core .Layer2 .String (),
264+ HeuristicType : core .WithdrawalSafety .String (),
265+ StartHeight : nil ,
266+ EndHeight : nil ,
267+ AlertingParams : & core.AlertPolicy {
268+ Sev : core .LOW .String (),
269+ Msg : alertMsg ,
270+ },
271+ SessionParams : map [string ]interface {}{
272+ "threshold" : 0.20 ,
273+ "coefficient_threshold" : 0.20 ,
274+ core .L1Portal : ts .Cfg .L1Deployments .OptimismPortalProxy .String (),
275+ core .L2ToL1MessagePasser : predeploys .L2ToL1MessagePasserAddr .String (),
276+ },
277+ },
262278 })
263279 require .NoError (t , err , "Error bootstrapping heuristic session" )
264280
@@ -284,12 +300,33 @@ func TestWithdrawalSafetyAllInvariants(t *testing.T) {
284300 _ , err = wait .ForReceiptOK (context .Background (), ts .L1Client , depositTx .Hash ())
285301 require .NoError (t , err )
286302
287- // Initiate and prove a withdrawal
303+ // Initiate withdrawal
288304 withdrawTx , err := l2ToL1MessagePasser .InitiateWithdrawal (l2Opts , aliceAddr , big .NewInt (100_000 ), calldata )
289305 require .NoError (t , err )
290- withdrawReceipt , err := wait .ForReceiptOK (context .Background (), ts .L2Client , withdrawTx .Hash ())
306+ initReceipt , err := wait .ForReceiptOK (context .Background (), ts .L2Client , withdrawTx .Hash ())
291307 require .NoError (t , err )
292308
309+ // Wait for Pessimism to process initiation
310+ require .NoError (t , wait .For (context .Background (), 500 * time .Millisecond , func () (bool , error ) {
311+ id := ids [0 ].PathID
312+ height , err := ts .Subsystems .PathHeight (id )
313+ if err != nil {
314+ return false , err
315+ }
316+
317+ return height != nil && height .Uint64 () > initReceipt .BlockNumber .Uint64 (), nil
318+ }))
319+
320+ // Ensure Pessimism has detected what it considers an unsafe withdrawal
321+ alerts := ts .TestSlackSvr .SlackAlerts ()
322+ require .Equal (t , 1 , len (alerts ), "expected 1 alerts" )
323+ assert .Contains (t , alerts [0 ].Text , core .WithdrawalSafety .String (), "expected alert to be for withdrawal_safety" )
324+ assert .Contains (t , alerts [0 ].Text , alertMsg , "expected alert to have alert message" )
325+
326+ // Ensure that specific invariant messages are included in the alert
327+ assert .Contains (t , alerts [0 ].Text , alertMsg , registry .GreaterThanPortal )
328+
329+ ts .TestSlackSvr .ClearAlerts ()
293330 // Mock the indexer call to return a really high withdrawal amount
294331 ts .TestIxClient .EXPECT ().GetAllWithdrawalsByAddress (gomock .Any ()).Return ([]api_mods.WithdrawalItem {
295332 {
@@ -298,7 +335,7 @@ func TestWithdrawalSafetyAllInvariants(t *testing.T) {
298335 },
299336 }, nil ).AnyTimes ()
300337
301- _ , proveReceipt := op_e2e .ProveWithdrawal (t , * ts .Cfg , ts .L1Client , ts .Sys .EthInstances ["sequencer" ], ts .Cfg .Secrets .Alice , withdrawReceipt )
338+ params , proveReceipt := op_e2e .ProveWithdrawal (t , * ts .Cfg , ts .L1Client , ts .Sys .EthInstances ["sequencer" ], ts .Cfg .Secrets .Alice , initReceipt )
302339
303340 // Wait for Pessimism to process the proven withdrawal and send a notification to the mocked Slack server.
304341 require .NoError (t , wait .For (context .Background (), 500 * time .Millisecond , func () (bool , error ) {
@@ -312,7 +349,7 @@ func TestWithdrawalSafetyAllInvariants(t *testing.T) {
312349 }))
313350
314351 // Ensure Pessimism has detected what it considers an unsafe withdrawal
315- alerts : = ts .TestSlackSvr .SlackAlerts ()
352+ alerts = ts .TestSlackSvr .SlackAlerts ()
316353 require .Equal (t , 1 , len (alerts ), "expected 1 alerts" )
317354 assert .Contains (t , alerts [0 ].Text , core .WithdrawalSafety .String (), "expected alert to be for withdrawal_safety" )
318355 assert .Contains (t , alerts [0 ].Text , fakeAddr .String (), "expected alert to be for dummy L2ToL1MessagePasser" )
@@ -323,34 +360,34 @@ func TestWithdrawalSafetyAllInvariants(t *testing.T) {
323360 assert .Contains (t , alerts [0 ].Text , alertMsg , registry .GreaterThanPortal )
324361 assert .Contains (t , alerts [0 ].Text , alertMsg , fmt .Sprintf (registry .GreaterThanThreshold , 20.0 ))
325362
326- // TODO(#178) - Feat - Support WithdrawalProven processing in withdrawal_safety heuristic
327- // Mock the indexer call to return a really low withdrawal amount
328- // ts.TestIxClient.EXPECT().GetAllWithdrawalsByAddress(gomock.Any()).Return([]api_mods.WithdrawalItem{
329- // {
330- // TransactionHash: "0x123",
331- // Amount: "1",
332- // },
333- // }, nil).AnyTimes()
363+ ts .TestIxClient .EXPECT ().GetAllWithdrawalsByAddress (gomock .Any ()).Return ([]api_mods.WithdrawalItem {
364+ {
365+ TransactionHash : "0x123" ,
366+ Amount : "1" ,
367+ },
368+ }, nil ).AnyTimes ()
334369
335370 // Finalize the withdrawal
336- // finalizeReceipt := op_e2e.FinalizeWithdrawal(t, *ts.Cfg, ts.L1Client, ts.Cfg.Secrets.Alice, proveReceipt, proveParams)
337-
338- // // Wait for Pessimism to process the finalized withdrawal and send a notification to the mocked Slack server.
339- // require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
340- // id := ids[0].PathID
341- // height, err := ts.Subsystems.PathHeight(id)
342- // if err != nil {
343- // return false, err
344- // }
345-
346- // return height.Uint64() > finalizeReceipt.BlockNumber.Uint64(), nil
347- // }))
348-
349- // alerts = ts.TestSlackSvr.SlackAlerts()
350- // require.Equal(t, 3, len(alerts), "expected 3 alerts")
351- // assert.Contains(t, alerts[0].Text, "unsafe_withdrawal", "expected alert to be for unsafe_withdrawal")
352- // assert.Contains(t, alerts[0].Text, fakeAddr.String(), "expected alert to be for dummy L2ToL1MessagePasser")
353- // assert.Contains(t, alerts[0].Text, alertMsg, "expected alert to have alert message")
371+ finalizeReceipt := op_e2e .FinalizeWithdrawal (t , * ts .Cfg , ts .L1Client , ts .Cfg .Secrets .Alice , proveReceipt , params )
372+
373+ // Wait for Pessimism to process the finalized withdrawal and send a notification to the mocked Slack server.
374+ require .NoError (t , wait .For (context .Background (), 500 * time .Millisecond , func () (bool , error ) {
375+ id := ids [0 ].PathID
376+ height , err := ts .Subsystems .PathHeight (id )
377+ if err != nil {
378+ return false , err
379+ }
380+
381+ return height .Uint64 () > finalizeReceipt .BlockNumber .Uint64 (), nil
382+ }))
383+
384+ alerts = ts .TestSlackSvr .SlackAlerts ()
385+ require .Equal (t , 1 , len (alerts ), "expected 1 alert" )
386+ assert .Contains (t , alerts [0 ].Text , core .WithdrawalSafety .String ())
387+ assert .Contains (t , alerts [0 ].Text , alertMsg , "expected alert to have alert message" )
388+
389+ // Ensure that specific invariant messages are included in the alert
390+ assert .Contains (t , alerts [0 ].Text , alertMsg , registry .TooSimilarToMax )
354391}
355392
356393// TestWithdrawalSafetyNoInvariants ... Verify that no alerts are produced in the event
@@ -418,7 +455,7 @@ func TestWithdrawalSafetyNoInvariants(t *testing.T) {
418455 },
419456 }, nil ).AnyTimes ()
420457
421- _ , proveReceipt := op_e2e .ProveWithdrawal (t , * ts .Cfg , ts .L1Client , ts .Sys .EthInstances ["sequencer" ], ts .Cfg .Secrets .Alice , withdrawReceipt )
458+ params , proveReceipt := op_e2e .ProveWithdrawal (t , * ts .Cfg , ts .L1Client , ts .Sys .EthInstances ["sequencer" ], ts .Cfg .Secrets .Alice , withdrawReceipt )
422459
423460 // Wait for Pessimism to process the proven withdrawal and send a notification to the mocked Slack server.
424461 require .NoError (t , wait .For (context .Background (), 500 * time .Millisecond , func () (bool , error ) {
@@ -431,9 +468,23 @@ func TestWithdrawalSafetyNoInvariants(t *testing.T) {
431468 return height != nil && height .Uint64 () > proveReceipt .BlockNumber .Uint64 (), nil
432469 }))
433470
434- // Ensure that this withdrawal triggered no alerts
471+ // Finalize the withdrawal
472+ finalizeReceipt := op_e2e .FinalizeWithdrawal (t , * ts .Cfg , ts .L1Client , ts .Cfg .Secrets .Alice , proveReceipt , params )
473+
474+ // Wait for Pessimism to process the finalized withdrawal and send a notification to the mocked Slack server.
475+ require .NoError (t , wait .For (context .Background (), 500 * time .Millisecond , func () (bool , error ) {
476+ id := ids [0 ].PathID
477+ height , err := ts .Subsystems .PathHeight (id )
478+ if err != nil {
479+ return false , err
480+ }
481+
482+ return height .Uint64 () > finalizeReceipt .BlockNumber .Uint64 (), nil
483+ }))
484+
485+ // Ensure that this withdrawal flow triggered no alerts
435486 alerts := ts .TestSlackSvr .SlackAlerts ()
436- require .Equal (t , 0 , len (alerts ), "expected 0 alerts" )
487+ require .Equal (t , 0 , len (alerts ))
437488}
438489
439490// TestFaultDetector ... Ensures that an alert is produced in the presence of a faulty L2Output root
0 commit comments