refactor(rpc): use native PrecompilesMap::move_precompiles in simulate (#22761)

Co-authored-by: Matthias Seitz <19890894+mattsse@users.noreply.github.com>
This commit is contained in:
Derek Cofausper
2026-03-03 22:56:28 -08:00
committed by GitHub
parent c572a3559e
commit 02816ce06f

View File

@@ -97,12 +97,6 @@ pub enum EthSimulateError {
/// Max init code size exceeded.
#[error("max initcode size exceeded")]
MaxInitCodeSizeExceeded,
/// `MovePrecompileToAddress` referenced itself in replacement.
#[error("MovePrecompileToAddress referenced itself")]
PrecompileSelfReference,
/// Multiple `MovePrecompileToAddress` referencing the same address.
#[error("Multiple MovePrecompileToAddress referencing the same address")]
PrecompileDuplicateAddress,
/// Attempted to move a non-precompile address.
#[error("account {0} is not a precompile")]
NotAPrecompile(Address),
@@ -120,8 +114,6 @@ impl EthSimulateError {
Self::BlockGasLimitExceeded => -38015,
Self::BlockNumberInvalid { .. } => -38020,
Self::BlockTimestampInvalid { .. } => -38021,
Self::PrecompileSelfReference => -38022,
Self::PrecompileDuplicateAddress => -38023,
Self::SenderNotEOA => -38024,
Self::MaxInitCodeSizeExceeded => -38025,
Self::GasLimitReached => -38026,
@@ -141,29 +133,10 @@ impl ToRpcError for EthSimulateError {
/// This function processes `movePrecompileToAddress` entries from the state overrides and
/// moves precompiles from their original addresses to new addresses. The original address
/// is cleared (precompile removed) and the precompile is installed at the destination address.
///
/// # Validation
///
/// - The source address must be a precompile (exists in the precompiles map)
/// - Moving multiple precompiles to the same destination is allowed
/// - Self-references (moving to the same address) are not explicitly forbidden here since that
/// would be a no-op
///
/// # Arguments
///
/// * `state_overrides` - The state overrides containing potential `movePrecompileToAddress` entries
/// * `precompiles` - Mutable reference to the EVM's precompiles map
///
/// # Returns
///
/// Returns `Ok(())` on success, or an `EthSimulateError::NotAPrecompile` if a source address
/// is not a precompile.
pub fn apply_precompile_overrides(
state_overrides: &StateOverride,
precompiles: &mut PrecompilesMap,
) -> Result<(), EthSimulateError> {
use alloy_evm::precompiles::DynPrecompile;
let moves: Vec<_> = state_overrides
.iter()
.filter_map(|(source, account_override)| {
@@ -171,37 +144,11 @@ pub fn apply_precompile_overrides(
})
.collect();
if moves.is_empty() {
return Ok(());
}
for (source, _) in &moves {
if precompiles.get(source).is_none() {
return Err(EthSimulateError::NotAPrecompile(*source));
}
}
let mut extracted: Vec<(Address, Address, DynPrecompile)> = Vec::with_capacity(moves.len());
for (source, dest) in moves {
if source == dest {
continue;
}
let mut found_precompile: Option<DynPrecompile> = None;
precompiles.apply_precompile(&source, |existing| {
found_precompile = existing;
None
});
if let Some(precompile) = found_precompile {
extracted.push((source, dest, precompile));
}
}
for (_, dest, precompile) in extracted {
precompiles.apply_precompile(&dest, |_| Some(precompile));
}
precompiles.move_precompiles(moves).map_err(
|alloy_evm::precompiles::MovePrecompileError::NotAPrecompile(addr)| {
EthSimulateError::NotAPrecompile(addr)
},
)?;
Ok(())
}