Skip to main content

How to write a simple Gno Smart Contract (Realm)

Overview

This guide shows you how to write a simple Counter Smart Contract, or rather a Realm, in Gno (Gnolang). For actually deploying the Realm, please see the deployment guide.

Our Counter Realm will have the following functionality:

  • Keeping track of the current count.
  • Incrementing / decrementing the count.
  • Fetching the current count value.

Prerequisites

  • Text editor
Editor support

The Gno language is based on Go, but it does not have all the bells and whistles in major text editors like Go. Advanced language features like IntelliSense are still in the works.

Currently, we officially have language support for ViM, Emacs and Visual Studio Code.

1. Setting up the work directory

Gno Realms can be typically written anywhere, under any structure, just like regular Go code. However, Gno developers have adopted a standard of organizing Gno logic under a specific directory hierarchy, which we will explore here.

Create the main working directory for our Realm:

mkdir counter-app

Since we are building a simple Counter Realm, inside our created counter-app directory, we can create another directory named r, which stands for realm:

cd counter-app
mkdir r

Alternatively, if we were writing a Gno Package, we would denote this directory name as p (for package). You can learn more about Packages in our Package development guide.

Additionally, we will create another sub-folder that will house our Realm code, named counter:

cd r
mkdir counter

After setting up our work directory structure, we should have something like this:

counter-app/
├─ r/
│ ├─ counter/
│ │ ├─ // source code here

2. Create counter.gno

Now that the work directory structure is set up, we can go into the counter sub-folder, and actually create our Counter Smart Contract:

cd counter
touch counter.gno
Gno file extension

All Gno (Gnolang) source code has the file extension .gno.

This file extension is required for existing gno tools and processes to work.

We can finally write out the logic of the Counter Smart Contract in counter.gno:

package counter

import (
"gno.land/p/demo/ufmt"
)

var count int

func Increment() {
count++
}

func Decrement() {
count--
}

func Render(_ string) string {
return ufmt.Sprintf("Count: %d", count)
}

There are a few things happening here, so let's dissect them:

  • We defined the logic of our Realm into a package called counter.
  • The package-level count variable stores the active count for the Realm (it is stateful).
  • Increment and Decrement are public Realm (Smart Contract) methods, and as such are callable by users.
  • Increment and Decrement directly modify the count value by making it go up or down (change state).
  • Calling the Render method would return the count value as a formatted string. Learn more about the Render method and how it's used here.
A note on constructors

Gno Realms support a concept taken from other programming languages - constructors.

For example, to initialize the count variable with custom logic, we can specify that logic within an init method, that is run only once on Realm deployment:

package counter

var count int

// ...

func init() {
count = 2 * 10 // arbitrary value
}

// ...

Conclusion

That's it 🎉

You have successfully built a simple Counter Realm that is ready to be deployed on the Gno chain and called by users. In the upcoming guides, we will see how we can develop more complex Realm logic and have them interact with outside tools like a wallet application.