github.com/Finschia/finschia-sdk@v0.49.1/x/auth/legacy/v043/store_test.go (about)

     1  package v043_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/require"
     9  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
    10  
    11  	"github.com/Finschia/finschia-sdk/simapp"
    12  	sdk "github.com/Finschia/finschia-sdk/types"
    13  	authkeeper "github.com/Finschia/finschia-sdk/x/auth/keeper"
    14  	authtypes "github.com/Finschia/finschia-sdk/x/auth/types"
    15  	"github.com/Finschia/finschia-sdk/x/auth/vesting/exported"
    16  	"github.com/Finschia/finschia-sdk/x/auth/vesting/types"
    17  	"github.com/Finschia/finschia-sdk/x/staking"
    18  	stakingkeeper "github.com/Finschia/finschia-sdk/x/staking/keeper"
    19  	stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types"
    20  )
    21  
    22  func TestMigrateVestingAccounts(t *testing.T) {
    23  	testCases := []struct {
    24  		name        string
    25  		prepareFunc func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress)
    26  		garbageFunc func(ctx sdk.Context, vesting exported.VestingAccount, app *simapp.SimApp) error
    27  		tokenAmount int64
    28  		expVested   int64
    29  		expFree     int64
    30  		blockTime   int64
    31  	}{
    32  		{
    33  			"delayed vesting has vested, multiple delegations less than the total account balance",
    34  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
    35  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
    36  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(200)))
    37  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
    38  
    39  				ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
    40  
    41  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
    42  
    43  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
    44  				require.NoError(t, err)
    45  				_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
    46  				require.NoError(t, err)
    47  				_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
    48  				require.NoError(t, err)
    49  			},
    50  			cleartTrackingFields,
    51  			300,
    52  			0,
    53  			300,
    54  			0,
    55  		},
    56  		{
    57  			"delayed vesting has vested, single delegations which exceed the vested amount",
    58  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
    59  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
    60  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(200)))
    61  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
    62  
    63  				ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
    64  
    65  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
    66  
    67  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
    68  				require.NoError(t, err)
    69  			},
    70  			cleartTrackingFields,
    71  			300,
    72  			0,
    73  			300,
    74  			0,
    75  		},
    76  		{
    77  			"delayed vesting has vested, multiple delegations which exceed the vested amount",
    78  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
    79  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
    80  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(200)))
    81  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
    82  
    83  				ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
    84  
    85  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
    86  
    87  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
    88  				require.NoError(t, err)
    89  				_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
    90  				require.NoError(t, err)
    91  				_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
    92  				require.NoError(t, err)
    93  			},
    94  			cleartTrackingFields,
    95  			300,
    96  			0,
    97  			300,
    98  			0,
    99  		},
   100  		{
   101  			"delayed vesting has not vested, single delegations  which exceed the vested amount",
   102  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   103  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   104  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(200)))
   105  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
   106  
   107  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   108  
   109  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
   110  				require.NoError(t, err)
   111  			},
   112  			cleartTrackingFields,
   113  			300,
   114  			200,
   115  			100,
   116  			0,
   117  		},
   118  		{
   119  			"delayed vesting has not vested, multiple delegations which exceed the vested amount",
   120  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   121  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   122  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(200)))
   123  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
   124  
   125  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   126  
   127  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
   128  				require.NoError(t, err)
   129  				_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
   130  				require.NoError(t, err)
   131  				_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
   132  				require.NoError(t, err)
   133  			},
   134  			cleartTrackingFields,
   135  			300,
   136  			200,
   137  			100,
   138  			0,
   139  		},
   140  		{
   141  			"not end time",
   142  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   143  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   144  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
   145  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
   146  
   147  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   148  
   149  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
   150  				require.NoError(t, err)
   151  				_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
   152  				require.NoError(t, err)
   153  				_, err = app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(100), stakingtypes.Unbonded, validator, true)
   154  				require.NoError(t, err)
   155  			},
   156  			cleartTrackingFields,
   157  			300,
   158  			300,
   159  			0,
   160  			0,
   161  		},
   162  		{
   163  			"delayed vesting has not vested, single delegation greater than the total account balance",
   164  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   165  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   166  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
   167  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(1, 0, 0).Unix())
   168  
   169  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   170  
   171  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
   172  				require.NoError(t, err)
   173  			},
   174  			cleartTrackingFields,
   175  			300,
   176  			300,
   177  			0,
   178  			0,
   179  		},
   180  		{
   181  			"delayed vesting has vested, single delegation greater than the total account balance",
   182  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   183  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   184  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
   185  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().Unix())
   186  
   187  				ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
   188  
   189  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   190  
   191  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
   192  				require.NoError(t, err)
   193  			},
   194  			cleartTrackingFields,
   195  			300,
   196  			0,
   197  			300,
   198  			0,
   199  		},
   200  		{
   201  			"continuous vesting, start time after blocktime",
   202  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   203  				startTime := ctx.BlockTime().AddDate(1, 0, 0).Unix()
   204  				endTime := ctx.BlockTime().AddDate(2, 0, 0).Unix()
   205  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   206  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
   207  				delayedAccount := types.NewContinuousVestingAccount(baseAccount, vestedCoins, startTime, endTime)
   208  
   209  				ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
   210  
   211  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   212  
   213  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
   214  				require.NoError(t, err)
   215  			},
   216  			cleartTrackingFields,
   217  			300,
   218  			300,
   219  			0,
   220  			0,
   221  		},
   222  		{
   223  			"continuous vesting, start time passed but not ended",
   224  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   225  				startTime := ctx.BlockTime().AddDate(-1, 0, 0).Unix()
   226  				endTime := ctx.BlockTime().AddDate(2, 0, 0).Unix()
   227  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   228  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
   229  				delayedAccount := types.NewContinuousVestingAccount(baseAccount, vestedCoins, startTime, endTime)
   230  
   231  				ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
   232  
   233  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   234  
   235  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
   236  				require.NoError(t, err)
   237  			},
   238  			cleartTrackingFields,
   239  			300,
   240  			200,
   241  			100,
   242  			0,
   243  		},
   244  		{
   245  			"continuous vesting, start time and endtime passed",
   246  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   247  				startTime := ctx.BlockTime().AddDate(-2, 0, 0).Unix()
   248  				endTime := ctx.BlockTime().AddDate(-1, 0, 0).Unix()
   249  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   250  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
   251  				delayedAccount := types.NewContinuousVestingAccount(baseAccount, vestedCoins, startTime, endTime)
   252  
   253  				ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
   254  
   255  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   256  
   257  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
   258  				require.NoError(t, err)
   259  			},
   260  			cleartTrackingFields,
   261  			300,
   262  			0,
   263  			300,
   264  			0,
   265  		},
   266  		{
   267  			"periodic vesting account, yet to be vested, some rewards delegated",
   268  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   269  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   270  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(100)))
   271  
   272  				start := ctx.BlockTime().Unix() + int64(time.Hour/time.Second)
   273  
   274  				periods := []types.Period{
   275  					{
   276  						Length: int64((24 * time.Hour) / time.Second),
   277  						Amount: vestedCoins,
   278  					},
   279  				}
   280  
   281  				account := types.NewPeriodicVestingAccount(baseAccount, vestedCoins, start, periods)
   282  
   283  				app.AccountKeeper.SetAccount(ctx, account)
   284  
   285  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(150), stakingtypes.Unbonded, validator, true)
   286  				require.NoError(t, err)
   287  			},
   288  			cleartTrackingFields,
   289  			300,
   290  			100,
   291  			50,
   292  			0,
   293  		},
   294  		{
   295  			"periodic vesting account, nothing has vested yet",
   296  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   297  				/*
   298  					Test case:
   299  					 - periodic vesting account starts at time 1601042400
   300  					 - account balance and original vesting: 3666666670000
   301  					 - nothing has vested, we put the block time slightly after start time
   302  					 - expected vested: original vesting amount
   303  					 - expected free: zero
   304  					 - we're delegating the full original vesting
   305  				*/
   306  				startTime := int64(1601042400)
   307  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   308  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
   309  				periods := []types.Period{
   310  					{
   311  						Length: 31536000,
   312  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
   313  					},
   314  					{
   315  						Length: 15638400,
   316  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
   317  					},
   318  					{
   319  						Length: 15897600,
   320  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
   321  					},
   322  				}
   323  
   324  				delayedAccount := types.NewPeriodicVestingAccount(baseAccount, vestedCoins, startTime, periods)
   325  
   326  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   327  
   328  				// delegation of the original vesting
   329  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(3666666670000), stakingtypes.Unbonded, validator, true)
   330  				require.NoError(t, err)
   331  			},
   332  			cleartTrackingFields,
   333  			3666666670000,
   334  			3666666670000,
   335  			0,
   336  			1601042400 + 1,
   337  		},
   338  		{
   339  			"periodic vesting account, all has vested",
   340  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   341  				/*
   342  					Test case:
   343  					 - periodic vesting account starts at time 1601042400
   344  					 - account balance and original vesting: 3666666670000
   345  					 - all has vested, so we set the block time at initial time + sum of all periods times + 1 => 1601042400 + 31536000 + 15897600 + 15897600 + 1
   346  					 - expected vested: zero
   347  					 - expected free: original vesting amount
   348  					 - we're delegating the full original vesting
   349  				*/
   350  				startTime := int64(1601042400)
   351  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   352  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
   353  				periods := []types.Period{
   354  					{
   355  						Length: 31536000,
   356  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
   357  					},
   358  					{
   359  						Length: 15638400,
   360  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
   361  					},
   362  					{
   363  						Length: 15897600,
   364  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
   365  					},
   366  				}
   367  
   368  				delayedAccount := types.NewPeriodicVestingAccount(baseAccount, vestedCoins, startTime, periods)
   369  
   370  				ctx = ctx.WithBlockTime(time.Unix(1601042400+31536000+15897600+15897600+1, 0))
   371  
   372  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   373  
   374  				// delegation of the original vesting
   375  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(3666666670000), stakingtypes.Unbonded, validator, true)
   376  				require.NoError(t, err)
   377  			},
   378  			cleartTrackingFields,
   379  			3666666670000,
   380  			0,
   381  			3666666670000,
   382  			1601042400 + 31536000 + 15897600 + 15897600 + 1,
   383  		},
   384  		{
   385  			"periodic vesting account, first period has vested",
   386  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   387  				/*
   388  					Test case:
   389  					 - periodic vesting account starts at time 1601042400
   390  					 - account balance and original vesting: 3666666670000
   391  					 - first period have vested, so we set the block time at initial time + time of the first periods + 1 => 1601042400 + 31536000 + 1
   392  					 - expected vested: original vesting - first period amount
   393  					 - expected free: first period amount
   394  					 - we're delegating the full original vesting
   395  				*/
   396  				startTime := int64(1601042400)
   397  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   398  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
   399  				periods := []types.Period{
   400  					{
   401  						Length: 31536000,
   402  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
   403  					},
   404  					{
   405  						Length: 15638400,
   406  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
   407  					},
   408  					{
   409  						Length: 15897600,
   410  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
   411  					},
   412  				}
   413  
   414  				delayedAccount := types.NewPeriodicVestingAccount(baseAccount, vestedCoins, startTime, periods)
   415  
   416  				ctx = ctx.WithBlockTime(time.Unix(1601042400+31536000+1, 0))
   417  
   418  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   419  
   420  				// delegation of the original vesting
   421  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(3666666670000), stakingtypes.Unbonded, validator, true)
   422  				require.NoError(t, err)
   423  			},
   424  			cleartTrackingFields,
   425  			3666666670000,
   426  			3666666670000 - 1833333335000,
   427  			1833333335000,
   428  			1601042400 + 31536000 + 1,
   429  		},
   430  		{
   431  			"periodic vesting account, first 2 period has vested",
   432  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   433  				/*
   434  					Test case:
   435  					 - periodic vesting account starts at time 1601042400
   436  					 - account balance and original vesting: 3666666670000
   437  					 - first 2 periods have vested, so we set the block time at initial time + time of the two periods + 1 => 1601042400 + 31536000 + 15638400 + 1
   438  					 - expected vested: original vesting - (sum of the first two periods amounts)
   439  					 - expected free: sum of the first two periods
   440  					 - we're delegating the full original vesting
   441  				*/
   442  				startTime := int64(1601042400)
   443  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   444  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(3666666670000)))
   445  				periods := []types.Period{
   446  					{
   447  						Length: 31536000,
   448  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(1833333335000))),
   449  					},
   450  					{
   451  						Length: 15638400,
   452  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
   453  					},
   454  					{
   455  						Length: 15897600,
   456  						Amount: sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(916666667500))),
   457  					},
   458  				}
   459  
   460  				delayedAccount := types.NewPeriodicVestingAccount(baseAccount, vestedCoins, startTime, periods)
   461  
   462  				ctx = ctx.WithBlockTime(time.Unix(1601042400+31536000+15638400+1, 0))
   463  
   464  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   465  
   466  				// delegation of the original vesting
   467  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(3666666670000), stakingtypes.Unbonded, validator, true)
   468  				require.NoError(t, err)
   469  			},
   470  			cleartTrackingFields,
   471  			3666666670000,
   472  			3666666670000 - 1833333335000 - 916666667500,
   473  			1833333335000 + 916666667500,
   474  			1601042400 + 31536000 + 15638400 + 1,
   475  		},
   476  		{
   477  			"vesting account has unbonding delegations in place",
   478  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   479  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   480  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
   481  
   482  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(10, 0, 0).Unix())
   483  
   484  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   485  
   486  				// delegation of the original vesting
   487  				_, err := app.StakingKeeper.Delegate(ctx, delegatorAddr, sdk.NewInt(300), stakingtypes.Unbonded, validator, true)
   488  				require.NoError(t, err)
   489  
   490  				ctx = ctx.WithBlockTime(ctx.BlockTime().AddDate(1, 0, 0))
   491  
   492  				valAddr, err := sdk.ValAddressFromBech32(validator.OperatorAddress)
   493  				require.NoError(t, err)
   494  
   495  				// un-delegation of the original vesting
   496  				_, err = app.StakingKeeper.Undelegate(ctx, delegatorAddr, valAddr, sdk.NewDecFromInt(sdk.NewInt(300)))
   497  				require.NoError(t, err)
   498  			},
   499  			cleartTrackingFields,
   500  			450,
   501  			300,
   502  			0,
   503  			0,
   504  		},
   505  		{
   506  			"vesting account has never delegated anything",
   507  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   508  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   509  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
   510  
   511  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(10, 0, 0).Unix())
   512  
   513  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   514  			},
   515  			cleartTrackingFields,
   516  			450,
   517  			0,
   518  			0,
   519  			0,
   520  		},
   521  		{
   522  			"vesting account has no delegation but dirty DelegatedFree and DelegatedVesting fields",
   523  			func(app *simapp.SimApp, ctx sdk.Context, validator stakingtypes.Validator, delegatorAddr sdk.AccAddress) {
   524  				baseAccount := authtypes.NewBaseAccountWithAddress(delegatorAddr)
   525  				vestedCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(300)))
   526  
   527  				delayedAccount := types.NewDelayedVestingAccount(baseAccount, vestedCoins, ctx.BlockTime().AddDate(10, 0, 0).Unix())
   528  
   529  				app.AccountKeeper.SetAccount(ctx, delayedAccount)
   530  			},
   531  			dirtyTrackingFields,
   532  			450,
   533  			0,
   534  			0,
   535  			0,
   536  		},
   537  	}
   538  
   539  	for _, tc := range testCases {
   540  		t.Run(tc.name, func(t *testing.T) {
   541  			app := simapp.Setup(false)
   542  			ctx := app.BaseApp.NewContext(false, tmproto.Header{
   543  				Time: time.Now(),
   544  			})
   545  
   546  			addrs := simapp.AddTestAddrs(app, ctx, 1, sdk.NewInt(tc.tokenAmount))
   547  			delegatorAddr := addrs[0]
   548  
   549  			_, valAddr := createValidator(t, ctx, app, tc.tokenAmount*2)
   550  			validator, found := app.StakingKeeper.GetValidator(ctx, valAddr)
   551  			require.True(t, found)
   552  
   553  			tc.prepareFunc(app, ctx, validator, delegatorAddr)
   554  
   555  			if tc.blockTime != 0 {
   556  				ctx = ctx.WithBlockTime(time.Unix(tc.blockTime, 0))
   557  			}
   558  
   559  			// We introduce the bug
   560  			savedAccount := app.AccountKeeper.GetAccount(ctx, delegatorAddr)
   561  			vestingAccount, ok := savedAccount.(exported.VestingAccount)
   562  			require.True(t, ok)
   563  			require.NoError(t, tc.garbageFunc(ctx, vestingAccount, app))
   564  
   565  			m := authkeeper.NewMigrator(app.AccountKeeper, app.GRPCQueryRouter())
   566  			require.NoError(t, m.MigrateV040ToV043(ctx))
   567  
   568  			var expVested sdk.Coins
   569  			var expFree sdk.Coins
   570  
   571  			if tc.expVested != 0 {
   572  				expVested = sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(tc.expVested)))
   573  			}
   574  
   575  			if tc.expFree != 0 {
   576  				expFree = sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(tc.expFree)))
   577  			}
   578  
   579  			trackingCorrected(
   580  				t,
   581  				ctx,
   582  				app.AccountKeeper,
   583  				savedAccount.GetAddress(),
   584  				expVested,
   585  				expFree,
   586  			)
   587  		})
   588  	}
   589  }
   590  
   591  func trackingCorrected(t *testing.T, ctx sdk.Context, ak authkeeper.AccountKeeper, addr sdk.AccAddress, expDelVesting, expDelFree sdk.Coins) {
   592  	t.Helper()
   593  	baseAccount := ak.GetAccount(ctx, addr)
   594  	vDA, ok := baseAccount.(exported.VestingAccount)
   595  	require.True(t, ok)
   596  
   597  	vestedOk := expDelVesting.Equal(vDA.GetDelegatedVesting())
   598  	freeOk := expDelFree.Equal(vDA.GetDelegatedFree())
   599  	require.True(t, vestedOk, vDA.GetDelegatedVesting().String())
   600  	require.True(t, freeOk, vDA.GetDelegatedFree().String())
   601  }
   602  
   603  func cleartTrackingFields(ctx sdk.Context, vesting exported.VestingAccount, app *simapp.SimApp) error {
   604  	switch t := vesting.(type) {
   605  	case *types.DelayedVestingAccount:
   606  		t.DelegatedFree = nil
   607  		t.DelegatedVesting = nil
   608  		app.AccountKeeper.SetAccount(ctx, t)
   609  	case *types.ContinuousVestingAccount:
   610  		t.DelegatedFree = nil
   611  		t.DelegatedVesting = nil
   612  		app.AccountKeeper.SetAccount(ctx, t)
   613  	case *types.PeriodicVestingAccount:
   614  		t.DelegatedFree = nil
   615  		t.DelegatedVesting = nil
   616  		app.AccountKeeper.SetAccount(ctx, t)
   617  	default:
   618  		return fmt.Errorf("expected vesting account, found %t", t)
   619  	}
   620  
   621  	return nil
   622  }
   623  
   624  func dirtyTrackingFields(ctx sdk.Context, vesting exported.VestingAccount, app *simapp.SimApp) error {
   625  	dirt := sdk.NewCoins(sdk.NewInt64Coin("stake", 42))
   626  
   627  	switch t := vesting.(type) {
   628  	case *types.DelayedVestingAccount:
   629  		t.DelegatedFree = dirt
   630  		t.DelegatedVesting = dirt
   631  		app.AccountKeeper.SetAccount(ctx, t)
   632  	case *types.ContinuousVestingAccount:
   633  		t.DelegatedFree = dirt
   634  		t.DelegatedVesting = dirt
   635  		app.AccountKeeper.SetAccount(ctx, t)
   636  	case *types.PeriodicVestingAccount:
   637  		t.DelegatedFree = dirt
   638  		t.DelegatedVesting = dirt
   639  		app.AccountKeeper.SetAccount(ctx, t)
   640  	default:
   641  		return fmt.Errorf("expected vesting account, found %t", t)
   642  	}
   643  
   644  	return nil
   645  }
   646  
   647  func createValidator(t *testing.T, ctx sdk.Context, app *simapp.SimApp, powers int64) (sdk.AccAddress, sdk.ValAddress) {
   648  	t.Helper()
   649  	valTokens := sdk.TokensFromConsensusPower(powers, sdk.DefaultPowerReduction)
   650  	addrs := simapp.AddTestAddrsIncremental(app, ctx, 1, valTokens)
   651  	valAddrs := simapp.ConvertAddrsToValAddrs(addrs)
   652  	pks := simapp.CreateTestPubKeys(1)
   653  	cdc := simapp.MakeTestEncodingConfig().Marshaler
   654  
   655  	app.StakingKeeper = stakingkeeper.NewKeeper(
   656  		cdc,
   657  		app.GetKey(stakingtypes.StoreKey),
   658  		app.AccountKeeper,
   659  		app.BankKeeper,
   660  		app.GetSubspace(stakingtypes.ModuleName),
   661  	)
   662  
   663  	val1, err := stakingtypes.NewValidator(valAddrs[0], pks[0], stakingtypes.Description{})
   664  	require.NoError(t, err)
   665  
   666  	app.StakingKeeper.SetValidator(ctx, val1)
   667  	require.NoError(t, app.StakingKeeper.SetValidatorByConsAddr(ctx, val1))
   668  	app.StakingKeeper.SetNewValidatorByPowerIndex(ctx, val1)
   669  
   670  	_, err = app.StakingKeeper.Delegate(ctx, addrs[0], valTokens, stakingtypes.Unbonded, val1, true)
   671  	require.NoError(t, err)
   672  
   673  	_ = staking.EndBlocker(ctx, app.StakingKeeper)
   674  
   675  	return addrs[0], valAddrs[0]
   676  }