@@ -4,6 +4,7 @@ use alloy_primitives::{
44 Address ,
55 map:: { Entry , HashMap } ,
66} ;
7+ use eyre:: WrapErr ;
78use foundry_block_explorers:: { contract:: Metadata , errors:: EtherscanError } ;
89use foundry_common:: compile:: etherscan_project;
910use foundry_config:: { Chain , Config } ;
@@ -73,26 +74,39 @@ impl ExternalIdentifier {
7374 /// Goes over the list of contracts we have pulled from the traces, clones their source from
7475 /// Etherscan and compiles them locally, for usage in the debugger.
7576 pub async fn get_compiled_contracts ( & self ) -> eyre:: Result < ContractSources > {
77+ // Collect contract info upfront so we can reference it in error messages
78+ let contracts_info: Vec < _ > = self
79+ . contracts
80+ . iter ( )
81+ . filter ( |( _, ( _, metadata) ) | {
82+ metadata. as_ref ( ) . is_some_and ( |metadata| !metadata. is_vyper ( ) )
83+ } )
84+ . map ( |( addr, ( _, metadata) ) | ( * addr, metadata. as_ref ( ) . unwrap ( ) . contract_name . clone ( ) ) )
85+ . collect ( ) ;
86+
7687 let outputs_fut = self
7788 . contracts
7889 . iter ( )
7990 // filter out vyper files
8091 . filter ( |( _, ( _, metadata) ) | {
8192 metadata. as_ref ( ) . is_some_and ( |metadata| !metadata. is_vyper ( ) )
8293 } )
83- . map ( |( address, ( _, metadata) ) | async move {
84- let metadata = metadata. as_ref ( ) . unwrap ( ) ;
85- sh_println ! ( "Compiling: {} {address}" , metadata. contract_name) ?;
86- let root = tempfile:: tempdir ( ) ?;
87- let root_path = root. path ( ) ;
88- let project = etherscan_project ( metadata, root_path) ?;
89- let output = project. compile ( ) ?;
90-
91- if output. has_compiler_errors ( ) {
92- eyre:: bail!( "{output}" )
93- }
94+ . map ( |( address, ( _, metadata) ) | {
95+ let addr = * address;
96+ let metadata = metadata. as_ref ( ) . unwrap ( ) . clone ( ) ;
97+ async move {
98+ sh_println ! ( "Compiling: {} {addr}" , metadata. contract_name) ?;
99+ let root = tempfile:: tempdir ( ) ?;
100+ let root_path = root. path ( ) ;
101+ let project = etherscan_project ( & metadata, root_path) ?;
102+ let output = project. compile ( ) ?;
103+
104+ if output. has_compiler_errors ( ) {
105+ eyre:: bail!( "{output}" )
106+ }
94107
95- Ok ( ( project, output, root) )
108+ Ok ( ( project, output, root) )
109+ }
96110 } )
97111 . collect :: < Vec < _ > > ( ) ;
98112
@@ -102,9 +116,13 @@ impl ExternalIdentifier {
102116 let mut sources: ContractSources = Default :: default ( ) ;
103117
104118 // construct the map
105- for res in outputs {
106- let ( project, output, _root) = res?;
107- sources. insert ( & output, project. root ( ) , None ) ?;
119+ for ( idx, res) in outputs. into_iter ( ) . enumerate ( ) {
120+ let ( addr, name) = & contracts_info[ idx] ;
121+ let ( project, output, _root) =
122+ res. wrap_err_with ( || format ! ( "Failed to compile contract {name} at {addr}" ) ) ?;
123+ sources
124+ . insert ( & output, project. root ( ) , None )
125+ . wrap_err_with ( || format ! ( "Failed to insert contract {name} at {addr}" ) ) ?;
108126 }
109127
110128 Ok ( sources)
0 commit comments