From df63f17caf7f5880ca070b5af7288c15225c53d8 Mon Sep 17 00:00:00 2001 From: Teddy Ding Date: Mon, 25 Mar 2024 10:20:20 -0400 Subject: [PATCH] Add upgrade handler for OIMF --- protocol/app/upgrades/v5.0.0/upgrade.go | 52 +++++++++++++++++++ protocol/mocks/PerpetualsKeeper.go | 20 +++++++ .../scripts/genesis/sample_pregenesis.json | 4 +- protocol/testing/genesis.sh | 7 ++- protocol/x/perpetuals/types/types.go | 1 + 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/protocol/app/upgrades/v5.0.0/upgrade.go b/protocol/app/upgrades/v5.0.0/upgrade.go index 2e8176c179..bd5ccbbb11 100644 --- a/protocol/app/upgrades/v5.0.0/upgrade.go +++ b/protocol/app/upgrades/v5.0.0/upgrade.go @@ -98,6 +98,55 @@ func blockRateLimitConfigUpdate( ) } +// Initialize soft and upper caps for OIMF +func initializeOIMFCaps( + ctx sdk.Context, + perpetualsKeeper perptypes.PerpetualsKeeper, +) { + allLiquidityTiers := perpetualsKeeper.GetAllLiquidityTiers(ctx) + for _, tier := range allLiquidityTiers { + if tier.Id == 0 { + // For large cap, no OIMF caps + tier.OpenInterestLowerCap = 0 + tier.OpenInterestUpperCap = 0 + } else if tier.Id == 1 { + // Mid cap + tier.OpenInterestLowerCap = 25_000_000_000_000 // 25 million USDC + tier.OpenInterestUpperCap = 50_000_000_000_000 // 50 million USDC + } else if tier.Id == 2 { + // Long tail + tier.OpenInterestLowerCap = 10_000_000_000_000 // 10 million USDC + tier.OpenInterestUpperCap = 20_000_000_000_000 // 20 million USDC + } else { + // Safety + tier.OpenInterestLowerCap = 500_000_000_000 // 0.5 million USDC + tier.OpenInterestUpperCap = 1_000_000_000_000 // 1 million USDC + } + + lt, err := perpetualsKeeper.SetLiquidityTier( + ctx, + tier.Id, + tier.Name, + tier.InitialMarginPpm, + tier.MaintenanceFractionPpm, + tier.ImpactNotional, + tier.OpenInterestLowerCap, + tier.OpenInterestUpperCap, + ) + if err != nil { + panic(fmt.Sprintf("failed to set liquidity tier: %+v,\n err: %s", tier.Id, err)) + } + // TODO(OTE-248): Optional - emit indexer events that for updated liquidity tier + ctx.Logger().Info( + fmt.Sprintf( + "Successfully set liqiquidity tier with `OpenInterestLower/UpperCap`: %+v\n", + lt, + ), + ) + // TODO(OTE-249): Add upgrade test that checks if the OIMF caps are set correctly + } +} + func CreateUpgradeHandler( mm *module.Manager, configurator module.Configurator, @@ -114,6 +163,9 @@ func CreateUpgradeHandler( // Set block rate limit configuration blockRateLimitConfigUpdate(sdkCtx, clobKeeper) + // Initialize liquidity tier with lower and upper OI caps. + initializeOIMFCaps(sdkCtx, perpetualsKeeper) + // TODO(TRA-93): Initialize `x/vault` module. return mm.RunMigrations(ctx, configurator, vm) diff --git a/protocol/mocks/PerpetualsKeeper.go b/protocol/mocks/PerpetualsKeeper.go index 85da4a3b2b..f729748879 100644 --- a/protocol/mocks/PerpetualsKeeper.go +++ b/protocol/mocks/PerpetualsKeeper.go @@ -82,6 +82,26 @@ func (_m *PerpetualsKeeper) GetAddPremiumVotes(ctx types.Context) *perpetualstyp return r0 } +// GetAllLiquidityTiers provides a mock function with given fields: ctx +func (_m *PerpetualsKeeper) GetAllLiquidityTiers(ctx types.Context) []perpetualstypes.LiquidityTier { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetAllLiquidityTiers") + } + + var r0 []perpetualstypes.LiquidityTier + if rf, ok := ret.Get(0).(func(types.Context) []perpetualstypes.LiquidityTier); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]perpetualstypes.LiquidityTier) + } + } + + return r0 +} + // GetAllPerpetuals provides a mock function with given fields: ctx func (_m *PerpetualsKeeper) GetAllPerpetuals(ctx types.Context) []perpetualstypes.Perpetual { ret := _m.Called(ctx) diff --git a/protocol/scripts/genesis/sample_pregenesis.json b/protocol/scripts/genesis/sample_pregenesis.json index 046f53e67f..414c3d4690 100644 --- a/protocol/scripts/genesis/sample_pregenesis.json +++ b/protocol/scripts/genesis/sample_pregenesis.json @@ -895,8 +895,8 @@ "initial_margin_ppm": 1000000, "maintenance_fraction_ppm": 200000, "name": "Safety", - "open_interest_lower_cap": 0, - "open_interest_upper_cap": 0 + "open_interest_lower_cap": 500000000000, + "open_interest_upper_cap": 1000000000000 } ], "params": { diff --git a/protocol/testing/genesis.sh b/protocol/testing/genesis.sh index 747b02bbbe..33252badf5 100755 --- a/protocol/testing/genesis.sh +++ b/protocol/testing/genesis.sh @@ -169,10 +169,9 @@ function edit_genesis() { dasel put -t int -f "$GENESIS" '.app_state.perpetuals.liquidity_tiers.[3].maintenance_fraction_ppm' -v '200000' # 20% of IM dasel put -t int -f "$GENESIS" '.app_state.perpetuals.liquidity_tiers.[3].base_position_notional' -v '1000000000' # 1_000 USDC dasel put -t int -f "$GENESIS" '.app_state.perpetuals.liquidity_tiers.[3].impact_notional' -v '2500000000' # 2_500 USDC (2_500 USDC / 100%) - # OIMF doesn't apply to `Safety`, since IMF is already at 100%. - dasel put -t int -f "$GENESIS" '.app_state.perpetuals.liquidity_tiers.[3].open_interest_lower_cap' -v '0' - dasel put -t int -f "$GENESIS" '.app_state.perpetuals.liquidity_tiers.[3].open_interest_upper_cap' -v '0' - + # For `Safety` IMF is already at 100%; still we set OIMF for completeness. + dasel put -t int -f "$GENESIS" '.app_state.perpetuals.liquidity_tiers.[3].open_interest_lower_cap' -v '500000000000' # 0.5 million USDC + dasel put -t int -f "$GENESIS" '.app_state.perpetuals.liquidity_tiers.[3].open_interest_upper_cap' -v '1000000000000' # 1 million USDC # Params. dasel put -t int -f "$GENESIS" '.app_state.perpetuals.params.funding_rate_clamp_factor_ppm' -v '6000000' # 600 % (same as 75% on hourly rate) diff --git a/protocol/x/perpetuals/types/types.go b/protocol/x/perpetuals/types/types.go index 81ba665c2b..7fc9ebdb9b 100644 --- a/protocol/x/perpetuals/types/types.go +++ b/protocol/x/perpetuals/types/types.go @@ -118,6 +118,7 @@ type PerpetualsKeeper interface { GetAllPerpetuals( ctx sdk.Context, ) []Perpetual + GetAllLiquidityTiers(ctx sdk.Context) (list []LiquidityTier) } type OpenInterestDelta struct {