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