Langsung ke konten utama
RekayasaMar 28, 2026

Deep EVM #15: Simulasi MEV — Binary Search, State Fork, dan Deadline 12 Detik

OS
Open Soft Team

Engineering Team

Mengapa Simulasi Diperlukan

Menemukan peluang arbitrase di graf pool tidak cukup — Anda harus memverifikasi bahwa transaksi benar-benar akan berhasil dan menguntungkan pada state blockchain saat ini. Simulasi adalah jembatan antara analisis off-chain dan eksekusi on-chain.

Tanpa simulasi, Anda akan:

  • Mengirim transaksi yang revert (membuang gas)
  • Salah menghitung profitabilitas (reserves sudah berubah)
  • Gagal memperhitungkan efek samping (reentrancy guard, pause mechanism)

revm: Simulator EVM di Rust

revm adalah implementasi EVM di Rust yang cepat dan modular. Digunakan oleh Foundry, Reth, dan sebagian besar bot MEV di produksi.

use revm::{
    db::CacheDB,
    primitives::{ExecutionResult, Output, TransactTo, U256},
    Evm,
};

fn simulate_swap(
    db: &mut CacheDB<impl DatabaseRef>,
    from: Address,
    to: Address,
    calldata: Bytes,
    value: U256,
) -> Result<Bytes, SimError> {
    let mut evm = Evm::builder()
        .with_db(db)
        .modify_tx_env(|tx| {
            tx.caller = from;
            tx.transact_to = TransactTo::Call(to);
            tx.data = calldata;
            tx.value = value;
            tx.gas_limit = 500_000;
        })
        .build();
    
    let result = evm.transact_commit()?;
    
    match result {
        ExecutionResult::Success { output, gas_used, .. } => {
            match output {
                Output::Call(data) => Ok(data),
                _ => Err(SimError::UnexpectedOutput),
            }
        }
        ExecutionResult::Revert { output, .. } => {
            Err(SimError::Revert(output))
        }
        ExecutionResult::Halt { reason, .. } => {
            Err(SimError::Halt(reason))
        }
    }
}

Fork State dari Node

Untuk simulasi akurat, Anda perlu state blockchain terbaru:

use alloy::providers::Provider;
use revm::db::AlloyDB;

async fn create_fork_db(provider: &impl Provider) -> CacheDB<AlloyDB> {
    let block = provider.get_block_number().await.unwrap();
    let alloy_db = AlloyDB::new(provider.clone(), block);
    CacheDB::new(alloy_db)
}

CacheDB meng-cache hasil query sehingga pembacaan berulang dari slot storage yang sama tidak memerlukan RPC call tambahan.

Binary Search untuk Jumlah Optimal

Alih-alih menghitung secara analitis, gunakan simulasi aktual untuk menemukan jumlah input optimal:

async fn find_optimal_amount(
    db: &CacheDB<impl DatabaseRef>,
    cycle: &ArbitrageCycle,
) -> (U256, U256) {
    let mut lo = U256::from(1_000_000_000_000_000u64); // 0.001 ETH
    let mut hi = U256::from(50_000_000_000_000_000_000u128); // 50 ETH
    
    for _ in 0..40 {
        let mid = (lo + hi) / 2;
        
        // Clone DB untuk simulasi non-destruktif
        let mut sim_db = db.clone();
        
        let profit = simulate_cycle(&mut sim_db, cycle, mid);
        let profit_higher = simulate_cycle(&mut db.clone(), cycle, mid + mid / 100);
        
        if profit_higher > profit {
            lo = mid;
        } else {
            hi = mid;
        }
    }
    
    let optimal = (lo + hi) / 2;
    let profit = simulate_cycle(&mut db.clone(), cycle, optimal);
    (optimal, profit)
}

Deadline 12 Detik

Ethereum menghasilkan block setiap 12 detik. Pencari MEV harus:

  1. Deteksi peluang — Memantau mempool dan event (1-2 detik)
  2. Simulasikan dan optimasi — Jalankan simulasi revm (1-3 detik)
  3. Bangun bundle — Buat dan tandatangani transaksi (< 1 detik)
  4. Kirim ke pembangun — Melalui Flashbots atau relay (1-2 detik)
  5. Margin keamanan — Waktu buffer (2-3 detik)

Total budget: ~12 detik. Jika simulasi memakan waktu terlalu lama, peluang sudah lewat.

Strategi Optimasi Waktu

use tokio::time::{timeout, Duration};

async fn search_with_deadline(
    opportunities: Vec<ArbitrageCycle>,
    db: &CacheDB<impl DatabaseRef>,
    deadline: Duration,
) -> Option<(ArbitrageCycle, U256, U256)> {
    let start = std::time::Instant::now();
    let mut best: Option<(ArbitrageCycle, U256, U256)> = None;
    
    for opp in opportunities {
        // Periksa deadline
        if start.elapsed() > deadline {
            break;
        }
        
        let remaining = deadline - start.elapsed();
        
        // Simulasi dengan timeout
        match timeout(remaining / 2, find_optimal_amount(db, &opp)).await {
            Ok((amount, profit)) => {
                if let Some((_, _, best_profit)) = &best {
                    if profit > *best_profit {
                        best = Some((opp, amount, profit));
                    }
                } else {
                    best = Some((opp, amount, profit));
                }
            }
            Err(_) => break, // Timeout
        }
    }
    
    best
}

Memperhitungkan Gas

Profitabilitas bersih = output - input - biaya gas:

fn net_profit(
    gross_profit: U256,
    gas_used: u64,
    base_fee: U256,
    priority_fee: U256,
) -> I256 {
    let gas_cost = U256::from(gas_used) * (base_fee + priority_fee);
    I256::from_raw(gross_profit) - I256::from_raw(gas_cost)
}

Bot MEV juga harus menawar sebagian profit ke pembangun block sebagai “tip” agar bundle mereka disertakan.

Simulasi Multi-Transaksi (Bundle)

Bundle MEV sering berisi beberapa transaksi:

fn simulate_bundle(
    db: &mut CacheDB<impl DatabaseRef>,
    transactions: &[Transaction],
) -> Result<BundleResult, SimError> {
    let mut total_gas = 0u64;
    let mut results = Vec::new();
    
    for tx in transactions {
        let result = simulate_swap(
            db,
            tx.from,
            tx.to,
            tx.calldata.clone(),
            tx.value,
        )?;
        total_gas += result.gas_used;
        results.push(result);
    }
    
    Ok(BundleResult {
        total_gas,
        results,
    })
}

PENTING: Simulasi bundle harus dijalankan secara sekuensial pada DB yang sama karena setiap transaksi mengubah state yang memengaruhi transaksi berikutnya.

Kesimpulan

Simulasi adalah komponen kritis infrastruktur MEV. revm memberikan simulasi cepat di Rust, fork state memastikan akurasi, binary search mengoptimalkan jumlah input, dan manajemen deadline memastikan Anda tidak melewatkan peluang. Kemampuan mensimulasikan dengan cepat dan akurat adalah keunggulan kompetitif utama bagi pencari MEV.