diff --git a/crates/anvil/tests/it/fork.rs b/crates/anvil/tests/it/fork.rs index c9d9b2c80b8fc..526f3263b67f8 100644 --- a/crates/anvil/tests/it/fork.rs +++ b/crates/anvil/tests/it/fork.rs @@ -837,7 +837,7 @@ async fn test_reset_fork_on_new_blocks() { let anvil_provider = handle.http_provider(); let endpoint = next_http_rpc_endpoint(); - let provider = Arc::new(get_http_provider(&endpoint)); + let provider = Arc::new(get_http_provider(&endpoint, false)); let current_block = anvil_provider.get_block_number().await.unwrap(); diff --git a/crates/anvil/tests/it/utils.rs b/crates/anvil/tests/it/utils.rs index 4a82c27745edd..9b79916427d80 100644 --- a/crates/anvil/tests/it/utils.rs +++ b/crates/anvil/tests/it/utils.rs @@ -8,7 +8,7 @@ use foundry_common::provider::{ }; pub fn http_provider(http_endpoint: &str) -> RetryProvider { - get_http_provider(http_endpoint) + get_http_provider(http_endpoint, false) } pub fn http_provider_with_signer( diff --git a/crates/cli/src/opts/evm.rs b/crates/cli/src/opts/evm.rs index e2e22f7d343ff..0193af2c05786 100644 --- a/crates/cli/src/opts/evm.rs +++ b/crates/cli/src/opts/evm.rs @@ -40,6 +40,14 @@ use foundry_common::shell; #[derive(Clone, Debug, Default, Serialize, Parser)] #[command(next_help_heading = "EVM options", about = None, long_about = None)] // override doc pub struct EvmArgs { + /// Allow insecure RPC connections (accept invalid HTTPS certificates). + /// + /// When the provider's inner runtime transport variant is HTTP, this configures the reqwest + /// client to accept invalid certificates. + #[arg(short = 'k', long = "insecure", default_value = "false")] + #[serde(rename = "eth_rpc_accept_invalid_certs")] + pub accept_invalid_certs: bool, + /// Fetch state over a remote endpoint instead of starting from an empty state. /// /// If you want to fetch state from a specific block number, see --fork-block-number. @@ -190,6 +198,10 @@ impl Provider for EvmArgs { dict.insert("eth_rpc_url".to_string(), fork_url.clone().into()); } + if self.accept_invalid_certs { + dict.insert("eth_rpc_accept_invalid_certs".to_string(), self.accept_invalid_certs.into()); + } + Ok(Map::from([(Config::selected_profile(), dict)])) } } diff --git a/crates/common/src/provider/mod.rs b/crates/common/src/provider/mod.rs index 870c2c24f895f..7caa65198e90b 100644 --- a/crates/common/src/provider/mod.rs +++ b/crates/common/src/provider/mod.rs @@ -70,15 +70,15 @@ pub type RetryProviderWithSigner = FillProvider< /// ``` #[inline] #[track_caller] -pub fn get_http_provider(builder: impl AsRef) -> RetryProvider { - try_get_http_provider(builder).unwrap() +pub fn get_http_provider(builder: impl AsRef, accept_invalid_certs: bool) -> RetryProvider { + try_get_http_provider(builder, accept_invalid_certs).unwrap() } /// Constructs a provider with a 100 millisecond interval poll if it's a localhost URL (most likely /// an anvil or other dev node) and with the default, or 7 second otherwise. #[inline] -pub fn try_get_http_provider(builder: impl AsRef) -> Result { - ProviderBuilder::new(builder.as_ref()).build() +pub fn try_get_http_provider(builder: impl AsRef, accept_invalid_certs: bool) -> Result { + ProviderBuilder::new(builder.as_ref()).accept_invalid_certs(accept_invalid_certs).build() } /// Helper type to construct a `RetryProvider` diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 3da6cb45fe657..208dcdee5e955 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -2044,7 +2044,7 @@ mod tests { async fn can_read_write_cache() { let Some(endpoint) = ENDPOINT else { return }; - let provider = get_http_provider(endpoint); + let provider = get_http_provider(endpoint, false); let block_num = provider.get_block_number().await.unwrap(); diff --git a/crates/evm/core/src/fork/database.rs b/crates/evm/core/src/fork/database.rs index 6a53a19843b1b..a7b0bfb32bdd8 100644 --- a/crates/evm/core/src/fork/database.rs +++ b/crates/evm/core/src/fork/database.rs @@ -278,7 +278,7 @@ mod tests { #[tokio::test(flavor = "multi_thread")] async fn fork_db_insert_basic_default() { let rpc = foundry_test_utils::rpc::next_http_rpc_endpoint(); - let provider = get_http_provider(rpc.clone()); + let provider = get_http_provider(rpc.clone(), false); let meta = BlockchainDbMeta::new(Default::default(), rpc); let db = BlockchainDb::new(meta, None); diff --git a/crates/evm/core/src/fork/multi.rs b/crates/evm/core/src/fork/multi.rs index d33fcf837105c..871f70de49447 100644 --- a/crates/evm/core/src/fork/multi.rs +++ b/crates/evm/core/src/fork/multi.rs @@ -544,6 +544,7 @@ async fn create_fork(mut fork: CreateFork) -> eyre::Result<(ForkId, CreatedFork, .maybe_initial_backoff(fork.evm_opts.fork_retry_backoff) .maybe_headers(fork.evm_opts.fork_headers.clone()) .compute_units_per_second(fork.evm_opts.get_compute_units_per_second()) + .accept_invalid_certs(fork.evm_opts.eth_rpc_accept_invalid_certs) .build()?, ); diff --git a/crates/evm/core/src/opts.rs b/crates/evm/core/src/opts.rs index 0a517d0c77f92..747b241214b21 100644 --- a/crates/evm/core/src/opts.rs +++ b/crates/evm/core/src/opts.rs @@ -82,6 +82,9 @@ pub struct EvmOpts { /// The CREATE2 deployer's address. pub create2_deployer: Address, + + /// Whether to accept invalid certificates for the rpc server. + pub eth_rpc_accept_invalid_certs: bool, } impl Default for EvmOpts { @@ -107,6 +110,7 @@ impl Default for EvmOpts { enable_tx_gas_limit: false, networks: NetworkConfigs::default(), create2_deployer: DEFAULT_CREATE2_DEPLOYER, + eth_rpc_accept_invalid_certs: false, } } } @@ -129,6 +133,7 @@ impl EvmOpts { pub async fn fork_evm_env(&self, fork_url: &str) -> eyre::Result<(crate::Env, AnyRpcBlock)> { let provider = ProviderBuilder::new(fork_url) .compute_units_per_second(self.get_compute_units_per_second()) + .accept_invalid_certs(self.eth_rpc_accept_invalid_certs) .build()?; environment( &provider, diff --git a/crates/script/src/broadcast.rs b/crates/script/src/broadcast.rs index f62387e532d52..f0baa61cc449f 100644 --- a/crates/script/src/broadcast.rs +++ b/crates/script/src/broadcast.rs @@ -49,8 +49,9 @@ pub async fn next_nonce( caller: Address, provider_url: &str, block_number: Option, + accept_invalid_certs: bool, ) -> eyre::Result { - let provider = try_get_http_provider(provider_url) + let provider = try_get_http_provider(provider_url, accept_invalid_certs) .wrap_err_with(|| format!("bad fork_url provider: {provider_url}"))?; let block_id = block_number.map_or(BlockId::latest(), BlockId::number); @@ -192,7 +193,7 @@ impl BundledState { .enumerate() .map(|(sequence_idx, sequence)| async move { let rpc_url = sequence.rpc_url(); - let provider = Arc::new(get_http_provider(rpc_url)); + let provider = Arc::new(get_http_provider(rpc_url, self.args.evm.accept_invalid_certs)); progress_ref .wait_for_pending( sequence_idx, @@ -268,7 +269,7 @@ impl BundledState { for i in 0..self.sequence.sequences().len() { let mut sequence = self.sequence.sequences_mut().get_mut(i).unwrap(); - let provider = Arc::new(try_get_http_provider(sequence.rpc_url())?); + let provider = Arc::new(try_get_http_provider(sequence.rpc_url(),self.args.evm.accept_invalid_certs)?); let already_broadcasted = sequence.receipts.len(); let seq_progress = progress.get_sequence_progress(i, sequence); diff --git a/crates/script/src/build.rs b/crates/script/src/build.rs index 9ee4403923e06..79603ca7d67d4 100644 --- a/crates/script/src/build.rs +++ b/crates/script/src/build.rs @@ -42,7 +42,7 @@ impl BuildData { pub async fn link(self, script_config: &ScriptConfig) -> Result { let create2_deployer = script_config.evm_opts.create2_deployer; let can_use_create2 = if let Some(fork_url) = &script_config.evm_opts.fork_url { - let provider = try_get_http_provider(fork_url)?; + let provider = try_get_http_provider(fork_url, script_config.config.eth_rpc_accept_invalid_certs)?; let deployer_code = provider.get_code_at(create2_deployer).await?; !deployer_code.is_empty() @@ -260,7 +260,7 @@ impl CompiledState { None } else { let fork_url = self.script_config.evm_opts.fork_url.clone().ok_or_eyre("Missing --fork-url field, if you were trying to broadcast a multi-chain sequence, please use --multi flag")?; - let provider = Arc::new(try_get_http_provider(fork_url)?); + let provider = Arc::new(try_get_http_provider(fork_url, self.args.evm.accept_invalid_certs)?); Some(provider.get_chain_id().await?) }; diff --git a/crates/script/src/execute.rs b/crates/script/src/execute.rs index 06a665b86823a..77a8686629a2a 100644 --- a/crates/script/src/execute.rs +++ b/crates/script/src/execute.rs @@ -234,9 +234,9 @@ impl RpcData { } /// Checks if all RPCs support EIP-3855. Prints a warning if not. - async fn check_shanghai_support(&self) -> Result<()> { + async fn check_shanghai_support(&self, accept_invalid_certs: bool) -> Result<()> { let chain_ids = self.total_rpcs.iter().map(|rpc| async move { - let provider = get_http_provider(rpc); + let provider = get_http_provider(rpc, accept_invalid_certs); let id = provider.get_chain_id().await.ok()?; NamedChain::try_from(id).ok() }); @@ -307,7 +307,7 @@ impl ExecutedState { ) } } - rpc_data.check_shanghai_support().await?; + rpc_data.check_shanghai_support(self.args.evm.accept_invalid_certs).await?; Ok(PreSimulationState { args: self.args, diff --git a/crates/script/src/lib.rs b/crates/script/src/lib.rs index 6a90aef307c19..69ab9d4cf1d53 100644 --- a/crates/script/src/lib.rs +++ b/crates/script/src/lib.rs @@ -234,6 +234,7 @@ impl ScriptArgs { if let Some(sender) = self.maybe_load_private_key()? { evm_opts.sender = sender; } + evm_opts.eth_rpc_accept_invalid_certs = config.eth_rpc_accept_invalid_certs; let script_config = ScriptConfig::new(config, evm_opts).await?; @@ -243,7 +244,6 @@ impl ScriptArgs { /// Executes the script pub async fn run_script(self) -> Result<()> { trace!(target: "script", "executing script command"); - let state = self.preprocess().await?; let create2_deployer = state.script_config.evm_opts.create2_deployer; let compiled = state.compile()?; @@ -584,7 +584,7 @@ pub struct ScriptConfig { impl ScriptConfig { pub async fn new(config: Config, evm_opts: EvmOpts) -> Result { let sender_nonce = if let Some(fork_url) = evm_opts.fork_url.as_ref() { - next_nonce(evm_opts.sender, fork_url, evm_opts.fork_block_number).await? + next_nonce(evm_opts.sender, fork_url, evm_opts.fork_block_number, config.eth_rpc_accept_invalid_certs).await? } else { // dapptools compatibility 1 @@ -595,7 +595,7 @@ impl ScriptConfig { pub async fn update_sender(&mut self, sender: Address) -> Result<()> { self.sender_nonce = if let Some(fork_url) = self.evm_opts.fork_url.as_ref() { - next_nonce(sender, fork_url, None).await? + next_nonce(sender, fork_url, None, self.config.eth_rpc_accept_invalid_certs).await? } else { // dapptools compatibility 1 diff --git a/crates/script/src/providers.rs b/crates/script/src/providers.rs index 2252010f43d3d..8b30b9a5c2855 100644 --- a/crates/script/src/providers.rs +++ b/crates/script/src/providers.rs @@ -17,11 +17,12 @@ impl ProvidersManager { &mut self, rpc: &str, is_legacy: bool, + accept_invalid_certs: bool, ) -> Result<&ProviderInfo> { Ok(match self.inner.entry(rpc.to_string()) { Entry::Occupied(entry) => entry.into_mut(), Entry::Vacant(entry) => { - let info = ProviderInfo::new(rpc, is_legacy).await?; + let info = ProviderInfo::new(rpc, is_legacy, accept_invalid_certs).await?; entry.insert(info) } }) @@ -52,8 +53,8 @@ pub enum GasPrice { } impl ProviderInfo { - pub async fn new(rpc: &str, mut is_legacy: bool) -> Result { - let provider = Arc::new(get_http_provider(rpc)); + pub async fn new(rpc: &str, mut is_legacy: bool, accept_invalid_certs: bool) -> Result { + let provider = Arc::new(get_http_provider(rpc, accept_invalid_certs)); let chain = provider.get_chain_id().await?; if let Some(chain) = Chain::from(chain).named() { diff --git a/crates/script/src/simulate.rs b/crates/script/src/simulate.rs index 354b4a3dabdf8..266b74f61919a 100644 --- a/crates/script/src/simulate.rs +++ b/crates/script/src/simulate.rs @@ -283,7 +283,7 @@ impl FilledTransactionsState { while let Some(mut tx) = txes_iter.next() { let tx_rpc = tx.rpc.to_owned(); - let provider_info = manager.get_or_init_provider(&tx.rpc, self.args.legacy).await?; + let provider_info = manager.get_or_init_provider(&tx.rpc, self.args.legacy, self.args.evm.accept_invalid_certs).await?; if let Some(tx) = tx.tx_mut().as_unsigned_mut() { // Handles chain specific requirements for unsigned transactions. diff --git a/crates/test-utils/src/script.rs b/crates/test-utils/src/script.rs index 2dfd11986d13c..2727d701ad2b8 100644 --- a/crates/test-utils/src/script.rs +++ b/crates/test-utils/src/script.rs @@ -64,7 +64,7 @@ impl ScriptTester { let mut provider = None; if let Some(endpoint) = endpoint { - provider = Some(get_http_provider(endpoint)) + provider = Some(get_http_provider(endpoint, false)) } Self {