anvil_zksync_api_server/
error.rs1use jsonrpsee::{
6 core::Serialize,
7 types::{ErrorCode, ErrorObject, ErrorObjectOwned},
8};
9use zksync_error::{
10 anvil_zksync::{gas_estim::GasEstimationError, node::AnvilNodeError, state::StateLoaderError},
11 ICustomError, IError as _, ZksyncError,
12};
13use zksync_web3_decl::error::Web3Error;
14
15use jsonrpsee::types::ErrorCode as RpcErrorCode;
16
17fn to_rpc<I: Serialize + ICustomError<ZksyncError, ZksyncError>>(
28 code: Option<i32>,
29 error: I,
30) -> ErrorObjectOwned {
31 ErrorObject::owned(
32 code.unwrap_or(error.to_unified().get_identifier().encode() as i32),
33 error.to_unified().get_message(),
34 Some(error),
35 )
36}
37
38pub trait RpcErrorAdapter {
43 fn into(error: Self) -> ErrorObjectOwned;
53}
54
55impl RpcErrorAdapter for StateLoaderError {
57 fn into(error: Self) -> ErrorObjectOwned {
58 let error_code = match error {
59 StateLoaderError::LoadingStateOverExistingState
60 | StateLoaderError::LoadEmptyState
61 | StateLoaderError::StateDecompression { .. }
62 | StateLoaderError::StateDeserialization { .. }
63 | StateLoaderError::UnknownStateVersion { .. }
64 | StateLoaderError::StateFileAccess { .. } => ErrorCode::InvalidParams,
65 StateLoaderError::GenericError { .. } => ErrorCode::InternalError,
66 _ => ErrorCode::InternalError,
67 };
68 to_rpc(Some(error_code.code()), error)
69 }
70}
71
72impl RpcErrorAdapter for AnvilNodeError {
73 fn into(error: Self) -> ErrorObjectOwned {
74 match &error {
76 AnvilNodeError::TransactionGasEstimationFailed { inner, .. } => {
77 RpcErrorAdapter::into(Web3Error::SubmitTransactionError(
80 error.to_unified().get_message(),
81 match &**inner {
82 GasEstimationError::TransactionRevert { data, .. }
83 | GasEstimationError::TransactionAlwaysReverts { data, .. } => data.clone(),
84 _ => vec![],
85 },
86 ))
87 }
88 AnvilNodeError::SerializationError { .. } => {
89 RpcErrorAdapter::into(Web3Error::SubmitTransactionError(
92 error.to_unified().get_message(),
93 vec![],
94 ))
95 }
96 _ => to_rpc(Some(RpcErrorCode::InternalError.code()), error),
97 }
98 }
99}
100
101impl RpcErrorAdapter for Web3Error {
103 fn into(error: Self) -> ErrorObjectOwned {
104 let web3_error = &error;
105 let code: RpcErrorCode = match web3_error {
107 Web3Error::InternalError(_) => RpcErrorCode::InternalError,
108 Web3Error::MethodNotImplemented => RpcErrorCode::MethodNotFound,
109 Web3Error::NoBlock
110 | Web3Error::PrunedBlock(_)
111 | Web3Error::PrunedL1Batch(_)
112 | Web3Error::ProxyError(_)
113 | Web3Error::TooManyTopics
114 | Web3Error::FilterNotFound
115 | Web3Error::LogsLimitExceeded(_, _, _)
116 | Web3Error::InvalidFilterBlockHash
117 | Web3Error::TreeApiUnavailable => RpcErrorCode::InvalidParams,
118 Web3Error::SubmitTransactionError(_, _) | Web3Error::SerializationError(_) => {
119 RpcErrorCode::ServerError(3)
120 }
121 Web3Error::ServerShuttingDown => RpcErrorCode::ServerIsBusy,
122 };
123
124 let data = match &error {
126 Web3Error::SubmitTransactionError(_, data) => Some(format!("0x{}", hex::encode(data))),
127 _ => None,
128 };
129
130 let message = match web3_error {
132 Web3Error::InternalError(e) => e.to_string(),
133 _ => web3_error.to_string(),
134 };
135
136 ErrorObject::owned(code.code(), message, data)
137 }
138}
139
140impl RpcErrorAdapter for anyhow::Error {
142 fn into(error: Self) -> ErrorObjectOwned {
143 ErrorObjectOwned::owned(
144 ErrorCode::InternalError.code(),
145 error.to_string(),
146 None::<()>,
147 )
148 }
149}
150
151pub(crate) fn rpc_invalid_params(msg: String) -> ErrorObjectOwned {
161 ErrorObjectOwned::owned(ErrorCode::InvalidParams.code(), msg, None::<()>)
162}
163
164pub(crate) fn rpc_unsupported<T>(method_name: &str) -> jsonrpsee::core::RpcResult<T> {
174 Err(ErrorObject::owned(
175 ErrorCode::MethodNotFound.code(),
176 format!("Method not found: {}", method_name),
177 None::<()>,
178 ))
179}