Realms and Packages
Gno.land Realms are Packages of Gno code that are identified by their "package paths" and are also "addressable" into an Address which has prefix "g1...".
A Realm is created when a Gno code Package is added to "gno.land/r/...", and the state of realm packages are mutated by signed function call messages from users calling exposed functions of realms. Realm functions can in turn call other functions creating a call stack beginning at origin with a user Account.
A "P" Package is created when a Package is added to "gno.land/p/...". "P" Packages are immutable and cannot be modified by any message after creation.
Realm and "P" Packages have an Account and Address derived from its package path. Users too have an Account and Address determined cryptographically from a BIP39 mnemonic phrase or secret.
Realms and users can both send and receive Coins using the Banker module by Address.
Realms are represented by a Realm
type in Gno:
type Realm struct {
addr Address // Gno address in the bech32 format
pkgPath string // realm's path on-chain
}
The full Realm API can be found under the reference section.
Smart Contract Realms
Often simply called realms
, Gno smart contracts contain Gno code and exist
on-chain at a specific package path. A package path is the
defining identifier of a realm, while its address is derived from it.
As opposed to pure packages, realms are stateful, meaning they keep their state between transaction calls. In practice, global variables used in realms are automatically persisted after a transaction has been executed. Thanks to this, Gno developers do not need to bother with the intricacies of state management and persistence, like they do with other languages.
Externally Owned Accounts (EOAs)
EOAs, or simply user realms
, are Gno addresses generated from a BIP39 mnemonic
phrase in a key management application, such as
gnokey, and web wallets, such as
Adena.
Currently, EOAs are the only realms that can initiate a transaction. They can do this by calling any of the possible messages in gno.land, which can be found here.
Working with Realms
Every Gno transaction produce a call stack that can switch across functions
declared in realm packages and functions declared in p packages. The std
package contains functions that return the current realm, previous realm, and
the origin caller's address.
std.GetOrigCaller()
- returns the address of the original signer of the transactionstd.PreviousRealm()
- returns the previous realm instance, which can be a user realm or a smart contract realmstd.CurrentRealm()
- returns the instance of the realm that has called it
Let's look at the return values of these functions in two distinct situations:
- EOA calling a realm
- EOA calling a sequence of realms
1. EOA calling a realm
When an EOA calls a realm, the call stack is initiated by the EOA, and the realm becomes the current context.
Take these two actors in the call stack:
EOA:
addr: `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5`
pkgPath: "" // empty as this is a user realm
Realm A:
addr: `g17m4ga9t9dxn8uf06p3cahdavzfexe33ecg8v2s`
pkgPath: `gno.land/r/demo/users`
┌─────────────────────┐ ┌─────────────────────────┐
│ EOA │ │ Realm A │
│ │ │ │
│ addr: │ │ addr: │
│ g1jg...sqf5 ├──────► g17m...8v2s │
│ │ │ │
│ pkgPath: │ │ pkgPath: │
│ "" │ │ gno.land/r/demo/users │
└─────────────────────┘ └─────────────────────────┘
Let's look at return values for each of the methods, called from within
Realm A
:
std.OriginCaller() => `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5`
std.PreviousRealm() => Realm {
addr: `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5`
pkgPath: ``
}
std.CurrentRealm() => Realm {
addr: `g17m4ga9t9dxn8uf06p3cahdavzfexe33ecg8v2s`
pkgPath: `gno.land/r/demo/users`
}
2. EOA calling a sequence of realms
Assuming that you use interrealm switching, when an EOA calls a sequence of realms, the call stack transitions through multiple realms. Each realm in the sequence becomes the current context as the call progresses.
Take these three actors in the call stack:
EOA:
addr: g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5
pkgPath: "" // empty as this is a user realm
Realm A:
addr: g1dvqd8qgvavqayxklzfdmccd2eps263p43pu2c6
pkgPath: gno.land/r/demo/a
Realm B:
addr: g1rsk9cwv034cw3s6csjeun2jqypj0ztpecqcm3v
pkgPath: gno.land/r/demo/b
┌─────────────────────┐ ┌──────────────────────┐ ┌─────────────────────┐
│ EOA │ │ Realm A │ │ Realm B │
│ │ │ │ │ │
│ addr: │ │ addr: │ │ addr: │
│ g1jg...sqf5 ├───► g17m...8v2s ├───► g1rs...cm3v │
│ │ │ │ │ │
│ pkgPath: │ │ pkgPath: │ │ pkgPath: │
│ "" │ │ gno.land/r/demo/a │ │ gno.land/r/demo/b │
└─────────────────────┘ └──────────────────────┘ └─────────────────────┘
Depending on which realm the methods are called in, the values will change. For
Realm A
:
std.OriginCaller() => `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5`
std.PreviousRealm() => Realm {
addr: `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5`
pkgPath: ``
}
std.CurrentRealm() => Realm {
addr: `g1dvqd8qgvavqayxklzfdmccd2eps263p43pu2c6`
pkgPath: `gno.land/r/demo/a`
}
For Realm B
:
std.OriginCaller() => `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5`
std.PreviousRealm() => Realm {
addr: `g1dvqd8qgvavqayxklzfdmccd2eps263p43pu2c6`
pkgPath: `gno.land/r/demo/a`
}
std.CurrentRealm() => Realm {
addr: `g1rsk9cwv034cw3s6csjeun2jqypj0ztpecqcm3v`
pkgPath: `gno.land/r/demo/b`
}
Resources
See the Gno Interrealm Specification for more
information on language rules for interrealm (cross) safety including how and
when to use the cross()
and crossing()
functions and more.
For more information about realms and how they fit into the gno.land ecosystem, see the Package Path Structure documentation.
To learn how to develop your own realms, check out the Anatomy of a Gno Package and Example Minisocial dApp guides.