Skip to content

Commit

Permalink
Merge pull request #822 from persistenceOne/puneet/redelegateMsg
Browse files Browse the repository at this point in the history
fix: add msgBeginRedelegate
  • Loading branch information
puneet2019 authored May 1, 2024
2 parents 3ea5e81 + ad1793f commit 31b3e08
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 23 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Bug Fixes

- [815](https://github.com/persistenceOne/pstake-native/pull/815) Not escape merkle paths for proof verification.
- [822](https://github.com/persistenceOne/pstake-native/pull/822) liquidstake: redelegation to follow msg router instead
of keeper.

## [v2.12.0] - 2024-04-05

Expand Down
55 changes: 55 additions & 0 deletions x/liquidstake/keeper/liquidstake.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,61 @@ func (k Keeper) UnbondWithCap(
return lsmRedeemResp.Amount.Amount, nil
}

// RedelegateWithCap is a wrapper to invoke stakingKeeper.Redelegate but account for
// the amount of liquid staked shares and check against liquid staking cap.
func (k Keeper) RedelegateWithCap(
ctx sdk.Context,
delegatorAddress sdk.AccAddress,
validatorSrc sdk.ValAddress,
validatorDst sdk.ValAddress,
bondAmt math.Int,
) (time.Time, error) {
msgRedelegate := &stakingtypes.MsgBeginRedelegate{
DelegatorAddress: delegatorAddress.String(),
ValidatorSrcAddress: validatorSrc.String(),
ValidatorDstAddress: validatorDst.String(),
Amount: sdk.NewCoin(k.stakingKeeper.BondDenom(ctx), bondAmt),
}
handler := k.router.Handler(msgRedelegate)
if handler == nil {
k.Logger(ctx).Error("failed to find redelegate handler")

return time.Time{}, errorsmod.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s", sdk.MsgTypeURL(msgRedelegate))
}
res, err := handler(ctx, msgRedelegate)
if err != nil {
k.Logger(ctx).Error(
"failed to execute redelegate msg",
types.ErrorKeyVal,
err,
types.MsgKeyVal,
msgRedelegate.String(),
)

return time.Time{}, errorsmod.Wrapf(types.ErrRedelegateFailed, "failed to send redelegate msg with err: %v", err)
}
ctx.EventManager().EmitEvents(res.GetEvents())

if len(res.MsgResponses) != 1 {
return time.Time{}, errorsmod.Wrapf(
types.ErrInvalidResponse,
"expected msg response should be exactly 1, got: %v, responses: %v",
len(res.MsgResponses), res.MsgResponses,
)
}

var msgRedelegateResponse stakingtypes.MsgBeginRedelegateResponse
if err = k.cdc.Unmarshal(res.MsgResponses[0].Value, &msgRedelegateResponse); err != nil {
return time.Time{}, errorsmod.Wrapf(
sdkerrors.ErrJSONUnmarshal,
"cannot unmarshal redelegate tx response message: %v",
err,
)
}

return msgRedelegateResponse.CompletionTime, nil
}

// LSMDelegate captures a staked amount from existing delegation using LSM, re-stakes from proxyAcc and
// mints stkXPRT worth of stk coin value according to NetAmount and performs LiquidDelegate.
func (k Keeper) LSMDelegate(
Expand Down
7 changes: 4 additions & 3 deletions x/liquidstake/keeper/rebalancing.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,20 @@ func (k Keeper) TryRedelegation(ctx sdk.Context, re types.Redelegation) (complet
}

// calculate delShares from tokens with validation
shares, err := k.stakingKeeper.ValidateUnbondAmount(
_, err = k.stakingKeeper.ValidateUnbondAmount(
ctx, re.Delegator, srcVal, re.Amount,
)
if err != nil {
return time.Time{}, fmt.Errorf("failed to validate unbond amount: %w", err)
}

// when last, full redelegation of shares from delegation
amt := re.Amount
if re.Last {
shares = re.SrcValidator.GetDelShares(ctx, k.stakingKeeper)
amt = re.SrcValidator.GetLiquidTokens(ctx, k.stakingKeeper, false)
}
cachedCtx, writeCache := ctx.CacheContext()
completionTime, err = k.stakingKeeper.BeginRedelegation(cachedCtx, re.Delegator, srcVal, dstVal, shares)
completionTime, err = k.RedelegateWithCap(cachedCtx, re.Delegator, srcVal, dstVal, amt)
if err != nil {
return time.Time{}, fmt.Errorf("failed to begin redelegation: %w", err)
}
Expand Down
8 changes: 4 additions & 4 deletions x/liquidstake/keeper/rebalancing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,17 +211,17 @@ func (s *KeeperTestSuite) TestRebalancingCase1() {
reds = s.keeper.UpdateLiquidValidatorSet(s.ctx)
s.Require().Len(reds, 1)

// all redelegated, no delShares
// all redelegated, no delShares ( exception, dust )
proxyAccDel2, found = s.app.StakingKeeper.GetDelegation(s.ctx, types.LiquidStakeProxyAcc, valOpers[1])
s.Require().False(found)
s.Require().True(proxyAccDel2.Shares.LT(sdk.OneDec()))

// liquid validator removed, invalid after tombstoned
lvState, found = s.keeper.GetLiquidValidatorState(s.ctx, valOpers[1])
s.Require().True(found)
s.Require().Equal(lvState.OperatorAddress, valOpers[1].String())
s.Require().Equal(lvState.Status, types.ValidatorStatusInactive)
s.Require().EqualValues(lvState.DelShares, sdk.ZeroDec())
s.Require().EqualValues(lvState.LiquidTokens, sdk.ZeroInt())
s.Require().True(proxyAccDel2.Shares.LT(sdk.OneDec()))
s.Require().True(lvState.LiquidTokens.Equal(sdk.ZeroInt()))

// jail last liquid validator, undelegate all liquid tokens to proxy acc
nasBefore := s.keeper.GetNetAmountState(s.ctx)
Expand Down
1 change: 1 addition & 0 deletions x/liquidstake/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ var (
ErrUnbondFailed = errors.Register(ModuleName, 23, "unbond failed")
ErrInvalidResponse = errors.Register(ModuleName, 24, "invalid response")
ErrUnstakeFailed = errors.Register(ModuleName, 25, "Unstaking failed")
ErrRedelegateFailed = errors.Register(ModuleName, 26, "Redelegate failed")
)
16 changes: 0 additions & 16 deletions x/liquidstake/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,37 +49,21 @@ type StakingKeeper interface {
delAddr sdk.AccAddress, valAddr sdk.ValAddress) (delegation stakingtypes.Delegation, found bool)
IterateDelegations(ctx sdk.Context, delegator sdk.AccAddress,
fn func(index int64, delegation stakingtypes.DelegationI) (stop bool))
Delegate(
ctx sdk.Context, delAddr sdk.AccAddress, bondAmt math.Int, tokenSrc stakingtypes.BondStatus,
validator stakingtypes.Validator, subtractAccount bool,
) (newShares math.LegacyDec, err error)

BondDenom(ctx sdk.Context) (res string)
Unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, shares math.LegacyDec) (amount math.Int, err error)
UnbondingTime(ctx sdk.Context) (res time.Duration)
SetUnbondingDelegationEntry(
ctx sdk.Context, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress,
creationHeight int64, minTime time.Time, balance math.Int,
) stakingtypes.UnbondingDelegation
InsertUBDQueue(ctx sdk.Context, ubd stakingtypes.UnbondingDelegation,
completionTime time.Time)
ValidateUnbondAmount(
ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt math.Int,
) (shares math.LegacyDec, err error)
GetUnbondingDelegation(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (stakingtypes.UnbondingDelegation, bool)
GetAllUnbondingDelegations(ctx sdk.Context, delegator sdk.AccAddress) []stakingtypes.UnbondingDelegation
BeginRedelegation(
ctx sdk.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, sharesAmount math.LegacyDec,
) (completionTime time.Time, err error)
GetAllRedelegations(
ctx sdk.Context, delegator sdk.AccAddress, srcValAddress, dstValAddress sdk.ValAddress,
) []stakingtypes.Redelegation
HasReceivingRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) bool
BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate
HasMaxUnbondingDelegationEntries(ctx sdk.Context,
delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) bool
SafelyIncreaseTotalLiquidStakedTokens(ctx sdk.Context, amount math.Int, sharesAlreadyBonded bool) error
DecreaseTotalLiquidStakedTokens(ctx sdk.Context, amount math.Int) error
GetBondedPool(ctx sdk.Context) (bondedPool authtypes.ModuleAccountI)
}

Expand Down

0 comments on commit 31b3e08

Please sign in to comment.