Skip to main content

anvil/eth/error/
mod.rs

1//! Aggregated error type for this module
2
3use alloy_consensus::crypto::RecoveryError;
4use alloy_evm::overrides::StateOverrideError;
5use alloy_primitives::{B256, Bytes, SignatureError, TxHash, U256};
6use alloy_rpc_types::BlockNumberOrTag;
7use alloy_signer::Error as SignerError;
8use alloy_transport::TransportError;
9use anvil_core::eth::wallet::WalletError;
10use anvil_rpc::{
11    error::{ErrorCode, RpcError},
12    response::ResponseResult,
13};
14use foundry_evm::{backend::DatabaseError, decode::RevertDecoder};
15use revm::{
16    context_interface::result::{EVMError, InvalidHeader, InvalidTransaction},
17    interpreter::InstructionResult,
18};
19use serde::Serialize;
20use tempo_revm::TempoInvalidTransaction;
21use tokio::time::Duration;
22
23#[cfg(feature = "optimism")]
24mod optimism;
25
26pub(crate) type Result<T> = std::result::Result<T, BlockchainError>;
27
28#[derive(Debug, thiserror::Error)]
29pub enum BlockchainError {
30    #[error(transparent)]
31    Pool(#[from] PoolError),
32    #[error("No signer available")]
33    NoSignerAvailable,
34    #[error("Chain Id not available")]
35    ChainIdNotAvailable,
36    #[error("Invalid input: `max_priority_fee_per_gas` greater than `max_fee_per_gas`")]
37    InvalidFeeInput,
38    #[error("Transaction data is empty")]
39    EmptyRawTransactionData,
40    #[error("Failed to decode signed transaction")]
41    FailedToDecodeSignedTransaction,
42    #[error("Failed to decode transaction")]
43    FailedToDecodeTransaction,
44    #[error("Failed to decode receipt")]
45    FailedToDecodeReceipt,
46    #[error("Failed to decode state")]
47    FailedToDecodeStateDump,
48    #[error("Prevrandao not in the EVM's environment after merge")]
49    PrevrandaoNotSet,
50    #[error(transparent)]
51    SignatureError(#[from] SignatureError),
52    #[error(transparent)]
53    RecoveryError(#[from] RecoveryError),
54    #[error(transparent)]
55    SignerError(#[from] SignerError),
56    #[error("Rpc Endpoint not implemented")]
57    RpcUnimplemented,
58    #[error("Rpc error {0:?}")]
59    RpcError(RpcError),
60    #[error(transparent)]
61    InvalidTransaction(#[from] InvalidTransactionError),
62    #[error(transparent)]
63    FeeHistory(#[from] FeeHistoryError),
64    #[error(transparent)]
65    AlloyForkProvider(#[from] TransportError),
66    #[error("EVM error {0:?}")]
67    EvmError(InstructionResult),
68    #[error("Evm override error: {0}")]
69    EvmOverrideError(String),
70    #[error("Invalid url {0:?}")]
71    InvalidUrl(String),
72    #[error("Internal error: {0:?}")]
73    Internal(String),
74    #[error("BlockOutOfRangeError: block height is {0} but requested was {1}")]
75    BlockOutOfRange(u64, u64),
76    #[error("Resource not found")]
77    BlockNotFound,
78    #[error("unknown block")]
79    UnknownBlock,
80    /// Thrown when a requested transaction is not found
81    #[error("transaction not found")]
82    TransactionNotFound,
83    #[error("Required data unavailable")]
84    DataUnavailable,
85    #[error("Trie error: {0}")]
86    TrieError(String),
87    #[error("{0}")]
88    UintConversion(&'static str),
89    #[error("State override error: {0}")]
90    StateOverrideError(String),
91    #[error("Timestamp error: {0}")]
92    TimestampError(String),
93    #[error(transparent)]
94    DatabaseError(#[from] DatabaseError),
95    #[error(
96        "EIP-1559 style fee params (maxFeePerGas or maxPriorityFeePerGas) received but they are not supported by the current hardfork.\n\nYou can use them by running anvil with '--hardfork london' or later."
97    )]
98    EIP1559TransactionUnsupportedAtHardfork,
99    #[error(
100        "Access list received but is not supported by the current hardfork.\n\nYou can use it by running anvil with '--hardfork berlin' or later."
101    )]
102    EIP2930TransactionUnsupportedAtHardfork,
103    #[error(
104        "EIP-4844 fields received but is not supported by the current hardfork.\n\nYou can use it by running anvil with '--hardfork cancun' or later."
105    )]
106    EIP4844TransactionUnsupportedAtHardfork,
107    #[error(
108        "EIP-7702 fields received but is not supported by the current hardfork.\n\nYou can use it by running anvil with '--hardfork prague' or later."
109    )]
110    EIP7702TransactionUnsupportedAtHardfork,
111    #[error(
112        "op-stack deposit tx received but is not supported.\n\nYou can use it by running anvil with '--optimism'."
113    )]
114    DepositTransactionUnsupported,
115    #[error(
116        "tempo transaction received but is not supported.\n\nYou can use it by running anvil with '--tempo'."
117    )]
118    TempoTransactionUnsupported,
119    #[error("Unknown transaction type not supported")]
120    UnknownTransactionType,
121    #[error("Excess blob gas not set.")]
122    ExcessBlobGasNotSet,
123    #[error("{0}")]
124    Message(String),
125    #[error("Transaction {hash} was added to the mempool but wasn't confirmed within {duration:?}")]
126    TransactionConfirmationTimeout {
127        /// Hash of the transaction that timed out
128        hash: B256,
129        /// Duration that was waited before timing out
130        duration: Duration,
131    },
132    #[error("Invalid transaction request: {0}")]
133    InvalidTransactionRequest(String),
134    #[error("filter not found")]
135    FilterNotFound,
136}
137
138impl From<eyre::Report> for BlockchainError {
139    fn from(err: eyre::Report) -> Self {
140        Self::Message(err.to_string())
141    }
142}
143
144impl From<RpcError> for BlockchainError {
145    fn from(err: RpcError) -> Self {
146        Self::RpcError(err)
147    }
148}
149
150impl<T> From<EVMError<T>> for BlockchainError
151where
152    T: Into<Self>,
153{
154    fn from(err: EVMError<T>) -> Self {
155        match err {
156            EVMError::Transaction(err) => InvalidTransactionError::from(err).into(),
157            EVMError::Header(err) => match err {
158                InvalidHeader::ExcessBlobGasNotSet => Self::ExcessBlobGasNotSet,
159                InvalidHeader::PrevrandaoNotSet => Self::PrevrandaoNotSet,
160            },
161            EVMError::Database(err) => err.into(),
162            EVMError::Custom(err) => Self::Message(err),
163            EVMError::CustomAny(err) => Self::Message(err.to_string()),
164        }
165    }
166}
167
168impl<T> From<EVMError<T, TempoInvalidTransaction>> for BlockchainError
169where
170    T: Into<Self>,
171{
172    fn from(err: EVMError<T, TempoInvalidTransaction>) -> Self {
173        match err {
174            EVMError::Transaction(err) => match err {
175                TempoInvalidTransaction::EthInvalidTransaction(err) => {
176                    InvalidTransactionError::from(err).into()
177                }
178                err => Self::Message(format!("tempo transaction error: {err}")),
179            },
180            EVMError::Header(err) => match err {
181                InvalidHeader::ExcessBlobGasNotSet => Self::ExcessBlobGasNotSet,
182                InvalidHeader::PrevrandaoNotSet => Self::PrevrandaoNotSet,
183            },
184            EVMError::Database(err) => err.into(),
185            EVMError::Custom(err) => Self::Message(err),
186            EVMError::CustomAny(err) => Self::Message(err.to_string()),
187        }
188    }
189}
190
191impl From<WalletError> for BlockchainError {
192    fn from(value: WalletError) -> Self {
193        Self::Message(value.to_string())
194    }
195}
196
197impl<E> From<StateOverrideError<E>> for BlockchainError
198where
199    E: Into<Self>,
200{
201    fn from(value: StateOverrideError<E>) -> Self {
202        match value {
203            StateOverrideError::InvalidBytecode(err) => Self::StateOverrideError(err.to_string()),
204            StateOverrideError::BothStateAndStateDiff(addr) => Self::StateOverrideError(format!(
205                "state and state_diff can't be used together for account {addr}",
206            )),
207            StateOverrideError::Database(err) => err.into(),
208        }
209    }
210}
211
212/// Errors that can occur in the transaction pool
213#[derive(Debug, thiserror::Error)]
214pub enum PoolError {
215    #[error("Transaction with cyclic dependent transactions")]
216    CyclicTransaction,
217    /// Thrown if a replacement transaction's gas price is below the already imported transaction
218    #[error("Tx: [{0:?}] insufficient gas price to replace existing transaction")]
219    ReplacementUnderpriced(TxHash),
220    #[error("Tx: [{0:?}] already Imported")]
221    AlreadyImported(TxHash),
222}
223
224/// Errors that can occur with `eth_feeHistory`
225#[derive(Debug, thiserror::Error)]
226pub enum FeeHistoryError {
227    #[error("requested block range is out of bounds")]
228    InvalidBlockRange,
229    #[error("could not find newest block number requested: {0}")]
230    BlockNotFound(BlockNumberOrTag),
231}
232
233#[derive(Debug)]
234pub struct ErrDetail {
235    pub detail: String,
236}
237
238/// An error due to invalid transaction
239#[derive(Debug, thiserror::Error)]
240pub enum InvalidTransactionError {
241    /// returned if the nonce of a transaction is lower than the one present in the local chain.
242    #[error("nonce too low")]
243    NonceTooLow,
244    /// returned if the nonce of a transaction is higher than the next one expected based on the
245    /// local chain.
246    #[error("Nonce too high")]
247    NonceTooHigh,
248    /// Returned if the nonce of a transaction is too high
249    /// Incrementing the nonce would lead to invalid state (overflow)
250    #[error("nonce has max value")]
251    NonceMaxValue,
252    /// thrown if the transaction sender doesn't have enough funds for a transfer
253    #[error("insufficient funds for transfer")]
254    InsufficientFundsForTransfer,
255    /// thrown if creation transaction provides the init code bigger than init code size limit.
256    #[error("max initcode size exceeded")]
257    MaxInitCodeSizeExceeded,
258    /// Represents the inability to cover max cost + value (account balance too low).
259    #[error("Insufficient funds for gas * price + value")]
260    InsufficientFunds,
261    /// Thrown when calculating gas usage
262    #[error("gas uint64 overflow")]
263    GasUintOverflow,
264    /// returned if the transaction is specified to use less gas than required to start the
265    /// invocation.
266    #[error("intrinsic gas too low")]
267    GasTooLow,
268    /// returned if the transaction gas exceeds the limit
269    #[error("intrinsic gas too high -- {}",.0.detail)]
270    GasTooHigh(ErrDetail),
271    /// Thrown to ensure no one is able to specify a transaction with a tip higher than the total
272    /// fee cap.
273    #[error("max priority fee per gas higher than max fee per gas")]
274    TipAboveFeeCap,
275    /// Thrown post London if the transaction's fee is less than the base fee of the block
276    #[error("max fee per gas less than block base fee")]
277    FeeCapTooLow,
278    /// Thrown during estimate if caller has insufficient funds to cover the tx.
279    #[error("Out of gas: gas required exceeds allowance: {0:?}")]
280    BasicOutOfGas(u128),
281    /// Thrown if executing a transaction failed during estimate/call
282    #[error("execution reverted: {0:?}")]
283    Revert(Option<Bytes>),
284    /// Thrown if the sender of a transaction is a contract.
285    #[error("sender not an eoa")]
286    SenderNoEOA,
287    /// Thrown when a tx was signed with a different chain_id
288    #[error("invalid chain id for signer")]
289    InvalidChainId,
290    /// Thrown when a legacy tx was signed for a different chain
291    #[error("Incompatible EIP-155 transaction, signed for another chain")]
292    IncompatibleEIP155,
293    /// Thrown when an access list is used before the berlin hard fork.
294    #[error("Access lists are not supported before the Berlin hardfork")]
295    AccessListNotSupported,
296    /// Thrown when the block's `blob_gas_price` is greater than tx-specified
297    /// `max_fee_per_blob_gas` after Cancun.
298    #[error("Block `blob_gas_price` is greater than tx-specified `max_fee_per_blob_gas`")]
299    BlobFeeCapTooLow(u128, u128),
300    /// Thrown when we receive a tx with `blob_versioned_hashes` and we're not on the Cancun hard
301    /// fork.
302    #[error("Block `blob_versioned_hashes` is not supported before the Cancun hardfork")]
303    BlobVersionedHashesNotSupported,
304    /// Thrown when `max_fee_per_blob_gas` is not supported for blocks before the Cancun hardfork.
305    #[error("`max_fee_per_blob_gas` is not supported for blocks before the Cancun hardfork.")]
306    MaxFeePerBlobGasNotSupported,
307    /// Thrown when there are no `blob_hashes` in the transaction, and it is an EIP-4844 tx.
308    #[error("`blob_hashes` are required for EIP-4844 transactions")]
309    NoBlobHashes,
310    #[error("too many blobs in one transaction, have: {0}, max: {1}")]
311    TooManyBlobs(usize, usize),
312    /// Thrown when there's a blob validation error
313    #[error(transparent)]
314    BlobTransactionValidationError(#[from] alloy_consensus::BlobTransactionValidationError),
315    /// Thrown when Blob transaction is a create transaction. `to` must be present.
316    #[error("Blob transaction can't be a create transaction. `to` must be present.")]
317    BlobCreateTransaction,
318    /// Thrown when Blob transaction contains a versioned hash with an incorrect version.
319    #[error("Blob transaction contains a versioned hash with an incorrect version")]
320    BlobVersionNotSupported,
321    /// Thrown when there are no `blob_hashes` in the transaction.
322    #[error("There should be at least one blob in a Blob transaction.")]
323    EmptyBlobs,
324    /// Thrown when an access list is used before the berlin hard fork.
325    #[error("EIP-7702 authorization lists are not supported before the Prague hardfork")]
326    AuthorizationListNotSupported,
327    #[error("Transaction gas limit is greater than the block gas limit, gas_limit: {0}, cap: {1}")]
328    TxGasLimitGreaterThanCap(u64, u64),
329    /// Forwards error from the revm
330    #[error(transparent)]
331    Revm(revm::context_interface::result::InvalidTransaction),
332    /// Deposit transaction error post regolith
333    #[error("op-deposit failure post regolith")]
334    DepositTxErrorPostRegolith,
335    /// Missing enveloped transaction
336    #[error("missing enveloped transaction")]
337    MissingEnvelopedTx,
338    /// Native ETH value transfers are not allowed in Tempo mode
339    #[error("native value transfer not allowed in Tempo mode")]
340    TempoNativeValueTransfer,
341    /// Tempo transaction valid_before is expired or too close to current time
342    #[error("Tempo tx valid_before ({valid_before}) must be > current time + 3s ({min_allowed})")]
343    TempoValidBeforeExpired { valid_before: u64, min_allowed: u64 },
344    /// Tempo transaction valid_after is too far in the future
345    #[error("Tempo tx valid_after ({valid_after}) must be <= current time + 1h ({max_allowed})")]
346    TempoValidAfterTooFar { valid_after: u64, max_allowed: u64 },
347    /// Tempo transaction has too many authorizations
348    #[error("Tempo tx has too many authorizations ({count}), max allowed is {max}")]
349    TempoTooManyAuthorizations { count: usize, max: usize },
350    /// Tempo transaction fee payer has insufficient fee token balance
351    #[error("insufficient fee token balance: have {balance}, need {required}")]
352    TempoInsufficientFeeTokenBalance { balance: U256, required: U256 },
353}
354
355impl From<InvalidTransaction> for InvalidTransactionError {
356    fn from(err: InvalidTransaction) -> Self {
357        match err {
358            InvalidTransaction::InvalidChainId => Self::InvalidChainId,
359            InvalidTransaction::PriorityFeeGreaterThanMaxFee => Self::TipAboveFeeCap,
360            InvalidTransaction::GasPriceLessThanBasefee => Self::FeeCapTooLow,
361            InvalidTransaction::CallerGasLimitMoreThanBlock => {
362                Self::GasTooHigh(ErrDetail { detail: String::from("CallerGasLimitMoreThanBlock") })
363            }
364            InvalidTransaction::CallGasCostMoreThanGasLimit { .. } => {
365                Self::GasTooHigh(ErrDetail { detail: String::from("CallGasCostMoreThanGasLimit") })
366            }
367            InvalidTransaction::GasFloorMoreThanGasLimit { .. } => {
368                Self::GasTooHigh(ErrDetail { detail: String::from("GasFloorMoreThanGasLimit") })
369            }
370            InvalidTransaction::RejectCallerWithCode => Self::SenderNoEOA,
371            InvalidTransaction::LackOfFundForMaxFee { .. } => Self::InsufficientFunds,
372            InvalidTransaction::OverflowPaymentInTransaction => Self::GasUintOverflow,
373            InvalidTransaction::NonceOverflowInTransaction => Self::NonceMaxValue,
374            InvalidTransaction::CreateInitCodeSizeLimit => Self::MaxInitCodeSizeExceeded,
375            InvalidTransaction::NonceTooHigh { .. } => Self::NonceTooHigh,
376            InvalidTransaction::NonceTooLow { .. } => Self::NonceTooLow,
377            InvalidTransaction::AccessListNotSupported => Self::AccessListNotSupported,
378            InvalidTransaction::BlobGasPriceGreaterThanMax {
379                block_blob_gas_price,
380                tx_max_fee_per_blob_gas,
381            } => Self::BlobFeeCapTooLow(block_blob_gas_price, tx_max_fee_per_blob_gas),
382            InvalidTransaction::BlobVersionedHashesNotSupported => {
383                Self::BlobVersionedHashesNotSupported
384            }
385            InvalidTransaction::MaxFeePerBlobGasNotSupported => Self::MaxFeePerBlobGasNotSupported,
386            InvalidTransaction::BlobCreateTransaction => Self::BlobCreateTransaction,
387            InvalidTransaction::BlobVersionNotSupported => Self::BlobVersionNotSupported,
388            InvalidTransaction::EmptyBlobs => Self::EmptyBlobs,
389            InvalidTransaction::TooManyBlobs { have, max } => Self::TooManyBlobs(have, max),
390            InvalidTransaction::AuthorizationListNotSupported => {
391                Self::AuthorizationListNotSupported
392            }
393            InvalidTransaction::TxGasLimitGreaterThanCap { gas_limit, cap } => {
394                Self::TxGasLimitGreaterThanCap(gas_limit, cap)
395            }
396
397            InvalidTransaction::AuthorizationListInvalidFields
398            | InvalidTransaction::Eip1559NotSupported
399            | InvalidTransaction::Eip2930NotSupported
400            | InvalidTransaction::Eip4844NotSupported
401            | InvalidTransaction::Eip7702NotSupported
402            | InvalidTransaction::EmptyAuthorizationList
403            | InvalidTransaction::Eip7873NotSupported
404            | InvalidTransaction::Eip7873MissingTarget
405            | InvalidTransaction::MissingChainId
406            | InvalidTransaction::Str(_) => Self::Revm(err),
407        }
408    }
409}
410
411/// Helper trait to easily convert results to rpc results
412pub(crate) trait ToRpcResponseResult {
413    fn to_rpc_result(self) -> ResponseResult;
414}
415
416/// Converts a serializable value into a `ResponseResult`
417pub fn to_rpc_result<T: Serialize>(val: T) -> ResponseResult {
418    match serde_json::to_value(val) {
419        Ok(success) => ResponseResult::Success(success),
420        Err(err) => {
421            error!(%err, "Failed serialize rpc response");
422            ResponseResult::error(RpcError::internal_error())
423        }
424    }
425}
426
427impl<T: Serialize> ToRpcResponseResult for Result<T> {
428    fn to_rpc_result(self) -> ResponseResult {
429        match self {
430            Ok(val) => to_rpc_result(val),
431            Err(err) => match err {
432                BlockchainError::Pool(err) => {
433                    error!(%err, "txpool error");
434                    match err {
435                        PoolError::CyclicTransaction => {
436                            RpcError::transaction_rejected("Cyclic transaction detected")
437                        }
438                        PoolError::ReplacementUnderpriced(_) => {
439                            RpcError::transaction_rejected("replacement transaction underpriced")
440                        }
441                        PoolError::AlreadyImported(_) => {
442                            RpcError::transaction_rejected("transaction already imported")
443                        }
444                    }
445                }
446                BlockchainError::NoSignerAvailable => {
447                    RpcError::invalid_params("No Signer available")
448                }
449                BlockchainError::ChainIdNotAvailable => {
450                    RpcError::invalid_params("Chain Id not available")
451                }
452                BlockchainError::TransactionConfirmationTimeout { .. } => {
453                    RpcError::internal_error_with("Transaction confirmation timeout")
454                }
455                BlockchainError::InvalidTransaction(err) => match err {
456                    InvalidTransactionError::Revert(data) => {
457                        // this mimics geth revert error
458                        let mut msg = "execution reverted".to_string();
459                        if let Some(reason) = data
460                            .as_ref()
461                            .and_then(|data| RevertDecoder::new().maybe_decode(data, None))
462                        {
463                            msg = format!("{msg}: {reason}");
464                        }
465                        RpcError {
466                            // geth returns this error code on reverts, See <https://eips.ethereum.org/EIPS/eip-1474#specification>
467                            code: ErrorCode::ExecutionError,
468                            message: msg.into(),
469                            data: serde_json::to_value(data).ok(),
470                        }
471                    }
472                    InvalidTransactionError::GasTooLow => {
473                        // <https://eips.ethereum.org/EIPS/eip-1898>
474                        RpcError {
475                            code: ErrorCode::ServerError(-32000),
476                            message: err.to_string().into(),
477                            data: None,
478                        }
479                    }
480                    InvalidTransactionError::GasTooHigh(_) => {
481                        // <https://eips.ethereum.org/EIPS/eip-1898>
482                        RpcError {
483                            code: ErrorCode::ServerError(-32000),
484                            message: err.to_string().into(),
485                            data: None,
486                        }
487                    }
488                    _ => RpcError::transaction_rejected(err.to_string()),
489                },
490                BlockchainError::FeeHistory(err) => RpcError::invalid_params(err.to_string()),
491                BlockchainError::EmptyRawTransactionData => {
492                    RpcError::invalid_params("Empty transaction data")
493                }
494                BlockchainError::FailedToDecodeSignedTransaction => {
495                    RpcError::invalid_params("Failed to decode transaction")
496                }
497                BlockchainError::FailedToDecodeTransaction => {
498                    RpcError::invalid_params("Failed to decode transaction")
499                }
500                BlockchainError::FailedToDecodeReceipt => {
501                    RpcError::invalid_params("Failed to decode receipt")
502                }
503                BlockchainError::FailedToDecodeStateDump => {
504                    RpcError::invalid_params("Failed to decode state dump")
505                }
506                BlockchainError::SignerError(err) => RpcError::invalid_params(err.to_string()),
507                BlockchainError::SignatureError(err) => RpcError::invalid_params(err.to_string()),
508                BlockchainError::RpcUnimplemented => {
509                    RpcError::internal_error_with("Not implemented")
510                }
511                BlockchainError::PrevrandaoNotSet => RpcError::internal_error_with(err.to_string()),
512                BlockchainError::RpcError(err) => err,
513                BlockchainError::InvalidFeeInput => RpcError::invalid_params(
514                    "Invalid input: `max_priority_fee_per_gas` greater than `max_fee_per_gas`",
515                ),
516                BlockchainError::AlloyForkProvider(err) => {
517                    error!(target: "backend", %err, "fork provider error");
518                    match err {
519                        TransportError::ErrorResp(err) => RpcError {
520                            code: ErrorCode::from(err.code),
521                            message: err.message,
522                            data: err.data.and_then(|data| serde_json::to_value(data).ok()),
523                        },
524                        err => RpcError::internal_error_with(format!("Fork Error: {err:?}")),
525                    }
526                }
527                err @ BlockchainError::EvmError(_) => RpcError {
528                    // VM halts are execution failures, not JSON-RPC server faults. REVERT has a
529                    // dedicated code/data path above; other halts, such as invalid opcode, do not.
530                    code: ErrorCode::TransactionRejected,
531                    message: err.to_string().into(),
532                    data: None,
533                },
534                err @ BlockchainError::EvmOverrideError(_) => {
535                    RpcError::invalid_params(err.to_string())
536                }
537                err @ BlockchainError::InvalidUrl(_) => RpcError::invalid_params(err.to_string()),
538                BlockchainError::Internal(err) => RpcError::internal_error_with(err),
539                err @ BlockchainError::BlockOutOfRange(_, _) => {
540                    RpcError::invalid_params(err.to_string())
541                }
542                err @ BlockchainError::BlockNotFound => RpcError {
543                    // <https://eips.ethereum.org/EIPS/eip-1898>
544                    code: ErrorCode::ServerError(-32001),
545                    message: err.to_string().into(),
546                    data: None,
547                },
548                err @ BlockchainError::TransactionNotFound => RpcError {
549                    code: ErrorCode::ServerError(-32001),
550                    message: err.to_string().into(),
551                    data: None,
552                },
553                err @ BlockchainError::DataUnavailable => {
554                    RpcError::internal_error_with(err.to_string())
555                }
556                err @ BlockchainError::TrieError(_) => {
557                    RpcError::internal_error_with(err.to_string())
558                }
559                BlockchainError::UintConversion(err) => RpcError::invalid_params(err),
560                err @ BlockchainError::StateOverrideError(_) => {
561                    RpcError::invalid_params(err.to_string())
562                }
563                err @ BlockchainError::TimestampError(_) => {
564                    RpcError::invalid_params(err.to_string())
565                }
566                BlockchainError::DatabaseError(err) => {
567                    RpcError::internal_error_with(err.to_string())
568                }
569                err @ BlockchainError::EIP1559TransactionUnsupportedAtHardfork => {
570                    RpcError::invalid_params(err.to_string())
571                }
572                err @ BlockchainError::EIP2930TransactionUnsupportedAtHardfork => {
573                    RpcError::invalid_params(err.to_string())
574                }
575                err @ BlockchainError::EIP4844TransactionUnsupportedAtHardfork => {
576                    RpcError::invalid_params(err.to_string())
577                }
578                err @ BlockchainError::EIP7702TransactionUnsupportedAtHardfork => {
579                    RpcError::invalid_params(err.to_string())
580                }
581                err @ BlockchainError::DepositTransactionUnsupported => {
582                    RpcError::invalid_params(err.to_string())
583                }
584                err @ BlockchainError::TempoTransactionUnsupported => {
585                    RpcError::invalid_params(err.to_string())
586                }
587                err @ BlockchainError::ExcessBlobGasNotSet => {
588                    RpcError::invalid_params(err.to_string())
589                }
590                err @ BlockchainError::Message(_) => RpcError::internal_error_with(err.to_string()),
591                err @ BlockchainError::UnknownTransactionType => {
592                    RpcError::invalid_params(err.to_string())
593                }
594                err @ BlockchainError::InvalidTransactionRequest(_) => {
595                    RpcError::invalid_params(err.to_string())
596                }
597                err @ BlockchainError::RecoveryError(_) => {
598                    RpcError::invalid_params(err.to_string())
599                }
600                BlockchainError::FilterNotFound => RpcError {
601                    code: ErrorCode::ServerError(-32000),
602                    message: "filter not found".into(),
603                    data: None,
604                },
605                err @ BlockchainError::UnknownBlock => RpcError {
606                    code: ErrorCode::ServerError(-32000),
607                    message: err.to_string().into(),
608                    data: None,
609                },
610            }
611            .into(),
612        }
613    }
614}