@@ -28,7 +28,7 @@ use alloy_signer_local::{
2828} ;
2929use alloy_transport:: { Transport , TransportError } ;
3030use anvil_server:: ServerConfig ;
31- use eyre:: Result ;
31+ use eyre:: { Context , Result } ;
3232use foundry_common:: {
3333 provider:: { ProviderBuilder , RetryProvider } ,
3434 ALCHEMY_FREE_TIER_CUPS , NON_ARCHIVE_NODE_WARNING , REQUEST_TIMEOUT ,
@@ -44,15 +44,17 @@ use itertools::Itertools;
4444use parking_lot:: RwLock ;
4545use rand:: thread_rng;
4646use revm:: primitives:: BlobExcessGasAndPrice ;
47- use serde_json:: { json, to_writer , Value } ;
47+ use serde_json:: { json, Value } ;
4848use std:: {
4949 fmt:: Write as FmtWrite ,
5050 fs:: File ,
51+ io,
5152 net:: { IpAddr , Ipv4Addr } ,
5253 path:: { Path , PathBuf } ,
5354 sync:: Arc ,
5455 time:: Duration ,
5556} ;
57+ use tokio:: sync:: RwLock as TokioRwLock ;
5658use yansi:: Paint ;
5759
5860/// Default port the rpc will open
@@ -144,7 +146,7 @@ pub struct NodeConfig {
144146 /// How transactions are sorted in the mempool
145147 pub transaction_order : TransactionOrder ,
146148 /// Filename to write anvil output as json
147- pub config_out : Option < String > ,
149+ pub config_out : Option < PathBuf > ,
148150 /// The genesis to use to initialize the node
149151 pub genesis : Option < Genesis > ,
150152 /// Timeout in for requests sent to remote JSON-RPC server in forking mode
@@ -195,13 +197,13 @@ pub struct NodeConfig {
195197
196198impl NodeConfig {
197199 fn as_string ( & self , fork : Option < & ClientFork > ) -> String {
198- let mut config_string : String = String :: new ( ) ;
199- let _ = write ! ( config_string , "\n {}" , BANNER . green( ) ) ;
200- let _ = write ! ( config_string , "\n {VERSION_MESSAGE}" ) ;
201- let _ = write ! ( config_string , "\n {}" , "https://github.com/foundry-rs/foundry" . green( ) ) ;
200+ let mut s : String = String :: new ( ) ;
201+ let _ = write ! ( s , "\n {}" , BANNER . green( ) ) ;
202+ let _ = write ! ( s , "\n {VERSION_MESSAGE}" ) ;
203+ let _ = write ! ( s , "\n {}" , "https://github.com/foundry-rs/foundry" . green( ) ) ;
202204
203205 let _ = write ! (
204- config_string ,
206+ s ,
205207 r#"
206208
207209Available Accounts
@@ -210,11 +212,11 @@ Available Accounts
210212 ) ;
211213 let balance = alloy_primitives:: utils:: format_ether ( self . genesis_balance ) ;
212214 for ( idx, wallet) in self . genesis_accounts . iter ( ) . enumerate ( ) {
213- write ! ( config_string , "\n ({idx}) {} ({balance} ETH)" , wallet. address( ) ) . unwrap ( ) ;
215+ write ! ( s , "\n ({idx}) {} ({balance} ETH)" , wallet. address( ) ) . unwrap ( ) ;
214216 }
215217
216218 let _ = write ! (
217- config_string ,
219+ s ,
218220 r#"
219221
220222Private Keys
@@ -224,12 +226,12 @@ Private Keys
224226
225227 for ( idx, wallet) in self . genesis_accounts . iter ( ) . enumerate ( ) {
226228 let hex = hex:: encode ( wallet. credential ( ) . to_bytes ( ) ) ;
227- let _ = write ! ( config_string , "\n ({idx}) 0x{hex}" ) ;
229+ let _ = write ! ( s , "\n ({idx}) 0x{hex}" ) ;
228230 }
229231
230232 if let Some ( ref gen) = self . account_generator {
231233 let _ = write ! (
232- config_string ,
234+ s ,
233235 r#"
234236
235237Wallet
@@ -244,7 +246,7 @@ Derivation path: {}
244246
245247 if let Some ( fork) = fork {
246248 let _ = write ! (
247- config_string ,
249+ s ,
248250 r#"
249251
250252Fork
@@ -261,11 +263,11 @@ Chain ID: {}
261263 ) ;
262264
263265 if let Some ( tx_hash) = fork. transaction_hash ( ) {
264- let _ = writeln ! ( config_string , "Transaction hash: {tx_hash}" ) ;
266+ let _ = writeln ! ( s , "Transaction hash: {tx_hash}" ) ;
265267 }
266268 } else {
267269 let _ = write ! (
268- config_string ,
270+ s ,
269271 r#"
270272
271273Chain ID
@@ -279,7 +281,7 @@ Chain ID
279281
280282 if ( SpecId :: from ( self . get_hardfork ( ) ) as u8 ) < ( SpecId :: LONDON as u8 ) {
281283 let _ = write ! (
282- config_string ,
284+ s ,
283285 r#"
284286Gas Price
285287==================
@@ -290,7 +292,7 @@ Gas Price
290292 ) ;
291293 } else {
292294 let _ = write ! (
293- config_string ,
295+ s ,
294296 r#"
295297Base Fee
296298==================
@@ -302,7 +304,7 @@ Base Fee
302304 }
303305
304306 let _ = write ! (
305- config_string ,
307+ s ,
306308 r#"
307309Gas Limit
308310==================
@@ -326,7 +328,7 @@ Gas Limit
326328 ) ;
327329
328330 let _ = write ! (
329- config_string ,
331+ s ,
330332 r#"
331333Genesis Timestamp
332334==================
@@ -336,7 +338,7 @@ Genesis Timestamp
336338 self . get_genesis_timestamp( ) . green( )
337339 ) ;
338340
339- config_string
341+ s
340342 }
341343
342344 fn as_json ( & self , fork : Option < & ClientFork > ) -> Value {
@@ -749,7 +751,7 @@ impl NodeConfig {
749751
750752 /// Sets the file path to write the Anvil node's config info to.
751753 #[ must_use]
752- pub fn set_config_out ( mut self , config_out : Option < String > ) -> Self {
754+ pub fn set_config_out ( mut self , config_out : Option < PathBuf > ) -> Self {
753755 self . config_out = config_out;
754756 self
755757 }
@@ -903,21 +905,18 @@ impl NodeConfig {
903905 }
904906
905907 /// Prints the config info
906- pub fn print ( & self , fork : Option < & ClientFork > ) {
907- if self . config_out . is_some ( ) {
908- let config_out = self . config_out . as_deref ( ) . unwrap ( ) ;
909- to_writer (
910- & File :: create ( config_out) . expect ( "Unable to create anvil config description file" ) ,
911- & self . as_json ( fork) ,
912- )
913- . expect ( "Failed writing json" ) ;
908+ pub fn print ( & self , fork : Option < & ClientFork > ) -> Result < ( ) > {
909+ if let Some ( path) = & self . config_out {
910+ let file = io:: BufWriter :: new (
911+ File :: create ( path) . wrap_err ( "unable to create anvil config description file" ) ?,
912+ ) ;
913+ let value = self . as_json ( fork) ;
914+ serde_json:: to_writer ( file, & value) . wrap_err ( "failed writing JSON" ) ?;
914915 }
915-
916- if self . silent {
917- return ;
916+ if !self . silent {
917+ sh_println ! ( "{}" , self . as_string( fork) ) ?;
918918 }
919-
920- let _ = sh_println ! ( "{}" , self . as_string( fork) ) ;
919+ Ok ( ( ) )
921920 }
922921
923922 /// Returns the path where the cache file should be stored
@@ -983,7 +982,7 @@ impl NodeConfig {
983982 /// [Backend](mem::Backend)
984983 ///
985984 /// *Note*: only memory based backend for now
986- pub ( crate ) async fn setup ( & mut self ) -> mem:: Backend {
985+ pub ( crate ) async fn setup ( & mut self ) -> Result < mem:: Backend > {
987986 // configure the revm environment
988987
989988 let mut cfg =
@@ -1020,11 +1019,11 @@ impl NodeConfig {
10201019 self . get_blob_excess_gas_and_price ( ) ,
10211020 ) ;
10221021
1023- let ( db, fork) : ( Arc < tokio :: sync :: RwLock < Box < dyn Db > > > , Option < ClientFork > ) =
1022+ let ( db, fork) : ( Arc < TokioRwLock < Box < dyn Db > > > , Option < ClientFork > ) =
10241023 if let Some ( eth_rpc_url) = self . eth_rpc_url . clone ( ) {
1025- self . setup_fork_db ( eth_rpc_url, & mut env, & fees) . await
1024+ self . setup_fork_db ( eth_rpc_url, & mut env, & fees) . await ?
10261025 } else {
1027- ( Arc :: new ( tokio :: sync :: RwLock :: new ( Box :: < MemDb > :: default ( ) ) ) , None )
1026+ ( Arc :: new ( TokioRwLock :: new ( Box :: < MemDb > :: default ( ) ) ) , None )
10281027 } ;
10291028
10301029 // if provided use all settings of `genesis.json`
@@ -1062,29 +1061,29 @@ impl NodeConfig {
10621061 self . transaction_block_keeper ,
10631062 self . block_time ,
10641063 self . cache_path . clone ( ) ,
1065- Arc :: new ( tokio :: sync :: RwLock :: new ( self . clone ( ) ) ) ,
1064+ Arc :: new ( TokioRwLock :: new ( self . clone ( ) ) ) ,
10661065 )
1067- . await ;
1066+ . await ? ;
10681067
10691068 // Writes the default create2 deployer to the backend,
10701069 // if the option is not disabled and we are not forking.
10711070 if !self . disable_default_create2_deployer && self . eth_rpc_url . is_none ( ) {
10721071 backend
10731072 . set_create2_deployer ( DEFAULT_CREATE2_DEPLOYER )
10741073 . await
1075- . expect ( "Failed to create default create2 deployer") ;
1074+ . wrap_err ( "failed to create default create2 deployer") ? ;
10761075 }
10771076
10781077 if let Some ( state) = self . init_state . clone ( ) {
1079- backend. load_state ( state) . await . expect ( "Failed to load init state") ;
1078+ backend. load_state ( state) . await . wrap_err ( "failed to load init state") ? ;
10801079 }
10811080
1082- backend
1081+ Ok ( backend)
10831082 }
10841083
10851084 /// Configures everything related to forking based on the passed `eth_rpc_url`:
1086- /// - returning a tuple of a [ForkedDatabase] wrapped in an [Arc] [RwLock](tokio::sync::RwLock)
1087- /// and [ClientFork] wrapped in an [Option] which can be used in a [Backend](mem::Backend) to
1085+ /// - returning a tuple of a [ForkedDatabase] wrapped in an [Arc] [RwLock](TokioRwLock) and
1086+ /// [ClientFork] wrapped in an [Option] which can be used in a [Backend](mem::Backend) to
10881087 /// fork from.
10891088 /// - modifying some parameters of the passed `env`
10901089 /// - mutating some members of `self`
@@ -1093,15 +1092,11 @@ impl NodeConfig {
10931092 eth_rpc_url : String ,
10941093 env : & mut EnvWithHandlerCfg ,
10951094 fees : & FeeManager ,
1096- ) -> ( Arc < tokio:: sync:: RwLock < Box < dyn Db > > > , Option < ClientFork > ) {
1097- let ( db, config) = self . setup_fork_db_config ( eth_rpc_url, env, fees) . await ;
1098-
1099- let db: Arc < tokio:: sync:: RwLock < Box < dyn Db > > > =
1100- Arc :: new ( tokio:: sync:: RwLock :: new ( Box :: new ( db) ) ) ;
1101-
1095+ ) -> Result < ( Arc < TokioRwLock < Box < dyn Db > > > , Option < ClientFork > ) > {
1096+ let ( db, config) = self . setup_fork_db_config ( eth_rpc_url, env, fees) . await ?;
1097+ let db: Arc < TokioRwLock < Box < dyn Db > > > = Arc :: new ( TokioRwLock :: new ( Box :: new ( db) ) ) ;
11021098 let fork = ClientFork :: new ( config, Arc :: clone ( & db) ) ;
1103-
1104- ( db, Some ( fork) )
1099+ Ok ( ( db, Some ( fork) ) )
11051100 }
11061101
11071102 /// Configures everything related to forking based on the passed `eth_rpc_url`:
@@ -1114,7 +1109,7 @@ impl NodeConfig {
11141109 eth_rpc_url : String ,
11151110 env : & mut EnvWithHandlerCfg ,
11161111 fees : & FeeManager ,
1117- ) -> ( ForkedDatabase , ClientForkConfig ) {
1112+ ) -> Result < ( ForkedDatabase , ClientForkConfig ) > {
11181113 // TODO make provider agnostic
11191114 let provider = Arc :: new (
11201115 ProviderBuilder :: new ( & eth_rpc_url)
@@ -1125,23 +1120,22 @@ impl NodeConfig {
11251120 . initial_backoff ( 1000 )
11261121 . headers ( self . fork_headers . clone ( ) )
11271122 . build ( )
1128- . expect ( "Failed to establish provider to fork url") ,
1123+ . wrap_err ( "failed to establish provider to fork url") ? ,
11291124 ) ;
11301125
11311126 let ( fork_block_number, fork_chain_id, force_transactions) = if let Some ( fork_choice) =
11321127 & self . fork_choice
11331128 {
11341129 let ( fork_block_number, force_transactions) =
1135- derive_block_and_transactions ( fork_choice, & provider) . await . expect (
1136- "Failed to derive fork block number and force transactions from fork choice" ,
1137- ) ;
1130+ derive_block_and_transactions ( fork_choice, & provider) . await . wrap_err (
1131+ "failed to derive fork block number and force transactions from fork choice" ,
1132+ ) ? ;
11381133 let chain_id = if let Some ( chain_id) = self . fork_chain_id {
11391134 Some ( chain_id)
11401135 } else if self . hardfork . is_none ( ) {
1141- // auto adjust hardfork if not specified
1142- // but only if we're forking mainnet
1136+ // Auto-adjust hardfork if not specified, but only if we're forking mainnet.
11431137 let chain_id =
1144- provider. get_chain_id ( ) . await . expect ( "Failed to fetch network chain ID") ;
1138+ provider. get_chain_id ( ) . await . wrap_err ( "failed to fetch network chain ID") ? ;
11451139 if alloy_chains:: NamedChain :: Mainnet == chain_id {
11461140 let hardfork: EthereumHardfork = fork_block_number. into ( ) ;
11471141 env. handler_cfg . spec_id = hardfork. into ( ) ;
@@ -1155,15 +1149,16 @@ impl NodeConfig {
11551149 ( fork_block_number, chain_id, force_transactions)
11561150 } else {
11571151 // pick the last block number but also ensure it's not pending anymore
1158- let bn =
1159- find_latest_fork_block ( & provider) . await . expect ( "Failed to get fork block number" ) ;
1152+ let bn = find_latest_fork_block ( & provider)
1153+ . await
1154+ . wrap_err ( "failed to get fork block number" ) ?;
11601155 ( bn, None , None )
11611156 } ;
11621157
11631158 let block = provider
11641159 . get_block ( BlockNumberOrTag :: Number ( fork_block_number) . into ( ) , false . into ( ) )
11651160 . await
1166- . expect ( "Failed to get fork block") ;
1161+ . wrap_err ( "failed to get fork block") ? ;
11671162
11681163 let block = if let Some ( block) = block {
11691164 block
@@ -1179,9 +1174,9 @@ latest block number: {latest_block}"
11791174 if fork_block_number <= latest_block {
11801175 message. push_str ( & format ! ( "\n {NON_ARCHIVE_NODE_WARNING}" ) ) ;
11811176 }
1182- panic ! ( "{}" , message ) ;
1177+ eyre :: bail !( "{message}" ) ;
11831178 }
1184- panic ! ( "Failed to get block for block number: {fork_block_number}" )
1179+ eyre :: bail !( "failed to get block for block number: {fork_block_number}" )
11851180 } ;
11861181
11871182 let gas_limit = self . fork_gas_limit ( & block) ;
@@ -1243,7 +1238,7 @@ latest block number: {latest_block}"
12431238 let chain_id = if let Some ( fork_chain_id) = fork_chain_id {
12441239 fork_chain_id. to ( )
12451240 } else {
1246- provider. get_chain_id ( ) . await . unwrap ( )
1241+ provider. get_chain_id ( ) . await . wrap_err ( "failed to fetch network chain ID" ) ?
12471242 } ;
12481243
12491244 // need to update the dev signers and env with the chain id
@@ -1296,7 +1291,7 @@ latest block number: {latest_block}"
12961291 // need to insert the forked block's hash
12971292 db. insert_block_hash ( U256 :: from ( config. block_number ) , config. block_hash ) ;
12981293
1299- ( db, config)
1294+ Ok ( ( db, config) )
13001295 }
13011296
13021297 /// we only use the gas limit value of the block if it is non-zero and the block gas
@@ -1344,7 +1339,7 @@ async fn derive_block_and_transactions(
13441339 let transaction = provider
13451340 . get_transaction_by_hash ( transaction_hash. 0 . into ( ) )
13461341 . await ?
1347- . ok_or ( eyre:: eyre!( "Failed to get fork transaction by hash" ) ) ?;
1342+ . ok_or_else ( || eyre:: eyre!( "failed to get fork transaction by hash" ) ) ?;
13481343 let transaction_block_number = transaction. block_number . unwrap ( ) ;
13491344
13501345 // Get the block pertaining to the fork transaction
@@ -1354,13 +1349,13 @@ async fn derive_block_and_transactions(
13541349 alloy_rpc_types:: BlockTransactionsKind :: Full ,
13551350 )
13561351 . await ?
1357- . ok_or ( eyre:: eyre!( "Failed to get fork block by number" ) ) ?;
1352+ . ok_or_else ( || eyre:: eyre!( "failed to get fork block by number" ) ) ?;
13581353
13591354 // Filter out transactions that are after the fork transaction
13601355 let filtered_transactions = transaction_block
13611356 . transactions
13621357 . as_transactions ( )
1363- . ok_or ( eyre:: eyre!( "Failed to get transactions from full fork block" ) ) ?
1358+ . ok_or_else ( || eyre:: eyre!( "failed to get transactions from full fork block" ) ) ?
13641359 . iter ( )
13651360 . take_while_inclusive ( |& transaction| transaction. tx_hash ( ) != transaction_hash. 0 )
13661361 . collect :: < Vec < _ > > ( ) ;
0 commit comments