diff --git a/CHANGELOG.md b/CHANGELOG.md index f163ea25ecf8..f0bd8958e37e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* [#13323](https://github.com/cosmos/cosmos-sdk/pull/13323) Ensure `withdraw_rewards` rewards are emitted from all actions that result in rewards being withdrawn. * [#13233](https://github.com/cosmos/cosmos-sdk/pull/13233) Add `--append` to `add-genesis-account` sub-command to append new tokens after an account is already created. * (x/group) [#13214](https://github.com/cosmos/cosmos-sdk/pull/13214) Add `withdraw-proposal` command to group module's CLI transaction commands. * (x/auth) [#13048](https://github.com/cosmos/cosmos-sdk/pull/13048) Add handling of AccountNumberStoreKeyPrefix to the simulation decoder. diff --git a/x/distribution/keeper/delegation.go b/x/distribution/keeper/delegation.go index 3b158c15585e..c70062c11d3f 100644 --- a/x/distribution/keeper/delegation.go +++ b/x/distribution/keeper/delegation.go @@ -4,7 +4,6 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -162,13 +161,13 @@ func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val stakingtypes.Vali ) } - // truncate coins, return remainder to community pool - coins, remainder := rewards.TruncateDecimal() + // truncate reward dec coins, return remainder to community pool + finalRewards, remainder := rewards.TruncateDecimal() // add coins to user account - if !coins.IsZero() { + if !finalRewards.IsZero() { withdrawAddr := k.GetDelegatorWithdrawAddr(ctx, del.GetDelegatorAddr()) - err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, withdrawAddr, coins) + err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, withdrawAddr, finalRewards) if err != nil { return nil, err } @@ -189,5 +188,24 @@ func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val stakingtypes.Vali // remove delegator starting info k.DeleteDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) - return coins, nil + if finalRewards.IsZero() { + baseDenom, _ := sdk.GetBaseDenom() + if baseDenom == "" { + baseDenom = sdk.DefaultBondDenom + } + + // Note, we do not call the NewCoins constructor as we do not want the zero + // coin removed. + finalRewards = sdk.Coins{sdk.NewCoin(baseDenom, sdk.ZeroInt())} + } + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeWithdrawRewards, + sdk.NewAttribute(sdk.AttributeKeyAmount, finalRewards.String()), + sdk.NewAttribute(types.AttributeKeyValidator, val.GetOperator().String()), + ), + ) + + return finalRewards, nil } diff --git a/x/distribution/keeper/delegation_test.go b/x/distribution/keeper/delegation_test.go index 7b18c0241f3b..54d8be101ee0 100644 --- a/x/distribution/keeper/delegation_test.go +++ b/x/distribution/keeper/delegation_test.go @@ -684,19 +684,15 @@ func Test100PercentCommissionReward(t *testing.T) { rewards, err := app.DistrKeeper.WithdrawDelegationRewards(ctx, sdk.AccAddress(valAddrs[0]), valAddrs[0]) require.NoError(t, err) - denom, _ := sdk.GetBaseDenom() - zeroRewards := sdk.Coins{ - sdk.Coin{ - Denom: denom, - Amount: sdk.ZeroInt(), - }, - } + zeroRewards := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.ZeroInt())} require.True(t, rewards.IsEqual(zeroRewards)) + events := ctx.EventManager().Events() lastEvent := events[len(events)-1] - hasValue := false + + var hasValue bool for _, attr := range lastEvent.Attributes { - if string(attr.Key) == "amount" && string(attr.Value) == "0" { + if string(attr.Key) == "amount" && string(attr.Value) == "0stake" { hasValue = true } } diff --git a/x/distribution/keeper/keeper.go b/x/distribution/keeper/keeper.go index 6af1ede7e5cd..a18484fdec0c 100644 --- a/x/distribution/keeper/keeper.go +++ b/x/distribution/keeper/keeper.go @@ -96,22 +96,6 @@ func (k Keeper) WithdrawDelegationRewards(ctx sdk.Context, delAddr sdk.AccAddres return nil, err } - if rewards.IsZero() { - baseDenom, _ := sdk.GetBaseDenom() - rewards = sdk.Coins{sdk.Coin{ - Denom: baseDenom, - Amount: sdk.ZeroInt(), - }} - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeWithdrawRewards, - sdk.NewAttribute(sdk.AttributeKeyAmount, rewards.String()), - sdk.NewAttribute(types.AttributeKeyValidator, valAddr.String()), - ), - ) - // reinitialize the delegation k.initializeDelegation(ctx, valAddr, delAddr) return rewards, nil