alloy_sol_types/types/interface/
mod.rs

1use crate::{alloc::string::ToString, Error, Panic, Result, Revert, SolError};
2use alloc::{string::String, vec::Vec};
3use core::{convert::Infallible, fmt, iter::FusedIterator, marker::PhantomData};
4
5mod event;
6pub use event::SolEventInterface;
7
8/// A collection of ABI-encodable call-like types. This currently includes
9/// [`SolCall`] and [`SolError`].
10///
11/// This trait assumes that the implementing type always has a selector, and
12/// thus encoded/decoded data is always at least 4 bytes long.
13///
14/// This trait is implemented for [`Infallible`] to represent an empty
15/// interface. This is used by [`GenericContractError`].
16///
17/// [`SolCall`]: crate::SolCall
18/// [`SolError`]: crate::SolError
19///
20/// # Implementer's Guide
21///
22/// It should not be necessary to implement this trait manually. Instead, use
23/// the [`sol!`](crate::sol!) procedural macro to parse Solidity syntax into
24/// types that implement this trait.
25pub trait SolInterface: Sized {
26    /// The name of this type.
27    const NAME: &'static str;
28
29    /// The minimum length of the data for this type.
30    ///
31    /// This does *not* include the selector's length (4).
32    const MIN_DATA_LENGTH: usize;
33
34    /// The number of variants.
35    const COUNT: usize;
36
37    /// The selector of this instance.
38    fn selector(&self) -> [u8; 4];
39
40    /// The selector of this type at the given index, used in
41    /// [`selectors`](Self::selectors).
42    ///
43    /// This **must** return `None` if `i >= Self::COUNT`, and `Some` with a
44    /// different selector otherwise.
45    fn selector_at(i: usize) -> Option<[u8; 4]>;
46
47    /// Returns `true` if the given selector is known to this type.
48    fn valid_selector(selector: [u8; 4]) -> bool;
49
50    /// Returns an error if the given selector is not known to this type.
51    fn type_check(selector: [u8; 4]) -> Result<()> {
52        if Self::valid_selector(selector) {
53            Ok(())
54        } else {
55            Err(Error::UnknownSelector { name: Self::NAME, selector: selector.into() })
56        }
57    }
58
59    /// ABI-decodes the given data into one of the variants of `self`.
60    fn abi_decode_raw(selector: [u8; 4], data: &[u8]) -> Result<Self>;
61
62    /// ABI-decodes the given data into one of the variants of `self`, with validation.
63    ///
64    /// This is the same as [`abi_decode_raw`](Self::abi_decode_raw), but performs
65    /// validation checks on the decoded variant's data.
66    fn abi_decode_raw_validate(selector: [u8; 4], data: &[u8]) -> Result<Self>;
67
68    /// The size of the encoded data, *without* any selectors.
69    fn abi_encoded_size(&self) -> usize;
70
71    /// ABI-encodes `self` into the given buffer, *without* any selectors.
72    fn abi_encode_raw(&self, out: &mut Vec<u8>);
73
74    /// Returns an iterator over the selectors of this type.
75    #[inline]
76    fn selectors() -> Selectors<Self> {
77        Selectors::new()
78    }
79
80    /// ABI-encodes `self` into the given buffer.
81    #[inline]
82    fn abi_encode(&self) -> Vec<u8> {
83        let mut out = Vec::with_capacity(4 + self.abi_encoded_size());
84        out.extend(self.selector());
85        self.abi_encode_raw(&mut out);
86        out
87    }
88
89    /// ABI-decodes the given data into one of the variants of `self`.
90    #[inline]
91    fn abi_decode(data: &[u8]) -> Result<Self> {
92        if data.len() < Self::MIN_DATA_LENGTH.saturating_add(4) {
93            Err(crate::Error::type_check_fail(data, Self::NAME))
94        } else {
95            let (selector, data) = data.split_first_chunk().unwrap();
96            Self::abi_decode_raw(*selector, data)
97        }
98    }
99
100    /// ABI-decodes the given data into one of the variants of `self`, with validation.
101    ///
102    /// This is the same as [`abi_decode`](Self::abi_decode), but performs validation
103    /// checks on the decoded variant's data.
104    #[inline]
105    fn abi_decode_validate(data: &[u8]) -> Result<Self> {
106        if data.len() < Self::MIN_DATA_LENGTH.saturating_add(4) {
107            Err(crate::Error::type_check_fail(data, Self::NAME))
108        } else {
109            let (selector, data) = data.split_first_chunk().unwrap();
110            Self::abi_decode_raw_validate(*selector, data)
111        }
112    }
113}
114
115/// An empty [`SolInterface`] implementation. Used by [`GenericContractError`].
116impl SolInterface for Infallible {
117    // better than "Infallible" since it shows up in error messages
118    const NAME: &'static str = "GenericContractError";
119
120    // no selectors or data are valid
121    const MIN_DATA_LENGTH: usize = usize::MAX;
122    const COUNT: usize = 0;
123
124    #[inline]
125    fn selector(&self) -> [u8; 4] {
126        unreachable!()
127    }
128
129    #[inline]
130    fn selector_at(_i: usize) -> Option<[u8; 4]> {
131        None
132    }
133
134    #[inline]
135    fn valid_selector(_selector: [u8; 4]) -> bool {
136        false
137    }
138
139    #[inline]
140    fn abi_decode_raw(selector: [u8; 4], _data: &[u8]) -> Result<Self> {
141        Self::type_check(selector).map(|()| unreachable!())
142    }
143
144    #[inline]
145    fn abi_decode_raw_validate(selector: [u8; 4], _data: &[u8]) -> Result<Self> {
146        Self::type_check(selector).map(|()| unreachable!())
147    }
148
149    #[inline]
150    fn abi_encoded_size(&self) -> usize {
151        unreachable!()
152    }
153
154    #[inline]
155    fn abi_encode_raw(&self, _out: &mut Vec<u8>) {
156        unreachable!()
157    }
158}
159
160/// A generic contract error.
161///
162/// Contains a [`Revert`] or [`Panic`] error.
163pub type GenericContractError = ContractError<Infallible>;
164
165/// A generic contract error.
166///
167/// Contains a [`Revert`] or [`Panic`] error, or a custom error.
168///
169/// If you want an empty [`CustomError`](ContractError::CustomError) variant,
170/// use [`GenericContractError`].
171#[derive(Clone, Debug, PartialEq, Eq)]
172pub enum ContractError<T> {
173    /// A contract's custom error.
174    CustomError(T),
175    /// A generic revert. See [`Revert`] for more information.
176    Revert(Revert),
177    /// A panic. See [`Panic`] for more information.
178    Panic(Panic),
179}
180
181impl<T: SolInterface> From<T> for ContractError<T> {
182    #[inline]
183    fn from(value: T) -> Self {
184        Self::CustomError(value)
185    }
186}
187
188impl<T> From<Revert> for ContractError<T> {
189    #[inline]
190    fn from(value: Revert) -> Self {
191        Self::Revert(value)
192    }
193}
194
195impl<T> TryFrom<ContractError<T>> for Revert {
196    type Error = ContractError<T>;
197
198    #[inline]
199    fn try_from(value: ContractError<T>) -> Result<Self, Self::Error> {
200        match value {
201            ContractError::Revert(inner) => Ok(inner),
202            _ => Err(value),
203        }
204    }
205}
206
207impl<T> From<Panic> for ContractError<T> {
208    #[inline]
209    fn from(value: Panic) -> Self {
210        Self::Panic(value)
211    }
212}
213
214impl<T> TryFrom<ContractError<T>> for Panic {
215    type Error = ContractError<T>;
216
217    #[inline]
218    fn try_from(value: ContractError<T>) -> Result<Self, Self::Error> {
219        match value {
220            ContractError::Panic(inner) => Ok(inner),
221            _ => Err(value),
222        }
223    }
224}
225
226impl<T: fmt::Display> fmt::Display for ContractError<T> {
227    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228        match self {
229            Self::CustomError(error) => error.fmt(f),
230            Self::Panic(panic) => panic.fmt(f),
231            Self::Revert(revert) => revert.fmt(f),
232        }
233    }
234}
235
236impl<T: core::error::Error + 'static> core::error::Error for ContractError<T> {
237    #[inline]
238    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
239        match self {
240            Self::CustomError(error) => Some(error),
241            Self::Panic(panic) => Some(panic),
242            Self::Revert(revert) => Some(revert),
243        }
244    }
245}
246
247impl<T: SolInterface> SolInterface for ContractError<T> {
248    const NAME: &'static str = "ContractError";
249
250    // revert is 64, panic is 32
251    const MIN_DATA_LENGTH: usize = if T::MIN_DATA_LENGTH < 32 { T::MIN_DATA_LENGTH } else { 32 };
252
253    const COUNT: usize = T::COUNT + 2;
254
255    #[inline]
256    fn selector(&self) -> [u8; 4] {
257        match self {
258            Self::CustomError(error) => error.selector(),
259            Self::Panic(_) => Panic::SELECTOR,
260            Self::Revert(_) => Revert::SELECTOR,
261        }
262    }
263
264    #[inline]
265    fn selector_at(i: usize) -> Option<[u8; 4]> {
266        if i < T::COUNT {
267            T::selector_at(i)
268        } else {
269            match i - T::COUNT {
270                0 => Some(Revert::SELECTOR),
271                1 => Some(Panic::SELECTOR),
272                _ => None,
273            }
274        }
275    }
276
277    #[inline]
278    fn valid_selector(selector: [u8; 4]) -> bool {
279        match selector {
280            Revert::SELECTOR | Panic::SELECTOR => true,
281            s => T::valid_selector(s),
282        }
283    }
284
285    #[inline]
286    fn abi_decode_raw(selector: [u8; 4], data: &[u8]) -> Result<Self> {
287        match selector {
288            Revert::SELECTOR => Revert::abi_decode_raw(data).map(Self::Revert),
289            Panic::SELECTOR => Panic::abi_decode_raw(data).map(Self::Panic),
290            s => T::abi_decode_raw(s, data).map(Self::CustomError),
291        }
292    }
293
294    #[inline]
295    fn abi_decode_raw_validate(selector: [u8; 4], data: &[u8]) -> Result<Self> {
296        match selector {
297            Revert::SELECTOR => {
298                <Revert as SolError>::abi_decode_raw_validate(data).map(Self::Revert)
299            }
300            Panic::SELECTOR => <Panic as SolError>::abi_decode_raw_validate(data).map(Self::Panic),
301            s => T::abi_decode_raw_validate(s, data).map(Self::CustomError),
302        }
303    }
304
305    #[inline]
306    fn abi_encoded_size(&self) -> usize {
307        match self {
308            Self::CustomError(error) => error.abi_encoded_size(),
309            Self::Panic(panic) => panic.abi_encoded_size(),
310            Self::Revert(revert) => revert.abi_encoded_size(),
311        }
312    }
313
314    #[inline]
315    fn abi_encode_raw(&self, out: &mut Vec<u8>) {
316        match self {
317            Self::CustomError(error) => error.abi_encode_raw(out),
318            Self::Panic(panic) => panic.abi_encode_raw(out),
319            Self::Revert(revert) => revert.abi_encode_raw(out),
320        }
321    }
322}
323
324impl<T> ContractError<T> {
325    /// Returns `true` if `self` matches [`CustomError`](Self::CustomError).
326    #[inline]
327    pub const fn is_custom_error(&self) -> bool {
328        matches!(self, Self::CustomError(_))
329    }
330
331    /// Returns an immutable reference to the inner custom error if `self`
332    /// matches [`CustomError`](Self::CustomError).
333    #[inline]
334    pub const fn as_custom_error(&self) -> Option<&T> {
335        match self {
336            Self::CustomError(inner) => Some(inner),
337            _ => None,
338        }
339    }
340
341    /// Returns a mutable reference to the inner custom error if `self`
342    /// matches [`CustomError`](Self::CustomError).
343    #[inline]
344    pub fn as_custom_error_mut(&mut self) -> Option<&mut T> {
345        match self {
346            Self::CustomError(inner) => Some(inner),
347            _ => None,
348        }
349    }
350
351    /// Returns `true` if `self` matches [`Revert`](Self::Revert).
352    #[inline]
353    pub const fn is_revert(&self) -> bool {
354        matches!(self, Self::Revert(_))
355    }
356
357    /// Returns an immutable reference to the inner [`Revert`] if `self` matches
358    /// [`Revert`](Self::Revert).
359    #[inline]
360    pub const fn as_revert(&self) -> Option<&Revert> {
361        match self {
362            Self::Revert(inner) => Some(inner),
363            _ => None,
364        }
365    }
366
367    /// Returns a mutable reference to the inner [`Revert`] if `self` matches
368    /// [`Revert`](Self::Revert).
369    #[inline]
370    pub fn as_revert_mut(&mut self) -> Option<&mut Revert> {
371        match self {
372            Self::Revert(inner) => Some(inner),
373            _ => None,
374        }
375    }
376
377    /// Returns `true` if `self` matches [`Panic`](Self::Panic).
378    #[inline]
379    pub const fn is_panic(&self) -> bool {
380        matches!(self, Self::Panic(_))
381    }
382
383    /// Returns an immutable reference to the inner [`Panic`] if `self` matches
384    /// [`Panic`](Self::Panic).
385    #[inline]
386    pub const fn as_panic(&self) -> Option<&Panic> {
387        match self {
388            Self::Panic(inner) => Some(inner),
389            _ => None,
390        }
391    }
392
393    /// Returns a mutable reference to the inner [`Panic`] if `self` matches
394    /// [`Panic`](Self::Panic).
395    #[inline]
396    pub fn as_panic_mut(&mut self) -> Option<&mut Panic> {
397        match self {
398            Self::Panic(inner) => Some(inner),
399            _ => None,
400        }
401    }
402}
403
404/// Represents the reason for a revert in a generic contract error.
405pub type GenericRevertReason = RevertReason<Infallible>;
406
407/// Represents the reason for a revert in a smart contract.
408///
409/// This enum captures two possible scenarios for a revert:
410///
411/// - [`ContractError`](RevertReason::ContractError): Contains detailed error information, such as a
412///   specific [`Revert`] or [`Panic`] error.
413///
414/// - [`RawString`](RevertReason::RawString): Represents a raw string message as the reason for the
415///   revert.
416#[derive(Clone, Debug, PartialEq, Eq)]
417pub enum RevertReason<T> {
418    /// A detailed contract error, including a specific revert or panic error.
419    ContractError(ContractError<T>),
420    /// Represents a raw string message as the reason for the revert.
421    RawString(String),
422}
423
424impl<T: fmt::Display> fmt::Display for RevertReason<T> {
425    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
426        match self {
427            Self::ContractError(error) => error.fmt(f),
428            Self::RawString(raw_string) => f.write_str(raw_string),
429        }
430    }
431}
432
433/// Converts a `ContractError<T>` into a `RevertReason<T>`.
434impl<T> From<ContractError<T>> for RevertReason<T> {
435    fn from(error: ContractError<T>) -> Self {
436        Self::ContractError(error)
437    }
438}
439
440/// Converts a `Revert` into a `RevertReason<T>`.
441impl<T> From<Revert> for RevertReason<T> {
442    fn from(revert: Revert) -> Self {
443        Self::ContractError(ContractError::Revert(revert))
444    }
445}
446
447/// Converts a `String` into a `RevertReason<T>`.
448impl<T> From<String> for RevertReason<T> {
449    fn from(raw_string: String) -> Self {
450        Self::RawString(raw_string)
451    }
452}
453
454impl<T: SolInterface> RevertReason<T>
455where
456    Self: From<ContractError<Infallible>>,
457{
458    /// Decodes and retrieves the reason for a revert from the provided output data.
459    ///
460    /// This method attempts to decode the provided output data as a generic contract error
461    /// or a UTF-8 string (for Vyper reverts).
462    ///
463    /// If successful, it returns the decoded revert reason wrapped in an `Option`.
464    ///
465    /// If both attempts fail, it returns `None`.
466    pub fn decode(out: &[u8]) -> Option<Self> {
467        // Try to decode as a generic contract error.
468        if let Ok(error) = ContractError::<T>::abi_decode(out) {
469            return Some(error.into());
470        }
471
472        // If that fails, try to decode as a regular string.
473        if let Ok(decoded_string) = core::str::from_utf8(out) {
474            return Some(decoded_string.to_string().into());
475        }
476
477        // If both attempts fail, return None.
478        None
479    }
480}
481
482impl<T: SolInterface + fmt::Display> RevertReason<T> {
483    /// Returns the reason for a revert as a string.
484    #[allow(clippy::inherent_to_string_shadow_display)]
485    pub fn to_string(&self) -> String {
486        match self {
487            Self::ContractError(error) => error.to_string(),
488            Self::RawString(raw_string) => raw_string.clone(),
489        }
490    }
491}
492
493impl<T> RevertReason<T> {
494    /// Returns the raw string error message if this type is a [`RevertReason::RawString`]
495    pub fn as_raw_error(&self) -> Option<&str> {
496        match self {
497            Self::RawString(error) => Some(error.as_str()),
498            _ => None,
499        }
500    }
501
502    /// Returns the [`ContractError`] if this type is a [`RevertReason::ContractError`]
503    pub const fn as_contract_error(&self) -> Option<&ContractError<T>> {
504        match self {
505            Self::ContractError(error) => Some(error),
506            _ => None,
507        }
508    }
509
510    /// Returns `true` if `self` matches [`Revert`](ContractError::Revert).
511    pub const fn is_revert(&self) -> bool {
512        matches!(self, Self::ContractError(ContractError::Revert(_)))
513    }
514
515    /// Returns `true` if `self` matches [`Panic`](ContractError::Panic).
516    pub const fn is_panic(&self) -> bool {
517        matches!(self, Self::ContractError(ContractError::Panic(_)))
518    }
519
520    /// Returns `true` if `self` matches [`CustomError`](ContractError::CustomError).
521    pub const fn is_custom_error(&self) -> bool {
522        matches!(self, Self::ContractError(ContractError::CustomError(_)))
523    }
524}
525
526/// Iterator over the function or error selectors of a [`SolInterface`] type.
527///
528/// This `struct` is created by the [`selectors`] method on [`SolInterface`].
529/// See its documentation for more.
530///
531/// [`selectors`]: SolInterface::selectors
532pub struct Selectors<T> {
533    index: usize,
534    _marker: PhantomData<T>,
535}
536
537impl<T> Clone for Selectors<T> {
538    fn clone(&self) -> Self {
539        Self { index: self.index, _marker: PhantomData }
540    }
541}
542
543impl<T> fmt::Debug for Selectors<T> {
544    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
545        f.debug_struct("Selectors").field("index", &self.index).finish()
546    }
547}
548
549impl<T> Selectors<T> {
550    #[inline]
551    const fn new() -> Self {
552        Self { index: 0, _marker: PhantomData }
553    }
554}
555
556impl<T: SolInterface> Iterator for Selectors<T> {
557    type Item = [u8; 4];
558
559    #[inline]
560    fn next(&mut self) -> Option<Self::Item> {
561        let selector = T::selector_at(self.index)?;
562        self.index += 1;
563        Some(selector)
564    }
565
566    #[inline]
567    fn size_hint(&self) -> (usize, Option<usize>) {
568        let exact = self.len();
569        (exact, Some(exact))
570    }
571
572    #[inline]
573    fn count(self) -> usize {
574        self.len()
575    }
576}
577
578impl<T: SolInterface> ExactSizeIterator for Selectors<T> {
579    #[inline]
580    fn len(&self) -> usize {
581        T::COUNT - self.index
582    }
583}
584
585impl<T: SolInterface> FusedIterator for Selectors<T> {}
586
587#[cfg(test)]
588mod tests {
589    use super::*;
590    use alloy_primitives::{keccak256, U256};
591
592    fn sel(s: &str) -> [u8; 4] {
593        keccak256(s)[..4].try_into().unwrap()
594    }
595
596    #[test]
597    fn generic_contract_error_enum() {
598        assert_eq!(
599            GenericContractError::selectors().collect::<Vec<_>>(),
600            [sel("Error(string)"), sel("Panic(uint256)")]
601        );
602    }
603
604    #[test]
605    fn contract_error_enum_1() {
606        crate::sol! {
607            #[derive(Debug, PartialEq, Eq)]
608            contract C {
609                error Err1();
610            }
611        }
612
613        assert_eq!(C::CErrors::COUNT, 1);
614        assert_eq!(C::CErrors::MIN_DATA_LENGTH, 0);
615        assert_eq!(ContractError::<C::CErrors>::COUNT, 1 + 2);
616        assert_eq!(ContractError::<C::CErrors>::MIN_DATA_LENGTH, 0);
617
618        assert_eq!(C::CErrors::SELECTORS, [sel("Err1()")]);
619        assert_eq!(
620            ContractError::<C::CErrors>::selectors().collect::<Vec<_>>(),
621            vec![sel("Err1()"), sel("Error(string)"), sel("Panic(uint256)")],
622        );
623
624        for selector in C::CErrors::selectors() {
625            assert!(C::CErrors::valid_selector(selector));
626        }
627
628        for selector in ContractError::<C::CErrors>::selectors() {
629            assert!(ContractError::<C::CErrors>::valid_selector(selector));
630        }
631
632        let err1 = || C::Err1 {};
633        let errors_err1 = || C::CErrors::Err1(err1());
634        let contract_error_err1 = || ContractError::<C::CErrors>::CustomError(errors_err1());
635        let encoded_data = err1().abi_encode();
636        let selector = C::Err1::SELECTOR;
637        let raw_data = &encoded_data[4..];
638
639        assert_eq!(encoded_data[..4], selector);
640        assert_eq!(errors_err1().abi_encode(), encoded_data);
641        assert_eq!(contract_error_err1().abi_encode(), encoded_data);
642
643        assert_eq!(C::Err1::abi_decode(&encoded_data), Ok(err1()));
644        assert_eq!(
645            <C::CErrors as SolInterface>::abi_decode_validate(&encoded_data),
646            Ok(errors_err1())
647        );
648        assert_eq!(
649            <ContractError<C::CErrors> as SolInterface>::abi_decode_validate(&encoded_data),
650            Ok(contract_error_err1())
651        );
652
653        assert_eq!(
654            <C::CErrors as SolInterface>::abi_decode_raw_validate(selector, raw_data),
655            Ok(errors_err1())
656        );
657        assert_eq!(
658            <ContractError<C::CErrors> as SolInterface>::abi_decode_raw_validate(
659                selector, raw_data
660            ),
661            Ok(contract_error_err1())
662        );
663
664        for selector in C::CErrors::selectors() {
665            assert!(C::CErrors::valid_selector(selector));
666        }
667
668        for selector in ContractError::<C::CErrors>::selectors() {
669            assert!(ContractError::<C::CErrors>::valid_selector(selector));
670        }
671    }
672
673    #[test]
674    fn contract_error_enum_2() {
675        crate::sol! {
676            #[derive(Debug, PartialEq, Eq)]
677            contract C {
678                error Err1();
679                error Err2(uint256);
680                error Err3(string);
681            }
682        }
683
684        assert_eq!(C::CErrors::COUNT, 3);
685        assert_eq!(C::CErrors::MIN_DATA_LENGTH, 0);
686        assert_eq!(ContractError::<C::CErrors>::COUNT, 2 + 3);
687        assert_eq!(ContractError::<C::CErrors>::MIN_DATA_LENGTH, 0);
688
689        // sorted by selector
690        assert_eq!(
691            C::CErrors::SELECTORS,
692            [sel("Err3(string)"), sel("Err2(uint256)"), sel("Err1()")]
693        );
694        assert_eq!(
695            ContractError::<C::CErrors>::selectors().collect::<Vec<_>>(),
696            [
697                sel("Err3(string)"),
698                sel("Err2(uint256)"),
699                sel("Err1()"),
700                sel("Error(string)"),
701                sel("Panic(uint256)"),
702            ],
703        );
704
705        let err1 = || C::Err1 {};
706        let errors_err1 = || C::CErrors::Err1(err1());
707        let contract_error_err1 = || ContractError::<C::CErrors>::CustomError(errors_err1());
708        let encoded_data1 = err1().abi_encode();
709        let selector1 = C::Err1::SELECTOR;
710        let raw_data1 = &encoded_data1[4..];
711
712        assert_eq!(encoded_data1[..4], selector1);
713        assert_eq!(errors_err1().abi_encode(), encoded_data1);
714        assert_eq!(contract_error_err1().abi_encode(), encoded_data1);
715
716        assert_eq!(C::Err1::abi_decode(&encoded_data1), Ok(err1()));
717        assert_eq!(
718            <C::CErrors as SolInterface>::abi_decode_validate(&encoded_data1),
719            Ok(errors_err1())
720        );
721        assert_eq!(
722            <ContractError<C::CErrors> as SolInterface>::abi_decode_validate(&encoded_data1),
723            Ok(contract_error_err1())
724        );
725
726        assert_eq!(
727            <C::CErrors as SolInterface>::abi_decode_raw_validate(selector1, raw_data1),
728            Ok(errors_err1())
729        );
730        assert_eq!(
731            <ContractError<C::CErrors> as SolInterface>::abi_decode_raw_validate(
732                selector1, raw_data1
733            ),
734            Ok(contract_error_err1())
735        );
736
737        let err2 = || C::Err2(U256::from(42));
738        let errors_err2 = || C::CErrors::Err2(err2());
739        let contract_error_err2 = || ContractError::<C::CErrors>::CustomError(errors_err2());
740        let encoded_data2 = err2().abi_encode();
741        let selector2 = C::Err2::SELECTOR;
742        let raw_data2 = &encoded_data2[4..];
743
744        assert_eq!(encoded_data2[..4], selector2);
745        assert_eq!(errors_err2().abi_encode(), encoded_data2);
746        assert_eq!(contract_error_err2().abi_encode(), encoded_data2);
747
748        assert_eq!(C::Err2::abi_decode(&encoded_data2), Ok(err2()));
749        assert_eq!(
750            <C::CErrors as SolInterface>::abi_decode_validate(&encoded_data2),
751            Ok(errors_err2())
752        );
753        assert_eq!(
754            <ContractError<C::CErrors> as SolInterface>::abi_decode_validate(&encoded_data2),
755            Ok(contract_error_err2())
756        );
757
758        assert_eq!(
759            <C::CErrors as SolInterface>::abi_decode_raw_validate(selector2, raw_data2),
760            Ok(errors_err2())
761        );
762        assert_eq!(
763            <ContractError<C::CErrors> as SolInterface>::abi_decode_raw_validate(
764                selector2, raw_data2
765            ),
766            Ok(contract_error_err2())
767        );
768
769        let err3 = || C::Err3("hello".into());
770        let errors_err3 = || C::CErrors::Err3(err3());
771        let contract_error_err3 = || ContractError::<C::CErrors>::CustomError(errors_err3());
772        let encoded_data3 = err3().abi_encode();
773        let selector3 = C::Err3::SELECTOR;
774        let raw_data3 = &encoded_data3[4..];
775
776        assert_eq!(encoded_data3[..4], selector3);
777        assert_eq!(errors_err3().abi_encode(), encoded_data3);
778        assert_eq!(contract_error_err3().abi_encode(), encoded_data3);
779
780        assert_eq!(C::Err3::abi_decode(&encoded_data3), Ok(err3()));
781        assert_eq!(
782            <C::CErrors as SolInterface>::abi_decode_validate(&encoded_data3),
783            Ok(errors_err3())
784        );
785        assert_eq!(
786            <ContractError<C::CErrors> as SolInterface>::abi_decode_validate(&encoded_data3),
787            Ok(contract_error_err3())
788        );
789
790        assert_eq!(
791            <C::CErrors as SolInterface>::abi_decode_raw_validate(selector3, raw_data3),
792            Ok(errors_err3())
793        );
794        assert_eq!(
795            <ContractError<C::CErrors> as SolInterface>::abi_decode_raw_validate(
796                selector3, raw_data3
797            ),
798            Ok(contract_error_err3())
799        );
800
801        for selector in C::CErrors::selectors() {
802            assert!(C::CErrors::valid_selector(selector));
803        }
804
805        for selector in ContractError::<C::CErrors>::selectors() {
806            assert!(ContractError::<C::CErrors>::valid_selector(selector));
807        }
808    }
809}