2019-06-14 07:10:37 -07:00
|
|
|
package keeper
|
2018-07-18 00:05:48 -07:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2021-04-06 07:43:08 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/types/query"
|
2020-02-20 06:24:26 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/bank/types"
|
2018-07-18 00:05:48 -07:00
|
|
|
)
|
|
|
|
|
2019-07-31 08:39:02 -07:00
|
|
|
// RegisterInvariants registers the bank module invariants
|
2020-04-20 08:22:12 -07:00
|
|
|
func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) {
|
|
|
|
ir.RegisterRoute(types.ModuleName, "nonnegative-outstanding", NonnegativeBalanceInvariant(k))
|
|
|
|
ir.RegisterRoute(types.ModuleName, "total-supply", TotalSupply(k))
|
|
|
|
}
|
|
|
|
|
|
|
|
// AllInvariants runs all invariants of the X/bank module.
|
|
|
|
func AllInvariants(k Keeper) sdk.Invariant {
|
|
|
|
return func(ctx sdk.Context) (string, bool) {
|
|
|
|
return TotalSupply(k)(ctx)
|
|
|
|
}
|
2019-03-28 16:27:47 -07:00
|
|
|
}
|
|
|
|
|
2018-07-18 00:05:48 -07:00
|
|
|
// NonnegativeBalanceInvariant checks that all accounts in the application have non-negative balances
|
2020-04-20 08:22:12 -07:00
|
|
|
func NonnegativeBalanceInvariant(k ViewKeeper) sdk.Invariant {
|
2019-07-11 03:56:43 -07:00
|
|
|
return func(ctx sdk.Context) (string, bool) {
|
2020-01-30 13:31:16 -08:00
|
|
|
var (
|
|
|
|
msg string
|
|
|
|
count int
|
|
|
|
)
|
2019-07-11 03:56:43 -07:00
|
|
|
|
2020-04-20 08:22:12 -07:00
|
|
|
k.IterateAllBalances(ctx, func(addr sdk.AccAddress, balance sdk.Coin) bool {
|
2020-01-30 13:31:16 -08:00
|
|
|
if balance.IsNegative() {
|
2019-07-15 09:56:38 -07:00
|
|
|
count++
|
2020-01-30 13:31:16 -08:00
|
|
|
msg += fmt.Sprintf("\t%s has a negative balance of %s\n", addr, balance)
|
2018-09-09 08:34:09 -07:00
|
|
|
}
|
2020-01-30 13:31:16 -08:00
|
|
|
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
|
2019-07-15 09:56:38 -07:00
|
|
|
broken := count != 0
|
2018-07-18 00:05:48 -07:00
|
|
|
|
2020-01-30 13:31:16 -08:00
|
|
|
return sdk.FormatInvariant(
|
|
|
|
types.ModuleName, "nonnegative-outstanding",
|
|
|
|
fmt.Sprintf("amount of negative balances found %d\n%s", count, msg),
|
|
|
|
), broken
|
2018-07-18 00:05:48 -07:00
|
|
|
}
|
|
|
|
}
|
2020-04-20 08:22:12 -07:00
|
|
|
|
|
|
|
// TotalSupply checks that the total supply reflects all the coins held in accounts
|
|
|
|
func TotalSupply(k Keeper) sdk.Invariant {
|
|
|
|
return func(ctx sdk.Context) (string, bool) {
|
2020-05-19 13:17:29 -07:00
|
|
|
expectedTotal := sdk.Coins{}
|
2021-04-06 07:43:08 -07:00
|
|
|
supply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: query.MaxLimit})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return sdk.FormatInvariant(types.ModuleName, "query supply",
|
|
|
|
fmt.Sprintf("error querying total supply %v", err)), false
|
|
|
|
}
|
2020-04-20 08:22:12 -07:00
|
|
|
|
|
|
|
k.IterateAllBalances(ctx, func(_ sdk.AccAddress, balance sdk.Coin) bool {
|
|
|
|
expectedTotal = expectedTotal.Add(balance)
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
|
2021-03-03 01:58:16 -08:00
|
|
|
broken := !expectedTotal.IsEqual(supply)
|
2020-04-20 08:22:12 -07:00
|
|
|
|
|
|
|
return sdk.FormatInvariant(types.ModuleName, "total supply",
|
|
|
|
fmt.Sprintf(
|
|
|
|
"\tsum of accounts coins: %v\n"+
|
|
|
|
"\tsupply.Total: %v\n",
|
2021-03-03 01:58:16 -08:00
|
|
|
expectedTotal, supply)), broken
|
2020-04-20 08:22:12 -07:00
|
|
|
}
|
|
|
|
}
|