Skip to content

Commit

Permalink
refactor events emition, and msgresponse usage (#791)
Browse files Browse the repository at this point in the history
  • Loading branch information
puneet2019 authored Mar 20, 2024
1 parent 1db67d7 commit 547b8dc
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 43 deletions.
13 changes: 11 additions & 2 deletions x/liquidstake/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ func (s *KeeperTestSuite) TearDownTest() {
func (s *KeeperTestSuite) CreateValidators(powers []int64) ([]sdk.AccAddress, []sdk.ValAddress, []cryptotypes.PubKey) {
s.app.BeginBlocker(s.ctx, abci.RequestBeginBlock{})
num := len(powers)
addrs := testhelpers.AddTestAddrsIncremental(s.app, s.ctx, num, math.NewInt(1000000000))
addrs := testhelpers.AddTestAddrsIncremental(s.app, s.ctx, num, math.NewInt(10000000000000))
valAddrs := testhelpers.ConvertAddrsToValAddrs(addrs)
pks := testhelpers.CreateTestPubKeys(num)

skParams := s.app.StakingKeeper.GetParams(s.ctx)
skParams.ValidatorLiquidStakingCap = sdk.OneDec()
s.app.StakingKeeper.SetParams(s.ctx, skParams)
for i, power := range powers {
val, err := stakingtypes.NewValidator(valAddrs[i], pks[i], stakingtypes.Description{})
s.Require().NoError(err)
Expand All @@ -93,6 +95,13 @@ func (s *KeeperTestSuite) CreateValidators(powers []int64) ([]sdk.AccAddress, []
newShares, err := s.app.StakingKeeper.Delegate(s.ctx, addrs[i], math.NewInt(power), stakingtypes.Unbonded, val, true)
s.Require().NoError(err)
s.Require().Equal(newShares.TruncateInt(), math.NewInt(power))
msgValidatorBond := &stakingtypes.MsgValidatorBond{
DelegatorAddress: addrs[i].String(),
ValidatorAddress: val.OperatorAddress,
}
handler := s.app.MsgServiceRouter().Handler(msgValidatorBond)
_, err = handler(s.ctx, msgValidatorBond)
s.Require().NoError(err)
}

s.app.EndBlocker(s.ctx, abci.RequestEndBlock{})
Expand Down
87 changes: 53 additions & 34 deletions x/liquidstake/keeper/liquidstake.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"encoding/json"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"

Check failure on line 5 in x/liquidstake/keeper/liquidstake.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default -s prefix(github.com/persistenceOne/pstake-native) --custom-order (gci)
"sort"
"time"

Check failure on line 7 in x/liquidstake/keeper/liquidstake.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed with `-extra` (gofumpt)

Check failure on line 8 in x/liquidstake/keeper/liquidstake.go

View workflow job for this annotation

GitHub Actions / lint

File is not `goimports`-ed (goimports)
Expand Down Expand Up @@ -134,7 +135,7 @@ func (k Keeper) LiquidStake(
// LockOnLP sends tokens to a CW contract (Superfluid LP) with time locking.
// It performs a CosmWasm execution through global message handler and may fail.
// Emits events on a successful call.
func (k Keeper) LockOnLP(ctx sdk.Context, delegator sdk.AccAddress, amount sdk.Coin) ([]byte, error) {
func (k Keeper) LockOnLP(ctx sdk.Context, delegator sdk.AccAddress, amount sdk.Coin) ([]*codectypes.Any, error) {
params := k.GetParams(ctx)

if len(params.CwLockedPoolAddress) == 0 {
Expand Down Expand Up @@ -179,16 +180,9 @@ func (k Keeper) LockOnLP(ctx sdk.Context, delegator sdk.AccAddress, amount sdk.C
}

// emit the events from the dispatched actions
events := msgResp.Events
sdkEvents := make([]sdk.Event, 0, len(events))
for _, event := range events {
e := event
sdkEvents = append(sdkEvents, sdk.Event(e))
}

ctx.EventManager().EmitEvents(sdkEvents)
ctx.EventManager().EmitEvents(msgResp.GetEvents())

return msgResp.Data, nil
return msgResp.MsgResponses, nil
}

type ExecMsg struct {
Expand Down Expand Up @@ -281,24 +275,24 @@ func (k Keeper) LSMDelegate(
validator sdk.ValAddress,
proxyAcc sdk.AccAddress,
preLsmStake sdk.Coin,
) (newShares math.LegacyDec, stkXPRTMintAmount math.Int, err error) {
) (stkXPRTMintAmount math.Int, err error) {
params := k.GetParams(ctx)

if params.ModulePaused {
return sdk.ZeroDec(), sdk.ZeroInt(), types.ErrModulePaused
return sdk.ZeroInt(), types.ErrModulePaused
} else if params.LsmDisabled {
return sdk.ZeroDec(), sdk.ZeroInt(), types.ErrDisabledLSM
return sdk.ZeroInt(), types.ErrDisabledLSM
}

// check minimum liquid stake amount
if preLsmStake.Amount.LT(params.MinLiquidStakeAmount) {
return sdk.ZeroDec(), sdk.ZeroInt(), types.ErrLessThanMinLiquidStakeAmount
return sdk.ZeroInt(), types.ErrLessThanMinLiquidStakeAmount
}

// check bond denomination
bondDenom := k.stakingKeeper.BondDenom(ctx)
if preLsmStake.Denom != bondDenom {
return sdk.ZeroDec(), sdk.ZeroInt(), errorsmod.Wrapf(
return sdk.ZeroInt(), errorsmod.Wrapf(
types.ErrInvalidBondDenom, "invalid coin denomination: got %s, expected %s", preLsmStake.Denom, bondDenom,
)
}
Expand All @@ -307,22 +301,22 @@ func (k Keeper) LSMDelegate(
activeVals := k.GetActiveLiquidValidators(ctx, whitelistedValsMap)

if activeVals.Len() == 0 {
return sdk.ZeroDec(), sdk.ZeroInt(), types.ErrActiveLiquidValidatorsNotExists
return sdk.ZeroInt(), types.ErrActiveLiquidValidatorsNotExists
}

totalActiveWeight := activeVals.TotalWeight(whitelistedValsMap)
activeWeightQuorum := math.LegacyNewDecFromInt(totalActiveWeight).Quo(
math.LegacyNewDecFromInt(types.TotalValidatorWeight),
)
if activeWeightQuorum.LT(types.ActiveLiquidValidatorsWeightQuorum) {
return sdk.ZeroDec(), sdk.ZeroInt(), errorsmod.Wrapf(
return sdk.ZeroInt(), errorsmod.Wrapf(
types.ErrActiveLiquidValidatorsWeightQuorumNotReached, "%s < %s",
activeWeightQuorum.String(), types.ActiveLiquidValidatorsWeightQuorum.String(),
)
}

if !whitelistedValsMap.IsListed(validator.String()) {
return sdk.ZeroDec(), sdk.ZeroInt(), types.ErrLiquidValidatorsNotExists.Wrap("delegation from a non allowed validator")
return sdk.ZeroInt(), types.ErrLiquidValidatorsNotExists.Wrap("delegation from a non allowed validator")
}

// NetAmount must be calculated before send
Expand All @@ -339,24 +333,37 @@ func (k Keeper) LSMDelegate(

handler := k.router.Handler(lsmTokenizeMsg)
if handler == nil {
return sdk.ZeroDec(), sdk.ZeroInt(), sdkerrors.ErrUnknownRequest.Wrapf("unrecognized message route: %s", sdk.MsgTypeURL(lsmTokenizeMsg))
return sdk.ZeroInt(), sdkerrors.ErrUnknownRequest.Wrapf("unrecognized message route: %s", sdk.MsgTypeURL(lsmTokenizeMsg))
}

// [1] tokenize delegation into LSM shares
msgResp, err := handler(ctx, lsmTokenizeMsg)
if err != nil {
return sdk.ZeroDec(), sdk.ZeroInt(), types.ErrLSMTokenizeFailed.Wrapf("error: %s; message: %v", err.Error(), lsmTokenizeMsg)
return sdk.ZeroInt(), types.ErrLSMTokenizeFailed.Wrapf("error: %s; message: %v", err.Error(), lsmTokenizeMsg)
}
ctx.EventManager().EmitEvents(msgResp.GetEvents())

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

var lsmTokenizeResp stakingtypes.MsgTokenizeSharesResponse
if err := k.cdc.Unmarshal(msgResp.Data, &lsmTokenizeResp); err != nil {
panic("wrong data type: " + err.Error())
if err = k.cdc.Unmarshal(msgResp.MsgResponses[0].Value, &lsmTokenizeResp); err != nil {
return sdk.ZeroInt(), errorsmod.Wrapf(
sdkerrors.ErrJSONUnmarshal,
"cannot unmarshal tokenize share tx response message: %v",
err,
)
}

// [2] send LSM shares to proxyAcc
err = k.bankKeeper.SendCoins(ctx, delegator, proxyAcc, sdk.NewCoins(lsmTokenizeResp.Amount))
if err != nil {
return sdk.ZeroDec(), stkXPRTMintAmount, err
return stkXPRTMintAmount, err
}

lsmRedeemMsg := &stakingtypes.MsgRedeemTokensForShares{
Expand All @@ -366,18 +373,31 @@ func (k Keeper) LSMDelegate(

handler = k.router.Handler(lsmRedeemMsg)
if handler == nil {
return sdk.ZeroDec(), sdk.ZeroInt(), sdkerrors.ErrUnknownRequest.Wrapf("unrecognized message route: %s", sdk.MsgTypeURL(lsmRedeemMsg))
return sdk.ZeroInt(), sdkerrors.ErrUnknownRequest.Wrapf("unrecognized message route: %s", sdk.MsgTypeURL(lsmRedeemMsg))
}

// [3] redeem LSM shares from proxyAcc, to obtain a delegation
msgResp, err = handler(ctx, lsmRedeemMsg)
if err != nil {
return sdk.ZeroDec(), sdk.ZeroInt(), types.ErrLSMRedeemFailed.Wrapf("error: %s; message: %v", err.Error(), lsmRedeemMsg)
return sdk.ZeroInt(), types.ErrLSMRedeemFailed.Wrapf("error: %s; message: %v", err.Error(), lsmRedeemMsg)
}
ctx.EventManager().EmitEvents(msgResp.GetEvents())

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

var lsmRedeemResp stakingtypes.MsgRedeemTokensForSharesResponse
if err := k.cdc.Unmarshal(msgResp.Data, &lsmRedeemResp); err != nil {
panic("wrong data type: " + err.Error())
if err = k.cdc.Unmarshal(msgResp.MsgResponses[0].Value, &lsmRedeemResp); err != nil {
return sdk.ZeroInt(), errorsmod.Wrapf(
sdkerrors.ErrJSONUnmarshal,
"cannot unmarshal redeem tokens for shares tx response message: %v",
err,
)
}

// mint stkxprt, MintAmount = TotalSupply * StakeAmount/NetAmount
Expand All @@ -393,30 +413,29 @@ func (k Keeper) LSMDelegate(
}

if !stkXPRTMintAmount.IsPositive() {
return sdk.ZeroDec(), sdk.ZeroInt(), types.ErrTooSmallLiquidStakeAmount
return sdk.ZeroInt(), types.ErrTooSmallLiquidStakeAmount
}

// mint stkXPRT on module acc
mintCoin := sdk.NewCoins(sdk.NewCoin(liquidBondDenom, stkXPRTMintAmount))
err = k.bankKeeper.MintCoins(ctx, types.ModuleName, mintCoin)
if err != nil {
return sdk.ZeroDec(), stkXPRTMintAmount, err
return stkXPRTMintAmount, err
}

// send stkXPRT to delegator acc
err = k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, delegator, mintCoin)
if err != nil {
return sdk.ZeroDec(), stkXPRTMintAmount, err
return stkXPRTMintAmount, err
}

// but immediately lock new stkXPRT into LP on behalf of the delegator
_, err = k.LockOnLP(ctx, delegator, sdk.NewCoin(liquidBondDenom, stkXPRTMintAmount))
if err != nil {
return sdk.ZeroDec(), stkXPRTMintAmount, err
return stkXPRTMintAmount, err
}

newShares = lsmTokenizeResp.Amount.Amount.ToLegacyDec()
return newShares, stkXPRTMintAmount, err
return stkXPRTMintAmount, err
}

// LiquidDelegate delegates staking amount to active validators by proxy account.
Expand Down Expand Up @@ -662,7 +681,7 @@ func (k Keeper) CheckDelegationStates(ctx sdk.Context, proxyAcc sdk.AccAddress)
totalDelShares = totalDelShares.Add(delShares)
liquidTokens := val.TokensFromSharesTruncated(delShares).TruncateInt()
totalLiquidTokens = totalLiquidTokens.Add(liquidTokens)
totalRewards = totalRewards.Add(delReward.AmountOf(bondDenom))
totalRewards = totalRewards.Add(delReward.AmountOf(bondDenom).TruncateDec())
}
return false
},
Expand Down
3 changes: 1 addition & 2 deletions x/liquidstake/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (k msgServer) LiquidStake(goCtx context.Context, msg *types.MsgLiquidStake)
func (k msgServer) StakeToLP(goCtx context.Context, msg *types.MsgStakeToLP) (*types.MsgStakeToLPResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

newShares, stkXPRTMintAmount, err := k.LSMDelegate(
stkXPRTMintAmount, err := k.LSMDelegate(
ctx,
msg.GetDelegator(),
msg.GetValidator(),
Expand Down Expand Up @@ -96,7 +96,6 @@ func (k msgServer) StakeToLP(goCtx context.Context, msg *types.MsgStakeToLP) (*t
types.EventTypeMsgStakeToLP,
sdk.NewAttribute(types.AttributeKeyDelegator, msg.DelegatorAddress),
sdk.NewAttribute(types.AttributeKeyStakedAmount, msg.StakedAmount.String()),
sdk.NewAttribute(types.AttributeKeyNewShares, newShares.String()),
sdk.NewAttribute(types.AttributeKeyStkXPRTMintedAmount, stkXPRTMinted.String()),
sdk.NewAttribute(types.AttributeKeyCValue, cValue.String()),
),
Expand Down
2 changes: 1 addition & 1 deletion x/liquidstake/keeper/rebalancing.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ func (k Keeper) AutocompoundStakingRewards(ctx sdk.Context, whitelistedValsMap t
// re-staking of the accumulated rewards
cachedCtx, writeCache := ctx.CacheContext()
delegableAmount := proxyAccBalance.Amount.Sub(autocompoundFee.Amount)
_, err := k.LiquidDelegate(cachedCtx, types.LiquidStakeProxyAcc, activeVals, delegableAmount, whitelistedValsMap)
err := k.LiquidDelegate(cachedCtx, types.LiquidStakeProxyAcc, activeVals, delegableAmount, whitelistedValsMap)
if err != nil {
logger := k.Logger(ctx)
logger.Error("re-staking failed", "error", 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 @@ -276,9 +276,9 @@ func (s *KeeperTestSuite) TestRebalancingCase1() {

func (s *KeeperTestSuite) TestRebalancingConsecutiveCase() {
_, valOpers, _ := s.CreateValidators([]int64{
1000000, 1000000, 1000000, 1000000, 1000000,
1000000, 1000000, 1000000, 1000000, 1000000,
1000000, 1000000, 1000000, 1000000, 1000000,
1000000000000, 1000000000000, 1000000000000, 1000000000000, 1000000000000,
1000000000000, 1000000000000, 1000000000000, 1000000000000, 1000000000000,
1000000000000, 1000000000000, 1000000000000, 1000000000000, 1000000000000,
})
s.ctx = s.ctx.WithBlockHeight(100).WithBlockTime(testhelpers.ParseTime("2022-03-01T00:00:00Z"))
params := s.keeper.GetParams(s.ctx)
Expand Down Expand Up @@ -501,7 +501,7 @@ func (s *KeeperTestSuite) TestAutocompoundStakingRewards() {
totalRewardsAfter, totalDelSharesAfter, totalLiquidTokensAfter := s.keeper.CheckDelegationStates(s.ctx, types.LiquidStakeProxyAcc)
s.EqualValues(totalRewardsAfter, sdk.ZeroDec())

autocompoundFee := params.AutocompoundFeeRate.Mul(totalRewards)
autocompoundFee := params.AutocompoundFeeRate.Mul(totalRewards).TruncateDec()
s.EqualValues(totalDelSharesAfter, totalRewards.Sub(autocompoundFee).Add(totalDelShares).TruncateDec(), totalLiquidTokensAfter)

stakingParams := s.app.StakingKeeper.GetParams(s.ctx)
Expand Down

0 comments on commit 547b8dc

Please sign in to comment.