diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ff420adbd..b37dca1c9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,19 @@ # Changelog +## 0.29.0 + +BREAKING CHANGES + +* Gaia + * [\#3148](https://github.com/cosmos/cosmos-sdk/issues/3148) Fix `gaiad export` by adding a boolean to `NewGaiaApp` determining whether or not to load the latest version + +* SDK + * [\#3163](https://github.com/cosmos/cosmos-sdk/issues/3163) Withdraw commission on self bond removal + + ## 0.28.1 -BREAKNG CHANGES +BREAKING CHANGES * Gaia REST API (`gaiacli advanced rest-server`) * [lcd] [\#3045](https://github.com/cosmos/cosmos-sdk/pull/3045) Fix quoted json return on GET /keys (keys list) @@ -25,11 +36,11 @@ FEATURES IMPROVEMENTS * Gaia REST API (`gaiacli advanced rest-server`) - * \#2879, \#2880 Update deposit and vote endpoints to perform a direct txs query + * [\#2879](https://github.com/cosmos/cosmos-sdk/issues/2879), [\#2880](https://github.com/cosmos/cosmos-sdk/issues/2880) Update deposit and vote endpoints to perform a direct txs query when a given proposal is inactive and thus having votes and deposits removed from state. * Gaia CLI (`gaiacli`) - * \#2879, \#2880 Update deposit and vote CLI commands to perform a direct txs query + * [\#2879](https://github.com/cosmos/cosmos-sdk/issues/2879), [\#2880](https://github.com/cosmos/cosmos-sdk/issues/2880) Update deposit and vote CLI commands to perform a direct txs query when a given proposal is inactive and thus having votes and deposits removed from state. * Gaia diff --git a/x/distribution/keeper/hooks.go b/x/distribution/keeper/hooks.go index e9d31b8a23..910f6eafa2 100644 --- a/x/distribution/keeper/hooks.go +++ b/x/distribution/keeper/hooks.go @@ -87,6 +87,17 @@ func (k Keeper) onDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddre // Withdrawal all validator distribution rewards and cleanup the distribution record func (k Keeper) onDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + // Withdraw validator commission when validator self-bond is removed. + // Because we maintain the invariant that all delegations must be removed + // before a validator is deleted, this ensures that commission will be withdrawn + // before the validator is deleted (and the corresponding ValidatorDistInfo removed). + // If we change other parts of the code such that a self-delegation might remain after + // a validator is deleted, this logic will no longer be safe. + // TODO: Consider instead implementing this in a "BeforeValidatorRemoved" hook. + if valAddr.Equals(sdk.ValAddress(delAddr)) { + feePool, commission := k.withdrawValidatorCommission(ctx, valAddr) + k.WithdrawToDelegator(ctx, feePool, delAddr, commission) + } k.RemoveDelegationDistInfo(ctx, delAddr, valAddr) } diff --git a/x/distribution/keeper/validator.go b/x/distribution/keeper/validator.go index 4ce0834a71..8d861fef80 100644 --- a/x/distribution/keeper/validator.go +++ b/x/distribution/keeper/validator.go @@ -42,6 +42,9 @@ func (k Keeper) RemoveValidatorDistInfo(ctx sdk.Context, valAddr sdk.ValAddress) if vdi.DelAccum.Accum.IsPositive() { panic("Should not delete validator with unwithdrawn delegator accum") } + if !vdi.ValCommission.IsZero() { + panic("Should not delete validator with unwithdrawn validator commission") + } store := ctx.KVStore(k.storeKey) store.Delete(GetValidatorDistInfoKey(valAddr)) @@ -119,6 +122,15 @@ func (k Keeper) takeValidatorFeePoolRewards(ctx sdk.Context, operatorAddr sdk.Va return nil } +func (k Keeper) withdrawValidatorCommission(ctx sdk.Context, operatorAddr sdk.ValAddress) (types.FeePool, types.DecCoins) { + valInfo := k.GetValidatorDistInfo(ctx, operatorAddr) + wc := k.GetWithdrawContext(ctx, operatorAddr) + valInfo, feePool, commission := valInfo.WithdrawCommission(wc) + k.SetValidatorDistInfo(ctx, valInfo) + + return feePool, commission +} + // withdrawal all the validator rewards including the commission func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.ValAddress) sdk.Error { if !k.HasValidatorDistInfo(ctx, operatorAddr) { @@ -130,11 +142,8 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.Va withdraw := k.withdrawDelegationRewardsAll(ctx, accAddr) // withdrawal validator commission rewards - valInfo := k.GetValidatorDistInfo(ctx, operatorAddr) - wc := k.GetWithdrawContext(ctx, operatorAddr) - valInfo, feePool, commission := valInfo.WithdrawCommission(wc) + feePool, commission := k.withdrawValidatorCommission(ctx, operatorAddr) withdraw = withdraw.Plus(commission) - k.SetValidatorDistInfo(ctx, valInfo) k.WithdrawToDelegator(ctx, feePool, accAddr, withdraw) return nil