Implementing a voting system
A beginner's friendly series of articles in which you'll learn to code a Clarity Smart Contract. The goal is to develop an on-chain voting system.
Write your first Clarity Smart Contract
What are Smart Contracts?
Smart Contracts can be seen as the back-end code of our application. They are used to handle some logic and store on-chain data. "On-chain" means that the data will be stored on the Stacks Blockchain. It will act as a Database.
In this series of article, we'll develop a voting system in which the participants will vote for their favorite colors. There will be 4 choices of colors. In order to vote, the voters will rate each color from 0 (bad) to 5 (excellent). The winning color is the one with the best average grade.
👉 This voting mechanism is known as the majority judgment. It has multiple benefits. The main advantage here is to allow to define a single winner in one round of votes.
Create the project
$ clarinet new color-vote $ cd color-vote $ clarinet contract new color-vote $ code . # optional, open the project in VS Code
Open the file "contracts/color-vote.clar". It might contains some boilerplate comments. You may remove those.
Save the number of voters
In order to compute the average grade of each color, we'll have to know the total number of voters.
We will define a top level variable to store this value. While we're at it, add a read-only function to expose
(define-data-var nb-of-voters uint u0) (define-read-only (get-nb-of-voters) (var-get nb-of-voters))
nb-of-voters is an "unsigned integer": a positive integer. It's initialized at 0 and written
u means... "unsigned".
At this point, you can run
$ clarinet console in your terminal. It will open the clarity REPL and load the contract in it. It works because our contract is declared in the
Clarinet.toml file at the root of our project.
clarinet contract new did that for us.
To test our contract, run the following command in the REPL:
(contract-call? .color-vote get-nb-of-voters)
It should print
u0, the value of the
Define a public "vote" function that will simply increment the number of voters every time it's called. Add it at the end of the file.
(define-public (vote) (begin ;; the vote logic will be added later (ok (var-set nb-of-voters (+ (var-get nb-of-voters) u1))) ) )
👉 You may have noted that the function
get-nb-of-voters was defined with
vote was defined with
Both read-only and public are actually publics. The difference is that read-only function won't write data on the blockchain. It's super important because when a public function is called, the person doing it will have to pay some fees to run it. Whereas read-only functions are free to run.
👉 Unlike read-only functions, public functions must return a response type (an
error response). That's why we wrap the response in
👉 We used
(begin ...) inside our the function. It's actually optional here but it's needed to wrap multiple instructions in a function. It will be the case later in our
Let's put our code to the test. In your terminal, kill the REPL if it's still running (with
ctrl + c or
cmd + c). Launch it again with
clarinet console, it will load the updated contract. Run the following commands one by one:
(contract-call? .color-vote get-nb-of-voters) (contract-call? .color-vote vote) (contract-call? .color-vote get-nb-of-voters)
The commands should respectively print
(ok true) and
u1. It means that our contract is running as expected. Currently
vote can be called many times and it'll keep incrementing the value
This first article is quite short; we are just getting started. We still learned quite a few things;
- How to use
clarinetto bootstrap our contract and test it with the console,
- The difference between
- How to define, get and set variables.
In the next article, we'll see how to authorize only one vote per user.
At the end of this article, your code should look like that
(define-data-var nb-of-voters uint u0) (define-public (vote) (begin (ok (var-set nb-of-voters (+ (var-get nb-of-voters) u1))) ) ) (define-read-only (get-nb-of-voters) (var-get nb-of-voters))