feat(v0.2.0): Universal Multi-VM Execution Profiler, Atupa Studio, and Protocol Deep Audits - #12
Merged
Merged
Conversation
…a, Starknet, and Stellar support
- Extracted network-specific handlers from monolithic routers (cmd_capture, cmd_diff). - Modularized Nitro diff processing (calculate, print, render markdown, svg). - Modularized generic diff processing and rendering terminal summaries. - Fixed Clippy warnings (too_many_arguments, collapsible if). - Fully formatted the codebase.
…tput format Previously, finalize_report() unconditionally wrote the 'rendered' string to the .json artifact file. When --output=summary (the default), rendered contained ANSI terminal escape codes, making the file unreadable by Studio, CI tooling, and any downstream JSON parser. Fix: introduce a separate json_for_disk parameter that always holds the full serde_json-serialised report. The terminal-rendered string (with ANSI codes, short summaries, metric values) is printed to stdout only. All four capture handlers (nitro, starknet, solana, stellar) updated. render_nitro_report now returns (terminal_text, json) as a tuple.
…dio compatibility Starknet, Solana and Stellar capture handlers previously wrote a raw Vec<TraceStep> array to disk. The Studio's App.tsx and reportToTree.ts expect a StitchedReport object (tx_hash, steps: UnifiedStep[], totals). Loading non-Nitro reports in Studio would crash. Changes: - atupa-nitro VmKind: add Starknet / Solana / Stellar variants (From impl updated) - main.rs: add trace_steps_to_report() helper that wraps Vec<TraceStep> into a proper StitchedReport with chain-specific VmKind on each step - All three handlers use trace_steps_to_report() so every .json artifact is a uniform StitchedReport — loadable by Studio, diff, audit commands
- Split monolithic lib.rs into vm.rs, gas.rs, types.rs, diff.rs, config.rs - VmKind: add #[non_exhaustive], Display, TryFrom<&str> (with 'soroban' alias), and ParseVmKindError - GasCategory: exhaustive EVM match, unified classify_by_keyword() helper for Stylus/Starknet/Solana/Stellar, GasCategory::from_step now takes &VmKind - TraceStep: add TraceStep::evm() test-fixture constructor and is_call() helper - Profile: introduce ProfileBuilder with injectable generated_at timestamp for deterministic snapshot testing - DiffRow: add is_regression(), is_improvement(), is_neutral() predicates - ProtocolDiffReport: add has_regressions(), regressions(), improvements() helpers - AtupaConfig: add validate(), extract build_figment() helper, replace silent unwrap_or_else with log::warn!, use ENV_LOCK Mutex in tests for safe env mutation - lib.rs is now a thin re-export facade — all downstream import paths unchanged - 35 unit tests + 4 doc-tests all passing; clippy -D warnings clean
…nd tests - Extract LiquidationAccumulator to hold per-step state, removing the 60-line monolith from analyze_liquidation - Extract private helpers: resolve_address(), resolve_selector(), is_call_opcode(), selector_from_stack(), classify_gho_label(), build_diff_rows() — each with a single clear responsibility - Merge the duplicated selector-lookup logic from resolve_label and resolve_selector_label into one shared resolve_selector() function - is_call_opcode() predicate shared by both analyze_liquidation and extract_gho_metrics, eliminating the duplicated guard - Fix bogus oracle addresses (placeholder '0xD81E9938...?' and oversized address) with real Ethereum Mainnet values; store all addresses lowercase for O(1) compare - Add LIQUIDATION_EFFICIENCY_BASE named constant replacing the magic 100_000.0 - Fix summary() panic on short hashes by using .get(..10).unwrap_or() - Add #[derive(PartialEq)] to LiquidationReport, LabeledCall, GhoSupplyMetrics - Remove unused thiserror and serde_json from Cargo.toml - Expand tests from 5 → 15, covering: facilitator/oracle address resolution, resolve_selector_label, summary() short-hash safety, zero-efficiency edge case, reverted-flag propagation, GHO non-call filter, and diff regression detection
Mirrors the same pattern applied to atupa-core.
New modules:
- selectors.rs : const tables (POOL_SELECTORS, GHO_SELECTORS, GHO_FACILITATORS,
AAVE_ORACLES), resolve_address(), resolve_selector(),
is_call_opcode(), selector_from_stack(), LIQUIDATION_EFFICIENCY_BASE
- adapter.rs : AaveV3Adapter + ProtocolAdapter impl + static resolve_selector_label
- gho.rs : GhoSupplyMetrics + classify_gho_label()
- report.rs : LiquidationReport, LabeledCall, LiquidationAccumulator
- tracer.rs : AaveDeepTracer, build_diff_rows()
- lib.rs : thin pub mod + pub use re-export facade (all paths unchanged)
Tests: 35 tests across all 5 modules (selectors: 10, adapter: 7, gho: 5,
report: 5, tracer: 8) — all passing, clippy -D warnings clean
…ilder and ERC-20 adapter - Split monolithic lib.rs into traits.rs, registry.rs, uniswap_v4.rs, erc20.rs - ProtocolAdapter: add Send + Sync bounds, default helper methods (resolve_selector, resolve_address, matches_address, matches_selector) - AdapterRegistry: add with_adapter/with_boxed_adapter builder chaining, register_typed, clear, contains, len, is_empty, iter, and resolve_selector/resolve_address helpers - UniswapV4Adapter: static resolve_hook_selector helper, case-insensitive matching - Erc20Adapter: new standard ERC-20/ERC-721/permit built-in adapter - Clean up unused dependencies from Cargo.toml - Add 18 unit tests + doc tests (previously 0 unit tests), clippy clean
…nd comprehensive test suite - Split monolithic lib.rs into selectors.rs, adapter.rs, report.rs, tracer.rs - selectors.rs: exact/prefixed/case-insensitive selector matching, lowercase address constants - adapter.rs: LidoAdapter + ProtocolAdapter implementation with static resolve_selector_label - report.rs: LidoReport, LabeledCall, LidoAccumulator step processor, summary() with safe slice - tracer.rs: LidoDeepTracer, build_diff_rows() - lib.rs: thin re-export facade - Clean up unused dependencies (serde_json, log) from Cargo.toml - Add 19 unit tests (previously 0 unit tests), clippy clean
…itcher, client, and types - Split monolithic lib.rs into error.rs, types.rs, stitcher.rs, client.rs - error.rs: NitroError enum with Network, Rpc, Serialization, Stitch variants, NitroResult alias - types.rs: StylusHostIO (cost calculations), VmKind (Display + conversion), UnifiedStep (to_trace_step, is_evm, is_stylus), StitchedReport (queries, summary with bounds check) - stitcher.rs: MixedTraceStitcher decomposed into clean helpers (extract_target_address, drain_wasm_window, drain_trailing_stylus_steps, aggregate_category_costs) - client.rs: NitroClient with concurrent dual-tracing and extracted is_nitro_chain helper - Clean up unused anyhow dependency from Cargo.toml - Expanded unit tests to 15 tests, full workspace clippy clean
…or, and diff renderer - Split monolithic lib.rs into common.rs, flamegraph.rs, diff.rs - common.rs: layout constants (canvas width, bar height, padding), shared truncate_label(), stack_leaf(), and render_empty_svg() - flamegraph.rs: SvgGenerator with decomposed layout_depth_lanes(), layout_wasm_section(), make_bar_label(), build_tooltip(), get_stack_css_class() - diff.rs: generate_diff_flamegraph using shared common layout helpers and cleaner bar/legend rendering - lib.rs: thin module facade re-exporting SvgGenerator and generate_diff_flamegraph - Cargo.toml: cleaned unused serde, serde_json, log dependencies - Expanded unit tests across common, flamegraph, and diff modules (13 tests total), clippy clean
… modules - Split monolithic files into decoder.rs, normalize.rs, aggregator.rs - decoder.rs: extract_target_address() with 20-byte formatting, extract_memory_selector() with single/cross-word boundary memory parsing - normalize.rs: Parser struct with normalize() and normalize_raw() - aggregator.rs: Aggregator decomposing call context decoding from stack aggregation - lib.rs: clean re-export facade - Cargo.toml: remove unused dependencies (serde, serde_json, anyhow) - Expanded unit tests across decoder, normalize, and aggregator (13 tests total), clippy clean
…odules - Split monolithic lib.rs into error.rs, types.rs, client.rs, etherscan.rs - error.rs: RpcError enum with Network, Json, Node variants, RpcResult alias - types.rs: RawStructLog (is_reverted, is_call helpers), TraceResult, internal RpcResponse envelope - client.rs: EthClient with debug_traceTransaction, eth_chainId, eth_getTransactionReceipt, and static selector_from_input() - etherscan.rs: EtherscanResolver with async background warming and thread-safe flush - Cargo.toml: clean unused anyhow dependency - Expanded unit tests across all modules (8 tests total), clippy clean
- Split monolithic lib.rs into registry.rs, profile.rs, and thin lib.rs facade - registry.rs: build_default_registry() pre-loading Uniswap v4, ERC-20, Aave v3 / GHO, Lido stETH - profile.rs: VmHint enum, detect_vm() heuristics, execute_profile() decomposed into clean handlers (fetch_starknet_stacks, fetch_solana_stacks, fetch_stellar_stacks, fetch_evm_nitro_stacks, render_and_save_flamegraph), get_network_name(), demo_stacks() - lib.rs: public module and re-export facade - Added comprehensive unit tests across registry and profile modules (5 tests total), clippy clean
- Split monolithic lib.rs into error.rs, client.rs, parser.rs, and thin lib.rs facade - error.rs: SolanaError enum with Network, Rpc, Parse, Timeout variants, SolanaResult alias - client.rs: SolanaClient with get_transaction_logs, SolanaTransactionResponse, SolanaMeta - parser.rs: SolanaLogStitcher with decomposed handle_invoke, handle_consumed, handle_return, OnceLock regex compilation - Cargo.toml: clean unused anyhow, log, tokio dependencies - Expanded unit tests across error, client, and parser modules (6 tests total), clippy clean
…ent modules - Split monolithic lib.rs into error.rs, types.rs, flattener.rs, client.rs, and thin lib.rs facade - error.rs: StarknetError enum with Network, Rpc, Serialization, Process variants, StarknetResult alias - types.rs: ExecutionResources (has_builtins helper), FunctionInvocation, StarknetTransactionTrace - flattener.rs: flatten_invocation, flatten_trace, explicit builtin gas-equivalent weights table (Pedersen, Range Check, Bitwise, Poseidon, EC OP, ECDSA) - client.rs: StarknetClient with starknet_traceTransaction querying and profile_transaction - Cargo.toml: clean unused anyhow, log, tokio dependencies - Expanded unit tests across all modules (6 tests total), clippy clean
…modules - Split monolithic lib.rs into error.rs, types.rs, parser.rs, client.rs, and thin lib.rs facade - error.rs: StellarError enum with Network, Rpc, Parse, Timeout variants, StellarResult alias - types.rs: SorobanDiagnosticEvent, StellarTransactionResponse data models - parser.rs: StellarTraceParser with estimate_host_fn_gas_cost, cost constants (put_contract_data, get_contract_data, crypto, invoke), depth tracking - client.rs: StellarClient with get_transaction_trace querying - Cargo.toml: clean unused anyhow, log, tokio dependencies - Expanded unit tests across all modules (7 tests total), clippy clean
…nner, and utils submodules
…ctor, and execution engine
…oization dependencies
…, Stellar, Aave v3, Lido, and Diff
…and dynamic trace units
…onical formatting
… sync rustfmt.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🏮 Summary of Changes (v0.2.0 Release)
This pull request upgrades Atupa into a Universal Multi-VM Execution Profiler & Visual Analysis Suite, delivering native support for EVM, Arbitrum Stylus (Dual-VM), Solana (SVM), Starknet (Cairo), and Stellar (Soroban), alongside deep protocol-specific decoders, embedded local Studio visualization, and CI gas regression gating.
🌐 Multi-VM Execution Adapters & Unified Clock Stitching
msg_sender,storage_load_bytes32,native_keccak256), with ranked HostIO Hot Paths analysis.get_contract_data,put_contract_data,compute_sha256) and state ledger updates.🔬 Protocol-Specific Deep Auditing
Pool.supply, ScaledBalance rebase indexing, real-time address label resolution, andGHOFlashMinterflash loan tracking.submit()->stETH::mintSharesrebase calculation -> Lido Oracle consensus reports -> Withdrawal Queue NFT minting).💻 Modular Rust CLI & Project Scaffolding
profile,capture,audit,diff,studio,init).atupa init: Auto-detects Foundry, Hardhat, and Stylus projects to scaffoldatupa.tomland automated GitHub Actions workflows in one click.atupa diff: Self-contained differential gas evaluator enforcing budget thresholds (--threshold) with automated markdown and SVG flamegraph generation.🏮 Atupa Studio (Embedded Local-First Web UI)
rust-embed.CU,steps,gas-equiv,gas) according to the detected VM runtime.🛡️ CI/CD & Testing
rustfmt.toml), linting (clippy), and unit tests.✅ Verification
cargo test --workspace: 100% passed (all unit, integration, and doctests)cargo clippy --workspace --all-targets: 0 warningscargo fmt --all -- --check: 100% clean