github.com/Finschia/finschia-sdk@v0.48.1/x/staking/keeper/delegation_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/Finschia/finschia-sdk/simapp"
    11  	sdk "github.com/Finschia/finschia-sdk/types"
    12  	"github.com/Finschia/finschia-sdk/x/staking/keeper"
    13  	"github.com/Finschia/finschia-sdk/x/staking/teststaking"
    14  	"github.com/Finschia/finschia-sdk/x/staking/types"
    15  )
    16  
    17  // tests GetDelegation, GetDelegatorDelegations, SetDelegation, RemoveDelegation, GetDelegatorDelegations
    18  func TestDelegation(t *testing.T) {
    19  	_, app, ctx := createTestInput()
    20  
    21  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 3, sdk.NewInt(10000))
    22  	valAddrs := simapp.ConvertAddrsToValAddrs(addrDels)
    23  
    24  	// construct the validators
    25  	amts := []sdk.Int{sdk.NewInt(9), sdk.NewInt(8), sdk.NewInt(7)}
    26  	var validators [3]types.Validator
    27  	for i, amt := range amts {
    28  		validators[i] = teststaking.NewValidator(t, valAddrs[i], PKs[i])
    29  		validators[i], _ = validators[i].AddTokensFromDel(amt)
    30  	}
    31  
    32  	validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], true)
    33  	validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], true)
    34  	validators[2] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[2], true)
    35  
    36  	// first add a validators[0] to delegate too
    37  	bond1to1 := types.NewDelegation(addrDels[0], valAddrs[0], sdk.NewDec(9))
    38  
    39  	// check the empty keeper first
    40  	_, found := app.StakingKeeper.GetDelegation(ctx, addrDels[0], valAddrs[0])
    41  	require.False(t, found)
    42  
    43  	// set and retrieve a record
    44  	app.StakingKeeper.SetDelegation(ctx, bond1to1)
    45  	resBond, found := app.StakingKeeper.GetDelegation(ctx, addrDels[0], valAddrs[0])
    46  	require.True(t, found)
    47  	require.Equal(t, bond1to1, resBond)
    48  
    49  	// modify a records, save, and retrieve
    50  	bond1to1.Shares = sdk.NewDec(99)
    51  	app.StakingKeeper.SetDelegation(ctx, bond1to1)
    52  	resBond, found = app.StakingKeeper.GetDelegation(ctx, addrDels[0], valAddrs[0])
    53  	require.True(t, found)
    54  	require.Equal(t, bond1to1, resBond)
    55  
    56  	// add some more records
    57  	bond1to2 := types.NewDelegation(addrDels[0], valAddrs[1], sdk.NewDec(9))
    58  	bond1to3 := types.NewDelegation(addrDels[0], valAddrs[2], sdk.NewDec(9))
    59  	bond2to1 := types.NewDelegation(addrDels[1], valAddrs[0], sdk.NewDec(9))
    60  	bond2to2 := types.NewDelegation(addrDels[1], valAddrs[1], sdk.NewDec(9))
    61  	bond2to3 := types.NewDelegation(addrDels[1], valAddrs[2], sdk.NewDec(9))
    62  	app.StakingKeeper.SetDelegation(ctx, bond1to2)
    63  	app.StakingKeeper.SetDelegation(ctx, bond1to3)
    64  	app.StakingKeeper.SetDelegation(ctx, bond2to1)
    65  	app.StakingKeeper.SetDelegation(ctx, bond2to2)
    66  	app.StakingKeeper.SetDelegation(ctx, bond2to3)
    67  
    68  	// test all bond retrieve capabilities
    69  	resBonds := app.StakingKeeper.GetDelegatorDelegations(ctx, addrDels[0], 5)
    70  	require.Equal(t, 3, len(resBonds))
    71  	require.Equal(t, bond1to1, resBonds[0])
    72  	require.Equal(t, bond1to2, resBonds[1])
    73  	require.Equal(t, bond1to3, resBonds[2])
    74  	resBonds = app.StakingKeeper.GetAllDelegatorDelegations(ctx, addrDels[0])
    75  	require.Equal(t, 3, len(resBonds))
    76  	resBonds = app.StakingKeeper.GetDelegatorDelegations(ctx, addrDels[0], 2)
    77  	require.Equal(t, 2, len(resBonds))
    78  	resBonds = app.StakingKeeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
    79  	require.Equal(t, 3, len(resBonds))
    80  	require.Equal(t, bond2to1, resBonds[0])
    81  	require.Equal(t, bond2to2, resBonds[1])
    82  	require.Equal(t, bond2to3, resBonds[2])
    83  	allBonds := app.StakingKeeper.GetAllDelegations(ctx)
    84  	require.Equal(t, 6, len(allBonds))
    85  	require.Equal(t, bond1to1, allBonds[0])
    86  	require.Equal(t, bond1to2, allBonds[1])
    87  	require.Equal(t, bond1to3, allBonds[2])
    88  	require.Equal(t, bond2to1, allBonds[3])
    89  	require.Equal(t, bond2to2, allBonds[4])
    90  	require.Equal(t, bond2to3, allBonds[5])
    91  
    92  	resVals := app.StakingKeeper.GetDelegatorValidators(ctx, addrDels[0], 3)
    93  	require.Equal(t, 3, len(resVals))
    94  	resVals = app.StakingKeeper.GetDelegatorValidators(ctx, addrDels[1], 4)
    95  	require.Equal(t, 3, len(resVals))
    96  
    97  	for i := 0; i < 3; i++ {
    98  		resVal, err := app.StakingKeeper.GetDelegatorValidator(ctx, addrDels[0], valAddrs[i])
    99  		require.Nil(t, err)
   100  		require.Equal(t, valAddrs[i], resVal.GetOperator())
   101  
   102  		resVal, err = app.StakingKeeper.GetDelegatorValidator(ctx, addrDels[1], valAddrs[i])
   103  		require.Nil(t, err)
   104  		require.Equal(t, valAddrs[i], resVal.GetOperator())
   105  
   106  		resDels := app.StakingKeeper.GetValidatorDelegations(ctx, valAddrs[i])
   107  		require.Len(t, resDels, 2)
   108  	}
   109  
   110  	// test total bonded for single delegator
   111  	expBonded := bond1to1.Shares.Add(bond2to1.Shares).Add(bond1to3.Shares)
   112  	resDelBond := app.StakingKeeper.GetDelegatorBonded(ctx, addrDels[0])
   113  	require.Equal(t, expBonded, sdk.NewDecFromInt(resDelBond))
   114  
   115  	// delete a record
   116  	app.StakingKeeper.RemoveDelegation(ctx, bond2to3)
   117  	_, found = app.StakingKeeper.GetDelegation(ctx, addrDels[1], valAddrs[2])
   118  	require.False(t, found)
   119  	resBonds = app.StakingKeeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
   120  	require.Equal(t, 2, len(resBonds))
   121  	require.Equal(t, bond2to1, resBonds[0])
   122  	require.Equal(t, bond2to2, resBonds[1])
   123  
   124  	resBonds = app.StakingKeeper.GetAllDelegatorDelegations(ctx, addrDels[1])
   125  	require.Equal(t, 2, len(resBonds))
   126  
   127  	// delete all the records from delegator 2
   128  	app.StakingKeeper.RemoveDelegation(ctx, bond2to1)
   129  	app.StakingKeeper.RemoveDelegation(ctx, bond2to2)
   130  	_, found = app.StakingKeeper.GetDelegation(ctx, addrDels[1], valAddrs[0])
   131  	require.False(t, found)
   132  	_, found = app.StakingKeeper.GetDelegation(ctx, addrDels[1], valAddrs[1])
   133  	require.False(t, found)
   134  	resBonds = app.StakingKeeper.GetDelegatorDelegations(ctx, addrDels[1], 5)
   135  	require.Equal(t, 0, len(resBonds))
   136  }
   137  
   138  // tests Get/Set/Remove UnbondingDelegation
   139  func TestUnbondingDelegation(t *testing.T) {
   140  	_, app, ctx := createTestInput()
   141  
   142  	delAddrs := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(10000))
   143  	valAddrs := simapp.ConvertAddrsToValAddrs(delAddrs)
   144  
   145  	ubd := types.NewUnbondingDelegation(
   146  		delAddrs[0],
   147  		valAddrs[0],
   148  		0,
   149  		time.Unix(0, 0).UTC(),
   150  		sdk.NewInt(5),
   151  	)
   152  
   153  	// set and retrieve a record
   154  	app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
   155  	resUnbond, found := app.StakingKeeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
   156  	require.True(t, found)
   157  	require.Equal(t, ubd, resUnbond)
   158  
   159  	// modify a records, save, and retrieve
   160  	expUnbond := sdk.NewInt(21)
   161  	ubd.Entries[0].Balance = expUnbond
   162  	app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
   163  
   164  	resUnbonds := app.StakingKeeper.GetUnbondingDelegations(ctx, delAddrs[0], 5)
   165  	require.Equal(t, 1, len(resUnbonds))
   166  
   167  	resUnbonds = app.StakingKeeper.GetAllUnbondingDelegations(ctx, delAddrs[0])
   168  	require.Equal(t, 1, len(resUnbonds))
   169  
   170  	resUnbond, found = app.StakingKeeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
   171  	require.True(t, found)
   172  	require.Equal(t, ubd, resUnbond)
   173  
   174  	resDelUnbond := app.StakingKeeper.GetDelegatorUnbonding(ctx, delAddrs[0])
   175  	require.Equal(t, expUnbond, resDelUnbond)
   176  
   177  	// delete a record
   178  	app.StakingKeeper.RemoveUnbondingDelegation(ctx, ubd)
   179  	_, found = app.StakingKeeper.GetUnbondingDelegation(ctx, delAddrs[0], valAddrs[0])
   180  	require.False(t, found)
   181  
   182  	resUnbonds = app.StakingKeeper.GetUnbondingDelegations(ctx, delAddrs[0], 5)
   183  	require.Equal(t, 0, len(resUnbonds))
   184  
   185  	resUnbonds = app.StakingKeeper.GetAllUnbondingDelegations(ctx, delAddrs[0])
   186  	require.Equal(t, 0, len(resUnbonds))
   187  }
   188  
   189  func TestUnbondDelegation(t *testing.T) {
   190  	_, app, ctx := createTestInput()
   191  
   192  	delAddrs := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.NewInt(10000))
   193  	valAddrs := simapp.ConvertAddrsToValAddrs(delAddrs)
   194  
   195  	startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   196  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   197  
   198  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens))))
   199  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   200  
   201  	// create a validator and a delegator to that validator
   202  	// note this validator starts not-bonded
   203  	validator := teststaking.NewValidator(t, valAddrs[0], PKs[0])
   204  
   205  	validator, issuedShares := validator.AddTokensFromDel(startTokens)
   206  	require.Equal(t, startTokens, issuedShares.RoundInt())
   207  
   208  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   209  
   210  	delegation := types.NewDelegation(delAddrs[0], valAddrs[0], issuedShares)
   211  	app.StakingKeeper.SetDelegation(ctx, delegation)
   212  
   213  	bondTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 6)
   214  	amount, err := app.StakingKeeper.Unbond(ctx, delAddrs[0], valAddrs[0], bondTokens.ToDec())
   215  	require.NoError(t, err)
   216  	require.Equal(t, bondTokens, amount) // shares to be added to an unbonding delegation
   217  
   218  	delegation, found := app.StakingKeeper.GetDelegation(ctx, delAddrs[0], valAddrs[0])
   219  	require.True(t, found)
   220  	validator, found = app.StakingKeeper.GetValidator(ctx, valAddrs[0])
   221  	require.True(t, found)
   222  
   223  	remainingTokens := startTokens.Sub(bondTokens)
   224  	require.Equal(t, remainingTokens, delegation.Shares.RoundInt())
   225  	require.Equal(t, remainingTokens, validator.BondedTokens())
   226  }
   227  
   228  func TestUnbondingDelegationsMaxEntries(t *testing.T) {
   229  	_, app, ctx := createTestInput()
   230  
   231  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.NewInt(10000))
   232  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   233  
   234  	startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   235  
   236  	bondDenom := app.StakingKeeper.BondDenom(ctx)
   237  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   238  
   239  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
   240  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   241  
   242  	// create a validator and a delegator to that validator
   243  	validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
   244  
   245  	validator, issuedShares := validator.AddTokensFromDel(startTokens)
   246  	require.Equal(t, startTokens, issuedShares.RoundInt())
   247  
   248  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   249  	require.True(sdk.IntEq(t, startTokens, validator.BondedTokens()))
   250  	require.True(t, validator.IsBonded())
   251  
   252  	delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares)
   253  	app.StakingKeeper.SetDelegation(ctx, delegation)
   254  
   255  	maxEntries := app.StakingKeeper.MaxEntries(ctx)
   256  
   257  	oldBonded := app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
   258  	oldNotBonded := app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
   259  
   260  	// should all pass
   261  	var completionTime time.Time
   262  	for i := uint32(0); i < maxEntries; i++ {
   263  		var err error
   264  		completionTime, err = app.StakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1))
   265  		require.NoError(t, err)
   266  	}
   267  
   268  	newBonded := app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
   269  	newNotBonded := app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
   270  	require.True(sdk.IntEq(t, newBonded, oldBonded.SubRaw(int64(maxEntries))))
   271  	require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.AddRaw(int64(maxEntries))))
   272  
   273  	oldBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
   274  	oldNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
   275  
   276  	// an additional unbond should fail due to max entries
   277  	_, err := app.StakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1))
   278  	require.Error(t, err)
   279  
   280  	newBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
   281  	newNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
   282  
   283  	require.True(sdk.IntEq(t, newBonded, oldBonded))
   284  	require.True(sdk.IntEq(t, newNotBonded, oldNotBonded))
   285  
   286  	// mature unbonding delegations
   287  	ctx = ctx.WithBlockTime(completionTime)
   288  	_, err = app.StakingKeeper.CompleteUnbonding(ctx, addrDels[0], addrVals[0])
   289  	require.NoError(t, err)
   290  
   291  	newBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
   292  	newNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
   293  	require.True(sdk.IntEq(t, newBonded, oldBonded))
   294  	require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.SubRaw(int64(maxEntries))))
   295  
   296  	oldNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
   297  
   298  	// unbonding  should work again
   299  	_, err = app.StakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1))
   300  	require.NoError(t, err)
   301  
   302  	newBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount
   303  	newNotBonded = app.BankKeeper.GetBalance(ctx, app.StakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount
   304  	require.True(sdk.IntEq(t, newBonded, oldBonded.SubRaw(1)))
   305  	require.True(sdk.IntEq(t, newNotBonded, oldNotBonded.AddRaw(1)))
   306  }
   307  
   308  // // test undelegating self delegation from a validator pushing it below MinSelfDelegation
   309  // // shift it from the bonded to unbonding state and jailed
   310  func TestUndelegateSelfDelegationBelowMinSelfDelegation(t *testing.T) {
   311  	_, app, ctx := createTestInput()
   312  
   313  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.NewInt(10000))
   314  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   315  	delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   316  	delCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), delTokens))
   317  
   318  	// create a validator with a self-delegation
   319  	validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
   320  
   321  	validator.MinSelfDelegation = delTokens
   322  	validator, issuedShares := validator.AddTokensFromDel(delTokens)
   323  	require.Equal(t, delTokens, issuedShares.RoundInt())
   324  
   325  	// add bonded tokens to pool for delegations
   326  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   327  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), delCoins))
   328  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   329  
   330  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   331  	app.StakingKeeper.SetValidatorByConsAddr(ctx, validator)
   332  	require.True(t, validator.IsBonded())
   333  
   334  	selfDelegation := types.NewDelegation(sdk.AccAddress(addrVals[0].Bytes()), addrVals[0], issuedShares)
   335  	app.StakingKeeper.SetDelegation(ctx, selfDelegation)
   336  
   337  	// add bonded tokens to pool for delegations
   338  	bondedPool := app.StakingKeeper.GetBondedPool(ctx)
   339  	require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
   340  	app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
   341  
   342  	// create a second delegation to this validator
   343  	app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validator)
   344  	validator, issuedShares = validator.AddTokensFromDel(delTokens)
   345  	require.True(t, validator.IsBonded())
   346  	require.Equal(t, delTokens, issuedShares.RoundInt())
   347  
   348  	// add bonded tokens to pool for delegations
   349  	require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
   350  	app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
   351  
   352  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   353  	delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares)
   354  	app.StakingKeeper.SetDelegation(ctx, delegation)
   355  
   356  	val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
   357  	_, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], app.StakingKeeper.TokensFromConsensusPower(ctx, 6).ToDec())
   358  	require.NoError(t, err)
   359  
   360  	// end block
   361  	applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
   362  
   363  	validator, found := app.StakingKeeper.GetValidator(ctx, addrVals[0])
   364  	require.True(t, found)
   365  	require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 14), validator.Tokens)
   366  	require.Equal(t, types.Unbonding, validator.Status)
   367  	require.True(t, validator.Jailed)
   368  }
   369  
   370  func TestUndelegateFromUnbondingValidator(t *testing.T) {
   371  	_, app, ctx := createTestInput()
   372  	delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   373  	delCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), delTokens))
   374  
   375  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(0))
   376  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   377  
   378  	// create a validator with a self-delegation
   379  	validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
   380  	app.StakingKeeper.SetValidatorByConsAddr(ctx, validator)
   381  
   382  	validator, issuedShares := validator.AddTokensFromDel(delTokens)
   383  	require.Equal(t, delTokens, issuedShares.RoundInt())
   384  
   385  	// add bonded tokens to pool for delegations
   386  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   387  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), delCoins))
   388  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   389  
   390  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   391  	require.True(t, validator.IsBonded())
   392  
   393  	selfDelegation := types.NewDelegation(addrVals[0].Bytes(), addrVals[0], issuedShares)
   394  	app.StakingKeeper.SetDelegation(ctx, selfDelegation)
   395  
   396  	// add bonded tokens to pool for delegations
   397  	bondedPool := app.StakingKeeper.GetBondedPool(ctx)
   398  	require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
   399  	app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
   400  
   401  	// create a second delegation to this validator
   402  	app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validator)
   403  
   404  	validator, issuedShares = validator.AddTokensFromDel(delTokens)
   405  	require.Equal(t, delTokens, issuedShares.RoundInt())
   406  
   407  	require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
   408  	app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
   409  
   410  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   411  	delegation := types.NewDelegation(addrDels[1], addrVals[0], issuedShares)
   412  	app.StakingKeeper.SetDelegation(ctx, delegation)
   413  
   414  	require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
   415  	app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
   416  
   417  	header := ctx.BlockHeader()
   418  	blockHeight := int64(10)
   419  	header.Height = blockHeight
   420  	blockTime := time.Unix(333, 0)
   421  	header.Time = blockTime
   422  	ctx = ctx.WithBlockHeader(header)
   423  
   424  	// unbond the all self-delegation to put validator in unbonding state
   425  	val0AccAddr := sdk.AccAddress(addrVals[0])
   426  	_, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec())
   427  	require.NoError(t, err)
   428  
   429  	// end block
   430  	applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
   431  
   432  	validator, found := app.StakingKeeper.GetValidator(ctx, addrVals[0])
   433  	require.True(t, found)
   434  	require.Equal(t, blockHeight, validator.UnbondingHeight)
   435  	params := app.StakingKeeper.GetParams(ctx)
   436  	require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingTime))
   437  
   438  	blockHeight2 := int64(20)
   439  	blockTime2 := time.Unix(444, 0).UTC()
   440  	ctx = ctx.WithBlockHeight(blockHeight2)
   441  	ctx = ctx.WithBlockTime(blockTime2)
   442  
   443  	// unbond some of the other delegation's shares
   444  	_, err = app.StakingKeeper.Undelegate(ctx, addrDels[1], addrVals[0], sdk.NewDec(6))
   445  	require.NoError(t, err)
   446  
   447  	// retrieve the unbonding delegation
   448  	ubd, found := app.StakingKeeper.GetUnbondingDelegation(ctx, addrDels[1], addrVals[0])
   449  	require.True(t, found)
   450  	require.Len(t, ubd.Entries, 1)
   451  	require.True(t, ubd.Entries[0].Balance.Equal(sdk.NewInt(6)))
   452  	assert.Equal(t, blockHeight2, ubd.Entries[0].CreationHeight)
   453  	assert.True(t, blockTime2.Add(params.UnbondingTime).Equal(ubd.Entries[0].CompletionTime))
   454  }
   455  
   456  func TestUndelegateFromUnbondedValidator(t *testing.T) {
   457  	_, app, ctx := createTestInput()
   458  	delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   459  	delCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), delTokens))
   460  
   461  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(0))
   462  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   463  
   464  	// add bonded tokens to pool for delegations
   465  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   466  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), delCoins))
   467  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   468  
   469  	// create a validator with a self-delegation
   470  	validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
   471  	app.StakingKeeper.SetValidatorByConsAddr(ctx, validator)
   472  
   473  	valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   474  	validator, issuedShares := validator.AddTokensFromDel(valTokens)
   475  	require.Equal(t, valTokens, issuedShares.RoundInt())
   476  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   477  	require.True(t, validator.IsBonded())
   478  
   479  	val0AccAddr := sdk.AccAddress(addrVals[0])
   480  	selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
   481  	app.StakingKeeper.SetDelegation(ctx, selfDelegation)
   482  
   483  	// add bonded tokens to pool for delegations
   484  	bondedPool := app.StakingKeeper.GetBondedPool(ctx)
   485  	require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
   486  	app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
   487  
   488  	// create a second delegation to this validator
   489  	app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validator)
   490  	validator, issuedShares = validator.AddTokensFromDel(delTokens)
   491  	require.Equal(t, delTokens, issuedShares.RoundInt())
   492  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   493  	require.True(t, validator.IsBonded())
   494  	delegation := types.NewDelegation(addrDels[1], addrVals[0], issuedShares)
   495  	app.StakingKeeper.SetDelegation(ctx, delegation)
   496  
   497  	ctx = ctx.WithBlockHeight(10)
   498  	ctx = ctx.WithBlockTime(time.Unix(333, 0))
   499  
   500  	// unbond the all self-delegation to put validator in unbonding state
   501  	_, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec())
   502  	require.NoError(t, err)
   503  
   504  	// end block
   505  	applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
   506  
   507  	validator, found := app.StakingKeeper.GetValidator(ctx, addrVals[0])
   508  	require.True(t, found)
   509  	require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight)
   510  	params := app.StakingKeeper.GetParams(ctx)
   511  	require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingTime))
   512  
   513  	// unbond the validator
   514  	ctx = ctx.WithBlockTime(validator.UnbondingTime)
   515  	app.StakingKeeper.UnbondAllMatureValidators(ctx)
   516  
   517  	// Make sure validator is still in state because there is still an outstanding delegation
   518  	validator, found = app.StakingKeeper.GetValidator(ctx, addrVals[0])
   519  	require.True(t, found)
   520  	require.Equal(t, validator.Status, types.Unbonded)
   521  
   522  	// unbond some of the other delegation's shares
   523  	unbondTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 6)
   524  	_, err = app.StakingKeeper.Undelegate(ctx, addrDels[1], addrVals[0], unbondTokens.ToDec())
   525  	require.NoError(t, err)
   526  
   527  	// unbond rest of the other delegation's shares
   528  	remainingTokens := delTokens.Sub(unbondTokens)
   529  	_, err = app.StakingKeeper.Undelegate(ctx, addrDels[1], addrVals[0], remainingTokens.ToDec())
   530  	require.NoError(t, err)
   531  
   532  	//  now validator should be deleted from state
   533  	validator, found = app.StakingKeeper.GetValidator(ctx, addrVals[0])
   534  	require.False(t, found, "%v", validator)
   535  }
   536  
   537  func TestUnbondingAllDelegationFromValidator(t *testing.T) {
   538  	_, app, ctx := createTestInput()
   539  	delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   540  	delCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), delTokens))
   541  
   542  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(0))
   543  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   544  
   545  	// add bonded tokens to pool for delegations
   546  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   547  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), delCoins))
   548  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   549  
   550  	// create a validator with a self-delegation
   551  	validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
   552  	app.StakingKeeper.SetValidatorByConsAddr(ctx, validator)
   553  
   554  	valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   555  	validator, issuedShares := validator.AddTokensFromDel(valTokens)
   556  	require.Equal(t, valTokens, issuedShares.RoundInt())
   557  
   558  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   559  	require.True(t, validator.IsBonded())
   560  	val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
   561  
   562  	selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
   563  	app.StakingKeeper.SetDelegation(ctx, selfDelegation)
   564  
   565  	// create a second delegation to this validator
   566  	app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validator)
   567  	validator, issuedShares = validator.AddTokensFromDel(delTokens)
   568  	require.Equal(t, delTokens, issuedShares.RoundInt())
   569  
   570  	// add bonded tokens to pool for delegations
   571  	bondedPool := app.StakingKeeper.GetBondedPool(ctx)
   572  	require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), delCoins))
   573  	app.AccountKeeper.SetModuleAccount(ctx, bondedPool)
   574  
   575  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   576  	require.True(t, validator.IsBonded())
   577  
   578  	delegation := types.NewDelegation(addrDels[1], addrVals[0], issuedShares)
   579  	app.StakingKeeper.SetDelegation(ctx, delegation)
   580  
   581  	ctx = ctx.WithBlockHeight(10)
   582  	ctx = ctx.WithBlockTime(time.Unix(333, 0))
   583  
   584  	// unbond the all self-delegation to put validator in unbonding state
   585  	_, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], valTokens.ToDec())
   586  	require.NoError(t, err)
   587  
   588  	// end block
   589  	applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
   590  
   591  	// unbond all the remaining delegation
   592  	_, err = app.StakingKeeper.Undelegate(ctx, addrDels[1], addrVals[0], delTokens.ToDec())
   593  	require.NoError(t, err)
   594  
   595  	// validator should still be in state and still be in unbonding state
   596  	validator, found := app.StakingKeeper.GetValidator(ctx, addrVals[0])
   597  	require.True(t, found)
   598  	require.Equal(t, validator.Status, types.Unbonding)
   599  
   600  	// unbond the validator
   601  	ctx = ctx.WithBlockTime(validator.UnbondingTime)
   602  	app.StakingKeeper.UnbondAllMatureValidators(ctx)
   603  
   604  	// validator should now be deleted from state
   605  	_, found = app.StakingKeeper.GetValidator(ctx, addrVals[0])
   606  	require.False(t, found)
   607  }
   608  
   609  // Make sure that that the retrieving the delegations doesn't affect the state
   610  func TestGetRedelegationsFromSrcValidator(t *testing.T) {
   611  	_, app, ctx := createTestInput()
   612  
   613  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(0))
   614  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   615  
   616  	rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0,
   617  		time.Unix(0, 0), sdk.NewInt(5),
   618  		sdk.NewDec(5))
   619  
   620  	// set and retrieve a record
   621  	app.StakingKeeper.SetRedelegation(ctx, rd)
   622  	resBond, found := app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
   623  	require.True(t, found)
   624  
   625  	// get the redelegations one time
   626  	redelegations := app.StakingKeeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
   627  	require.Equal(t, 1, len(redelegations))
   628  	require.Equal(t, redelegations[0], resBond)
   629  
   630  	// get the redelegations a second time, should be exactly the same
   631  	redelegations = app.StakingKeeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
   632  	require.Equal(t, 1, len(redelegations))
   633  	require.Equal(t, redelegations[0], resBond)
   634  }
   635  
   636  // tests Get/Set/Remove/Has UnbondingDelegation
   637  func TestRedelegation(t *testing.T) {
   638  	_, app, ctx := createTestInput()
   639  
   640  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(0))
   641  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   642  
   643  	rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0,
   644  		time.Unix(0, 0).UTC(), sdk.NewInt(5),
   645  		sdk.NewDec(5))
   646  
   647  	// test shouldn't have and redelegations
   648  	has := app.StakingKeeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1])
   649  	require.False(t, has)
   650  
   651  	// set and retrieve a record
   652  	app.StakingKeeper.SetRedelegation(ctx, rd)
   653  	resRed, found := app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
   654  	require.True(t, found)
   655  
   656  	redelegations := app.StakingKeeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
   657  	require.Equal(t, 1, len(redelegations))
   658  	require.Equal(t, redelegations[0], resRed)
   659  
   660  	redelegations = app.StakingKeeper.GetRedelegations(ctx, addrDels[0], 5)
   661  	require.Equal(t, 1, len(redelegations))
   662  	require.Equal(t, redelegations[0], resRed)
   663  
   664  	redelegations = app.StakingKeeper.GetAllRedelegations(ctx, addrDels[0], nil, nil)
   665  	require.Equal(t, 1, len(redelegations))
   666  	require.Equal(t, redelegations[0], resRed)
   667  
   668  	// check if has the redelegation
   669  	has = app.StakingKeeper.HasReceivingRedelegation(ctx, addrDels[0], addrVals[1])
   670  	require.True(t, has)
   671  
   672  	// modify a records, save, and retrieve
   673  	rd.Entries[0].SharesDst = sdk.NewDec(21)
   674  	app.StakingKeeper.SetRedelegation(ctx, rd)
   675  
   676  	resRed, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
   677  	require.True(t, found)
   678  	require.Equal(t, rd, resRed)
   679  
   680  	redelegations = app.StakingKeeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0])
   681  	require.Equal(t, 1, len(redelegations))
   682  	require.Equal(t, redelegations[0], resRed)
   683  
   684  	redelegations = app.StakingKeeper.GetRedelegations(ctx, addrDels[0], 5)
   685  	require.Equal(t, 1, len(redelegations))
   686  	require.Equal(t, redelegations[0], resRed)
   687  
   688  	// delete a record
   689  	app.StakingKeeper.RemoveRedelegation(ctx, rd)
   690  	_, found = app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
   691  	require.False(t, found)
   692  
   693  	redelegations = app.StakingKeeper.GetRedelegations(ctx, addrDels[0], 5)
   694  	require.Equal(t, 0, len(redelegations))
   695  
   696  	redelegations = app.StakingKeeper.GetAllRedelegations(ctx, addrDels[0], nil, nil)
   697  	require.Equal(t, 0, len(redelegations))
   698  }
   699  
   700  func TestRedelegateToSameValidator(t *testing.T) {
   701  	_, app, ctx := createTestInput()
   702  
   703  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.NewInt(0))
   704  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   705  
   706  	valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   707  	startCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), valTokens))
   708  
   709  	// add bonded tokens to pool for delegations
   710  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   711  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), startCoins))
   712  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   713  
   714  	// create a validator with a self-delegation
   715  	validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
   716  	validator, issuedShares := validator.AddTokensFromDel(valTokens)
   717  	require.Equal(t, valTokens, issuedShares.RoundInt())
   718  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   719  	require.True(t, validator.IsBonded())
   720  
   721  	val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
   722  	selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
   723  	app.StakingKeeper.SetDelegation(ctx, selfDelegation)
   724  
   725  	_, err := app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[0], sdk.NewDec(5))
   726  	require.Error(t, err)
   727  }
   728  
   729  func TestRedelegationMaxEntries(t *testing.T) {
   730  	_, app, ctx := createTestInput()
   731  
   732  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(0))
   733  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   734  
   735  	startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 20)
   736  	startCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens))
   737  
   738  	// add bonded tokens to pool for delegations
   739  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   740  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), startCoins))
   741  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   742  
   743  	// create a validator with a self-delegation
   744  	validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
   745  	valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   746  	validator, issuedShares := validator.AddTokensFromDel(valTokens)
   747  	require.Equal(t, valTokens, issuedShares.RoundInt())
   748  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   749  	val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
   750  	selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
   751  	app.StakingKeeper.SetDelegation(ctx, selfDelegation)
   752  
   753  	// create a second validator
   754  	validator2 := teststaking.NewValidator(t, addrVals[1], PKs[1])
   755  	validator2, issuedShares = validator2.AddTokensFromDel(valTokens)
   756  	require.Equal(t, valTokens, issuedShares.RoundInt())
   757  
   758  	validator2 = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator2, true)
   759  	require.Equal(t, types.Bonded, validator2.Status)
   760  
   761  	maxEntries := app.StakingKeeper.MaxEntries(ctx)
   762  
   763  	// redelegations should pass
   764  	var completionTime time.Time
   765  	for i := uint32(0); i < maxEntries; i++ {
   766  		var err error
   767  		completionTime, err = app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1))
   768  		require.NoError(t, err)
   769  	}
   770  
   771  	// an additional redelegation should fail due to max entries
   772  	_, err := app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1))
   773  	require.Error(t, err)
   774  
   775  	// mature redelegations
   776  	ctx = ctx.WithBlockTime(completionTime)
   777  	_, err = app.StakingKeeper.CompleteRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1])
   778  	require.NoError(t, err)
   779  
   780  	// redelegation should work again
   781  	_, err = app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], sdk.NewDec(1))
   782  	require.NoError(t, err)
   783  }
   784  
   785  func TestRedelegateSelfDelegation(t *testing.T) {
   786  	_, app, ctx := createTestInput()
   787  
   788  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(0))
   789  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   790  
   791  	startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 30)
   792  	startCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens))
   793  
   794  	// add bonded tokens to pool for delegations
   795  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   796  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), startCoins))
   797  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   798  
   799  	// create a validator with a self-delegation
   800  	validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
   801  	app.StakingKeeper.SetValidatorByConsAddr(ctx, validator)
   802  
   803  	valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   804  	validator, issuedShares := validator.AddTokensFromDel(valTokens)
   805  	require.Equal(t, valTokens, issuedShares.RoundInt())
   806  
   807  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   808  
   809  	val0AccAddr := sdk.AccAddress(addrVals[0])
   810  	selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
   811  	app.StakingKeeper.SetDelegation(ctx, selfDelegation)
   812  
   813  	// create a second validator
   814  	validator2 := teststaking.NewValidator(t, addrVals[1], PKs[1])
   815  	validator2, issuedShares = validator2.AddTokensFromDel(valTokens)
   816  	require.Equal(t, valTokens, issuedShares.RoundInt())
   817  	validator2 = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator2, true)
   818  	require.Equal(t, types.Bonded, validator2.Status)
   819  
   820  	// create a second delegation to validator 1
   821  	delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   822  	validator, issuedShares = validator.AddTokensFromDel(delTokens)
   823  	require.Equal(t, delTokens, issuedShares.RoundInt())
   824  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   825  
   826  	delegation := types.NewDelegation(addrDels[0], addrVals[0], issuedShares)
   827  	app.StakingKeeper.SetDelegation(ctx, delegation)
   828  
   829  	_, err := app.StakingKeeper.BeginRedelegation(ctx, val0AccAddr, addrVals[0], addrVals[1], delTokens.ToDec())
   830  	require.NoError(t, err)
   831  
   832  	// end block
   833  	applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2)
   834  
   835  	validator, found := app.StakingKeeper.GetValidator(ctx, addrVals[0])
   836  	require.True(t, found)
   837  	require.Equal(t, valTokens, validator.Tokens)
   838  	require.Equal(t, types.Unbonding, validator.Status)
   839  }
   840  
   841  func TestRedelegateFromUnbondingValidator(t *testing.T) {
   842  	_, app, ctx := createTestInput()
   843  
   844  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(0))
   845  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   846  
   847  	startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 30)
   848  	startCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens))
   849  
   850  	// add bonded tokens to pool for delegations
   851  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   852  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), startCoins))
   853  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   854  
   855  	// create a validator with a self-delegation
   856  	validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
   857  	app.StakingKeeper.SetValidatorByConsAddr(ctx, validator)
   858  
   859  	valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   860  	validator, issuedShares := validator.AddTokensFromDel(valTokens)
   861  	require.Equal(t, valTokens, issuedShares.RoundInt())
   862  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   863  	val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
   864  	selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
   865  	app.StakingKeeper.SetDelegation(ctx, selfDelegation)
   866  
   867  	// create a second delegation to this validator
   868  	app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validator)
   869  	delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   870  	validator, issuedShares = validator.AddTokensFromDel(delTokens)
   871  	require.Equal(t, delTokens, issuedShares.RoundInt())
   872  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   873  	delegation := types.NewDelegation(addrDels[1], addrVals[0], issuedShares)
   874  	app.StakingKeeper.SetDelegation(ctx, delegation)
   875  
   876  	// create a second validator
   877  	validator2 := teststaking.NewValidator(t, addrVals[1], PKs[1])
   878  	validator2, issuedShares = validator2.AddTokensFromDel(valTokens)
   879  	require.Equal(t, valTokens, issuedShares.RoundInt())
   880  	validator2 = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator2, true)
   881  
   882  	header := ctx.BlockHeader()
   883  	blockHeight := int64(10)
   884  	header.Height = blockHeight
   885  	blockTime := time.Unix(333, 0)
   886  	header.Time = blockTime
   887  	ctx = ctx.WithBlockHeader(header)
   888  
   889  	// unbond the all self-delegation to put validator in unbonding state
   890  	_, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec())
   891  	require.NoError(t, err)
   892  
   893  	// end block
   894  	applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
   895  
   896  	validator, found := app.StakingKeeper.GetValidator(ctx, addrVals[0])
   897  	require.True(t, found)
   898  	require.Equal(t, blockHeight, validator.UnbondingHeight)
   899  	params := app.StakingKeeper.GetParams(ctx)
   900  	require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingTime))
   901  
   902  	// change the context
   903  	header = ctx.BlockHeader()
   904  	blockHeight2 := int64(20)
   905  	header.Height = blockHeight2
   906  	blockTime2 := time.Unix(444, 0)
   907  	header.Time = blockTime2
   908  	ctx = ctx.WithBlockHeader(header)
   909  
   910  	// unbond some of the other delegation's shares
   911  	redelegateTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 6)
   912  	_, err = app.StakingKeeper.BeginRedelegation(ctx, addrDels[1], addrVals[0], addrVals[1], redelegateTokens.ToDec())
   913  	require.NoError(t, err)
   914  
   915  	// retrieve the unbonding delegation
   916  	ubd, found := app.StakingKeeper.GetRedelegation(ctx, addrDels[1], addrVals[0], addrVals[1])
   917  	require.True(t, found)
   918  	require.Len(t, ubd.Entries, 1)
   919  	assert.Equal(t, blockHeight, ubd.Entries[0].CreationHeight)
   920  	assert.True(t, blockTime.Add(params.UnbondingTime).Equal(ubd.Entries[0].CompletionTime))
   921  }
   922  
   923  func TestRedelegateFromUnbondedValidator(t *testing.T) {
   924  	_, app, ctx := createTestInput()
   925  
   926  	addrDels := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(0))
   927  	addrVals := simapp.ConvertAddrsToValAddrs(addrDels)
   928  
   929  	startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 30)
   930  	startCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens))
   931  
   932  	// add bonded tokens to pool for delegations
   933  	notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
   934  	require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), startCoins))
   935  	app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
   936  
   937  	// create a validator with a self-delegation
   938  	validator := teststaking.NewValidator(t, addrVals[0], PKs[0])
   939  	app.StakingKeeper.SetValidatorByConsAddr(ctx, validator)
   940  
   941  	valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   942  	validator, issuedShares := validator.AddTokensFromDel(valTokens)
   943  	require.Equal(t, valTokens, issuedShares.RoundInt())
   944  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   945  	val0AccAddr := sdk.AccAddress(addrVals[0].Bytes())
   946  	selfDelegation := types.NewDelegation(val0AccAddr, addrVals[0], issuedShares)
   947  	app.StakingKeeper.SetDelegation(ctx, selfDelegation)
   948  
   949  	// create a second delegation to this validator
   950  	app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validator)
   951  	delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
   952  	validator, issuedShares = validator.AddTokensFromDel(delTokens)
   953  	require.Equal(t, delTokens, issuedShares.RoundInt())
   954  	validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
   955  	delegation := types.NewDelegation(addrDels[1], addrVals[0], issuedShares)
   956  	app.StakingKeeper.SetDelegation(ctx, delegation)
   957  
   958  	// create a second validator
   959  	validator2 := teststaking.NewValidator(t, addrVals[1], PKs[1])
   960  	validator2, issuedShares = validator2.AddTokensFromDel(valTokens)
   961  	require.Equal(t, valTokens, issuedShares.RoundInt())
   962  	validator2 = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator2, true)
   963  	require.Equal(t, types.Bonded, validator2.Status)
   964  
   965  	ctx = ctx.WithBlockHeight(10)
   966  	ctx = ctx.WithBlockTime(time.Unix(333, 0))
   967  
   968  	// unbond the all self-delegation to put validator in unbonding state
   969  	_, err := app.StakingKeeper.Undelegate(ctx, val0AccAddr, addrVals[0], delTokens.ToDec())
   970  	require.NoError(t, err)
   971  
   972  	// end block
   973  	applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1)
   974  
   975  	validator, found := app.StakingKeeper.GetValidator(ctx, addrVals[0])
   976  	require.True(t, found)
   977  	require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight)
   978  	params := app.StakingKeeper.GetParams(ctx)
   979  	require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingTime))
   980  
   981  	// unbond the validator
   982  	app.StakingKeeper.UnbondingToUnbonded(ctx, validator)
   983  
   984  	// redelegate some of the delegation's shares
   985  	redelegationTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 6)
   986  	_, err = app.StakingKeeper.BeginRedelegation(ctx, addrDels[1], addrVals[0], addrVals[1], redelegationTokens.ToDec())
   987  	require.NoError(t, err)
   988  
   989  	// no red should have been found
   990  	red, found := app.StakingKeeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
   991  	require.False(t, found, "%v", red)
   992  }