Primary entry point for any AI agent working in this codebase. Also read CONTRIBUTING.md for general contribution guidelines.
Gno (Gnolang) is a deterministic, interpreted variant of Go for writing smart contracts. gno.land is the L1 blockchain that runs Gno code.
| Pillar | Directory | What it does |
|---|---|---|
| GnoVM | gnovm/ |
Interpreter/VM, parser, type-checker |
| gno.land | gno.land/ |
Blockchain node, ABCI app, SDK, CLI tools |
| Tendermint2 | tm2/ |
Consensus, p2p, mempool, crypto, RPC |
Other directories: examples/ (sample realms/packages), contribs/ (tools: gnodev, gnofaucet, etc.), misc/, docs/, .github/.
.gnolooks like Go but runs in a deterministic VM.- No goroutines, channels,
unsafe,net,os. - Realms (
r/) are stateful (on-chain state). - Packages (
p/) are stateless libraries. - Import paths:
gno.land/p/...orgno.land/r/...— nevergithub.com/.... - Module config:
gnomod.toml(notgo.mod). cross(rlm)form for cross-realm calls.realmtype for realm-aware functions.
make install # Install gnokey, gno, gnodev
make test # Run all tests (slow)
make lint # golangci-lint
make fmt # Format all code| Gno tests | Go tests |
|---|---|
gno test ./path/... |
go test ./... |
Test files: _test.gno |
Test files: _test.go |
Filetests: _filetest.gno |
Integration: .txtar in gno.land/pkg/integration/testdata/ |
VM file tests: gnovm/tests/files/ with // Output: |
Standard Go test runner |
- After changing gas constants or allocation/GC logic, always run these before declaring done:
go test ./gno.land/pkg/sdk/vm/ -run Gasgo test ./gno.land/pkg/integration/ -run TestTestdatago test ./gnovm/pkg/gnolang/ -run Files -test.short
- Always run
/simplifybefore presenting completed work on non-trivial changes. - When comparing gas numbers or performance metrics before vs after, always verify the test logic has not changed, including loop counts and input sizes. Show reasoning, not just numbers.
- Never claim a percentage improvement without confirming the test is doing the same work in both cases.
- Format:
gno fmt. - Import paths:
gno.land/{p,r}/...only. - No OS/network access.
- Before writing Gno code, read the relevant docs in
docs/resources/:gno-interrealm.md— cross-realm calls,cross(rlm)/realmsemanticseffective-gno.md— idiomatic Gno patternsgo-gno-compatibility.md— what works and what doesn't vs Gogno-testing.md— testing patterns for.gnofilesgno-packages.md— package structure and conventions
- Format:
gofmt/goimports. - Lint:
golangci-lint(.github/golangci.yml).
- Commits: conventional (
feat:,fix:,docs:,chore:,test:,refactor:) with optional scope (feat(gnovm):). - Branches: kebab-case (
fix-vm-params), always feature branches. - If posting comments or reviews under your owner's GitHub account fully autonomously (no human reviewing the output before it is posted), disclose that you are an AI agent (e.g., prefix with
[bot]or add a "generated by" note) so humans can distinguish agent activity from the account owner. Human-assisted contributions that the account owner reviews and approves before posting do not need this disclosure. - Don't credit the agent as a commit author (
Co-Authored-By,Assisted-By, "Generated by"); the human author owns the commit. Note AI usage in the PR description if relevant. - When writing PR descriptions, grep for all new/modified files in the diff (
git diff --stat) and categorize them. Do not omit major new files like benchmarks, tooling, or calibration scripts. - List all categories of work in PR descriptions, including features, bug fixes, tooling, and tests, not just the headline feature.
- Keep PRs up to date with
master— merge regularly and resolve conflicts promptly. - When merging
masterinto your branch, review incoming changes carefully. IfCONTRIBUTING.mdorAGENTS.mdwas updated, re-read and follow the latest rules. - Be respectful and helpful in PR comments and reviews — optimize for the reviewer's time, especially human maintainers.
- See CONTRIBUTING.md.
- Before writing or reviewing any caller-authentication, access-control, or cross-realm code in Gno (
/r/,/p/,/e/packages), readdocs/resources/gno-interrealm.md. Do not pattern-match from Soliditymsg.senderor other-language intuition. - For the complete AI-focused checklist (10 cases), read
docs/resources/gno-ai-contract-review.mdbefore reviewing any realm. runtime.PreviousRealm()only shifts on explicit cross-calls (fn(cross, ...)) into crossing functions (func fn(cur realm, ...){...}). APreviousRealm().PkgPath() == "..."check inside a non-crossing function does not identify the immediate caller and is a security bug.- In crossing functions (
func F(cur realm, ...)), always usecur.IsCurrent()before callingcur.Previous(). Never usechain/runtime/unsafe.PreviousRealm()in a crossing function — it bypasses the frame verification thatcur.IsCurrent()provides. Any import ofchain/runtime/unsafealongsidecur realmparameters is a red flag. - When editing a realm that accepts payment via
banker.OriginSend(), the caller guard must becur.Previous().IsUserCall(), notIsUser().IsUser()acceptsmaketx runephemeral realms, which can consume the origin-send envelope before calling your function and bypass the payment check. See docs/resources/effective-gno.md § Verifying inbound Coin payments. - When you see an existing realm using
IsUser()plusbanker.OriginSend(), flag it and cross-check nearbyOriginSendusage. - Never return a pointer to a
/p/-type instance stored in realm state if that type has any exported mutation method (e.g.avl.Tree.Set,avl.Tree.Remove). Readonly taint does not block method dispatch — borrow rule #2 fires and the write commits under your realm's authority. Return values or narrow read-only views instead. Render(path string)receives attacker-controlled input. Never write path segments, user-supplied keys, or free-form string values directly into markdown output. Usesanitize.InlineTextfromgno.land/p/nt/markdown/sanitize/v0for inline content.
Every non-trivial AI-assisted PR must include an ADR. This documents what the AI understood so reviewers can verify assumptions and future contributors can build on it.
| Scope | Directory |
|---|---|
| GnoVM | gnovm/adr/ |
| gno.land | gno.land/adr/ |
| Tendermint2 | tm2/adr/ |
Naming: pr<number>_<description>.md.
Use prxxxx_ if PR number unknown.
Include: context, decision, alternatives considered, consequences.
See gnovm/adr/ for examples.
Match detail to complexity.
Skip ADRs for: trivial bug fixes, formatting, simple tests, docs-only changes.
git push --force— never force push unless explicitly asked.--no-verify— never skip hooks.go generate— slow, large diffs. Only if explicitly asked.- Modify
gno.land/genesis/— only if that's the task. - Goroutines/OS calls in
.gno— never works. - Break
gno.land/p/demo/backwards-compat — needs discussion. - AI-assisted PRs without an ADR.
| What | Where |
|---|---|
| Understand a realm | Read its main .gno file |
| VM internals | gnovm/pkg/gnolang/machine.go, gnovm/pkg/gnolang/preprocess.go |
| Node/keeper | gno.land/pkg/sdk/vm/keeper.go |
| Client/RPC | gno.land/pkg/gnoclient/ |
| Example patterns | examples/gno.land/p/nt/ownable/ |
| Past decisions | gnovm/adr/, gno.land/adr/ and tm2/adr/ |
- Realm — stateful smart contract (
.gno, underr/) - Package — stateless library (under
p/) - GnoVM — the interpreter
- gno.land — the blockchain
- Gnolang — the language
- ADR — architecture decision record
- ABCI — app-to-consensus interface
- GovDAO — governance DAO
- gnokey — key/tx CLI
- gnoland — node binary
- gnodev — local dev with hot reload
This file should stay concise, correct, and useful. Both humans and agents should help maintain it.
Humans: if you spot something wrong or missing, fix it directly — small PRs welcome. If an agent got confused by something, add a clarification here so the next one doesn't.
Agents: if you hit something misleading or missing in this doc during your work, flag it to the human and suggest a concrete edit. Include the fix in your PR when practical — future agents will benefit. If your human corrects you on something that this doc could have prevented, propose adding it.
The goal is a living document that gets sharper with each use.