> For the complete documentation index, see [llms.txt](https://docs.stacks.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stacks.co/clarinet/validation-and-analysis.md).

# Validation and Analysis

<div data-with-frame="true"><figure><img src="https://284917788-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZz9BLmTU9oydDpL3qiUh%2Fuploads%2FsoO5zGe2Vo4YqFJk6lTj%2Fpath-to-production.png?alt=media&amp;token=e90535de-e536-457d-b9d9-e80e15944a89" alt=""><figcaption></figcaption></figure></div>

Clarinet provides tools for validating, analyzing, linting, and debugging your smart contracts. From static type checking to real-time cost analysis, you can check your contracts for errors and costs before deployment.

Contract validation spans static analysis, runtime debugging, and cost optimization.

## Understanding contract validation

**Static analysis vs. runtime debugging**

| Static analysis                         | 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 validation with `clarinet check`:

```bash
clarinet check
```

Successful output resembles:

```
✔ 3 contracts checked
```

When validation fails, Clarinet prints diagnostics:

```
✖ 1 error detected

Error in contracts/token.clar:15:10
  |
15|  (ok (+ balance amount))
  |         ^^^^^^^
  |
  = Type error: expected uint, found (response uint uint)
```

{% stepper %}
{% step %}
**Run basic checks**

Use `clarinet check` to validate your contracts and catch type/syntax errors before deployment.

```bash
clarinet check
```

{% endstep %}

{% step %}
**Check a specific contract**

Focus validation during development on a single contract file:

```bash
clarinet check contracts/nft.clar
```

{% endstep %}

{% step %}
**Integrate into CI**

Automate validation in continuous integration pipelines. Example GitHub Actions workflow:

```yaml
name: Contract Validation
on: [push, pull_request]

jobs:
  sanity-checks:
    runs-on: ubuntu-latest
    container: ghcr.io/stx-labs/clarinet:latest
    steps:
      - uses: actions/checkout@v4
      - name: Check Clarity contracts check
        run: clarinet check --use-on-disk-deployment-plan
      - name: Check Clarity contracts format
        run: clarinet fmt --check
```

{% endstep %}
{% endstepper %}

**Validation scope**

Clarinet validates multiple aspects of your contracts:

| Validation type          | What it checks                                     |
| ------------------------ | -------------------------------------------------- |
| **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       |

<details>

<summary><code>clarinet check --output=&#x3C;format></code></summary>

Add the `--output=<format>` option to `clarinet check` to print diagnostics as JSON or other formats. LLMs and other tools can parse this output. Currently supported formats are `standard`, `json`, and `jsonpretty`.

{% code title="" expandable="true" %}

```
> clarinet check --output=json

{
  "success": true,
  "diagnostics": {
    "/home/user/git/stx-labs/stacks-wormhole-ntt/.cache/requirements/SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-registry.clar": [
      {
        "level": "Warning",
        "message": "constant `ERR_INVALID_REQUEST_ID` never used",
        "spans": [
          {
            "start_line": 5,
            "start_column": 1,
            "end_line": 5,
            "end_column": 51
          }
        ],
        "suggestion": "Remove this expression"
      },
      {
        "level": "Warning",
        "message": "constant `governance-role` is not SCREAMING_SNAKE_CASE: IllegalCharacter(103)",
        "spans": [
          {
            "start_line": 9,
            "start_column": 1,
            "end_line": 9,
            "end_column": 38
          }
        ],
        "suggestion": "Remove the illegal character 'g'"
      }
    ]
  }
}
```

{% endcode %}

</details>

### Linter analysis

Clarinet includes a built-in linter as part of `clarinet check` that flags common mistakes, inefficiencies, and unused code in Clarity contracts.

Clarinet v3.24.1 has 23 lints in four groups: `unused` (dead code), `perf` (inefficient code), `safety` (code that might not do what you intended) and `style` (naming conventions). Each lint can be configured on its own or through its group.

| Identifier               | Description                                                                                                                                                                                          | Lint group |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `unused_binding`         | Detects unused function parameters and `let` bindings.                                                                                                                                               | `unused`   |
| `unused_const`           | Detects unused `define-constant` declarations.                                                                                                                                                       | `unused`   |
| `unused_data_var`        | Detects `define-data-var` declarations that are never used, never read, or never written (a value that is never written can be a constant).                                                          | `unused`   |
| `unused_map`             | Detects `define-map` declarations that are never accessed.                                                                                                                                           | `unused`   |
| `unused_private_fn`      | Detects private functions that are never called.                                                                                                                                                     | `unused`   |
| `unused_token`           | Detects fungible and non-fungible tokens that are never minted.                                                                                                                                      | `unused`   |
| `unused_trait`           | Detects traits imported with `use-trait` that are never used as parameter types.                                                                                                                     | `unused`   |
| `flatten_variadic`       | Suggests flattening nested calls to a variadic function, for example `(+ a (+ b c))` to `(+ a b c)`. From Clarity 6 this includes `concat`, which became variadic.                                   | `perf`     |
| `unnecessary_as_max_len` | Detects unnecessary `as-max-len?` calls.                                                                                                                                                             | `perf`     |
| `unnecessary_public`     | Detects public functions that could be read-only because they change no state.                                                                                                                       | `perf`     |
| `unnecessary_tuple`      | Detects tuples with a single field.                                                                                                                                                                  | `perf`     |
| `at_block`               | Warns about uses of `at-block`, which is proposed for removal.                                                                                                                                       | `safety`   |
| `error_const`            | Checks that every `ERR_` constant is an `(err ...)` value and that no two `ERR_` constants share a value.                                                                                            | `safety`   |
| `noop`                   | Detects expressions that have no effect, such as `(is-eq 1)`.                                                                                                                                        | `safety`   |
| `panic`                  | Warns about `unwrap-panic` and `unwrap-err-panic`.                                                                                                                                                   | `safety`   |
| `renamed_builtin`        | Detects calls to a builtin that a later Clarity version renamed. The one rename today is `with-stacking` to `with-staking` (Clarity 6); the old spelling keeps working in Clarity 4 and 5 contracts. | `safety`   |
| `case_binding`           | Enforces `kebab-case` on `let` bindings and function argument names.                                                                                                                                 | `style`    |
| `case_const`             | Enforces `SCREAMING_SNAKE_CASE` on constants.                                                                                                                                                        | `style`    |
| `case_data_var`          | Enforces `kebab-case` on data variables.                                                                                                                                                             | `style`    |
| `case_fn`                | Enforces `kebab-case` on function names.                                                                                                                                                             | `style`    |
| `case_map`               | Enforces `kebab-case` on maps.                                                                                                                                                                       | `style`    |
| `case_token`             | Enforces `kebab-case` on fungible and non-fungible token names.                                                                                                                                      | `style`    |
| `case_trait`             | Enforces `kebab-case` on trait names.                                                                                                                                                                | `style`    |

#### Bypassing the linter

Code can look unused when it is 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: the linter allows identifiers with a trailing `_` (a leading `_` does not work) to be unused, but other lints still apply to them.

Individual lints can also be disabled for a specific line using Clarity's annotation syntax:

```clarity
;; #[allow(lint_name_1, lint_name_2, ...)]
```

#### Configuration

By default, lints in the `unused`, `perf` and `safety` groups report at the `warning` level and `style` lints at the `notice` level. Change the level per lint or per group in `Clarinet.toml`.

**Individual lint configuration**

```toml
[repl.analysis.lints]
noop = true # Defaults to "warning"
unused_const = "warning"
unused_data_var = "error"
unused_map = false
```

**Lint group configuration**

```toml
[repl.analysis.lint_groups]
all = true      # Sets the default level to "warning" for all lints
style = "notice" # Cosmetic lints only generate notices
unused = "error" # Enforces removal of unused code
```

## Runtime analysis

The Clarinet console has commands for inspecting behavior during execution.

### Cost analysis with `::toggle_costs`

Turn on automatic cost display after every expression:

```clarity
::toggle_costs
;; Always show costs: true

(contract-call? .counter count-up)
;; +----------------------+----------+------------+------------+
;; |                      | Consumed | Limit      | Percentage |
;; |----------------------+----------+------------+------------|
;; | Runtime              | 4775     | 5000000000 | 0.00 %     |
;; | Read count           | 5        | 15000      | 0.03 %     |
;; | Read length (bytes)  | 268      | 100000000  | 0.00 %     |
;; | Write count          | 1        | 15000      | 0.01 %     |
;; | Write length (bytes) | 41       | 15000000   | 0.00 %     |
;; +----------------------+----------+------------+------------+
;; (ok true)
```

### Execution tracing with `::trace`

Trace function calls to understand execution flow:

```clarity
::trace (contract-call? .defi-pool swap u100 'token-a 'token-b)
;; (contract-call? .defi-pool swap u100 'token-a 'token-b) <console>
;; ( get-pool-balance 'token-a ) defi-pool:15:8
;;   ↳ args: 'token-a
;;     u50000
;; ( get-pool-balance 'token-b ) defi-pool:16:8
;;   ↳ args: 'token-b
;;     u75000
;; ( calculate-output u100 u50000 u75000 ) defi-pool:18:12
;;   ↳ args: u100, u50000, u75000
;;     u149
;; (ok u149)
```

### Interactive debugging with `::debug`

Set breakpoints and step through execution:

```clarity
::debug (contract-call? .complex-contract process-batch)
break validate-input
;; Breakpoint set at validate-input
continue
;; Hit breakpoint at validate-input:23
```

Common navigation commands:

{% hint style="info" %}

* `step` or `s`: step into subexpressions
* `finish` or `f`: complete the current expression
* `next` or `n`: step over subexpressions
* `continue` or `c`: resume execution
  {% endhint %}

### Using `::get_costs` for targeted analysis

```clarity
::get_costs (contract-call? .defi-pool add-liquidity u1000 u1000)
;; +----------------------+----------+------------+------------+
;; |                      | Consumed | Limit      | Percentage |
;; |----------------------+----------+------------+------------|
;; | Runtime              | 12250    | 5000000000 | 0.00 %     |
;; | Read count           | 6        | 15000      | 0.04 %     |
;; | Read length (bytes)  | 192      | 100000000  | 0.00 %     |
;; | Write count          | 3        | 15000      | 0.02 %     |
;; | Write length (bytes) | 96       | 15000000   | 0.00 %     |
;; +----------------------+----------+------------+------------+
;; (ok {lp-tokens: u1000})
```

### Spotting costly operations with `::trace`

```clarity
::trace (contract-call? .complex-algo process-large-dataset)
```

Review the trace for loops with high iteration counts, nested map/filter operations, repeated contract calls, and large data structure manipulations.

## Debugging workflows

Run `::debug` to pause execution and show the current source location:

```clarity
::debug (contract-call? .counter count-up)
;; ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.counter:9:3
;;   6
;;   7      ;; Increment the count for the caller
;;   8      (define-public (count-up)
;; ->9        (ok (map-set counters tx-sender (+ (get-count tx-sender) u1)))
;;             ^
;;  10     )
```

### Analyzing failed transactions with `::trace`

```clarity
::trace (contract-call? .marketplace purchase u999)
;; (contract-call? .marketplace purchase u999) <console>
;; ( get-listing u999 ) marketplace:45:12
;;   ↳ args: u999
;;     none
;; (err u404)  # Listing not found
```

### Using `::encode` and `::decode` for inspection

```clarity
::encode { id: u1, active: true }
;; 0c0000000206616374697665030269640100000000000000000000000000000001

::decode 0d0000000b48656c6c6f20776f726c64
;; "Hello world"
```

### Testing time-dependent logic

```clarity
::get_block_height
;; Current block height: 4

::advance_chain_tip 100
;; new burn height: 3
;; new stacks height: 104

(contract-call? .vesting claim)
;; (ok {claimed: u2500, remaining: u7500})
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.stacks.co/clarinet/validation-and-analysis.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
