Skip to content

Commit

Permalink
fix(anvil): reset from fork to another fork (#8768)
Browse files Browse the repository at this point in the history
fix(anvil): reset from fork to another fork
  • Loading branch information
yash-atreya authored Sep 6, 2024
1 parent d8f6631 commit 872e2f3
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 27 deletions.
1 change: 0 additions & 1 deletion crates/anvil/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1075,7 +1075,6 @@ impl NodeConfig {
let provider = Arc::new(
ProviderBuilder::new(&eth_rpc_url)
.timeout(self.fork_request_timeout)
// .timeout_retry(self.fork_request_retries)
.initial_backoff(self.fork_retry_backoff.as_millis() as u64)
.compute_units_per_second(self.compute_units_per_second)
.max_retry(self.fork_request_retries)
Expand Down
64 changes: 39 additions & 25 deletions crates/anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{
storage::{BlockchainStorage, InMemoryBlockStates, MinedBlockOutcome},
},
revm::{db::DatabaseRef, primitives::AccountInfo},
NodeConfig, PrecompileFactory,
ForkChoice, NodeConfig, PrecompileFactory,
};
use alloy_consensus::{Account, Header, Receipt, ReceiptWithBloom};
use alloy_eips::eip4844::MAX_BLOBS_PER_BLOCK;
Expand Down Expand Up @@ -427,37 +427,51 @@ impl Backend {
.ok_or(BlockchainError::BlockNotFound)?;
// update all settings related to the forked block
{
let mut env = self.env.write();
env.cfg.chain_id = fork.chain_id();

env.block = BlockEnv {
number: U256::from(fork_block_number),
timestamp: U256::from(fork_block.header.timestamp),
gas_limit: U256::from(fork_block.header.gas_limit),
difficulty: fork_block.header.difficulty,
prevrandao: Some(fork_block.header.mix_hash.unwrap_or_default()),
// Keep previous `coinbase` and `basefee` value
coinbase: env.block.coinbase,
basefee: env.block.basefee,
..env.block.clone()
};
if let Some(fork_url) = forking.json_rpc_url {
// Set the fork block number
let mut node_config = self.node_config.write().await;
node_config.fork_choice = Some(ForkChoice::Block(fork_block_number));

self.time.reset(env.block.timestamp.to::<u64>());
let mut env = self.env.read().clone();
let (forked_db, client_fork_config) =
node_config.setup_fork_db_config(fork_url, &mut env, &self.fees).await;

// this is the base fee of the current block, but we need the base fee of
// the next block
let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas(
fork_block.header.gas_used,
fork_block.header.gas_limit,
fork_block.header.base_fee_per_gas.unwrap_or_default(),
);
*self.db.write().await = Box::new(forked_db);
let fork = ClientFork::new(client_fork_config, Arc::clone(&self.db));
*self.fork.write() = Some(fork);
*self.env.write() = env;
} else {
let mut env = self.env.write();
env.cfg.chain_id = fork.chain_id();
env.block = BlockEnv {
number: U256::from(fork_block_number),
timestamp: U256::from(fork_block.header.timestamp),
gas_limit: U256::from(fork_block.header.gas_limit),
difficulty: fork_block.header.difficulty,
prevrandao: Some(fork_block.header.mix_hash.unwrap_or_default()),
// Keep previous `coinbase` and `basefee` value
coinbase: env.block.coinbase,
basefee: env.block.basefee,
..env.block.clone()
};

self.fees.set_base_fee(next_block_base_fee);
// this is the base fee of the current block, but we need the base fee of
// the next block
let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas(
fork_block.header.gas_used,
fork_block.header.gas_limit,
fork_block.header.base_fee_per_gas.unwrap_or_default(),
);

self.fees.set_base_fee(next_block_base_fee);
}

// reset the time to the timestamp of the forked block
self.time.reset(fork_block.header.timestamp);

// also reset the total difficulty
self.blockchain.storage.write().total_difficulty = fork.total_difficulty();
}

// reset storage
*self.blockchain.storage.write() = BlockchainStorage::forked(
fork.block_number(),
Expand Down
34 changes: 33 additions & 1 deletion crates/anvil/tests/it/fork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
abi::{Greeter, ERC721},
utils::{http_provider, http_provider_with_signer},
};
use alloy_chains::NamedChain;
use alloy_network::{EthereumWallet, ReceiptResponse, TransactionBuilder};
use alloy_primitives::{address, b256, bytes, Address, Bytes, TxHash, TxKind, U256};
use alloy_provider::Provider;
Expand All @@ -17,7 +18,7 @@ use alloy_signer_local::PrivateKeySigner;
use anvil::{eth::EthApi, spawn, NodeConfig, NodeHandle};
use foundry_common::provider::get_http_provider;
use foundry_config::Config;
use foundry_test_utils::rpc::{self, next_http_rpc_endpoint};
use foundry_test_utils::rpc::{self, next_http_rpc_endpoint, next_rpc_endpoint};
use futures::StreamExt;
use std::{sync::Arc, thread::sleep, time::Duration};

Expand Down Expand Up @@ -476,6 +477,37 @@ async fn can_reset_properly() {
assert!(fork_tx_provider.get_transaction_by_hash(tx.transaction_hash).await.unwrap().is_none())
}

// Ref: <https://github.com/foundry-rs/foundry/issues/8684>
#[tokio::test(flavor = "multi_thread")]
async fn can_reset_fork_to_new_fork() {
let eth_rpc_url = next_rpc_endpoint(NamedChain::Mainnet);
let (api, handle) = spawn(NodeConfig::test().with_eth_rpc_url(Some(eth_rpc_url))).await;
let provider = handle.http_provider();

let op = address!("C0d3c0d3c0D3c0D3C0d3C0D3C0D3c0d3c0d30007"); // L2CrossDomainMessenger - Dead on mainnet.

let tx = TransactionRequest::default().with_to(op).with_input("0x54fd4d50");

let tx = WithOtherFields::new(tx);

let mainnet_call_output = provider.call(&tx).await.unwrap();

assert_eq!(mainnet_call_output, Bytes::new()); // 0x

let optimism = next_rpc_endpoint(NamedChain::Optimism);

api.anvil_reset(Some(Forking {
json_rpc_url: Some(optimism.to_string()),
block_number: Some(124659890),
}))
.await
.unwrap();

let code = provider.get_code_at(op).await.unwrap();

assert_ne!(code, Bytes::new());
}

#[tokio::test(flavor = "multi_thread")]
async fn test_fork_timestamp() {
let start = std::time::Instant::now();
Expand Down

0 comments on commit 872e2f3

Please sign in to comment.