cosmos-sdk/x/distribution/keeper/delegation_test.go

699 lines
25 KiB
Go
Raw Normal View History

package keeper_test
2018-10-04 18:37:40 -07:00
2018-10-09 10:58:59 -07:00
import (
"testing"
abci "github.com/tendermint/tendermint/abci/types"
2018-12-10 06:27:25 -08:00
2020-03-20 10:14:14 -07:00
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
2019-01-11 12:08:01 -08:00
"github.com/cosmos/cosmos-sdk/x/staking"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
2018-10-09 10:58:59 -07:00
)
2018-10-04 18:37:40 -07:00
2019-01-16 13:38:05 -08:00
func TestCalculateRewardsBasic(t *testing.T) {
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, abci.Header{})
sh := staking.NewHandler(app.StakingKeeper)
addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1000))
valAddrs := simapp.ConvertAddrsToValAddrs(addr)
2019-01-16 13:38:05 -08:00
// create validator with 50% commission
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := stakingtypes.NewMsgCreateValidator(
valAddrs[0], valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), stakingtypes.Description{}, commission, sdk.OneInt(),
)
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
2019-01-16 13:38:05 -08:00
// end block to bond validator
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// fetch validator and delegation
val := app.StakingKeeper.Validator(ctx, valAddrs[0])
del := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
2019-01-16 13:38:05 -08:00
// historical count should be 2 (once for validator init, once for delegation init)
require.Equal(t, uint64(2), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx))
2019-01-16 13:38:05 -08:00
// end period
endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// historical count should be 2 still
require.Equal(t, uint64(2), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx))
2019-01-16 13:38:05 -08:00
// calculate delegation rewards
rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards should be zero
require.True(t, rewards.IsZero())
// allocate some rewards
initial := int64(10)
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// end period
endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards should be half the tokens
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, rewards)
2019-01-16 13:38:05 -08:00
// commission should be the other half
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
2018-10-10 23:14:06 -07:00
}
2019-01-16 13:38:05 -08:00
func TestCalculateRewardsAfterSlash(t *testing.T) {
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, abci.Header{})
addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(100000000))
valAddrs := simapp.ConvertAddrsToValAddrs(addr)
sh := staking.NewHandler(app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// create validator with 50% commission
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
valPower := int64(100)
valTokens := sdk.TokensFromConsensusPower(valPower)
msg := stakingtypes.NewMsgCreateValidator(valAddrs[0], valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, valTokens), stakingtypes.Description{}, commission, sdk.OneInt())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
2019-01-16 13:38:05 -08:00
// end block to bond validator
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// fetch validator and delegation
val := app.StakingKeeper.Validator(ctx, valAddrs[0])
del := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
2019-01-16 13:38:05 -08:00
// end period
endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards
rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards should be zero
require.True(t, rewards.IsZero())
// start out block height
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
// slash the validator by 50%
app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1))
2019-01-16 13:38:05 -08:00
// retrieve validator
val = app.StakingKeeper.Validator(ctx, valAddrs[0])
2019-01-16 13:38:05 -08:00
// increase block height
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
// allocate some rewards
initial := sdk.TokensFromConsensusPower(10)
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.ToDec()}}
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// end period
endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards should be half the tokens
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.QuoRaw(2).ToDec()}}, rewards)
2019-01-16 13:38:05 -08:00
// commission should be the other half
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.QuoRaw(2).ToDec()}},
app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
2018-10-04 18:37:40 -07:00
}
2019-01-16 13:38:05 -08:00
func TestCalculateRewardsAfterManySlashes(t *testing.T) {
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, abci.Header{})
sh := staking.NewHandler(app.StakingKeeper)
addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(100000000))
valAddrs := simapp.ConvertAddrsToValAddrs(addr)
2019-01-16 13:38:05 -08:00
// create validator with 50% commission
power := int64(100)
valTokens := sdk.TokensFromConsensusPower(power)
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := stakingtypes.NewMsgCreateValidator(valAddrs[0], valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, valTokens), stakingtypes.Description{}, commission, sdk.OneInt())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
2019-01-16 13:38:05 -08:00
// end block to bond validator
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// fetch validator and delegation
val := app.StakingKeeper.Validator(ctx, valAddrs[0])
del := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
2019-01-16 13:38:05 -08:00
// end period
endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards
rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards should be zero
require.True(t, rewards.IsZero())
// start out block height
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
// slash the validator by 50%
app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), power, sdk.NewDecWithPrec(5, 1))
2019-01-16 13:38:05 -08:00
// fetch the validator again
val = app.StakingKeeper.Validator(ctx, valAddrs[0])
2019-01-16 13:38:05 -08:00
// increase block height
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
// allocate some rewards
initial := sdk.TokensFromConsensusPower(10)
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.ToDec()}}
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// slash the validator by 50% again
app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), power/2, sdk.NewDecWithPrec(5, 1))
2019-01-16 13:38:05 -08:00
// fetch the validator again
val = app.StakingKeeper.Validator(ctx, valAddrs[0])
2019-01-16 13:38:05 -08:00
// increase block height
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
// allocate some more rewards
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// end period
endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards should be half the tokens
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.ToDec()}}, rewards)
2019-01-16 13:38:05 -08:00
// commission should be the other half
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.ToDec()}},
app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
}
2019-01-16 13:38:05 -08:00
func TestCalculateRewardsMultiDelegator(t *testing.T) {
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, abci.Header{})
sh := staking.NewHandler(app.StakingKeeper)
addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(100000000))
valAddrs := simapp.ConvertAddrsToValAddrs(addr)
2019-01-16 13:38:05 -08:00
// create validator with 50% commission
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := stakingtypes.NewMsgCreateValidator(valAddrs[0], valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), stakingtypes.Description{}, commission, sdk.OneInt())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
2019-01-16 13:38:05 -08:00
// end block to bond validator
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// fetch validator and delegation
val := app.StakingKeeper.Validator(ctx, valAddrs[0])
del1 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
2019-01-16 13:38:05 -08:00
// allocate some rewards
initial := int64(20)
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// second delegation
msg2 := stakingtypes.NewMsgDelegate(sdk.AccAddress(valAddrs[1]), valAddrs[0], sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)))
res, err = sh(ctx, msg2)
require.NoError(t, err)
require.NotNil(t, res)
del2 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0])
2019-01-16 13:38:05 -08:00
// fetch updated validator
val = app.StakingKeeper.Validator(ctx, valAddrs[0])
2019-01-16 13:38:05 -08:00
// end block
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// allocate some more rewards
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// end period
endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards for del1
rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards for del1 should be 3/4 initial
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial * 3 / 4)}}, rewards)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards for del2
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards for del2 should be 1/4 initial
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial * 1 / 4)}}, rewards)
2019-01-16 13:38:05 -08:00
// commission should be equal to initial (50% twice)
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial)}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
2018-10-04 18:37:40 -07:00
}
2019-01-16 13:38:05 -08:00
func TestWithdrawDelegationRewardsBasic(t *testing.T) {
balancePower := int64(1000)
balanceTokens := sdk.TokensFromConsensusPower(balancePower)
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, abci.Header{})
addr := simapp.AddTestAddrs(app, ctx, 1, sdk.NewInt(1000000000))
valAddrs := simapp.ConvertAddrsToValAddrs(addr)
sh := staking.NewHandler(app.StakingKeeper)
2019-01-16 13:38:05 -08:00
2019-06-28 13:11:27 -07:00
// set module account coins
distrAcc := app.DistrKeeper.GetDistributionAccount(ctx)
require.NoError(t, app.BankKeeper.SetBalances(ctx, distrAcc.GetAddress(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, balanceTokens))))
app.AccountKeeper.SetModuleAccount(ctx, distrAcc)
2019-06-28 13:11:27 -07:00
2019-01-16 13:38:05 -08:00
// create validator with 50% commission
power := int64(100)
valTokens := sdk.TokensFromConsensusPower(power)
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := stakingtypes.NewMsgCreateValidator(
valAddrs[0], valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, valTokens),
stakingtypes.Description{}, commission, sdk.OneInt(),
)
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
2019-01-16 13:38:05 -08:00
// assert correct initial balance
expTokens := balanceTokens.Sub(valTokens)
require.Equal(t,
sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, expTokens)},
app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0])),
)
2019-01-16 13:38:05 -08:00
// end block to bond validator
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// fetch validator and delegation
val := app.StakingKeeper.Validator(ctx, valAddrs[0])
2019-01-16 13:38:05 -08:00
// allocate some rewards
initial := sdk.TokensFromConsensusPower(10)
tokens := sdk.DecCoins{sdk.NewDecCoin(sdk.DefaultBondDenom, initial)}
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// historical count should be 2 (initial + latest for delegation)
require.Equal(t, uint64(2), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx))
2019-01-16 13:38:05 -08:00
// withdraw rewards
_, err = app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
require.Nil(t, err)
2019-01-16 13:38:05 -08:00
// historical count should still be 2 (added one record, cleared one)
require.Equal(t, uint64(2), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx))
2019-01-16 13:38:05 -08:00
// assert correct balance
exp := balanceTokens.Sub(valTokens).Add(initial.QuoRaw(2))
require.Equal(t,
sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, exp)},
app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0])),
)
2019-01-16 13:38:05 -08:00
// withdraw commission
_, err = app.DistrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0])
require.Nil(t, err)
2019-01-16 13:38:05 -08:00
// assert correct balance
exp = balanceTokens.Sub(valTokens).Add(initial)
require.Equal(t,
sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, exp)},
app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0])),
)
2019-01-16 13:38:05 -08:00
}
func TestCalculateRewardsAfterManySlashesInSameBlock(t *testing.T) {
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, abci.Header{})
addr := simapp.AddTestAddrs(app, ctx, 1, sdk.NewInt(1000000000))
valAddrs := simapp.ConvertAddrsToValAddrs(addr)
sh := staking.NewHandler(app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// create validator with 50% commission
power := int64(100)
valTokens := sdk.TokensFromConsensusPower(power)
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := stakingtypes.NewMsgCreateValidator(valAddrs[0], valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, valTokens), stakingtypes.Description{}, commission, sdk.OneInt())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
2019-01-16 13:38:05 -08:00
// end block to bond validator
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// fetch validator and delegation
val := app.StakingKeeper.Validator(ctx, valAddrs[0])
del := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
2019-01-16 13:38:05 -08:00
// end period
endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards
rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards should be zero
require.True(t, rewards.IsZero())
// start out block height
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
// allocate some rewards
initial := sdk.TokensFromConsensusPower(10).ToDec()
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// slash the validator by 50%
app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), power, sdk.NewDecWithPrec(5, 1))
2019-01-16 13:38:05 -08:00
// slash the validator by 50% again
app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), power/2, sdk.NewDecWithPrec(5, 1))
2019-01-16 13:38:05 -08:00
// fetch the validator again
val = app.StakingKeeper.Validator(ctx, valAddrs[0])
2019-01-16 13:38:05 -08:00
// increase block height
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
// allocate some more rewards
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// end period
endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards should be half the tokens
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}, rewards)
2019-01-16 13:38:05 -08:00
// commission should be the other half
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
2019-01-16 13:38:05 -08:00
}
func TestCalculateRewardsMultiDelegatorMultiSlash(t *testing.T) {
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, abci.Header{})
sh := staking.NewHandler(app.StakingKeeper)
addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1000000000))
valAddrs := simapp.ConvertAddrsToValAddrs(addr)
2019-01-16 13:38:05 -08:00
// create validator with 50% commission
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
power := int64(100)
valTokens := sdk.TokensFromConsensusPower(power)
msg := stakingtypes.NewMsgCreateValidator(valAddrs[0], valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, valTokens), stakingtypes.Description{}, commission, sdk.OneInt())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
2019-01-16 13:38:05 -08:00
// end block to bond validator
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// fetch validator and delegation
val := app.StakingKeeper.Validator(ctx, valAddrs[0])
del1 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
2019-01-16 13:38:05 -08:00
// allocate some rewards
initial := sdk.TokensFromConsensusPower(30).ToDec()
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// slash the validator
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), power, sdk.NewDecWithPrec(5, 1))
2019-01-16 13:38:05 -08:00
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
// second delegation
delTokens := sdk.TokensFromConsensusPower(100)
msg2 := stakingtypes.NewMsgDelegate(sdk.AccAddress(valAddrs[1]), valAddrs[0],
sdk.NewCoin(sdk.DefaultBondDenom, delTokens))
res, err = sh(ctx, msg2)
require.NoError(t, err)
require.NotNil(t, res)
del2 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0])
2019-01-16 13:38:05 -08:00
// end block
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// allocate some more rewards
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// slash the validator again
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
app.StakingKeeper.Slash(ctx, valConsAddr1, ctx.BlockHeight(), power, sdk.NewDecWithPrec(5, 1))
2019-01-16 13:38:05 -08:00
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
// fetch updated validator
val = app.StakingKeeper.Validator(ctx, valAddrs[0])
2019-01-16 13:38:05 -08:00
// end period
endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards for del1
rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards for del1 should be 2/3 initial (half initial first period, 1/6 initial second period)
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.QuoInt64(2).Add(initial.QuoInt64(6))}}, rewards)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards for del2
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards for del2 should be initial / 3
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.QuoInt64(3)}}, rewards)
2019-01-16 13:38:05 -08:00
// commission should be equal to initial (twice 50% commission, unaffected by slashing)
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
2019-01-16 13:38:05 -08:00
}
func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) {
app := simapp.Setup(false)
ctx := app.BaseApp.NewContext(false, abci.Header{})
sh := staking.NewHandler(app.StakingKeeper)
addr := simapp.AddTestAddrs(app, ctx, 2, sdk.NewInt(1000000000))
valAddrs := simapp.ConvertAddrsToValAddrs(addr)
initial := int64(20)
2019-06-28 13:11:27 -07:00
// set module account coins
distrAcc := app.DistrKeeper.GetDistributionAccount(ctx)
err := app.BankKeeper.SetBalances(ctx, distrAcc.GetAddress(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000))))
2020-01-30 13:31:16 -08:00
require.NoError(t, err)
app.AccountKeeper.SetModuleAccount(ctx, distrAcc)
2019-06-28 13:11:27 -07:00
tokens := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, sdk.NewDec(initial))}
2019-01-16 13:38:05 -08:00
// create validator with 50% commission
commission := stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := stakingtypes.NewMsgCreateValidator(valAddrs[0], valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), stakingtypes.Description{}, commission, sdk.OneInt())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
2019-01-16 13:38:05 -08:00
// end block to bond validator
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// fetch validator and delegation
val := app.StakingKeeper.Validator(ctx, valAddrs[0])
del1 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
2019-01-16 13:38:05 -08:00
// allocate some rewards
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// historical count should be 2 (validator init, delegation init)
require.Equal(t, uint64(2), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx))
2019-01-16 13:38:05 -08:00
// second delegation
msg2 := stakingtypes.NewMsgDelegate(sdk.AccAddress(valAddrs[1]), valAddrs[0], sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)))
res, err = sh(ctx, msg2)
require.NoError(t, err)
require.NotNil(t, res)
2019-01-16 13:38:05 -08:00
// historical count should be 3 (second delegation init)
require.Equal(t, uint64(3), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx))
2019-01-16 13:38:05 -08:00
// fetch updated validator
val = app.StakingKeeper.Validator(ctx, valAddrs[0])
del2 := app.StakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0])
2019-01-16 13:38:05 -08:00
// end block
staking.EndBlocker(ctx, app.StakingKeeper)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// allocate some more rewards
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// first delegator withdraws
_, err = app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
require.NoError(t, err)
2019-01-16 13:38:05 -08:00
// second delegator withdraws
_, err = app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0])
require.NoError(t, err)
2019-01-16 13:38:05 -08:00
// historical count should be 3 (validator init + two delegations)
require.Equal(t, uint64(3), app.DistrKeeper.GetValidatorHistoricalReferenceCount(ctx))
2019-01-16 13:38:05 -08:00
// validator withdraws commission
_, err = app.DistrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0])
require.NoError(t, err)
2019-01-16 13:38:05 -08:00
// end period
endingPeriod := app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards for del1
rewards := app.DistrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards for del1 should be zero
require.True(t, rewards.IsZero())
// calculate delegation rewards for del2
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards for del2 should be zero
require.True(t, rewards.IsZero())
// commission should be zero
require.True(t, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// allocate some more rewards
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// first delegator withdraws again
_, err = app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
require.NoError(t, err)
2019-01-16 13:38:05 -08:00
// end period
endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards for del1
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards for del1 should be zero
require.True(t, rewards.IsZero())
// calculate delegation rewards for del2
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards for del2 should be 1/4 initial
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 4)}}, rewards)
2019-01-16 13:38:05 -08:00
// commission should be half initial
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
2019-01-16 13:38:05 -08:00
// next block
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
2019-01-16 13:38:05 -08:00
// allocate some more rewards
app.DistrKeeper.AllocateTokensToValidator(ctx, val, tokens)
2019-01-16 13:38:05 -08:00
// withdraw commission
_, err = app.DistrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0])
require.NoError(t, err)
2019-01-16 13:38:05 -08:00
// end period
endingPeriod = app.DistrKeeper.IncrementValidatorPeriod(ctx, val)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards for del1
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards for del1 should be 1/4 initial
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 4)}}, rewards)
2019-01-16 13:38:05 -08:00
// calculate delegation rewards for del2
rewards = app.DistrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod)
2019-01-16 13:38:05 -08:00
// rewards for del2 should be 1/2 initial
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(initial / 2)}}, rewards)
2019-01-16 13:38:05 -08:00
// commission should be zero
require.True(t, app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
2018-10-04 18:37:40 -07:00
}