diff --git a/x/staking/keeper/msg_server_test.go b/x/staking/keeper/msg_server_test.go index 545365ee5cff..501ecfb8264f 100644 --- a/x/staking/keeper/msg_server_test.go +++ b/x/staking/keeper/msg_server_test.go @@ -1221,3 +1221,131 @@ func TestICADelegateUndelegate(t *testing.T) { require.True(t, found, "validator should have been found") require.Equal(t, sdk.ZeroDec(), validator.LiquidShares, "validator liquid shares after undelegation") } + +func TestCancelUnbondingDelegation(t *testing.T) { + // setup the app + _, app, ctx := createTestInput() + msgServer := keeper.NewMsgServerImpl(app.StakingKeeper) + bondDenom := app.StakingKeeper.BondDenom(ctx) + + // set the not bonded pool module account + notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) + startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 5) + startCoin := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens)) + + require.NoError(t, simapp.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), startCoin)) + app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) + + moduleBalance := app.BankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), app.StakingKeeper.BondDenom(ctx)) + require.Equal(t, sdk.NewInt64Coin(bondDenom, startTokens.Int64()), moduleBalance) + + // create a validator + validatorPubKey := simapp.CreateTestPubKeys(1)[0] + validatorAddr := sdk.ValAddress(validatorPubKey.Address()) + + validator := teststaking.NewValidator(t, validatorAddr, validatorPubKey) + validator.Tokens = startTokens + validator.DelegatorShares = sdk.NewDecFromInt(startTokens) + validator.Status = types.Bonded + app.StakingKeeper.SetValidator(ctx, validator) + + // create a delegator + delAddrs := simapp.AddTestAddrsIncremental(app, ctx, 2, sdk.NewInt(10000)) + delegatorAddr := delAddrs[0] + + // setting the ubd entry + unbondingAmount := sdk.NewInt64Coin(app.StakingKeeper.BondDenom(ctx), 5) + ubd := types.NewUnbondingDelegation( + delegatorAddr, validatorAddr, 10, + ctx.BlockTime().Add(time.Minute*10), + unbondingAmount.Amount, + 1, + ) + + // set and retrieve a record + app.StakingKeeper.SetUnbondingDelegation(ctx, ubd) + resUnbond, found := app.StakingKeeper.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) + require.True(t, found) + require.Equal(t, ubd, resUnbond) + + testCases := []struct { + Name string + ExceptErr bool + req types.MsgCancelUnbondingDelegation + }{ + { + Name: "invalid height", + ExceptErr: true, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), sdk.NewInt(4)), + CreationHeight: 0, + }, + }, + { + Name: "validator not exists", + ExceptErr: true, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: sdk.ValAddress(sdk.AccAddress("asdsad")).String(), + Amount: unbondingAmount, + CreationHeight: 0, + }, + }, + { + Name: "invalid delegator address", + ExceptErr: true, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: "invalid_delegator_addrtess", + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: unbondingAmount, + CreationHeight: 0, + }, + }, + { + Name: "invalid amount", + ExceptErr: true, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: unbondingAmount.Add(sdk.NewInt64Coin(bondDenom, 10)), + CreationHeight: 10, + }, + }, + { + Name: "success", + ExceptErr: false, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: unbondingAmount.Sub(sdk.NewInt64Coin(bondDenom, 1)), + CreationHeight: 10, + }, + }, + { + Name: "success", + ExceptErr: false, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: unbondingAmount.Sub(unbondingAmount.Sub(sdk.NewInt64Coin(bondDenom, 1))), + CreationHeight: 10, + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + _, err := msgServer.CancelUnbondingDelegation(sdk.WrapSDKContext(ctx), &testCase.req) + if testCase.ExceptErr { + require.Error(t, err) + } else { + require.NoError(t, err) + balanceForNotBondedPool := app.BankKeeper.GetBalance(ctx, sdk.AccAddress(notBondedPool.GetAddress()), bondDenom) + require.Equal(t, balanceForNotBondedPool, moduleBalance.Sub(testCase.req.Amount)) + moduleBalance = moduleBalance.Sub(testCase.req.Amount) + } + }) + } +}