diff --git a/x/auction/keeper/invariants.go b/x/auction/keeper/invariants.go index 8ed32a48..83c8f689 100644 --- a/x/auction/keeper/invariants.go +++ b/x/auction/keeper/invariants.go @@ -10,10 +10,10 @@ import ( // RegisterInvariants registers all auction invariants func RegisterInvariants(ir sdk.InvariantRegistry, k *Keeper) { - ir.RegisterRoute(types.ModuleName, "module-accounts", ModuleAccountInvariant(k)) + ir.RegisterRoute(types.ModuleName, "module-account", ModuleAccountInvariant(k)) } -// AllInvariants runs all invariants of the auctions module. +// AllInvariants runs all invariants of the auction module. func AllInvariants(k *Keeper) sdk.Invariant { return func(ctx sdk.Context) (string, bool) { return ModuleAccountInvariant(k)(ctx) @@ -23,7 +23,6 @@ func AllInvariants(k *Keeper) sdk.Invariant { // ModuleAccountInvariant checks that the 'auction' module account balance is non-negative. func ModuleAccountInvariant(k *Keeper) sdk.Invariant { return func(ctx sdk.Context) (string, bool) { - fmt.Println("running auction module invariant") moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName) if k.bankKeeper.GetAllBalances(ctx, moduleAddress).IsAnyNegative() { return sdk.FormatInvariant( diff --git a/x/bond/keeper/invariants.go b/x/bond/keeper/invariants.go new file mode 100644 index 00000000..b8366c92 --- /dev/null +++ b/x/bond/keeper/invariants.go @@ -0,0 +1,37 @@ +package keeper + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + types "git.vdb.to/cerc-io/laconic2d/x/bond" +) + +// RegisterInvariants registers all bond invariants +func RegisterInvariants(ir sdk.InvariantRegistry, k *Keeper) { + ir.RegisterRoute(types.ModuleName, "module-account", ModuleAccountInvariant(k)) +} + +// AllInvariants runs all invariants of the bond module. +func AllInvariants(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + return ModuleAccountInvariant(k)(ctx) + } +} + +// ModuleAccountInvariant checks that the 'bond' module account balance is non-negative. +func ModuleAccountInvariant(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName) + if k.bankKeeper.GetAllBalances(ctx, moduleAddress).IsAnyNegative() { + return sdk.FormatInvariant( + types.ModuleName, + "module-account", + fmt.Sprintf("Module account '%s' has negative balance.", types.ModuleName)), + true + } + + return "", false + } +} diff --git a/x/bond/module/module.go b/x/bond/module/module.go index 073f5224..414a64ff 100644 --- a/x/bond/module/module.go +++ b/x/bond/module/module.go @@ -24,6 +24,7 @@ var ( _ module.HasGenesis = AppModule{} _ module.HasServices = AppModule{} _ module.HasConsensusVersion = AppModule{} + _ module.HasInvariants = AppModule{} ) // ConsensusVersion defines the current module consensus version @@ -116,3 +117,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { bond.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) bond.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper)) } + +// module.HasInvariants + +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + keeper.RegisterInvariants(ir, am.keeper) +} diff --git a/x/registry/keeper/invariants.go b/x/registry/keeper/invariants.go new file mode 100644 index 00000000..378692a7 --- /dev/null +++ b/x/registry/keeper/invariants.go @@ -0,0 +1,71 @@ +package keeper + +import ( + "errors" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + types "git.vdb.to/cerc-io/laconic2d/x/registry" +) + +// RegisterInvariants registers all registry invariants +func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) { + ir.RegisterRoute(types.ModuleName, "module-account", ModuleAccountInvariant(&k)) + ir.RegisterRoute(types.ModuleName, "record-bond", RecordBondInvariant(&k)) +} + +// AllInvariants runs all invariants of the registry module. +func AllInvariants(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + res, stop := ModuleAccountInvariant(k)(ctx) + if stop { + return res, stop + } + + return RecordBondInvariant(k)(ctx) + } +} + +// ModuleAccountInvariant checks that the 'registry' module account balance is non-negative. +func ModuleAccountInvariant(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + moduleAddress := k.accountKeeper.GetModuleAddress(types.ModuleName) + if k.bankKeeper.GetAllBalances(ctx, moduleAddress).IsAnyNegative() { + return sdk.FormatInvariant( + types.ModuleName, + "module-account", + fmt.Sprintf("Module account '%s' has negative balance.", types.ModuleName)), + true + } + + return "", false + } +} + +// RecordBondInvariant checks that for every record: +// if bondId is not null, associated bond exists +func RecordBondInvariant(k *Keeper) sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + err := k.Records.Walk(ctx, nil, func(key string, record types.Record) (bool, error) { + if record.BondId != "" { + bondExists, err := k.bondKeeper.HasBond(ctx, record.BondId) + if err != nil { + return true, err + } + + if !bondExists { + return true, errors.New(record.Id) + } + } + + return false, nil + }) + + if err != nil { + return sdk.FormatInvariant(types.ModuleName, "record-bond", fmt.Sprintf("Bond not found for record id: '%s'.", err.Error())), true + } + + return "", false + } +} diff --git a/x/registry/module/module.go b/x/registry/module/module.go index 7e4f5703..d8a325af 100644 --- a/x/registry/module/module.go +++ b/x/registry/module/module.go @@ -27,6 +27,7 @@ var ( _ module.HasServices = AppModule{} _ module.HasConsensusVersion = AppModule{} _ appmodule.HasEndBlocker = AppModule{} + _ module.HasInvariants = AppModule{} ) // ConsensusVersion defines the current module consensus version. @@ -127,6 +128,12 @@ func (am AppModule) EndBlock(ctx context.Context) error { return EndBlocker(ctx, am.keeper) } +// module.HasInvariants + +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { + keeper.RegisterInvariants(ir, am.keeper) +} + // Get the root tx command of this module func (AppModule) GetTxCmd() *cobra.Command { return cli.GetTxCmd()