Skip to main content

atupa_core/
lib.rs

1pub mod config;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5/// Standard EVM Gas Categories for logical grouping of execution costs.
6#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
7#[serde(rename_all = "PascalCase")]
8pub enum GasCategory {
9    /// Opcodes like SSTORE
10    StorageWrite,
11    /// Opcodes like SLOAD
12    StorageRead,
13    /// Memory operations (MLOAD, MSTORE, etc.)
14    Memory,
15    /// Cryptographic operations (KECCAK256)
16    Crypto,
17    /// External calls (CALL, DELEGATECALL, etc.)
18    Call,
19    /// Logic and arithmetic
20    Execution,
21    /// Precompiled contract calls
22    Precompile,
23    /// Root execution frame
24    Root,
25    #[default]
26    Other,
27}
28
29/// A single step in the EVM execution trace (equivalent to structLog).
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct TraceStep {
32    pub pc: u64,
33    pub op: String,
34    pub gas: u64,
35    pub gas_cost: u64,
36    pub depth: u16,
37    pub stack: Option<Vec<String>>,
38    pub memory: Option<Vec<String>>,
39    #[serde(default)]
40    pub error: Option<String>,
41    #[serde(default)]
42    pub reverted: bool,
43}
44
45/// A single collapsed stack entry for aggregation.
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct CollapsedStack {
48    pub stack: String,
49    pub weight: u64,
50    pub last_pc: Option<u64>,
51    #[serde(default)]
52    pub target_address: Option<String>,
53    #[serde(default)]
54    pub resolved_label: Option<String>,
55    #[serde(default)]
56    pub reverted: bool,
57}
58
59/// A collapsed execution path with aggregated gas costs.
60#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct HotPath {
62    pub stack: String,
63    pub gas: u64,
64    pub percentage: f64,
65    pub category: GasCategory,
66}
67
68/// The final report generated by Atupa.
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct Profile {
71    pub version: String,
72    pub transaction_hash: String,
73    pub total_gas: u64,
74    pub categories: HashMap<GasCategory, u64>,
75    pub hot_paths: Vec<HotPath>,
76    pub generated_at: String,
77}
78
79impl Profile {
80    pub fn new(tx_hash: String) -> Self {
81        Self {
82            version: env!("CARGO_PKG_VERSION").to_string(),
83            transaction_hash: tx_hash,
84            total_gas: 0,
85            categories: HashMap::new(),
86            hot_paths: Vec::new(),
87            generated_at: chrono::Utc::now().to_rfc3339(),
88        }
89    }
90}