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
17pub struct AddressIdentity<'a> {
19 pub address: Address,
21 pub label: Option<String>,
23 pub contract: Option<String>,
27 pub abi: Option<Cow<'a, JsonAbi>>,
29 pub artifact_id: Option<ArtifactId>,
31}
32
33pub trait TraceIdentifier {
35 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
41pub struct TraceIdentifiers<'a> {
43 pub local: Option<LocalTraceIdentifier<'a>>,
45 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 pub const fn new() -> Self {
74 Self { local: None, etherscan: None }
75 }
76
77 pub fn with_local(mut self, known_contracts: &'a ContractsByArtifact) -> Self {
79 self.local = Some(LocalTraceIdentifier::new(known_contracts));
80 self
81 }
82
83 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 pub fn is_empty(&self) -> bool {
91 self.local.is_none() && self.etherscan.is_none()
92 }
93}