Skip to content

Commit dce314f

Browse files
authored
fix(zone): only remove withdrawals after successful receipts (#378)
1 parent 3a0edfd commit dce314f

2 files changed

Lines changed: 36 additions & 5 deletions

File tree

crates/tempo-zone/src/metrics.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@ pub(crate) struct WithdrawalProcessorMetrics {
2727
/// Number of withdrawals confirmed on L1.
2828
pub(crate) withdrawals_confirmed_total: Counter,
2929

30-
/// Number of withdrawals that failed to send or confirm.
30+
/// Number of withdrawals that failed to send, confirm, or reverted after inclusion.
3131
pub(crate) withdrawals_failed_total: Counter,
3232

33+
/// Number of `processWithdrawal` transactions that were included on L1 but reverted.
34+
pub(crate) withdrawals_reverted_total: Counter,
35+
3336
/// Time spent processing a withdrawal queue slot.
3437
pub(crate) slot_processing_duration_seconds: Histogram,
3538
}

crates/tempo-zone/src/withdrawals.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use std::{
3131
time::{Duration, Instant},
3232
};
3333

34+
use alloy_network::ReceiptResponse;
3435
use alloy_primitives::{Address, B256};
3536
use alloy_provider::DynProvider;
3637
use parking_lot::Mutex;
@@ -45,6 +46,8 @@ use crate::{
4546
};
4647
use tempo_alloy::rpc::TempoCallBuilderExt;
4748

49+
const PROCESS_WITHDRAWAL_CONFIRM_TIMEOUT: Duration = Duration::from_secs(30);
50+
4851
/// Shared handle to the withdrawal store.
4952
#[derive(Clone)]
5053
pub struct SharedWithdrawalStore(Arc<Mutex<WithdrawalStore>>);
@@ -341,6 +344,7 @@ impl WithdrawalProcessor {
341344
"Processing withdrawal batch"
342345
);
343346
let slot_started_at = Instant::now();
347+
let slot_queue_hash = abi::Withdrawal::queue_hash(&withdrawals);
344348

345349
for (i, withdrawal) in withdrawals.iter().enumerate() {
346350
self.metrics.withdrawals_processed_total.increment(1);
@@ -398,12 +402,32 @@ impl WithdrawalProcessor {
398402
Ok(pending) => {
399403
let tx_hash = *pending.tx_hash();
400404
match pending
401-
.with_required_confirmations(1)
402-
.with_timeout(Some(std::time::Duration::from_secs(30)))
403-
.watch()
405+
.with_timeout(Some(PROCESS_WITHDRAWAL_CONFIRM_TIMEOUT))
406+
.get_receipt()
404407
.await
405408
{
406-
Ok(_) => {
409+
Ok(receipt) => {
410+
if !receipt.status() {
411+
self.metrics.withdrawals_failed_total.increment(1);
412+
self.metrics.withdrawals_reverted_total.increment(1);
413+
self.record_slot_duration(slot_started_at.elapsed());
414+
self.repair_notify.notify_one();
415+
416+
error!(
417+
slot = head_val,
418+
index = i,
419+
%tx_hash,
420+
to = %withdrawal.to,
421+
amount = %withdrawal.amount,
422+
queue_head = head_val,
423+
queue_tail = tail_val,
424+
expected_slot_queue_hash = %slot_queue_hash,
425+
expected_remaining_queue = %remaining_queue,
426+
"processWithdrawal tx was included but reverted; keeping batch in store and requesting repair"
427+
);
428+
return Ok(());
429+
}
430+
407431
self.metrics.withdrawals_confirmed_total.increment(1);
408432
info!(
409433
slot = head_val,
@@ -422,6 +446,8 @@ impl WithdrawalProcessor {
422446
slot = head_val,
423447
index = i,
424448
%tx_hash,
449+
expected_slot_queue_hash = %slot_queue_hash,
450+
expected_remaining_queue = %remaining_queue,
425451
to = %withdrawal.to,
426452
amount = %withdrawal.amount,
427453
error = %e,
@@ -437,6 +463,8 @@ impl WithdrawalProcessor {
437463
error!(
438464
slot = head_val,
439465
index = i,
466+
expected_slot_queue_hash = %slot_queue_hash,
467+
expected_remaining_queue = %remaining_queue,
440468
to = %withdrawal.to,
441469
amount = %withdrawal.amount,
442470
error = %e,

0 commit comments

Comments
 (0)