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
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
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
andDecrement
are public Realm (Smart Contract) methods, and as such are callable by users.Increment
andDecrement
directly modify thecount
value by making it go up or down (change state).- Calling the
Render
method would return thecount
value as a formatted string. Learn more about theRender
method and how it's used here.
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.