refactor: use mocks for x/distribution (#12889)
* initial commit * add mocks * TestAllocateTokensToManyValidators * one file more in, like a hundred left * progress * progress * move tests to integration * finally got TestCalculateRewardsMultiDelegator right lol * small fixes * progress * progress * progress * progress * revert test panic * progress * progress * more progress * fix go.mod * merge * merge * cache issue? * fix go.sum * fix tests * make mocks * move back simulations Co-authored-by: Marko <marbar3778@yahoo.com>
This commit is contained in:
parent
8436dc1741
commit
0024a0bf44
@ -21,6 +21,7 @@ $mockgen_cmd -source=x/authz/expected_keepers.go -package testutil -destination
|
||||
$mockgen_cmd -source=x/bank/types/expected_keepers.go -package testutil -destination x/bank/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=x/group/testutil/expected_keepers.go -package testutil -destination x/group/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=x/evidence/types/expected_keepers.go -package testutil -destination x/evidence/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=x/distribution/types/expected_keepers.go -package testutil -destination x/distribution/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=x/slashing/types/expected_keepers.go -package testutil -destination x/slashing/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=x/genutil/types/expected_keepers.go -package testutil -destination x/genutil/testutil/expected_keepers_mocks.go
|
||||
$mockgen_cmd -source=x/gov/testutil/expected_keepers.go -package testutil -destination x/gov/testutil/expected_keepers_mocks.go
|
||||
|
||||
248
tests/integration/distribution/keeper/allocation_test.go
Normal file
248
tests/integration/distribution/keeper/allocation_test.go
Normal file
@ -0,0 +1,248 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/testutil"
|
||||
disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func TestAllocateTokensToValidatorWithCommission(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
addrs := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 3, sdk.NewInt(1234))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
|
||||
// create validator with 50% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(sdk.ValAddress(addrs[0]), valConsPk0, sdk.NewInt(100), true)
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
|
||||
// allocate tokens
|
||||
tokens := sdk.DecCoins{
|
||||
{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(10)},
|
||||
}
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// check commission
|
||||
expected := sdk.DecCoins{
|
||||
{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(5)},
|
||||
}
|
||||
require.Equal(t, expected, distrKeeper.GetValidatorAccumulatedCommission(ctx, val.GetOperator()).Commission)
|
||||
|
||||
// check current rewards
|
||||
require.Equal(t, expected, distrKeeper.GetValidatorCurrentRewards(ctx, val.GetOperator()).Rewards)
|
||||
}
|
||||
|
||||
func TestAllocateTokensToManyValidators(t *testing.T) {
|
||||
var (
|
||||
accountKeeper authkeeper.AccountKeeper
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&accountKeeper,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
// reset fee pool
|
||||
distrKeeper.SetFeePool(ctx, disttypes.InitialFeePool())
|
||||
|
||||
addrs := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1234))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
|
||||
// create validator with 50% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[0], valConsPk0, sdk.NewInt(100), true)
|
||||
|
||||
// create second validator with 0% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(math.LegacyNewDec(0), math.LegacyNewDec(0), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[1], valConsPk1, sdk.NewInt(100), true)
|
||||
|
||||
abciValA := abci.Validator{
|
||||
Address: valConsPk0.Address(),
|
||||
Power: 100,
|
||||
}
|
||||
abciValB := abci.Validator{
|
||||
Address: valConsPk1.Address(),
|
||||
Power: 100,
|
||||
}
|
||||
|
||||
// assert initial state: zero outstanding rewards, zero community pool, zero commission, zero current rewards
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetFeePool(ctx).CommunityPool.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards.IsZero())
|
||||
|
||||
// allocate tokens as if both had voted and second was proposer
|
||||
fees := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)))
|
||||
feeCollector := accountKeeper.GetModuleAccount(ctx, types.FeeCollectorName)
|
||||
require.NotNil(t, feeCollector)
|
||||
|
||||
// fund fee collector
|
||||
require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, feeCollector.GetName(), fees))
|
||||
|
||||
accountKeeper.SetAccount(ctx, feeCollector)
|
||||
|
||||
votes := []abci.VoteInfo{
|
||||
{
|
||||
Validator: abciValA,
|
||||
SignedLastBlock: true,
|
||||
},
|
||||
{
|
||||
Validator: abciValB,
|
||||
SignedLastBlock: true,
|
||||
},
|
||||
}
|
||||
distrKeeper.AllocateTokens(ctx, 200, votes)
|
||||
|
||||
// 98 outstanding rewards (100 less 2 to community pool)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards)
|
||||
|
||||
// 2 community pool coins
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(2)}}, distrKeeper.GetFeePool(ctx).CommunityPool)
|
||||
|
||||
// 50% commission for first proposer, (0.5 * 98%) * 100 / 2 = 23.25
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(2450, 2)}}, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
|
||||
|
||||
// zero commission for second proposer
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
|
||||
|
||||
// just staking.proportional for first proposer less commission = (0.5 * 98%) * 100 / 2 = 24.50
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(2450, 2)}}, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards)
|
||||
|
||||
// proposer reward + staking.proportional for second proposer = (0.5 * (98%)) * 100 = 49
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards)
|
||||
}
|
||||
|
||||
func TestAllocateTokensTruncation(t *testing.T) {
|
||||
var (
|
||||
accountKeeper authkeeper.AccountKeeper
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&accountKeeper,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
// reset fee pool
|
||||
distrKeeper.SetFeePool(ctx, disttypes.InitialFeePool())
|
||||
|
||||
addrs := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 3, sdk.NewInt(1234))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
|
||||
// create validator with 10% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[0], valConsPk0, sdk.NewInt(110), true)
|
||||
|
||||
// create second validator with 10% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[1], valConsPk1, sdk.NewInt(100), true)
|
||||
|
||||
// create third validator with 10% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[2], valConsPk2, sdk.NewInt(100), true)
|
||||
|
||||
abciValA := abci.Validator{
|
||||
Address: valConsPk0.Address(),
|
||||
Power: 11,
|
||||
}
|
||||
abciValB := abci.Validator{
|
||||
Address: valConsPk1.Address(),
|
||||
Power: 10,
|
||||
}
|
||||
abciValС := abci.Validator{
|
||||
Address: valConsPk2.Address(),
|
||||
Power: 10,
|
||||
}
|
||||
|
||||
// assert initial state: zero outstanding rewards, zero community pool, zero commission, zero current rewards
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetFeePool(ctx).CommunityPool.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards.IsZero())
|
||||
|
||||
// allocate tokens as if both had voted and second was proposer
|
||||
fees := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(634195840)))
|
||||
|
||||
feeCollector := accountKeeper.GetModuleAccount(ctx, types.FeeCollectorName)
|
||||
require.NotNil(t, feeCollector)
|
||||
|
||||
require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, feeCollector.GetName(), fees))
|
||||
|
||||
accountKeeper.SetAccount(ctx, feeCollector)
|
||||
|
||||
votes := []abci.VoteInfo{
|
||||
{
|
||||
Validator: abciValA,
|
||||
SignedLastBlock: true,
|
||||
},
|
||||
{
|
||||
Validator: abciValB,
|
||||
SignedLastBlock: true,
|
||||
},
|
||||
{
|
||||
Validator: abciValС,
|
||||
SignedLastBlock: true,
|
||||
},
|
||||
}
|
||||
distrKeeper.AllocateTokens(ctx, 31, votes)
|
||||
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsValid())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsValid())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[2]).Rewards.IsValid())
|
||||
}
|
||||
21
tests/integration/distribution/keeper/common_test.go
Normal file
21
tests/integration/distribution/keeper/common_test.go
Normal file
@ -0,0 +1,21 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
var (
|
||||
PKS = simtestutil.CreateTestPubKeys(5)
|
||||
|
||||
valConsPk0 = PKS[0]
|
||||
valConsPk1 = PKS[1]
|
||||
valConsPk2 = PKS[2]
|
||||
|
||||
valConsAddr0 = sdk.ConsAddress(valConsPk0.Address())
|
||||
valConsAddr1 = sdk.ConsAddress(valConsPk1.Address())
|
||||
|
||||
distrAcc = authtypes.NewEmptyModuleAccount(types.ModuleName)
|
||||
)
|
||||
824
tests/integration/distribution/keeper/delegation_test.go
Normal file
824
tests/integration/distribution/keeper/delegation_test.go
Normal file
@ -0,0 +1,824 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func TestCalculateRewardsBasic(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
distrKeeper.DeleteAllValidatorHistoricalRewards(ctx)
|
||||
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
|
||||
// create validator with 50% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[0], valConsPk0, sdk.NewInt(100), true)
|
||||
|
||||
// end block to bond validator and start new block
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
tstaking.Ctx = ctx
|
||||
|
||||
// fetch validator and delegation
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
del := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
|
||||
// historical count should be 2 (once for validator init, once for delegation init)
|
||||
require.Equal(t, uint64(2), distrKeeper.GetValidatorHistoricalReferenceCount(ctx))
|
||||
|
||||
// end period
|
||||
endingPeriod := distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// historical count should be 2 still
|
||||
require.Equal(t, uint64(2), distrKeeper.GetValidatorHistoricalReferenceCount(ctx))
|
||||
|
||||
// calculate delegation rewards
|
||||
rewards := distrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
|
||||
|
||||
// rewards should be zero
|
||||
require.True(t, rewards.IsZero())
|
||||
|
||||
// allocate some rewards
|
||||
initial := int64(10)
|
||||
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial)}}
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// end period
|
||||
endingPeriod = distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
|
||||
|
||||
// rewards should be half the tokens
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial / 2)}}, rewards)
|
||||
|
||||
// commission should be the other half
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial / 2)}}, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
|
||||
}
|
||||
|
||||
func TestCalculateRewardsAfterSlash(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(100000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
|
||||
// create validator with 50% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
valPower := int64(100)
|
||||
tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk0, valPower, true)
|
||||
|
||||
// end block to bond validator
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// fetch validator and delegation
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
del := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
|
||||
// end period
|
||||
endingPeriod := distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards
|
||||
rewards := distrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
|
||||
|
||||
// rewards should be zero
|
||||
require.True(t, rewards.IsZero())
|
||||
|
||||
// start out block height
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
|
||||
// slash the validator by 50%
|
||||
stakingKeeper.Slash(ctx, valConsAddr0, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1))
|
||||
|
||||
// retrieve validator
|
||||
val = stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
|
||||
// increase block height
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
|
||||
// allocate some rewards
|
||||
initial := stakingKeeper.TokensFromConsensusPower(ctx, 10)
|
||||
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecFromInt(initial)}}
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// end period
|
||||
endingPeriod = distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
|
||||
|
||||
// rewards should be half the tokens
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecFromInt(initial.QuoRaw(2))}}, rewards)
|
||||
|
||||
// commission should be the other half
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecFromInt(initial.QuoRaw(2))}},
|
||||
distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
|
||||
}
|
||||
|
||||
func TestCalculateRewardsAfterManySlashes(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(100000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
|
||||
// create validator with 50% commission
|
||||
valPower := int64(100)
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk0, valPower, true)
|
||||
|
||||
// end block to bond validator
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// fetch validator and delegation
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
del := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
|
||||
// end period
|
||||
endingPeriod := distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards
|
||||
rewards := distrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
|
||||
|
||||
// rewards should be zero
|
||||
require.True(t, rewards.IsZero())
|
||||
|
||||
// start out block height
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
|
||||
// slash the validator by 50%
|
||||
stakingKeeper.Slash(ctx, valConsAddr0, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1))
|
||||
|
||||
// fetch the validator again
|
||||
val = stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
|
||||
// increase block height
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
|
||||
// allocate some rewards
|
||||
initial := stakingKeeper.TokensFromConsensusPower(ctx, 10)
|
||||
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecFromInt(initial)}}
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// slash the validator by 50% again
|
||||
stakingKeeper.Slash(ctx, valConsAddr0, ctx.BlockHeight(), valPower/2, sdk.NewDecWithPrec(5, 1))
|
||||
|
||||
// fetch the validator again
|
||||
val = stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
|
||||
// increase block height
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
|
||||
// allocate some more rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// end period
|
||||
endingPeriod = distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
|
||||
|
||||
// rewards should be half the tokens
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecFromInt(initial)}}, rewards)
|
||||
|
||||
// commission should be the other half
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecFromInt(initial)}},
|
||||
distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
|
||||
}
|
||||
|
||||
func TestCalculateRewardsMultiDelegator(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(100000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
|
||||
// create validator with 50% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[0], valConsPk0, sdk.NewInt(100), true)
|
||||
|
||||
// end block to bond validator
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// fetch validator and delegation
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
del1 := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
|
||||
// allocate some rewards
|
||||
initial := int64(20)
|
||||
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial)}}
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// second delegation
|
||||
tstaking.Ctx = ctx
|
||||
tstaking.Delegate(sdk.AccAddress(valAddrs[1]), valAddrs[0], sdk.NewInt(100))
|
||||
del2 := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0])
|
||||
|
||||
// fetch updated validator
|
||||
val = stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
|
||||
// end block
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// allocate some more rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// end period
|
||||
endingPeriod := distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards for del1
|
||||
rewards := distrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod)
|
||||
|
||||
// rewards for del1 should be 3/4 initial
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial * 3 / 4)}}, rewards)
|
||||
|
||||
// calculate delegation rewards for del2
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod)
|
||||
|
||||
// rewards for del2 should be 1/4 initial
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial * 1 / 4)}}, rewards)
|
||||
|
||||
// commission should be equal to initial (50% twice)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial)}}, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
|
||||
}
|
||||
|
||||
func TestWithdrawDelegationRewardsBasic(t *testing.T) {
|
||||
var (
|
||||
accountKeeper authkeeper.AccountKeeper
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&accountKeeper,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
distrKeeper.DeleteAllValidatorHistoricalRewards(ctx)
|
||||
|
||||
balancePower := int64(1000)
|
||||
balanceTokens := stakingKeeper.TokensFromConsensusPower(ctx, balancePower)
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 1, sdk.NewInt(1000000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
|
||||
// set module account coins
|
||||
distrAcc := distrKeeper.GetDistributionAccount(ctx)
|
||||
require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, balanceTokens))))
|
||||
accountKeeper.SetModuleAccount(ctx, distrAcc)
|
||||
|
||||
// create validator with 50% commission
|
||||
power := int64(100)
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
valTokens := tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk0, power, true)
|
||||
|
||||
// assert correct initial balance
|
||||
expTokens := balanceTokens.Sub(valTokens)
|
||||
require.Equal(t,
|
||||
sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, expTokens)},
|
||||
bankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0])),
|
||||
)
|
||||
|
||||
// end block to bond validator
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// fetch validator and delegation
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
|
||||
// allocate some rewards
|
||||
initial := stakingKeeper.TokensFromConsensusPower(ctx, 10)
|
||||
tokens := sdk.DecCoins{sdk.NewDecCoin(sdk.DefaultBondDenom, initial)}
|
||||
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// historical count should be 2 (initial + latest for delegation)
|
||||
require.Equal(t, uint64(2), distrKeeper.GetValidatorHistoricalReferenceCount(ctx))
|
||||
|
||||
// withdraw rewards
|
||||
_, err = distrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
require.Nil(t, err)
|
||||
|
||||
// historical count should still be 2 (added one record, cleared one)
|
||||
require.Equal(t, uint64(2), distrKeeper.GetValidatorHistoricalReferenceCount(ctx))
|
||||
|
||||
// assert correct balance
|
||||
exp := balanceTokens.Sub(valTokens).Add(initial.QuoRaw(2))
|
||||
require.Equal(t,
|
||||
sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, exp)},
|
||||
bankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0])),
|
||||
)
|
||||
|
||||
// withdraw commission
|
||||
_, err = distrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0])
|
||||
require.Nil(t, err)
|
||||
|
||||
// assert correct balance
|
||||
exp = balanceTokens.Sub(valTokens).Add(initial)
|
||||
require.Equal(t,
|
||||
sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, exp)},
|
||||
bankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0])),
|
||||
)
|
||||
}
|
||||
|
||||
func TestCalculateRewardsAfterManySlashesInSameBlock(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 1, sdk.NewInt(1000000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
|
||||
// create validator with 50% commission
|
||||
valPower := int64(100)
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk0, valPower, true)
|
||||
|
||||
// end block to bond validator
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// fetch validator and delegation
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
del := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
|
||||
// end period
|
||||
endingPeriod := distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards
|
||||
rewards := distrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
|
||||
|
||||
// rewards should be zero
|
||||
require.True(t, rewards.IsZero())
|
||||
|
||||
// start out block height
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
|
||||
// allocate some rewards
|
||||
initial := sdk.NewDecFromInt(stakingKeeper.TokensFromConsensusPower(ctx, 10))
|
||||
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// slash the validator by 50%
|
||||
stakingKeeper.Slash(ctx, valConsAddr0, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1))
|
||||
|
||||
// slash the validator by 50% again
|
||||
stakingKeeper.Slash(ctx, valConsAddr0, ctx.BlockHeight(), valPower/2, sdk.NewDecWithPrec(5, 1))
|
||||
|
||||
// fetch the validator again
|
||||
val = stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
|
||||
// increase block height
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
|
||||
// allocate some more rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// end period
|
||||
endingPeriod = distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del, endingPeriod)
|
||||
|
||||
// rewards should be half the tokens
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}, rewards)
|
||||
|
||||
// commission should be the other half
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
|
||||
}
|
||||
|
||||
func TestCalculateRewardsMultiDelegatorMultiSlash(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1000000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
|
||||
// create validator with 50% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
valPower := int64(100)
|
||||
tstaking.CreateValidatorWithValPower(valAddrs[0], valConsPk0, valPower, true)
|
||||
|
||||
// end block to bond validator
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// fetch validator and delegation
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
del1 := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
|
||||
// allocate some rewards
|
||||
initial := sdk.NewDecFromInt(stakingKeeper.TokensFromConsensusPower(ctx, 30))
|
||||
tokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// slash the validator
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
stakingKeeper.Slash(ctx, valConsAddr0, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1))
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
|
||||
// second delegation
|
||||
tstaking.DelegateWithPower(sdk.AccAddress(valAddrs[1]), valAddrs[0], 100)
|
||||
|
||||
del2 := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0])
|
||||
|
||||
// end block
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// allocate some more rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// slash the validator again
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
stakingKeeper.Slash(ctx, valConsAddr0, ctx.BlockHeight(), valPower, sdk.NewDecWithPrec(5, 1))
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 3)
|
||||
|
||||
// fetch updated validator
|
||||
val = stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
|
||||
// end period
|
||||
endingPeriod := distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards for del1
|
||||
rewards := distrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod)
|
||||
|
||||
// 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)
|
||||
|
||||
// calculate delegation rewards for del2
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod)
|
||||
|
||||
// rewards for del2 should be initial / 3
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial.QuoInt64(3)}}, rewards)
|
||||
|
||||
// commission should be equal to initial (twice 50% commission, unaffected by slashing)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: initial}}, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
|
||||
}
|
||||
|
||||
func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) {
|
||||
var (
|
||||
accountKeeper authkeeper.AccountKeeper
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&accountKeeper,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
distrKeeper.DeleteAllValidatorHistoricalRewards(ctx)
|
||||
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1000000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
initial := int64(20)
|
||||
|
||||
// set module account coins
|
||||
distrAcc := distrKeeper.GetDistributionAccount(ctx)
|
||||
require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000)))))
|
||||
accountKeeper.SetModuleAccount(ctx, distrAcc)
|
||||
|
||||
tokens := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyNewDec(initial))}
|
||||
|
||||
// create validator with 50% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[0], valConsPk0, sdk.NewInt(100), true)
|
||||
|
||||
// end block to bond validator
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// fetch validator and delegation
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
del1 := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
|
||||
// allocate some rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// historical count should be 2 (validator init, delegation init)
|
||||
require.Equal(t, uint64(2), distrKeeper.GetValidatorHistoricalReferenceCount(ctx))
|
||||
|
||||
// second delegation
|
||||
tstaking.Delegate(sdk.AccAddress(valAddrs[1]), valAddrs[0], sdk.NewInt(100))
|
||||
|
||||
// historical count should be 3 (second delegation init)
|
||||
require.Equal(t, uint64(3), distrKeeper.GetValidatorHistoricalReferenceCount(ctx))
|
||||
|
||||
// fetch updated validator
|
||||
val = stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
del2 := stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0])
|
||||
|
||||
// end block
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// allocate some more rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// first delegator withdraws
|
||||
_, err = distrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
// second delegator withdraws
|
||||
_, err = distrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[1]), valAddrs[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
// historical count should be 3 (validator init + two delegations)
|
||||
require.Equal(t, uint64(3), distrKeeper.GetValidatorHistoricalReferenceCount(ctx))
|
||||
|
||||
// validator withdraws commission
|
||||
_, err = distrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
// end period
|
||||
endingPeriod := distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards for del1
|
||||
rewards := distrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod)
|
||||
|
||||
// rewards for del1 should be zero
|
||||
require.True(t, rewards.IsZero())
|
||||
|
||||
// calculate delegation rewards for del2
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod)
|
||||
|
||||
// rewards for del2 should be zero
|
||||
require.True(t, rewards.IsZero())
|
||||
|
||||
// commission should be zero
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// allocate some more rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// first delegator withdraws again
|
||||
_, err = distrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
// end period
|
||||
endingPeriod = distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards for del1
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod)
|
||||
|
||||
// rewards for del1 should be zero
|
||||
require.True(t, rewards.IsZero())
|
||||
|
||||
// calculate delegation rewards for del2
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod)
|
||||
|
||||
// rewards for del2 should be 1/4 initial
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial / 4)}}, rewards)
|
||||
|
||||
// commission should be half initial
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial / 2)}}, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// allocate some more rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// withdraw commission
|
||||
_, err = distrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
// end period
|
||||
endingPeriod = distrKeeper.IncrementValidatorPeriod(ctx, val)
|
||||
|
||||
// calculate delegation rewards for del1
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del1, endingPeriod)
|
||||
|
||||
// rewards for del1 should be 1/4 initial
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial / 4)}}, rewards)
|
||||
|
||||
// calculate delegation rewards for del2
|
||||
rewards = distrKeeper.CalculateDelegationRewards(ctx, val, del2, endingPeriod)
|
||||
|
||||
// rewards for del2 should be 1/2 initial
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(initial / 2)}}, rewards)
|
||||
|
||||
// commission should be zero
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
|
||||
}
|
||||
|
||||
func Test100PercentCommissionReward(t *testing.T) {
|
||||
var (
|
||||
accountKeeper authkeeper.AccountKeeper
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&accountKeeper,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1000000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
initial := int64(20)
|
||||
|
||||
// set module account coins
|
||||
distrAcc := distrKeeper.GetDistributionAccount(ctx)
|
||||
require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, distrAcc.GetName(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000)))))
|
||||
accountKeeper.SetModuleAccount(ctx, distrAcc)
|
||||
|
||||
tokens := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyNewDec(initial))}
|
||||
|
||||
// create validator with 100% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(10, 1), sdk.NewDecWithPrec(10, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[0], valConsPk0, sdk.NewInt(100), true)
|
||||
stakingKeeper.Delegation(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
|
||||
// end block to bond validator
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// fetch validator
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
|
||||
// allocate some rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// end block
|
||||
staking.EndBlocker(ctx, stakingKeeper)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// allocate some more rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
// next block
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
|
||||
// allocate some more rewards
|
||||
distrKeeper.AllocateTokensToValidator(ctx, val, tokens)
|
||||
|
||||
rewards, err := distrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
denom, _ := sdk.GetBaseDenom()
|
||||
zeroRewards := sdk.Coins{
|
||||
sdk.Coin{
|
||||
Denom: denom,
|
||||
Amount: math.ZeroInt(),
|
||||
},
|
||||
}
|
||||
require.True(t, rewards.IsEqual(zeroRewards))
|
||||
events := ctx.EventManager().Events()
|
||||
lastEvent := events[len(events)-1]
|
||||
hasValue := false
|
||||
for _, attr := range lastEvent.Attributes {
|
||||
if string(attr.Key) == "amount" && string(attr.Value) == "0" {
|
||||
hasValue = true
|
||||
}
|
||||
}
|
||||
require.True(t, hasValue)
|
||||
}
|
||||
@ -364,7 +364,7 @@ func (suite *KeeperTestSuite) TestGRPCDelegationRewards() {
|
||||
|
||||
tstaking := teststaking.NewHelper(suite.T(), ctx, suite.stakingKeeper)
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[0], valConsPk1, sdk.NewInt(100), true)
|
||||
tstaking.CreateValidator(valAddrs[0], valConsPk0, sdk.NewInt(100), true)
|
||||
|
||||
staking.EndBlocker(ctx, suite.stakingKeeper)
|
||||
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
|
||||
186
tests/integration/distribution/keeper/keeper_test.go
Normal file
186
tests/integration/distribution/keeper/keeper_test.go
Normal file
@ -0,0 +1,186 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
)
|
||||
|
||||
func TestSetWithdrawAddr(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1000000000))
|
||||
|
||||
params := distrKeeper.GetParams(ctx)
|
||||
params.WithdrawAddrEnabled = false
|
||||
require.NoError(t, distrKeeper.SetParams(ctx, params))
|
||||
|
||||
err = distrKeeper.SetWithdrawAddr(ctx, addr[0], addr[1])
|
||||
require.NotNil(t, err)
|
||||
|
||||
params.WithdrawAddrEnabled = true
|
||||
require.NoError(t, distrKeeper.SetParams(ctx, params))
|
||||
|
||||
err = distrKeeper.SetWithdrawAddr(ctx, addr[0], addr[1])
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Error(t, distrKeeper.SetWithdrawAddr(ctx, addr[0], distrAcc.GetAddress()))
|
||||
}
|
||||
|
||||
func TestWithdrawValidatorCommission(t *testing.T) {
|
||||
var (
|
||||
accountKeeper authkeeper.AccountKeeper
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&accountKeeper,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
valCommission := sdk.DecCoins{
|
||||
sdk.NewDecCoinFromDec("mytoken", math.LegacyNewDec(5).Quo(math.LegacyNewDec(4))),
|
||||
sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(3).Quo(math.LegacyNewDec(2))),
|
||||
}
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 1, sdk.NewInt(1000000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
|
||||
// set module account coins
|
||||
distrAcc := distrKeeper.GetDistributionAccount(ctx)
|
||||
coins := sdk.NewCoins(sdk.NewCoin("mytoken", sdk.NewInt(2)), sdk.NewCoin("stake", sdk.NewInt(2)))
|
||||
require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, distrAcc.GetName(), coins))
|
||||
|
||||
accountKeeper.SetModuleAccount(ctx, distrAcc)
|
||||
|
||||
// check initial balance
|
||||
balance := bankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0]))
|
||||
expTokens := stakingKeeper.TokensFromConsensusPower(ctx, 1000)
|
||||
expCoins := sdk.NewCoins(sdk.NewCoin("stake", expTokens))
|
||||
require.Equal(t, expCoins, balance)
|
||||
|
||||
// set outstanding rewards
|
||||
distrKeeper.SetValidatorOutstandingRewards(ctx, valAddrs[0], types.ValidatorOutstandingRewards{Rewards: valCommission})
|
||||
|
||||
// set commission
|
||||
distrKeeper.SetValidatorAccumulatedCommission(ctx, valAddrs[0], types.ValidatorAccumulatedCommission{Commission: valCommission})
|
||||
|
||||
// withdraw commission
|
||||
_, err = distrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
// check balance increase
|
||||
balance = bankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0]))
|
||||
require.Equal(t, sdk.NewCoins(
|
||||
sdk.NewCoin("mytoken", sdk.NewInt(1)),
|
||||
sdk.NewCoin("stake", expTokens.AddRaw(1)),
|
||||
), balance)
|
||||
|
||||
// check remainder
|
||||
remainder := distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission
|
||||
require.Equal(t, sdk.DecCoins{
|
||||
sdk.NewDecCoinFromDec("mytoken", math.LegacyNewDec(1).Quo(math.LegacyNewDec(4))),
|
||||
sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(1).Quo(math.LegacyNewDec(2))),
|
||||
}, remainder)
|
||||
|
||||
require.True(t, true)
|
||||
}
|
||||
|
||||
func TestGetTotalRewards(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
valCommission := sdk.DecCoins{
|
||||
sdk.NewDecCoinFromDec("mytoken", math.LegacyNewDec(5).Quo(math.LegacyNewDec(4))),
|
||||
sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(3).Quo(math.LegacyNewDec(2))),
|
||||
}
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1000000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
|
||||
distrKeeper.SetValidatorOutstandingRewards(ctx, valAddrs[0], types.ValidatorOutstandingRewards{Rewards: valCommission})
|
||||
distrKeeper.SetValidatorOutstandingRewards(ctx, valAddrs[1], types.ValidatorOutstandingRewards{Rewards: valCommission})
|
||||
|
||||
expectedRewards := valCommission.MulDec(math.LegacyNewDec(2))
|
||||
totalRewards := distrKeeper.GetTotalRewards(ctx)
|
||||
|
||||
require.Equal(t, expectedRewards, totalRewards)
|
||||
}
|
||||
|
||||
func TestFundCommunityPool(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
// reset fee pool
|
||||
distrKeeper.SetFeePool(ctx, types.InitialFeePool())
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, math.ZeroInt())
|
||||
|
||||
amount := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
|
||||
require.NoError(t, banktestutil.FundAccount(bankKeeper, ctx, addr[0], amount))
|
||||
|
||||
initPool := distrKeeper.GetFeePool(ctx)
|
||||
require.Empty(t, initPool.CommunityPool)
|
||||
|
||||
err = distrKeeper.FundCommunityPool(ctx, amount, addr[0])
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, initPool.CommunityPool.Add(sdk.NewDecCoinsFromCoins(amount...)...), distrKeeper.GetFeePool(ctx).CommunityPool)
|
||||
require.Empty(t, bankKeeper.GetAllBalances(ctx, addr[0]))
|
||||
}
|
||||
117
tests/integration/distribution/keeper/params_test.go
Normal file
117
tests/integration/distribution/keeper/params_test.go
Normal file
@ -0,0 +1,117 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
)
|
||||
|
||||
func (s *KeeperTestSuite) TestParams() {
|
||||
// default params
|
||||
communityTax := sdk.NewDecWithPrec(2, 2) // 2%
|
||||
baseProposerReward := sdk.NewDecWithPrec(1, 2) // 1%
|
||||
bonusProposerReward := sdk.NewDecWithPrec(4, 2) // 4%
|
||||
withdrawAddrEnabled := true
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
input types.Params
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
{
|
||||
name: "community tax > 1",
|
||||
input: types.Params{
|
||||
CommunityTax: sdk.NewDecWithPrec(2, 0),
|
||||
BaseProposerReward: baseProposerReward,
|
||||
BonusProposerReward: bonusProposerReward,
|
||||
WithdrawAddrEnabled: withdrawAddrEnabled,
|
||||
},
|
||||
expErr: true,
|
||||
expErrMsg: "community tax should be non-negative and less than one",
|
||||
},
|
||||
{
|
||||
name: "negative community tax",
|
||||
input: types.Params{
|
||||
CommunityTax: sdk.NewDecWithPrec(-2, 1),
|
||||
BaseProposerReward: baseProposerReward,
|
||||
BonusProposerReward: bonusProposerReward,
|
||||
WithdrawAddrEnabled: withdrawAddrEnabled,
|
||||
},
|
||||
expErr: true,
|
||||
expErrMsg: "community tax should be non-negative and less than one",
|
||||
},
|
||||
{
|
||||
name: "base proposer reward > 1",
|
||||
input: types.Params{
|
||||
CommunityTax: communityTax,
|
||||
BaseProposerReward: sdk.NewDecWithPrec(2, 0),
|
||||
BonusProposerReward: bonusProposerReward,
|
||||
WithdrawAddrEnabled: withdrawAddrEnabled,
|
||||
},
|
||||
expErr: true,
|
||||
expErrMsg: "sum of base, bonus proposer rewards, and community tax cannot be greater than one",
|
||||
},
|
||||
{
|
||||
name: "negative base proposer reward",
|
||||
input: types.Params{
|
||||
CommunityTax: communityTax,
|
||||
BaseProposerReward: sdk.NewDecWithPrec(-2, 0),
|
||||
BonusProposerReward: bonusProposerReward,
|
||||
WithdrawAddrEnabled: withdrawAddrEnabled,
|
||||
},
|
||||
expErr: true,
|
||||
expErrMsg: "base proposer reward should be positive",
|
||||
},
|
||||
{
|
||||
name: "bonus proposer reward > 1",
|
||||
input: types.Params{
|
||||
CommunityTax: communityTax,
|
||||
BaseProposerReward: baseProposerReward,
|
||||
BonusProposerReward: sdk.NewDecWithPrec(2, 0),
|
||||
WithdrawAddrEnabled: withdrawAddrEnabled,
|
||||
},
|
||||
expErr: true,
|
||||
expErrMsg: "sum of base, bonus proposer rewards, and community tax cannot be greater than one",
|
||||
},
|
||||
{
|
||||
name: "negative bonus proposer reward",
|
||||
input: types.Params{
|
||||
CommunityTax: communityTax,
|
||||
BaseProposerReward: baseProposerReward,
|
||||
BonusProposerReward: sdk.NewDecWithPrec(-2, 0),
|
||||
WithdrawAddrEnabled: withdrawAddrEnabled,
|
||||
},
|
||||
expErr: true,
|
||||
expErrMsg: "bonus proposer reward should be positive",
|
||||
},
|
||||
{
|
||||
name: "all good",
|
||||
input: types.Params{
|
||||
CommunityTax: communityTax,
|
||||
BaseProposerReward: baseProposerReward,
|
||||
BonusProposerReward: bonusProposerReward,
|
||||
WithdrawAddrEnabled: withdrawAddrEnabled,
|
||||
},
|
||||
expErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
s.Run(tc.name, func() {
|
||||
expected := s.distrKeeper.GetParams(s.ctx)
|
||||
err := s.distrKeeper.SetParams(s.ctx, tc.input)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.expErrMsg)
|
||||
} else {
|
||||
expected = tc.input
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
params := s.distrKeeper.GetParams(s.ctx)
|
||||
s.Require().Equal(expected, params)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -2,50 +2,53 @@ package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/testutil"
|
||||
distrtestutil "github.com/cosmos/cosmos-sdk/x/distribution/testutil"
|
||||
disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func TestAllocateTokensToValidatorWithCommission(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
ctrl := gomock.NewController(t)
|
||||
key := sdk.NewKVStoreKey(disttypes.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(t, key, sdk.NewTransientStoreKey("transient_test"))
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig(distribution.AppModuleBasic{})
|
||||
ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: time.Now()})
|
||||
|
||||
bankKeeper := distrtestutil.NewMockBankKeeper(ctrl)
|
||||
stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl)
|
||||
accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl)
|
||||
|
||||
accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress())
|
||||
|
||||
distrKeeper := keeper.NewKeeper(
|
||||
encCfg.Codec,
|
||||
key,
|
||||
accountKeeper,
|
||||
bankKeeper,
|
||||
stakingKeeper,
|
||||
"fee_collector",
|
||||
authtypes.NewModuleAddress("gov").String(),
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
addrs := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 3, sdk.NewInt(1234))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
|
||||
// create validator with 50% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(sdk.ValAddress(addrs[0]), valConsPk1, sdk.NewInt(100), true)
|
||||
val := stakingKeeper.Validator(ctx, valAddrs[0])
|
||||
val, err := distrtestutil.CreateValidator(valConsPk0, math.NewInt(100))
|
||||
require.NoError(t, err)
|
||||
val.Commission = stakingtypes.NewCommission(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val).AnyTimes()
|
||||
|
||||
// allocate tokens
|
||||
tokens := sdk.DecCoins{
|
||||
@ -64,65 +67,70 @@ func TestAllocateTokensToValidatorWithCommission(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAllocateTokensToManyValidators(t *testing.T) {
|
||||
var (
|
||||
accountKeeper authkeeper.AccountKeeper
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
ctrl := gomock.NewController(t)
|
||||
key := sdk.NewKVStoreKey(disttypes.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(t, key, sdk.NewTransientStoreKey("transient_test"))
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig(distribution.AppModuleBasic{})
|
||||
ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: time.Now()})
|
||||
|
||||
bankKeeper := distrtestutil.NewMockBankKeeper(ctrl)
|
||||
stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl)
|
||||
accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl)
|
||||
|
||||
feeCollectorAcc := authtypes.NewEmptyModuleAccount("fee_collector")
|
||||
accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress())
|
||||
accountKeeper.EXPECT().GetModuleAccount(gomock.Any(), "fee_collector").Return(feeCollectorAcc)
|
||||
|
||||
distrKeeper := keeper.NewKeeper(
|
||||
encCfg.Codec,
|
||||
key,
|
||||
accountKeeper,
|
||||
bankKeeper,
|
||||
stakingKeeper,
|
||||
"fee_collector",
|
||||
authtypes.NewModuleAddress("gov").String(),
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&accountKeeper,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
// reset fee pool
|
||||
// reset fee pool & set params
|
||||
distrKeeper.SetParams(ctx, disttypes.DefaultParams())
|
||||
distrKeeper.SetFeePool(ctx, disttypes.InitialFeePool())
|
||||
|
||||
addrs := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1234))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
|
||||
// create validator with 50% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[0], valConsPk1, sdk.NewInt(100), true)
|
||||
valAddr0 := sdk.ValAddress(valConsAddr0)
|
||||
val0, err := distrtestutil.CreateValidator(valConsPk0, math.NewInt(100))
|
||||
require.NoError(t, err)
|
||||
val0.Commission = stakingtypes.NewCommission(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0))
|
||||
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val0).AnyTimes()
|
||||
|
||||
// create second validator with 0% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(math.LegacyNewDec(0), math.LegacyNewDec(0), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[1], valConsPk2, sdk.NewInt(100), true)
|
||||
valAddr1 := sdk.ValAddress(valConsAddr1)
|
||||
val1, err := distrtestutil.CreateValidator(valConsPk1, math.NewInt(100))
|
||||
require.NoError(t, err)
|
||||
val1.Commission = stakingtypes.NewCommission(math.LegacyNewDec(0), math.LegacyNewDec(0), math.LegacyNewDec(0))
|
||||
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk1)).Return(val1).AnyTimes()
|
||||
|
||||
abciValA := abci.Validator{
|
||||
Address: valConsPk1.Address(),
|
||||
Address: valConsPk0.Address(),
|
||||
Power: 100,
|
||||
}
|
||||
abciValB := abci.Validator{
|
||||
Address: valConsPk2.Address(),
|
||||
Address: valConsPk1.Address(),
|
||||
Power: 100,
|
||||
}
|
||||
|
||||
// assert initial state: zero outstanding rewards, zero community pool, zero commission, zero current rewards
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddr0).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddr1).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetFeePool(ctx).CommunityPool.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddr0).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddr1).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddr0).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddr1).Rewards.IsZero())
|
||||
|
||||
// allocate tokens as if both had voted and second was proposer
|
||||
fees := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)))
|
||||
feeCollector := accountKeeper.GetModuleAccount(ctx, types.FeeCollectorName)
|
||||
require.NotNil(t, feeCollector)
|
||||
|
||||
// fund fee collector
|
||||
require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, feeCollector.GetName(), fees))
|
||||
|
||||
accountKeeper.SetAccount(ctx, feeCollector)
|
||||
bankKeeper.EXPECT().GetAllBalances(gomock.Any(), feeCollectorAcc.GetAddress()).Return(fees)
|
||||
bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), "fee_collector", disttypes.ModuleName, fees)
|
||||
|
||||
votes := []abci.VoteInfo{
|
||||
{
|
||||
@ -137,94 +145,102 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
|
||||
distrKeeper.AllocateTokens(ctx, 200, votes)
|
||||
|
||||
// 98 outstanding rewards (100 less 2 to community pool)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddr0).Rewards)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddr1).Rewards)
|
||||
|
||||
// 2 community pool coins
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: math.LegacyNewDec(2)}}, distrKeeper.GetFeePool(ctx).CommunityPool)
|
||||
|
||||
// 50% commission for first proposer, (0.5 * 98%) * 100 / 2 = 23.25
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(2450, 2)}}, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(2450, 2)}}, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddr0).Commission)
|
||||
|
||||
// zero commission for second proposer
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddr1).Commission.IsZero())
|
||||
|
||||
// just staking.proportional for first proposer less commission = (0.5 * 98%) * 100 / 2 = 24.50
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(2450, 2)}}, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(2450, 2)}}, distrKeeper.GetValidatorCurrentRewards(ctx, valAddr0).Rewards)
|
||||
|
||||
// proposer reward + staking.proportional for second proposer = (0.5 * (98%)) * 100 = 49
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards)
|
||||
require.Equal(t, sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecWithPrec(490, 1)}}, distrKeeper.GetValidatorCurrentRewards(ctx, valAddr1).Rewards)
|
||||
}
|
||||
|
||||
func TestAllocateTokensTruncation(t *testing.T) {
|
||||
var (
|
||||
accountKeeper authkeeper.AccountKeeper
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
ctrl := gomock.NewController(t)
|
||||
key := sdk.NewKVStoreKey(disttypes.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(t, key, sdk.NewTransientStoreKey("transient_test"))
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig(distribution.AppModuleBasic{})
|
||||
ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: time.Now()})
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&accountKeeper,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
bankKeeper := distrtestutil.NewMockBankKeeper(ctrl)
|
||||
stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl)
|
||||
accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
feeCollectorAcc := authtypes.NewEmptyModuleAccount("fee_collector")
|
||||
accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress())
|
||||
accountKeeper.EXPECT().GetModuleAccount(gomock.Any(), "fee_collector").Return(feeCollectorAcc)
|
||||
|
||||
distrKeeper := keeper.NewKeeper(
|
||||
encCfg.Codec,
|
||||
key,
|
||||
accountKeeper,
|
||||
bankKeeper,
|
||||
stakingKeeper,
|
||||
"fee_collector",
|
||||
authtypes.NewModuleAddress("gov").String(),
|
||||
)
|
||||
|
||||
// reset fee pool
|
||||
distrKeeper.SetFeePool(ctx, disttypes.InitialFeePool())
|
||||
|
||||
addrs := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 3, sdk.NewInt(1234))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs)
|
||||
tstaking := teststaking.NewHelper(t, ctx, stakingKeeper)
|
||||
distrKeeper.SetParams(ctx, disttypes.DefaultParams())
|
||||
|
||||
// create validator with 10% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[0], valConsPk1, sdk.NewInt(110), true)
|
||||
valAddr0 := sdk.ValAddress(valConsAddr0)
|
||||
val0, err := distrtestutil.CreateValidator(valConsPk0, math.NewInt(100))
|
||||
require.NoError(t, err)
|
||||
val0.Commission = stakingtypes.NewCommission(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
|
||||
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk0)).Return(val0).AnyTimes()
|
||||
|
||||
// create second validator with 10% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[1], valConsPk2, sdk.NewInt(100), true)
|
||||
valAddr1 := sdk.ValAddress(valConsAddr1)
|
||||
val1, err := distrtestutil.CreateValidator(valConsPk1, math.NewInt(100))
|
||||
require.NoError(t, err)
|
||||
val1.Commission = stakingtypes.NewCommission(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
|
||||
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk1)).Return(val1).AnyTimes()
|
||||
|
||||
// create third validator with 10% commission
|
||||
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
|
||||
tstaking.CreateValidator(valAddrs[2], valConsPk3, sdk.NewInt(100), true)
|
||||
valAddr2 := sdk.ValAddress(valConsAddr2)
|
||||
val2, err := stakingtypes.NewValidator(sdk.ValAddress(valConsAddr2), valConsPk1, stakingtypes.Description{})
|
||||
require.NoError(t, err)
|
||||
val2.Commission = stakingtypes.NewCommission(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), math.LegacyNewDec(0))
|
||||
stakingKeeper.EXPECT().ValidatorByConsAddr(gomock.Any(), sdk.GetConsAddress(valConsPk2)).Return(val2).AnyTimes()
|
||||
|
||||
abciValA := abci.Validator{
|
||||
Address: valConsPk1.Address(),
|
||||
Address: valConsPk0.Address(),
|
||||
Power: 11,
|
||||
}
|
||||
abciValB := abci.Validator{
|
||||
Address: valConsPk2.Address(),
|
||||
Address: valConsPk1.Address(),
|
||||
Power: 10,
|
||||
}
|
||||
abciValС := abci.Validator{
|
||||
Address: valConsPk3.Address(),
|
||||
abciValC := abci.Validator{
|
||||
Address: valConsPk2.Address(),
|
||||
Power: 10,
|
||||
}
|
||||
|
||||
// assert initial state: zero outstanding rewards, zero community pool, zero commission, zero current rewards
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddr0).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddr1).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddr1).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetFeePool(ctx).CommunityPool.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[1]).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[0]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddrs[1]).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddr0).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddr1).Commission.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddr0).Rewards.IsZero())
|
||||
require.True(t, distrKeeper.GetValidatorCurrentRewards(ctx, valAddr1).Rewards.IsZero())
|
||||
|
||||
// allocate tokens as if both had voted and second was proposer
|
||||
fees := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(634195840)))
|
||||
|
||||
feeCollector := accountKeeper.GetModuleAccount(ctx, types.FeeCollectorName)
|
||||
require.NotNil(t, feeCollector)
|
||||
|
||||
require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, feeCollector.GetName(), fees))
|
||||
|
||||
accountKeeper.SetAccount(ctx, feeCollector)
|
||||
bankKeeper.EXPECT().GetAllBalances(gomock.Any(), feeCollectorAcc.GetAddress()).Return(fees)
|
||||
bankKeeper.EXPECT().SendCoinsFromModuleToModule(gomock.Any(), "fee_collector", disttypes.ModuleName, fees)
|
||||
|
||||
votes := []abci.VoteInfo{
|
||||
{
|
||||
@ -236,13 +252,13 @@ func TestAllocateTokensTruncation(t *testing.T) {
|
||||
SignedLastBlock: true,
|
||||
},
|
||||
{
|
||||
Validator: abciValС,
|
||||
Validator: abciValC,
|
||||
SignedLastBlock: true,
|
||||
},
|
||||
}
|
||||
distrKeeper.AllocateTokens(ctx, 31, votes)
|
||||
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[0]).Rewards.IsValid())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[1]).Rewards.IsValid())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddrs[2]).Rewards.IsValid())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddr0).Rewards.IsValid())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddr1).Rewards.IsValid())
|
||||
require.True(t, distrKeeper.GetValidatorOutstandingRewards(ctx, valAddr2).Rewards.IsValid())
|
||||
}
|
||||
|
||||
@ -10,10 +10,11 @@ import (
|
||||
var (
|
||||
PKS = simtestutil.CreateTestPubKeys(5)
|
||||
|
||||
valConsPk1 = PKS[0]
|
||||
valConsPk2 = PKS[1]
|
||||
valConsPk3 = PKS[2]
|
||||
valConsPk0 = PKS[0]
|
||||
valConsPk1 = PKS[1]
|
||||
valConsPk2 = PKS[2]
|
||||
|
||||
valConsAddr0 = sdk.ConsAddress(valConsPk0.Address())
|
||||
valConsAddr1 = sdk.ConsAddress(valConsPk1.Address())
|
||||
valConsAddr2 = sdk.ConsAddress(valConsPk2.Address())
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -2,114 +2,117 @@ package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/testutil"
|
||||
distrtestutil "github.com/cosmos/cosmos-sdk/x/distribution/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
)
|
||||
|
||||
func TestSetWithdrawAddr(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
ctrl := gomock.NewController(t)
|
||||
key := sdk.NewKVStoreKey(types.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(t, key, sdk.NewTransientStoreKey("transient_test"))
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig(distribution.AppModuleBasic{})
|
||||
ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: time.Now()})
|
||||
addrs := simtestutil.CreateIncrementalAccounts(2)
|
||||
|
||||
delegatorAddr := addrs[0]
|
||||
withdrawAddr := addrs[1]
|
||||
|
||||
bankKeeper := distrtestutil.NewMockBankKeeper(ctrl)
|
||||
stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl)
|
||||
accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl)
|
||||
|
||||
accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress())
|
||||
|
||||
bankKeeper.EXPECT().BlockedAddr(withdrawAddr).Return(false).AnyTimes()
|
||||
bankKeeper.EXPECT().BlockedAddr(distrAcc.GetAddress()).Return(true).AnyTimes()
|
||||
|
||||
distrKeeper := keeper.NewKeeper(
|
||||
encCfg.Codec,
|
||||
key,
|
||||
accountKeeper,
|
||||
bankKeeper,
|
||||
stakingKeeper,
|
||||
"fee_collector",
|
||||
authtypes.NewModuleAddress("gov").String(),
|
||||
)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1000000000))
|
||||
|
||||
params := distrKeeper.GetParams(ctx)
|
||||
params := types.DefaultParams()
|
||||
params.WithdrawAddrEnabled = false
|
||||
require.NoError(t, distrKeeper.SetParams(ctx, params))
|
||||
|
||||
err = distrKeeper.SetWithdrawAddr(ctx, addr[0], addr[1])
|
||||
err := distrKeeper.SetWithdrawAddr(ctx, delegatorAddr, withdrawAddr)
|
||||
require.NotNil(t, err)
|
||||
|
||||
params.WithdrawAddrEnabled = true
|
||||
require.NoError(t, distrKeeper.SetParams(ctx, params))
|
||||
|
||||
err = distrKeeper.SetWithdrawAddr(ctx, addr[0], addr[1])
|
||||
err = distrKeeper.SetWithdrawAddr(ctx, delegatorAddr, withdrawAddr)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Error(t, distrKeeper.SetWithdrawAddr(ctx, addr[0], distrAcc.GetAddress()))
|
||||
require.Error(t, distrKeeper.SetWithdrawAddr(ctx, delegatorAddr, distrAcc.GetAddress()))
|
||||
}
|
||||
|
||||
func TestWithdrawValidatorCommission(t *testing.T) {
|
||||
var (
|
||||
accountKeeper authkeeper.AccountKeeper
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
ctrl := gomock.NewController(t)
|
||||
key := sdk.NewKVStoreKey(types.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(t, key, sdk.NewTransientStoreKey("transient_test"))
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig(distribution.AppModuleBasic{})
|
||||
ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: time.Now()})
|
||||
addrs := simtestutil.CreateIncrementalAccounts(1)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&accountKeeper,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
valAddr := sdk.ValAddress(addrs[0])
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
bankKeeper := distrtestutil.NewMockBankKeeper(ctrl)
|
||||
stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl)
|
||||
accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl)
|
||||
|
||||
accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress())
|
||||
|
||||
valCommission := sdk.DecCoins{
|
||||
sdk.NewDecCoinFromDec("mytoken", math.LegacyNewDec(5).Quo(math.LegacyNewDec(4))),
|
||||
sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(3).Quo(math.LegacyNewDec(2))),
|
||||
}
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 1, sdk.NewInt(1000000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
|
||||
// set module account coins
|
||||
distrAcc := distrKeeper.GetDistributionAccount(ctx)
|
||||
coins := sdk.NewCoins(sdk.NewCoin("mytoken", sdk.NewInt(2)), sdk.NewCoin("stake", sdk.NewInt(2)))
|
||||
require.NoError(t, banktestutil.FundModuleAccount(bankKeeper, ctx, distrAcc.GetName(), coins))
|
||||
|
||||
accountKeeper.SetModuleAccount(ctx, distrAcc)
|
||||
|
||||
// check initial balance
|
||||
balance := bankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0]))
|
||||
expTokens := stakingKeeper.TokensFromConsensusPower(ctx, 1000)
|
||||
expCoins := sdk.NewCoins(sdk.NewCoin("stake", expTokens))
|
||||
require.Equal(t, expCoins, balance)
|
||||
distrKeeper := keeper.NewKeeper(
|
||||
encCfg.Codec,
|
||||
key,
|
||||
accountKeeper,
|
||||
bankKeeper,
|
||||
stakingKeeper,
|
||||
"fee_collector",
|
||||
authtypes.NewModuleAddress("gov").String(),
|
||||
)
|
||||
|
||||
// set outstanding rewards
|
||||
distrKeeper.SetValidatorOutstandingRewards(ctx, valAddrs[0], types.ValidatorOutstandingRewards{Rewards: valCommission})
|
||||
distrKeeper.SetValidatorOutstandingRewards(ctx, valAddr, types.ValidatorOutstandingRewards{Rewards: valCommission})
|
||||
|
||||
// set commission
|
||||
distrKeeper.SetValidatorAccumulatedCommission(ctx, valAddrs[0], types.ValidatorAccumulatedCommission{Commission: valCommission})
|
||||
distrKeeper.SetValidatorAccumulatedCommission(ctx, valAddr, types.ValidatorAccumulatedCommission{Commission: valCommission})
|
||||
|
||||
// withdraw commission
|
||||
_, err = distrKeeper.WithdrawValidatorCommission(ctx, valAddrs[0])
|
||||
coins := sdk.NewCoins(sdk.NewCoin("mytoken", sdk.NewInt(1)), sdk.NewCoin("stake", sdk.NewInt(1)))
|
||||
// if SendCoinsFromModuleToAccount is called, we know that the withdraw was successful
|
||||
bankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), "distribution", addrs[0], coins).Return(nil)
|
||||
|
||||
_, err := distrKeeper.WithdrawValidatorCommission(ctx, valAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
// check balance increase
|
||||
balance = bankKeeper.GetAllBalances(ctx, sdk.AccAddress(valAddrs[0]))
|
||||
require.Equal(t, sdk.NewCoins(
|
||||
sdk.NewCoin("mytoken", sdk.NewInt(1)),
|
||||
sdk.NewCoin("stake", expTokens.AddRaw(1)),
|
||||
), balance)
|
||||
|
||||
// check remainder
|
||||
remainder := distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddrs[0]).Commission
|
||||
remainder := distrKeeper.GetValidatorAccumulatedCommission(ctx, valAddr).Commission
|
||||
require.Equal(t, sdk.DecCoins{
|
||||
sdk.NewDecCoinFromDec("mytoken", math.LegacyNewDec(1).Quo(math.LegacyNewDec(4))),
|
||||
sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(1).Quo(math.LegacyNewDec(2))),
|
||||
@ -119,31 +122,39 @@ func TestWithdrawValidatorCommission(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTotalRewards(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
ctrl := gomock.NewController(t)
|
||||
key := sdk.NewKVStoreKey(types.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(t, key, sdk.NewTransientStoreKey("transient_test"))
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig(distribution.AppModuleBasic{})
|
||||
ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: time.Now()})
|
||||
addrs := simtestutil.CreateIncrementalAccounts(2)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
valAddr0 := sdk.ValAddress(addrs[0])
|
||||
valAddr1 := sdk.ValAddress(addrs[1])
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
bankKeeper := distrtestutil.NewMockBankKeeper(ctrl)
|
||||
stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl)
|
||||
accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl)
|
||||
|
||||
accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress())
|
||||
|
||||
distrKeeper := keeper.NewKeeper(
|
||||
encCfg.Codec,
|
||||
key,
|
||||
accountKeeper,
|
||||
bankKeeper,
|
||||
stakingKeeper,
|
||||
"fee_collector",
|
||||
authtypes.NewModuleAddress("gov").String(),
|
||||
)
|
||||
|
||||
valCommission := sdk.DecCoins{
|
||||
sdk.NewDecCoinFromDec("mytoken", math.LegacyNewDec(5).Quo(math.LegacyNewDec(4))),
|
||||
sdk.NewDecCoinFromDec("stake", math.LegacyNewDec(3).Quo(math.LegacyNewDec(2))),
|
||||
}
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(1000000000))
|
||||
valAddrs := simtestutil.ConvertAddrsToValAddrs(addr)
|
||||
|
||||
distrKeeper.SetValidatorOutstandingRewards(ctx, valAddrs[0], types.ValidatorOutstandingRewards{Rewards: valCommission})
|
||||
distrKeeper.SetValidatorOutstandingRewards(ctx, valAddrs[1], types.ValidatorOutstandingRewards{Rewards: valCommission})
|
||||
distrKeeper.SetValidatorOutstandingRewards(ctx, valAddr0, types.ValidatorOutstandingRewards{Rewards: valCommission})
|
||||
distrKeeper.SetValidatorOutstandingRewards(ctx, valAddr1, types.ValidatorOutstandingRewards{Rewards: valCommission})
|
||||
|
||||
expectedRewards := valCommission.MulDec(math.LegacyNewDec(2))
|
||||
totalRewards := distrKeeper.GetTotalRewards(ctx)
|
||||
@ -152,35 +163,39 @@ func TestGetTotalRewards(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFundCommunityPool(t *testing.T) {
|
||||
var (
|
||||
bankKeeper bankkeeper.Keeper
|
||||
distrKeeper keeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
)
|
||||
ctrl := gomock.NewController(t)
|
||||
key := sdk.NewKVStoreKey(types.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(t, key, sdk.NewTransientStoreKey("transient_test"))
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig(distribution.AppModuleBasic{})
|
||||
ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Time: time.Now()})
|
||||
addrs := simtestutil.CreateIncrementalAccounts(1)
|
||||
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&bankKeeper,
|
||||
&distrKeeper,
|
||||
&stakingKeeper,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
bankKeeper := distrtestutil.NewMockBankKeeper(ctrl)
|
||||
stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl)
|
||||
accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress())
|
||||
|
||||
distrKeeper := keeper.NewKeeper(
|
||||
encCfg.Codec,
|
||||
key,
|
||||
accountKeeper,
|
||||
bankKeeper,
|
||||
stakingKeeper,
|
||||
"fee_collector",
|
||||
authtypes.NewModuleAddress("gov").String(),
|
||||
)
|
||||
|
||||
// reset fee pool
|
||||
distrKeeper.SetFeePool(ctx, types.InitialFeePool())
|
||||
|
||||
addr := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 2, math.ZeroInt())
|
||||
|
||||
amount := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
|
||||
require.NoError(t, banktestutil.FundAccount(bankKeeper, ctx, addr[0], amount))
|
||||
|
||||
initPool := distrKeeper.GetFeePool(ctx)
|
||||
require.Empty(t, initPool.CommunityPool)
|
||||
|
||||
err = distrKeeper.FundCommunityPool(ctx, amount, addr[0])
|
||||
amount := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
|
||||
bankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), addrs[0], "distribution", amount).Return(nil)
|
||||
err := distrKeeper.FundCommunityPool(ctx, amount, addrs[0])
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, initPool.CommunityPool.Add(sdk.NewDecCoinsFromCoins(amount...)...), distrKeeper.GetFeePool(ctx).CommunityPool)
|
||||
require.Empty(t, bankKeeper.GetAllBalances(ctx, addr[0]))
|
||||
}
|
||||
|
||||
@ -1,11 +1,45 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
distrtestutil "github.com/cosmos/cosmos-sdk/x/distribution/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
|
||||
func (s *KeeperTestSuite) TestParams() {
|
||||
func TestParams(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
key := sdk.NewKVStoreKey(disttypes.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(t, key, sdk.NewTransientStoreKey("transient_test"))
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig(distribution.AppModuleBasic{})
|
||||
ctx := testCtx.Ctx.WithBlockHeader(tmproto.Header{Height: 1})
|
||||
|
||||
bankKeeper := distrtestutil.NewMockBankKeeper(ctrl)
|
||||
stakingKeeper := distrtestutil.NewMockStakingKeeper(ctrl)
|
||||
accountKeeper := distrtestutil.NewMockAccountKeeper(ctrl)
|
||||
|
||||
accountKeeper.EXPECT().GetModuleAddress("distribution").Return(distrAcc.GetAddress())
|
||||
|
||||
distrKeeper := keeper.NewKeeper(
|
||||
encCfg.Codec,
|
||||
key,
|
||||
accountKeeper,
|
||||
bankKeeper,
|
||||
stakingKeeper,
|
||||
"fee_collector",
|
||||
authtypes.NewModuleAddress("gov").String(),
|
||||
)
|
||||
|
||||
// default params
|
||||
communityTax := sdk.NewDecWithPrec(2, 2) // 2%
|
||||
baseProposerReward := sdk.NewDecWithPrec(1, 2) // 1%
|
||||
@ -98,20 +132,20 @@ func (s *KeeperTestSuite) TestParams() {
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
s.Run(tc.name, func() {
|
||||
expected := s.distrKeeper.GetParams(s.ctx)
|
||||
err := s.distrKeeper.SetParams(s.ctx, tc.input)
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
expected := distrKeeper.GetParams(ctx)
|
||||
err := distrKeeper.SetParams(ctx, tc.input)
|
||||
|
||||
if tc.expErr {
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), tc.expErrMsg)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.expErrMsg)
|
||||
} else {
|
||||
expected = tc.input
|
||||
s.Require().NoError(err)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
params := s.distrKeeper.GetParams(s.ctx)
|
||||
s.Require().Equal(expected, params)
|
||||
params := distrKeeper.GetParams(ctx)
|
||||
require.Equal(t, expected, params)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
376
x/distribution/testutil/expected_keepers_mocks.go
Normal file
376
x/distribution/testutil/expected_keepers_mocks.go
Normal file
@ -0,0 +1,376 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: x/distribution/types/expected_keepers.go
|
||||
|
||||
// Package testutil is a generated GoMock package.
|
||||
package testutil
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
types "github.com/cosmos/cosmos-sdk/types"
|
||||
types0 "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
types1 "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockAccountKeeper is a mock of AccountKeeper interface.
|
||||
type MockAccountKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockAccountKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper.
|
||||
type MockAccountKeeperMockRecorder struct {
|
||||
mock *MockAccountKeeper
|
||||
}
|
||||
|
||||
// NewMockAccountKeeper creates a new mock instance.
|
||||
func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper {
|
||||
mock := &MockAccountKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockAccountKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetAccount mocks base method.
|
||||
func (m *MockAccountKeeper) GetAccount(ctx types.Context, addr types.AccAddress) types0.AccountI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAccount", ctx, addr)
|
||||
ret0, _ := ret[0].(types0.AccountI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetAccount indicates an expected call of GetAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetAccount(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetAccount), ctx, addr)
|
||||
}
|
||||
|
||||
// GetModuleAccount mocks base method.
|
||||
func (m *MockAccountKeeper) GetModuleAccount(ctx types.Context, name string) types0.ModuleAccountI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModuleAccount", ctx, name)
|
||||
ret0, _ := ret[0].(types0.ModuleAccountI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetModuleAccount indicates an expected call of GetModuleAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModuleAccount(ctx, name interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAccount), ctx, name)
|
||||
}
|
||||
|
||||
// GetModuleAddress mocks base method.
|
||||
func (m *MockAccountKeeper) GetModuleAddress(name string) types.AccAddress {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModuleAddress", name)
|
||||
ret0, _ := ret[0].(types.AccAddress)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetModuleAddress indicates an expected call of GetModuleAddress.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModuleAddress(name interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAddress", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAddress), name)
|
||||
}
|
||||
|
||||
// SetModuleAccount mocks base method.
|
||||
func (m *MockAccountKeeper) SetModuleAccount(arg0 types.Context, arg1 types0.ModuleAccountI) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetModuleAccount", arg0, arg1)
|
||||
}
|
||||
|
||||
// SetModuleAccount indicates an expected call of SetModuleAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) SetModuleAccount(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetModuleAccount", reflect.TypeOf((*MockAccountKeeper)(nil).SetModuleAccount), arg0, arg1)
|
||||
}
|
||||
|
||||
// MockBankKeeper is a mock of BankKeeper interface.
|
||||
type MockBankKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockBankKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper.
|
||||
type MockBankKeeperMockRecorder struct {
|
||||
mock *MockBankKeeper
|
||||
}
|
||||
|
||||
// NewMockBankKeeper creates a new mock instance.
|
||||
func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper {
|
||||
mock := &MockBankKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockBankKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// BlockedAddr mocks base method.
|
||||
func (m *MockBankKeeper) BlockedAddr(addr types.AccAddress) bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "BlockedAddr", addr)
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// BlockedAddr indicates an expected call of BlockedAddr.
|
||||
func (mr *MockBankKeeperMockRecorder) BlockedAddr(addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockedAddr", reflect.TypeOf((*MockBankKeeper)(nil).BlockedAddr), addr)
|
||||
}
|
||||
|
||||
// GetAllBalances mocks base method.
|
||||
func (m *MockBankKeeper) GetAllBalances(ctx types.Context, addr types.AccAddress) types.Coins {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAllBalances", ctx, addr)
|
||||
ret0, _ := ret[0].(types.Coins)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetAllBalances indicates an expected call of GetAllBalances.
|
||||
func (mr *MockBankKeeperMockRecorder) GetAllBalances(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBalances", reflect.TypeOf((*MockBankKeeper)(nil).GetAllBalances), ctx, addr)
|
||||
}
|
||||
|
||||
// SendCoinsFromAccountToModule mocks base method.
|
||||
func (m *MockBankKeeper) SendCoinsFromAccountToModule(ctx types.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SendCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SendCoinsFromAccountToModule indicates an expected call of SendCoinsFromAccountToModule.
|
||||
func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt)
|
||||
}
|
||||
|
||||
// SendCoinsFromModuleToAccount mocks base method.
|
||||
func (m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx types.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SendCoinsFromModuleToAccount", ctx, senderModule, recipientAddr, amt)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SendCoinsFromModuleToAccount indicates an expected call of SendCoinsFromModuleToAccount.
|
||||
func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt)
|
||||
}
|
||||
|
||||
// SendCoinsFromModuleToModule mocks base method.
|
||||
func (m *MockBankKeeper) SendCoinsFromModuleToModule(ctx types.Context, senderModule, recipientModule string, amt types.Coins) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SendCoinsFromModuleToModule", ctx, senderModule, recipientModule, amt)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SendCoinsFromModuleToModule indicates an expected call of SendCoinsFromModuleToModule.
|
||||
func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToModule(ctx, senderModule, recipientModule, amt interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToModule), ctx, senderModule, recipientModule, amt)
|
||||
}
|
||||
|
||||
// SpendableCoins mocks base method.
|
||||
func (m *MockBankKeeper) SpendableCoins(ctx types.Context, addr types.AccAddress) types.Coins {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SpendableCoins", ctx, addr)
|
||||
ret0, _ := ret[0].(types.Coins)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SpendableCoins indicates an expected call of SpendableCoins.
|
||||
func (mr *MockBankKeeperMockRecorder) SpendableCoins(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoins", reflect.TypeOf((*MockBankKeeper)(nil).SpendableCoins), ctx, addr)
|
||||
}
|
||||
|
||||
// MockStakingKeeper is a mock of StakingKeeper interface.
|
||||
type MockStakingKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockStakingKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockStakingKeeperMockRecorder is the mock recorder for MockStakingKeeper.
|
||||
type MockStakingKeeperMockRecorder struct {
|
||||
mock *MockStakingKeeper
|
||||
}
|
||||
|
||||
// NewMockStakingKeeper creates a new mock instance.
|
||||
func NewMockStakingKeeper(ctrl *gomock.Controller) *MockStakingKeeper {
|
||||
mock := &MockStakingKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockStakingKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Delegation mocks base method.
|
||||
func (m *MockStakingKeeper) Delegation(arg0 types.Context, arg1 types.AccAddress, arg2 types.ValAddress) types1.DelegationI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Delegation", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(types1.DelegationI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Delegation indicates an expected call of Delegation.
|
||||
func (mr *MockStakingKeeperMockRecorder) Delegation(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delegation", reflect.TypeOf((*MockStakingKeeper)(nil).Delegation), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// GetAllDelegatorDelegations mocks base method.
|
||||
func (m *MockStakingKeeper) GetAllDelegatorDelegations(ctx types.Context, delegator types.AccAddress) []types1.Delegation {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAllDelegatorDelegations", ctx, delegator)
|
||||
ret0, _ := ret[0].([]types1.Delegation)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetAllDelegatorDelegations indicates an expected call of GetAllDelegatorDelegations.
|
||||
func (mr *MockStakingKeeperMockRecorder) GetAllDelegatorDelegations(ctx, delegator interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllDelegatorDelegations", reflect.TypeOf((*MockStakingKeeper)(nil).GetAllDelegatorDelegations), ctx, delegator)
|
||||
}
|
||||
|
||||
// GetAllSDKDelegations mocks base method.
|
||||
func (m *MockStakingKeeper) GetAllSDKDelegations(ctx types.Context) []types1.Delegation {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAllSDKDelegations", ctx)
|
||||
ret0, _ := ret[0].([]types1.Delegation)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetAllSDKDelegations indicates an expected call of GetAllSDKDelegations.
|
||||
func (mr *MockStakingKeeperMockRecorder) GetAllSDKDelegations(ctx interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllSDKDelegations", reflect.TypeOf((*MockStakingKeeper)(nil).GetAllSDKDelegations), ctx)
|
||||
}
|
||||
|
||||
// GetAllValidators mocks base method.
|
||||
func (m *MockStakingKeeper) GetAllValidators(ctx types.Context) []types1.Validator {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAllValidators", ctx)
|
||||
ret0, _ := ret[0].([]types1.Validator)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetAllValidators indicates an expected call of GetAllValidators.
|
||||
func (mr *MockStakingKeeperMockRecorder) GetAllValidators(ctx interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllValidators", reflect.TypeOf((*MockStakingKeeper)(nil).GetAllValidators), ctx)
|
||||
}
|
||||
|
||||
// IterateDelegations mocks base method.
|
||||
func (m *MockStakingKeeper) IterateDelegations(ctx types.Context, delegator types.AccAddress, fn func(int64, types1.DelegationI) bool) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "IterateDelegations", ctx, delegator, fn)
|
||||
}
|
||||
|
||||
// IterateDelegations indicates an expected call of IterateDelegations.
|
||||
func (mr *MockStakingKeeperMockRecorder) IterateDelegations(ctx, delegator, fn interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateDelegations", reflect.TypeOf((*MockStakingKeeper)(nil).IterateDelegations), ctx, delegator, fn)
|
||||
}
|
||||
|
||||
// IterateValidators mocks base method.
|
||||
func (m *MockStakingKeeper) IterateValidators(arg0 types.Context, arg1 func(int64, types1.ValidatorI) bool) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "IterateValidators", arg0, arg1)
|
||||
}
|
||||
|
||||
// IterateValidators indicates an expected call of IterateValidators.
|
||||
func (mr *MockStakingKeeperMockRecorder) IterateValidators(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateValidators", reflect.TypeOf((*MockStakingKeeper)(nil).IterateValidators), arg0, arg1)
|
||||
}
|
||||
|
||||
// Validator mocks base method.
|
||||
func (m *MockStakingKeeper) Validator(arg0 types.Context, arg1 types.ValAddress) types1.ValidatorI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Validator", arg0, arg1)
|
||||
ret0, _ := ret[0].(types1.ValidatorI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Validator indicates an expected call of Validator.
|
||||
func (mr *MockStakingKeeperMockRecorder) Validator(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validator", reflect.TypeOf((*MockStakingKeeper)(nil).Validator), arg0, arg1)
|
||||
}
|
||||
|
||||
// ValidatorByConsAddr mocks base method.
|
||||
func (m *MockStakingKeeper) ValidatorByConsAddr(arg0 types.Context, arg1 types.ConsAddress) types1.ValidatorI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorByConsAddr", arg0, arg1)
|
||||
ret0, _ := ret[0].(types1.ValidatorI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ValidatorByConsAddr indicates an expected call of ValidatorByConsAddr.
|
||||
func (mr *MockStakingKeeperMockRecorder) ValidatorByConsAddr(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorByConsAddr", reflect.TypeOf((*MockStakingKeeper)(nil).ValidatorByConsAddr), arg0, arg1)
|
||||
}
|
||||
|
||||
// MockStakingHooks is a mock of StakingHooks interface.
|
||||
type MockStakingHooks struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockStakingHooksMockRecorder
|
||||
}
|
||||
|
||||
// MockStakingHooksMockRecorder is the mock recorder for MockStakingHooks.
|
||||
type MockStakingHooksMockRecorder struct {
|
||||
mock *MockStakingHooks
|
||||
}
|
||||
|
||||
// NewMockStakingHooks creates a new mock instance.
|
||||
func NewMockStakingHooks(ctrl *gomock.Controller) *MockStakingHooks {
|
||||
mock := &MockStakingHooks{ctrl: ctrl}
|
||||
mock.recorder = &MockStakingHooksMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockStakingHooks) EXPECT() *MockStakingHooksMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AfterDelegationModified mocks base method.
|
||||
func (m *MockStakingHooks) AfterDelegationModified(ctx types.Context, delAddr types.AccAddress, valAddr types.ValAddress) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "AfterDelegationModified", ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
// AfterDelegationModified indicates an expected call of AfterDelegationModified.
|
||||
func (mr *MockStakingHooksMockRecorder) AfterDelegationModified(ctx, delAddr, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AfterDelegationModified", reflect.TypeOf((*MockStakingHooks)(nil).AfterDelegationModified), ctx, delAddr, valAddr)
|
||||
}
|
||||
|
||||
// AfterValidatorCreated mocks base method.
|
||||
func (m *MockStakingHooks) AfterValidatorCreated(ctx types.Context, valAddr types.ValAddress) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "AfterValidatorCreated", ctx, valAddr)
|
||||
}
|
||||
|
||||
// AfterValidatorCreated indicates an expected call of AfterValidatorCreated.
|
||||
func (mr *MockStakingHooksMockRecorder) AfterValidatorCreated(ctx, valAddr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AfterValidatorCreated", reflect.TypeOf((*MockStakingHooks)(nil).AfterValidatorCreated), ctx, valAddr)
|
||||
}
|
||||
128
x/distribution/testutil/staking_helper.go
Normal file
128
x/distribution/testutil/staking_helper.go
Normal file
@ -0,0 +1,128 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
func CreateValidator(pk cryptotypes.PubKey, stake math.Int) (stakingtypes.Validator, error) {
|
||||
valConsAddr := sdk.GetConsAddress(pk)
|
||||
val, err := stakingtypes.NewValidator(sdk.ValAddress(valConsAddr), pk, stakingtypes.Description{})
|
||||
val.Tokens = stake
|
||||
val.DelegatorShares = math.LegacyNewDecFromInt(val.Tokens)
|
||||
return val, err
|
||||
}
|
||||
|
||||
func CallCreateValidatorHooks(ctx sdk.Context, k keeper.Keeper, addr sdk.AccAddress, valAddr sdk.ValAddress) error {
|
||||
err := k.Hooks().AfterValidatorCreated(ctx, valAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = k.Hooks().BeforeDelegationCreated(ctx, addr, valAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = k.Hooks().AfterDelegationModified(ctx, addr, valAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SlashValidator copies what x/staking Slash does. It should be used for testing only.
|
||||
// And it must be updated whenever the original function is updated.
|
||||
// The passed validator will get its tokens updated.
|
||||
func SlashValidator(
|
||||
ctx sdk.Context,
|
||||
consAddr sdk.ConsAddress,
|
||||
infractionHeight int64,
|
||||
power int64,
|
||||
slashFactor sdk.Dec,
|
||||
validator *stakingtypes.Validator,
|
||||
distrKeeper *keeper.Keeper,
|
||||
) math.Int {
|
||||
if slashFactor.IsNegative() {
|
||||
panic(fmt.Errorf("attempted to slash with a negative slash factor: %v", slashFactor))
|
||||
}
|
||||
|
||||
// call the before-modification hook
|
||||
err := distrKeeper.Hooks().BeforeValidatorModified(ctx, validator.GetOperator())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// we simplify this part, as we won't be able to test redelegations or
|
||||
// unbonding delegations
|
||||
if infractionHeight != ctx.BlockHeight() {
|
||||
// if a new test lands here we might need to update this function to handle redelegations and unbonding
|
||||
// or just make it an integration test.
|
||||
panic("we can't test any other case here")
|
||||
}
|
||||
|
||||
slashAmountDec := sdk.NewDecFromInt(validator.Tokens).Mul(sdk.NewDecWithPrec(5, 1))
|
||||
slashAmount := slashAmountDec.TruncateInt()
|
||||
|
||||
// cannot decrease balance below zero
|
||||
tokensToBurn := sdk.MinInt(slashAmount, validator.Tokens)
|
||||
tokensToBurn = sdk.MaxInt(tokensToBurn, math.ZeroInt()) // defensive.
|
||||
|
||||
// we need to calculate the *effective* slash fraction for distribution
|
||||
if validator.Tokens.IsPositive() {
|
||||
effectiveFraction := sdk.NewDecFromInt(tokensToBurn).QuoRoundUp(sdk.NewDecFromInt(validator.Tokens))
|
||||
// possible if power has changed
|
||||
if effectiveFraction.GT(math.LegacyOneDec()) {
|
||||
effectiveFraction = math.LegacyOneDec()
|
||||
}
|
||||
// call the before-slashed hook
|
||||
distrKeeper.Hooks().BeforeValidatorSlashed(ctx, validator.GetOperator(), effectiveFraction)
|
||||
}
|
||||
// Deduct from validator's bonded tokens and update the validator.
|
||||
// Burn the slashed tokens from the pool account and decrease the total supply.
|
||||
validator.Tokens = validator.Tokens.Sub(tokensToBurn)
|
||||
|
||||
return tokensToBurn
|
||||
}
|
||||
|
||||
// Delegate imitate what x/staking Delegate does. It should be used for testing only.
|
||||
// If a delegation is passed we are simulating an update to a previous delegation,
|
||||
// if it's nil then we simulate a new delegation.
|
||||
func Delegate(
|
||||
ctx sdk.Context,
|
||||
distrKeeper keeper.Keeper,
|
||||
delegator sdk.AccAddress,
|
||||
validator *stakingtypes.Validator,
|
||||
amount math.Int,
|
||||
delegation *stakingtypes.Delegation,
|
||||
) (
|
||||
newShares sdk.Dec,
|
||||
updatedDel stakingtypes.Delegation,
|
||||
err error,
|
||||
) {
|
||||
if delegation != nil {
|
||||
err = distrKeeper.Hooks().BeforeDelegationSharesModified(ctx, delegator, validator.GetOperator())
|
||||
} else {
|
||||
err = distrKeeper.Hooks().BeforeDelegationCreated(ctx, delegator, validator.GetOperator())
|
||||
del := stakingtypes.NewDelegation(delegator, validator.GetOperator(), math.LegacyZeroDec())
|
||||
delegation = &del
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return math.LegacyZeroDec(), stakingtypes.Delegation{}, err
|
||||
}
|
||||
|
||||
// Add tokens from delegation to validator
|
||||
updateVal, newShares := validator.AddTokensFromDel(amount)
|
||||
*validator = updateVal
|
||||
|
||||
delegation.Shares = delegation.Shares.Add(newShares)
|
||||
|
||||
return newShares, *delegation, nil
|
||||
}
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/configurator"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
@ -20,7 +21,6 @@ import (
|
||||
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
@ -103,7 +103,7 @@ func (suite *SimTestSuite) TestSimulateMsgWithdrawDelegatorReward() {
|
||||
validator0 := suite.getTestingValidator0(accounts)
|
||||
|
||||
// setup delegation
|
||||
delTokens := suite.stakingKeeper.TokensFromConsensusPower(suite.ctx, 2)
|
||||
delTokens := sdk.TokensFromConsensusPower(2, sdk.DefaultPowerReduction)
|
||||
validator0, issuedShares := validator0.AddTokensFromDel(delTokens)
|
||||
delegator := accounts[1]
|
||||
delegation := stakingtypes.NewDelegation(delegator.Address, validator0.GetOperator(), issuedShares)
|
||||
@ -235,18 +235,29 @@ type SimTestSuite struct {
|
||||
}
|
||||
|
||||
func (suite *SimTestSuite) SetupTest() {
|
||||
app, err := simtestutil.Setup(testutil.AppConfig,
|
||||
&suite.cdc,
|
||||
&suite.txConfig,
|
||||
&suite.stakingKeeper,
|
||||
&suite.accountKeeper,
|
||||
&suite.bankKeeper,
|
||||
&suite.distrKeeper,
|
||||
var (
|
||||
appBuilder *runtime.AppBuilder
|
||||
err error
|
||||
)
|
||||
suite.app, err = simtestutil.Setup(configurator.NewAppConfig(
|
||||
configurator.AuthModule(),
|
||||
configurator.ParamsModule(),
|
||||
configurator.BankModule(),
|
||||
configurator.StakingModule(),
|
||||
configurator.TxModule(),
|
||||
configurator.DistributionModule(),
|
||||
), &suite.accountKeeper,
|
||||
&suite.bankKeeper,
|
||||
&suite.cdc,
|
||||
&appBuilder,
|
||||
&suite.stakingKeeper,
|
||||
&suite.distrKeeper,
|
||||
&suite.txConfig,
|
||||
)
|
||||
|
||||
suite.NoError(err)
|
||||
|
||||
suite.app = app
|
||||
suite.ctx = app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
suite.ctx = suite.app.BaseApp.NewContext(false, tmproto.Header{})
|
||||
|
||||
genesisVals := suite.stakingKeeper.GetAllValidators(suite.ctx)
|
||||
suite.Require().Len(genesisVals, 1)
|
||||
@ -381,7 +381,7 @@ func setupValidatorRewards(app *simapp.SimApp, ctx sdk.Context, valAddress sdk.V
|
||||
decCoins := sdk.DecCoins{sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, math.LegacyOneDec())}
|
||||
historicalRewards := distrtypes.NewValidatorHistoricalRewards(decCoins, 2)
|
||||
app.DistrKeeper.SetValidatorHistoricalRewards(ctx, valAddress, 2, historicalRewards)
|
||||
// setup current revards
|
||||
// setup current rewards
|
||||
currentRewards := distrtypes.NewValidatorCurrentRewards(decCoins, 3)
|
||||
app.DistrKeeper.SetValidatorCurrentRewards(ctx, valAddress, currentRewards)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user