github.com/cosmos/cosmos-sdk@v0.50.10/x/staking/keeper/unbonding_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"time"
     5  
     6  	"cosmossdk.io/math"
     7  
     8  	addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
     9  	sdk "github.com/cosmos/cosmos-sdk/types"
    10  	"github.com/cosmos/cosmos-sdk/x/staking/testutil"
    11  	"github.com/cosmos/cosmos-sdk/x/staking/types"
    12  )
    13  
    14  func (s *KeeperTestSuite) TestIncrementUnbondingID() {
    15  	for i := 1; i < 10; i++ {
    16  		id, err := s.stakingKeeper.IncrementUnbondingID(s.ctx)
    17  		s.Require().NoError(err)
    18  		s.Require().Equal(uint64(i), id)
    19  	}
    20  }
    21  
    22  func (s *KeeperTestSuite) TestUnbondingTypeAccessors() {
    23  	require := s.Require()
    24  	cases := []struct {
    25  		exists   bool
    26  		name     string
    27  		expected types.UnbondingType
    28  	}{
    29  		{
    30  			name:     "existing 1",
    31  			exists:   true,
    32  			expected: types.UnbondingType_UnbondingDelegation,
    33  		},
    34  		{
    35  			name:     "existing 2",
    36  			exists:   true,
    37  			expected: types.UnbondingType_Redelegation,
    38  		},
    39  		{
    40  			name:   "not existing",
    41  			exists: false,
    42  		},
    43  	}
    44  
    45  	for i, tc := range cases {
    46  		s.Run(tc.name, func() {
    47  			if tc.exists {
    48  				require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, uint64(i), tc.expected))
    49  			}
    50  
    51  			unbondingType, err := s.stakingKeeper.GetUnbondingType(s.ctx, uint64(i))
    52  			if tc.exists {
    53  				require.NoError(err)
    54  				require.Equal(tc.expected, unbondingType)
    55  			} else {
    56  				require.ErrorIs(err, types.ErrNoUnbondingType)
    57  			}
    58  		})
    59  	}
    60  }
    61  
    62  func (s *KeeperTestSuite) TestUnbondingDelegationByUnbondingIDAccessors() {
    63  	delAddrs, valAddrs := createValAddrs(2)
    64  	require := s.Require()
    65  
    66  	type exists struct {
    67  		setUnbondingDelegation              bool
    68  		setUnbondingDelegationByUnbondingID bool
    69  	}
    70  
    71  	cases := []struct {
    72  		exists   exists
    73  		name     string
    74  		expected types.UnbondingDelegation
    75  	}{
    76  		{
    77  			name:   "existing 1",
    78  			exists: exists{true, true},
    79  			expected: types.NewUnbondingDelegation(
    80  				delAddrs[0],
    81  				valAddrs[0],
    82  				0,
    83  				time.Unix(0, 0).UTC(),
    84  				math.NewInt(5),
    85  				0,
    86  				addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"),
    87  			),
    88  		},
    89  		{
    90  			name:   "not existing 1",
    91  			exists: exists{false, true},
    92  			expected: types.NewUnbondingDelegation(
    93  				delAddrs[1],
    94  				valAddrs[1],
    95  				0,
    96  				time.Unix(0, 0).UTC(),
    97  				math.NewInt(5),
    98  				0,
    99  				addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"),
   100  			),
   101  		},
   102  		{
   103  			name:   "not existing 2",
   104  			exists: exists{false, false},
   105  			expected: types.NewUnbondingDelegation(
   106  				delAddrs[0],
   107  				valAddrs[0],
   108  				0,
   109  				time.Unix(0, 0).UTC(),
   110  				math.NewInt(5),
   111  				0,
   112  				addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"),
   113  			),
   114  		},
   115  	}
   116  
   117  	for i, tc := range cases {
   118  		s.Run(tc.name, func() {
   119  			if tc.exists.setUnbondingDelegation {
   120  				require.NoError(s.stakingKeeper.SetUnbondingDelegation(s.ctx, tc.expected))
   121  			}
   122  
   123  			if tc.exists.setUnbondingDelegationByUnbondingID {
   124  				require.NoError(s.stakingKeeper.SetUnbondingDelegationByUnbondingID(s.ctx, tc.expected, uint64(i)))
   125  			}
   126  
   127  			ubd, err := s.stakingKeeper.GetUnbondingDelegationByUnbondingID(s.ctx, uint64(i))
   128  			if tc.exists.setUnbondingDelegation && tc.exists.setUnbondingDelegationByUnbondingID {
   129  				require.NoError(err)
   130  				require.Equal(tc.expected, ubd)
   131  			} else {
   132  				require.ErrorIs(err, types.ErrNoUnbondingDelegation)
   133  			}
   134  		})
   135  	}
   136  }
   137  
   138  func (s *KeeperTestSuite) TestRedelegationByUnbondingIDAccessors() {
   139  	delAddrs, valAddrs := createValAddrs(2)
   140  	require := s.Require()
   141  
   142  	type exists struct {
   143  		setRedelegation              bool
   144  		setRedelegationByUnbondingID bool
   145  	}
   146  
   147  	cases := []struct {
   148  		exists   exists
   149  		name     string
   150  		expected types.Redelegation
   151  	}{
   152  		{
   153  			name:   "existing 1",
   154  			exists: exists{true, true},
   155  			expected: types.NewRedelegation(
   156  				delAddrs[0],
   157  				valAddrs[0],
   158  				valAddrs[1],
   159  				0,
   160  				time.Unix(5, 0).UTC(),
   161  				math.NewInt(10),
   162  				math.LegacyNewDec(10),
   163  				0,
   164  				addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"),
   165  			),
   166  		},
   167  		{
   168  			name:   "not existing 1",
   169  			exists: exists{false, true},
   170  			expected: types.NewRedelegation(
   171  				delAddrs[1],
   172  				valAddrs[0],
   173  				valAddrs[1],
   174  				0,
   175  				time.Unix(5, 0).UTC(),
   176  				math.NewInt(10),
   177  				math.LegacyNewDec(10),
   178  				0,
   179  				addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"),
   180  			),
   181  		},
   182  		{
   183  			name:   "not existing 2",
   184  			exists: exists{false, false},
   185  			expected: types.NewRedelegation(
   186  				delAddrs[1],
   187  				valAddrs[1],
   188  				valAddrs[0],
   189  				0,
   190  				time.Unix(5, 0).UTC(),
   191  				math.NewInt(10),
   192  				math.LegacyNewDec(10),
   193  				0,
   194  				addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"),
   195  			),
   196  		},
   197  	}
   198  
   199  	for i, tc := range cases {
   200  		s.Run(tc.name, func() {
   201  			if tc.exists.setRedelegation {
   202  				require.NoError(s.stakingKeeper.SetRedelegation(s.ctx, tc.expected))
   203  			}
   204  
   205  			if tc.exists.setRedelegationByUnbondingID {
   206  				require.NoError(s.stakingKeeper.SetRedelegationByUnbondingID(s.ctx, tc.expected, uint64(i)))
   207  			}
   208  
   209  			red, err := s.stakingKeeper.GetRedelegationByUnbondingID(s.ctx, uint64(i))
   210  			if tc.exists.setRedelegation && tc.exists.setRedelegationByUnbondingID {
   211  				require.NoError(err)
   212  				require.Equal(tc.expected, red)
   213  			} else {
   214  				require.ErrorIs(err, types.ErrNoRedelegation)
   215  			}
   216  		})
   217  	}
   218  }
   219  
   220  func (s *KeeperTestSuite) TestValidatorByUnbondingIDAccessors() {
   221  	_, valAddrs := createValAddrs(3)
   222  	require := s.Require()
   223  
   224  	type exists struct {
   225  		setValidator              bool
   226  		setValidatorByUnbondingID bool
   227  	}
   228  
   229  	cases := []struct {
   230  		exists    exists
   231  		name      string
   232  		validator types.Validator
   233  	}{
   234  		{
   235  			name:      "existing 1",
   236  			exists:    exists{true, true},
   237  			validator: testutil.NewValidator(s.T(), valAddrs[0], PKs[0]),
   238  		},
   239  		{
   240  			name:      "not existing 1",
   241  			exists:    exists{false, true},
   242  			validator: testutil.NewValidator(s.T(), valAddrs[1], PKs[1]),
   243  		},
   244  		{
   245  			name:      "not existing 2",
   246  			exists:    exists{false, false},
   247  			validator: testutil.NewValidator(s.T(), valAddrs[2], PKs[0]),
   248  		},
   249  	}
   250  
   251  	for i, tc := range cases {
   252  		s.Run(tc.name, func() {
   253  			if tc.exists.setValidator {
   254  				require.NoError(s.stakingKeeper.SetValidator(s.ctx, tc.validator))
   255  			}
   256  
   257  			if tc.exists.setValidatorByUnbondingID {
   258  				require.NoError(s.stakingKeeper.SetValidatorByUnbondingID(s.ctx, tc.validator, uint64(i)))
   259  			}
   260  
   261  			val, err := s.stakingKeeper.GetValidatorByUnbondingID(s.ctx, uint64(i))
   262  			if tc.exists.setValidator && tc.exists.setValidatorByUnbondingID {
   263  				require.NoError(err)
   264  				require.Equal(tc.validator, val)
   265  			} else {
   266  				require.ErrorIs(err, types.ErrNoValidatorFound)
   267  			}
   268  		})
   269  	}
   270  }
   271  
   272  func (s *KeeperTestSuite) TestUnbondingCanComplete() {
   273  	delAddrs, valAddrs := createValAddrs(3)
   274  	require := s.Require()
   275  
   276  	unbondingID := uint64(1)
   277  
   278  	// no unbondingID set
   279  	err := s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
   280  	require.ErrorIs(err, types.ErrNoUnbondingType)
   281  
   282  	// unbonding delegation
   283  	require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_UnbondingDelegation))
   284  	err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
   285  	require.ErrorIs(err, types.ErrNoUnbondingDelegation)
   286  
   287  	ubd := types.NewUnbondingDelegation(
   288  		delAddrs[0],
   289  		valAddrs[0],
   290  		0,
   291  		time.Unix(0, 0).UTC(),
   292  		math.NewInt(5),
   293  		unbondingID,
   294  		addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"),
   295  	)
   296  	require.NoError(s.stakingKeeper.SetUnbondingDelegation(s.ctx, ubd))
   297  	require.NoError(s.stakingKeeper.SetUnbondingDelegationByUnbondingID(s.ctx, ubd, unbondingID))
   298  	err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
   299  	require.ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative)
   300  
   301  	err = s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID)
   302  	require.NoError(err)
   303  	s.bankKeeper.EXPECT().UndelegateCoinsFromModuleToAccount(s.ctx, types.NotBondedPoolName, delAddrs[0], sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(5)))).Return(nil)
   304  	err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
   305  	require.NoError(err)
   306  
   307  	// redelegation
   308  	unbondingID++
   309  	require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_Redelegation))
   310  	err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
   311  	require.ErrorIs(err, types.ErrNoRedelegation)
   312  
   313  	red := types.NewRedelegation(
   314  		delAddrs[0],
   315  		valAddrs[0],
   316  		valAddrs[1],
   317  		0,
   318  		time.Unix(5, 0).UTC(),
   319  		math.NewInt(10),
   320  		math.LegacyNewDec(10),
   321  		unbondingID,
   322  		addresscodec.NewBech32Codec("cosmosvaloper"), addresscodec.NewBech32Codec("cosmos"),
   323  	)
   324  	require.NoError(s.stakingKeeper.SetRedelegation(s.ctx, red))
   325  	require.NoError(s.stakingKeeper.SetRedelegationByUnbondingID(s.ctx, red, unbondingID))
   326  	err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
   327  	require.ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative)
   328  
   329  	require.NoError(s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID))
   330  	require.NoError(s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID))
   331  
   332  	// validator unbonding
   333  	unbondingID++
   334  	require.NoError(s.stakingKeeper.SetUnbondingType(s.ctx, unbondingID, types.UnbondingType_ValidatorUnbonding))
   335  	err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
   336  	require.ErrorIs(err, types.ErrNoValidatorFound)
   337  
   338  	val := testutil.NewValidator(s.T(), valAddrs[0], PKs[0])
   339  	require.NoError(s.stakingKeeper.SetValidator(s.ctx, val))
   340  	require.NoError(s.stakingKeeper.SetValidatorByUnbondingID(s.ctx, val, unbondingID))
   341  	err = s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID)
   342  	require.ErrorIs(err, types.ErrUnbondingOnHoldRefCountNegative)
   343  
   344  	require.NoError(s.stakingKeeper.PutUnbondingOnHold(s.ctx, unbondingID))
   345  	require.NoError(s.stakingKeeper.UnbondingCanComplete(s.ctx, unbondingID))
   346  }