forest/rpc/methods/eth/
errors.rs

1// Copyright 2019-2025 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use crate::rpc::error::RpcErrorData;
5use crate::shim::error::ExitCode;
6use serde::Serialize;
7use std::fmt::Debug;
8use thiserror::Error;
9
10/// This error indicates that the execution reverted while executing the message.
11/// Code is taken from https://github.com/filecoin-project/lotus/blob/release/v1.32.1/api/api_errors.go#L27
12pub const EXECUTION_REVERTED_CODE: i32 = 11;
13
14#[derive(Clone, Debug, Error, Serialize)]
15pub enum EthErrors {
16    #[error("{message}")]
17    ExecutionReverted {
18        message: String,
19        data: Option<String>,
20    },
21}
22
23impl EthErrors {
24    /// Create a new ExecutionReverted error with formatted message
25    pub fn execution_reverted(exit_code: ExitCode, error: &str, reason: &str, data: &[u8]) -> Self {
26        Self::ExecutionReverted {
27            message: format!(
28                "message execution failed (exit=[{exit_code}], revert reason=[{reason}], vm error=[{error}])"
29            ),
30            data: (!data.is_empty()).then(|| format!("0x{}", hex::encode(data))),
31        }
32    }
33}
34
35impl RpcErrorData for EthErrors {
36    fn error_code(&self) -> Option<i32> {
37        match self {
38            EthErrors::ExecutionReverted { .. } => Some(EXECUTION_REVERTED_CODE),
39        }
40    }
41
42    fn error_message(&self) -> Option<String> {
43        match self {
44            EthErrors::ExecutionReverted { message, .. } => Some(message.clone()),
45        }
46    }
47
48    fn error_data(&self) -> Option<serde_json::Value> {
49        match self {
50            EthErrors::ExecutionReverted { data, .. } => {
51                data.clone().map(serde_json::Value::String)
52            }
53        }
54    }
55}