alloy_dyn_abi/
error.rs

1use alloc::{borrow::Cow, string::String};
2use alloy_primitives::{B256, Selector, hex, hex::FromHexError};
3use alloy_sol_types::Error as SolTypesError;
4use core::fmt;
5use parser::Error as TypeParserError;
6
7/// Dynamic ABI result type.
8pub type Result<T, E = Error> = core::result::Result<T, E>;
9
10/// Error when parsing EIP-712 `encodeType` strings
11///
12/// <https://eips.ethereum.org/EIPS/eip-712#definition-of-encodetype>
13#[derive(Clone, Debug, PartialEq)]
14pub enum Error {
15    /// Unknown type referenced from another type.
16    #[cfg(feature = "eip712")]
17    MissingType(String),
18    /// Detected circular dep during typegraph resolution.
19    #[cfg(feature = "eip712")]
20    CircularDependency(String),
21    /// Invalid property definition.
22    #[cfg(feature = "eip712")]
23    InvalidPropertyDefinition(String),
24
25    /// Type mismatch during encoding or coercion.
26    TypeMismatch {
27        /// The expected type.
28        expected: String,
29        /// The actual type.
30        actual: String,
31    },
32    /// Length mismatch during encoding.
33    EncodeLengthMismatch {
34        /// The expected length.
35        expected: usize,
36        /// The actual length.
37        actual: usize,
38    },
39
40    /// Length mismatch during event topic decoding.
41    TopicLengthMismatch {
42        /// The expected length.
43        expected: usize,
44        /// The actual length.
45        actual: usize,
46    },
47
48    /// Selector mismatch during function or error decoding.
49    SelectorMismatch {
50        /// The expected selector.
51        expected: Selector,
52        /// The actual selector.
53        actual: Selector,
54    },
55
56    /// Invalid event signature.
57    EventSignatureMismatch {
58        /// The expected signature.
59        expected: B256,
60        /// The actual signature.
61        actual: B256,
62    },
63
64    /// [`hex`](mod@hex) error.
65    Hex(hex::FromHexError),
66    /// [`alloy_sol_type_parser`] error.
67    TypeParser(TypeParserError),
68    /// [`alloy_sol_types`] error.
69    SolTypes(SolTypesError),
70}
71
72impl From<FromHexError> for Error {
73    #[inline]
74    fn from(e: FromHexError) -> Self {
75        Self::Hex(e)
76    }
77}
78
79impl From<SolTypesError> for Error {
80    #[inline]
81    fn from(e: SolTypesError) -> Self {
82        Self::SolTypes(e)
83    }
84}
85
86impl From<TypeParserError> for Error {
87    #[inline]
88    fn from(e: TypeParserError) -> Self {
89        Self::TypeParser(e)
90    }
91}
92
93impl From<alloc::collections::TryReserveError> for Error {
94    #[inline]
95    fn from(value: alloc::collections::TryReserveError) -> Self {
96        Self::SolTypes(value.into())
97    }
98}
99
100impl core::error::Error for Error {
101    #[inline]
102    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
103        match self {
104            Self::Hex(e) => Some(e),
105            Self::TypeParser(e) => Some(e),
106            Self::SolTypes(e) => Some(e),
107            _ => None,
108        }
109    }
110}
111
112impl fmt::Display for Error {
113    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114        match self {
115            #[cfg(feature = "eip712")]
116            Self::MissingType(name) => write!(f, "missing type in type resolution: {name}"),
117            #[cfg(feature = "eip712")]
118            Self::CircularDependency(dep) => write!(f, "circular dependency: {dep}"),
119            #[cfg(feature = "eip712")]
120            Self::InvalidPropertyDefinition(def) => write!(f, "invalid property definition: {def}"),
121
122            Self::TypeMismatch { expected, actual } => write!(
123                f,
124                "type mismatch: expected type {expected:?}, got value with type {actual:?}",
125            ),
126            &Self::EncodeLengthMismatch { expected, actual } => {
127                write!(f, "encode length mismatch: expected {expected} types, got {actual}",)
128            }
129
130            &Self::TopicLengthMismatch { expected, actual } => {
131                write!(f, "invalid log topic list length: expected {expected} topics, got {actual}",)
132            }
133            Self::EventSignatureMismatch { expected, actual } => {
134                write!(f, "invalid event signature: expected {expected}, got {actual}",)
135            }
136            Self::SelectorMismatch { expected, actual } => {
137                write!(f, "selector mismatch: expected {expected}, got {actual}",)
138            }
139            Self::Hex(e) => e.fmt(f),
140            Self::TypeParser(e) => e.fmt(f),
141            Self::SolTypes(e) => e.fmt(f),
142        }
143    }
144}
145
146impl Error {
147    /// Instantiates a new error with a static str.
148    pub fn custom(s: impl Into<Cow<'static, str>>) -> Self {
149        Self::SolTypes(SolTypesError::custom(s))
150    }
151
152    #[cfg(feature = "eip712")]
153    pub(crate) fn eip712_coerce(expected: &crate::DynSolType, actual: &serde_json::Value) -> Self {
154        #[allow(unused_imports)]
155        use alloc::string::ToString;
156        Self::TypeMismatch { expected: expected.to_string(), actual: actual.to_string() }
157    }
158
159    #[cfg(feature = "eip712")]
160    pub(crate) fn invalid_property_def(def: &str) -> Self {
161        Self::InvalidPropertyDefinition(def.into())
162    }
163
164    #[cfg(feature = "eip712")]
165    pub(crate) fn missing_type(name: &str) -> Self {
166        Self::MissingType(name.into())
167    }
168
169    #[cfg(feature = "eip712")]
170    pub(crate) fn circular_dependency(dep: &str) -> Self {
171        Self::CircularDependency(dep.into())
172    }
173}