github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/staking/app_test.go (about)

     1  package staking
     2  
     3  import (
     4  	"testing"
     5  
     6  	abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types"
     7  	"github.com/stretchr/testify/require"
     8  
     9  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    11  	authexported "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/exported"
    12  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/bank"
    13  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/mock"
    14  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/staking/types"
    15  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/supply"
    16  	supplyexported "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/supply/exported"
    17  )
    18  
    19  // getMockApp returns an initialized mock application for this module.
    20  func getMockApp(t *testing.T) (*mock.App, Keeper) {
    21  	mApp := mock.NewApp()
    22  
    23  	RegisterCodec(mApp.Cdc.GetCdc())
    24  	supply.RegisterCodec(mApp.Cdc.GetCdc())
    25  
    26  	keyStaking := sdk.NewKVStoreKey(StoreKey)
    27  	keySupply := sdk.NewKVStoreKey(supply.StoreKey)
    28  
    29  	feeCollector := supply.NewEmptyModuleAccount(auth.FeeCollectorName)
    30  	notBondedPool := supply.NewEmptyModuleAccount(types.NotBondedPoolName, supply.Burner, supply.Staking)
    31  	bondPool := supply.NewEmptyModuleAccount(types.BondedPoolName, supply.Burner, supply.Staking)
    32  
    33  	blacklistedAddrs := make(map[string]bool)
    34  	blacklistedAddrs[feeCollector.GetAddress().String()] = true
    35  	blacklistedAddrs[notBondedPool.GetAddress().String()] = true
    36  	blacklistedAddrs[bondPool.GetAddress().String()] = true
    37  
    38  	bankKeeper := bank.NewBaseKeeper(mApp.AccountKeeper, mApp.ParamsKeeper.Subspace(bank.DefaultParamspace), blacklistedAddrs)
    39  	maccPerms := map[string][]string{
    40  		auth.FeeCollectorName:   nil,
    41  		types.NotBondedPoolName: {supply.Burner, supply.Staking},
    42  		types.BondedPoolName:    {supply.Burner, supply.Staking},
    43  	}
    44  	supplyKeeper := supply.NewKeeper(mApp.Cdc.GetCdc(), keySupply, mApp.AccountKeeper, bank.NewBankKeeperAdapter(bankKeeper), maccPerms)
    45  	keeper := NewKeeper(mApp.Cdc.GetCdc(), keyStaking, supplyKeeper, mApp.ParamsKeeper.Subspace(DefaultParamspace))
    46  
    47  	mApp.Router().AddRoute(RouterKey, NewHandler(keeper))
    48  	mApp.SetEndBlocker(getEndBlocker(keeper))
    49  	mApp.SetInitChainer(getInitChainer(mApp, keeper, mApp.AccountKeeper, supplyKeeper,
    50  		[]supplyexported.ModuleAccountI{feeCollector, notBondedPool, bondPool}))
    51  
    52  	require.NoError(t, mApp.CompleteSetup(keyStaking, keySupply))
    53  	return mApp, keeper
    54  }
    55  
    56  // getEndBlocker returns a staking endblocker.
    57  func getEndBlocker(keeper Keeper) sdk.EndBlocker {
    58  	return func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
    59  		validatorUpdates := EndBlocker(ctx, keeper)
    60  
    61  		return abci.ResponseEndBlock{
    62  			ValidatorUpdates: validatorUpdates,
    63  		}
    64  	}
    65  }
    66  
    67  // getInitChainer initializes the chainer of the mock app and sets the genesis
    68  // state. It returns an empty ResponseInitChain.
    69  func getInitChainer(mapp *mock.App, keeper Keeper, accountKeeper types.AccountKeeper, supplyKeeper types.SupplyKeeper,
    70  	blacklistedAddrs []supplyexported.ModuleAccountI) sdk.InitChainer {
    71  	return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
    72  		mapp.InitChainer(ctx, req)
    73  
    74  		// set module accounts
    75  		for _, macc := range blacklistedAddrs {
    76  			supplyKeeper.SetModuleAccount(ctx, macc)
    77  		}
    78  
    79  		stakingGenesis := DefaultGenesisState()
    80  		validators := InitGenesis(ctx, keeper, accountKeeper, supplyKeeper, stakingGenesis)
    81  		return abci.ResponseInitChain{
    82  			Validators: validators,
    83  		}
    84  	}
    85  }
    86  
    87  //__________________________________________________________________________________________
    88  
    89  func checkValidator(t *testing.T, mapp *mock.App, keeper Keeper,
    90  	addr sdk.ValAddress, expFound bool) Validator {
    91  
    92  	ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{})
    93  	validator, found := keeper.GetValidator(ctxCheck, addr)
    94  
    95  	require.Equal(t, expFound, found)
    96  	return validator
    97  }
    98  
    99  func checkDelegation(
   100  	t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr sdk.AccAddress,
   101  	validatorAddr sdk.ValAddress, expFound bool, expShares sdk.Dec,
   102  ) {
   103  
   104  	ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{})
   105  	delegation, found := keeper.GetDelegation(ctxCheck, delegatorAddr, validatorAddr)
   106  	if expFound {
   107  		require.True(t, found)
   108  		require.True(sdk.DecEq(t, expShares, delegation.Shares))
   109  
   110  		return
   111  	}
   112  
   113  	require.False(t, found)
   114  }
   115  
   116  func TestStakingMsgs(t *testing.T) {
   117  	mApp, keeper := getMockApp(t)
   118  
   119  	genTokens := sdk.NewInt(42)
   120  	bondTokens := sdk.NewInt(10)
   121  	genCoin := sdk.NewCoin(sdk.DefaultBondDenom, genTokens)
   122  	bondCoin := sdk.NewCoin(sdk.DefaultBondDenom, bondTokens)
   123  
   124  	acc1 := &auth.BaseAccount{
   125  		Address: addr1,
   126  		Coins:   sdk.Coins{genCoin},
   127  	}
   128  	acc2 := &auth.BaseAccount{
   129  		Address: addr2,
   130  		Coins:   sdk.Coins{genCoin},
   131  	}
   132  	accs := []authexported.Account{acc1, acc2}
   133  
   134  	mock.SetGenesis(mApp, accs)
   135  	mApp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: mApp.LastBlockHeight() + 1}})
   136  	mApp.EndBlock(abci.RequestEndBlock{})
   137  	mApp.Commit(abci.RequestCommit{})
   138  
   139  	mock.CheckBalance(t, mApp, addr1, sdk.Coins{genCoin})
   140  	mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin})
   141  
   142  	// create validator
   143  	description := NewDescription("foo_moniker", "", "", "", "")
   144  	createValidatorMsg := NewMsgCreateValidator(
   145  		sdk.ValAddress(addr1), priv1.PubKey(), bondCoin, description, commissionRates, sdk.OneInt(),
   146  	)
   147  
   148  	header := abci.Header{Height: mApp.LastBlockHeight() + 1}
   149  	mock.SignCheckDeliver(t, mApp.Cdc.GetCdc(), mApp.BaseApp, header, []sdk.Msg{createValidatorMsg}, []uint64{0}, []uint64{0}, true, true, priv1)
   150  	mock.CheckBalance(t, mApp, addr1, sdk.Coins{genCoin.Sub(bondCoin)}.Sub(sdk.NewDecCoinsFromDec(sdk.DefaultBondDenom, sdk.OneDec())))
   151  
   152  	header = abci.Header{Height: mApp.LastBlockHeight() + 1}
   153  	mApp.BeginBlock(abci.RequestBeginBlock{Header: header})
   154  
   155  	validator := checkValidator(t, mApp, keeper, sdk.ValAddress(addr1), true)
   156  	require.Equal(t, sdk.ValAddress(addr1), validator.OperatorAddress)
   157  	require.Equal(t, sdk.Unbonded, validator.Status)
   158  	require.True(sdk.IntEq(t, sdk.ZeroInt(), validator.BondedTokens()))
   159  
   160  	header = abci.Header{Height: mApp.LastBlockHeight() + 1}
   161  	mApp.BeginBlock(abci.RequestBeginBlock{Header: header})
   162  
   163  	// edit the validator
   164  	description = NewDescription("bar_moniker", "", "", "", "")
   165  	editValidatorMsg := NewMsgEditValidator(sdk.ValAddress(addr1), description, nil, nil)
   166  
   167  	header = abci.Header{Height: mApp.LastBlockHeight() + 1}
   168  	mock.SignCheckDeliver(t, mApp.Cdc.GetCdc(), mApp.BaseApp, header, []sdk.Msg{editValidatorMsg}, []uint64{0}, []uint64{1}, true, true, priv1)
   169  
   170  	validator = checkValidator(t, mApp, keeper, sdk.ValAddress(addr1), true)
   171  	require.Equal(t, description, validator.Description)
   172  
   173  	// delegate
   174  	mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin})
   175  	delegateMsg := NewMsgDelegate(addr2, sdk.ValAddress(addr1), bondCoin)
   176  
   177  	header = abci.Header{Height: mApp.LastBlockHeight() + 1}
   178  	mock.SignCheckDeliver(t, mApp.Cdc.GetCdc(), mApp.BaseApp, header, []sdk.Msg{delegateMsg}, []uint64{1}, []uint64{0}, true, true, priv2)
   179  	mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Sub(bondCoin).Sub(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1)))})
   180  	checkDelegation(t, mApp, keeper, addr2, sdk.ValAddress(addr1), true, bondTokens.ToDec())
   181  
   182  	// begin unbonding
   183  	beginUnbondingMsg := NewMsgUndelegate(addr2, sdk.ValAddress(addr1), bondCoin)
   184  	header = abci.Header{Height: mApp.LastBlockHeight() + 1}
   185  	mock.SignCheckDeliver(t, mApp.Cdc.GetCdc(), mApp.BaseApp, header, []sdk.Msg{beginUnbondingMsg}, []uint64{1}, []uint64{1}, true, true, priv2)
   186  
   187  	// delegation should exist anymore
   188  	checkDelegation(t, mApp, keeper, addr2, sdk.ValAddress(addr1), false, sdk.Dec{})
   189  
   190  	// balance should be the same because bonding not yet complete
   191  	mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Sub(bondCoin).Sub(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2)))})
   192  }