Skip to content

Commit

Permalink
[feat][protocol] halt withdrawals if chain outage seen within the las…
Browse files Browse the repository at this point in the history
…t 5 minutes
  • Loading branch information
lucas-dydx committed Jan 11, 2024
1 parent 2bfcb31 commit 02d5053
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 6 deletions.
1 change: 1 addition & 0 deletions proto/dydxprotocol/blocktime/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ service Query {
// Queries all recorded downtime info.
rpc AllDowntimeInfo(QueryAllDowntimeInfoRequest)
returns (QueryAllDowntimeInfoResponse);
option (google.api.http).get = "/dydxprotocol/v4/blocktime/all_downtime_info";
}

// QueryDowntimeParamsRequest is a request type for the DowntimeParams
Expand Down
1 change: 1 addition & 0 deletions protocol/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,7 @@ func New(
app.AssetsKeeper,
app.BankKeeper,
app.PerpetualsKeeper,
app.BlockTimeKeeper,
app.IndexerEventManager,
)
subaccountsModule := subaccountsmodule.NewAppModule(
Expand Down
1 change: 1 addition & 0 deletions protocol/lib/metrics/metric_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const (
LiquidationsLiquidationMatchNegativeTNC = "liquidations_liquidation_match_negative_tnc"
ClobMevErrorCount = "clob_mev_error_count"
SubaccountsNegativeTncSubaccountSeen = "negative_tnc_subaccount_seen"
SubaccountsChainOutageSeen = "chain_outage_seen"

// Gauges
InsuranceFundBalance = "insurance_fund_balance"
Expand Down
6 changes: 5 additions & 1 deletion protocol/testutil/keeper/subaccounts.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package keeper

import (
dbm "github.com/cosmos/cosmos-db"
"math/big"
"testing"

dbm "github.com/cosmos/cosmos-db"

"github.com/dydxprotocol/v4-chain/protocol/testutil/constants"

"github.com/dydxprotocol/v4-chain/protocol/indexer/common"
Expand All @@ -21,6 +22,7 @@ import (
"github.com/dydxprotocol/v4-chain/protocol/dtypes"
asskeeper "github.com/dydxprotocol/v4-chain/protocol/x/assets/keeper"
assettypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types"
blocktimekeeper "github.com/dydxprotocol/v4-chain/protocol/x/blocktime/keeper"
perpskeeper "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals/keeper"
priceskeeper "github.com/dydxprotocol/v4-chain/protocol/x/prices/keeper"
"github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/keeper"
Expand Down Expand Up @@ -84,6 +86,7 @@ func createSubaccountsKeeper(
ak *asskeeper.Keeper,
bk types.BankKeeper,
pk *perpskeeper.Keeper,
btk *blocktimekeeper.Keeper,
transientStoreKey storetypes.StoreKey,
msgSenderEnabled bool,
) (*keeper.Keeper, storetypes.StoreKey) {
Expand All @@ -101,6 +104,7 @@ func createSubaccountsKeeper(
ak,
bk,
pk,
btk,
mockIndexerEventsManager,
)

Expand Down
2 changes: 2 additions & 0 deletions protocol/x/subaccounts/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type (
assetsKeeper types.AssetsKeeper
bankKeeper types.BankKeeper
perpetualsKeeper types.PerpetualsKeeper
blocktimeKeeper types.BlocktimeKeeper
indexerEventManager indexer_manager.IndexerEventManager
}
)
Expand All @@ -28,6 +29,7 @@ func NewKeeper(
assetsKeeper types.AssetsKeeper,
bankKeeper types.BankKeeper,
perpetualsKeeper types.PerpetualsKeeper,
blocktimeKeeper types.BlocktimeKeeper,
indexerEventManager indexer_manager.IndexerEventManager,
) *Keeper {
return &Keeper{
Expand Down
33 changes: 28 additions & 5 deletions protocol/x/subaccounts/keeper/subaccount.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package keeper

import (
storetypes "cosmossdk.io/store/types"
"errors"
"fmt"
"math/big"
"math/rand"
"time"

storetypes "cosmossdk.io/store/types"

errorsmod "cosmossdk.io/errors"
"cosmossdk.io/store/prefix"
"github.com/cosmos/cosmos-sdk/telemetry"
Expand Down Expand Up @@ -483,8 +484,10 @@ func (k Keeper) internalCanUpdateSubaccounts(
success = true
successPerUpdate = make([]types.UpdateResult, len(settledUpdates))

// Block all withdrawals and transfers if there was a negative TNC subaccount seen within the
// last `WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS`.
// Block all withdrawals and transfers if either of the following is true within the last
// `WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS`:
// - There was a negative TNC subaccount seen.
// - There was a chain outage that lasted at least five minutes.
if updateType == types.Withdrawal || updateType == types.Transfer {
lastBlockNegativeTncSubaccountSeen, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx)
currentBlock := uint32(ctx.BlockHeight())
Expand All @@ -501,8 +504,26 @@ func (k Keeper) internalCanUpdateSubaccounts(
)
}

if exists && currentBlock-lastBlockNegativeTncSubaccountSeen <
types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS {
// Panic if the current block is less than the last block a chain outage was seen.
downtimeInfo := k.blocktimeKeeper.GetDowntimeInfoFor(ctx, 5*time.Minute)
if currentBlock < downtimeInfo.BlockInfo.Height {
panic(
fmt.Sprintf(
"internalCanUpdateSubaccounts: current block (%d) is less than the last "+
"block a chain outage was seen (%d)",
currentBlock,
downtimeInfo.BlockInfo.Height,
),
)
}

negativeTncSubaccountSeen := exists && currentBlock-lastBlockNegativeTncSubaccountSeen <
types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS
// TODO: update this to check for existence.
chainOutageSeen := currentBlock-downtimeInfo.BlockInfo.Height <
types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS

if negativeTncSubaccountSeen || chainOutageSeen {
success = false
for i := range settledUpdates {
successPerUpdate[i] = types.WithdrawalsAndTransfersBlocked
Expand All @@ -511,6 +532,8 @@ func (k Keeper) internalCanUpdateSubaccounts(
metrics.SubaccountWithdrawalsAndTransfersBlocked,
1,
metrics.GetLabelForStringValue(metrics.UpdateType, updateType.String()),
metrics.GetLabelForBoolValue(metrics.SubaccountsNegativeTncSubaccountSeen, negativeTncSubaccountSeen),
metrics.GetLabelForBoolValue(metrics.SubaccountsChainOutageSeen, chainOutageSeen),
)
return success, successPerUpdate, nil
}
Expand Down
6 changes: 6 additions & 0 deletions protocol/x/subaccounts/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package types
import (
"context"
"math/big"
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
blocktimetypes "github.com/dydxprotocol/v4-chain/protocol/x/blocktime/types"
perptypes "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals/types"
)

Expand Down Expand Up @@ -87,3 +89,7 @@ type BankKeeper interface {
) error
SendCoinsFromModuleToModule(ctx context.Context, senderModule, recipientModule string, amt sdk.Coins) error
}

type BlocktimeKeeper interface {
GetDowntimeInfoFor(ctx sdk.Context, duration time.Duration) blocktimetypes.AllDowntimeInfo_DowntimeInfo
}

0 comments on commit 02d5053

Please sign in to comment.