alloy_sol_types/
errors.rs1use crate::abi;
11use alloc::{borrow::Cow, boxed::Box, collections::TryReserveError, string::String};
12use alloy_primitives::{B256, LogData, hex};
13use core::fmt;
14
15pub type Result<T, E = Error> = core::result::Result<T, E>;
17
18#[derive(Clone, Debug, PartialEq)]
20pub enum Error {
21 TypeCheckFail {
23 expected_type: Cow<'static, str>,
25 data: String,
27 },
28
29 Overrun,
31
32 Reserve(TryReserveError),
34
35 BufferNotEmpty,
37
38 ReserMismatch,
40
41 RecursionLimitExceeded(u8),
43
44 InvalidEnumValue {
46 name: &'static str,
48 value: u8,
50 max: u8,
52 },
53
54 InvalidEventSignatureHash {
56 name: &'static str,
58 got: B256,
60 expected: B256,
62 },
63
64 InvalidLog {
66 name: &'static str,
68 log: Box<LogData>,
70 },
71
72 UnknownSelector {
74 name: &'static str,
76 selector: alloy_primitives::FixedBytes<4>,
78 },
79
80 FromHexError(hex::FromHexError),
82
83 Other(Cow<'static, str>),
85}
86
87impl core::error::Error for Error {
88 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
89 match self {
90 Self::Reserve(e) => Some(e),
91 Self::FromHexError(e) => Some(e),
92 _ => None,
93 }
94 }
95}
96
97impl fmt::Display for Error {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 match self {
100 Self::TypeCheckFail { expected_type, data } => {
101 write!(f, "type check failed for {expected_type:?} with data: {data}",)
102 }
103 Self::Overrun
104 | Self::BufferNotEmpty
105 | Self::ReserMismatch
106 | Self::RecursionLimitExceeded(_) => {
107 f.write_str("ABI decoding failed: ")?;
108 match *self {
109 Self::Overrun => f.write_str("buffer overrun while deserializing"),
110 Self::BufferNotEmpty => f.write_str("buffer not empty after deserialization"),
111 Self::ReserMismatch => f.write_str("reserialization did not match original"),
112 Self::RecursionLimitExceeded(limit) => {
113 write!(f, "recursion limit of {limit} exceeded during decoding")
114 }
115 _ => unreachable!(),
116 }
117 }
118 Self::Reserve(e) => e.fmt(f),
119 Self::InvalidEnumValue { name, value, max } => {
120 write!(f, "`{value}` is not a valid {name} enum value (max: `{max}`)")
121 }
122 Self::InvalidEventSignatureHash { name, got, expected } => {
123 write!(
124 f,
125 "invalid signature hash for event {name:?}: got {got}, expected {expected}"
126 )
127 }
128 Self::InvalidLog { name, log } => {
129 write!(f, "could not decode {name} from log: {log:?}")
130 }
131 Self::UnknownSelector { name, selector } => {
132 write!(f, "unknown selector `{selector}` for {name}")
133 }
134 Self::FromHexError(e) => e.fmt(f),
135 Self::Other(e) => f.write_str(e),
136 }
137 }
138}
139
140impl Error {
141 #[cold]
143 pub fn custom(s: impl Into<Cow<'static, str>>) -> Self {
144 Self::Other(s.into())
145 }
146
147 #[cold]
149 pub fn type_check_fail_sig(mut data: &[u8], signature: &'static str) -> Self {
150 if data.len() > 4 {
151 data = &data[..4];
152 }
153 let expected_type = signature.split('(').next().unwrap();
154 Self::type_check_fail(data, expected_type)
155 }
156
157 #[cold]
159 pub fn type_check_fail_token<T: crate::SolType>(token: &T::Token<'_>) -> Self {
160 Self::type_check_fail(&abi::encode(token), T::SOL_NAME)
161 }
162
163 #[cold]
165 pub fn type_check_fail(data: &[u8], expected_type: impl Into<Cow<'static, str>>) -> Self {
166 Self::TypeCheckFail { expected_type: expected_type.into(), data: hex::encode(data) }
167 }
168
169 #[cold]
171 pub fn unknown_selector(name: &'static str, selector: [u8; 4]) -> Self {
172 Self::UnknownSelector { name, selector: selector.into() }
173 }
174
175 #[doc(hidden)] #[cold]
177 pub const fn invalid_event_signature_hash(
178 name: &'static str,
179 got: B256,
180 expected: B256,
181 ) -> Self {
182 Self::InvalidEventSignatureHash { name, got, expected }
183 }
184}
185
186impl From<hex::FromHexError> for Error {
187 #[inline]
188 fn from(value: hex::FromHexError) -> Self {
189 Self::FromHexError(value)
190 }
191}
192
193impl From<TryReserveError> for Error {
194 #[inline]
195 fn from(value: TryReserveError) -> Self {
196 Self::Reserve(value)
197 }
198}