From 941effc14d018b8f595be455d75d97b15ad6bc67 Mon Sep 17 00:00:00 2001 From: helldealer Date: Sat, 15 Jun 2019 16:26:17 +0800 Subject: [PATCH] Merge PR #4553: Fix undelegate losing tokens issue --- .../4553-undelegate-max-entries-check-first | 1 + x/staking/keeper/delegation.go | 8 ++--- x/staking/keeper/delegation_test.go | 33 ++++++++++++++++++- 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 .pending/improvements/sdk/4553-undelegate-max-entries-check-first diff --git a/.pending/improvements/sdk/4553-undelegate-max-entries-check-first b/.pending/improvements/sdk/4553-undelegate-max-entries-check-first new file mode 100644 index 0000000000..0b4a8488e1 --- /dev/null +++ b/.pending/improvements/sdk/4553-undelegate-max-entries-check-first @@ -0,0 +1 @@ +#4553 undelegate max entries check first diff --git a/x/staking/keeper/delegation.go b/x/staking/keeper/delegation.go index f89e931ce0..6005be3744 100644 --- a/x/staking/keeper/delegation.go +++ b/x/staking/keeper/delegation.go @@ -583,15 +583,15 @@ func (k Keeper) Undelegate( ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec, ) (time.Time, sdk.Error) { + if k.HasMaxUnbondingDelegationEntries(ctx, delAddr, valAddr) { + return time.Time{}, types.ErrMaxUnbondingDelegationEntries(k.Codespace()) + } + returnAmount, err := k.unbond(ctx, delAddr, valAddr, sharesAmount) if err != nil { return time.Time{}, err } - if k.HasMaxUnbondingDelegationEntries(ctx, delAddr, valAddr) { - return time.Time{}, types.ErrMaxUnbondingDelegationEntries(k.Codespace()) - } - completionTime := ctx.BlockHeader().Time.Add(k.UnbondingTime(ctx)) ubd := k.SetUnbondingDelegationEntry(ctx, delAddr, valAddr, ctx.BlockHeight(), completionTime, returnAmount) k.InsertUBDQueue(ctx, ubd, completionTime) diff --git a/x/staking/keeper/delegation_test.go b/x/staking/keeper/delegation_test.go index 9397aa41cc..1a3278bdb7 100644 --- a/x/staking/keeper/delegation_test.go +++ b/x/staking/keeper/delegation_test.go @@ -207,7 +207,7 @@ func TestUnbondDelegation(t *testing.T) { } func TestUnbondingDelegationsMaxEntries(t *testing.T) { - ctx, _, keeper := CreateTestInput(t, false, 1) + ctx, ak, keeper := CreateTestInput(t, false, 1) pool := keeper.GetPool(ctx) startTokens := sdk.TokensFromConsensusPower(10) pool.NotBondedTokens = startTokens @@ -236,15 +236,46 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) { require.NoError(t, err) } + // delegator shares should be reduced by 7 + delegator, _ := keeper.GetDelegation(ctx, addrDels[0], addrVals[0]) + require.Equal(t, sdk.NewDec(9999993), delegator.GetShares()) + + acc := ak.GetAccount(ctx, addrDels[0]) + require.Equal(t, int64(1000000), acc.GetCoins().AmountOf("stake").Int64()) + // an additional unbond should fail due to max entries _, err := keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) require.Error(t, err) + // delegator shares should not reduced + delegator, _ = keeper.GetDelegation(ctx, addrDels[0], addrVals[0]) + require.Equal(t, sdk.NewDec(9999993), delegator.GetShares()) + // mature unbonding delegations ctx = ctx.WithBlockTime(completionTime) err = keeper.CompleteUnbonding(ctx, addrDels[0], addrVals[0]) require.NoError(t, err) + // delegator account balance should be increased by 7 + acc = ak.GetAccount(ctx, addrDels[0]) + require.Equal(t, int64(1000007), acc.GetCoins().AmountOf("stake").Int64()) + + completionTime, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(3)) + require.NoError(t, err) + + // delegator shares should be reduced by 3 + dele2, _ := keeper.GetDelegation(ctx, addrDels[0], addrVals[0]) + require.Equal(t, sdk.NewDec(9999990), dele2.GetShares()) + + // mature unbonding delegations + ctx = ctx.WithBlockTime(completionTime) + err = keeper.CompleteUnbonding(ctx, addrDels[0], addrVals[0]) + require.NoError(t, err) + + // delegator account balance should be increased by 3 + acc = ak.GetAccount(ctx, addrDels[0]) + require.Equal(t, int64(1000010), acc.GetCoins().AmountOf("stake").Int64()) + // unbonding should work again _, err = keeper.Undelegate(ctx, addrDels[0], addrVals[0], sdk.NewDec(1)) require.NoError(t, err)