Skip to content

Commit ff0db6f

Browse files
authored
fix(anvil): coerce decoder hardfork to executed network family (#16454)
1 parent e1d41a7 commit ff0db6f

4 files changed

Lines changed: 50 additions & 2 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
anvil: patch
3+
---
4+
5+
Fixed anvil trace decoding to follow the executed network hardfork when a cross-namespace hardfork override is configured.

crates/anvil/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1422,7 +1422,7 @@ impl NodeConfig {
14221422
.unwrap_or_else(|| self.get_hardfork());
14231423
let mut decoder_builder = CallTraceDecoderBuilder::new()
14241424
.with_networks(self.networks)
1425-
.with_hardfork(Some(active_hardfork));
1425+
.with_hardfork(Some(self.networks.executed_hardfork(active_hardfork)));
14261426
if self.print_traces {
14271427
// if traces should get printed we configure the decoder with the signatures cache
14281428
if let Ok(identifier) = SignaturesIdentifier::new(false) {

crates/anvil/src/eth/backend/mem/mod.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1490,7 +1490,7 @@ impl<N: Network> Backend<N> {
14901490

14911491
/// Returns a trace decoder configured for the currently resolved hardfork.
14921492
fn call_trace_decoder(&self) -> Arc<CallTraceDecoder> {
1493-
let hardfork = Some(self.hardfork());
1493+
let hardfork = Some(self.networks.executed_hardfork(self.hardfork()));
14941494
let decoder = self.call_trace_decoder.read();
14951495
if decoder.hardfork() == hardfork {
14961496
return Arc::clone(&decoder);
@@ -9883,6 +9883,20 @@ mod tests {
98839883
assert_eq!(outcome.block_number, original_best_number + 1);
98849884
}
98859885

9886+
#[tokio::test]
9887+
async fn trace_decoder_follows_executed_hardfork_for_cross_namespace_override() {
9888+
let (api, _) = spawn(
9889+
NodeConfig::test_tempo()
9890+
.with_hardfork(Some(FoundryHardfork::Ethereum(EthereumHardfork::Prague))),
9891+
)
9892+
.await;
9893+
9894+
let decoder = api.backend.call_trace_decoder();
9895+
assert_eq!(decoder.hardfork(), Some(FoundryHardfork::Tempo(api.backend.tempo_hardfork())));
9896+
// The refresh compares the same coerced value, so repeated calls stay stable.
9897+
assert!(Arc::ptr_eq(&decoder, &api.backend.call_trace_decoder()));
9898+
}
9899+
98869900
#[cfg(feature = "monad")]
98879901
#[tokio::test]
98889902
async fn monad_trace_decoder_follows_resolved_hardfork() {

crates/evm/networks/src/lib.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,23 @@ impl NetworkConfigs {
461461
false
462462
}
463463

464+
/// Coerces `hardfork` into this network's family.
465+
///
466+
/// Execution and fee rules apply the same lossy `From` conversions, so a cross-namespace
467+
/// override such as `--hardfork prague` on a Tempo node runs as a Tempo hardfork. Callers that
468+
/// need to describe what actually executed, like trace decoding, go through here rather than
469+
/// carrying the configured value.
470+
pub fn executed_hardfork(&self, hardfork: FoundryHardfork) -> FoundryHardfork {
471+
if self.is_tempo() {
472+
return TempoHardfork::from(hardfork).into();
473+
}
474+
#[cfg(feature = "monad")]
475+
if self.is_monad() {
476+
return MonadHardfork::from(hardfork).into();
477+
}
478+
hardfork
479+
}
480+
464481
/// Returns additional cheatcode contract addresses for the active network.
465482
pub const fn extra_cheatcode_addresses(&self) -> &'static [Address] {
466483
#[cfg(feature = "monad")]
@@ -1789,4 +1806,16 @@ mod tests {
17891806
assert!(cfg_optimism.is_optimism());
17901807
}
17911808
}
1809+
1810+
#[test]
1811+
fn executed_hardfork_follows_the_network_family() {
1812+
// A cross-namespace override runs as the configured network's hardfork, so the value used
1813+
// to describe execution has to be coerced the same way.
1814+
let prague = FoundryHardfork::Ethereum(EthereumHardfork::Prague);
1815+
assert_eq!(NetworkConfigs::default().executed_hardfork(prague), prague);
1816+
assert_eq!(
1817+
NetworkConfigs::with_tempo().executed_hardfork(prague),
1818+
FoundryHardfork::Tempo(TempoHardfork::from(prague))
1819+
);
1820+
}
17921821
}

0 commit comments

Comments
 (0)