github.com/Finschia/finschia-sdk@v0.48.1/x/distribution/keeper/delegation_test.go (about) 1 package keeper_test 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 8 9 "github.com/Finschia/finschia-sdk/simapp" 10 sdk "github.com/Finschia/finschia-sdk/types" 11 "github.com/Finschia/finschia-sdk/x/staking" 12 "github.com/Finschia/finschia-sdk/x/staking/teststaking" 13 stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" 14 ) 15 16 func TestCalculateRewardsBasic(t *testing.T) { 17 app := simapp.Setup(false) 18 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 19 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 20 21 addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1000)) 22 valAddrs := simapp.ConvertAddrsToValAddrs(addr) 23 24 // create validator with 50% commission 25 tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) 26 tstaking.CreateValidator(valAddrs[0], valConsPk1, sdk.NewInt(100), true) 27 28 // end block to bond validator and start new block 29 staking.EndBlocker(ctx, app.StakingKeeper) 30 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 31 tstaking.Ctx = ctx 32 33 // fetch validator and delegation 34 val := app.StakingKeeper.Validator(ctx, valAddrs[0]) 35 del := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 36 37 // historical count should be 2 (once for validator init, once for delegation init) 38 require.Equal(t, uint64(2), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx)) 39 40 // end period 41 endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 42 43 // historical count should be 2 still 44 require.Equal(t, uint64(2), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx)) 45 46 // calculate delegation rewards 47 rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod) 48 49 // rewards should be zero 50 require.True(t, rewards.IsZero()) 51 52 // allocate some rewards 53 initial := int64(10) 54 tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}} 55 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 56 57 // end period 58 endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 59 60 // calculate delegation rewards 61 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod) 62 63 // rewards should be half the tokens 64 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, rewards) 65 66 // commission should be the other half 67 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission) 68 } 69 70 func TestCalculateRewardsAfterSlash(t *testing.T) { 71 app := simapp.Setup(false) 72 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 73 74 addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(100000000)) 75 valAddrs := simapp.ConvertAddrsToValAddrs(addr) 76 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 77 78 // create validator with 50% commission 79 tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) 80 valPower := int64(100) 81 tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk1, valPower, true) 82 83 // end block to bond validator 84 staking.EndBlocker(ctx, app.StakingKeeper) 85 86 // next block 87 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 88 89 // fetch validator and delegation 90 val := app.StakingKeeper.Validator(ctx, valAddrs[0]) 91 del := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 92 93 // end period 94 endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 95 96 // calculate delegation rewards 97 rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod) 98 99 // rewards should be zero 100 require.True(t, rewards.IsZero()) 101 102 // start out block height 103 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 104 105 // slash the validator by 50% 106 app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1)) 107 108 // retrieve validator 109 val = app.StakingKeeper.Validator(ctx, valAddrs[0]) 110 111 // increase block height 112 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 113 114 // allocate some rewards 115 initial := app.StakingKeeper.TokensFromConsensusPower(ctx, 10) 116 tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.ToDec()}} 117 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 118 119 // end period 120 endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 121 122 // calculate delegation rewards 123 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod) 124 125 // rewards should be half the tokens 126 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.QuoRaw(2).ToDec()}}, rewards) 127 128 // commission should be the other half 129 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.QuoRaw(2).ToDec()}}, 130 app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission) 131 } 132 133 func TestCalculateRewardsAfterManySlashes(t *testing.T) { 134 app := simapp.Setup(false) 135 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 136 137 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 138 addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(100000000)) 139 valAddrs := simapp.ConvertAddrsToValAddrs(addr) 140 141 // create validator with 50% commission 142 valPower := int64(100) 143 tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) 144 tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk1, valPower, true) 145 146 // end block to bond validator 147 staking.EndBlocker(ctx, app.StakingKeeper) 148 149 // next block 150 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 151 152 // fetch validator and delegation 153 val := app.StakingKeeper.Validator(ctx, valAddrs[0]) 154 del := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 155 156 // end period 157 endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 158 159 // calculate delegation rewards 160 rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod) 161 162 // rewards should be zero 163 require.True(t, rewards.IsZero()) 164 165 // start out block height 166 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 167 168 // slash the validator by 50% 169 app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1)) 170 171 // fetch the validator again 172 val = app.StakingKeeper.Validator(ctx, valAddrs[0]) 173 174 // increase block height 175 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 176 177 // allocate some rewards 178 initial := app.StakingKeeper.TokensFromConsensusPower(ctx, 10) 179 tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.ToDec()}} 180 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 181 182 // slash the validator by 50% again 183 app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), valPower/2, sdk.NewDecWithPrec(5, 1)) 184 185 // fetch the validator again 186 val = app.StakingKeeper.Validator(ctx, valAddrs[0]) 187 188 // increase block height 189 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 190 191 // allocate some more rewards 192 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 193 194 // end period 195 endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 196 197 // calculate delegation rewards 198 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod) 199 200 // rewards should be half the tokens 201 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.ToDec()}}, rewards) 202 203 // commission should be the other half 204 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.ToDec()}}, 205 app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission) 206 } 207 208 func TestCalculateRewardsMultiDelegator(t *testing.T) { 209 app := simapp.Setup(false) 210 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 211 212 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 213 addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(100000000)) 214 valAddrs := simapp.ConvertAddrsToValAddrs(addr) 215 216 // create validator with 50% commission 217 tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) 218 tstaking.CreateValidator(valAddrs[0], valConsPk1, sdk.NewInt(100), true) 219 220 // end block to bond validator 221 staking.EndBlocker(ctx, app.StakingKeeper) 222 223 // next block 224 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 225 226 // fetch validator and delegation 227 val := app.StakingKeeper.Validator(ctx, valAddrs[0]) 228 del1 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 229 230 // allocate some rewards 231 initial := int64(20) 232 tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}} 233 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 234 235 // second delegation 236 tstaking.Ctx = ctx 237 tstaking.Delegate(sdk.AccAddress(valAddrs[1]), valAddrs[0], sdk.NewInt(100)) 238 del2 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0]) 239 240 // fetch updated validator 241 val = app.StakingKeeper.Validator(ctx, valAddrs[0]) 242 243 // end block 244 staking.EndBlocker(ctx, app.StakingKeeper) 245 246 // next block 247 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 248 249 // allocate some more rewards 250 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 251 252 // end period 253 endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 254 255 // calculate delegation rewards for del1 256 rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod) 257 258 // rewards for del1 should be 3/4 initial 259 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial * 3 / 4)}}, rewards) 260 261 // calculate delegation rewards for del2 262 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod) 263 264 // rewards for del2 should be 1/4 initial 265 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial * 1 / 4)}}, rewards) 266 267 // commission should be equal to initial (50% twice) 268 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission) 269 } 270 271 func TestWithdrawDelegationRewardsBasic(t *testing.T) { 272 app := simapp.Setup(false) 273 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 274 275 balancePower := int64(1000) 276 balanceTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, balancePower) 277 addr := simapp.AddTestAddrs(app, ctx, 1, sdk.NewInt(1000000000)) 278 valAddrs := simapp.ConvertAddrsToValAddrs(addr) 279 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 280 281 // set module account coins 282 distrAcc := app.DistrKeeper.GetDistributionAccount(ctx) 283 require.NoError(t, simapp.FundModuleAccount(app, ctx, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, balanceTokens)))) 284 app.AccountKeeper.SetModuleAccount(ctx, distrAcc) 285 286 // create validator with 50% commission 287 power := int64(100) 288 tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) 289 valTokens := tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk1, power, true) 290 291 // assert correct initial balance 292 expTokens := balanceTokens.Sub(valTokens) 293 require.Equal(t, 294 sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, expTokens)}, 295 app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0])), 296 ) 297 298 // end block to bond validator 299 staking.EndBlocker(ctx, app.StakingKeeper) 300 301 // next block 302 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 303 304 // fetch validator and delegation 305 val := app.StakingKeeper.Validator(ctx, valAddrs[0]) 306 307 // allocate some rewards 308 initial := app.StakingKeeper.TokensFromConsensusPower(ctx, 10) 309 tokens := sdk.DecCoins{sdk.NewDecCoin(sdk.DefaultBondDenom, initial)} 310 311 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 312 313 // historical count should be 2 (initial + latest for delegation) 314 require.Equal(t, uint64(2), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx)) 315 316 // withdraw rewards 317 _, err := app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 318 require.Nil(t, err) 319 320 // historical count should still be 2 (added one record, cleared one) 321 require.Equal(t, uint64(2), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx)) 322 323 // assert correct balance 324 exp := balanceTokens.Sub(valTokens).Add(initial.QuoRaw(2)) 325 require.Equal(t, 326 sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, exp)}, 327 app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0])), 328 ) 329 330 // withdraw commission 331 _, err = app.DistrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0]) 332 require.Nil(t, err) 333 } 334 335 func TestWithdrawDelegationZeroRewards(t *testing.T) { 336 app := simapp.Setup(false) 337 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 338 339 balancePower := int64(1000) 340 balanceTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, balancePower) 341 addr := simapp.AddTestAddrs(app, ctx, 1, sdk.NewInt(1000000000)) 342 valAddrs := simapp.ConvertAddrsToValAddrs(addr) 343 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 344 345 // set module account coins 346 distrAcc := app.DistrKeeper.GetDistributionAccount(ctx) 347 require.NoError(t, simapp.FundModuleAccount(app, ctx, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, balanceTokens)))) 348 app.AccountKeeper.SetModuleAccount(ctx, distrAcc) 349 350 // create validator with 50% commission 351 power := int64(100) 352 tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) 353 _ = tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk1, power, true) 354 355 // withdraw rewards -- should be 0 356 amount, err := app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 357 require.NoError(t, err) 358 require.True(t, amount.IsZero(), "expected withdraw rewards to be zero") 359 require.True(t, amount.IsValid(), "expected returned coins to be valid") 360 } 361 362 func TestCalculateRewardsAfterManySlashesInSameBlock(t *testing.T) { 363 app := simapp.Setup(false) 364 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 365 366 addr := simapp.AddTestAddrs(app, ctx, 1, sdk.NewInt(1000000000)) 367 valAddrs := simapp.ConvertAddrsToValAddrs(addr) 368 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 369 370 // create validator with 50% commission 371 valPower := int64(100) 372 tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) 373 tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk1, valPower, true) 374 375 // end block to bond validator 376 staking.EndBlocker(ctx, app.StakingKeeper) 377 378 // next block 379 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 380 381 // fetch validator and delegation 382 val := app.StakingKeeper.Validator(ctx, valAddrs[0]) 383 del := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 384 385 // end period 386 endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 387 388 // calculate delegation rewards 389 rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod) 390 391 // rewards should be zero 392 require.True(t, rewards.IsZero()) 393 394 // start out block height 395 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 396 397 // allocate some rewards 398 initial := app.StakingKeeper.TokensFromConsensusPower(ctx, 10).ToDec() 399 tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}} 400 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 401 402 // slash the validator by 50% 403 app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1)) 404 405 // slash the validator by 50% again 406 app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), valPower/2, sdk.NewDecWithPrec(5, 1)) 407 408 // fetch the validator again 409 val = app.StakingKeeper.Validator(ctx, valAddrs[0]) 410 411 // increase block height 412 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 413 414 // allocate some more rewards 415 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 416 417 // end period 418 endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 419 420 // calculate delegation rewards 421 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod) 422 423 // rewards should be half the tokens 424 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}, rewards) 425 426 // commission should be the other half 427 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission) 428 } 429 430 func TestCalculateRewardsMultiDelegatorMultiSlash(t *testing.T) { 431 app := simapp.Setup(false) 432 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 433 434 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 435 addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1000000000)) 436 valAddrs := simapp.ConvertAddrsToValAddrs(addr) 437 438 // create validator with 50% commission 439 tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) 440 valPower := int64(100) 441 tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk1, valPower, true) 442 443 // end block to bond validator 444 staking.EndBlocker(ctx, app.StakingKeeper) 445 446 // next block 447 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 448 449 // fetch validator and delegation 450 val := app.StakingKeeper.Validator(ctx, valAddrs[0]) 451 del1 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 452 453 // allocate some rewards 454 initial := app.StakingKeeper.TokensFromConsensusPower(ctx, 30).ToDec() 455 tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}} 456 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 457 458 // slash the validator 459 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 460 app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1)) 461 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 462 463 // second delegation 464 tstaking.DelegateWithPower(sdk.AccAddress(valAddrs[1]), valAddrs[0], 100) 465 466 del2 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0]) 467 468 // end block 469 staking.EndBlocker(ctx, app.StakingKeeper) 470 471 // next block 472 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 473 474 // allocate some more rewards 475 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 476 477 // slash the validator again 478 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 479 app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1)) 480 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3) 481 482 // fetch updated validator 483 val = app.StakingKeeper.Validator(ctx, valAddrs[0]) 484 485 // end period 486 endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 487 488 // calculate delegation rewards for del1 489 rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod) 490 491 // rewards for del1 should be 2/3 initial (half initial first period, 1/6 initial second period) 492 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.QuoInt64(2).Add(initial.QuoInt64(6))}}, rewards) 493 494 // calculate delegation rewards for del2 495 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod) 496 497 // rewards for del2 should be initial / 3 498 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.QuoInt64(3)}}, rewards) 499 500 // commission should be equal to initial (twice 50% commission, unaffected by slashing) 501 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission) 502 } 503 504 func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) { 505 app := simapp.Setup(false) 506 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 507 508 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 509 addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1000000000)) 510 valAddrs := simapp.ConvertAddrsToValAddrs(addr) 511 initial := int64(20) 512 513 // set module account coins 514 distrAcc := app.DistrKeeper.GetDistributionAccount(ctx) 515 require.NoError(t, simapp.FundModuleAccount(app, ctx, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000))))) 516 app.AccountKeeper.SetModuleAccount(ctx, distrAcc) 517 518 tokens := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.NewDec(initial))} 519 520 // create validator with 50% commission 521 tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0)) 522 tstaking.CreateValidator(valAddrs[0], valConsPk1, sdk.NewInt(100), true) 523 524 // end block to bond validator 525 staking.EndBlocker(ctx, app.StakingKeeper) 526 527 // next block 528 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 529 530 // fetch validator and delegation 531 val := app.StakingKeeper.Validator(ctx, valAddrs[0]) 532 del1 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 533 534 // allocate some rewards 535 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 536 537 // historical count should be 2 (validator init, delegation init) 538 require.Equal(t, uint64(2), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx)) 539 540 // second delegation 541 tstaking.Delegate(sdk.AccAddress(valAddrs[1]), valAddrs[0], sdk.NewInt(100)) 542 543 // historical count should be 3 (second delegation init) 544 require.Equal(t, uint64(3), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx)) 545 546 // fetch updated validator 547 val = app.StakingKeeper.Validator(ctx, valAddrs[0]) 548 del2 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0]) 549 550 // end block 551 staking.EndBlocker(ctx, app.StakingKeeper) 552 553 // next block 554 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 555 556 // allocate some more rewards 557 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 558 559 // first delegator withdraws 560 _, err := app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 561 require.NoError(t, err) 562 563 // second delegator withdraws 564 _, err = app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0]) 565 require.NoError(t, err) 566 567 // historical count should be 3 (validator init + two delegations) 568 require.Equal(t, uint64(3), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx)) 569 570 // validator withdraws commission 571 _, err = app.DistrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0]) 572 require.NoError(t, err) 573 574 // end period 575 endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 576 577 // calculate delegation rewards for del1 578 rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod) 579 580 // rewards for del1 should be zero 581 require.True(t, rewards.IsZero()) 582 583 // calculate delegation rewards for del2 584 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod) 585 586 // rewards for del2 should be zero 587 require.True(t, rewards.IsZero()) 588 589 // commission should be zero 590 require.True(t, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero()) 591 592 // next block 593 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 594 595 // allocate some more rewards 596 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 597 598 // first delegator withdraws again 599 _, err = app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) 600 require.NoError(t, err) 601 602 // end period 603 endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 604 605 // calculate delegation rewards for del1 606 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod) 607 608 // rewards for del1 should be zero 609 require.True(t, rewards.IsZero()) 610 611 // calculate delegation rewards for del2 612 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod) 613 614 // rewards for del2 should be 1/4 initial 615 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 4)}}, rewards) 616 617 // commission should be half initial 618 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission) 619 620 // next block 621 ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) 622 623 // allocate some more rewards 624 app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens) 625 626 // withdraw commission 627 _, err = app.DistrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0]) 628 require.NoError(t, err) 629 630 // end period 631 endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val) 632 633 // calculate delegation rewards for del1 634 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod) 635 636 // rewards for del1 should be 1/4 initial 637 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 4)}}, rewards) 638 639 // calculate delegation rewards for del2 640 rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod) 641 642 // rewards for del2 should be 1/2 initial 643 require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, rewards) 644 645 // commission should be zero 646 require.True(t, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero()) 647 }