Skip to content

Commit

Permalink
feat: Dynamic c value limit updates (#758)
Browse files Browse the repository at this point in the history
* dynamic c value limit updates

* add constants and tests

* changelog

* Update x/liquidstakeibc/keeper/keeper.go

Co-authored-by: Puneet <[email protected]>

* use else

---------

Co-authored-by: Puneet <[email protected]>
  • Loading branch information
kruspy and puneet2019 authored Feb 8, 2024
1 parent 3f56ff5 commit 417d692
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Features

- [758](https://github.com/persistenceOne/pstake-native/pull/758) Dynamic C Value limit updates.
- [757](https://github.com/persistenceOne/pstake-native/pull/757) Change ibc transfer to use timeoutTimestamp instead of
timeoutHeight
- [755](https://github.com/persistenceOne/pstake-native/pull/755) Add channel-id, port to ratesync host-chains and
Expand Down
42 changes: 42 additions & 0 deletions x/liquidstakeibc/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"fmt"

"cosmossdk.io/math"
"github.com/cometbft/cometbft/libs/log"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
Expand Down Expand Up @@ -301,9 +302,11 @@ func (k *Keeper) UpdateCValues(ctx sdk.Context) {
hc.LastCValue = hc.CValue
hc.CValue = cValue
k.SetHostChain(ctx, hc)

if err := k.Hooks().PostCValueUpdate(ctx, hc.MintDenom(), hc.HostDenom, hc.CValue); err != nil {
k.Logger(ctx).Error("PostCValueUpdate hook failed with ", "err:", err)
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeCValueUpdate,
Expand Down Expand Up @@ -333,6 +336,8 @@ func (k *Keeper) UpdateCValues(ctx sdk.Context) {
sdk.NewAttribute(types.AttributeNewCValue, hc.CValue.String()),
),
)
} else {
k.RecalculateCValueLimits(ctx, hc, mintedAmount, liquidStakedAmount)
}
}
}
Expand All @@ -341,6 +346,43 @@ func (k *Keeper) CValueWithinLimits(hc *types.HostChain) bool {
return hc.CValue.LT(hc.Params.UpperCValueLimit) && hc.CValue.GT(hc.Params.LowerCValueLimit)
}

func (k *Keeper) RecalculateCValueLimits(ctx sdk.Context, hc *types.HostChain, mintedAmount, lsAmount math.Int) {
// if there has been no activity on the chain yet, leave the limits as they are
if mintedAmount.IsZero() || lsAmount.IsZero() {
return
}

// calculate twice the amount of rewards which will be transferred next rewards epoch
diff := sdk.NewDecFromInt(hc.GetHostChainTotalDelegations()).
Mul(hc.AutoCompoundFactor).Mul(sdk.NewDec(types.CValueDynamicLowerDiff))

// calculate the new lower and upper limit
newLowerLimit := sdk.NewDecFromInt(mintedAmount).Quo(sdk.NewDecFromInt(lsAmount).Add(diff))
newUpperLimit := hc.CValue.Add(hc.CValue.Sub(newLowerLimit).Mul(sdk.NewDec(types.CValueDynamicUpperDiff)))

// update the limits on the host chain
hc.Params.LowerCValueLimit = newLowerLimit
hc.Params.UpperCValueLimit = newUpperLimit
k.SetHostChain(ctx, hc)

k.Logger(ctx).Info(
fmt.Sprintf("Updated C Value limits for %s. Current C Value %s, new lower limit %s, new upper limit %s",
hc.ChainId,
hc.CValue,
hc.Params.LowerCValueLimit,
hc.Params.UpperCValueLimit,
),
)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeCValueLimitsUpdated,
sdk.NewAttribute(types.AttributeChainID, hc.ChainId),
sdk.NewAttribute(types.AttributeLowerLimit, hc.Params.LowerCValueLimit.String()),
sdk.NewAttribute(types.AttributeUpperLimit, hc.Params.UpperCValueLimit.String()),
),
)
}

func (k *Keeper) CalculateAutocompoundLimit(autocompoundFactor sdk.Dec) sdk.Dec {
return autocompoundFactor.Quo(sdk.NewDec(types.Percentage)).Quo(sdk.NewDec(types.DaysInYear))
}
Expand Down
26 changes: 26 additions & 0 deletions x/liquidstakeibc/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,29 @@ func (suite *IntegrationTestSuite) TestUpdateCValues() {
hc, _ = pstakeApp.LiquidStakeIBCKeeper.GetHostChain(ctx, suite.chainB.ChainID)
suite.Require().Equal(false, hc.Active)
}

func (suite *IntegrationTestSuite) TestRecalculateCValueLimits() {
pstakeApp, ctx := suite.app, suite.ctx
hc, found := pstakeApp.LiquidStakeIBCKeeper.GetHostChain(ctx, suite.chainB.ChainID)
suite.Require().Equal(true, found)
suite.Require().NotNil(hc)
suite.Require().Equal(sdk.NewDec(1), hc.CValue)

pstakeApp.LiquidStakeIBCKeeper.RecalculateCValueLimits(ctx, hc, sdk.NewInt(0), sdk.NewInt(0))
suite.Require().Equal("0.950000000000000000", hc.Params.LowerCValueLimit.String())
suite.Require().Equal("1.050000000000000000", hc.Params.UpperCValueLimit.String())

hc.Validators[0].DelegatedAmount = sdk.NewInt(1000)
pstakeApp.LiquidStakeIBCKeeper.SetHostChainValidator(ctx, hc, hc.Validators[0])

pstakeApp.LiquidStakeIBCKeeper.RecalculateCValueLimits(ctx, hc, sdk.NewInt(1000), sdk.NewInt(1000))

expectedLower := sdk.NewDec(1000).Quo(sdk.NewDec(1000).
Add(sdk.NewDec(1000).Mul(hc.AutoCompoundFactor).Mul(sdk.NewDec(types.CValueDynamicLowerDiff))))

suite.Require().Equal(expectedLower, hc.Params.LowerCValueLimit)

expectedUpper := hc.CValue.Add(hc.CValue.Sub(hc.Params.LowerCValueLimit).Mul(sdk.NewDec(types.CValueDynamicUpperDiff)))

suite.Require().Equal(expectedUpper, hc.Params.UpperCValueLimit)
}
3 changes: 3 additions & 0 deletions x/liquidstakeibc/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const (
EventTypeSlashing = "validator_slash"
EventTypeUpdateParams = "update_params"
EventTypeChainDisabled = "chain_disabled"
EventTypeCValueLimitsUpdated = "c_value_limits"
EventTypeValidatorStatusUpdate = "validator_status_update"
EventTypeValidatorExchangeRateUpdate = "validator_exchange_rate_update"
EventTypeValidatorDelegableStateUpdate = "validator_delegable_state_update"
Expand Down Expand Up @@ -58,6 +59,8 @@ const (
AttributeChainID = "chain_id"
AttributeNewCValue = "new_c_value"
AttributeOldCValue = "old_c_value"
AttributeLowerLimit = "lower_limit"
AttributeUpperLimit = "upper_limit"
AttributeEpoch = "epoch_number"
AttributeValidatorAddress = "validator_address"
AttributeExistingDelegation = "existing_delegation"
Expand Down
4 changes: 4 additions & 0 deletions x/liquidstakeibc/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ const (
Percentage int64 = 100

DaysInYear int64 = 365

CValueDynamicLowerDiff int64 = 2

CValueDynamicUpperDiff int64 = 10
)

// Consts for KV updates, update host chain
Expand Down

0 comments on commit 417d692

Please sign in to comment.