Part of the
Tollcraftinitiative.
soroban-cost-linter is a static analysis tool for Stellar smart contract developers. It analyzes your Rust code before compilation to detect input-independent, structurally expensive patterns that would unnecessarily drive up your Soroban resource metering and network fees.
This tool acts as the preventative shield in the Tollcraft two-tiered cost pipeline, pairing conceptually with our runtime test harness, soroban-budget-assert.
Soroban charges for CPU instructions, memory allocations, and storage operations. While testing your contract against the network is the only way to measure input-dependent costs (like unbounded loops or dynamic vector sizing), many expensive mistakes are structurally obvious without ever running the code.
Writing env.storage().instance().set() inside a for loop is mathematically guaranteed to be expensive. soroban-cost-linter catches these structural anti-patterns directly in your IDE or CI/CD pipeline before they make it to testnet.
The linter hooks into the Rust compiler's AST to catch specific Soroban anti-patterns. Three lints ship in v0.1.1:
soroban_storage_in_loop: Flags storage read/write operations placed inside loop bodies, suggesting memory aggregation instead.redundant_env_clone: Detects unnecessary.clone()calls on the SorobanEnvobject.unnecessary_host_function_call: Identifies redundant calls to host functions (like fetching the ledger sequence) that should be called once and bound to a local variable.
soroban-cost-linter is designed to be Stage 1 of your cost-awareness pipeline:
- Linter (
soroban-cost-linter): Runs at compile-time (or viacargo check). Catches obvious, static structural flaws. - Assert (
soroban-budget-assert): Runs at test-time. Simulates your cleanly-linted code against the network to measure actual execution costs based on real runtime inputs.
Both tools share configuration via a unified budget.toml file for thresholds and suppressions.
Since soroban-cost-linter hooks directly into Rust's AST, it relies on Dylint to run dynamic library lints. The linter library requires Dylint version ^6.0.1.
cargo install cargo-dylint dylint-link --version "^6.0.1"Add the linter to your Soroban workspace:
cargo install --git https://github.com/Tollcraft/soroban-cost-linter.git cargo-cost-lint
Run the linter across your entire workspace:
cargo cost-lint
To suppress a false positive or an intentionally expensive operation, standard Rust attributes are fully supported. Place this directly above the flagged function or block:
#[allow(soroban_storage_in_loop)]
fn deliberate_storage_loop(env: Env) {
for item in items {
// Deliberate storage loop
}
}You can define project-wide linting rules and severity levels in the same budget.toml file used by soroban-budget-assert. Place this in your workspace root:
[lints]
# Set to "warn", "deny", or "allow"
soroban_storage_in_loop = "deny"
redundant_env_clone = "warn"
unnecessary_host_function_call = "warn"
We are actively looking for contributors in cost-model research, AST parsing, and lint specification.
- Check the open issues to find tasks labeled
good first issueorhelp wanted. - Fork the repository.
- Ensure all Pull Requests target the
mainbranch. - Pass all local tests before submitting.
See CONTRIBUTING.md for more detailed guidelines.
Join the discussion on our Discord.
| Name | Role | Contact |
|---|---|---|
| mallison031 | Maintainer | GitHub |
| Tollcraft Team | Core Maintainers | Tollcraft on Telegram |