actors_runtime/
actor_error.rs

1use fvm_shared::error::ExitCode;
2use thiserror::Error;
3
4/// TODO fix error system; actor errors should be transparent to the VM.
5/// The error type that gets returned by actor method calls.
6#[derive(Error, Debug, Clone, PartialEq)]
7#[error("ActorError(exit_code: {exit_code:?}, msg: {msg})")]
8pub struct ActorError {
9    /// The exit code for this invocation, must not be `0`.
10    exit_code: ExitCode,
11    /// Message for debugging purposes,
12    msg: String,
13}
14
15impl ActorError {
16    pub fn new(exit_code: ExitCode, msg: String) -> Self {
17        Self { exit_code, msg }
18    }
19
20    /// Returns the exit code of the error.
21    pub fn exit_code(&self) -> ExitCode {
22        self.exit_code
23    }
24
25    /// Returns true when the exit code is `Ok`.
26    pub fn is_ok(&self) -> bool {
27        self.exit_code == ExitCode::Ok
28    }
29
30    /// Error message of the actor error.
31    pub fn msg(&self) -> &str {
32        &self.msg
33    }
34
35    /// Prefix error message with a string message.
36    pub fn wrap(mut self, msg: impl AsRef<str>) -> Self {
37        self.msg = format!("{}: {}", msg.as_ref(), self.msg);
38        self
39    }
40}
41
42// TODO former EncodingError
43impl From<fvm_shared::encoding::Error> for ActorError {
44    fn from(e: fvm_shared::encoding::Error) -> Self {
45        Self {
46            exit_code: ExitCode::ErrSerialization,
47            msg: e.to_string(),
48        }
49    }
50}
51
52// TODO former CborError
53impl From<fvm_shared::encoding::error::Error> for ActorError {
54    fn from(e: fvm_shared::encoding::error::Error) -> Self {
55        Self {
56            exit_code: ExitCode::ErrSerialization,
57            msg: e.to_string(),
58        }
59    }
60}
61
62/// Converts an actor deletion error into an actor error with the appropriate exit code. This
63/// facilitates propagation.
64#[cfg(target_arch = "wasm32")]
65impl From<fvm_sdk::error::ActorDeleteError> for ActorError {
66    fn from(e: fvm_sdk::error::ActorDeleteError) -> Self {
67        use fvm_sdk::error::ActorDeleteError::*;
68        Self {
69            // FIXME: These shouldn't be "system" errors, but we're trying to match existing
70            // behavior here.
71            exit_code: match e {
72                BeneficiaryIsSelf => ExitCode::SysErrIllegalActor,
73                BeneficiaryDoesNotExist => ExitCode::SysErrIllegalArgument,
74            },
75            msg: e.to_string(),
76        }
77    }
78}
79
80/// Converts a no-state error into an an actor error with the appropriate exit code (illegal actor).
81/// This facilitates propagation.
82#[cfg(target_arch = "wasm32")]
83impl From<fvm_sdk::error::NoStateError> for ActorError {
84    fn from(e: fvm_sdk::error::NoStateError) -> Self {
85        Self {
86            // FIXME: These shouldn't be "system" errors, but we're trying to match existing
87            // behavior here.
88            exit_code: ExitCode::SysErrIllegalActor,
89            msg: e.to_string(),
90        }
91    }
92}
93
94/// Performs conversions from SyscallResult, whose error type is ExitCode,
95/// to ActorErrors. This facilitates propagation.
96impl From<ExitCode> for ActorError {
97    fn from(e: ExitCode) -> Self {
98        ActorError {
99            exit_code: e,
100            msg: "".to_string(),
101        }
102    }
103}
104
105/// Convenience macro for generating Actor Errors
106#[macro_export]
107macro_rules! actor_error {
108    // Error with only one stringable expression
109    ( $code:ident; $msg:expr ) => { $crate::ActorError::new(fvm_shared::error::ExitCode::$code, $msg.to_string()) };
110
111    // String with positional arguments
112    ( $code:ident; $msg:literal $(, $ex:expr)+ ) => {
113        $crate::ActorError::new(fvm_shared::error::ExitCode::$code, format!($msg, $($ex,)*))
114    };
115
116    // Error with only one stringable expression, with comma separator
117    ( $code:ident, $msg:expr ) => { $crate::actor_error!($code; $msg) };
118
119    // String with positional arguments, with comma separator
120    ( $code:ident, $msg:literal $(, $ex:expr)+ ) => {
121        $crate::actor_error!($code; $msg $(, $ex)*)
122    };
123}