Aller au contenu principal
BlockchainMar 28, 2026

Deep EVM #15 : Simulation MEV — Recherche binaire, forks d'état et le délai de 12 secondes

OS
Open Soft Team

Engineering Team

Pourquoi simuler ?

Dans le MEV, vous ne pouvez pas deviner — vous devez savoir exactement combien de profit une opportunité va générer, combien de gas elle consommera, et si la transaction réussira. La simulation est la seule façon d’obtenir ces réponses avant de soumettre un bundle.

Fork d’état avec revm

revm est une implémentation de l’EVM en Rust, optimisée pour la vitesse. Elle peut forker l’état d’un nœud Ethereum et exécuter des transactions localement :

use revm::{EVM, db::CacheDB, primitives::*};

fn simulate_swap(
    state: &CacheDB,
    swap_calldata: Bytes,
    target_contract: Address,
) -> Result<SimResult, Error> {
    let mut evm = EVM::new();
    evm.database(state.clone());

    evm.env.tx = TxEnv {
        caller: bot_address(),
        transact_to: TransactTo::Call(target_contract),
        data: swap_calldata,
        value: U256::ZERO,
        gas_limit: 500_000,
        ..Default::default()
    };

    let result = evm.transact()?;
    Ok(SimResult {
        gas_used: result.gas_used,
        output: result.output,
        success: result.is_success(),
    })
}

Recherche binaire du montant optimal

La courbe profit/montant pour un arbitrage AMM est concave — le profit augmente avec le montant jusqu’à un point optimal puis diminue. La recherche binaire est idéale :

fn find_optimal_amount(
    state: &CacheDB,
    cycle: &[Pool],
    token: Address,
) -> (U256, U256) {
    let mut lo = U256::from(1_000_000); // 0.001 ETH minimum
    let mut hi = U256::from(100_000_000_000_000_000_000u128); // 100 ETH max

    for _ in 0..128 {
        let mid = (lo + hi) / 2;
        let profit_at_mid = simulate_cycle(state, cycle, mid);
        let profit_at_mid_plus = simulate_cycle(state, cycle, mid + lo);

        if profit_at_mid_plus > profit_at_mid {
            lo = mid;
        } else {
            hi = mid;
        }
    }

    let optimal = (lo + hi) / 2;
    let profit = simulate_cycle(state, cycle, optimal);
    (optimal, profit)
}

Le délai de 12 secondes

Les blocs Ethereum arrivent toutes les 12 secondes. Votre pipeline doit :

  1. Recevoir le nouveau bloc
  2. Mettre à jour l’état local
  3. Détecter les nouvelles opportunités
  4. Simuler chaque opportunité
  5. Optimiser le montant
  6. Soumettre le bundle au constructeur de blocs

Tout cela en moins de ~6 secondes (pour laisser au constructeur le temps d’inclure votre bundle).

async fn block_pipeline(block: Block) {
    let start = Instant::now();
    let deadline = start + Duration::from_secs(6);

    // Mise à jour de l'état
    let state = update_state(&block).await;

    // Recherche d'opportunités en parallèle
    let opportunities = find_opportunities(&state).await;

    for opp in opportunities {
        if Instant::now() > deadline {
            break; // Plus le temps — soumettre ce qu'on a
        }

        let (amount, profit) = find_optimal_amount(&state, &opp);
        let gas_cost = estimate_gas_cost(&state, &opp, amount);

        if profit > gas_cost * 2 { // Marge de sécurité 2x
            submit_bundle(&opp, amount).await;
        }
    }
}

Simulation de bundles

Un bundle MEV peut contenir plusieurs transactions ordonnées. Simulez le bundle complet, pas les transactions individuelles :

fn simulate_bundle(
    state: &CacheDB,
    transactions: &[Transaction],
) -> BundleResult {
    let mut current_state = state.clone();
    let mut total_profit = U256::ZERO;
    let mut total_gas = 0u64;

    for tx in transactions {
        let result = simulate_on_state(&current_state, tx);
        if !result.success {
            return BundleResult::Failed;
        }
        current_state = result.new_state;
        total_profit += result.profit;
        total_gas += result.gas_used;
    }

    BundleResult::Success { total_profit, total_gas }
}

Conclusion

La simulation MEV est le pont entre la détection d’opportunités et la soumission de bundles rentables. revm pour le fork d’état, la recherche binaire pour l’optimisation, et le respect strict du délai de 12 secondes constituent les piliers du pipeline.

Dans le prochain article, nous couvrirons le bundling et la résolution de conflits.