Skip to main content

Hello, world

In the world of smart contracts, everything is a blockchain transaction. You use tokens in your wallet to deploy a smart contract in a transaction, and each call to that contract after it's published is also a transaction. Because block times can affect how quickly a function is executed and returned, it's advantageous to perform local development and testing of smart contracts with a simulated blockchain, so that functions execute immediately. This tutorial introduces you to local smart contract development with [Clarinet][], a development tool for building and testing Clarity smart contracts.

Clarity, the smart contract language used on the Stacks Blockchain, is a LISP-based language and uses its parenthesized notation. Clarity is an interpreted language, and decidable. To learn more basics about the language, see the Introduction to Clarity topic.

In this tutorial you will:

  • Create a new Clarinet project
  • Add a new Clarity contract to the project
  • Populate the contract with 2 types of functions
  • Execute the functions in a local, simulated blockchain
  • Optionally, deploy and test the contract on the testnet blockchain

Prerequisites

For this tutorial, you should have a local installation of Clarinet. Refer to [Installing Clarinet][] for instructions on how to set up your local environment. You should also have a text editor or IDE to edit the Clarity smart contract.

If you are using the online REPL, you can skip to step 3 of the tutorial and enter the code into the sandbox.

If you are using Visual Studio Code, you may want to install the [Clarity Visual Studio Code plugin][].

Optional prerequisites

While this tutorial primarily focuses on local smart contract development, you may wish to deploy your contract to a live blockchain. For simplicity, contract deployment is performed using the [testnet sandbox][]. If you wish to complete the optional deployment step, you should have the [Leather wallet][] installed, and you should request testnet STX tokens from the [testnet faucet][] on the testnet explorer. Note that requesting testnet STX from the faucet can take up to 15 minutes, so you may wish to request the tokens before beginning the tutorial.

Step 1: create a new project

With Clarinet installed locally, open a new terminal window and create a new Clarinet project with the command:

clarinet new clarity-hello-world && cd clarity-hello-world

This command creates a new directory for your smart contract project, populated with boilerplate configuration and testing files. Creating a new project only creates the Clarinet configuration, in the next step you can add a contract to the project.

Step 2: create a new contract

From the clarity-hello-world directory, create a new Clarity contract with the command:

clarinet contract new hello-world

This command adds a new hello-world.clar file in the contracts directory, and adds a hello-world_test.ts file to the test directory. This tutorial ignores the test file, but for production contracts, you can create [unit tests][] using it.

Step 3: add code to the hello-world contract

Open the contracts/hello-world.clar file in a text editor or IDE. Delete the boilerplate comments, for the purpose of this tutorial they're not necessary.

For this tutorial, you'll add two Clarity functions to the contract. Clarity functions are fully enclosed in parentheses, and whitespace doesn't matter.

The first function is a public function called say-hi.

(define-public (say-hi)
(ok "hello world"))

Public functions in Clarity are callable from other smart contracts, which enables you to break complex tasks into smaller, simpler smart contracts (an exercise in [separating concerns][]).

info

To create private functions, you would use the define-private keyword. Private functions can only be called from within the smart contract they're declared in. External contracts can only call public functions.

The function doesn't take any parameters and simply returns "hello world" using the [ok][] response constructor.

The second function is a [read-only function][] called echo-number.

(define-read-only (echo-number (val int))
(ok val))

Read-only functions are also public functions, but as the name implies, they can't change any variables or datamaps. echo-number takes an input parameter of type int and uses an [ok][] response to return the value passed to the function.

info

Clarity supports a variety of other types

The full contracts/hello-world.clar file should look like this:

(define-public (say-hi)
(ok "hello world"))

(define-read-only (echo-number (val int))
(ok val))

In the following steps you can interact with this contract in the local console. You can optionally deploy this contract to the testnet and interact with it on a live blockchain.

Step 4: interact with the contract in the Clarinet console

In the clarity-hello-world directory in your terminal, use the following command to verify that the syntax in your contract is correct:

clarinet check

If there are no errors, the command returns no output. If there are errors, verify that your contract is exactly as listed in the preceding section.

In the same directory, use the following command to launch the local console:

clarinet console

This console is a Clarinet read-eval-print loop (REPL) that executes Clarity code instantly when a function is called. When the Clarinet console is invoked, it provides a summary of the available contracts and the simulated wallets in memory:

