An invariant is a property of the application that should always be true. In the context of the Cosmos SDK, an
Invariant is a function that checks for a particular invariant. These functions are useful to detect bugs early on and act upon them to limit their potential consequences (e.g. by halting the chain). They are also useful in the development process of the application to detect bugs via simulations.
# Pre-requisite Readings
Invariant is a function that checks for a particular invariant within a module. Module
Invariants must follow the
string return value is the invariant message, which can be used when printing logs, and the
bool return value is the actual result of the invariant check.
In practice, each module implements
Invariants in a
./keeper/invariants.go file within the module's folder. The standard is to implement one
Invariant function per logical grouping of invariants with the following model:
Additionally, module developers should generally implement an
AllInvariants function that runs all the
Invariants functions of the module:
Finally, module developers need to implement the
RegisterInvariants method as part of the
AppModule interface. Indeed, the
RegisterInvariants method of the module, implemented in the
module/module.go file, typically only defers the call to a
RegisterInvariants method implemented in the
keeper/invariants.go file. The
RegisterInvariants method registers a route for each
Invariant function in the
For more, see an example of
Invariants implementation from the
staking module (opens new window).
# Invariant Registry
InvariantRegistry is a registry where the
Invariants of all the modules of an application are registered. There is only one
InvariantRegistry per application, meaning module developers need not implement their own
InvariantRegistry when building a module. All module developers need to do is to register their modules' invariants in the
InvariantRegistry, as explained in the section above. The rest of this section gives more information on the
InvariantRegistry itself, and does not contain anything directly relevant to module developers.
At its core, the
InvariantRegistry is defined in the SDK as an interface:
Typically, this interface is implemented in the
keeper of a specific module. The most used implementation of an
InvariantRegistry can be found in the
InvariantRegistry is therefore typically instantiated by instantiating the
keeper of the
crisis module in the application's constructor function.
Invariants can be checked manually via
messages, but most often they are checked automatically at the end of each block. Here is an example from the
In both cases, if one of the
Invariants returns false, the
InvariantRegistry can trigger special logic (e.g. have the application panic and print the
Invariants message in the log).
Learn about genesis functionalities