@@ -5159,10 +5159,10 @@ mod tests {
51595159 [forks]
51605160
51615161 [forks.mainnet]
5162- rpc_endpoint = "${_MAINNET_RPC }"
5162+ rpc_endpoint = "${MAINNET_RPC }"
51635163
51645164 [forks.mainnet.vars]
5165- weth = "${_WETH_ADDRESS }"
5165+ weth = "${WETH_MAINNET }"
51665166 usdc = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
51675167 pool_name = "USDC-ETH"
51685168 pool_fee = 3000
@@ -5173,7 +5173,7 @@ mod tests {
51735173 int_array = [-100, 200, -300]
51745174 uint_array = [100, 200, 300]
51755175 addr_array = [
5176- "${_ADDR1 }",
5176+ "${ADDR_1 }",
51775177 "0x2222222222222222222222222222222222222222"
51785178 ]
51795179 bytes32_array = [
@@ -5182,24 +5182,33 @@ mod tests {
51825182 ]
51835183 bytes_array = ["0x1234", "0x5678", "0xabcd"]
51845184 string_array = ["hello", "world", "test"]
5185+
5186+ [forks.10]
5187+ rpc_endpoint = "${OPTIMISM_RPC}"
5188+
5189+ [forks.10.vars]
5190+ weth = "${WETH_OPTIMISM}"
51855191 "# ,
51865192 ) ?;
51875193
51885194 // Now set the environment variables
5189- jail. set_env ( "_MAINNET_RPC" , "mainnet-rpc" ) ;
5190- jail. set_env ( "_WETH_ADDRESS" , "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" ) ;
5191- jail. set_env ( "_ADDR1" , "0x1111111111111111111111111111111111111111" ) ;
5195+ jail. set_env ( "MAINNET_RPC" , "mainnet-rpc" ) ;
5196+ jail. set_env ( "OPTIMISM_RPC" , "optimism-rpc" ) ;
5197+ jail. set_env ( "WETH_MAINNET" , "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" ) ;
5198+ jail. set_env ( "WETH_OPTIMISM" , "0x4200000000000000000000000000000000000006" ) ;
5199+ jail. set_env ( "ADDR_1" , "0x1111111111111111111111111111111111111111" ) ;
51925200
51935201 // Reload the config with env vars set
51945202 let config = Config :: load ( ) . unwrap ( ) ;
51955203
5196- let expected: HashMap < String , ForkChainConfig > = vec ! [ (
5197- "mainnet" . to_string( ) ,
5198- ForkChainConfig {
5199- rpc_endpoint: Some ( RpcEndpoint :: new( RpcEndpointUrl :: Url (
5200- "mainnet-rpc" . to_string( ) ,
5201- ) ) ) ,
5202- vars: vec![
5204+ let expected: HashMap < String , ForkChainConfig > = vec ! [
5205+ (
5206+ "mainnet" . to_string( ) ,
5207+ ForkChainConfig {
5208+ rpc_endpoint: Some ( RpcEndpoint :: new( RpcEndpointUrl :: Url (
5209+ "mainnet-rpc" . to_string( ) ,
5210+ ) ) ) ,
5211+ vars: vec![
52035212 ( "weth" . into( ) , "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" . into( ) ) ,
52045213 ( "usdc" . into( ) , "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" . into( ) ) ,
52055214 ( "pool_name" . into( ) , "USDC-ETH" . into( ) ) ,
@@ -5219,10 +5228,25 @@ mod tests {
52195228 ( "bytes_array" . into( ) , vec![ "0x1234" , "0x5678" , "0xabcd" ] . into( ) ) ,
52205229 ( "string_array" . into( ) , vec![ "hello" , "world" , "test" ] . into( ) ) ,
52215230 ]
5222- . into_iter( )
5223- . collect( ) ,
5224- } ,
5225- ) ]
5231+ . into_iter( )
5232+ . collect( ) ,
5233+ } ,
5234+ ) ,
5235+ (
5236+ "optimism" . to_string( ) ,
5237+ ForkChainConfig {
5238+ rpc_endpoint: Some ( RpcEndpoint :: new( RpcEndpointUrl :: Url (
5239+ "optimism-rpc" . to_string( ) ,
5240+ ) ) ) ,
5241+ vars: vec![ (
5242+ "weth" . into( ) ,
5243+ "0x4200000000000000000000000000000000000006" . into( ) ,
5244+ ) ]
5245+ . into_iter( )
5246+ . collect( ) ,
5247+ } ,
5248+ ) ,
5249+ ]
52265250 . into_iter ( )
52275251 . collect ( ) ;
52285252 assert_eq ! (
@@ -5231,18 +5255,29 @@ mod tests {
52315255 ) ;
52325256
52335257 let expected_mainnet = expected. get ( "mainnet" ) . unwrap ( ) ;
5258+ let expected_optimism = expected. get ( "optimism" ) . unwrap ( ) ;
52345259 let mainnet = config. forks . get ( "mainnet" ) . unwrap ( ) ;
5260+ let optimism = config. forks . get ( "optimism" ) . unwrap ( ) ;
52355261
5236- // Verify that rpc_endpoint is now resolved to the actual value
5262+ // Verify that rpc_endpoints are resolved to their actual value
52375263 if let Some ( rpc) = & mainnet. rpc_endpoint {
5238- // The rpc endpoint should be resolved after env var is set
52395264 let resolved_url = rpc. to_owned ( ) . resolve ( ) . url ( ) . unwrap ( ) ;
52405265 assert_eq ! ( resolved_url, "mainnet-rpc" ) ;
52415266 }
5267+ if let Some ( rpc) = & optimism. rpc_endpoint {
5268+ let resolved_url = rpc. to_owned ( ) . resolve ( ) . url ( ) . unwrap ( ) ;
5269+ assert_eq ! ( resolved_url, "optimism-rpc" ) ;
5270+ }
52425271
5243- // Verify that weth is now resolved to the actual address
5244- let weth_after = mainnet. vars . get ( "weth" ) . unwrap ( ) ;
5245- assert_eq ! ( weth_after. as_str( ) . unwrap( ) , "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" ) ;
5272+ // Verify that weth placeholders are resolved to their actual addresses
5273+ assert_eq ! (
5274+ mainnet. vars. get( "weth" ) . unwrap( ) . as_str( ) . unwrap( ) ,
5275+ expected_mainnet. vars. get( "weth" ) . unwrap( ) . as_str( ) . unwrap( ) ,
5276+ ) ;
5277+ assert_eq ! (
5278+ optimism. vars. get( "weth" ) . unwrap( ) . as_str( ) . unwrap( ) ,
5279+ expected_optimism. vars. get( "weth" ) . unwrap( ) . as_str( ) . unwrap( ) ,
5280+ ) ;
52465281
52475282 // Check all other vars match expected values
52485283 for ( k, v) in & expected_mainnet. vars {
@@ -5292,6 +5327,89 @@ mod tests {
52925327 } ) ;
52935328 }
52945329
5330+ #[ test]
5331+ fn test_fork_config_invalid_chain_fails ( ) {
5332+ figment:: Jail :: expect_with ( |jail| {
5333+ jail. create_file (
5334+ "foundry.toml" ,
5335+ r#"
5336+ [forks]
5337+
5338+ [forks.randomchain]
5339+ rpc_endpoint = "random-chain-rpc"
5340+ [forks.randomchain.vars]
5341+ some_value = "some_value"
5342+ "# ,
5343+ ) ?;
5344+ let result = Config :: load ( ) ;
5345+ assert ! ( result. is_err( ) ) ;
5346+ let err_str = result. unwrap_err ( ) . to_string ( ) ;
5347+
5348+ // Check the error message
5349+ assert ! ( err_str. contains(
5350+ "foundry config error: chain name 'randomchain' is not supported by 'alloy_chains'"
5351+ ) ) ;
5352+
5353+ Ok ( ( ) )
5354+ } ) ;
5355+
5356+ figment:: Jail :: expect_with ( |jail| {
5357+ jail. create_file (
5358+ "foundry.toml" ,
5359+ r#"
5360+ [forks]
5361+
5362+ [forks.0]
5363+ rpc_endpoint = "random-chain-rpc"
5364+ [forks.0.vars]
5365+ some_value = "some_value"
5366+ "# ,
5367+ ) ?;
5368+ let result = Config :: load ( ) ;
5369+ assert ! ( result. is_err( ) ) ;
5370+ let err_str = result. unwrap_err ( ) . to_string ( ) ;
5371+
5372+ // Check the error message
5373+ assert ! (
5374+ err_str. contains(
5375+ "foundry config error: chain id '0' is not supported by 'alloy_chains'"
5376+ )
5377+ ) ;
5378+
5379+ Ok ( ( ) )
5380+ } ) ;
5381+ }
5382+
5383+ #[ test]
5384+ fn test_fork_config_duplicate_key_fails ( ) {
5385+ figment:: Jail :: expect_with ( |jail| {
5386+ jail. create_file (
5387+ "foundry.toml" ,
5388+ r#"
5389+ [forks]
5390+
5391+ [forks.mainnet]
5392+ rpc_endpoint = "mainnet-rpc"
5393+ [forks.mainnet.vars]
5394+ some_value = "some_value"
5395+
5396+ [forks.1]
5397+ rpc_endpoint = "mainnet-rpc"
5398+ [forks.1.vars]
5399+ some_value = "some_value"
5400+ "# ,
5401+ ) ?;
5402+ let result = Config :: load ( ) ;
5403+ assert ! ( result. is_err( ) ) ;
5404+ let err_str = result. unwrap_err ( ) . to_string ( ) ;
5405+
5406+ // Check the error message
5407+ assert ! ( err_str. contains( "duplicate fork configuration." ) ) ;
5408+
5409+ Ok ( ( ) )
5410+ } ) ;
5411+ }
5412+
52955413 #[ test]
52965414 fn test_fork_config_missing_env_var_fails ( ) {
52975415 figment:: Jail :: expect_with ( |jail| {
0 commit comments