github.com/Finschia/finschia-sdk@v0.48.1/x/bank/keeper/invariants.go (about) 1 package keeper 2 3 import ( 4 "fmt" 5 6 sdk "github.com/Finschia/finschia-sdk/types" 7 "github.com/Finschia/finschia-sdk/types/query" 8 "github.com/Finschia/finschia-sdk/x/bank/types" 9 ) 10 11 // RegisterInvariants registers the bank module invariants 12 func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) { 13 ir.RegisterRoute(types.ModuleName, "nonnegative-outstanding", NonnegativeBalanceInvariant(k)) 14 ir.RegisterRoute(types.ModuleName, "total-supply", TotalSupply(k)) 15 } 16 17 // AllInvariants runs all invariants of the X/bank module. 18 func AllInvariants(k Keeper) sdk.Invariant { 19 return func(ctx sdk.Context) (string, bool) { 20 return TotalSupply(k)(ctx) 21 } 22 } 23 24 // NonnegativeBalanceInvariant checks that all accounts in the application have non-negative balances 25 func NonnegativeBalanceInvariant(k ViewKeeper) sdk.Invariant { 26 return func(ctx sdk.Context) (string, bool) { 27 var ( 28 msg string 29 count int 30 ) 31 32 k.IterateAllBalances(ctx, func(addr sdk.AccAddress, balance sdk.Coin) bool { 33 if balance.IsNegative() { 34 count++ 35 msg += fmt.Sprintf("\t%s has a negative balance of %s\n", addr, balance) 36 } 37 38 return false 39 }) 40 41 broken := count != 0 42 43 return sdk.FormatInvariant( 44 types.ModuleName, "nonnegative-outstanding", 45 fmt.Sprintf("amount of negative balances found %d\n%s", count, msg), 46 ), broken 47 } 48 } 49 50 // TotalSupply checks that the total supply reflects all the coins held in accounts 51 func TotalSupply(k Keeper) sdk.Invariant { 52 return func(ctx sdk.Context) (string, bool) { 53 expectedTotal := sdk.Coins{} 54 supply, _, err := k.GetPaginatedTotalSupply(ctx, &query.PageRequest{Limit: query.MaxLimit}) 55 if err != nil { 56 return sdk.FormatInvariant(types.ModuleName, "query supply", 57 fmt.Sprintf("error querying total supply %v", err)), false 58 } 59 60 k.IterateAllBalances(ctx, func(_ sdk.AccAddress, balance sdk.Coin) bool { 61 expectedTotal = expectedTotal.Add(balance) 62 return false 63 }) 64 65 broken := !expectedTotal.IsEqual(supply) 66 67 return sdk.FormatInvariant(types.ModuleName, "total supply", 68 fmt.Sprintf( 69 "\tsum of accounts coins: %v\n"+ 70 "\tsupply.Total: %v\n", 71 expectedTotal, supply)), broken 72 } 73 }