github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/keeper/invariants.go (about)

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  
     6  	ethermint "github.com/fibonacci-chain/fbc/app/types"
     7  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     8  	authexported "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/exported"
     9  	"github.com/fibonacci-chain/fbc/x/evm/types"
    10  )
    11  
    12  const (
    13  	balanceInvariant = "balance"
    14  	nonceInvariant   = "nonce"
    15  )
    16  
    17  // RegisterInvariants registers the evm module invariants
    18  func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) {
    19  	ir.RegisterRoute(types.ModuleName, balanceInvariant, k.BalanceInvariant())
    20  	ir.RegisterRoute(types.ModuleName, nonceInvariant, k.NonceInvariant())
    21  }
    22  
    23  // BalanceInvariant checks that all auth module's EthAccounts in the application have the same balance
    24  // as the EVM one.
    25  func (k Keeper) BalanceInvariant() sdk.Invariant {
    26  	return func(ctx sdk.Context) (string, bool) {
    27  		var (
    28  			msg   string
    29  			count int
    30  		)
    31  
    32  		csdb := types.CreateEmptyCommitStateDB(k.GenerateCSDBParams(), ctx)
    33  		k.accountKeeper.IterateAccounts(ctx, func(account authexported.Account) bool {
    34  			ethAccount, ok := account.(*ethermint.EthAccount)
    35  			if !ok {
    36  				// ignore non EthAccounts
    37  				return false
    38  			}
    39  
    40  			accountBalance := ethAccount.GetCoins().AmountOf(sdk.DefaultBondDenom)
    41  			evmBalance := csdb.GetBalance(ethAccount.EthAddress())
    42  
    43  			if evmBalance.Cmp(accountBalance.BigInt()) != 0 {
    44  				count++
    45  				msg += fmt.Sprintf(
    46  					"\tbalance mismatch for address %s: account balance %s, evm balance %s\n",
    47  					account.GetAddress(), accountBalance.String(), evmBalance.String(),
    48  				)
    49  			}
    50  
    51  			return false
    52  		})
    53  
    54  		broken := count != 0
    55  
    56  		return sdk.FormatInvariant(
    57  			types.ModuleName, balanceInvariant,
    58  			fmt.Sprintf("account balances mismatches found %d\n%s", count, msg),
    59  		), broken
    60  	}
    61  }
    62  
    63  // NonceInvariant checks that all auth module's EthAccounts in the application have the same nonce
    64  // sequence as the EVM.
    65  func (k Keeper) NonceInvariant() sdk.Invariant {
    66  	return func(ctx sdk.Context) (string, bool) {
    67  		var (
    68  			msg   string
    69  			count int
    70  		)
    71  
    72  		csdb := types.CreateEmptyCommitStateDB(k.GenerateCSDBParams(), ctx)
    73  		k.accountKeeper.IterateAccounts(ctx, func(account authexported.Account) bool {
    74  			ethAccount, ok := account.(*ethermint.EthAccount)
    75  			if !ok {
    76  				// ignore non EthAccounts
    77  				return false
    78  			}
    79  
    80  			evmNonce := csdb.GetNonce(ethAccount.EthAddress())
    81  
    82  			if evmNonce != ethAccount.Sequence {
    83  				count++
    84  				msg += fmt.Sprintf(
    85  					"\nonce mismatch for address %s: account nonce %d, evm nonce %d\n",
    86  					account.GetAddress(), ethAccount.Sequence, evmNonce,
    87  				)
    88  			}
    89  
    90  			return false
    91  		})
    92  
    93  		broken := count != 0
    94  
    95  		return sdk.FormatInvariant(
    96  			types.ModuleName, nonceInvariant,
    97  			fmt.Sprintf("account nonces mismatches found %d\n%s", count, msg),
    98  		), broken
    99  	}
   100  }