Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore/v4.x lo migrations #674

Closed
wants to merge 11 commits into from
4 changes: 3 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
servicemetrics "github.com/skip-mev/slinky/service/metrics"

v401 "github.com/neutron-org/neutron/v4/app/upgrades/v4.0.1"
v402 "github.com/neutron-org/neutron/v4/app/upgrades/v4.2.0"
"github.com/neutron-org/neutron/v4/x/globalfee"
globalfeetypes "github.com/neutron-org/neutron/v4/x/globalfee/types"

Expand Down Expand Up @@ -225,7 +226,7 @@ const (
)

var (
Upgrades = []upgrades.Upgrade{v401.Upgrade}
Upgrades = []upgrades.Upgrade{v401.Upgrade, v402.Upgrade}

// DefaultNodeHome default home directories for the application daemon
DefaultNodeHome string
Expand Down Expand Up @@ -1409,6 +1410,7 @@ func (app *App) setupUpgradeHandlers() {
MarketmapKeeper: app.MarketMapKeeper,
FeeMarketKeeper: app.FeeMarkerKeeper,
DynamicfeesKeeper: app.DynamicFeesKeeper,
DexKeeper: &app.DexKeeper,
GlobalFeeSubspace: app.GetSubspace(globalfee.ModuleName),
CcvConsumerSubspace: app.GetSubspace(ccvconsumertypes.ModuleName),
},
Expand Down
3 changes: 3 additions & 0 deletions app/upgrades/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (

paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
transferkeeper "github.com/cosmos/ibc-go/v8/modules/apps/transfer/keeper"

dexkeeper "github.com/neutron-org/neutron/v4/x/dex/keeper"
)

// Upgrade defines a struct containing necessary fields that a SoftwareUpgradeProposal
Expand Down Expand Up @@ -64,6 +66,7 @@ type UpgradeKeepers struct {
MarketmapKeeper *marketmapkeeper.Keeper
FeeMarketKeeper *feemarketkeeper.Keeper
DynamicfeesKeeper *dynamicfeeskeeper.Keeper
DexKeeper *dexkeeper.Keeper
// subspaces
GlobalFeeSubspace paramtypes.Subspace
CcvConsumerSubspace paramtypes.Subspace
Expand Down
20 changes: 20 additions & 0 deletions app/upgrades/v4.2.0/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package v400

import (
storetypes "cosmossdk.io/store/types"

"github.com/neutron-org/neutron/v4/app/upgrades"
)

const (
// UpgradeName defines the on-chain upgrade name.
UpgradeName = "v4.2.0"
)

var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
CreateUpgradeHandler: CreateUpgradeHandler,
StoreUpgrades: storetypes.StoreUpgrades{
Added: []string{},
},
}
121 changes: 121 additions & 0 deletions app/upgrades/v4.2.0/upgrades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package v400

import (
"context"
"fmt"

upgradetypes "cosmossdk.io/x/upgrade/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"

math_utils "github.com/neutron-org/neutron/v4/utils/math"

"cosmossdk.io/math"

"github.com/neutron-org/neutron/v4/app/upgrades"
dexkeeper "github.com/neutron-org/neutron/v4/x/dex/keeper"
dextypes "github.com/neutron-org/neutron/v4/x/dex/types"
)

func CreateUpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
keepers *upgrades.UpgradeKeepers,
_ upgrades.StoreKeys,
_ codec.Codec,
) upgradetypes.UpgradeHandler {
return func(c context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
ctx := sdk.UnwrapSDKContext(c)

ctx.Logger().Info("Starting module migrations...")
vm, err := mm.RunMigrations(ctx, configurator, vm)
if err != nil {
return vm, err
}

// Only run this migration for testnet.
// NEUTRON-1 HAS ALREADY BEEN UPGRADED AND RE-RUNNING THE MIGRATION WOULD BREAK STATE!
if ctx.ChainID() == "pion-1" {
migrateLimitOrderTrancheAccounting(ctx, *keepers.DexKeeper)
}

ctx.Logger().Info(fmt.Sprintf("Migration {%s} applied", UpgradeName))
return vm, nil
}
}

type TrancheData struct {
SharesWithdrawn math.Int
Tranche dextypes.LimitOrderTranche
}

func fetchTrancheByTrancheUser(
ctx sdk.Context,
k dexkeeper.Keeper,
trancheUser *dextypes.LimitOrderTrancheUser,
) (*dextypes.LimitOrderTranche, bool) {
key := dextypes.LimitOrderTrancheKey{
TickIndexTakerToMaker: trancheUser.TickIndexTakerToMaker,
TradePairId: trancheUser.TradePairId,
TrancheKey: trancheUser.TrancheKey,
}

return k.GetLimitOrderTrancheByKey(ctx, key.KeyMarshal())
}

// Due to a bug in our limitorder accounting we must update the TotalTakerDenom to ensure correct accounting for withdrawals
func migrateLimitOrderTrancheAccounting(ctx sdk.Context, k dexkeeper.Keeper) {
ctx.Logger().Info("Migrating LimitOrderTranches...")

trancheUpdateData := make(map[string]TrancheData)
trancheUsersToDelete := make([]*dextypes.LimitOrderTrancheUser, 0)

allTrancheUsers := k.GetAllLimitOrderTrancheUser(ctx)

// Iterate through all limitOrderTrancheUsers
// Sum up the total SharesWithdrawn for each tranche
for _, trancheUser := range allTrancheUsers {
val, ok := trancheUpdateData[trancheUser.TrancheKey]
if !ok {
tranche, found := fetchTrancheByTrancheUser(ctx, k, trancheUser)

// Due to an earlier error in our rounding behavior / tranche accounting
// there are trancheUsers that have dust amounts of un-withdrawn shares but the tranche has already been deleted
// FWIW this issue only exists on pion-1
// We can safely delete these trancheUsers
if !found {
trancheUsersToDelete = append(trancheUsersToDelete, trancheUser)
continue
}

trancheUpdateData[trancheUser.TrancheKey] = TrancheData{SharesWithdrawn: trancheUser.SharesWithdrawn, Tranche: *tranche}
} else {
newVal := TrancheData{
SharesWithdrawn: val.SharesWithdrawn.Add(trancheUser.SharesWithdrawn),
Tranche: val.Tranche,
}
trancheUpdateData[trancheUser.TrancheKey] = newVal
}
}

// Update tranches
for _, trancheData := range trancheUpdateData {
tranche := trancheData.Tranche
// Calculate total sharesWithdrawn from tranche (denominated in TakerDenom)
sharesWithdrawnTaker := math_utils.NewPrecDecFromInt(trancheData.SharesWithdrawn).Quo(trancheData.Tranche.PriceTakerToMaker)
// TotalTakerDenom = ReservesTakerDenom + SharesWithdrawn
newTotalTakerDenom := sharesWithdrawnTaker.TruncateInt().Add(tranche.ReservesTakerDenom)
// Update Tranche
tranche.TotalTakerDenom = newTotalTakerDenom

// Save new limit order tranche
k.SetLimitOrderTranche(ctx, &tranche)

}

// Delete the orphaned trancheUsers
for _, trancheUser := range trancheUsersToDelete {
k.RemoveLimitOrderTrancheUser(ctx, trancheUser)
}
}
Loading
Loading