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

     1  package keeper
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     8  	"github.com/fibonacci-chain/fbc/x/distribution/types"
     9  	"github.com/fibonacci-chain/fbc/x/staking"
    10  	stakingexported "github.com/fibonacci-chain/fbc/x/staking/exported"
    11  	stakingtypes "github.com/fibonacci-chain/fbc/x/staking/types"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/suite"
    14  
    15  	tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestCalculateRewardsBasic(t *testing.T) {
    20  	communityTax := sdk.NewDecWithPrec(2, 2)
    21  	ctx, _, _, dk, sk, _, _ := CreateTestInputAdvanced(t, false, 1000, communityTax)
    22  	tmtypes.UnittestOnlySetMilestoneVenus2Height(-1)
    23  	dk.SetDistributionType(ctx, types.DistributionTypeOnChain)
    24  	dk.SetInitExistedValidatorFlag(ctx, true)
    25  
    26  	// create validator
    27  	DoCreateValidator(t, ctx, sk, valOpAddr1, valConsPk1)
    28  
    29  	// end block to bond validator
    30  	staking.EndBlocker(ctx, sk)
    31  
    32  	// next block
    33  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
    34  
    35  	// set new rate 0.5
    36  	newRate, _ := sdk.NewDecFromStr("0.5")
    37  	ctx.SetBlockTime(time.Now().UTC().Add(48 * time.Hour))
    38  	DoEditValidator(t, ctx, sk, valOpAddr1, newRate)
    39  	staking.EndBlocker(ctx, sk)
    40  
    41  	// next block
    42  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
    43  
    44  	// fetch validator
    45  	val := sk.Validator(ctx, valOpAddr1)
    46  
    47  	// historical count should be 1 (once for validator init)
    48  	require.Equal(t, uint64(1), dk.GetValidatorHistoricalReferenceCount(ctx))
    49  
    50  	// end period
    51  	dk.incrementValidatorPeriod(ctx, val)
    52  
    53  	// historical count should be 1 still
    54  	require.Equal(t, uint64(1), dk.GetValidatorHistoricalReferenceCount(ctx))
    55  
    56  	// allocate some rewards
    57  	initial := int64(10)
    58  	tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}
    59  	dk.AllocateTokensToValidator(ctx, val, tokens)
    60  
    61  	// end period
    62  	dk.incrementValidatorPeriod(ctx, val)
    63  
    64  	// commission should be the other half
    65  	require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, dk.GetValidatorAccumulatedCommission(ctx, valOpAddr1))
    66  	require.Equal(t, sdk.SysCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}, dk.GetValidatorOutstandingRewards(ctx, valOpAddr1))
    67  }
    68  
    69  func TestCalculateRewardsMultiDelegator(t *testing.T) {
    70  	communityTax := sdk.NewDecWithPrec(2, 2)
    71  	ctx, _, _, dk, sk, _, _ := CreateTestInputAdvanced(t, false, 1000, communityTax)
    72  	tmtypes.UnittestOnlySetMilestoneVenus2Height(-1)
    73  	dk.SetDistributionType(ctx, types.DistributionTypeOnChain)
    74  	dk.SetInitExistedValidatorFlag(ctx, true)
    75  
    76  	// create validator
    77  	DoCreateValidator(t, ctx, sk, valOpAddr1, valConsPk1)
    78  
    79  	// end block to bond validator
    80  	staking.EndBlocker(ctx, sk)
    81  
    82  	// next block
    83  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
    84  
    85  	// set new rate 0.5
    86  	newRate, _ := sdk.NewDecFromStr("0.5")
    87  	ctx.SetBlockTime(time.Now().UTC().Add(48 * time.Hour))
    88  	DoEditValidator(t, ctx, sk, valOpAddr1, newRate)
    89  	staking.EndBlocker(ctx, sk)
    90  
    91  	// next block
    92  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
    93  
    94  	// fetch validator and delegation
    95  	val := sk.Validator(ctx, valOpAddr1)
    96  
    97  	// allocate some rewards
    98  	initial := int64(20)
    99  	tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}
   100  	dk.AllocateTokensToValidator(ctx, val, tokens)
   101  
   102  	valOpAddrs := []sdk.ValAddress{valOpAddr1}
   103  	//first delegation
   104  	DoDeposit(t, ctx, sk, delAddr1, sdk.NewCoin(sk.BondDenom(ctx), sdk.NewInt(100)))
   105  	require.Equal(t, uint64(1), dk.GetValidatorHistoricalReferenceCount(ctx))
   106  	DoAddShares(t, ctx, sk, delAddr1, valOpAddrs)
   107  	// historical count should be 2(first is init validator)
   108  	require.Equal(t, uint64(2), dk.GetValidatorHistoricalReferenceCount(ctx))
   109  
   110  	//second delegation
   111  	DoDeposit(t, ctx, sk, delAddr2, sdk.NewCoin(sk.BondDenom(ctx), sdk.NewInt(100)))
   112  	DoAddShares(t, ctx, sk, delAddr2, valOpAddrs)
   113  	require.Equal(t, uint64(3), dk.GetValidatorHistoricalReferenceCount(ctx))
   114  
   115  	// fetch updated validator
   116  	val = sk.Validator(ctx, valOpAddr1)
   117  
   118  	// end block
   119  	staking.EndBlocker(ctx, sk)
   120  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
   121  
   122  	// allocate some more rewards
   123  	dk.AllocateTokensToValidator(ctx, val, tokens)
   124  	// end period
   125  	endingPeriod := dk.incrementValidatorPeriod(ctx, val)
   126  
   127  	// calculate delegation rewards for del1
   128  	rewards1 := dk.calculateDelegationRewards(ctx, val, delAddr1, endingPeriod)
   129  	require.True(t, rewards1[0].Amount.LT(sdk.NewDec(initial/4)))
   130  	require.True(t, rewards1[0].Amount.GT(sdk.NewDec((initial/4)-1)))
   131  
   132  	// calculate delegation rewards for del2
   133  	rewards2 := dk.calculateDelegationRewards(ctx, val, delAddr2, endingPeriod)
   134  	require.True(t, rewards2[0].Amount.LT(sdk.NewDec(initial/4)))
   135  	require.True(t, rewards2[0].Amount.GT(sdk.NewDec((initial/4)-1)))
   136  
   137  	// commission should be equal to initial (50% twice)
   138  	require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}, dk.GetValidatorAccumulatedCommission(ctx, valOpAddr1))
   139  }
   140  
   141  func TestWithdrawDelegationRewardsBasic(t *testing.T) {
   142  	communityTax := sdk.NewDecWithPrec(2, 2)
   143  	ctx, ak, _, dk, sk, _, _ := CreateTestInputAdvanced(t, false, 1000, communityTax)
   144  	tmtypes.UnittestOnlySetMilestoneVenus2Height(-1)
   145  	dk.SetDistributionType(ctx, types.DistributionTypeOnChain)
   146  	dk.SetInitExistedValidatorFlag(ctx, true)
   147  
   148  	balanceTokens := sdk.NewCoins(sdk.NewCoin(sk.BondDenom(ctx), sdk.TokensFromConsensusPower(int64(1000))))
   149  
   150  	//set module account coins
   151  	distrAcc := dk.GetDistributionAccount(ctx)
   152  	distrAcc.SetCoins(balanceTokens)
   153  	dk.supplyKeeper.SetModuleAccount(ctx, distrAcc)
   154  
   155  	// create validator
   156  	DoCreateValidator(t, ctx, sk, valOpAddr1, valConsPk1)
   157  
   158  	// end block to bond validator
   159  	staking.EndBlocker(ctx, sk)
   160  
   161  	// next block
   162  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
   163  
   164  	// set new rate 0.5
   165  	newRate, _ := sdk.NewDecFromStr("0.5")
   166  	ctx.SetBlockTime(time.Now().UTC().Add(48 * time.Hour))
   167  	DoEditValidator(t, ctx, sk, valOpAddr1, newRate)
   168  	staking.EndBlocker(ctx, sk)
   169  	valTokens := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sk.ParamsMinSelfDelegation(ctx))}
   170  	// assert correct initial balance
   171  	expTokens := balanceTokens.Sub(valTokens)
   172  	require.Equal(t, expTokens, ak.GetAccount(ctx, sdk.AccAddress(valOpAddr1)).GetCoins())
   173  
   174  	// end block to bond validator
   175  	staking.EndBlocker(ctx, sk)
   176  
   177  	// next block
   178  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
   179  
   180  	// fetch validator and delegation
   181  	val := sk.Validator(ctx, valOpAddr1)
   182  
   183  	initial := int64(20)
   184  	tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}
   185  
   186  	dk.AllocateTokensToValidator(ctx, val, tokens)
   187  
   188  	// historical count should be 1 (initial)
   189  	require.Equal(t, uint64(1), dk.GetValidatorHistoricalReferenceCount(ctx))
   190  
   191  	//assert correct balance
   192  	exp := balanceTokens.Sub(valTokens)
   193  	require.Equal(t, exp, ak.GetAccount(ctx, sdk.AccAddress(valOpAddr1)).GetCoins())
   194  
   195  	// withdraw commission
   196  	_, err := dk.WithdrawValidatorCommission(ctx, valOpAddr1)
   197  	require.Nil(t, err)
   198  
   199  	// assert correct balance
   200  	exp = balanceTokens.Sub(valTokens).Add(tokens.QuoDec(sdk.NewDec(int64(2)))[0])
   201  	require.Equal(t, exp, ak.GetAccount(ctx, sdk.AccAddress(valOpAddr1)).GetCoins())
   202  }
   203  
   204  func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) {
   205  	communityTax := sdk.NewDecWithPrec(2, 2)
   206  	ctx, ak, _, dk, sk, _, _ := CreateTestInputAdvanced(t, false, 1000, communityTax)
   207  	tmtypes.UnittestOnlySetMilestoneVenus2Height(-1)
   208  	dk.SetDistributionType(ctx, types.DistributionTypeOnChain)
   209  	dk.SetInitExistedValidatorFlag(ctx, true)
   210  
   211  	balanceTokens := sdk.NewCoins(sdk.NewCoin(sk.BondDenom(ctx), sdk.TokensFromConsensusPower(int64(1000))))
   212  
   213  	//set module account coins
   214  	distrAcc := dk.GetDistributionAccount(ctx)
   215  	distrAcc.SetCoins(balanceTokens)
   216  	dk.supplyKeeper.SetModuleAccount(ctx, distrAcc)
   217  
   218  	// create validator
   219  	DoCreateValidator(t, ctx, sk, valOpAddr1, valConsPk1)
   220  
   221  	// end block to bond validator
   222  	staking.EndBlocker(ctx, sk)
   223  
   224  	// next block
   225  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
   226  
   227  	// set new rate 0.5
   228  	newRate, _ := sdk.NewDecFromStr("0.5")
   229  	ctx.SetBlockTime(time.Now().UTC().Add(48 * time.Hour))
   230  	DoEditValidator(t, ctx, sk, valOpAddr1, newRate)
   231  	staking.EndBlocker(ctx, sk)
   232  	valTokens := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sk.ParamsMinSelfDelegation(ctx))}
   233  	// assert correct initial balance
   234  	expTokens := balanceTokens.Sub(valTokens)
   235  	require.Equal(t, expTokens, ak.GetAccount(ctx, sdk.AccAddress(valOpAddr1)).GetCoins())
   236  
   237  	// end block to bond validator
   238  	staking.EndBlocker(ctx, sk)
   239  
   240  	// next block
   241  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
   242  
   243  	// fetch validator
   244  	val := sk.Validator(ctx, valOpAddr1)
   245  
   246  	// allocate some rewards
   247  	initial := int64(20)
   248  	tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}
   249  	dk.AllocateTokensToValidator(ctx, val, tokens)
   250  
   251  	//historical count should be 1 (validator init)
   252  	require.Equal(t, uint64(1), dk.GetValidatorHistoricalReferenceCount(ctx))
   253  
   254  	//first delegation
   255  	DoDeposit(t, ctx, sk, delAddr1, sdk.NewCoin(sk.BondDenom(ctx), sdk.NewInt(100)))
   256  	// historical count should be 1
   257  	require.Equal(t, uint64(1), dk.GetValidatorHistoricalReferenceCount(ctx))
   258  	valOpAddrs := []sdk.ValAddress{valOpAddr1}
   259  	DoAddShares(t, ctx, sk, delAddr1, valOpAddrs)
   260  	// historical count should be 2 (first delegation init)
   261  	require.Equal(t, uint64(2), dk.GetValidatorHistoricalReferenceCount(ctx))
   262  	// end block
   263  	staking.EndBlocker(ctx, sk)
   264  
   265  	//second delegation
   266  	DoDeposit(t, ctx, sk, delAddr2, sdk.NewCoin(sk.BondDenom(ctx), sdk.NewInt(100)))
   267  	// historical count should be 2
   268  	require.Equal(t, uint64(2), dk.GetValidatorHistoricalReferenceCount(ctx))
   269  	DoAddShares(t, ctx, sk, delAddr2, valOpAddrs)
   270  	// historical count should be 3 (second delegation init)
   271  	require.Equal(t, uint64(3), dk.GetValidatorHistoricalReferenceCount(ctx))
   272  	// end block
   273  	staking.EndBlocker(ctx, sk)
   274  
   275  	// next block
   276  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
   277  
   278  	// fetch updated validator
   279  	val = sk.Validator(ctx, valOpAddr1)
   280  
   281  	// allocate some more rewards
   282  	dk.AllocateTokensToValidator(ctx, val, tokens)
   283  
   284  	// first delegator withdraws
   285  	dk.WithdrawDelegationRewards(ctx, sdk.AccAddress(delAddr1), valOpAddr1)
   286  
   287  	// second delegator withdraws
   288  	dk.WithdrawDelegationRewards(ctx, sdk.AccAddress(delAddr2), valOpAddr1)
   289  
   290  	// historical count should be 3 (two delegations)
   291  	require.Equal(t, uint64(3), dk.GetValidatorHistoricalReferenceCount(ctx))
   292  
   293  	// validator withdraws commission
   294  	dk.WithdrawValidatorCommission(ctx, valOpAddr1)
   295  
   296  	// end period
   297  	endingPeriod := dk.incrementValidatorPeriod(ctx, val)
   298  
   299  	// calculate delegation rewards for del1
   300  	rewards := dk.calculateDelegationRewards(ctx, val, delAddr1, endingPeriod)
   301  
   302  	// rewards for del1 should be zero
   303  	require.True(t, rewards.IsZero())
   304  
   305  	// calculate delegation rewards for del2
   306  	rewards = dk.calculateDelegationRewards(ctx, val, delAddr2, endingPeriod)
   307  
   308  	// rewards for del2 should be zero
   309  	require.True(t, rewards.IsZero())
   310  
   311  	// commission should be zero
   312  	require.True(t, dk.GetValidatorAccumulatedCommission(ctx, valOpAddr1).IsZero())
   313  
   314  	// next block
   315  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
   316  
   317  	// allocate some more rewards
   318  	dk.AllocateTokensToValidator(ctx, val, tokens)
   319  
   320  	// first delegator withdraws again
   321  	dk.WithdrawDelegationRewards(ctx, delAddr1, valOpAddr1)
   322  
   323  	// end period
   324  	endingPeriod = dk.incrementValidatorPeriod(ctx, val)
   325  
   326  	// calculate delegation rewards for del1
   327  	rewards = dk.calculateDelegationRewards(ctx, val, delAddr1, endingPeriod)
   328  
   329  	// rewards for del1 should be zero
   330  	require.True(t, rewards.IsZero())
   331  
   332  	// calculate delegation rewards for del2
   333  	rewards = dk.calculateDelegationRewards(ctx, val, delAddr2, endingPeriod)
   334  
   335  	// rewards for del2 should be close to 1/4 initial
   336  	require.True(t, rewards[0].Amount.LT(sdk.NewDec(initial/4)))
   337  	require.True(t, rewards[0].Amount.GT(sdk.NewDec((initial/4)-1)))
   338  
   339  	// commission should be half initial
   340  	require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, dk.GetValidatorAccumulatedCommission(ctx, valOpAddr1))
   341  
   342  	// next block
   343  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
   344  
   345  	// allocate some more rewards
   346  	dk.AllocateTokensToValidator(ctx, val, tokens)
   347  
   348  	// withdraw commission
   349  	dk.WithdrawValidatorCommission(ctx, valOpAddr1)
   350  
   351  	// end period
   352  	endingPeriod = dk.incrementValidatorPeriod(ctx, val)
   353  	// calculate delegation rewards for del1
   354  	rewards = dk.calculateDelegationRewards(ctx, val, delAddr1, endingPeriod)
   355  
   356  	// rewards for del1 should be 1/4 initial
   357  	require.True(t, rewards[0].Amount.LT(sdk.NewDec(initial/4)))
   358  	require.True(t, rewards[0].Amount.GT(sdk.NewDec((initial/4)-1)))
   359  
   360  	// calculate delegation rewards for del2
   361  	rewards = dk.calculateDelegationRewards(ctx, val, delAddr2, endingPeriod)
   362  
   363  	// rewards for del2 should be 1/4 + 1/4 initial
   364  	// rewards for del1 should be close to 1/2 initial
   365  	require.True(t, rewards[0].Amount.LT(sdk.NewDec(initial/2)))
   366  	require.True(t, rewards[0].Amount.GT(sdk.NewDec((initial/2)-1)))
   367  
   368  	// commission should be zero
   369  	require.True(t, dk.GetValidatorAccumulatedCommission(ctx, valOpAddr1).IsZero())
   370  }
   371  
   372  func TestInitExistedDelegationStartInfoSuite(t *testing.T) {
   373  	suite.Run(t, new(InitExistedDelegationStartInfoestSuite))
   374  }
   375  
   376  type InitExistedDelegationStartInfoestSuite struct {
   377  	suite.Suite
   378  }
   379  
   380  func changeDistribution(ctx sdk.Context, dk Keeper) {
   381  	//change to distribution onchain
   382  	dk.SetInitExistedValidatorFlag(ctx, true)
   383  	dk.SetDistributionType(ctx, types.DistributionTypeOnChain)
   384  	dk.stakingKeeper.IterateValidators(ctx, func(index int64, validator stakingexported.ValidatorI) (stop bool) {
   385  		if validator != nil {
   386  			dk.initExistedValidatorForDistrProposal(ctx, validator)
   387  		}
   388  		return false
   389  	})
   390  }
   391  
   392  func (suite *InitExistedDelegationStartInfoestSuite) TestInitExistedDelegationStartInfo() {
   393  	testCases := []struct {
   394  		title                         string
   395  		execute1                      func(ctx *sdk.Context, dk Keeper)
   396  		execute2                      func(ctx *sdk.Context, dk Keeper)
   397  		execute3                      func(ctx *sdk.Context, dk Keeper)
   398  		execute4                      func(ctx *sdk.Context, dk Keeper)
   399  		beforeAddSharesReferenceCount uint64
   400  		afterAddSharesReferenceCount  uint64
   401  		afterWithdrawReferenceCount   uint64
   402  		coins                         sdk.Coins
   403  		err                           error
   404  	}{
   405  		{
   406  			"ErrCodeNotSupportWithdrawDelegationRewards",
   407  			func(ctx *sdk.Context, dk Keeper) {},
   408  			func(ctx *sdk.Context, dk Keeper) {
   409  				ctx.SetBlockTime(time.Now())
   410  			},
   411  			func(ctx *sdk.Context, dk Keeper) {},
   412  			func(ctx *sdk.Context, dk Keeper) {},
   413  			0,
   414  			0,
   415  			0,
   416  			sdk.Coins(nil),
   417  			types.ErrCodeNotSupportWithdrawDelegationRewards(),
   418  		},
   419  		{
   420  			"NO ERROR Before create validator",
   421  			func(ctx *sdk.Context, dk Keeper) {
   422  				changeDistribution(*ctx, dk)
   423  			},
   424  			func(ctx *sdk.Context, dk Keeper) {
   425  				ctx.SetBlockTime(time.Now())
   426  			},
   427  			func(ctx *sdk.Context, dk Keeper) {},
   428  			func(ctx *sdk.Context, dk Keeper) {},
   429  			1,
   430  			2,
   431  			2,
   432  			sdk.Coins(nil),
   433  			nil,
   434  		},
   435  		{
   436  			"NO ERROR Before Do Deposit",
   437  			func(ctx *sdk.Context, dk Keeper) {},
   438  			func(ctx *sdk.Context, dk Keeper) {
   439  				ctx.SetBlockTime(time.Now())
   440  				changeDistribution(*ctx, dk)
   441  			},
   442  			func(ctx *sdk.Context, dk Keeper) {},
   443  			func(ctx *sdk.Context, dk Keeper) {},
   444  			2,
   445  			3,
   446  			3,
   447  			sdk.Coins(nil),
   448  			nil,
   449  		},
   450  		{
   451  			"NO ERROR Before Do Add Shares",
   452  			func(ctx *sdk.Context, dk Keeper) {},
   453  			func(ctx *sdk.Context, dk Keeper) {
   454  				ctx.SetBlockTime(time.Now())
   455  			},
   456  			func(ctx *sdk.Context, dk Keeper) {
   457  				changeDistribution(*ctx, dk)
   458  			},
   459  			func(ctx *sdk.Context, dk Keeper) {},
   460  			2,
   461  			3,
   462  			3,
   463  			sdk.Coins(nil),
   464  			nil,
   465  		},
   466  		{
   467  			"NO ERROR After Do Add Shares",
   468  			func(ctx *sdk.Context, dk Keeper) {},
   469  			func(ctx *sdk.Context, dk Keeper) {
   470  				ctx.SetBlockTime(time.Now())
   471  			},
   472  			func(ctx *sdk.Context, dk Keeper) {},
   473  			func(ctx *sdk.Context, dk Keeper) {
   474  				changeDistribution(*ctx, dk)
   475  			},
   476  			0,
   477  			0,
   478  			3,
   479  			sdk.Coins(nil),
   480  			nil,
   481  		},
   482  		{
   483  			"ERROR No Shares",
   484  			func(ctx *sdk.Context, dk Keeper) {},
   485  			func(ctx *sdk.Context, dk Keeper) {},
   486  			func(ctx *sdk.Context, dk Keeper) {},
   487  			func(ctx *sdk.Context, dk Keeper) {
   488  				changeDistribution(*ctx, dk)
   489  			},
   490  			0,
   491  			0,
   492  			2,
   493  			sdk.Coins(nil),
   494  			types.ErrCodeZeroDelegationShares(),
   495  		},
   496  	}
   497  
   498  	for _, tc := range testCases {
   499  		suite.Run(tc.title, func() {
   500  			communityTax := sdk.NewDecWithPrec(2, 2)
   501  			ctx, _, _, dk, sk, _, _ := CreateTestInputAdvanced(suite.T(), false, 1000, communityTax)
   502  			tmtypes.UnittestOnlySetMilestoneVenus2Height(-1)
   503  			balanceTokens := sdk.NewCoins(sdk.NewCoin(sk.BondDenom(ctx), sdk.TokensFromConsensusPower(int64(1000))))
   504  			//set module account coins
   505  			distrAcc := dk.GetDistributionAccount(ctx)
   506  			distrAcc.SetCoins(balanceTokens)
   507  			dk.supplyKeeper.SetModuleAccount(ctx, distrAcc)
   508  			tc.execute1(&ctx, dk)
   509  			// create validator
   510  			DoCreateValidator(suite.T(), ctx, sk, valOpAddr1, valConsPk1)
   511  			// end block to bond validator
   512  			staking.EndBlocker(ctx, sk)
   513  
   514  			ctx.SetBlockHeight(ctx.BlockHeight() + 1)
   515  			//ctx.SetBlockTime(time.Now())
   516  			tc.execute2(&ctx, dk)
   517  			//delegation
   518  			DoDeposit(suite.T(), ctx, sk, delAddr1, sdk.NewCoin(sk.BondDenom(ctx), sdk.NewInt(100)))
   519  
   520  			coins, err := dk.WithdrawDelegationRewards(ctx, delAddr1, valOpAddr1)
   521  			require.Equal(suite.T(), types.ErrCodeEmptyDelegationVoteValidator(), err)
   522  
   523  			tc.execute3(&ctx, dk)
   524  			// historical count
   525  			require.Equal(suite.T(), tc.beforeAddSharesReferenceCount, dk.GetValidatorHistoricalReferenceCount(ctx))
   526  			valOpAddrs := []sdk.ValAddress{valOpAddr1}
   527  			DoAddShares(suite.T(), ctx, sk, delAddr1, valOpAddrs)
   528  			require.Equal(suite.T(), tc.afterAddSharesReferenceCount, dk.GetValidatorHistoricalReferenceCount(ctx))
   529  
   530  			tc.execute4(&ctx, dk)
   531  			// end block
   532  			staking.EndBlocker(ctx, sk)
   533  
   534  			coins, err = dk.WithdrawDelegationRewards(ctx, delAddr1, valOpAddr3)
   535  			require.Equal(suite.T(), types.ErrCodeEmptyValidatorDistInfo(), err)
   536  
   537  			coins, err = dk.WithdrawDelegationRewards(ctx, delAddr2, valOpAddr1)
   538  			require.Equal(suite.T(), types.ErrCodeEmptyDelegationDistInfo(), err)
   539  
   540  			coins, err = dk.WithdrawDelegationRewards(ctx, delAddr1, valOpAddr1)
   541  			require.Equal(suite.T(), tc.afterWithdrawReferenceCount, dk.GetValidatorHistoricalReferenceCount(ctx))
   542  			require.Equal(suite.T(), tc.coins, coins)
   543  			require.Equal(suite.T(), tc.err, err)
   544  		})
   545  	}
   546  }
   547  
   548  func TestInvalidDelegation(t *testing.T) {
   549  	communityTax := sdk.NewDecWithPrec(2, 2)
   550  	// Cannot init when distribution proposal valid
   551  	ctx, _, _, dk, sk, _, _ := CreateTestInputAdvanced(t, false, 1000, communityTax)
   552  	DoCreateValidator(t, ctx, sk, valOpAddr1, valConsPk1)
   553  	dk.initializeDelegation(ctx, valOpAddr1, delAddr1)
   554  	require.False(t, dk.HasDelegatorStartingInfo(ctx, valOpAddr1, delAddr1))
   555  
   556  	// Cannot init when distribution proposal valid
   557  	val := dk.stakingKeeper.Validator(ctx, valOpAddr1)
   558  	del := dk.stakingKeeper.Delegator(ctx, delAddr1)
   559  	dk.initExistedDelegationStartInfo(ctx, val, del)
   560  	require.False(t, dk.HasDelegatorStartingInfo(ctx, valOpAddr1, delAddr1))
   561  
   562  	// init delegation
   563  	ctx.SetBlockHeight(ctx.BlockHeight() + 1)
   564  	ctx.SetBlockTime(time.Now())
   565  	DoDeposit(t, ctx, sk, delAddr1, sdk.NewCoin(sk.BondDenom(ctx), sdk.NewInt(1)))
   566  	valOpAddrs := []sdk.ValAddress{valOpAddr1}
   567  	DoAddShares(t, ctx, sk, delAddr1, valOpAddrs)
   568  	staking.EndBlocker(ctx, sk)
   569  
   570  	// check calculateDelegationRewardsBetween startingPeriod > endingPeriod
   571  	newDec, _ := sdk.NewDecFromStr("1")
   572  	period := types.DelegatorStartingInfo{
   573  		PreviousPeriod: uint64(100),
   574  		Stake:          newDec,
   575  		Height:         10,
   576  	}
   577  	dk.SetDelegatorStartingInfo(ctx, valOpAddr1, delAddr1, period)
   578  	panicFunc := func() {
   579  		dk.calculateDelegationRewards(ctx, val, delAddr1, 1)
   580  	}
   581  	assert.PanicsWithValue(t, "startingPeriod cannot be greater than endingPeriod", panicFunc)
   582  
   583  	// check calculateDelegationRewards stake.GT(del.GetLastAddedShares())
   584  	newDec, _ = sdk.NewDecFromStr("100000000000000")
   585  	period = types.DelegatorStartingInfo{
   586  		PreviousPeriod: uint64(100),
   587  		Stake:          newDec,
   588  		Height:         10,
   589  	}
   590  	dk.SetDelegatorStartingInfo(ctx, valOpAddr1, delAddr1, period)
   591  	panicFunc = func() {
   592  		dk.calculateDelegationRewards(ctx, val, delAddr1, 1)
   593  	}
   594  	assert.Panics(t, panicFunc)
   595  }
   596  
   597  func TestIncrementValidatorPeriod(t *testing.T) {
   598  	communityTax := sdk.NewDecWithPrec(2, 2)
   599  	ctx, _, _, dk, sk, _, _ := CreateTestInputAdvanced(t, false, 1000, communityTax)
   600  
   601  	// create validator
   602  	DoCreateValidator(t, ctx, sk, valOpAddr1, valConsPk1)
   603  	val := sk.Validator(ctx, valOpAddr1)
   604  
   605  	// distribution type invalid, No Panic
   606  	noPanicFunc := func() {
   607  		dk.incrementValidatorPeriod(ctx, val)
   608  	}
   609  	assert.NotPanics(t, noPanicFunc)
   610  }
   611  
   612  func TestRewardToCommunity(t *testing.T) {
   613  	communityTax := sdk.NewDecWithPrec(2, 2)
   614  	ctx, _, _, dk, sk, _, _ := CreateTestInputAdvanced(t, false, 1000, communityTax)
   615  	tmtypes.UnittestOnlySetMilestoneVenus2Height(-1)
   616  	dk.SetDistributionType(ctx, types.DistributionTypeOnChain)
   617  	dk.SetInitExistedValidatorFlag(ctx, true)
   618  
   619  	// create validator
   620  	DoCreateValidator(t, ctx, sk, valOpAddr1, valConsPk1)
   621  	newRate, _ := sdk.NewDecFromStr("0")
   622  	ctx.SetBlockTime(time.Now().UTC().Add(48 * time.Hour))
   623  	DoEditValidator(t, ctx, sk, valOpAddr1, newRate)
   624  	val := sk.Validator(ctx, valOpAddr1)
   625  
   626  	// allocate some rewards
   627  	tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(int64(20))}}
   628  	dk.AllocateTokensToValidator(ctx, val, tokens)
   629  
   630  	sk.SetValidator(ctx, stakingtypes.Validator{OperatorAddress: val.GetOperator(), DelegatorShares: sdk.NewDec(int64(0))})
   631  	val = sk.Validator(ctx, valOpAddr1)
   632  
   633  	beforeFeePool := dk.GetFeePool(ctx)
   634  	dk.incrementValidatorPeriod(ctx, val)
   635  	afterFeePool := dk.GetFeePool(ctx)
   636  	require.Equal(t, tokens, afterFeePool.CommunityPool.Sub(beforeFeePool.CommunityPool))
   637  }