Skip to content

Commit

Permalink
[CT-873] Deprecate FOK orders (#1597)
Browse files Browse the repository at this point in the history
  • Loading branch information
jayy04 authored Jun 11, 2024
1 parent 8f0d3bc commit 43f055f
Show file tree
Hide file tree
Showing 32 changed files with 338 additions and 2,102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,8 @@ export enum Order_TimeInForce {
TIME_IN_FORCE_POST_ONLY = 2,

/**
* TIME_IN_FORCE_FILL_OR_KILL - TIME_IN_FORCE_FILL_OR_KILL enforces that an order will either be filled
* completely and immediately by maker orders on the book or canceled if the
* entire amount can‘t be matched.
* TIME_IN_FORCE_FILL_OR_KILL - TIME_IN_FORCE_FILL_OR_KILL has been deprecated and will be removed in
* future versions.
*/
TIME_IN_FORCE_FILL_OR_KILL = 3,
UNRECOGNIZED = -1,
Expand Down Expand Up @@ -138,9 +137,8 @@ export enum Order_TimeInForceSDKType {
TIME_IN_FORCE_POST_ONLY = 2,

/**
* TIME_IN_FORCE_FILL_OR_KILL - TIME_IN_FORCE_FILL_OR_KILL enforces that an order will either be filled
* completely and immediately by maker orders on the book or canceled if the
* entire amount can‘t be matched.
* TIME_IN_FORCE_FILL_OR_KILL - TIME_IN_FORCE_FILL_OR_KILL has been deprecated and will be removed in
* future versions.
*/
TIME_IN_FORCE_FILL_OR_KILL = 3,
UNRECOGNIZED = -1,
Expand Down
7 changes: 3 additions & 4 deletions proto/dydxprotocol/clob/order.proto
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,9 @@ message Order {
// any newly-placed post only orders that would cross with other maker
// orders.
TIME_IN_FORCE_POST_ONLY = 2;
// TIME_IN_FORCE_FILL_OR_KILL enforces that an order will either be filled
// completely and immediately by maker orders on the book or canceled if the
// entire amount can‘t be matched.
TIME_IN_FORCE_FILL_OR_KILL = 3;
// TIME_IN_FORCE_FILL_OR_KILL has been deprecated and will be removed in
// future versions.
TIME_IN_FORCE_FILL_OR_KILL = 3 [ deprecated = true ];
}

// The time in force of this order.
Expand Down
42 changes: 40 additions & 2 deletions protocol/app/upgrades/v6.0.0/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,57 @@ package v_6_0_0

import (
"context"

clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types"
"fmt"

upgradetypes "cosmossdk.io/x/upgrade/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
indexerevents "github.com/dydxprotocol/v4-chain/protocol/indexer/events"
"github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager"
indexershared "github.com/dydxprotocol/v4-chain/protocol/indexer/shared"
"github.com/dydxprotocol/v4-chain/protocol/lib"
clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types"
)

func removeStatefulFOKOrders(ctx sdk.Context, k clobtypes.ClobKeeper) {
allStatefulOrders := k.GetAllStatefulOrders(ctx)
for _, order := range allStatefulOrders {
if order.TimeInForce == clobtypes.Order_TIME_IN_FORCE_FILL_OR_KILL {
// Remove the orders from state.
k.MustRemoveStatefulOrder(ctx, order.OrderId)

// Send indexer event for removal of stateful order.
k.GetIndexerEventManager().AddTxnEvent(
ctx,
indexerevents.SubtypeStatefulOrder,
indexerevents.StatefulOrderEventVersion,
indexer_manager.GetBytes(
indexerevents.NewStatefulOrderRemovalEvent(
order.OrderId,
indexershared.ConvertOrderRemovalReasonToIndexerOrderRemovalReason(
clobtypes.OrderRemoval_REMOVAL_REASON_CONDITIONAL_FOK_COULD_NOT_BE_FULLY_FILLED,
),
),
),
)
}
}
}

func CreateUpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
clobKeeper clobtypes.ClobKeeper,
) upgradetypes.UpgradeHandler {
return func(ctx context.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
sdkCtx := lib.UnwrapSDKContext(ctx, "app/upgrades")
sdkCtx.Logger().Info(fmt.Sprintf("Running %s Upgrade...", UpgradeName))

// Remove all stateful FOK orders from state.
removeStatefulFOKOrders(sdkCtx, clobKeeper)

sdkCtx.Logger().Info("Successfully removed stateful orders from state")

return mm.RunMigrations(ctx, configurator, vm)
}
}
191 changes: 99 additions & 92 deletions protocol/app/upgrades/v6.0.0/upgrade_container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ package v_6_0_0_test

import (
"testing"
"time"

v_6_0_0 "github.com/dydxprotocol/v4-chain/protocol/app/upgrades/v6.0.0"
"github.com/dydxprotocol/v4-chain/protocol/testing/containertest"
"github.com/dydxprotocol/v4-chain/protocol/testutil/constants"
clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types"
satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

const (
AliceBobBTCQuantums = 1_000_000
CarlDaveBTCQuantums = 2_000_000
CarlDaveETHQuantums = 4_000_000
)

func TestStateUpgrade(t *testing.T) {
Expand All @@ -43,145 +44,151 @@ func preUpgradeSetups(node *containertest.Node, t *testing.T) {

func preUpgradeChecks(node *containertest.Node, t *testing.T) {
// Add test for your upgrade handler logic below
preUpgradeStatefulOrderCheck(node, t)
}

func postUpgradeChecks(node *containertest.Node, t *testing.T) {
// Add test for your upgrade handler logic below
postUpgradeStatefulOrderCheck(node, t)
}

func placeOrders(node *containertest.Node, t *testing.T) {
require.NoError(t, containertest.BroadcastTx(
// FOK order setups.
require.NoError(t, containertest.BroadcastTxWithoutValidateBasic(
node,
&clobtypes.MsgPlaceOrder{
Order: clobtypes.Order{
OrderId: clobtypes.OrderId{
ClientId: 0,
ClientId: 100,
SubaccountId: satypes.SubaccountId{
Owner: constants.AliceAccAddress.String(),
Number: 0,
},
ClobPairId: 0,
OrderFlags: clobtypes.OrderIdFlags_Conditional,
},
Side: clobtypes.Order_SIDE_BUY,
Quantums: AliceBobBTCQuantums,
Subticks: 5_000_000,
GoodTilOneof: &clobtypes.Order_GoodTilBlock{
GoodTilBlock: 20,
Side: clobtypes.Order_SIDE_BUY,
Quantums: AliceBobBTCQuantums,
Subticks: 6_000_000,
TimeInForce: clobtypes.Order_TIME_IN_FORCE_FILL_OR_KILL,
ConditionType: clobtypes.Order_CONDITION_TYPE_TAKE_PROFIT,
ConditionalOrderTriggerSubticks: 6_000_000,
GoodTilOneof: &clobtypes.Order_GoodTilBlockTime{
GoodTilBlockTime: uint32(time.Now().Unix() + 300),
},
},
},
constants.AliceAccAddress.String(),
))
require.NoError(t, containertest.BroadcastTx(

err := node.Wait(1)
require.NoError(t, err)

require.NoError(t, containertest.BroadcastTxWithoutValidateBasic(
node,
&clobtypes.MsgPlaceOrder{
Order: clobtypes.Order{
OrderId: clobtypes.OrderId{
ClientId: 0,
ClientId: 101,
SubaccountId: satypes.SubaccountId{
Owner: constants.BobAccAddress.String(),
Owner: constants.AliceAccAddress.String(),
Number: 0,
},
ClobPairId: 0,
OrderFlags: clobtypes.OrderIdFlags_Conditional,
},
Side: clobtypes.Order_SIDE_SELL,
Quantums: AliceBobBTCQuantums,
Subticks: 5_000_000,
GoodTilOneof: &clobtypes.Order_GoodTilBlock{
GoodTilBlock: 20,
Side: clobtypes.Order_SIDE_SELL,
Quantums: AliceBobBTCQuantums,
Subticks: 6_000_000,
TimeInForce: clobtypes.Order_TIME_IN_FORCE_FILL_OR_KILL,
ConditionType: clobtypes.Order_CONDITION_TYPE_STOP_LOSS,
ConditionalOrderTriggerSubticks: 6_000_000,
GoodTilOneof: &clobtypes.Order_GoodTilBlockTime{
GoodTilBlockTime: uint32(time.Now().Unix() + 300),
},
},
},
constants.BobAccAddress.String(),
constants.AliceAccAddress.String(),
))
require.NoError(t, containertest.BroadcastTx(

err = node.Wait(2)
require.NoError(t, err)
}

func preUpgradeStatefulOrderCheck(node *containertest.Node, t *testing.T) {
// Check that all stateful orders are present.
_, err := containertest.Query(
node,
&clobtypes.MsgPlaceOrder{
Order: clobtypes.Order{
OrderId: clobtypes.OrderId{
ClientId: 0,
SubaccountId: satypes.SubaccountId{
Owner: constants.CarlAccAddress.String(),
Number: 0,
},
ClobPairId: 0,
},
Side: clobtypes.Order_SIDE_BUY,
Quantums: CarlDaveBTCQuantums,
Subticks: 5_000_000,
GoodTilOneof: &clobtypes.Order_GoodTilBlock{
GoodTilBlock: 20,
clobtypes.NewQueryClient,
clobtypes.QueryClient.StatefulOrder,
&clobtypes.QueryStatefulOrderRequest{
OrderId: clobtypes.OrderId{
ClientId: 100,
SubaccountId: satypes.SubaccountId{
Owner: constants.AliceAccAddress.String(),
Number: 0,
},
ClobPairId: 0,
OrderFlags: clobtypes.OrderIdFlags_Conditional,
},
},
constants.CarlAccAddress.String(),
))
require.NoError(t, containertest.BroadcastTx(
)
require.NoError(t, err)

_, err = containertest.Query(
node,
&clobtypes.MsgPlaceOrder{
Order: clobtypes.Order{
OrderId: clobtypes.OrderId{
ClientId: 0,
SubaccountId: satypes.SubaccountId{
Owner: constants.DaveAccAddress.String(),
Number: 0,
},
ClobPairId: 0,
},
Side: clobtypes.Order_SIDE_SELL,
Quantums: CarlDaveBTCQuantums,
Subticks: 5_000_000,
GoodTilOneof: &clobtypes.Order_GoodTilBlock{
GoodTilBlock: 20,
clobtypes.NewQueryClient,
clobtypes.QueryClient.StatefulOrder,
&clobtypes.QueryStatefulOrderRequest{
OrderId: clobtypes.OrderId{
ClientId: 101,
SubaccountId: satypes.SubaccountId{
Owner: constants.AliceAccAddress.String(),
Number: 0,
},
ClobPairId: 0,
OrderFlags: clobtypes.OrderIdFlags_Conditional,
},
},
constants.DaveAccAddress.String(),
))
require.NoError(t, containertest.BroadcastTx(
)
require.NoError(t, err)
}

func postUpgradeStatefulOrderCheck(node *containertest.Node, t *testing.T) {
// Check that all stateful orders are removed.
_, err := containertest.Query(
node,
&clobtypes.MsgPlaceOrder{
Order: clobtypes.Order{
OrderId: clobtypes.OrderId{
ClientId: 0,
SubaccountId: satypes.SubaccountId{
Owner: constants.CarlAccAddress.String(),
Number: 0,
},
ClobPairId: 1,
},
Side: clobtypes.Order_SIDE_BUY,
Quantums: CarlDaveETHQuantums,
Subticks: 5_000_000,
GoodTilOneof: &clobtypes.Order_GoodTilBlock{
GoodTilBlock: 20,
clobtypes.NewQueryClient,
clobtypes.QueryClient.StatefulOrder,
&clobtypes.QueryStatefulOrderRequest{
OrderId: clobtypes.OrderId{
ClientId: 100,
SubaccountId: satypes.SubaccountId{
Owner: constants.AliceAccAddress.String(),
Number: 0,
},
ClobPairId: 0,
OrderFlags: clobtypes.OrderIdFlags_Conditional,
},
},
constants.CarlAccAddress.String(),
))
require.NoError(t, containertest.BroadcastTx(
)
require.ErrorIs(t, err, status.Error(codes.NotFound, "not found"))

_, err = containertest.Query(
node,
&clobtypes.MsgPlaceOrder{
Order: clobtypes.Order{
OrderId: clobtypes.OrderId{
ClientId: 0,
SubaccountId: satypes.SubaccountId{
Owner: constants.DaveAccAddress.String(),
Number: 0,
},
ClobPairId: 1,
},
Side: clobtypes.Order_SIDE_SELL,
Quantums: CarlDaveETHQuantums,
Subticks: 5_000_000,
GoodTilOneof: &clobtypes.Order_GoodTilBlock{
GoodTilBlock: 20,
clobtypes.NewQueryClient,
clobtypes.QueryClient.StatefulOrder,
&clobtypes.QueryStatefulOrderRequest{
OrderId: clobtypes.OrderId{
ClientId: 101,
SubaccountId: satypes.SubaccountId{
Owner: constants.AliceAccAddress.String(),
Number: 0,
},
ClobPairId: 0,
OrderFlags: clobtypes.OrderIdFlags_Conditional,
},
},
constants.DaveAccAddress.String(),
))
err := node.Wait(2)
require.NoError(t, err)
)
require.ErrorIs(t, err, status.Error(codes.NotFound, "not found"))
}
20 changes: 20 additions & 0 deletions protocol/mocks/ClobKeeper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion protocol/testing/containertest/containertest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ set -eo pipefail
source "./genesis.sh"

CHAIN_ID="localdydxprotocol"
PREUPGRADE_VERSION="v5.0.0"
PREUPGRADE_VERSION="v5.0.2"

# Define mnemonics for all validators.
MNEMONICS=(
Expand Down
Loading

0 comments on commit 43f055f

Please sign in to comment.