hotshot_contract_adapter/
evm.rs

1use alloy::{network::Ethereum, providers::PendingTransactionBuilder, sol_types::SolInterface};
2
3pub trait DecodeRevert {
4    fn maybe_decode_revert<E: SolInterface + std::fmt::Debug>(
5        self,
6    ) -> anyhow::Result<PendingTransactionBuilder<Ethereum>>;
7}
8
9impl DecodeRevert
10    for alloy::contract::Result<PendingTransactionBuilder<Ethereum>, alloy::contract::Error>
11{
12    fn maybe_decode_revert<E: SolInterface + std::fmt::Debug>(
13        self,
14    ) -> anyhow::Result<PendingTransactionBuilder<Ethereum>> {
15        match self {
16            Ok(ret) => Ok(ret),
17            Err(err) => {
18                let decoded = err.as_decoded_interface_error::<E>();
19                let msg = match decoded {
20                    Some(e) => format!("{:?}", e),
21                    None => format!("{:?}", err),
22                };
23                Err(anyhow::anyhow!(msg))
24            },
25        }
26    }
27}
28
29#[cfg(test)]
30mod test {
31    use alloy::{
32        primitives::{Address, U256},
33        providers::ProviderBuilder,
34    };
35
36    use super::*;
37    use crate::sol_types::EspToken::{self, EspTokenErrors};
38
39    #[tokio::test]
40    async fn test_decode_revert_error() -> anyhow::Result<()> {
41        let provider = ProviderBuilder::new().on_anvil_with_wallet();
42
43        let token = EspToken::deploy(&provider).await?;
44        let err = token
45            .transfer(Address::random(), U256::MAX)
46            .send()
47            .await
48            .maybe_decode_revert::<EspTokenErrors>()
49            .unwrap_err();
50        assert!(err.to_string().contains("ERC20InsufficientBalance"));
51
52        Ok(())
53    }
54}