alloy_dyn_abi/
error.rs

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