clarity-repl v0.11.1
Enter "::help" for usage hints.
Connected to a transient in-memory database.
Contracts
+-------------------------------------------------------+-------------------------+
| Contract identifier | Public functions |
+-------------------------------------------------------+-------------------------+
| ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.hello-world | (echo-number (val int)) |
| | (say-hi) |
+-------------------------------------------------------+-------------------------+

Initialized balances
+------------------------------------------------------+---------+
| Address | STX |
+------------------------------------------------------+---------+
| ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE (deployer) | 1000000 |
+------------------------------------------------------+---------+
| ST1J4G6RR643BCG8G8SR6M2D9Z9KXT2NJDRK3FBTK (wallet_1) | 1000000 |
+------------------------------------------------------+---------+
| ST20ATRN26N9P05V2F1RHFRV24X8C8M3W54E427B2 (wallet_2) | 1000000 |
+------------------------------------------------------+---------+
| ST21HMSJATHZ888PD0S0SSTWP4J61TCRJYEVQ0STB (wallet_3) | 1000000 |
+------------------------------------------------------+---------+
| ST2QXSK64YQX3CQPC530K79XWQ98XFAM9W3XKEH3N (wallet_4) | 1000000 |
+------------------------------------------------------+---------+
| ST3DG3R65C9TTEEW5BC5XTSY0M1JM7NBE7GVWKTVJ (wallet_5) | 1000000 |
+------------------------------------------------------+---------+
| ST3R3B1WVY7RK5D3SV5YTH01XSX1S4NN5B3QK2X0W (wallet_6) | 1000000 |
+------------------------------------------------------+---------+
| ST3ZG8F9X4VKVTVQB2APF4NEYEE1HQHC2EDBF09JN (wallet_7) | 1000000 |
+------------------------------------------------------+---------+
| STEB8ZW46YZJ40E3P7A287RBJFWPHYNQ2AB5ECT8 (wallet_8) | 1000000 |
+------------------------------------------------------+---------+
| STFCVYY1RJDNJHST7RRTPACYHVJQDJ7R1DWTQHQA (wallet_9) | 1000000 |
+------------------------------------------------------+---------+

The console provides the ability to interact with your contract using Clarity commands. Call the say-hi function with the following command:

(contract-call? .hello-world say-hi)

The console immediately returns (ok "hello world"), the expected return value of the function.

Next, call the echo-number function:

(contract-call? .hello-world echo-number 42)

The console immediately returns (ok 42), the expected return value of the function with the parameters you called it with.

Try calling the echo-number function with an incorrect type, in this case an unsigned integer:

(contract-call? .hello-world echo-number u42)

The console should return Analysis error: expecting expression of type 'int', found 'uint', indicating that the call to the contract was invalid due to the incorrect type.

You have now learned the basics of Clarity and working with the Clarinet development tool. You may wish to optionally deploy the contract to the testnet, described in the next and final step.

Optional: deploy and test the contract on the testnet

For this tutorial, you'll use the [testnet sandbox][] to deploy your smart contract. Make sure you have connected your [Leather wallet][] to the sandbox using the Connect wallet button, then copy and paste your smart contract into the Clarity code editor on the Write & Deploy page. Edit the contract name or use the randomly generated name provided to you.

Hello world testnet sandbox

Click Deploy to deploy the contract to the blockchain. This will display the Leather wallet window with information about the transaction. Verify that the transaction looks correct, and the network is set to Testnet, and click Confirm.

The contract is added to the miners mempool, and included in the next block of the blockchain. This process can take up to 15 minutes to complete. You can review it on the [transactions][] page of the explorer or in the activity field of your web wallet.

When your contract is confirmed, navigate to the [call a contract][] page of the sandbox, and search for your contract. Enter your wallet address in the top field, you can copy this address by clicking the Leather wallet icon and clicking the Copy address button. Enter the contract name in the bottom field, in this case hello-world. Click Get Contract to view the contract.

Hello world sandbox contract

Click the say-hi function in the function summary, then click Call Function to perform the function call in the sandbox. This will display the Leather wallet with information about the transaction. Verify the information, then click Confirm to execute the function call.

The function call is added to the miners mempool, and is executed in the next block of the blockchain. This process can take up to 15 minutes to complete. You can review it on the [transactions][] page of the explorer or in the activity field of your web wallet.

When the transaction is complete, you can access the transaction summary page from the activity panel in your web wallet. The transaction summary page displays the output of the function:

Hello world transaction summary

You have now learned one method of deploying and interacting with smart contracts on Stacks. You have also learned the strengths of performing local development without having to wait for block times.