diff --git a/SUPPORTED_APIS.md b/SUPPORTED_APIS.md
index 5cf4f405..66b8ecf0 100644
--- a/SUPPORTED_APIS.md
+++ b/SUPPORTED_APIS.md
@@ -14,6 +14,7 @@ The `status` options are:
| Namespace | API |
Status
| Description |
| --- | --- | --- | --- |
+| `ANVIL` | `anvil_setRpcUrl` | `SUPPORTED` | Sets the fork RPC url. Assumes the underlying chain is the same as before |
| `ANVIL` | `anvil_setNextBlockBaseFeePerGas` | `SUPPORTED` | Sets the base fee of the next block |
| `ANVIL` | `anvil_dropTransaction` | `SUPPORTED` | Removes a transaction from the pool |
| `ANVIL` | `anvil_dropAllTransactions` | `SUPPORTED` | Remove all transactions from the pool |
diff --git a/src/fork.rs b/src/fork.rs
index dc7c2526..691bfc25 100644
--- a/src/fork.rs
+++ b/src/fork.rs
@@ -729,6 +729,11 @@ impl ForkDetails {
}
}
}
+
+ /// Sets fork's internal URL. Assumes the underlying chain is the same as before.
+ pub fn set_rpc_url(&mut self, url: String) {
+ self.fork_source = Box::new(HttpForkSource::new(url, self.cache_config.clone()));
+ }
}
#[cfg(test)]
diff --git a/src/namespaces/anvil.rs b/src/namespaces/anvil.rs
index 8a20480f..deb24f07 100644
--- a/src/namespaces/anvil.rs
+++ b/src/namespaces/anvil.rs
@@ -6,6 +6,14 @@ use crate::utils::Numeric;
#[rpc]
pub trait AnvilNamespaceT {
+ /// Sets the fork RPC url. Assumes the underlying chain is the same as before.
+ ///
+ /// # Arguments
+ ///
+ /// * `url` - Fork's new URL
+ #[rpc(name = "anvil_setRpcUrl")]
+ fn set_rpc_url(&self, url: String) -> RpcResult<()>;
+
/// Sets the base fee of the next block.
///
/// # Arguments
diff --git a/src/node/anvil.rs b/src/node/anvil.rs
index 1837da4e..f5fdc821 100644
--- a/src/node/anvil.rs
+++ b/src/node/anvil.rs
@@ -12,6 +12,15 @@ use crate::{
impl AnvilNamespaceT
for InMemoryNode
{
+ fn set_rpc_url(&self, url: String) -> RpcResult<()> {
+ self.set_rpc_url(url)
+ .map_err(|err| {
+ tracing::error!("failed setting RPC url: {:?}", err);
+ into_jsrpc_error(Web3Error::InternalError(err))
+ })
+ .into_boxed_future()
+ }
+
fn set_next_block_base_fee_per_gas(&self, base_fee: U256) -> RpcResult<()> {
self.set_next_block_base_fee_per_gas(base_fee)
.map_err(|err| {
diff --git a/src/node/in_memory_ext.rs b/src/node/in_memory_ext.rs
index 24202d32..b1b81c61 100644
--- a/src/node/in_memory_ext.rs
+++ b/src/node/in_memory_ext.rs
@@ -423,6 +423,31 @@ impl InMemoryNo
.set_base_fee(base_fee.as_u64());
Ok(())
}
+
+ pub fn set_rpc_url(&self, url: String) -> Result<()> {
+ let inner = self
+ .inner
+ .read()
+ .map_err(|err| anyhow!("failed acquiring lock: {:?}", err))?;
+ let mut fork_storage = inner
+ .fork_storage
+ .inner
+ .write()
+ .map_err(|err| anyhow!("failed acquiring lock: {:?}", err))?;
+ if let Some(fork) = &mut fork_storage.fork {
+ let old_url = fork.fork_source.get_fork_url().map_err(|e| {
+ anyhow::anyhow!(
+ "failed to resolve current fork's RPC URL: {}",
+ e.to_string()
+ )
+ })?;
+ fork.set_rpc_url(url.clone());
+ tracing::info!("Updated fork rpc from \"{}\" to \"{}\"", old_url, url);
+ } else {
+ tracing::info!("Non-forking node tried to switch RPC URL to '{url}'. Call `anvil_reset` instead if you wish to switch to forking mode");
+ }
+ Ok(())
+ }
}
#[cfg(test)]