reth_optimism_rpc/
error.rs1use alloy_json_rpc::ErrorPayload;
4use alloy_rpc_types_eth::{error::EthRpcErrorCode, BlockError};
5use alloy_transport::{RpcError, TransportErrorKind};
6use jsonrpsee_types::error::{INTERNAL_ERROR_CODE, INVALID_PARAMS_CODE};
7use op_revm::{OpHaltReason, OpTransactionError};
8use reth_evm::execute::ProviderError;
9use reth_optimism_evm::OpBlockExecutionError;
10use reth_rpc_eth_api::{AsEthApiError, EthTxEnvError, TransactionConversionError};
11use reth_rpc_eth_types::{error::api::FromEvmHalt, EthApiError};
12use reth_rpc_server_types::result::{internal_rpc_err, rpc_err};
13use revm::context_interface::result::{EVMError, InvalidTransaction};
14use std::{convert::Infallible, fmt::Display};
15
16#[derive(Debug, thiserror::Error)]
18pub enum OpEthApiError {
19 #[error(transparent)]
21 Eth(#[from] EthApiError),
22 #[error(transparent)]
24 Evm(#[from] OpBlockExecutionError),
25 #[error("failed to calculate l1 gas fee")]
27 L1BlockFeeError,
28 #[error("failed to calculate l1 gas used")]
30 L1BlockGasError,
31 #[error(transparent)]
33 InvalidTransaction(#[from] OpInvalidTransactionError),
34 #[error(transparent)]
36 Sequencer(#[from] SequencerClientError),
37}
38
39impl AsEthApiError for OpEthApiError {
40 fn as_err(&self) -> Option<&EthApiError> {
41 match self {
42 Self::Eth(err) => Some(err),
43 _ => None,
44 }
45 }
46}
47
48impl From<OpEthApiError> for jsonrpsee_types::error::ErrorObject<'static> {
49 fn from(err: OpEthApiError) -> Self {
50 match err {
51 OpEthApiError::Eth(err) => err.into(),
52 OpEthApiError::InvalidTransaction(err) => err.into(),
53 OpEthApiError::Evm(_) |
54 OpEthApiError::L1BlockFeeError |
55 OpEthApiError::L1BlockGasError => internal_rpc_err(err.to_string()),
56 OpEthApiError::Sequencer(err) => err.into(),
57 }
58 }
59}
60
61#[derive(thiserror::Error, Debug)]
63pub enum OpInvalidTransactionError {
64 #[error("no system transactions allowed after regolith")]
66 DepositSystemTxPostRegolith,
67 #[error("deposit transaction halted after regolith")]
69 HaltedDepositPostRegolith,
70 #[error(transparent)]
72 TxConditionalErr(#[from] TxConditionalErr),
73}
74
75impl From<OpInvalidTransactionError> for jsonrpsee_types::error::ErrorObject<'static> {
76 fn from(err: OpInvalidTransactionError) -> Self {
77 match err {
78 OpInvalidTransactionError::DepositSystemTxPostRegolith |
79 OpInvalidTransactionError::HaltedDepositPostRegolith => {
80 rpc_err(EthRpcErrorCode::TransactionRejected.code(), err.to_string(), None)
81 }
82 OpInvalidTransactionError::TxConditionalErr(_) => err.into(),
83 }
84 }
85}
86
87impl TryFrom<OpTransactionError> for OpInvalidTransactionError {
88 type Error = InvalidTransaction;
89
90 fn try_from(err: OpTransactionError) -> Result<Self, Self::Error> {
91 match err {
92 OpTransactionError::DepositSystemTxPostRegolith => {
93 Ok(Self::DepositSystemTxPostRegolith)
94 }
95 OpTransactionError::HaltedDepositPostRegolith => Ok(Self::HaltedDepositPostRegolith),
96 OpTransactionError::Base(err) => Err(err),
97 }
98 }
99}
100
101#[derive(Debug, thiserror::Error)]
103pub enum TxConditionalErr {
104 #[error("conditional cost exceeded maximum allowed")]
106 ConditionalCostExceeded,
107 #[error("invalid conditional parameters")]
109 InvalidCondition,
110 #[error("internal error: {0}")]
112 Internal(String),
113 #[error("storage value mismatch")]
115 StorageValueMismatch,
116 #[error("storage root mismatch")]
118 StorageRootMismatch,
119}
120
121impl TxConditionalErr {
122 pub fn internal<E: Display>(err: E) -> Self {
124 Self::Internal(err.to_string())
125 }
126}
127
128impl From<TxConditionalErr> for jsonrpsee_types::error::ErrorObject<'static> {
129 fn from(err: TxConditionalErr) -> Self {
130 let code = match &err {
131 TxConditionalErr::Internal(_) => INTERNAL_ERROR_CODE,
132 _ => INVALID_PARAMS_CODE,
133 };
134
135 jsonrpsee_types::error::ErrorObject::owned(code, err.to_string(), None::<String>)
136 }
137}
138
139#[derive(Debug, thiserror::Error)]
141pub enum SequencerClientError {
142 #[error(transparent)]
144 HttpError(#[from] RpcError<TransportErrorKind>),
145}
146
147impl From<SequencerClientError> for jsonrpsee_types::error::ErrorObject<'static> {
148 fn from(err: SequencerClientError) -> Self {
149 match err {
150 SequencerClientError::HttpError(RpcError::ErrorResp(ErrorPayload {
151 code,
152 message,
153 data,
154 })) => jsonrpsee_types::error::ErrorObject::owned(code as i32, message, data),
155 err => jsonrpsee_types::error::ErrorObject::owned(
156 INTERNAL_ERROR_CODE,
157 err.to_string(),
158 None::<String>,
159 ),
160 }
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}
191
192impl From<TransactionConversionError> for OpEthApiError {
193 fn from(value: TransactionConversionError) -> Self {
194 Self::Eth(EthApiError::from(value))
195 }
196}
197
198impl From<EthTxEnvError> for OpEthApiError {
199 fn from(value: EthTxEnvError) -> Self {
200 Self::Eth(EthApiError::from(value))
201 }
202}
203
204impl From<ProviderError> for OpEthApiError {
205 fn from(value: ProviderError) -> Self {
206 Self::Eth(EthApiError::from(value))
207 }
208}
209
210impl From<BlockError> for OpEthApiError {
211 fn from(value: BlockError) -> Self {
212 Self::Eth(EthApiError::from(value))
213 }
214}
215
216impl From<Infallible> for OpEthApiError {
217 fn from(value: Infallible) -> Self {
218 match value {}
219 }
220}