From 10e62c59b7e7b5fc15743302b5b3712f627a751d Mon Sep 17 00:00:00 2001 From: jayy04 <103467857+jayy04@users.noreply.github.com> Date: Thu, 14 Sep 2023 15:02:42 -0400 Subject: [PATCH] v0.2.2 hard fork to update clob pairs (#263) * v0.2.2 hard fork to update clob pairs * remove from memclob * clear op queue * update numbers * update test * Add UpdateClobPair indexer event * recreate orderbook * missing args * clear untriggered conditional order struct * fix lint * fix multiple clob pair per perpetual issue * pass by value * disable trading until after upgrade * add unsafe reset memclob method * update subticks per tick and QCE to latest values * update pepe values --------- Co-authored-by: Teddy Ding --- protocol/app/app.go | 6 +- protocol/app/app_test.go | 4 +- protocol/app/upgrades.go | 15 ++- protocol/app/upgrades/types.go | 5 - protocol/app/upgrades/v0.2.2/constants.go | 26 +++++ protocol/app/upgrades/v0.2.2/upgrades.go | 64 +++++++++++++ protocol/app/upgrades_test.go | 7 +- .../indexer/events/update_clob_pair_create.go | 24 +++++ protocol/mocks/ClobKeeper.go | 96 +++++-------------- protocol/mocks/MemClob.go | 5 + protocol/mocks/PerpetualsClobKeeper.go | 12 +-- protocol/mocks/PerpetualsKeeper.go | 24 ++--- protocol/x/clob/ante/clob.go | 6 ++ protocol/x/clob/keeper/clob_pair.go | 23 +++++ protocol/x/clob/memclob/memclob.go | 8 ++ protocol/x/clob/types/errors.go | 5 + protocol/x/clob/types/memclob.go | 3 + 17 files changed, 214 insertions(+), 119 deletions(-) create mode 100644 protocol/app/upgrades/v0.2.2/constants.go create mode 100644 protocol/app/upgrades/v0.2.2/upgrades.go create mode 100644 protocol/indexer/events/update_clob_pair_create.go diff --git a/protocol/app/app.go b/protocol/app/app.go index 50cd1646d8..8ec6048318 100644 --- a/protocol/app/app.go +++ b/protocol/app/app.go @@ -172,6 +172,8 @@ import ( "github.com/dydxprotocol/v4-chain/protocol/indexer" "github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager" "github.com/dydxprotocol/v4-chain/protocol/indexer/msgsender" + + v0_2_2 "github.com/dydxprotocol/v4-chain/protocol/app/upgrades/v0.2.2" ) var ( @@ -180,8 +182,8 @@ var ( // `Upgrades` defines the upgrade handlers and store loaders for the application. // New upgrades should be added to this slice after they are implemented. - Upgrades = []upgrades.Upgrade{} - Forks = []upgrades.Fork{} + Upgrades = []upgrades.Upgrade{v0_2_2.Upgrade} + Forks = []upgrades.Fork{v0_2_2.Fork} ) var ( diff --git a/protocol/app/app_test.go b/protocol/app/app_test.go index 9dca226ed6..41b98b6aea 100644 --- a/protocol/app/app_test.go +++ b/protocol/app/app_test.go @@ -150,11 +150,11 @@ func TestSimulationManager(t *testing.T) { } func TestUpgrades(t *testing.T) { - require.Len(t, app.Upgrades, 0, "Expected no Upgrades") + require.Len(t, app.Upgrades, 1, "Expected 1 Upgrades") } func TestForks(t *testing.T) { - require.Len(t, app.Forks, 0, "Expected no Forks") + require.Len(t, app.Forks, 1, "Expected 1 Forks") } func TestModuleBasics(t *testing.T) { diff --git a/protocol/app/upgrades.go b/protocol/app/upgrades.go index 93926a2833..7c97a6feb3 100644 --- a/protocol/app/upgrades.go +++ b/protocol/app/upgrades.go @@ -5,20 +5,19 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + v0_2_2 "github.com/dydxprotocol/v4-chain/protocol/app/upgrades/v0.2.2" ) // setupUpgradeHandlers registers the upgrade handlers to perform custom upgrade // logic and state migrations for software upgrades. func (app *App) setupUpgradeHandlers() { - for _, upgrade := range Upgrades { - if app.UpgradeKeeper.HasHandler(upgrade.UpgradeName) { - panic(fmt.Sprintf("Cannot register duplicate upgrade handler '%s'", upgrade.UpgradeName)) - } - app.UpgradeKeeper.SetUpgradeHandler( - upgrade.UpgradeName, - upgrade.CreateUpgradeHandler(app.ModuleManager, app.configurator), - ) + if app.UpgradeKeeper.HasHandler(v0_2_2.UpgradeName) { + panic(fmt.Sprintf("Cannot register duplicate upgrade handler '%s'", v0_2_2.UpgradeName)) } + app.UpgradeKeeper.SetUpgradeHandler( + v0_2_2.UpgradeName, + v0_2_2.CreateUpgradeHandler(app.ModuleManager, app.configurator, app.ClobKeeper), + ) } // setUpgradeStoreLoaders sets custom store loaders to customize the rootMultiStore diff --git a/protocol/app/upgrades/types.go b/protocol/app/upgrades/types.go index 01cec47da8..3a772a4de4 100644 --- a/protocol/app/upgrades/types.go +++ b/protocol/app/upgrades/types.go @@ -2,8 +2,6 @@ package upgrades import ( store "github.com/cosmos/cosmos-sdk/store/types" - "github.com/cosmos/cosmos-sdk/types/module" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) // Upgrade defines a struct containing necessary fields that a MsgSoftwareUpgrade @@ -14,9 +12,6 @@ type Upgrade struct { // Upgrade version name, for the upgrade handler, e.g. `v7` UpgradeName string - // CreateUpgradeHandler defines the function that creates an upgrade handler - CreateUpgradeHandler func(*module.Manager, module.Configurator) upgradetypes.UpgradeHandler - // Store upgrades, should be used for any new modules introduced, new modules deleted, or store names renamed. StoreUpgrades store.StoreUpgrades } diff --git a/protocol/app/upgrades/v0.2.2/constants.go b/protocol/app/upgrades/v0.2.2/constants.go new file mode 100644 index 0000000000..00e8e81f1c --- /dev/null +++ b/protocol/app/upgrades/v0.2.2/constants.go @@ -0,0 +1,26 @@ +package v0_2_2 + +import ( + store "github.com/cosmos/cosmos-sdk/store/types" + "github.com/dydxprotocol/v4-chain/protocol/app/upgrades" +) + +const ( + UpgradeName = "v0.2.2" + // Target upgrade time is Sept 15, 2023, 1pm EST, + // estimated to occur on block 178500, assuming 1.5s block time. + UpgradeHeight = 178500 +) + +var ( + Fork = upgrades.Fork{ + UpgradeName: UpgradeName, + UpgradeHeight: UpgradeHeight, + UpgradeInfo: "", + } + + Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, + StoreUpgrades: store.StoreUpgrades{}, + } +) diff --git a/protocol/app/upgrades/v0.2.2/upgrades.go b/protocol/app/upgrades/v0.2.2/upgrades.go new file mode 100644 index 0000000000..a7cb256256 --- /dev/null +++ b/protocol/app/upgrades/v0.2.2/upgrades.go @@ -0,0 +1,64 @@ +package v0_2_2 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + clobmodulekeeper "github.com/dydxprotocol/v4-chain/protocol/x/clob/keeper" + clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" +) + +func CreateUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, + clobKeeper *clobmodulekeeper.Keeper, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + ctx.Logger().Info("Running v0.2.2 hard fork...") + + // Update clob pairs. + clobPairs := clobKeeper.GetAllClobPairs(ctx) + for _, clobPair := range clobPairs { + switch clobPair.Id { + case 0, 1: + clobPair.SubticksPerTick = 1e5 + clobPair.QuantumConversionExponent = -9 + case 28: + clobPair.SubticksPerTick = 1e6 + clobPair.QuantumConversionExponent = -12 + case 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32: + clobPair.SubticksPerTick = 1e6 + clobPair.QuantumConversionExponent = -9 + default: + ctx.Logger().Error("Unknown clob pair id", "clobPairId", clobPair.Id) + } + clobKeeper.UnsafeSetClobPair( + ctx, + clobPair, + ) + } + + // Delete all stateful ordes. + placedStatefulOrders := clobKeeper.GetAllPlacedStatefulOrders(ctx) + for _, order := range placedStatefulOrders { + clobKeeper.MustRemoveStatefulOrder(ctx, order.OrderId) + } + + untriggeredConditionalOrders := clobKeeper.GetAllUntriggeredConditionalOrders(ctx) + for _, order := range untriggeredConditionalOrders { + clobKeeper.MustRemoveStatefulOrder(ctx, order.OrderId) + } + clobKeeper.UntriggeredConditionalOrders = make( + map[clobtypes.ClobPairId]*clobmodulekeeper.UntriggeredConditionalOrders, + ) + + // Update memclob. + clobKeeper.MemClob.UnsafeResetMemclob(ctx) + + clobKeeper.PerpetualIdToClobPairId = make(map[uint32][]clobtypes.ClobPairId) + clobKeeper.InitMemClobOrderbooks(ctx) + + return mm.RunMigrations(ctx, configurator, vm) + } +} diff --git a/protocol/app/upgrades_test.go b/protocol/app/upgrades_test.go index b3041c732b..a4dd383861 100644 --- a/protocol/app/upgrades_test.go +++ b/protocol/app/upgrades_test.go @@ -1,12 +1,13 @@ package app_test import ( + "testing" + "github.com/dydxprotocol/v4-chain/protocol/app" "github.com/stretchr/testify/require" - "testing" ) func TestDefaultUpgradesAndForks(t *testing.T) { - require.Empty(t, app.Upgrades, "Expected empty upgrades list") - require.Empty(t, app.Forks, "Expected empty forks list") + require.Len(t, app.Upgrades, 1, "Expected 1 upgrade") + require.Len(t, app.Forks, 1, "Expected 1 fork") } diff --git a/protocol/indexer/events/update_clob_pair_create.go b/protocol/indexer/events/update_clob_pair_create.go new file mode 100644 index 0000000000..d48443fceb --- /dev/null +++ b/protocol/indexer/events/update_clob_pair_create.go @@ -0,0 +1,24 @@ +package events + +import ( + v1 "github.com/dydxprotocol/v4-chain/protocol/indexer/protocol/v1" + "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" +) + +// NewUpdateClobPairEvent creates a UpdateClobPairEventV1 +// representing update of a clob pair. +func NewUpdateClobPairEvent( + clobPairId uint32, + status types.ClobPair_Status, + quantumConversionExponent int32, + subticksPerTick uint32, + stepBaseQuantums uint64, +) *UpdateClobPairEventV1 { + return &UpdateClobPairEventV1{ + ClobPairId: clobPairId, + Status: v1.ConvertToClobPairStatus(status), + QuantumConversionExponent: quantumConversionExponent, + SubticksPerTick: subticksPerTick, + StepBaseQuantums: stepBaseQuantums, + } +} diff --git a/protocol/mocks/ClobKeeper.go b/protocol/mocks/ClobKeeper.go index 336f5ac4af..c5b1a3220f 100644 --- a/protocol/mocks/ClobKeeper.go +++ b/protocol/mocks/ClobKeeper.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package mocks @@ -29,16 +29,13 @@ func (_m *ClobKeeper) AddOrderToOrderbookCollatCheck(ctx types.Context, clobPair ret := _m.Called(ctx, clobPairId, subaccountOpenOrders) var r0 bool - var r1 map[subaccountstypes.SubaccountId]subaccountstypes.UpdateResult - if rf, ok := ret.Get(0).(func(types.Context, clobtypes.ClobPairId, map[subaccountstypes.SubaccountId][]clobtypes.PendingOpenOrder) (bool, map[subaccountstypes.SubaccountId]subaccountstypes.UpdateResult)); ok { - return rf(ctx, clobPairId, subaccountOpenOrders) - } if rf, ok := ret.Get(0).(func(types.Context, clobtypes.ClobPairId, map[subaccountstypes.SubaccountId][]clobtypes.PendingOpenOrder) bool); ok { r0 = rf(ctx, clobPairId, subaccountOpenOrders) } else { r0 = ret.Get(0).(bool) } + var r1 map[subaccountstypes.SubaccountId]subaccountstypes.UpdateResult if rf, ok := ret.Get(1).(func(types.Context, clobtypes.ClobPairId, map[subaccountstypes.SubaccountId][]clobtypes.PendingOpenOrder) map[subaccountstypes.SubaccountId]subaccountstypes.UpdateResult); ok { r1 = rf(ctx, clobPairId, subaccountOpenOrders) } else { @@ -97,16 +94,13 @@ func (_m *ClobKeeper) CreatePerpetualClobPair(ctx types.Context, clobPairId uint ret := _m.Called(ctx, clobPairId, perpetualId, stepSizeInBaseQuantums, quantumConversionExponent, subticksPerTick, status) var r0 clobtypes.ClobPair - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, uint32, uint32, subaccountstypes.BaseQuantums, int32, uint32, clobtypes.ClobPair_Status) (clobtypes.ClobPair, error)); ok { - return rf(ctx, clobPairId, perpetualId, stepSizeInBaseQuantums, quantumConversionExponent, subticksPerTick, status) - } if rf, ok := ret.Get(0).(func(types.Context, uint32, uint32, subaccountstypes.BaseQuantums, int32, uint32, clobtypes.ClobPair_Status) clobtypes.ClobPair); ok { r0 = rf(ctx, clobPairId, perpetualId, stepSizeInBaseQuantums, quantumConversionExponent, subticksPerTick, status) } else { r0 = ret.Get(0).(clobtypes.ClobPair) } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, uint32, uint32, subaccountstypes.BaseQuantums, int32, uint32, clobtypes.ClobPair_Status) error); ok { r1 = rf(ctx, clobPairId, perpetualId, stepSizeInBaseQuantums, quantumConversionExponent, subticksPerTick, status) } else { @@ -142,10 +136,6 @@ func (_m *ClobKeeper) GetBankruptcyPriceInQuoteQuantums(ctx types.Context, subac ret := _m.Called(ctx, subaccountId, perpetualId, deltaQuantums) var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId, uint32, *big.Int) (*big.Int, error)); ok { - return rf(ctx, subaccountId, perpetualId, deltaQuantums) - } if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId, uint32, *big.Int) *big.Int); ok { r0 = rf(ctx, subaccountId, perpetualId, deltaQuantums) } else { @@ -154,6 +144,7 @@ func (_m *ClobKeeper) GetBankruptcyPriceInQuoteQuantums(ctx types.Context, subac } } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, subaccountstypes.SubaccountId, uint32, *big.Int) error); ok { r1 = rf(ctx, subaccountId, perpetualId, deltaQuantums) } else { @@ -168,16 +159,13 @@ func (_m *ClobKeeper) GetClobPair(ctx types.Context, id clobtypes.ClobPairId) (c ret := _m.Called(ctx, id) var r0 clobtypes.ClobPair - var r1 bool - if rf, ok := ret.Get(0).(func(types.Context, clobtypes.ClobPairId) (clobtypes.ClobPair, bool)); ok { - return rf(ctx, id) - } if rf, ok := ret.Get(0).(func(types.Context, clobtypes.ClobPairId) clobtypes.ClobPair); ok { r0 = rf(ctx, id) } else { r0 = ret.Get(0).(clobtypes.ClobPair) } + var r1 bool if rf, ok := ret.Get(1).(func(types.Context, clobtypes.ClobPairId) bool); ok { r1 = rf(ctx, id) } else { @@ -192,10 +180,6 @@ func (_m *ClobKeeper) GetFillablePrice(ctx types.Context, subaccountId subaccoun ret := _m.Called(ctx, subaccountId, perpetualId, deltaQuantums) var r0 *big.Rat - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId, uint32, *big.Int) (*big.Rat, error)); ok { - return rf(ctx, subaccountId, perpetualId, deltaQuantums) - } if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId, uint32, *big.Int) *big.Rat); ok { r0 = rf(ctx, subaccountId, perpetualId, deltaQuantums) } else { @@ -204,6 +188,7 @@ func (_m *ClobKeeper) GetFillablePrice(ctx types.Context, subaccountId subaccoun } } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, subaccountstypes.SubaccountId, uint32, *big.Int) error); ok { r1 = rf(ctx, subaccountId, perpetualId, deltaQuantums) } else { @@ -250,10 +235,6 @@ func (_m *ClobKeeper) GetLiquidationInsuranceFundDelta(ctx types.Context, subacc ret := _m.Called(ctx, subaccountId, perpetualId, isBuy, fillAmount, subticks) var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId, uint32, bool, uint64, clobtypes.Subticks) (*big.Int, error)); ok { - return rf(ctx, subaccountId, perpetualId, isBuy, fillAmount, subticks) - } if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId, uint32, bool, uint64, clobtypes.Subticks) *big.Int); ok { r0 = rf(ctx, subaccountId, perpetualId, isBuy, fillAmount, subticks) } else { @@ -262,6 +243,7 @@ func (_m *ClobKeeper) GetLiquidationInsuranceFundDelta(ctx types.Context, subacc } } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, subaccountstypes.SubaccountId, uint32, bool, uint64, clobtypes.Subticks) error); ok { r1 = rf(ctx, subaccountId, perpetualId, isBuy, fillAmount, subticks) } else { @@ -290,16 +272,13 @@ func (_m *ClobKeeper) GetLongTermOrderPlacement(ctx types.Context, orderId clobt ret := _m.Called(ctx, orderId) var r0 clobtypes.LongTermOrderPlacement - var r1 bool - if rf, ok := ret.Get(0).(func(types.Context, clobtypes.OrderId) (clobtypes.LongTermOrderPlacement, bool)); ok { - return rf(ctx, orderId) - } if rf, ok := ret.Get(0).(func(types.Context, clobtypes.OrderId) clobtypes.LongTermOrderPlacement); ok { r0 = rf(ctx, orderId) } else { r0 = ret.Get(0).(clobtypes.LongTermOrderPlacement) } + var r1 bool if rf, ok := ret.Get(1).(func(types.Context, clobtypes.OrderId) bool); ok { r1 = rf(ctx, orderId) } else { @@ -314,11 +293,6 @@ func (_m *ClobKeeper) GetMaxAndMinPositionNotionalLiquidatable(ctx types.Context ret := _m.Called(ctx, positionToLiquidate) var r0 *big.Int - var r1 *big.Int - var r2 error - if rf, ok := ret.Get(0).(func(types.Context, *subaccountstypes.PerpetualPosition) (*big.Int, *big.Int, error)); ok { - return rf(ctx, positionToLiquidate) - } if rf, ok := ret.Get(0).(func(types.Context, *subaccountstypes.PerpetualPosition) *big.Int); ok { r0 = rf(ctx, positionToLiquidate) } else { @@ -327,6 +301,7 @@ func (_m *ClobKeeper) GetMaxAndMinPositionNotionalLiquidatable(ctx types.Context } } + var r1 *big.Int if rf, ok := ret.Get(1).(func(types.Context, *subaccountstypes.PerpetualPosition) *big.Int); ok { r1 = rf(ctx, positionToLiquidate) } else { @@ -335,6 +310,7 @@ func (_m *ClobKeeper) GetMaxAndMinPositionNotionalLiquidatable(ctx types.Context } } + var r2 error if rf, ok := ret.Get(2).(func(types.Context, *subaccountstypes.PerpetualPosition) error); ok { r2 = rf(ctx, positionToLiquidate) } else { @@ -349,17 +325,13 @@ func (_m *ClobKeeper) GetPerpetualPositionToLiquidate(ctx types.Context, subacco ret := _m.Called(ctx, subaccountId) var r0 clobtypes.ClobPair - var r1 *big.Int - var r2 error - if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId) (clobtypes.ClobPair, *big.Int, error)); ok { - return rf(ctx, subaccountId) - } if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId) clobtypes.ClobPair); ok { r0 = rf(ctx, subaccountId) } else { r0 = ret.Get(0).(clobtypes.ClobPair) } + var r1 *big.Int if rf, ok := ret.Get(1).(func(types.Context, subaccountstypes.SubaccountId) *big.Int); ok { r1 = rf(ctx, subaccountId) } else { @@ -368,6 +340,7 @@ func (_m *ClobKeeper) GetPerpetualPositionToLiquidate(ctx types.Context, subacco } } + var r2 error if rf, ok := ret.Get(2).(func(types.Context, subaccountstypes.SubaccountId) error); ok { r2 = rf(ctx, subaccountId) } else { @@ -442,10 +415,6 @@ func (_m *ClobKeeper) GetSubaccountMaxInsuranceLost(ctx types.Context, subaccoun ret := _m.Called(ctx, subaccountId, perpetualId) var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId, uint32) (*big.Int, error)); ok { - return rf(ctx, subaccountId, perpetualId) - } if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId, uint32) *big.Int); ok { r0 = rf(ctx, subaccountId, perpetualId) } else { @@ -454,6 +423,7 @@ func (_m *ClobKeeper) GetSubaccountMaxInsuranceLost(ctx types.Context, subaccoun } } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, subaccountstypes.SubaccountId, uint32) error); ok { r1 = rf(ctx, subaccountId, perpetualId) } else { @@ -468,10 +438,6 @@ func (_m *ClobKeeper) GetSubaccountMaxNotionalLiquidatable(ctx types.Context, su ret := _m.Called(ctx, subaccountId, perpetualId) var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId, uint32) (*big.Int, error)); ok { - return rf(ctx, subaccountId, perpetualId) - } if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId, uint32) *big.Int); ok { r0 = rf(ctx, subaccountId, perpetualId) } else { @@ -480,6 +446,7 @@ func (_m *ClobKeeper) GetSubaccountMaxNotionalLiquidatable(ctx types.Context, su } } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, subaccountstypes.SubaccountId, uint32) error); ok { r1 = rf(ctx, subaccountId, perpetualId) } else { @@ -536,16 +503,13 @@ func (_m *ClobKeeper) IsLiquidatable(ctx types.Context, subaccountId subaccounts ret := _m.Called(ctx, subaccountId) var r0 bool - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId) (bool, error)); ok { - return rf(ctx, subaccountId) - } if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId) bool); ok { r0 = rf(ctx, subaccountId) } else { r0 = ret.Get(0).(bool) } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, subaccountstypes.SubaccountId) error); ok { r1 = rf(ctx, subaccountId) } else { @@ -576,10 +540,6 @@ func (_m *ClobKeeper) MaybeGetLiquidationOrder(ctx types.Context, subaccountId s ret := _m.Called(ctx, subaccountId) var r0 *clobtypes.LiquidationOrder - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId) (*clobtypes.LiquidationOrder, error)); ok { - return rf(ctx, subaccountId) - } if rf, ok := ret.Get(0).(func(types.Context, subaccountstypes.SubaccountId) *clobtypes.LiquidationOrder); ok { r0 = rf(ctx, subaccountId) } else { @@ -588,6 +548,7 @@ func (_m *ClobKeeper) MaybeGetLiquidationOrder(ctx types.Context, subaccountId s } } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, subaccountstypes.SubaccountId) error); ok { r1 = rf(ctx, subaccountId) } else { @@ -650,23 +611,20 @@ func (_m *ClobKeeper) PlacePerpetualLiquidation(ctx types.Context, liquidationOr ret := _m.Called(ctx, liquidationOrder) var r0 subaccountstypes.BaseQuantums - var r1 clobtypes.OrderStatus - var r2 error - if rf, ok := ret.Get(0).(func(types.Context, clobtypes.LiquidationOrder) (subaccountstypes.BaseQuantums, clobtypes.OrderStatus, error)); ok { - return rf(ctx, liquidationOrder) - } if rf, ok := ret.Get(0).(func(types.Context, clobtypes.LiquidationOrder) subaccountstypes.BaseQuantums); ok { r0 = rf(ctx, liquidationOrder) } else { r0 = ret.Get(0).(subaccountstypes.BaseQuantums) } + var r1 clobtypes.OrderStatus if rf, ok := ret.Get(1).(func(types.Context, clobtypes.LiquidationOrder) clobtypes.OrderStatus); ok { r1 = rf(ctx, liquidationOrder) } else { r1 = ret.Get(1).(clobtypes.OrderStatus) } + var r2 error if rf, ok := ret.Get(2).(func(types.Context, clobtypes.LiquidationOrder) error); ok { r2 = rf(ctx, liquidationOrder) } else { @@ -681,23 +639,20 @@ func (_m *ClobKeeper) PlaceShortTermOrder(ctx types.Context, msg *clobtypes.MsgP ret := _m.Called(ctx, msg) var r0 subaccountstypes.BaseQuantums - var r1 clobtypes.OrderStatus - var r2 error - if rf, ok := ret.Get(0).(func(types.Context, *clobtypes.MsgPlaceOrder) (subaccountstypes.BaseQuantums, clobtypes.OrderStatus, error)); ok { - return rf(ctx, msg) - } if rf, ok := ret.Get(0).(func(types.Context, *clobtypes.MsgPlaceOrder) subaccountstypes.BaseQuantums); ok { r0 = rf(ctx, msg) } else { r0 = ret.Get(0).(subaccountstypes.BaseQuantums) } + var r1 clobtypes.OrderStatus if rf, ok := ret.Get(1).(func(types.Context, *clobtypes.MsgPlaceOrder) clobtypes.OrderStatus); ok { r1 = rf(ctx, msg) } else { r1 = ret.Get(1).(clobtypes.OrderStatus) } + var r2 error if rf, ok := ret.Get(2).(func(types.Context, *clobtypes.MsgPlaceOrder) error); ok { r2 = rf(ctx, msg) } else { @@ -740,31 +695,27 @@ func (_m *ClobKeeper) ProcessSingleMatch(ctx types.Context, matchWithOrders *clo ret := _m.Called(ctx, matchWithOrders) var r0 bool - var r1 subaccountstypes.UpdateResult - var r2 subaccountstypes.UpdateResult - var r3 *clobtypes.OffchainUpdates - var r4 error - if rf, ok := ret.Get(0).(func(types.Context, *clobtypes.MatchWithOrders) (bool, subaccountstypes.UpdateResult, subaccountstypes.UpdateResult, *clobtypes.OffchainUpdates, error)); ok { - return rf(ctx, matchWithOrders) - } if rf, ok := ret.Get(0).(func(types.Context, *clobtypes.MatchWithOrders) bool); ok { r0 = rf(ctx, matchWithOrders) } else { r0 = ret.Get(0).(bool) } + var r1 subaccountstypes.UpdateResult if rf, ok := ret.Get(1).(func(types.Context, *clobtypes.MatchWithOrders) subaccountstypes.UpdateResult); ok { r1 = rf(ctx, matchWithOrders) } else { r1 = ret.Get(1).(subaccountstypes.UpdateResult) } + var r2 subaccountstypes.UpdateResult if rf, ok := ret.Get(2).(func(types.Context, *clobtypes.MatchWithOrders) subaccountstypes.UpdateResult); ok { r2 = rf(ctx, matchWithOrders) } else { r2 = ret.Get(2).(subaccountstypes.UpdateResult) } + var r3 *clobtypes.OffchainUpdates if rf, ok := ret.Get(3).(func(types.Context, *clobtypes.MatchWithOrders) *clobtypes.OffchainUpdates); ok { r3 = rf(ctx, matchWithOrders) } else { @@ -773,6 +724,7 @@ func (_m *ClobKeeper) ProcessSingleMatch(ctx types.Context, matchWithOrders *clo } } + var r4 error if rf, ok := ret.Get(4).(func(types.Context, *clobtypes.MatchWithOrders) error); ok { r4 = rf(ctx, matchWithOrders) } else { diff --git a/protocol/mocks/MemClob.go b/protocol/mocks/MemClob.go index 273156693a..17a4c62a44 100644 --- a/protocol/mocks/MemClob.go +++ b/protocol/mocks/MemClob.go @@ -348,6 +348,11 @@ func (_m *MemClob) SetMemclobGauges(ctx types.Context) { _m.Called(ctx) } +// UnsafeResetMemclob provides a mock function with given fields: ctx +func (_m *MemClob) UnsafeResetMemclob(ctx types.Context) { + _m.Called(ctx) +} + type mockConstructorTestingTNewMemClob interface { mock.TestingT Cleanup(func()) diff --git a/protocol/mocks/PerpetualsClobKeeper.go b/protocol/mocks/PerpetualsClobKeeper.go index f3ef9f22cc..8b2f59e4b9 100644 --- a/protocol/mocks/PerpetualsClobKeeper.go +++ b/protocol/mocks/PerpetualsClobKeeper.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package mocks @@ -18,16 +18,13 @@ func (_m *PerpetualsClobKeeper) GetPricePremiumForPerpetual(ctx types.Context, p ret := _m.Called(ctx, perpetualId, params) var r0 int32 - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, uint32, perpetualstypes.GetPricePremiumParams) (int32, error)); ok { - return rf(ctx, perpetualId, params) - } if rf, ok := ret.Get(0).(func(types.Context, uint32, perpetualstypes.GetPricePremiumParams) int32); ok { r0 = rf(ctx, perpetualId, params) } else { r0 = ret.Get(0).(int32) } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, uint32, perpetualstypes.GetPricePremiumParams) error); ok { r1 = rf(ctx, perpetualId, params) } else { @@ -42,16 +39,13 @@ func (_m *PerpetualsClobKeeper) IsPerpetualClobPairActive(ctx types.Context, per ret := _m.Called(ctx, perpetualId) var r0 bool - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, uint32) (bool, error)); ok { - return rf(ctx, perpetualId) - } if rf, ok := ret.Get(0).(func(types.Context, uint32) bool); ok { r0 = rf(ctx, perpetualId) } else { r0 = ret.Get(0).(bool) } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, uint32) error); ok { r1 = rf(ctx, perpetualId) } else { diff --git a/protocol/mocks/PerpetualsKeeper.go b/protocol/mocks/PerpetualsKeeper.go index 6c0536a0b7..8a8cc1f98e 100644 --- a/protocol/mocks/PerpetualsKeeper.go +++ b/protocol/mocks/PerpetualsKeeper.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.26.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package mocks @@ -51,11 +51,6 @@ func (_m *PerpetualsKeeper) GetMarginRequirements(ctx types.Context, id uint32, ret := _m.Called(ctx, id, bigQuantums) var r0 *big.Int - var r1 *big.Int - var r2 error - if rf, ok := ret.Get(0).(func(types.Context, uint32, *big.Int) (*big.Int, *big.Int, error)); ok { - return rf(ctx, id, bigQuantums) - } if rf, ok := ret.Get(0).(func(types.Context, uint32, *big.Int) *big.Int); ok { r0 = rf(ctx, id, bigQuantums) } else { @@ -64,6 +59,7 @@ func (_m *PerpetualsKeeper) GetMarginRequirements(ctx types.Context, id uint32, } } + var r1 *big.Int if rf, ok := ret.Get(1).(func(types.Context, uint32, *big.Int) *big.Int); ok { r1 = rf(ctx, id, bigQuantums) } else { @@ -72,6 +68,7 @@ func (_m *PerpetualsKeeper) GetMarginRequirements(ctx types.Context, id uint32, } } + var r2 error if rf, ok := ret.Get(2).(func(types.Context, uint32, *big.Int) error); ok { r2 = rf(ctx, id, bigQuantums) } else { @@ -86,10 +83,6 @@ func (_m *PerpetualsKeeper) GetNetCollateral(ctx types.Context, id uint32, bigQu ret := _m.Called(ctx, id, bigQuantums) var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, uint32, *big.Int) (*big.Int, error)); ok { - return rf(ctx, id, bigQuantums) - } if rf, ok := ret.Get(0).(func(types.Context, uint32, *big.Int) *big.Int); ok { r0 = rf(ctx, id, bigQuantums) } else { @@ -98,6 +91,7 @@ func (_m *PerpetualsKeeper) GetNetCollateral(ctx types.Context, id uint32, bigQu } } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, uint32, *big.Int) error); ok { r1 = rf(ctx, id, bigQuantums) } else { @@ -112,10 +106,6 @@ func (_m *PerpetualsKeeper) GetNetNotional(ctx types.Context, id uint32, bigQuan ret := _m.Called(ctx, id, bigQuantums) var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, uint32, *big.Int) (*big.Int, error)); ok { - return rf(ctx, id, bigQuantums) - } if rf, ok := ret.Get(0).(func(types.Context, uint32, *big.Int) *big.Int); ok { r0 = rf(ctx, id, bigQuantums) } else { @@ -124,6 +114,7 @@ func (_m *PerpetualsKeeper) GetNetNotional(ctx types.Context, id uint32, bigQuan } } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, uint32, *big.Int) error); ok { r1 = rf(ctx, id, bigQuantums) } else { @@ -138,10 +129,6 @@ func (_m *PerpetualsKeeper) GetNotionalInBaseQuantums(ctx types.Context, id uint ret := _m.Called(ctx, id, bigQuoteQuantums) var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(types.Context, uint32, *big.Int) (*big.Int, error)); ok { - return rf(ctx, id, bigQuoteQuantums) - } if rf, ok := ret.Get(0).(func(types.Context, uint32, *big.Int) *big.Int); ok { r0 = rf(ctx, id, bigQuoteQuantums) } else { @@ -150,6 +137,7 @@ func (_m *PerpetualsKeeper) GetNotionalInBaseQuantums(ctx types.Context, id uint } } + var r1 error if rf, ok := ret.Get(1).(func(types.Context, uint32, *big.Int) error); ok { r1 = rf(ctx, id, bigQuoteQuantums) } else { diff --git a/protocol/x/clob/ante/clob.go b/protocol/x/clob/ante/clob.go index 07656a6aca..d0bb302c48 100644 --- a/protocol/x/clob/ante/clob.go +++ b/protocol/x/clob/ante/clob.go @@ -5,6 +5,7 @@ import ( "github.com/cometbft/cometbft/libs/log" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + v0_2_2 "github.com/dydxprotocol/v4-chain/protocol/app/upgrades/v0.2.2" "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" @@ -58,6 +59,11 @@ func (cd ClobDecorator) AnteHandle( return next(ctx, tx, simulate) } + // Disable trading until after the v0.2.2 upgrade. + if ctx.BlockHeight() <= v0_2_2.UpgradeHeight+int64(types.ShortBlockWindow) { + return ctx, types.ErrTradingDisabled + } + msgs := tx.GetMsgs() var msg = msgs[0] diff --git a/protocol/x/clob/keeper/clob_pair.go b/protocol/x/clob/keeper/clob_pair.go index 0e80fdc478..b0f2ad7a47 100644 --- a/protocol/x/clob/keeper/clob_pair.go +++ b/protocol/x/clob/keeper/clob_pair.go @@ -553,3 +553,26 @@ func (k Keeper) IsPerpetualClobPairActive( return clobPair.Status == types.ClobPair_STATUS_ACTIVE, nil } + +// UnsafeSetClobPair sets a specific `ClobPair` in the store from its index. +func (k Keeper) UnsafeSetClobPair(ctx sdk.Context, clobPair types.ClobPair) { + b := k.cdc.MustMarshal(&clobPair) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ClobPairKeyPrefix)) + // Write the `ClobPair` to state. + store.Set(types.ClobPairKey(clobPair.GetClobPairId()), b) + + // Send UpdateClobPair to indexer. + k.GetIndexerEventManager().AddTxnEvent( + ctx, + indexerevents.SubtypeUpdateClobPair, + indexer_manager.GetB64EncodedEventMessage( + indexerevents.NewUpdateClobPairEvent( + clobPair.Id, + clobPair.Status, + clobPair.QuantumConversionExponent, + clobPair.SubticksPerTick, + clobPair.StepBaseQuantums, + ), + ), + ) +} diff --git a/protocol/x/clob/memclob/memclob.go b/protocol/x/clob/memclob/memclob.go index 139e74b131..1a5bdb8f07 100644 --- a/protocol/x/clob/memclob/memclob.go +++ b/protocol/x/clob/memclob/memclob.go @@ -69,6 +69,14 @@ func (m *MemClobPriceTimePriority) SetClobKeeper(clobKeeper types.MemClobKeeper) m.clobKeeper = clobKeeper } +func (m *MemClobPriceTimePriority) UnsafeResetMemclob( + ctx sdk.Context, +) { + m.openOrders = newMemclobOpenOrders() + m.cancels = newMemclobCancels() + m.operationsToPropose = *types.NewOperationsToPropose() +} + // CancelOrder removes a Short-Term order by `OrderId` (if it exists) from all order-related data structures // in the memclob. This method manages only Short-Term cancellations. For stateful cancellations, see // `msg_server_cancel_orders.go`. diff --git a/protocol/x/clob/types/errors.go b/protocol/x/clob/types/errors.go index c81af92f3b..1bbec50fc6 100644 --- a/protocol/x/clob/types/errors.go +++ b/protocol/x/clob/types/errors.go @@ -452,6 +452,11 @@ var ( 9003, "Reduce-only is currently disabled", ) + ErrTradingDisabled = sdkerrors.Register( + ModuleName, + 9004, + "Trading is currently disabled", + ) // Equity tier limit errors. ErrInvalidEquityTierLimitConfig = sdkerrors.Register( diff --git a/protocol/x/clob/types/memclob.go b/protocol/x/clob/types/memclob.go index a56e4eb5d4..0669748d5a 100644 --- a/protocol/x/clob/types/memclob.go +++ b/protocol/x/clob/types/memclob.go @@ -19,6 +19,9 @@ const StatefulOrderTimeWindow time.Duration = 95 * 24 * time.Hour // 95 days. // MemClob is an interface that encapsulates all reads and writes to the // CLOB's in-memory data structures. type MemClob interface { + UnsafeResetMemclob( + ctx sdk.Context, + ) SetClobKeeper( keeper MemClobKeeper, )