Validation and Analysis

Clarinet provides powerful tools for validating, analyzing, linting, and debugging your smart contracts. From static type checking to real-time cost analysis, you can ensure your contracts are correct and efficient before deployment.
Contract validation spans static analysis, runtime debugging, and cost optimization. Each discipline helps you gain confidence in contract behavior.
Understanding contract validation
Static analysis vs. runtime debugging
Catches issues before deployment
Reveals behavior during execution
Flags type mismatches and syntax errors
Shows actual execution costs
Ensures trait compliance
Exposes state changes and side effects
Detects undefined variables
Highlights transaction flow
Validates function signatures
Surfaces performance bottlenecks
Static analysis
Run comprehensive validation with clarinet check:
Successful output resembles:
When validation fails, Clarinet provides detailed diagnostics:
Run basic checks
Use clarinet check to validate your contracts and catch type/syntax errors before deployment.
Check a specific contract
Focus validation during development on a single contract file:
Integrate into CI
Automate validation in continuous integration pipelines. Example GitHub Actions workflow:
Validation scope
Clarinet validates multiple aspects of your contracts:
Type safety
Function parameters, return values, variable types
Trait compliance
Implementation matches trait definitions
Response consistency
ok/err branches return the same types
Variable scope
Variables defined before use
Function visibility
Proper use of public, private, and read-only
Linter analysis
Clarinet includes a built-in linter as part of clarinet check to help identify common mistakes, inefficiencies, and unused code in Clarity contracts. Linters play an important role in improving code quality by surfacing issues early in development and encouraging clearer, more maintainable contracts.
Clarinet currently provides a set of lints focused on dead code analysis. These lints detect declarations and expressions that have no effect on contract execution and can be configured individually.
The following lints are available:
Identifier
Description
unused_const
Detects unused define-constant declarations.
unused_data_var
Detects define-data-var declarations that are never written.
unused_map
Detects define-map declarations that are never accessed.
unused_private_fn
Detects private functions that are never called.
unused_token
Detects fungible and non-fungible tokens that are never minted.
unused_trait
Detects traits imported with use-trait that are never used as parameter types.
unused_binding
Detects unused function parameters and let bindings.
In addition, the noop lint detects expressions that have no effect, such as: (is-eq 1)
Bypassing the Linter
In some cases, code may appear unused but may be used in a way the linter can't see. Examples include private functions used only in tests, or bindings whose evaluation has side effects.
Clarinet follows a convention similar to Rust: identifiers with a trailing _ might generate other kinds of warnings for them but the linter will allow them to be unused.
Note: prefixing identifiers with _ is not currently supported, only suffixing is.
Individual lints can also be disabled for a specific line using Clarity’s annotation syntax:
Configuration
All non-style/non-cosmetic lints are enabled by default at the warning level and can be customized in Clarinet.toml.
Individual lint configuration
Lint group configuration
Runtime analysis
The Clarinet console offers runtime tools that help you inspect behavior during execution.
Cost analysis with ::toggle_costs
::toggle_costsEnable automatic cost display after every expression:
Execution tracing with ::trace
::traceTrace function calls to understand execution flow:
Interactive debugging with ::debug
::debugSet breakpoints and step through execution:
Common navigation commands:
stepors– step into subexpressionsfinishorf– complete the current expressionnextorn– step over subexpressionscontinueorc– resume execution
Using ::get_costs for targeted analysis
::get_costs for targeted analysisSpotting costly operations with ::trace
::traceReview the trace for loops with high iteration counts, nested map/filter operations, repeated contract calls, and large data structure manipulations.
Debugging workflows
Master interactive debugging to identify issues quickly:
Analyzing failed transactions with ::trace
::traceUsing ::encode and ::decode for inspection
::encode and ::decode for inspectionTesting time-dependent logic
Last updated
Was this helpful?