package keeper_test import ( "testing" "cosmossdk.io/math" "gotest.tools/v3/assert" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/testutil" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) func TestMsgUpdateParams(t *testing.T) { t.Parallel() f := initFixture(t) // default params communityTax := sdk.NewDecWithPrec(2, 2) // 2% withdrawAddrEnabled := true testCases := []struct { name string input *types.MsgUpdateParams expErr bool expErrMsg string }{ { name: "invalid authority", input: &types.MsgUpdateParams{ Authority: "invalid", Params: types.Params{ CommunityTax: sdk.NewDecWithPrec(2, 0), WithdrawAddrEnabled: withdrawAddrEnabled, BaseProposerReward: sdk.ZeroDec(), BonusProposerReward: sdk.ZeroDec(), }, }, expErr: true, expErrMsg: "invalid authority", }, { name: "community tax > 1", input: &types.MsgUpdateParams{ Authority: f.distrKeeper.GetAuthority(), Params: types.Params{ CommunityTax: sdk.NewDecWithPrec(2, 0), WithdrawAddrEnabled: withdrawAddrEnabled, BaseProposerReward: sdk.ZeroDec(), BonusProposerReward: sdk.ZeroDec(), }, }, expErr: true, expErrMsg: "community tax should be non-negative and less than one", }, { name: "negative community tax", input: &types.MsgUpdateParams{ Authority: f.distrKeeper.GetAuthority(), Params: types.Params{ CommunityTax: sdk.NewDecWithPrec(-2, 1), WithdrawAddrEnabled: withdrawAddrEnabled, BaseProposerReward: sdk.ZeroDec(), BonusProposerReward: sdk.ZeroDec(), }, }, expErr: true, expErrMsg: "community tax should be non-negative and less than one", }, { name: "base proposer reward set", input: &types.MsgUpdateParams{ Authority: f.distrKeeper.GetAuthority(), Params: types.Params{ CommunityTax: communityTax, BaseProposerReward: sdk.NewDecWithPrec(1, 2), BonusProposerReward: sdk.ZeroDec(), WithdrawAddrEnabled: withdrawAddrEnabled, }, }, expErr: true, expErrMsg: "cannot update base or bonus proposer reward because these are deprecated fields: invalid request", }, { name: "bonus proposer reward set", input: &types.MsgUpdateParams{ Authority: f.distrKeeper.GetAuthority(), Params: types.Params{ CommunityTax: communityTax, BaseProposerReward: sdk.ZeroDec(), BonusProposerReward: sdk.NewDecWithPrec(1, 2), WithdrawAddrEnabled: withdrawAddrEnabled, }, }, expErr: true, expErrMsg: "cannot update base or bonus proposer reward because these are deprecated fields: invalid request", }, { name: "all good", input: &types.MsgUpdateParams{ Authority: f.distrKeeper.GetAuthority(), Params: types.Params{ CommunityTax: communityTax, BaseProposerReward: sdk.ZeroDec(), BonusProposerReward: sdk.ZeroDec(), WithdrawAddrEnabled: withdrawAddrEnabled, }, }, expErr: false, }, } for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { _, err := f.msgServer.UpdateParams(f.ctx, tc.input) if tc.expErr { assert.ErrorContains(t, err, tc.expErrMsg) } else { assert.NilError(t, err) } }) } } func TestCommunityPoolSpend(t *testing.T) { t.Parallel() f := initFixture(t) recipient := sdk.AccAddress([]byte("addr1_______________")) testCases := []struct { name string input *types.MsgCommunityPoolSpend expErr bool expErrMsg string }{ { name: "invalid authority", input: &types.MsgCommunityPoolSpend{ Authority: "invalid", Recipient: recipient.String(), Amount: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(100))), }, expErr: true, expErrMsg: "invalid authority", }, { name: "invalid recipient", input: &types.MsgCommunityPoolSpend{ Authority: f.distrKeeper.GetAuthority(), Recipient: "invalid", Amount: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(100))), }, expErr: true, expErrMsg: "decoding bech32 failed", }, { name: "valid message", input: &types.MsgCommunityPoolSpend{ Authority: f.distrKeeper.GetAuthority(), Recipient: recipient.String(), Amount: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(100))), }, expErr: false, }, } for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { _, err := f.msgServer.CommunityPoolSpend(f.ctx, tc.input) if tc.expErr { assert.ErrorContains(t, err, tc.expErrMsg) } else { assert.NilError(t, err) r, err := sdk.AccAddressFromBech32(tc.input.Recipient) assert.NilError(t, err) b := f.bankKeeper.GetAllBalances(f.ctx, r) assert.Assert(t, b.IsZero() == false) } }) } } func TestMsgDepositValidatorRewardsPool(t *testing.T) { t.Parallel() f := initFixture(t) tstaking := stakingtestutil.NewHelper(t, f.ctx, f.stakingKeeper) tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), math.LegacyNewDec(0)) tstaking.CreateValidator(f.valAddrs[1], valConsPk0, sdk.NewInt(100), true) // mint a non-staking token and send to an account amt := sdk.NewCoins(sdk.NewInt64Coin("foo", 500)) f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, amt) f.bankKeeper.SendCoinsFromModuleToAccount(f.ctx, minttypes.ModuleName, f.addrs[0], amt) testCases := []struct { name string input *types.MsgDepositValidatorRewardsPool expErr bool expErrMsg string }{ { name: "happy path (staking token)", input: &types.MsgDepositValidatorRewardsPool{ Authority: f.addrs[0].String(), ValidatorAddress: f.valAddrs[1].String(), Amount: sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.ctx), sdk.NewInt(100))), }, }, { name: "happy path (non-staking token)", input: &types.MsgDepositValidatorRewardsPool{ Authority: f.addrs[0].String(), ValidatorAddress: f.valAddrs[1].String(), Amount: amt, }, }, { name: "invalid validator", input: &types.MsgDepositValidatorRewardsPool{ Authority: f.addrs[0].String(), ValidatorAddress: sdk.ValAddress([]byte("addr1_______________")).String(), Amount: sdk.NewCoins(sdk.NewCoin(f.stakingKeeper.BondDenom(f.ctx), sdk.NewInt(100))), }, expErr: true, expErrMsg: "validator does not exist", }, } for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { _, err := f.msgServer.DepositValidatorRewardsPool(f.ctx, tc.input) if tc.expErr { assert.ErrorContains(t, err, tc.expErrMsg) } else { assert.NilError(t, err) valAddr, err := sdk.ValAddressFromBech32(tc.input.ValidatorAddress) assert.NilError(t, err) // check validator outstanding rewards outstandingRewards := f.distrKeeper.GetValidatorOutstandingRewards(f.ctx, valAddr) for _, c := range tc.input.Amount { x := outstandingRewards.Rewards.AmountOf(c.Denom) assert.DeepEqual(t, x, sdk.NewDecFromInt(c.Amount)) } } }) } }