VM Tooling & Test Harness
Overview
Section titled “Overview”Ashen ships two developer-friendly tools for smart contract work:
vm-tooling: a CLI for ELF validation, disassembly, traces, gas profiling, and code cache introspection.vm-test-harness: a Rust crate that runs Zig/Rust contracts in-memory without a full node.
This guide covers both, with practical examples.
vm-tooling CLI
Section titled “vm-tooling CLI”Run from the repo root:
cargo run -p vm-tooling -- --helpCommon commands
Section titled “Common commands”| Command | Purpose |
|---|---|
deploy-manifest | Emit a v1 deploy manifest |
elf-validate | Validate a contract ELF against the VM rules |
disasm | Disassemble a contract ELF |
trace | Execute and trace a contract call |
gas | Print the active gas schedule |
cache-stats | Show code cache stats and promotion thresholds |
predecode | Predecode ELF for JIT/AOT tiers |
gas-profile | Profile per-basic-block gas usage |
gas-budget-check | Check gas profiles against .gas-budgets.toml |
corpus-freeze | Generate a conformance corpus |
corpus-run | Execute a corpus against a tier |
Validate a contract ELF
Section titled “Validate a contract ELF”cargo run -p vm-tooling -- elf-validate --elf ./contracts/my_token/zig-out/bin/my_tokenDisassemble a contract
Section titled “Disassemble a contract”cargo run -p vm-tooling -- disasm --file ./contracts/my_token/zig-out/bin/my_tokenTrace a contract call
Section titled “Trace a contract call”cargo run -p vm-tooling -- trace \ --file ./contracts/my_token/zig-out/bin/my_token \ --calldata-hex 0x50494e47 \ --gas 1000000 \ --out ./trace.json--calldata-hex expects ABI v1 bytes: selector || borsh(args).
Gas profiling and budgets
Section titled “Gas profiling and budgets”cargo run -p vm-tooling -- gas-profile \ --file ./contracts/my_token/zig-out/bin/my_token \ --trace-out ./gas-trace.jsoncargo run -p vm-tooling -- gas-budget-check --config ./.gas-budgets.tomlConformance corpus
Section titled “Conformance corpus”cargo run -p vm-tooling -- corpus-freeze --out ./corpus --cases 100cargo run -p vm-tooling -- corpus-run --dir ./corpus --tier interpreterValid tiers: interpreter, jit, aot (and native when the
cranelift-native feature is enabled).
vm-test-harness
Section titled “vm-test-harness”vm-test-harness is a Rust crate for running contracts in-memory with a
deterministic host. It is ideal for unit tests and fast iteration.
Key components:
TestHost: in-memory storage, logs, balances, and block contextContractHarness: loads and executes contract ELFs- Fixtures & assertions: storage helpers, event checks, snapshots
Minimal example
Section titled “Minimal example”use vm_test_harness::{ContractHarness, TestHost};use vm_test_harness::{assert_call_ok, build_calldata_no_args};
let mut host = TestHost::new();let harness = ContractHarness::from_zig_artifact("contracts/my_token/zig-out/bin/my_token") .expect("artifact exists") .expect("load contract");
let calldata = build_calldata_no_args(*b"PING");let result = harness.call(&mut host, b"origin", b"my_token", &calldata, 1_000_000);
assert_call_ok(&result, "PING should succeed");Helpful patterns
Section titled “Helpful patterns”- Use
ContractHarness::from_zig_artifact_or_skipin CI to skip gracefully when the ELF is missing. - Use
StorageFixturehelpers to seed storage and verify state changes. - Use
TestHost::snapshot()/restore_snapshot()for complex flows.
For a more complete walkthrough, see /guides/contract-testing/.
Related
Section titled “Related”/reference/rpc-api/for node-side RPC call types/guides/contract-testing/for harness patterns and fixtures