foundry_evm_traces/identifier/
mod.rs1use alloy_json_abi::JsonAbi;
2use alloy_primitives::{Address, Bytes, map::AddressHashMap};
3use foundry_common::ContractsByArtifact;
4use foundry_compilers::ArtifactId;
5use foundry_config::{Chain, Config};
6use revm_inspectors::tracing::types::CallTraceNode;
7use std::borrow::Cow;
8
9mod local;
10pub use local::LocalTraceIdentifier;
11
12mod external;
13pub use external::ExternalIdentifier;
14
15mod signatures;
16pub use signatures::{SignaturesCache, SignaturesIdentifier};
17
18#[derive(Debug)]
20pub struct IdentifiedAddress<'a> {
21 pub address: Address,
23 pub label: Option<String>,
25 pub contract: Option<String>,
29 pub abi: Option<Cow<'a, JsonAbi>>,
31 pub constructor_args_offset: Option<usize>,
33 pub artifact_id: Option<ArtifactId>,
35}
36
37pub trait TraceIdentifier {
39 fn identify_addresses(&mut self, nodes: &[&CallTraceNode]) -> Vec<IdentifiedAddress<'_>>;
41}
42
43pub struct TraceIdentifiers<'a> {
45 pub local: Option<LocalTraceIdentifier<'a>>,
47 pub external: Option<ExternalIdentifier>,
49}
50
51impl Default for TraceIdentifiers<'_> {
52 fn default() -> Self {
53 Self::new()
54 }
55}
56
57impl TraceIdentifier for TraceIdentifiers<'_> {
58 fn identify_addresses(&mut self, nodes: &[&CallTraceNode]) -> Vec<IdentifiedAddress<'_>> {
59 if nodes.is_empty() {
60 return Vec::new();
61 }
62
63 let mut identities = Vec::with_capacity(nodes.len());
64 if let Some(local) = &mut self.local {
65 identities.extend(local.identify_addresses(nodes));
66 if identities.len() >= nodes.len() {
67 return identities;
68 }
69 }
70 if let Some(external) = &mut self.external {
71 identities.extend(external.identify_addresses(nodes));
72 }
73 identities
74 }
75}
76
77impl<'a> TraceIdentifiers<'a> {
78 pub const fn new() -> Self {
80 Self { local: None, external: None }
81 }
82
83 pub fn with_local(mut self, known_contracts: &'a ContractsByArtifact) -> Self {
85 self.local = Some(LocalTraceIdentifier::new(known_contracts));
86 self
87 }
88
89 pub fn with_local_and_bytecodes(
91 mut self,
92 known_contracts: &'a ContractsByArtifact,
93 contracts_bytecode: &'a AddressHashMap<Bytes>,
94 ) -> Self {
95 self.local =
96 Some(LocalTraceIdentifier::new(known_contracts).with_bytecodes(contracts_bytecode));
97 self
98 }
99
100 pub fn with_external(mut self, config: &Config, chain: Option<Chain>) -> eyre::Result<Self> {
102 self.external = ExternalIdentifier::new(config, chain)?;
103 Ok(self)
104 }
105
106 pub const fn is_empty(&self) -> bool {
108 self.local.is_none() && self.external.is_none()
109 }
110}