reth_optimism_rpc/
error.rs
1use alloy_rpc_types_eth::{error::EthRpcErrorCode, BlockError};
4use alloy_transport::{RpcError, TransportErrorKind};
5use jsonrpsee_types::error::{INTERNAL_ERROR_CODE, INVALID_PARAMS_CODE};
6use op_revm::{OpHaltReason, OpTransactionError};
7use reth_optimism_evm::OpBlockExecutionError;
8use reth_rpc_eth_api::AsEthApiError;
9use reth_rpc_eth_types::{error::api::FromEvmHalt, EthApiError};
10use reth_rpc_server_types::result::{internal_rpc_err, rpc_err};
11use revm::context_interface::result::{EVMError, InvalidTransaction};
12use std::fmt::Display;
13
14#[derive(Debug, thiserror::Error)]
16pub enum OpEthApiError {
17 #[error(transparent)]
19 Eth(#[from] EthApiError),
20 #[error(transparent)]
22 Evm(#[from] OpBlockExecutionError),
23 #[error("failed to calculate l1 gas fee")]
25 L1BlockFeeError,
26 #[error("failed to calculate l1 gas used")]
28 L1BlockGasError,
29 #[error(transparent)]
31 InvalidTransaction(#[from] OpInvalidTransactionError),
32 #[error(transparent)]
34 Sequencer(#[from] SequencerClientError),
35}
36
37impl AsEthApiError for OpEthApiError {
38 fn as_err(&self) -> Option<&EthApiError> {
39 match self {
40 Self::Eth(err) => Some(err),
41 _ => None,
42 }
43 }
44}
45
46impl From<OpEthApiError> for jsonrpsee_types::error::ErrorObject<'static> {
47 fn from(err: OpEthApiError) -> Self {
48 match err {
49 OpEthApiError::Eth(err) => err.into(),
50 OpEthApiError::InvalidTransaction(err) => err.into(),
51 OpEthApiError::Evm(_) |
52 OpEthApiError::L1BlockFeeError |
53 OpEthApiError::L1BlockGasError => internal_rpc_err(err.to_string()),
54 OpEthApiError::Sequencer(err) => err.into(),
55 }
56 }
57}
58
59#[derive(thiserror::Error, Debug)]
61pub enum OpInvalidTransactionError {
62 #[error("no system transactions allowed after regolith")]
64 DepositSystemTxPostRegolith,
65 #[error("deposit transaction halted after regolith")]
67 HaltedDepositPostRegolith,
68 #[error(transparent)]
70 TxConditionalErr(#[from] TxConditionalErr),
71}
72
73impl From<OpInvalidTransactionError> for jsonrpsee_types::error::ErrorObject<'static> {
74 fn from(err: OpInvalidTransactionError) -> Self {
75 match err {
76 OpInvalidTransactionError::DepositSystemTxPostRegolith |
77 OpInvalidTransactionError::HaltedDepositPostRegolith => {
78 rpc_err(EthRpcErrorCode::TransactionRejected.code(), err.to_string(), None)
79 }
80 OpInvalidTransactionError::TxConditionalErr(_) => err.into(),
81 }
82 }
83}
84
85impl TryFrom<OpTransactionError> for OpInvalidTransactionError {
86 type Error = InvalidTransaction;
87
88 fn try_from(err: OpTransactionError) -> Result<Self, Self::Error> {
89 match err {
90 OpTransactionError::DepositSystemTxPostRegolith => {
91 Ok(Self::DepositSystemTxPostRegolith)
92 }
93 OpTransactionError::HaltedDepositPostRegolith => Ok(Self::HaltedDepositPostRegolith),
94 OpTransactionError::Base(err) => Err(err),
95 }
96 }
97}
98
99#[derive(Debug, thiserror::Error)]
101pub enum TxConditionalErr {
102 #[error("conditional cost exceeded maximum allowed")]
104 ConditionalCostExceeded,
105 #[error("invalid conditional parameters")]
107 InvalidCondition,
108 #[error("internal error: {0}")]
110 Internal(String),
111 #[error("storage value mismatch")]
113 StorageValueMismatch,
114 #[error("storage root mismatch")]
116 StorageRootMismatch,
117}
118
119impl TxConditionalErr {
120 pub fn internal<E: Display>(err: E) -> Self {
122 Self::Internal(err.to_string())
123 }
124}
125
126impl From<TxConditionalErr> for jsonrpsee_types::error::ErrorObject<'static> {
127 fn from(err: TxConditionalErr) -> Self {
128 let code = match &err {
129 TxConditionalErr::Internal(_) => INTERNAL_ERROR_CODE,
130 _ => INVALID_PARAMS_CODE,
131 };
132
133 jsonrpsee_types::error::ErrorObject::owned(code, err.to_string(), None::<String>)
134 }
135}
136
137#[derive(Debug, thiserror::Error)]
139pub enum SequencerClientError {
140 #[error(transparent)]
142 HttpError(#[from] RpcError<TransportErrorKind>),
143 #[error("invalid sequencer transaction")]
145 InvalidSequencerTransaction,
146}
147
148impl From<SequencerClientError> for jsonrpsee_types::error::ErrorObject<'static> {
149 fn from(err: SequencerClientError) -> Self {
150 jsonrpsee_types::error::ErrorObject::owned(
151 INTERNAL_ERROR_CODE,
152 err.to_string(),
153 None::<String>,
154 )
155 }
156}
157
158impl From<BlockError> for OpEthApiError {
159 fn from(error: BlockError) -> Self {
160 Self::Eth(error.into())
161 }
162}
163
164impl<T> From<EVMError<T, OpTransactionError>> for OpEthApiError
165where
166 T: Into<EthApiError>,
167{
168 fn from(error: EVMError<T, OpTransactionError>) -> Self {
169 match error {
170 EVMError::Transaction(err) => match err.try_into() {
171 Ok(err) => Self::InvalidTransaction(err),
172 Err(err) => Self::Eth(EthApiError::InvalidTransaction(err.into())),
173 },
174 EVMError::Database(err) => Self::Eth(err.into()),
175 EVMError::Header(err) => Self::Eth(err.into()),
176 EVMError::Custom(err) => Self::Eth(EthApiError::EvmCustom(err)),
177 }
178 }
179}
180
181impl FromEvmHalt<OpHaltReason> for OpEthApiError {
182 fn from_evm_halt(halt: OpHaltReason, gas_limit: u64) -> Self {
183 match halt {
184 OpHaltReason::FailedDeposit => {
185 OpInvalidTransactionError::HaltedDepositPostRegolith.into()
186 }
187 OpHaltReason::Base(halt) => EthApiError::from_evm_halt(halt, gas_limit).into(),
188 }
189 }
190}