foundry_evm_traces/identifier/
mod.rs

1use alloy_json_abi::JsonAbi;
2use alloy_primitives::Address;
3use foundry_common::ContractsByArtifact;
4use foundry_compilers::ArtifactId;
5use foundry_config::{Chain, Config};
6use std::borrow::Cow;
7
8mod local;
9pub use local::LocalTraceIdentifier;
10
11mod etherscan;
12pub use etherscan::EtherscanIdentifier;
13
14mod signatures;
15pub use signatures::{CachedSignatures, SignaturesIdentifier, SingleSignaturesIdentifier};
16
17/// An address identity
18pub struct AddressIdentity<'a> {
19    /// The address this identity belongs to
20    pub address: Address,
21    /// The label for the address
22    pub label: Option<String>,
23    /// The contract this address represents
24    ///
25    /// Note: This may be in the format `"<artifact>:<contract>"`.
26    pub contract: Option<String>,
27    /// The ABI of the contract at this address
28    pub abi: Option<Cow<'a, JsonAbi>>,
29    /// The artifact ID of the contract, if any.
30    pub artifact_id: Option<ArtifactId>,
31}
32
33/// Trace identifiers figure out what ABIs and labels belong to all the addresses of the trace.
34pub trait TraceIdentifier {
35    /// Attempts to identify an address in one or more call traces.
36    fn identify_addresses<'a, A>(&mut self, addresses: A) -> Vec<AddressIdentity<'_>>
37    where
38        A: Iterator<Item = (&'a Address, Option<&'a [u8]>, Option<&'a [u8]>)> + Clone;
39}
40
41/// A collection of trace identifiers.
42pub struct TraceIdentifiers<'a> {
43    /// The local trace identifier.
44    pub local: Option<LocalTraceIdentifier<'a>>,
45    /// The optional Etherscan trace identifier.
46    pub etherscan: Option<EtherscanIdentifier>,
47}
48
49impl Default for TraceIdentifiers<'_> {
50    fn default() -> Self {
51        Self::new()
52    }
53}
54
55impl TraceIdentifier for TraceIdentifiers<'_> {
56    fn identify_addresses<'a, A>(&mut self, addresses: A) -> Vec<AddressIdentity<'_>>
57    where
58        A: Iterator<Item = (&'a Address, Option<&'a [u8]>, Option<&'a [u8]>)> + Clone,
59    {
60        let mut identities = Vec::new();
61        if let Some(local) = &mut self.local {
62            identities.extend(local.identify_addresses(addresses.clone()));
63        }
64        if let Some(etherscan) = &mut self.etherscan {
65            identities.extend(etherscan.identify_addresses(addresses));
66        }
67        identities
68    }
69}
70
71impl<'a> TraceIdentifiers<'a> {
72    /// Creates a new, empty instance.
73    pub const fn new() -> Self {
74        Self { local: None, etherscan: None }
75    }
76
77    /// Sets the local identifier.
78    pub fn with_local(mut self, known_contracts: &'a ContractsByArtifact) -> Self {
79        self.local = Some(LocalTraceIdentifier::new(known_contracts));
80        self
81    }
82
83    /// Sets the etherscan identifier.
84    pub fn with_etherscan(mut self, config: &Config, chain: Option<Chain>) -> eyre::Result<Self> {
85        self.etherscan = EtherscanIdentifier::new(config, chain)?;
86        Ok(self)
87    }
88
89    /// Returns `true` if there are no set identifiers.
90    pub fn is_empty(&self) -> bool {
91        self.local.is_none() && self.etherscan.is_none()
92    }
93}