Debug a contract

Step through and debug your contracts inside the command line.

Let's take a simple counter contract and walk through how we can leverage all the debugging commands.

(define-map Counters principal uint)

(define-read-only (get-count (who principal))
  (default-to u0 (map-get? Counters who))
)

(define-public (count-up)
  (ok (map-set Counters tx-sender (+ (get-count tx-sender) u1)))
)

To initiate a debug session, first run the clarinet console command inside your project.

Terminal
clarinet console

Trace

The ::trace command expects an expression, so let's make a contract-call? with our count-up function and see what happens.

Terminal
::trace (contract-call? .counter count-up)

We should see a complete trace of our get-count function call, outputting the arguments that were passed in (tx-sender) and return value (u0).

Example response:

(contract-call? .counter count-up)  <console>
├── ( get-count tx-sender )  counter:8:38
 args: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM
 u0
 (ok true)

If we were to run this again, we should see the return value go from u0 to u1.

Breakpoints

You also might want to set a breakpoint at a specific line to better understand what's happening in your contract.

With ::debug, we can add breakpoints at a specific line of a contract or function to better understand what's happening in our contracts.

Let's add a couple new functions to illustrate:

;; Existing contract code...

(define-public (count-twice)
  (double)
)

(define-private (double)
  (begin
    (unwrap-panic (count-up))
    (count-up)
  )
)

To see this in action, let's add a break on our count-up function when calling our new double function.

Terminal
::debug (contract-call? .counter count-twice)
break count-up
Breakpoint Commands

To step through these breakpoints, we can use one of the following commands:

  • Step-in (step or s): Step into the sub-expressions.
  • Step-out (finish or f): Complete execution of the current expression and return the result to the parent.
  • Step-over (next or n): Continue to completion of the current expression, stepping over sub-expressions.
  • Continue (continue or c): Continue execution until hitting a breakpoint or completing execution.

Using the continue command, our breakpoint in our double function triggers twice due to two count-up calls, enabling variable and map analysis.

Last updated on