diff --git a/x/staking/keeper/msg_server.go b/x/staking/keeper/msg_server.go index ee718aaa2a07..0eac2ace6123 100644 --- a/x/staking/keeper/msg_server.go +++ b/x/staking/keeper/msg_server.go @@ -861,6 +861,11 @@ func (k msgServer) RedeemTokensForShares(goCtx context.Context, msg *types.MsgRe } tokens := validator.TokensFromShares(shares).TruncateInt() + // prevent redemption that returns a 0 amount + if tokens.IsZero() { + return nil, types.ErrTinyRedemptionAmount + } + // If this redemption is NOT from a liquid staking provider, decrement the total liquid staked // If the redemption was from a liquid staking provider, the shares are still considered // liquid, even in their non-tokenized form (since they are owned by a liquid staking provider) diff --git a/x/staking/simulation/operations.go b/x/staking/simulation/operations.go index 8d7fcf381797..b3bdb6cf0df0 100644 --- a/x/staking/simulation/operations.go +++ b/x/staking/simulation/operations.go @@ -923,8 +923,10 @@ func SimulateMsgRedeemTokensforShares(ak types.AccountKeeper, bk types.BankKeepe } // prevent redemption that returns a 0 amount - shareDenomSupply := bk.GetSupply(ctx, tokenizeShareRecord.GetShareTokenDenom()) - shares := delegation.Shares.Mul(sdk.NewDecFromInt(redeemCoin.Amount)).QuoInt(shareDenomSupply.Amount) + shares := sdk.NewDecFromInt(redeemCoin.Amount) + if redeemCoin.Amount.Equal(delegation.Shares.TruncateInt()) { + shares = delegation.Shares + } if validator.TokensFromShares(shares).TruncateInt().IsZero() { return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgRedeemTokensForShares, "zero tokens returned"), nil, nil diff --git a/x/staking/types/errors.go b/x/staking/types/errors.go index 32d07d74b972..a684f5898af3 100644 --- a/x/staking/types/errors.go +++ b/x/staking/types/errors.go @@ -70,4 +70,5 @@ var ( ErrTokenizeSharesAlreadyDisabledForAccount = sdkerrors.Register(ModuleName, 116, "tokenize shares is already disabled for this account") ErrValidatorLiquidSharesUnderflow = sdkerrors.Register(ModuleName, 117, "validator liquid shares underflow") ErrTotalLiquidStakedUnderflow = sdkerrors.Register(ModuleName, 118, "total liquid staked underflow") + ErrTinyRedemptionAmount = sdkerrors.Register(ModuleName, 119, "too few tokens to redeem (truncates to zero tokens)") )