Skip to content

Commit

Permalink
InstantUndelegate + basic test
Browse files Browse the repository at this point in the history
  • Loading branch information
czarcas7ic committed May 8, 2024
1 parent bd886bb commit 5046a6d
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
38 changes: 38 additions & 0 deletions tests/integration/staking/keeper/delegation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,41 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) {
assert.Assert(math.IntEq(t, newBonded, oldBonded.SubRaw(1)))
assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded.AddRaw(1)))
}

func TestInstantUndelegate(t *testing.T) {
_, app, ctx := createTestInput(t)

delAddrs := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.NewInt(10000))
valAddrs := simtestutil.ConvertAddrsToValAddrs(delAddrs)

startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)

require.NoError(t, banktestutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens))))
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)

// create a validator and a delegator to that validator
// note this validator starts not-bonded
validator := testutil.NewValidator(t, valAddrs[0], PKs[0])

validator, issuedShares := validator.AddTokensFromDel(startTokens)
require.Equal(t, startTokens, issuedShares.RoundInt())

validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)

delegation := types.NewDelegation(delAddrs[0], valAddrs[0], issuedShares)
app.StakingKeeper.SetDelegation(ctx, delegation)

bondTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 6)

oldBal := app.BankKeeper.GetBalance(ctx, delAddrs[0], app.StakingKeeper.BondDenom(ctx))

res, err := app.StakingKeeper.InstantUndelegate(ctx, delAddrs[0], valAddrs[0], sdk.NewDecFromInt(bondTokens))
require.NoError(t, err)

require.Equal(t, res, sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), bondTokens)))

newBal := app.BankKeeper.GetBalance(ctx, delAddrs[0], app.StakingKeeper.BondDenom(ctx))

require.Equal(t, oldBal.Add(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), bondTokens)), newBal)
}
34 changes: 34 additions & 0 deletions x/staking/keeper/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,40 @@ func (k Keeper) Undelegate(
return completionTime, returnAmount, nil
}

// InstantUndelegate allows another module account to undelegate while bypassing unbonding time.
// This function is a combination of Undelegate and CompleteUnbonding,
// but skips the creation and deletion of UnbondingDelegationEntry
func (k Keeper) InstantUndelegate(
ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec,
) (sdk.Coins, error) {

validator, found := k.GetValidator(ctx, valAddr)
if !found {
return nil, types.ErrNoDelegatorForAddress
}

returnAmount, err := k.Unbond(ctx, delAddr, valAddr, sharesAmount)
if err != nil {
return nil, err
}

bondDenom := k.GetParams(ctx).BondDenom

amt := sdk.NewCoin(bondDenom, returnAmount)
res := sdk.NewCoins(amt)

moduleName := types.NotBondedPoolName
if validator.IsBonded() {
moduleName = types.BondedPoolName
}
err = k.bankKeeper.UndelegateCoinsFromModuleToAccount(ctx, moduleName, delAddr, res)
if err != nil {
return nil, err
}
return res, nil

}

// CompleteUnbonding completes the unbonding of all mature entries in the
// retrieved unbonding delegation object and returns the total unbonding balance
// or an error upon failure.
Expand Down

0 comments on commit 5046a6d

Please sign in to comment.