anvil_zksync_core/node/
error.rs1use alloy::hex::ToHexExt;
2use anvil_zksync_traces::identifier::SignaturesIdentifier;
3use async_trait::async_trait;
4use zksync_error::anvil_zksync::halt::HaltError;
5use zksync_error::anvil_zksync::revert::RevertError;
6use zksync_multivm::interface::{Halt, VmRevertReason};
7
8async fn handle_vm_revert_reason(reason: &VmRevertReason) -> (String, &[u8]) {
9 match reason {
10 VmRevertReason::General { msg, data } => (msg.to_string(), data),
11 VmRevertReason::InnerTxError => ("Inner transaction error".to_string(), &[]),
12 VmRevertReason::VmError => ("VM Error".to_string(), &[]),
13 VmRevertReason::Unknown {
14 function_selector,
15 data,
16 } => {
17 if function_selector.is_empty() {
18 ("Error: no function selector available".to_string(), &[])
19 } else {
20 let hex_selector = function_selector.encode_hex();
21 match SignaturesIdentifier::global()
22 .identify_function(function_selector)
23 .await
24 {
25 Some(decoded_name) => (decoded_name.name, data),
26 None => (
27 format!("Error with function selector: 0x{hex_selector}"),
28 data,
29 ),
30 }
31 }
32 }
33 _ => ("".to_string(), &[]),
34 }
35}
36
37fn revert_reason(halt: &Halt) -> Option<&VmRevertReason> {
39 match halt {
40 Halt::ValidationFailed(reason)
41 | Halt::PaymasterValidationFailed(reason)
42 | Halt::PrePaymasterPreparationFailed(reason)
43 | Halt::PayForTxFailed(reason)
44 | Halt::FailedToMarkFactoryDependencies(reason)
45 | Halt::FailedToChargeFee(reason)
46 | Halt::Unknown(reason) => Some(reason),
47 _ => None,
48 }
49}
50
51#[async_trait]
52pub trait ToRevertReason {
53 async fn to_revert_reason(self) -> RevertError;
54}
55
56#[async_trait]
57impl ToRevertReason for VmRevertReason {
58 async fn to_revert_reason(self) -> RevertError {
59 let (message, data) = handle_vm_revert_reason(&self).await;
60
61 match self {
62 VmRevertReason::General { .. } => RevertError::General {
63 msg: message,
64 data: data.encode_hex().into(),
65 },
66 VmRevertReason::InnerTxError => RevertError::InnerTxError,
67 VmRevertReason::VmError => RevertError::VmError,
68 VmRevertReason::Unknown { .. } => RevertError::Unknown {
69 function_selector: message,
70 data: data.encode_hex(),
71 },
72 _ => RevertError::Unknown {
73 function_selector: message,
74 data: data.encode_hex(),
75 },
76 }
77 }
78}
79
80#[async_trait]
81pub trait ToHaltError {
82 async fn to_halt_error(self) -> HaltError;
83}
84
85#[async_trait]
86impl ToHaltError for Halt {
87 async fn to_halt_error(self) -> HaltError {
88 let (msg_opt, data_opt) = if let Some(reason) = revert_reason(&self) {
89 let (msg, data) = handle_vm_revert_reason(reason).await;
90 (Some(msg), Some(data.encode_hex()))
91 } else {
92 (None, None)
93 };
94
95 let msg = msg_opt.unwrap_or_else(|| "Unknown revert reason".into());
96 let data = data_opt.unwrap_or_default();
97
98 match self {
99 Halt::ValidationFailed(_) => HaltError::ValidationFailed { msg, data },
100 Halt::PaymasterValidationFailed(_) => {
101 HaltError::PaymasterValidationFailed { msg, data }
102 }
103 Halt::PrePaymasterPreparationFailed(_) => {
104 HaltError::PrePaymasterPreparationFailed { msg, data }
105 }
106 Halt::PayForTxFailed(_) => HaltError::PayForTxFailed { msg, data },
107 Halt::FailedToMarkFactoryDependencies(_) => {
108 HaltError::FailedToMarkFactoryDependencies { msg, data }
109 }
110 Halt::FailedToChargeFee(_) => HaltError::FailedToChargeFee { msg, data },
111 Halt::Unknown(_) => HaltError::Unknown { msg, data },
112 Halt::UnexpectedVMBehavior(msg) => HaltError::UnexpectedVMBehavior { problem: msg },
114 Halt::FailedToSetL2Block(msg) => HaltError::FailedToSetL2Block { msg },
115 Halt::FailedToAppendTransactionToL2Block(msg) => {
116 HaltError::FailedToAppendTransactionToL2Block { msg }
117 }
118 Halt::TracerCustom(msg) => HaltError::TracerCustom { msg },
119 Halt::FromIsNotAnAccount => HaltError::FromIsNotAnAccount,
120 Halt::InnerTxError => HaltError::InnerTxError,
121 Halt::BootloaderOutOfGas => HaltError::BootloaderOutOfGas,
122 Halt::ValidationOutOfGas => HaltError::ValidationOutOfGas,
123 Halt::TooBigGasLimit => HaltError::TooBigGasLimit,
124 Halt::NotEnoughGasProvided => HaltError::NotEnoughGasProvided,
125 Halt::MissingInvocationLimitReached => HaltError::MissingInvocationLimitReached,
126 Halt::VMPanic => HaltError::VMPanic,
127 Halt::FailedToPublishCompressedBytecodes => {
128 HaltError::FailedToPublishCompressedBytecodes
129 }
130 Halt::FailedBlockTimestampAssertion => HaltError::FailedBlockTimestampAssertion,
131 }
132 }
133}