1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// Copyright 2022-2023, Offchain Labs, Inc.
// For licensing, see https://github.com/OffchainLabs/stylus-sdk-rs/blob/stylus/licenses/COPYRIGHT.md

use alloc::vec::Vec;
use alloy_sol_types::{Panic, PanicKind, SolError};

/// Represents error data when a call fails.
#[derive(Debug, PartialEq)]
pub enum Error {
    /// Revert data returned by the other contract.
    Revert(Vec<u8>),
    /// Failure to decode the other contract's return data.
    AbiDecodingFailed(alloy_sol_types::Error),
}

impl From<alloy_sol_types::Error> for Error {
    fn from(err: alloy_sol_types::Error) -> Self {
        Error::AbiDecodingFailed(err)
    }
}

/// Encode an error.
///
/// This is useful so that users can use `Error` as a variant in their error
/// types. It should not be necessary to implement this.
pub trait MethodError {
    /// Users should not have to call this.
    fn encode(self) -> Vec<u8>;
}

impl MethodError for Error {
    #[inline]
    fn encode(self) -> Vec<u8> {
        From::from(self)
    }
}

impl<T: SolError> MethodError for T {
    #[inline]
    fn encode(self) -> Vec<u8> {
        SolError::encode(&self)
    }
}

impl From<Error> for Vec<u8> {
    #[allow(unused)]
    fn from(err: Error) -> Vec<u8> {
        match err {
            Error::Revert(data) => data,
            Error::AbiDecodingFailed(err) => {
                console!("failed to decode return data from external call: {err}");
                Panic::from(PanicKind::Generic).encode()
            }
        }
    }
}