use super::GasArgs;
use anyhow::{Context, Result};
use colored::*;
pub fn run(args: &GasArgs) -> Result<()> {
eprintln!("{}", "⛽ Forge Guard — Gas Analysis".bold());
let mut cmd = std::process::Command::new("forge");
cmd.arg("snapshot");
if let Some(contract) = &args.contract {
cmd.arg("--match-contract").arg(contract);
}
if args.all {
cmd.arg("--all");
}
eprintln!("\n🚀 Running gas analysis...\n");
let output = cmd.output().context("Failed to run forge snapshot")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::bail!("Gas analysis failed: {}", stderr);
}
let stdout = String::from_utf8_lossy(&output.stdout);
println!("{}", stdout);
eprintln!("{}", "\n── Gas Summary ──".bold());
eprintln!(
" ⚠️ Functions exceeding {} gas threshold will need optimization",
args.warn_threshold
);
for line in stdout.lines() {
if let Some(gas_str) = line.split('|').nth(2) {
if let Ok(gas) = gas_str.trim().replace(',', "").parse::<u64>() {
if gas > args.warn_threshold {
println!(
" {} {} — {} gas",
"⚠️".yellow(),
line.split('|').next().unwrap_or("?").trim(),
gas
);
}
}
}
}
if let Some(diff_path) = &args.diff {
eprintln!("\n📊 Gas diff against {} requested", diff_path);
}
eprintln!("\n{}", "✅ Gas analysis complete.".green().bold());
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gas_arg_defaults() {
let args = GasArgs {
shared: super::super::SharedFlags {
chain: "ethereum".into(),
project: std::path::PathBuf::from("."),
json: false,
markdown: false,
strict: false,
offline: false,
production: false,
report: false,
parallelism: 4,
},
contract: None,
diff: None,
all: false,
warn_threshold: 50_000,
};
assert!(args.contract.is_none());
assert!(args.diff.is_none());
assert!(!args.all);
assert_eq!(args.warn_threshold, 50_000);
}
#[test]
fn test_gas_with_contract_and_threshold() {
let args = GasArgs {
shared: super::super::SharedFlags::default(),
contract: Some("Counter".into()),
diff: Some("previous.json".into()),
all: true,
warn_threshold: 100_000,
};
assert_eq!(args.contract.as_deref(), Some("Counter"));
assert_eq!(args.diff.as_deref(), Some("previous.json"));
assert!(args.all);
assert_eq!(args.warn_threshold, 100_000);
}
}