Crates.io | revm-trace |
lib.rs | revm-trace |
version | 2.0.0 |
source | src |
created_at | 2024-11-24 04:21:34.641751 |
updated_at | 2024-12-09 03:36:19.519911 |
description | A Rust library for tracing EVM transactions, including call traces, asset transfers, and error analysis using REVM |
homepage | |
repository | https://github.com/Rollp0x/revm-trace |
max_upload_size | |
id | 1458958 |
size | 268,961 |
A Rust library that combines powerful transaction simulation with comprehensive analysis capabilities for EVM-based blockchains. Built on REVM, this tool enables you to:
Perfect for:
Flexible Inspector System
TxInspector
for transaction analysisComplete Call Hierarchy Analysis
Enhanced Error Handling
Batch Transaction Processing
Asset Analysis
async
- Enable async support
ws
- WebSocket provider support
http
- HTTP provider support (default)
Add this to your Cargo.toml
:
revm-trace = "2.0.0"
use revm_trace::{
TransactionProcessor,
evm::create_evm_with_inspector,
types::{BlockEnv, SimulationTx, SimulationBatch},
inspectors::TxInspector,
};
use alloy::primitives::{address, U256, TxKind};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Initialize EVM with transaction inspector
let mut evm = create_evm_with_inspector(
"https://eth-mainnet.g.alchemy.com/v2/your-api-key",
TxInspector::new(),
).await?;
// Create simulation transaction
let tx = SimulationTx {
caller: address!("dead00000000000000000000000000000000beef"),
transact_to: TxKind::Call(address!("dac17f958d2ee523a2206206994597c13d831ec7")),
value: U256::from(1000000000000000000u64), // 1 ETH
data: vec![].into(),
};
// Create batch with single transaction
let batch = SimulationBatch {
block_env: BlockEnv {
number: 18000000,
timestamp: 1700000000,
},
transactions: vec![tx],
is_stateful: false,
};
// Execute transaction batch
let results = evm.process_transactions(batch)
.into_iter()
.map(|v| v.unwrap())
.collect::<Vec<_>>();
// Process results
for (execution_result, inspector_output) in results {
match execution_result.is_success() {
true => {
println!("Transaction succeeded!");
for transfer in inspector_output.asset_transfers {
println!(
"Transfer: {} from {} to {}",
transfer.value, transfer.from, transfer.to.unwrap()
);
}
}
false => {
println!("Transaction failed!");
if let Some(error_trace) = inspector_output.error_trace_address {
println!("Error occurred at call depth: {}", error_trace.len());
}
}
}
}
Ok(())
}
For more detailed examples and use cases, please check:
Example Directory: Contains standalone examples demonstrating specific features
Integration Tests: Comprehensive test cases showing various usage scenarios
These examples cover common use cases and demonstrate best practices for using the library.
For a quick overview, here are some key examples:
All simulations run in an isolated environment:
The EVM instance is not thread-safe and cannot be shared between threads. Here's how to handle concurrent operations:
// DON'T share a single EVM instance across threads
let mut evm = create_evm_with_inspector("https://rpc...", TxInspector::new()).await?;
let results: Vec<_> = transactions
.par_iter() // ❌ This will fail - EVM instance is not thread-safe
.map(|tx| {
evm.process_transactions(SimulationBatch {
block_env: block_env.clone(),
transactions: vec![tx.clone()],
is_stateful: true,
}) // Sharing EVM across threads
})
.collect();
// Process transactions sequentially with a single EVM instance
let mut evm = create_evm_with_inspector("https://rpc...", TxInspector::new()).await?;
let results: Vec<_> = transactions
.iter()
.map(|tx| {
evm.process_transactions(SimulationBatch {
block_env: block_env.clone(),
transactions: vec![tx.clone()],
is_stateful: true,
})
})
.collect();
use rayon::prelude::*;
// Create new EVM instance for each thread
let results: Vec<Result<_, _>> = transactions
.par_iter()
.map(|tx| async {
// Each thread gets its own EVM instance
let mut evm = create_evm_with_inspector("https://rpc...", TxInspector::new()).await?;
evm.process_transactions(SimulationBatch {
block_env: block_env.clone(),
transactions: vec![tx.clone()],
is_stateful: true,
})
})
.collect();
RPC Limitations:
Resource Usage:
Optimal Approach:
For small batches: Use sequential processing
For large batches: Use parallel processing with connection pooling
Consider implementing a worker pool pattern for better resource management
The library automatically handles proxy contracts by resolving their implementations:
Simulations can be run against different historical states:
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under either of
at your option.