1use alloy::sol_types::SolInterface;
5
6pub type Result<T, E = Error> = std::result::Result<T, E>;
7
8#[derive(Debug, thiserror::Error)]
9pub enum Error {
10 #[error("from utf8 error: {0}")]
11 FromUtf8(#[from] std::string::FromUtf8Error),
12 #[error("io error: {0}")]
13 Io(#[from] std::io::Error),
14
15 #[error("rpc error: {0}")]
16 Rpc(#[from] alloy::transports::RpcError<alloy::transports::TransportErrorKind>),
17 #[error("cargo metadata error: {0}")]
18 CargoMetadata(#[from] cargo_metadata::Error),
19 #[error("json error: {0}")]
20 Json(#[from] serde_json::Error),
21 #[error("toml serialize error: {0}")]
22 TomlSerialize(#[from] toml::ser::Error),
23 #[error("toml deserialize error: {0}")]
24 TomlDeserialize(#[from] toml::de::Error),
25
26 #[error("command failed (exit code: {code:?})", code = .0.exit_code)]
28 CommandFailure(crate::core::message::ProcessOutput),
29 #[error("{0}")]
30 Build(#[from] crate::core::build::BuildError),
31 #[error("{0}")]
32 Toolchain(#[from] crate::utils::toolchain::ToolchainError),
33}
34
35#[derive(Debug, thiserror::Error)]
36pub enum CommandError {
37 #[error("io error: {0}")]
38 Io(#[from] std::io::Error),
39 #[error("{0}")]
40 CommandFailure(#[from] CommandFailure),
41}
42
43#[derive(Debug, thiserror::Error)]
44#[error("command failed (exit code: {code:?}", code = .0.exit_code)]
45pub struct CommandFailure(crate::core::message::ProcessOutput);
46
47impl CommandFailure {
48 pub fn check(
49 process_name: impl Into<String>,
50 output: std::process::Output,
51 ) -> Result<String, Self> {
52 let process_output = crate::core::message::ProcessOutput {
53 process_name: process_name.into(),
54 stdout: String::from_utf8_lossy(&output.stdout).to_string(),
55 stderr: String::from_utf8_lossy(&output.stderr).to_string(),
56 exit_code: output.status.code(),
57 };
58 if output.status.success() {
59 Ok(process_output.stdout)
60 } else {
61 Err(CommandFailure(process_output))
62 }
63 }
64}
65
66#[derive(Debug, thiserror::Error)]
67pub enum ContractDecodeError {
68 #[error("failed to send tx: {0:?}")]
69 FailedToSendTx(alloy::contract::Error),
70 #[error("no error payload found in response: {0:?}")]
71 NoErrorPayload(alloy::transports::RpcError<alloy::transports::TransportErrorKind>),
72 #[error("failed to decode error: {0:?}")]
73 FailedToDecode(alloy::rpc::json_rpc::ErrorPayload),
74}
75
76pub fn decode_contract_error<E: SolInterface>(
77 e: alloy::contract::Error,
78) -> Result<E, ContractDecodeError> {
79 let alloy::contract::Error::TransportError(tperr) = e else {
80 return Err(ContractDecodeError::FailedToSendTx(e));
81 };
82 let Some(err_resp) = tperr.as_error_resp() else {
83 return Err(ContractDecodeError::NoErrorPayload(tperr));
84 };
85 let Some(errs) = err_resp.as_decoded_interface_error::<E>() else {
86 return Err(ContractDecodeError::FailedToDecode(err_resp.clone()));
87 };
88 Ok(errs)
89}