Quickstart

Build your first Clarity smart contract in under 5 minutes


What you'll learn

In this guide, you'll build a simple counter smart contract and interact with it in a local environment. By the end, you'll understand:

How to create and structure a Clarity smart contract project
The basics of writing Clarity code with maps and public functions
How to validate and test your contracts using Clarinet's console

Prerequisites

To follow this guide, you'll need:

Clarinet installed on your machine. Follow the installation guide if needed.
A code editor like VS Code for editing Clarity files.

Create your project

Let's start by creating a new Clarinet project. The clarinet new command sets up everything you need for smart contract development, including a testing framework, deployment configurations, and a local development environment:

Terminal
$
clarinet new counter
Create directory counter
Create directory contracts
Create directory settings
Create directory tests
Create file Clarinet.toml
Create file package.json
Create file vitest.config.js

Clarinet creates a complete project structure for you. Each folder serves a specific purpose in your development workflow:

Clarinet.toml
package.json
vitest.config.js

Generate your contract

Now that we have our project structure, let's create a smart contract. Navigate into your project directory and use Clarinet's contract generator:

Terminal
$
cd counter
$
clarinet contract new counter
Created file contracts/counter.clar
Created file tests/counter.test.ts
Updated Clarinet.toml with contract counter

Clarinet automatically creates both your contract file and a corresponding test file. This follows the best practice of writing tests alongside your contract code:

FilePurpose
contracts/counter.clarYour smart contract code
tests/counter.test.tsTest file for your contract

Notice that Clarinet also updated your Clarinet.toml file. This configuration file tracks all contracts in your project and their deployment settings.

Write your contract code

Time to write our smart contract! Open contracts/counter.clar and replace its contents with our counter implementation. This contract will maintain a separate count for each user who interacts with it:

contracts/counter.clar
;; Define a map to store counts for each user
(define-map Counters principal uint)
;; Increment the count for the caller
(define-public (count-up)
(ok (map-set Counters tx-sender (+ (get-count tx-sender) u1)))
)
;; Get the current count for a user
(define-read-only (get-count (who principal))
(default-to u0 (map-get? Counters who))
)

Let's understand what each part does:

  • define-map creates a persistent storage map that associates each user (principal) with their count
  • tx-sender is a built-in variable that contains the address of whoever calls the function
  • define-public declares functions that can modify contract state
  • define-read-only declares functions that only read data without modifying it

Validate your contract

Before we can test our contract, let's make sure it's syntactically correct and type-safe. Clarinet's check command analyzes your contract without deploying it:

Terminal
$
clarinet check
1 contract checked

If you see errors instead, here are the most common issues and how to fix them:

ErrorFix
Unknown keywordCheck spelling of Clarity functions
Type mismatchEnsure you're using correct types (uint, principal, etc.)
Unresolved contractVerify contract name matches filename

Test in the console

Now for the exciting part—let's interact with our contract! Clarinet provides an interactive console where you can call functions and see results immediately. Start the console with:

Terminal
$
clarinet console

Once the console loads, you can call your contract functions directly. Here are a few examples you can try:

Terminal
$
(contract-call? .counter count-up)
(ok true)
$
(contract-call? .counter get-count tx-sender)
u1
$
(contract-call? .counter count-up)
(ok true)
$
(contract-call? .counter get-count tx-sender)
u2

Next steps