From b1ea4c5609be8d06933fb86d2b9137090e888ed2 Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Wed, 20 Mar 2024 00:28:36 -0600 Subject: [PATCH 01/16] [TRA-125] Update withdrawal gating to be per collateral pool. --- protocol/x/clob/keeper/process_operations.go | 2 +- .../x/clob/keeper/process_operations_test.go | 2 +- protocol/x/clob/types/expected_keepers.go | 1 + ...y_withdrawal_and_transfers_blocked_info.go | 2 +- ...hdrawal_and_transfers_blocked_info_test.go | 8 ++-- .../keeper/negative_tnc_subaccount.go | 18 ++++--- .../keeper/negative_tnc_subaccount_test.go | 48 +++++++++---------- protocol/x/subaccounts/keeper/subaccount.go | 2 +- .../x/subaccounts/keeper/subaccount_test.go | 2 +- protocol/x/subaccounts/types/keys.go | 6 +-- 10 files changed, 48 insertions(+), 43 deletions(-) diff --git a/protocol/x/clob/keeper/process_operations.go b/protocol/x/clob/keeper/process_operations.go index 1d0445a7c9..719c368036 100644 --- a/protocol/x/clob/keeper/process_operations.go +++ b/protocol/x/clob/keeper/process_operations.go @@ -694,7 +694,7 @@ func (k Keeper) PersistMatchDeleveragingToState( metrics.GetLabelForBoolValue(metrics.IsLong, position.GetIsLong()), metrics.GetLabelForBoolValue(metrics.DeliverTx, true), ) - k.subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, lib.MustConvertIntegerToUint32(ctx.BlockHeight())) + k.subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, satypes.ModuleAddress, lib.MustConvertIntegerToUint32(ctx.BlockHeight())) return nil } diff --git a/protocol/x/clob/keeper/process_operations_test.go b/protocol/x/clob/keeper/process_operations_test.go index df6af12351..9d06915973 100644 --- a/protocol/x/clob/keeper/process_operations_test.go +++ b/protocol/x/clob/keeper/process_operations_test.go @@ -2397,7 +2397,7 @@ func runProcessProposerOperationsTestCase( } // Verify the negative TNC subaccount seen block. - seenNegativeTncSubaccountBlock, exists := ks.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock(ctx) + seenNegativeTncSubaccountBlock, exists := ks.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock(ctx, satypes.ModuleAddress) if tc.expectedNegativeTncSubaccountSeen { require.True(t, exists) require.Equal(t, uint32(ctx.BlockHeight()), seenNegativeTncSubaccountBlock) diff --git a/protocol/x/clob/types/expected_keepers.go b/protocol/x/clob/types/expected_keepers.go index 3c4c8b86a2..2ff76a44bc 100644 --- a/protocol/x/clob/types/expected_keepers.go +++ b/protocol/x/clob/types/expected_keepers.go @@ -61,6 +61,7 @@ type SubaccountsKeeper interface { ) SetNegativeTncSubaccountSeenAtBlock( ctx sdk.Context, + collateralPoolAddr sdk.AccAddress, blockHeight uint32, ) TransferFeesToFeeCollectorModule(ctx sdk.Context, assetId uint32, amount *big.Int, perpetualId uint32) error diff --git a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go index eb0931e75b..e0530ca187 100644 --- a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go +++ b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go @@ -25,7 +25,7 @@ func (k Keeper) GetWithdrawalAndTransfersBlockedInfo( ) chainOutageSeenAtBlock, chainOutageExists := downtimeInfo.BlockInfo.Height, downtimeInfo.BlockInfo.Height > 0 && downtimeInfo.Duration > 0 - negativeTncSubaccountSeenAtBlock, negativeTncSubaccountSeenAtBlockExists := k.GetNegativeTncSubaccountSeenAtBlock(ctx) + negativeTncSubaccountSeenAtBlock, negativeTncSubaccountSeenAtBlockExists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) // Withdrawals and transfers are blocked at non-zero block iff a chain outage or negative TNC subaccount exists. withdrawalsAndTransfersBlockedUntilBlock := uint32(0) diff --git a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go index 735eefcaa0..5757ac8384 100644 --- a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go +++ b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go @@ -48,7 +48,7 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { `Negative TNC subaccount seen in state returns withdrawals and transfers unblocked after the delay`: { setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock(ctx, 7) + sk.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 7) }, request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{}, @@ -96,7 +96,7 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { `Negative TNC subaccount and chain outage seen in state returns withdrawals and transfers unblocked after the max block number + delay (negative TNC subaccount block greater)`: { setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock(ctx, 27) + sk.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 27) bk.SetAllDowntimeInfo( ctx, &blocktimetypes.AllDowntimeInfo{ @@ -131,7 +131,7 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { `Negative TNC subaccount and chain outage seen in state returns withdrawals and transfers unblocked after the max block number + delay (chain outage block greater)`: { setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock(ctx, 37) + sk.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 37) bk.SetAllDowntimeInfo( ctx, &blocktimetypes.AllDowntimeInfo{ @@ -166,7 +166,7 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { `Negative TNC subaccount and chain outage seen in state returns withdrawals and transfers unblocked after the max block number + delay (both blocks equal)`: { setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock(ctx, 3) + sk.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 3) bk.SetAllDowntimeInfo( ctx, &blocktimetypes.AllDowntimeInfo{ diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go index 7f52c54f91..0e72c348be 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go @@ -3,6 +3,7 @@ package keeper import ( "fmt" + "cosmossdk.io/store/prefix" storetypes "cosmossdk.io/store/types" sdk "github.com/cosmos/cosmos-sdk/types" gogotypes "github.com/cosmos/gogoproto/types" @@ -13,18 +14,20 @@ import ( // seen in state and a boolean for whether it exists in state. func (k Keeper) GetNegativeTncSubaccountSeenAtBlock( ctx sdk.Context, + collateralPoolAddr sdk.AccAddress, ) (uint32, bool) { - store := ctx.KVStore(k.storeKey) - return k.getNegativeTncSubaccountSeenAtBlock(store) + store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix)) + return k.getNegativeTncSubaccountSeenAtBlock(store, collateralPoolAddr) } // getNegativeTncSubaccountSeenAtBlock is a helper function that takes a store and returns the last // block height a negative TNC subaccount was seen in state and a boolean for whether it exists in state. func (k Keeper) getNegativeTncSubaccountSeenAtBlock( store storetypes.KVStore, + collateralPoolAddr sdk.AccAddress, ) (uint32, bool) { b := store.Get( - []byte(types.NegativeTncSubaccountSeenAtBlockKey), + collateralPoolAddr, ) blockHeight := gogotypes.UInt32Value{Value: 0} exists := false @@ -37,16 +40,17 @@ func (k Keeper) getNegativeTncSubaccountSeenAtBlock( } // SetNegativeTncSubaccountSeenAtBlock sets a block number in state where a negative TNC subaccount -// was seen. This function will overwrite previous values at this key. +// was seen for a specific collateral pool. This function will overwrite previous values at this key. // This function will panic if the old block height is greater than the new block height. func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( ctx sdk.Context, + collateralPoolAddr sdk.AccAddress, blockHeight uint32, ) { - store := ctx.KVStore(k.storeKey) + store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix)) // Panic if the stored block height value exists and is greater than the new block height value. - currentValue, exists := k.getNegativeTncSubaccountSeenAtBlock(store) + currentValue, exists := k.getNegativeTncSubaccountSeenAtBlock(store, collateralPoolAddr) if exists && blockHeight < currentValue { panic( fmt.Sprintf( @@ -59,7 +63,7 @@ func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( blockHeightValue := gogotypes.UInt32Value{Value: blockHeight} store.Set( - []byte(types.NegativeTncSubaccountSeenAtBlockKey), + []byte(collateralPoolAddr), k.cdc.MustMarshal(&blockHeightValue), ) } diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go index 39ffcbb440..520821793e 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go @@ -21,7 +21,7 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }{ "Block height defaults to zero if not set and doesn't exist": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx) + block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) require.False(t, exists) require.Equal( t, @@ -34,8 +34,8 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, "Block height can be updated": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, 1) - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 1) + block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) require.True(t, exists) require.Equal( t, @@ -45,13 +45,13 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, expectedMultiStoreWrites: []string{ - types.NegativeTncSubaccountSeenAtBlockKey, + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, }, }, "Block height can be updated more than once": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, 1) - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 1) + block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) require.True(t, exists) require.Equal( t, @@ -59,8 +59,8 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, 2) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 2) + block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) require.True(t, exists) require.Equal( t, @@ -68,8 +68,8 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, 3) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 3) + block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) require.True(t, exists) require.Equal( t, @@ -77,8 +77,8 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, 10) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 10) + block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) require.True(t, exists) require.Equal( t, @@ -88,16 +88,16 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, expectedMultiStoreWrites: []string{ - types.NegativeTncSubaccountSeenAtBlockKey, - types.NegativeTncSubaccountSeenAtBlockKey, - types.NegativeTncSubaccountSeenAtBlockKey, - types.NegativeTncSubaccountSeenAtBlockKey, + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, }, }, "Block height can be updated to same block height": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, 0) - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 0) + block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) require.True(t, exists) require.Equal( t, @@ -105,8 +105,8 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, 0) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 0) + block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) require.True(t, exists) require.Equal( t, @@ -116,8 +116,8 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, expectedMultiStoreWrites: []string{ - types.NegativeTncSubaccountSeenAtBlockKey, - types.NegativeTncSubaccountSeenAtBlockKey, + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, }, }, } @@ -146,10 +146,10 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock_PanicsOnDecreasingBlock(t *testi // Setup keeper state and test parameters. ctx, subaccountsKeeper, _, _, _, _, _, _, _ := keepertest.SubaccountsKeepers(t, true) - subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, 2) + subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 2) require.PanicsWithValue( t, "SetNegativeTncSubaccountSeenAtBlock: new block height (1) is less than the current block height (2)", - func() { subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, 1) }, + func() { subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 1) }, ) } diff --git a/protocol/x/subaccounts/keeper/subaccount.go b/protocol/x/subaccounts/keeper/subaccount.go index ca9e978e80..98cccb034c 100644 --- a/protocol/x/subaccounts/keeper/subaccount.go +++ b/protocol/x/subaccounts/keeper/subaccount.go @@ -556,7 +556,7 @@ func (k Keeper) internalCanUpdateSubaccounts( // - 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, negativeTncSubaccountExists := k.GetNegativeTncSubaccountSeenAtBlock(ctx) + lastBlockNegativeTncSubaccountSeen, negativeTncSubaccountExists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) currentBlock := uint32(ctx.BlockHeight()) // Panic if the current block is less than the last block a negative TNC subaccount was seen. diff --git a/protocol/x/subaccounts/keeper/subaccount_test.go b/protocol/x/subaccounts/keeper/subaccount_test.go index 699ff4ce44..b05dd0e4d8 100644 --- a/protocol/x/subaccounts/keeper/subaccount_test.go +++ b/protocol/x/subaccounts/keeper/subaccount_test.go @@ -3085,7 +3085,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { // Set the negative TNC subaccount seen at block in state if it's greater than 0. if tc.negativeTncSubaccountSeenAtBlock != 0 { - keeper.SetNegativeTncSubaccountSeenAtBlock(ctx, tc.negativeTncSubaccountSeenAtBlock) + keeper.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, tc.negativeTncSubaccountSeenAtBlock) } // Set the current block number on the context. diff --git a/protocol/x/subaccounts/types/keys.go b/protocol/x/subaccounts/types/keys.go index 6843297789..f09a752c39 100644 --- a/protocol/x/subaccounts/types/keys.go +++ b/protocol/x/subaccounts/types/keys.go @@ -13,7 +13,7 @@ const ( const ( // SubaccountKeyPrefix is the prefix to retrieve all Subaccounts SubaccountKeyPrefix = "SA:" - // NegativeTncSubaccountSeenAtBlockKey is the store key that stores the last - // block a negative TNC subaccount was seen in state. - NegativeTncSubaccountSeenAtBlockKey = "NegSA:" + // NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix is the prefix for the store key that + // stores the last block a negative TNC subaccount was seen in state for a specific collateral pool. + NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix = "NegSA:" ) From c534fafbf1d63494fefbc36cc2f2de6c64c7480e Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Wed, 20 Mar 2024 02:08:36 -0600 Subject: [PATCH 02/16] Fix E2E test. --- protocol/x/clob/e2e/withdrawal_gating_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/x/clob/e2e/withdrawal_gating_test.go b/protocol/x/clob/e2e/withdrawal_gating_test.go index 7e5d34cce3..176d7a79d2 100644 --- a/protocol/x/clob/e2e/withdrawal_gating_test.go +++ b/protocol/x/clob/e2e/withdrawal_gating_test.go @@ -252,7 +252,7 @@ func TestWithdrawalGating_NegativeTncSubaccount_BlocksThenUnblocks(t *testing.T) tApp.App.SubaccountsKeeper.GetSubaccount(ctx, *expectedSubaccount.Id), ) } - negativeTncSubaccountSeenAtBlock, exists := tApp.App.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock(ctx) + negativeTncSubaccountSeenAtBlock, exists := tApp.App.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock(ctx, satypes.ModuleAddress) require.Equal(t, tc.expectedWithdrawalsGated, exists) require.Equal(t, tc.expectedNegativeTncSubaccountSeenAtBlock, negativeTncSubaccountSeenAtBlock) From 1761f76e9d8f9a556cc1a22f994cc55a0a82714a Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Wed, 20 Mar 2024 08:50:28 -0600 Subject: [PATCH 03/16] Update tests. --- proto/dydxprotocol/subaccounts/query.proto | 7 +- protocol/testutil/constants/addresses.go | 6 + ...y_withdrawal_and_transfers_blocked_info.go | 7 +- ...hdrawal_and_transfers_blocked_info_test.go | 42 +++- .../keeper/negative_tnc_subaccount.go | 7 +- .../keeper/negative_tnc_subaccount_test.go | 213 +++++++++++------- protocol/x/subaccounts/keeper/subaccount.go | 61 ++++- .../x/subaccounts/keeper/subaccount_test.go | 111 +++++---- protocol/x/subaccounts/types/query.pb.go | 142 ++++++++---- protocol/x/subaccounts/types/query.pb.gw.go | 18 ++ 10 files changed, 440 insertions(+), 174 deletions(-) diff --git a/proto/dydxprotocol/subaccounts/query.proto b/proto/dydxprotocol/subaccounts/query.proto index 740d50977a..9b1d2c789a 100644 --- a/proto/dydxprotocol/subaccounts/query.proto +++ b/proto/dydxprotocol/subaccounts/query.proto @@ -56,8 +56,11 @@ message QuerySubaccountAllResponse { } // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a request type for -// fetching information about whether withdrawals and transfers are blocked. -message QueryGetWithdrawalAndTransfersBlockedInfoRequest {} +// fetching information about whether withdrawals and transfers are blocked for a specific +// collateral pool. +message QueryGetWithdrawalAndTransfersBlockedInfoRequest { + string collateral_pool_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; +} // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a response type for // fetching information about whether withdrawals and transfers are blocked. diff --git a/protocol/testutil/constants/addresses.go b/protocol/testutil/constants/addresses.go index d4987bad8a..259a548a3e 100644 --- a/protocol/testutil/constants/addresses.go +++ b/protocol/testutil/constants/addresses.go @@ -2,6 +2,8 @@ package constants import ( sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" ) var ( @@ -17,4 +19,8 @@ var ( BobConsAddress = sdk.ConsAddress(BobPrivateKey.PubKey().Address()) CarlConsAddress = sdk.ConsAddress(CarlPrivateKey.PubKey().Address()) DaveConsAddress = sdk.ConsAddress(DavePrivateKey.PubKey().Address()) + + // Collateral pool addresses for isolated perpetuals. + IsoCollateralPoolAddress = authtypes.NewModuleAddress(satypes.ModuleName + ":3") + Iso2CollateralPoolAddress = authtypes.NewModuleAddress(satypes.ModuleName + ":4") ) diff --git a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go index e0530ca187..fbda2dbf8c 100644 --- a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go +++ b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go @@ -3,6 +3,8 @@ package keeper import ( "context" + sdk "github.com/cosmos/cosmos-sdk/types" + "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -25,7 +27,10 @@ func (k Keeper) GetWithdrawalAndTransfersBlockedInfo( ) chainOutageSeenAtBlock, chainOutageExists := downtimeInfo.BlockInfo.Height, downtimeInfo.BlockInfo.Height > 0 && downtimeInfo.Duration > 0 - negativeTncSubaccountSeenAtBlock, negativeTncSubaccountSeenAtBlockExists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) + negativeTncSubaccountSeenAtBlock, negativeTncSubaccountSeenAtBlockExists := k.GetNegativeTncSubaccountSeenAtBlock( + ctx, + sdk.MustAccAddressFromBech32(req.CollateralPoolAddress), + ) // Withdrawals and transfers are blocked at non-zero block iff a chain outage or negative TNC subaccount exists. withdrawalsAndTransfersBlockedUntilBlock := uint32(0) diff --git a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go index 5757ac8384..ef704aabd7 100644 --- a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go +++ b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go @@ -9,6 +9,7 @@ import ( "google.golang.org/grpc/status" sdktypes "github.com/cosmos/cosmos-sdk/types" + "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" keepertest "github.com/dydxprotocol/v4-chain/protocol/testutil/keeper" btkeeper "github.com/dydxprotocol/v4-chain/protocol/x/blocktime/keeper" blocktimetypes "github.com/dydxprotocol/v4-chain/protocol/x/blocktime/types" @@ -37,7 +38,9 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { at block 0`: { setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) {}, - request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{}, + request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ + CollateralPoolAddress: types.ModuleAddress.String(), + }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ NegativeTncSubaccountSeenAtBlock: 0, @@ -51,7 +54,9 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { sk.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 7) }, - request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{}, + request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ + CollateralPoolAddress: types.ModuleAddress.String(), + }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ NegativeTncSubaccountSeenAtBlock: 7, @@ -60,6 +65,23 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, }, }, + `Negative TNC subaccount seen in state returns withdrawals and transfers unblocked + after the delay (for isolated collateral pool address)`: { + setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { + sk.SetNegativeTncSubaccountSeenAtBlock(ctx, constants.IsoCollateralPoolAddress, 5) + }, + + request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ + CollateralPoolAddress: constants.IsoCollateralPoolAddress.String(), + }, + + response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ + NegativeTncSubaccountSeenAtBlock: 5, + ChainOutageSeenAtBlock: 0, + WithdrawalsAndTransfersUnblockedAtBlock: 5 + + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + }, + }, `Chain outage seen in state returns withdrawals and transfers unblocked after the delay`: { setup: func(ctx sdktypes.Context, k sakeeper.Keeper, bk btkeeper.Keeper) { bk.SetAllDowntimeInfo( @@ -84,7 +106,9 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }) }, - request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{}, + request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ + CollateralPoolAddress: types.ModuleAddress.String(), + }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ NegativeTncSubaccountSeenAtBlock: 0, @@ -119,7 +143,9 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }) }, - request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{}, + request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ + CollateralPoolAddress: types.ModuleAddress.String(), + }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ NegativeTncSubaccountSeenAtBlock: 27, @@ -154,7 +180,9 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }) }, - request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{}, + request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ + CollateralPoolAddress: types.ModuleAddress.String(), + }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ NegativeTncSubaccountSeenAtBlock: 37, @@ -189,7 +217,9 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }) }, - request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{}, + request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ + CollateralPoolAddress: types.ModuleAddress.String(), + }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ NegativeTncSubaccountSeenAtBlock: 3, diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go index 0e72c348be..390acb5e53 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go @@ -11,7 +11,7 @@ import ( ) // GetNegativeTncSubaccountSeenAtBlock gets the last block height a negative TNC subaccount was -// seen in state and a boolean for whether it exists in state. +// seen in state for the given collateral pool address and a boolean for whether it exists in state. func (k Keeper) GetNegativeTncSubaccountSeenAtBlock( ctx sdk.Context, collateralPoolAddr sdk.AccAddress, @@ -21,7 +21,8 @@ func (k Keeper) GetNegativeTncSubaccountSeenAtBlock( } // getNegativeTncSubaccountSeenAtBlock is a helper function that takes a store and returns the last -// block height a negative TNC subaccount was seen in state and a boolean for whether it exists in state. +// block height a negative TNC subaccount was seen in state for the given collateral pool address +// and a boolean for whether it exists in state. func (k Keeper) getNegativeTncSubaccountSeenAtBlock( store storetypes.KVStore, collateralPoolAddr sdk.AccAddress, @@ -63,7 +64,7 @@ func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( blockHeightValue := gogotypes.UInt32Value{Value: blockHeight} store.Set( - []byte(collateralPoolAddr), + collateralPoolAddr.Bytes(), k.cdc.MustMarshal(&blockHeightValue), ) } diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go index 520821793e..b303e17188 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go @@ -4,6 +4,7 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" keepertest "github.com/dydxprotocol/v4-chain/protocol/testutil/keeper" "github.com/dydxprotocol/v4-chain/protocol/testutil/tracer" "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/keeper" @@ -12,6 +13,11 @@ import ( ) func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { + testCollateralPoolAddresses := []sdk.AccAddress{ + constants.IsoCollateralPoolAddress, + constants.Iso2CollateralPoolAddress, + types.ModuleAddress, + } tests := map[string]struct { // Setup. setupTestAndPerformAssertions func(ctx sdk.Context, s keeper.Keeper) @@ -21,104 +27,149 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }{ "Block height defaults to zero if not set and doesn't exist": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) - require.False(t, exists) - require.Equal( - t, - uint32(0), - block, - ) + for _, collateralPoolAddr := range testCollateralPoolAddresses { + block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + require.False(t, exists) + require.Equal( + t, + uint32(0), + block, + ) + } }, expectedMultiStoreWrites: []string{}, }, "Block height can be updated": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 1) - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) - require.True(t, exists) - require.Equal( - t, - uint32(1), - block, - ) + for _, collateralPoolAddr := range testCollateralPoolAddresses { + k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 1) + block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + require.True(t, exists) + require.Equal( + t, + uint32(1), + block, + ) + } }, expectedMultiStoreWrites: []string{ - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + string(constants.IsoCollateralPoolAddress), + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + string(constants.Iso2CollateralPoolAddress), + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + string(types.ModuleAddress), }, }, "Block height can be updated more than once": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 1) - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) - require.True(t, exists) - require.Equal( - t, - uint32(1), - block, - ) - - k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 2) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) - require.True(t, exists) - require.Equal( - t, - uint32(2), - block, - ) - - k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 3) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) - require.True(t, exists) - require.Equal( - t, - uint32(3), - block, - ) - - k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 10) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) - require.True(t, exists) - require.Equal( - t, - uint32(10), - block, - ) + for _, collateralPoolAddr := range testCollateralPoolAddresses { + k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 1) + block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + require.True(t, exists) + require.Equal( + t, + uint32(1), + block, + ) + + k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 2) + block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + require.True(t, exists) + require.Equal( + t, + uint32(2), + block, + ) + + k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 3) + block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + require.True(t, exists) + require.Equal( + t, + uint32(3), + block, + ) + + k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 10) + block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + require.True(t, exists) + require.Equal( + t, + uint32(10), + block, + ) + } }, - expectedMultiStoreWrites: []string{ - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, - }, + expectedMultiStoreWrites: append( + getWriteKeys(constants.IsoCollateralPoolAddress, 4), + append( + getWriteKeys(constants.Iso2CollateralPoolAddress, 4), + getWriteKeys(types.ModuleAddress, 4)..., + )..., + ), }, "Block height can be updated to same block height": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 0) - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) - require.True(t, exists) - require.Equal( - t, - uint32(0), - block, - ) - - k.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 0) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) - require.True(t, exists) - require.Equal( - t, - uint32(0), - block, - ) + for _, collateralPoolAddr := range testCollateralPoolAddresses { + k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 0) + block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + require.True(t, exists) + require.Equal( + t, + uint32(0), + block, + ) + + k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 0) + block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + require.True(t, exists) + require.Equal( + t, + uint32(0), + block, + ) + } }, - expectedMultiStoreWrites: []string{ - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix, + expectedMultiStoreWrites: append( + getWriteKeys(constants.IsoCollateralPoolAddress, 2), + append( + getWriteKeys(constants.Iso2CollateralPoolAddress, 2), + getWriteKeys(types.ModuleAddress, 2)..., + )..., + ), + }, + "Block height can be updated to different block heights for each collateral pool address": { + setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { + for i, collateralPoolAddr := range testCollateralPoolAddresses { + k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, uint32(i)) + block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + require.True(t, exists) + require.Equal( + t, + uint32(i), + block, + ) + + k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, uint32(2*i+1)) + block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + require.True(t, exists) + require.Equal( + t, + uint32(2*i+1), + block, + ) + } }, + + expectedMultiStoreWrites: append( + getWriteKeys(constants.IsoCollateralPoolAddress, 2), + append( + getWriteKeys(constants.Iso2CollateralPoolAddress, 2), + getWriteKeys(types.ModuleAddress, 2)..., + )..., + ), }, } @@ -153,3 +204,11 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock_PanicsOnDecreasingBlock(t *testi func() { subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 1) }, ) } + +func getWriteKeys(address sdk.AccAddress, times int) []string { + writeKeys := make([]string, times) + for i := 0; i < times; i++ { + writeKeys[i] = types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + string(address) + } + return writeKeys +} diff --git a/protocol/x/subaccounts/keeper/subaccount.go b/protocol/x/subaccounts/keeper/subaccount.go index 98cccb034c..421e84bffa 100644 --- a/protocol/x/subaccounts/keeper/subaccount.go +++ b/protocol/x/subaccounts/keeper/subaccount.go @@ -62,8 +62,16 @@ func (k Keeper) GetCollateralPoolForSubaccount(ctx sdk.Context, subaccountId typ sdk.AccAddress, error, ) { - // Use the default collateral pool if the subaccount has no perpetual positions. + subaccount := k.GetSubaccount(ctx, subaccountId) + return k.getCollateralPoolForSubaccount(ctx, subaccount) +} + +func (k Keeper) getCollateralPoolForSubaccount(ctx sdk.Context, subaccount types.Subaccount) ( + sdk.AccAddress, + error, +) { + // Use the default collateral pool if the subaccount has no perpetual positions. if len(subaccount.PerpetualPositions) == 0 { return types.ModuleAddress, nil } @@ -553,10 +561,14 @@ func (k Keeper) internalCanUpdateSubaccounts( // 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 negative TNC subaccount seen for any of the collateral pools of subaccounts being updated // - There was a chain outage that lasted at least five minutes. if updateType == types.Withdrawal || updateType == types.Transfer { - lastBlockNegativeTncSubaccountSeen, negativeTncSubaccountExists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress) + collateralPoolAddresses, err := k.getCollateralPoolAddresses(ctx, settledUpdates) + if err != nil { + return false, nil, err + } + lastBlockNegativeTncSubaccountSeen, negativeTncSubaccountExists := k.getLastBlockNegativeSubaccountSeen(ctx, collateralPoolAddresses) currentBlock := uint32(ctx.BlockHeight()) // Panic if the current block is less than the last block a negative TNC subaccount was seen. @@ -951,3 +963,46 @@ func applyUpdatesToPositions[ return result, nil } + +// getCollateralPoolAddresses gets a slice of collateral pool addresses for the subaccounts in the +// slice of `settledUpdate`s passed in. +// The slice will be de-duplicated and will contain unique collateral pool addresses. +func (k Keeper) getCollateralPoolAddresses( + ctx sdk.Context, + settledUpdates []settledUpdate, +) ([]sdk.AccAddress, error) { + collateralPoolAddressMap := make(map[string]bool) + collateralPoolAddresses := make([]sdk.AccAddress, 0) + for _, u := range settledUpdates { + collateralPoolAddress, err := k.getCollateralPoolForSubaccount(ctx, u.SettledSubaccount) + if err != nil { + return nil, err + } + if _, exists := collateralPoolAddressMap[collateralPoolAddress.String()]; !exists { + collateralPoolAddresses = append(collateralPoolAddresses, collateralPoolAddress) + collateralPoolAddressMap[collateralPoolAddress.String()] = true + } + } + return collateralPoolAddresses, nil +} + +// getLastBlockNegativeSubaccountSeen gets the last block where a subaccount with negative total net +// collateral was seen for a slice of collateral pool addresses. +func (k Keeper) getLastBlockNegativeSubaccountSeen( + ctx sdk.Context, + collateralPoolAddresses []sdk.AccAddress, +) ( + lastBlockNegativeSubaccountSeen uint32, + negativeSubaccountExists bool, +) { + lastBlockNegativeSubaccountSeen = uint32(0) + negativeSubaccountExists = false + for _, collateralPoolAddress := range collateralPoolAddresses { + blockHeight, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddress) + if exists && blockHeight > lastBlockNegativeSubaccountSeen { + lastBlockNegativeSubaccountSeen = blockHeight + negativeSubaccountExists = true + } + } + return lastBlockNegativeSubaccountSeen, negativeSubaccountExists +} diff --git a/protocol/x/subaccounts/keeper/subaccount_test.go b/protocol/x/subaccounts/keeper/subaccount_test.go index b05dd0e4d8..75b142525a 100644 --- a/protocol/x/subaccounts/keeper/subaccount_test.go +++ b/protocol/x/subaccounts/keeper/subaccount_test.go @@ -2411,7 +2411,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { // Negative TNC subaccount state currentBlock uint32 - negativeTncSubaccountSeenAtBlock uint32 + negativeTncSubaccountSeenAtBlock map[string]uint32 // Update type updateType types.UpdateType @@ -2441,8 +2441,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, msgSenderEnabled: true, - currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100, + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100, + }, updateType: types.Deposit, }, @@ -2473,8 +2475,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100 - - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, updateType: types.Deposit, }, @@ -2503,8 +2507,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, msgSenderEnabled: true, - currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 0, + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 0, + }, updateType: types.Deposit, }, @@ -2532,8 +2538,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, msgSenderEnabled: true, - currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100, + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100, + }, updateType: types.Withdrawal, }, @@ -2563,8 +2571,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100 - - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, updateType: types.Withdrawal, }, @@ -2604,8 +2614,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100 - - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + }, updateType: types.Withdrawal, }, @@ -2643,8 +2655,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, msgSenderEnabled: true, - currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 0, + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 0, + }, updateType: types.Withdrawal, }, @@ -2689,8 +2703,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, msgSenderEnabled: false, - currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100, + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100, + }, updateType: types.Match, }, @@ -2737,8 +2753,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: false, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100 - - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, updateType: types.Match, }, @@ -2783,8 +2801,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, msgSenderEnabled: false, - currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 0, + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 0, + }, updateType: types.Match, }, @@ -2814,9 +2834,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, msgSenderEnabled: true, - currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100, - + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100, + }, updateType: types.Match, }, `undercollateralized matches are not blocked if current block is within @@ -2847,8 +2868,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100 - - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, updateType: types.Match, }, @@ -2878,8 +2901,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, msgSenderEnabled: true, - currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 0, + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 0, + }, updateType: types.Match, }, @@ -2910,8 +2935,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, msgSenderEnabled: true, - currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100, + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100, + }, updateType: types.Withdrawal, }, @@ -2944,8 +2971,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100 - - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, updateType: types.Withdrawal, }, @@ -2978,8 +3007,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 100 - - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + }, updateType: types.Withdrawal, }, @@ -3010,8 +3041,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, msgSenderEnabled: true, - currentBlock: 100, - negativeTncSubaccountSeenAtBlock: 0, + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 0, + }, updateType: types.Withdrawal, }, @@ -3084,8 +3117,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { subaccountId := *subaccounts[0].Id // Set the negative TNC subaccount seen at block in state if it's greater than 0. - if tc.negativeTncSubaccountSeenAtBlock != 0 { - keeper.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, tc.negativeTncSubaccountSeenAtBlock) + for collateralPoolAddress, negativeTncSubaccountSeenAtBlock := range tc.negativeTncSubaccountSeenAtBlock { + if negativeTncSubaccountSeenAtBlock != 0 { + keeper.SetNegativeTncSubaccountSeenAtBlock(ctx, sdk.MustAccAddressFromBech32(collateralPoolAddress), negativeTncSubaccountSeenAtBlock) + } } // Set the current block number on the context. diff --git a/protocol/x/subaccounts/types/query.pb.go b/protocol/x/subaccounts/types/query.pb.go index 1c0893dc8a..3c5ad19cb4 100644 --- a/protocol/x/subaccounts/types/query.pb.go +++ b/protocol/x/subaccounts/types/query.pb.go @@ -228,8 +228,10 @@ func (m *QuerySubaccountAllResponse) GetPagination() *query.PageResponse { } // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a request type for -// fetching information about whether withdrawals and transfers are blocked. +// fetching information about whether withdrawals and transfers are blocked for a specific +// collateral pool. type QueryGetWithdrawalAndTransfersBlockedInfoRequest struct { + CollateralPoolAddress string `protobuf:"bytes,1,opt,name=collateral_pool_address,json=collateralPoolAddress,proto3" json:"collateral_pool_address,omitempty"` } func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) Reset() { @@ -269,6 +271,13 @@ func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) XXX_DiscardUnknown() var xxx_messageInfo_QueryGetWithdrawalAndTransfersBlockedInfoRequest proto.InternalMessageInfo +func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) GetCollateralPoolAddress() string { + if m != nil { + return m.CollateralPoolAddress + } + return "" +} + // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a response type for // fetching information about whether withdrawals and transfers are blocked. type QueryGetWithdrawalAndTransfersBlockedInfoResponse struct { @@ -349,49 +358,51 @@ func init() { } var fileDescriptor_adc19ff1d5b72954 = []byte{ - // 666 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0x4d, 0x6b, 0xd4, 0x40, - 0x18, 0xde, 0x6c, 0x3f, 0xc0, 0x91, 0x5e, 0x86, 0x52, 0xb7, 0x41, 0xd6, 0xb2, 0xac, 0x6d, 0x95, - 0x36, 0xe3, 0xb6, 0x15, 0x41, 0x28, 0xb8, 0x7b, 0xb0, 0x5a, 0x0f, 0xd5, 0xb4, 0x52, 0x10, 0x24, - 0x4c, 0x92, 0x69, 0x1a, 0x4c, 0x67, 0xb6, 0x99, 0x49, 0x3f, 0x28, 0xbd, 0x78, 0xf3, 0x26, 0xf8, - 0x03, 0xbc, 0x7a, 0x15, 0xfd, 0x11, 0x3d, 0x16, 0xbd, 0x78, 0x12, 0x69, 0xfd, 0x09, 0xfe, 0x00, - 0xd9, 0x99, 0xc9, 0x26, 0xdb, 0x1a, 0x76, 0x15, 0x6f, 0xc9, 0xcc, 0xfb, 0x3c, 0xef, 0xf3, 0xbc, - 0xf3, 0x3e, 0xa0, 0xee, 0x1f, 0xfa, 0x07, 0xed, 0x98, 0x09, 0xe6, 0xb1, 0x08, 0xf1, 0xc4, 0xc5, - 0x9e, 0xc7, 0x12, 0x2a, 0x38, 0xda, 0x4d, 0x48, 0x7c, 0x68, 0xc9, 0x2b, 0x58, 0xc9, 0x57, 0x59, - 0xb9, 0x2a, 0x73, 0xd2, 0x63, 0x7c, 0x87, 0x71, 0x47, 0x5e, 0x22, 0xf5, 0xa3, 0x40, 0xe6, 0x78, - 0xc0, 0x02, 0xa6, 0xce, 0x3b, 0x5f, 0xfa, 0xf4, 0x7a, 0xc0, 0x58, 0x10, 0x11, 0x84, 0xdb, 0x21, - 0xc2, 0x94, 0x32, 0x81, 0x45, 0xc8, 0x68, 0x8a, 0xb9, 0xad, 0x18, 0x90, 0x8b, 0x39, 0x51, 0x0a, - 0xd0, 0x5e, 0xc3, 0x25, 0x02, 0x37, 0x50, 0x1b, 0x07, 0x21, 0x95, 0xc5, 0xba, 0xf6, 0x56, 0xa1, - 0xf4, 0xec, 0x5b, 0x95, 0xd6, 0x3c, 0x30, 0xf9, 0xac, 0x43, 0xb6, 0x42, 0xc4, 0x7a, 0xf7, 0xce, - 0x26, 0xbb, 0x09, 0xe1, 0x02, 0x5a, 0x60, 0x84, 0xed, 0x53, 0x12, 0x57, 0x8c, 0x29, 0x63, 0xf6, - 0x4a, 0xab, 0xf2, 0xe5, 0xf3, 0xfc, 0xb8, 0x36, 0xd2, 0xf4, 0xfd, 0x98, 0x70, 0xbe, 0x2e, 0xe2, - 0x90, 0x06, 0xb6, 0x2a, 0x83, 0x13, 0x60, 0x94, 0x26, 0x3b, 0x2e, 0x89, 0x2b, 0xe5, 0x29, 0x63, - 0x76, 0xcc, 0xd6, 0x7f, 0x35, 0x02, 0xae, 0xc9, 0x26, 0xf9, 0x0e, 0xbc, 0xcd, 0x28, 0x27, 0x70, - 0x15, 0x80, 0x4c, 0x93, 0xec, 0x73, 0x75, 0xa1, 0x6e, 0x15, 0x0d, 0xd5, 0xca, 0x18, 0x5a, 0xc3, - 0x27, 0xdf, 0x6f, 0x94, 0xec, 0x1c, 0xba, 0xeb, 0xa5, 0x19, 0x45, 0x97, 0xbd, 0x3c, 0x04, 0x20, - 0x9b, 0x93, 0x6e, 0x34, 0x6d, 0x69, 0x37, 0x9d, 0xa1, 0x5a, 0xea, 0x59, 0xf5, 0x50, 0xad, 0xa7, - 0x38, 0x20, 0x1a, 0x6b, 0xe7, 0x90, 0xb5, 0x8f, 0x06, 0x30, 0x2f, 0x98, 0x69, 0x46, 0x51, 0xa1, - 0x9f, 0xa1, 0x7f, 0xf7, 0x03, 0x57, 0x7a, 0x24, 0x97, 0xa5, 0xe4, 0x99, 0xbe, 0x92, 0x95, 0x90, - 0x1e, 0xcd, 0x0b, 0xe0, 0x4e, 0xfa, 0xc8, 0x9b, 0xa1, 0xd8, 0xf6, 0x63, 0xbc, 0x8f, 0xa3, 0x26, - 0xf5, 0x37, 0x62, 0x4c, 0xf9, 0x16, 0x89, 0x79, 0x2b, 0x62, 0xde, 0x2b, 0xe2, 0x3f, 0xa6, 0x5b, - 0x4c, 0x7b, 0xae, 0xbd, 0x2f, 0x83, 0xc6, 0x5f, 0x80, 0xb4, 0xfd, 0x35, 0x70, 0x93, 0x92, 0x00, - 0x8b, 0x70, 0x8f, 0x38, 0x82, 0x7a, 0x4e, 0xe6, 0xc6, 0xe1, 0x84, 0x50, 0x07, 0x0b, 0xc7, 0xed, - 0xc0, 0xe4, 0x03, 0x8c, 0xd9, 0x53, 0x69, 0xf1, 0x06, 0xf5, 0xb2, 0x51, 0xac, 0x13, 0x42, 0x9b, - 0x42, 0xd2, 0xc3, 0xfb, 0xc0, 0xf4, 0xb6, 0x71, 0x48, 0x1d, 0x96, 0x08, 0x1c, 0x90, 0x0b, 0x2c, - 0x6a, 0xcd, 0x26, 0x64, 0xc5, 0x9a, 0x2c, 0xc8, 0x63, 0x5f, 0x82, 0xb9, 0xfd, 0xae, 0x72, 0xee, - 0x60, 0xea, 0x3b, 0x22, 0x15, 0xef, 0x24, 0xd4, 0x55, 0xfa, 0x33, 0xb6, 0x21, 0xc9, 0x36, 0x93, - 0xc3, 0xe4, 0xed, 0x3e, 0x4f, 0x01, 0x9a, 0x7e, 0xe1, 0xd7, 0x30, 0x18, 0x91, 0x13, 0x82, 0x9f, - 0x0c, 0x00, 0x32, 0xf9, 0x70, 0xb1, 0xf8, 0xbd, 0x0b, 0xb3, 0x66, 0x36, 0xfa, 0x80, 0x2e, 0x67, - 0xa7, 0xb6, 0xfc, 0xfa, 0xeb, 0xcf, 0x77, 0xe5, 0x7b, 0xf0, 0x2e, 0x1a, 0x20, 0xef, 0xe8, 0x48, - 0x66, 0xf4, 0x18, 0x1d, 0xa9, 0x50, 0x1e, 0xc3, 0x0f, 0x06, 0x18, 0xeb, 0x59, 0xe2, 0xbe, 0xc2, - 0xff, 0x14, 0x2c, 0x73, 0x69, 0x60, 0xe1, 0xb9, 0x9c, 0xd4, 0xe6, 0xa4, 0xf6, 0x69, 0x58, 0x1f, - 0x44, 0x3b, 0x7c, 0x53, 0x06, 0xf5, 0x41, 0xf6, 0x10, 0xae, 0xf6, 0x1f, 0xfd, 0xa0, 0x09, 0x30, - 0x9f, 0xfc, 0x17, 0x2e, 0xed, 0xf7, 0x91, 0xf4, 0xdb, 0x82, 0x0f, 0x8a, 0xfd, 0x16, 0xef, 0x6a, - 0xba, 0xa9, 0x21, 0xdd, 0x62, 0xad, 0xcd, 0x93, 0xb3, 0xaa, 0x71, 0x7a, 0x56, 0x35, 0x7e, 0x9c, - 0x55, 0x8d, 0xb7, 0xe7, 0xd5, 0xd2, 0xe9, 0x79, 0xb5, 0xf4, 0xed, 0xbc, 0x5a, 0x7a, 0xb1, 0x1c, - 0x84, 0x62, 0x3b, 0x71, 0x2d, 0x8f, 0xed, 0xf4, 0x76, 0xd9, 0x5b, 0x9a, 0x97, 0x11, 0x41, 0xdd, - 0x93, 0x83, 0x9e, 0xce, 0xe2, 0xb0, 0x4d, 0xb8, 0x3b, 0x2a, 0x6f, 0x17, 0x7f, 0x07, 0x00, 0x00, - 0xff, 0xff, 0x06, 0xb5, 0xab, 0xe1, 0xf9, 0x06, 0x00, 0x00, + // 697 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x4f, 0xd4, 0x40, + 0x14, 0xdf, 0x2e, 0x7f, 0x12, 0xc7, 0x70, 0x99, 0x20, 0x2c, 0x8d, 0x59, 0xc9, 0x66, 0x05, 0x34, + 0xd0, 0xba, 0x80, 0x31, 0x31, 0x21, 0x71, 0xf7, 0x20, 0x8a, 0x07, 0x70, 0xc1, 0x90, 0x98, 0x98, + 0x66, 0xda, 0x0e, 0xa5, 0x71, 0x98, 0x59, 0x3a, 0x53, 0xfe, 0x84, 0x70, 0x31, 0x5e, 0xbc, 0x99, + 0xf8, 0x01, 0xbc, 0x7a, 0x35, 0xfa, 0x21, 0x38, 0x12, 0xbd, 0x78, 0x32, 0x06, 0xfc, 0x08, 0x7e, + 0x00, 0xb3, 0x33, 0xd3, 0x6d, 0x17, 0x6c, 0x76, 0x35, 0xde, 0x3a, 0xf3, 0xde, 0xef, 0xbd, 0xdf, + 0xef, 0x37, 0xef, 0x15, 0x54, 0xfd, 0x43, 0xff, 0xa0, 0x15, 0x31, 0xc1, 0x3c, 0x46, 0x6c, 0x1e, + 0xbb, 0xc8, 0xf3, 0x58, 0x4c, 0x05, 0xb7, 0x77, 0x63, 0x1c, 0x1d, 0x5a, 0x32, 0x04, 0x4b, 0xd9, + 0x2c, 0x2b, 0x93, 0x65, 0x4e, 0x78, 0x8c, 0xef, 0x30, 0xee, 0xc8, 0xa0, 0xad, 0x0e, 0x0a, 0x64, + 0x8e, 0x06, 0x2c, 0x60, 0xea, 0xbe, 0xfd, 0xa5, 0x6f, 0xaf, 0x07, 0x8c, 0x05, 0x04, 0xdb, 0xa8, + 0x15, 0xda, 0x88, 0x52, 0x26, 0x90, 0x08, 0x19, 0x4d, 0x30, 0xb7, 0x55, 0x05, 0xdb, 0x45, 0x1c, + 0x2b, 0x06, 0xf6, 0x5e, 0xcd, 0xc5, 0x02, 0xd5, 0xec, 0x16, 0x0a, 0x42, 0x2a, 0x93, 0x75, 0xee, + 0xad, 0x5c, 0xea, 0xe9, 0xb7, 0x4a, 0xad, 0x78, 0x60, 0xe2, 0x69, 0xbb, 0xd8, 0x32, 0x16, 0xeb, + 0x9d, 0x58, 0x13, 0xef, 0xc6, 0x98, 0x0b, 0x68, 0x81, 0x21, 0xb6, 0x4f, 0x71, 0x54, 0x32, 0x26, + 0x8d, 0x99, 0x2b, 0x8d, 0xd2, 0x97, 0xcf, 0x73, 0xa3, 0x5a, 0x48, 0xdd, 0xf7, 0x23, 0xcc, 0xf9, + 0xba, 0x88, 0x42, 0x1a, 0x34, 0x55, 0x1a, 0x1c, 0x03, 0xc3, 0x34, 0xde, 0x71, 0x71, 0x54, 0x2a, + 0x4e, 0x1a, 0x33, 0x23, 0x4d, 0x7d, 0xaa, 0x60, 0x30, 0x2e, 0x9b, 0x64, 0x3b, 0xf0, 0x16, 0xa3, + 0x1c, 0xc3, 0x15, 0x00, 0x52, 0x4e, 0xb2, 0xcf, 0xd5, 0xf9, 0xaa, 0x95, 0x67, 0xaa, 0x95, 0x56, + 0x68, 0x0c, 0x9e, 0x7c, 0xbf, 0x51, 0x68, 0x66, 0xd0, 0x1d, 0x2d, 0x75, 0x42, 0x2e, 0x6b, 0x79, + 0x08, 0x40, 0xea, 0x93, 0x6e, 0x34, 0x65, 0x69, 0x35, 0x6d, 0x53, 0x2d, 0xf5, 0xac, 0xda, 0x54, + 0x6b, 0x0d, 0x05, 0x58, 0x63, 0x9b, 0x19, 0x64, 0xe5, 0xa3, 0x01, 0xcc, 0x0b, 0x62, 0xea, 0x84, + 0xe4, 0xea, 0x19, 0xf8, 0x77, 0x3d, 0x70, 0xb9, 0x8b, 0x72, 0x51, 0x52, 0x9e, 0xee, 0x49, 0x59, + 0x11, 0xe9, 0xe2, 0xfc, 0xda, 0x00, 0x77, 0x92, 0x57, 0xde, 0x0c, 0xc5, 0xb6, 0x1f, 0xa1, 0x7d, + 0x44, 0xea, 0xd4, 0xdf, 0x88, 0x10, 0xe5, 0x5b, 0x38, 0xe2, 0x0d, 0xc2, 0xbc, 0x97, 0xd8, 0x7f, + 0x4c, 0xb7, 0x58, 0x62, 0xd8, 0x1a, 0x18, 0xf7, 0x18, 0x21, 0x48, 0xe0, 0x08, 0x11, 0xa7, 0xc5, + 0x18, 0x71, 0x90, 0x7a, 0xf4, 0x9e, 0xe3, 0x70, 0x2d, 0x05, 0xae, 0x31, 0x46, 0x74, 0xb0, 0xf2, + 0xbe, 0x08, 0x6a, 0x7f, 0x41, 0x43, 0x3b, 0xba, 0x0a, 0x6e, 0x52, 0x1c, 0x20, 0x11, 0xee, 0x61, + 0x47, 0x50, 0xcf, 0x49, 0x0d, 0x72, 0x38, 0xc6, 0xd4, 0x41, 0xc2, 0x71, 0xdb, 0x30, 0xc9, 0x6a, + 0xa4, 0x39, 0x99, 0x24, 0x6f, 0x50, 0x2f, 0x75, 0x77, 0x1d, 0x63, 0x5a, 0x17, 0xb2, 0x3c, 0xbc, + 0x0f, 0x4c, 0x6f, 0x1b, 0x85, 0xd4, 0x61, 0xb1, 0x40, 0x01, 0xbe, 0x50, 0x45, 0x4d, 0xee, 0x98, + 0xcc, 0x58, 0x95, 0x09, 0x59, 0xec, 0x0b, 0x30, 0xbb, 0xdf, 0x61, 0xce, 0x1d, 0x44, 0x7d, 0x47, + 0x24, 0xe4, 0x9d, 0x98, 0xba, 0x8a, 0x7f, 0x5a, 0x6d, 0x40, 0x56, 0x9b, 0xce, 0x60, 0xb2, 0x72, + 0x9f, 0x25, 0x00, 0x5d, 0x7e, 0xfe, 0xd7, 0x20, 0x18, 0x92, 0x0e, 0xc1, 0x4f, 0x06, 0x00, 0x29, + 0x7d, 0xb8, 0x90, 0x3f, 0x42, 0xb9, 0xeb, 0x6b, 0xd6, 0x7a, 0x80, 0x2e, 0xaf, 0x63, 0x65, 0xe9, + 0xd5, 0xd7, 0x9f, 0xef, 0x8a, 0xf7, 0xe0, 0x5d, 0xbb, 0x8f, 0x5f, 0x88, 0x7d, 0x24, 0xd7, 0xfe, + 0xd8, 0x3e, 0x52, 0x7b, 0x7e, 0x0c, 0x3f, 0x18, 0x60, 0xa4, 0x6b, 0x2f, 0x7a, 0x12, 0xff, 0xd3, + 0xae, 0x9a, 0x8b, 0x7d, 0x13, 0xcf, 0xac, 0x5e, 0x65, 0x56, 0x72, 0x9f, 0x82, 0xd5, 0x7e, 0xb8, + 0xc3, 0x37, 0x45, 0x50, 0xed, 0x67, 0x0e, 0xe1, 0x4a, 0x6f, 0xeb, 0xfb, 0xdd, 0x29, 0xf3, 0xc9, + 0x7f, 0xa9, 0xa5, 0xf5, 0x3e, 0x92, 0x7a, 0x1b, 0xf0, 0x41, 0xbe, 0xde, 0xfc, 0x59, 0x4d, 0x26, + 0x35, 0xa4, 0x5b, 0xac, 0xb1, 0x79, 0x72, 0x56, 0x36, 0x4e, 0xcf, 0xca, 0xc6, 0x8f, 0xb3, 0xb2, + 0xf1, 0xf6, 0xbc, 0x5c, 0x38, 0x3d, 0x2f, 0x17, 0xbe, 0x9d, 0x97, 0x0b, 0xcf, 0x97, 0x82, 0x50, + 0x6c, 0xc7, 0xae, 0xe5, 0xb1, 0x9d, 0xee, 0x2e, 0x7b, 0x8b, 0x73, 0x72, 0x45, 0xec, 0xce, 0xcd, + 0x41, 0x57, 0x67, 0x71, 0xd8, 0xc2, 0xdc, 0x1d, 0x96, 0xd1, 0x85, 0xdf, 0x01, 0x00, 0x00, 0xff, + 0xff, 0x79, 0x40, 0x83, 0x76, 0x4c, 0x07, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -726,6 +737,13 @@ func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) MarshalToSizedBuffer( _ = i var l int _ = l + if len(m.CollateralPoolAddress) > 0 { + i -= len(m.CollateralPoolAddress) + copy(dAtA[i:], m.CollateralPoolAddress) + i = encodeVarintQuery(dAtA, i, uint64(len(m.CollateralPoolAddress))) + i-- + dAtA[i] = 0xa + } return len(dAtA) - i, nil } @@ -843,6 +861,10 @@ func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) Size() (n int) { } var l int _ = l + l = len(m.CollateralPoolAddress) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } return n } @@ -1289,6 +1311,38 @@ func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) Unmarshal(dAtA []byte return fmt.Errorf("proto: QueryGetWithdrawalAndTransfersBlockedInfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CollateralPoolAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CollateralPoolAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/protocol/x/subaccounts/types/query.pb.gw.go b/protocol/x/subaccounts/types/query.pb.gw.go index 00ebde2bbe..9aebee906d 100644 --- a/protocol/x/subaccounts/types/query.pb.gw.go +++ b/protocol/x/subaccounts/types/query.pb.gw.go @@ -145,10 +145,21 @@ func local_request_Query_SubaccountAll_0(ctx context.Context, marshaler runtime. } +var ( + filter_Query_GetWithdrawalAndTransfersBlockedInfo_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + func request_Query_GetWithdrawalAndTransfersBlockedInfo_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryGetWithdrawalAndTransfersBlockedInfoRequest var metadata runtime.ServerMetadata + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GetWithdrawalAndTransfersBlockedInfo_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.GetWithdrawalAndTransfersBlockedInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -158,6 +169,13 @@ func local_request_Query_GetWithdrawalAndTransfersBlockedInfo_0(ctx context.Cont var protoReq QueryGetWithdrawalAndTransfersBlockedInfoRequest var metadata runtime.ServerMetadata + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GetWithdrawalAndTransfersBlockedInfo_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.GetWithdrawalAndTransfersBlockedInfo(ctx, &protoReq) return msg, metadata, err From 379dcaee25b7a04c189e9fd056c24d6942d6b15f Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:51:39 -0600 Subject: [PATCH 04/16] Update x/subaccounts tests. --- protocol/x/clob/e2e/withdrawal_gating_test.go | 5 +- protocol/x/clob/keeper/process_operations.go | 10 +- .../x/clob/keeper/process_operations_test.go | 5 +- protocol/x/clob/types/expected_keepers.go | 4 + ...y_withdrawal_and_transfers_blocked_info.go | 4 +- .../keeper/negative_tnc_subaccount.go | 10 +- protocol/x/subaccounts/keeper/subaccount.go | 6 +- .../x/subaccounts/keeper/subaccount_test.go | 737 +++++++++++++++--- 8 files changed, 671 insertions(+), 110 deletions(-) diff --git a/protocol/x/clob/e2e/withdrawal_gating_test.go b/protocol/x/clob/e2e/withdrawal_gating_test.go index 176d7a79d2..65ea83db65 100644 --- a/protocol/x/clob/e2e/withdrawal_gating_test.go +++ b/protocol/x/clob/e2e/withdrawal_gating_test.go @@ -252,7 +252,10 @@ func TestWithdrawalGating_NegativeTncSubaccount_BlocksThenUnblocks(t *testing.T) tApp.App.SubaccountsKeeper.GetSubaccount(ctx, *expectedSubaccount.Id), ) } - negativeTncSubaccountSeenAtBlock, exists := tApp.App.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock(ctx, satypes.ModuleAddress) + negativeTncSubaccountSeenAtBlock, exists := tApp.App.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock( + ctx, + satypes.ModuleAddress, + ) require.Equal(t, tc.expectedWithdrawalsGated, exists) require.Equal(t, tc.expectedNegativeTncSubaccountSeenAtBlock, negativeTncSubaccountSeenAtBlock) diff --git a/protocol/x/clob/keeper/process_operations.go b/protocol/x/clob/keeper/process_operations.go index 719c368036..818b0412c4 100644 --- a/protocol/x/clob/keeper/process_operations.go +++ b/protocol/x/clob/keeper/process_operations.go @@ -694,7 +694,15 @@ func (k Keeper) PersistMatchDeleveragingToState( metrics.GetLabelForBoolValue(metrics.IsLong, position.GetIsLong()), metrics.GetLabelForBoolValue(metrics.DeliverTx, true), ) - k.subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, satypes.ModuleAddress, lib.MustConvertIntegerToUint32(ctx.BlockHeight())) + collateralPoolAddress, err := k.subaccountsKeeper.GetCollateralPoolFromPerpetualId(ctx, perpetualId) + if err != nil { + return err + } + k.subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock( + ctx, + collateralPoolAddress, + lib.MustConvertIntegerToUint32(ctx.BlockHeight()), + ) return nil } diff --git a/protocol/x/clob/keeper/process_operations_test.go b/protocol/x/clob/keeper/process_operations_test.go index 9d06915973..3a257816cf 100644 --- a/protocol/x/clob/keeper/process_operations_test.go +++ b/protocol/x/clob/keeper/process_operations_test.go @@ -2397,7 +2397,10 @@ func runProcessProposerOperationsTestCase( } // Verify the negative TNC subaccount seen block. - seenNegativeTncSubaccountBlock, exists := ks.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock(ctx, satypes.ModuleAddress) + seenNegativeTncSubaccountBlock, exists := ks.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock( + ctx, + satypes.ModuleAddress, + ) if tc.expectedNegativeTncSubaccountSeen { require.True(t, exists) require.Equal(t, uint32(ctx.BlockHeight()), seenNegativeTncSubaccountBlock) diff --git a/protocol/x/clob/types/expected_keepers.go b/protocol/x/clob/types/expected_keepers.go index 2ff76a44bc..662c989d8f 100644 --- a/protocol/x/clob/types/expected_keepers.go +++ b/protocol/x/clob/types/expected_keepers.go @@ -70,6 +70,10 @@ type SubaccountsKeeper interface { amount *big.Int, perpetualId uint32, ) error + GetCollateralPoolFromPerpetualId( + ctx sdk.Context, + perpetualId uint32, + ) (sdk.AccAddress, error) } type AssetsKeeper interface { diff --git a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go index fbda2dbf8c..2c8cac4045 100644 --- a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go +++ b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go @@ -3,8 +3,6 @@ package keeper import ( "context" - sdk "github.com/cosmos/cosmos-sdk/types" - "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -29,7 +27,7 @@ func (k Keeper) GetWithdrawalAndTransfersBlockedInfo( downtimeInfo.BlockInfo.Height > 0 && downtimeInfo.Duration > 0 negativeTncSubaccountSeenAtBlock, negativeTncSubaccountSeenAtBlockExists := k.GetNegativeTncSubaccountSeenAtBlock( ctx, - sdk.MustAccAddressFromBech32(req.CollateralPoolAddress), + sdktypes.MustAccAddressFromBech32(req.CollateralPoolAddress), ) // Withdrawals and transfers are blocked at non-zero block iff a chain outage or negative TNC subaccount exists. diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go index 390acb5e53..121852cdb8 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go @@ -16,7 +16,10 @@ func (k Keeper) GetNegativeTncSubaccountSeenAtBlock( ctx sdk.Context, collateralPoolAddr sdk.AccAddress, ) (uint32, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix)) + store := prefix.NewStore( + ctx.KVStore(k.storeKey), + []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix), + ) return k.getNegativeTncSubaccountSeenAtBlock(store, collateralPoolAddr) } @@ -48,7 +51,10 @@ func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( collateralPoolAddr sdk.AccAddress, blockHeight uint32, ) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix)) + store := prefix.NewStore( + ctx.KVStore(k.storeKey), + []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix), + ) // Panic if the stored block height value exists and is greater than the new block height value. currentValue, exists := k.getNegativeTncSubaccountSeenAtBlock(store, collateralPoolAddr) diff --git a/protocol/x/subaccounts/keeper/subaccount.go b/protocol/x/subaccounts/keeper/subaccount.go index 421e84bffa..96db67ba17 100644 --- a/protocol/x/subaccounts/keeper/subaccount.go +++ b/protocol/x/subaccounts/keeper/subaccount.go @@ -62,7 +62,6 @@ func (k Keeper) GetCollateralPoolForSubaccount(ctx sdk.Context, subaccountId typ sdk.AccAddress, error, ) { - subaccount := k.GetSubaccount(ctx, subaccountId) return k.getCollateralPoolForSubaccount(ctx, subaccount) } @@ -568,7 +567,10 @@ func (k Keeper) internalCanUpdateSubaccounts( if err != nil { return false, nil, err } - lastBlockNegativeTncSubaccountSeen, negativeTncSubaccountExists := k.getLastBlockNegativeSubaccountSeen(ctx, collateralPoolAddresses) + lastBlockNegativeTncSubaccountSeen, negativeTncSubaccountExists := k.getLastBlockNegativeSubaccountSeen( + ctx, + collateralPoolAddresses, + ) currentBlock := uint32(ctx.BlockHeight()) // Panic if the current block is less than the last block a negative TNC subaccount was seen. diff --git a/protocol/x/subaccounts/keeper/subaccount_test.go b/protocol/x/subaccounts/keeper/subaccount_test.go index 75b142525a..bd82a737e1 100644 --- a/protocol/x/subaccounts/keeper/subaccount_test.go +++ b/protocol/x/subaccounts/keeper/subaccount_test.go @@ -2377,7 +2377,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { Number: 0, } secondSubaccountId := types.SubaccountId{ - Owner: "0", + Owner: "1", Number: 1, } @@ -2389,16 +2389,16 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { marketParamPrices []pricestypes.MarketParamPrice // subaccount state - perpetualPositions []*types.PerpetualPosition - assetPositions []*types.AssetPosition + perpetualPositions map[types.SubaccountId][]*types.PerpetualPosition + assetPositions map[types.SubaccountId][]*types.AssetPosition // updates updates []types.Update // expectations expectedQuoteBalance *big.Int - expectedPerpetualPositions []*types.PerpetualPosition - expectedAssetPositions []*types.AssetPosition + expectedPerpetualPositions map[types.SubaccountId][]*types.PerpetualPosition + expectedAssetPositions map[types.SubaccountId][]*types.AssetPosition expectedSuccess bool expectedSuccessPerUpdate []types.UpdateResult expectedErr error @@ -2425,10 +2425,12 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), }, }, - expectedAssetPositions: []*types.AssetPosition{ - { - AssetId: uint32(0), - Quantums: dtypes.NewInt(100), // 100 USDC + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: { + { + AssetId: uint32(0), + Quantums: dtypes.NewInt(100), // 100 USDC + }, }, }, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ @@ -2458,10 +2460,12 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), }, }, - expectedAssetPositions: []*types.AssetPosition{ - { - AssetId: uint32(0), - Quantums: dtypes.NewInt(100), // 100 USDC + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: { + { + AssetId: uint32(0), + Quantums: dtypes.NewInt(100), // 100 USDC + }, }, }, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ @@ -2491,10 +2495,12 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), }, }, - expectedAssetPositions: []*types.AssetPosition{ - { - AssetId: uint32(0), - Quantums: dtypes.NewInt(100), // 100 USDC + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: { + { + AssetId: uint32(0), + Quantums: dtypes.NewInt(100), // 100 USDC + }, }, }, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ @@ -2521,13 +2527,13 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { perpetuals: []perptypes.Perpetual{ constants.BtcUsd_SmallMarginRequirement, }, - perpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedPerpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedAssetPositions: []*types.AssetPosition{}, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ firstSubaccountId: {}, }, @@ -2553,13 +2559,13 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { perpetuals: []perptypes.Perpetual{ constants.BtcUsd_SmallMarginRequirement, }, - perpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedPerpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedAssetPositions: []*types.AssetPosition{}, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ firstSubaccountId: {}, }, @@ -2586,16 +2592,18 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { perpetuals: []perptypes.Perpetual{ constants.BtcUsd_SmallMarginRequirement, }, - perpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedPerpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedAssetPositions: []*types.AssetPosition{ - { - AssetId: uint32(0), - Quantums: dtypes.NewInt(-100), // 100 USDC + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: { + { + AssetId: uint32(0), + Quantums: dtypes.NewInt(-100), // 100 USDC + }, }, }, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ @@ -2628,16 +2636,63 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { perpetuals: []perptypes.Perpetual{ constants.BtcUsd_SmallMarginRequirement, }, - perpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedPerpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedAssetPositions: []*types.AssetPosition{ + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: { + { + AssetId: uint32(0), + Quantums: dtypes.NewInt(-100), // 100 USDC + }, + }, + }, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: { + { + AssetId: uint32(0), + Quantums: dtypes.NewInt(-100), // 100 USDC + }, + }, + }, + updates: []types.Update{ { - AssetId: uint32(0), - Quantums: dtypes.NewInt(-100), // 100 USDC + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + types.ModuleAddress.String(): 0, + }, + + updateType: types.Withdrawal, + }, + `withdrawals are not blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for a different + collateral pool`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: true, + expectedSuccessPerUpdate: []types.UpdateResult{types.Success}, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: { + { + AssetId: uint32(0), + Quantums: dtypes.NewInt(-100), // 100 USDC + }, }, }, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ @@ -2657,31 +2712,259 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { currentBlock: 100, negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.IsoCollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, + + updateType: types.Withdrawal, + }, + `withdrawals are blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for an isolated + perpetual collateral pool`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: false, + expectedSuccessPerUpdate: []types.UpdateResult{types.WithdrawalsAndTransfersBlocked}, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + constants.IsoUsd_IsolatedMarket, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: {}, + }, + updates: []types.Update{ + { + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.IsoCollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, + + updateType: types.Withdrawal, + }, + `withdrawals are blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for one isolated + perpetual collateral pool and negative TNC subaccount was never seen for the cross-perpetual + collateral pool, both of which are associated with subaccounts being updated`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: false, + expectedSuccessPerUpdate: []types.UpdateResult{ + types.WithdrawalsAndTransfersBlocked, + types.WithdrawalsAndTransfersBlocked, + }, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + constants.IsoUsd_IsolatedMarket, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: {}, + secondSubaccountId: {}, + }, + updates: []types.Update{ + { + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + { + SubaccountId: secondSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.IsoCollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, types.ModuleAddress.String(): 0, }, updateType: types.Withdrawal, }, + `withdrawals are blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for one isolated + perpetual collateral pool and negative TNC subaccount was seen for the cross-perpetual + collateral pool after WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + both of which are associated with subaccounts being updated`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: false, + expectedSuccessPerUpdate: []types.UpdateResult{ + types.WithdrawalsAndTransfersBlocked, + types.WithdrawalsAndTransfersBlocked, + }, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + constants.IsoUsd_IsolatedMarket, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: {}, + secondSubaccountId: {}, + }, + updates: []types.Update{ + { + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + { + SubaccountId: secondSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.IsoCollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + types.ModuleAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + }, + + updateType: types.Withdrawal, + }, + `withdrawals are blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for one isolated + perpetual collateral pool and negative TNC subaccount was never seen for another isolated + collateral pool, both of which are associated with subaccounts being updated`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: false, + expectedSuccessPerUpdate: []types.UpdateResult{ + types.WithdrawalsAndTransfersBlocked, + types.WithdrawalsAndTransfersBlocked, + }, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + constants.IsoUsd_IsolatedMarket, + constants.Iso2Usd_IsolatedMarket, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + secondSubaccountId: {&constants.PerpetualPosition_OneISO2Long}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + secondSubaccountId: {&constants.PerpetualPosition_OneISO2Long}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: {}, + secondSubaccountId: {}, + }, + updates: []types.Update{ + { + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + { + SubaccountId: secondSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.IsoCollateralPoolAddress.String(): 0, + constants.Iso2CollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, + + updateType: types.Withdrawal, + }, + `withdrawals are blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for one isolated + perpetual collateral pool and negative TNC subaccount was seen for another isolated perpetual + collateral pool after WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + both of which are associated with subaccounts being updated`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: false, + expectedSuccessPerUpdate: []types.UpdateResult{ + types.WithdrawalsAndTransfersBlocked, + types.WithdrawalsAndTransfersBlocked, + }, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + constants.IsoUsd_IsolatedMarket, + constants.Iso2Usd_IsolatedMarket, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + secondSubaccountId: {&constants.PerpetualPosition_OneISO2Long}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + secondSubaccountId: {&constants.PerpetualPosition_OneISO2Long}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: {}, + secondSubaccountId: {}, + }, + updates: []types.Update{ + { + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + { + SubaccountId: secondSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.IsoCollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + constants.Iso2CollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, + + updateType: types.Withdrawal, + }, "well-collateralized matches are not blocked if negative TNC subaccount was seen at current block": { - assetPositions: testutil.CreateUsdcAssetPosition(big.NewInt(25_000_000_000)), // $25,000 + assetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: testutil.CreateUsdcAssetPosition(big.NewInt(25_000_000_000)), // $25,000 + }, expectedQuoteBalance: big.NewInt(0), expectedSuccess: true, expectedSuccessPerUpdate: []types.UpdateResult{types.Success}, perpetuals: []perptypes.Perpetual{ constants.BtcUsd_NoMarginRequirement, }, - perpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedPerpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneAndHalfBTCLong, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneAndHalfBTCLong}, }, expectedUpdatedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ firstSubaccountId: { &constants.PerpetualPosition_OneAndHalfBTCLong, }, }, - expectedAssetPositions: []*types.AssetPosition{}, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ firstSubaccountId: { { @@ -2712,25 +2995,27 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, `well-collateralized matches are not blocked if current block is within WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS`: { - assetPositions: testutil.CreateUsdcAssetPosition(big.NewInt(25_000_000_000)), // $25,000 + assetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: testutil.CreateUsdcAssetPosition(big.NewInt(25_000_000_000)), // $25,000 + }, expectedQuoteBalance: big.NewInt(0), expectedSuccess: true, expectedSuccessPerUpdate: []types.UpdateResult{types.Success}, perpetuals: []perptypes.Perpetual{ constants.BtcUsd_NoMarginRequirement, }, - perpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedPerpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneAndHalfBTCLong, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneAndHalfBTCLong}, }, expectedUpdatedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ firstSubaccountId: { &constants.PerpetualPosition_OneAndHalfBTCLong, }, }, - expectedAssetPositions: []*types.AssetPosition{}, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ firstSubaccountId: { { @@ -2761,25 +3046,27 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { updateType: types.Match, }, "well-collateralized matches are not blocked if negative TNC subaccount was never seen": { - assetPositions: testutil.CreateUsdcAssetPosition(big.NewInt(25_000_000_000)), // $25,000 + assetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: testutil.CreateUsdcAssetPosition(big.NewInt(25_000_000_000)), // $25,000 + }, expectedQuoteBalance: big.NewInt(0), expectedSuccess: true, expectedSuccessPerUpdate: []types.UpdateResult{types.Success}, perpetuals: []perptypes.Perpetual{ constants.BtcUsd_NoMarginRequirement, }, - perpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneBTCLong, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, }, - expectedPerpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneAndHalfBTCLong, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneAndHalfBTCLong}, }, expectedUpdatedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ firstSubaccountId: { &constants.PerpetualPosition_OneAndHalfBTCLong, }, }, - expectedAssetPositions: []*types.AssetPosition{}, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ firstSubaccountId: { { @@ -2815,11 +3102,11 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { perpetuals: []perptypes.Perpetual{ constants.BtcUsd_SmallMarginRequirement, }, - perpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneHundredthBTCLong, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneHundredthBTCLong}, }, - expectedPerpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneHundredthBTCLong, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneHundredthBTCLong}, }, updates: []types.Update{ { @@ -2848,11 +3135,11 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { perpetuals: []perptypes.Perpetual{ constants.BtcUsd_SmallMarginRequirement, }, - perpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneHundredthBTCLong, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneHundredthBTCLong}, }, - expectedPerpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneHundredthBTCLong, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneHundredthBTCLong}, }, updates: []types.Update{ { @@ -2882,11 +3169,11 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { perpetuals: []perptypes.Perpetual{ constants.BtcUsd_SmallMarginRequirement, }, - perpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneHundredthBTCLong, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneHundredthBTCLong}, }, - expectedPerpetualPositions: []*types.PerpetualPosition{ - &constants.PerpetualPosition_OneHundredthBTCLong, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneHundredthBTCLong}, }, updates: []types.Update{ { @@ -2916,9 +3203,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.WithdrawalsAndTransfersBlocked, }, perpetuals: []perptypes.Perpetual{}, - perpetualPositions: []*types.PerpetualPosition{}, - expectedPerpetualPositions: []*types.PerpetualPosition{}, - expectedAssetPositions: []*types.AssetPosition{}, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ firstSubaccountId: {}, secondSubaccountId: {}, @@ -2940,7 +3227,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.ModuleAddress.String(): 100, }, - updateType: types.Withdrawal, + updateType: types.Transfer, }, `transfers are blocked if negative TNC subaccount was seen within WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS`: { @@ -2951,9 +3238,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.WithdrawalsAndTransfersBlocked, }, perpetuals: []perptypes.Perpetual{}, - perpetualPositions: []*types.PerpetualPosition{}, - expectedPerpetualPositions: []*types.PerpetualPosition{}, - expectedAssetPositions: []*types.AssetPosition{}, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ firstSubaccountId: {}, secondSubaccountId: {}, @@ -2976,7 +3263,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, - updateType: types.Withdrawal, + updateType: types.Transfer, }, `transfers are not blocked if negative TNC subaccount was seen after WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS`: { @@ -2987,9 +3274,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.Success, }, perpetuals: []perptypes.Perpetual{}, - perpetualPositions: []*types.PerpetualPosition{}, - expectedPerpetualPositions: []*types.PerpetualPosition{}, - expectedAssetPositions: []*types.AssetPosition{}, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ firstSubaccountId: {}, secondSubaccountId: {}, @@ -3012,7 +3299,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, }, - updateType: types.Withdrawal, + updateType: types.Transfer, }, "transfers are not blocked if negative TNC subaccount was never seen": { expectedQuoteBalance: big.NewInt(-100), @@ -3022,9 +3309,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.Success, }, perpetuals: []perptypes.Perpetual{}, - perpetualPositions: []*types.PerpetualPosition{}, - expectedPerpetualPositions: []*types.PerpetualPosition{}, - expectedAssetPositions: []*types.AssetPosition{}, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ firstSubaccountId: {}, secondSubaccountId: {}, @@ -3046,7 +3333,240 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.ModuleAddress.String(): 0, }, - updateType: types.Withdrawal, + updateType: types.Transfer, + }, + `transfers are not blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for a different + collateral pool from the ones associated with the subaccounts being updated`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: false, + expectedSuccessPerUpdate: []types.UpdateResult{ + types.NewlyUndercollateralized, + types.Success, + }, + perpetuals: []perptypes.Perpetual{ + constants.IsoUsd_IsolatedMarket, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + secondSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + secondSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: {}, + secondSubaccountId: {}, + }, + updates: []types.Update{ + { + SubaccountId: firstSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + { + SubaccountId: secondSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.Iso2CollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, + + updateType: types.Transfer, + }, + `transfers are blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for one isolated + perpetual collateral pool and negative TNC subaccount was never seen for the cross-perpetual + collateral pool, both of which are associated with subaccounts being updated`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: false, + expectedSuccessPerUpdate: []types.UpdateResult{ + types.WithdrawalsAndTransfersBlocked, + types.WithdrawalsAndTransfersBlocked, + }, + perpetuals: []perptypes.Perpetual{ + constants.IsoUsd_IsolatedMarket, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + secondSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + secondSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: {}, + secondSubaccountId: {}, + }, + updates: []types.Update{ + { + SubaccountId: firstSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + { + SubaccountId: secondSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.IsoCollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + types.ModuleAddress.String(): 0, + }, + + updateType: types.Transfer, + }, + `transferss are blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for one isolated + perpetual collateral pool and negative TNC subaccount was seen for the cross-perpetual + collateral pool after WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + both of which are associated with subaccounts being updated`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: false, + expectedSuccessPerUpdate: []types.UpdateResult{ + types.WithdrawalsAndTransfersBlocked, + types.WithdrawalsAndTransfersBlocked, + }, + perpetuals: []perptypes.Perpetual{ + constants.IsoUsd_IsolatedMarket, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + secondSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + secondSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: {}, + secondSubaccountId: {}, + }, + updates: []types.Update{ + { + SubaccountId: firstSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + { + SubaccountId: secondSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.IsoCollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + types.ModuleAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + }, + + updateType: types.Transfer, + }, + `transfers are blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for one isolated + perpetual collateral pool and negative TNC subaccount was never seen for another isolated perpetual + collateral pool, both of which are associated with subaccounts being updated`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: false, + expectedSuccessPerUpdate: []types.UpdateResult{ + types.WithdrawalsAndTransfersBlocked, + types.WithdrawalsAndTransfersBlocked, + }, + perpetuals: []perptypes.Perpetual{ + constants.IsoUsd_IsolatedMarket, + constants.Iso2Usd_IsolatedMarket, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + secondSubaccountId: {&constants.PerpetualPosition_OneISO2Long}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + secondSubaccountId: {&constants.PerpetualPosition_OneISO2Long}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: {}, + secondSubaccountId: {}, + }, + updates: []types.Update{ + { + SubaccountId: firstSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + { + SubaccountId: secondSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.IsoCollateralPoolAddress.String(): 0, + constants.Iso2CollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, + + updateType: types.Transfer, + }, + `transferss are blocked if negative TNC subaccount was seen within + WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS for one isolated + perpetual collateral pool and negative TNC subaccount was seen for another the cross-perpetual + collateral pool after WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + both of which are associated with subaccounts being updated`: { + expectedQuoteBalance: big.NewInt(-100), + expectedSuccess: false, + expectedSuccessPerUpdate: []types.UpdateResult{ + types.WithdrawalsAndTransfersBlocked, + types.WithdrawalsAndTransfersBlocked, + }, + perpetuals: []perptypes.Perpetual{ + constants.IsoUsd_IsolatedMarket, + constants.Iso2Usd_IsolatedMarket, + }, + perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + secondSubaccountId: {&constants.PerpetualPosition_OneISO2Long}, + }, + expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ + firstSubaccountId: {&constants.PerpetualPosition_OneISOLong}, + secondSubaccountId: {&constants.PerpetualPosition_OneISO2Long}, + }, + expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, + expectedUpdatedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{ + firstSubaccountId: {}, + secondSubaccountId: {}, + }, + updates: []types.Update{ + { + SubaccountId: firstSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), + }, + { + SubaccountId: secondSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), + }, + }, + msgSenderEnabled: true, + + currentBlock: 100, + negativeTncSubaccountSeenAtBlock: map[string]uint32{ + constants.IsoCollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, + constants.Iso2CollateralPoolAddress.String(): 100 - + types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, + }, + + updateType: types.Transfer, }, } @@ -3110,16 +3630,28 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { } subaccounts := createNSubaccount(keeper, ctx, 2, big.NewInt(1_000)) - subaccounts[0].PerpetualPositions = tc.perpetualPositions - subaccounts[0].AssetPositions = tc.assetPositions - keeper.SetSubaccount(ctx, subaccounts[0]) - keeper.SetSubaccount(ctx, subaccounts[1]) + for _, subaccount := range subaccounts { + if perpetualPositions, exists := tc.perpetualPositions[*subaccount.Id]; exists { + subaccount.PerpetualPositions = perpetualPositions + } else { + subaccount.PerpetualPositions = []*types.PerpetualPosition{} + } + if assetPositions, exists := tc.assetPositions[*subaccount.Id]; exists { + subaccount.AssetPositions = assetPositions + } else { + subaccount.AssetPositions = []*types.AssetPosition{} + } + keeper.SetSubaccount(ctx, subaccount) + } subaccountId := *subaccounts[0].Id // Set the negative TNC subaccount seen at block in state if it's greater than 0. for collateralPoolAddress, negativeTncSubaccountSeenAtBlock := range tc.negativeTncSubaccountSeenAtBlock { if negativeTncSubaccountSeenAtBlock != 0 { - keeper.SetNegativeTncSubaccountSeenAtBlock(ctx, sdk.MustAccAddressFromBech32(collateralPoolAddress), negativeTncSubaccountSeenAtBlock) + keeper.SetNegativeTncSubaccountSeenAtBlock( + ctx, sdk.MustAccAddressFromBech32(collateralPoolAddress), + negativeTncSubaccountSeenAtBlock, + ) } } @@ -3163,14 +3695,19 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { ) } - newSubaccount := keeper.GetSubaccount(ctx, subaccountId) - require.Equal(t, len(tc.expectedPerpetualPositions), len(newSubaccount.PerpetualPositions)) - for i, ep := range tc.expectedPerpetualPositions { - require.Equal(t, *ep, *newSubaccount.PerpetualPositions[i]) + for subaccountIdToCheck, expectedPerpetualPositions := range tc.expectedPerpetualPositions { + newSubaccount := keeper.GetSubaccount(ctx, subaccountIdToCheck) + require.Equal(t, len(expectedPerpetualPositions), len(newSubaccount.PerpetualPositions)) + for i, ep := range expectedPerpetualPositions { + require.Equal(t, *ep, *newSubaccount.PerpetualPositions[i]) + } } - require.Equal(t, len(tc.expectedAssetPositions), len(newSubaccount.AssetPositions)) - for i, ep := range tc.expectedAssetPositions { - require.Equal(t, *ep, *newSubaccount.AssetPositions[i]) + for subaccountIdToCheck, expectedAssetPositions := range tc.expectedAssetPositions { + newSubaccount := keeper.GetSubaccount(ctx, subaccountIdToCheck) + require.Equal(t, len(expectedAssetPositions), len(newSubaccount.AssetPositions)) + for i, ap := range expectedAssetPositions { + require.Equal(t, *ap, *newSubaccount.AssetPositions[i]) + } } }) } From 38bdcfa907411085d4bbf413d796c21fcb97d820 Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:56:06 -0600 Subject: [PATCH 05/16] Fix protos. --- .../dydxprotocol/subaccounts/query.lcd.ts | 12 +++++-- .../subaccounts/query.rpc.Query.ts | 6 ++-- .../codegen/dydxprotocol/subaccounts/query.ts | 31 ++++++++++++++----- proto/dydxprotocol/subaccounts/query.proto | 7 +++-- 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.lcd.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.lcd.ts index 93d034a144..edfa4c2775 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.lcd.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.lcd.ts @@ -42,9 +42,17 @@ export class LCDQueryClient { if so which block they are re-enabled on. */ - async getWithdrawalAndTransfersBlockedInfo(_params: QueryGetWithdrawalAndTransfersBlockedInfoRequest = {}): Promise { + async getWithdrawalAndTransfersBlockedInfo(params: QueryGetWithdrawalAndTransfersBlockedInfoRequest): Promise { + const options: any = { + params: {} + }; + + if (typeof params?.collateralPoolAddress !== "undefined") { + options.params.collateral_pool_address = params.collateralPoolAddress; + } + const endpoint = `dydxprotocol/subaccounts/withdrawals_and_transfers_blocked_info`; - return await this.req.get(endpoint); + return await this.req.get(endpoint, options); } } \ No newline at end of file diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.rpc.Query.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.rpc.Query.ts index 41f65d7652..1e76701fcf 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.rpc.Query.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.rpc.Query.ts @@ -15,7 +15,7 @@ export interface Query { * if so which block they are re-enabled on. */ - getWithdrawalAndTransfersBlockedInfo(request?: QueryGetWithdrawalAndTransfersBlockedInfoRequest): Promise; + getWithdrawalAndTransfersBlockedInfo(request: QueryGetWithdrawalAndTransfersBlockedInfoRequest): Promise; } export class QueryClientImpl implements Query { private readonly rpc: Rpc; @@ -41,7 +41,7 @@ export class QueryClientImpl implements Query { return promise.then(data => QuerySubaccountAllResponse.decode(new _m0.Reader(data))); } - getWithdrawalAndTransfersBlockedInfo(request: QueryGetWithdrawalAndTransfersBlockedInfoRequest = {}): Promise { + getWithdrawalAndTransfersBlockedInfo(request: QueryGetWithdrawalAndTransfersBlockedInfoRequest): Promise { const data = QueryGetWithdrawalAndTransfersBlockedInfoRequest.encode(request).finish(); const promise = this.rpc.request("dydxprotocol.subaccounts.Query", "GetWithdrawalAndTransfersBlockedInfo", data); return promise.then(data => QueryGetWithdrawalAndTransfersBlockedInfoResponse.decode(new _m0.Reader(data))); @@ -60,7 +60,7 @@ export const createRpcQueryExtension = (base: QueryClient) => { return queryService.subaccountAll(request); }, - getWithdrawalAndTransfersBlockedInfo(request?: QueryGetWithdrawalAndTransfersBlockedInfoRequest): Promise { + getWithdrawalAndTransfersBlockedInfo(request: QueryGetWithdrawalAndTransfersBlockedInfoRequest): Promise { return queryService.getWithdrawalAndTransfersBlockedInfo(request); } diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.ts index 0b1d182ed9..d7ac251143 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.ts @@ -48,16 +48,22 @@ export interface QuerySubaccountAllResponseSDKType { } /** * QueryGetWithdrawalAndTransfersBlockedInfoRequest is a request type for - * fetching information about whether withdrawals and transfers are blocked. + * fetching information about whether withdrawals and transfers are blocked for + * a specific collateral pool. */ -export interface QueryGetWithdrawalAndTransfersBlockedInfoRequest {} +export interface QueryGetWithdrawalAndTransfersBlockedInfoRequest { + collateralPoolAddress: string; +} /** * QueryGetWithdrawalAndTransfersBlockedInfoRequest is a request type for - * fetching information about whether withdrawals and transfers are blocked. + * fetching information about whether withdrawals and transfers are blocked for + * a specific collateral pool. */ -export interface QueryGetWithdrawalAndTransfersBlockedInfoRequestSDKType {} +export interface QueryGetWithdrawalAndTransfersBlockedInfoRequestSDKType { + collateral_pool_address: string; +} /** * QueryGetWithdrawalAndTransfersBlockedInfoRequest is a response type for * fetching information about whether withdrawals and transfers are blocked. @@ -280,11 +286,17 @@ export const QuerySubaccountAllResponse = { }; function createBaseQueryGetWithdrawalAndTransfersBlockedInfoRequest(): QueryGetWithdrawalAndTransfersBlockedInfoRequest { - return {}; + return { + collateralPoolAddress: "" + }; } export const QueryGetWithdrawalAndTransfersBlockedInfoRequest = { - encode(_: QueryGetWithdrawalAndTransfersBlockedInfoRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + encode(message: QueryGetWithdrawalAndTransfersBlockedInfoRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.collateralPoolAddress !== "") { + writer.uint32(10).string(message.collateralPoolAddress); + } + return writer; }, @@ -297,6 +309,10 @@ export const QueryGetWithdrawalAndTransfersBlockedInfoRequest = { const tag = reader.uint32(); switch (tag >>> 3) { + case 1: + message.collateralPoolAddress = reader.string(); + break; + default: reader.skipType(tag & 7); break; @@ -306,8 +322,9 @@ export const QueryGetWithdrawalAndTransfersBlockedInfoRequest = { return message; }, - fromPartial(_: DeepPartial): QueryGetWithdrawalAndTransfersBlockedInfoRequest { + fromPartial(object: DeepPartial): QueryGetWithdrawalAndTransfersBlockedInfoRequest { const message = createBaseQueryGetWithdrawalAndTransfersBlockedInfoRequest(); + message.collateralPoolAddress = object.collateralPoolAddress ?? ""; return message; } diff --git a/proto/dydxprotocol/subaccounts/query.proto b/proto/dydxprotocol/subaccounts/query.proto index 9b1d2c789a..2a998d32b2 100644 --- a/proto/dydxprotocol/subaccounts/query.proto +++ b/proto/dydxprotocol/subaccounts/query.proto @@ -56,10 +56,11 @@ message QuerySubaccountAllResponse { } // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a request type for -// fetching information about whether withdrawals and transfers are blocked for a specific -// collateral pool. +// fetching information about whether withdrawals and transfers are blocked for +// a specific collateral pool. message QueryGetWithdrawalAndTransfersBlockedInfoRequest { - string collateral_pool_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + string collateral_pool_address = 1 + [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; } // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a response type for From 997764911df4898627d880c71af9ad31dc689323 Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Wed, 20 Mar 2024 11:04:24 -0600 Subject: [PATCH 06/16] Regen proto. --- protocol/x/subaccounts/types/query.pb.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocol/x/subaccounts/types/query.pb.go b/protocol/x/subaccounts/types/query.pb.go index 3c5ad19cb4..3927ca4817 100644 --- a/protocol/x/subaccounts/types/query.pb.go +++ b/protocol/x/subaccounts/types/query.pb.go @@ -228,8 +228,8 @@ func (m *QuerySubaccountAllResponse) GetPagination() *query.PageResponse { } // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a request type for -// fetching information about whether withdrawals and transfers are blocked for a specific -// collateral pool. +// fetching information about whether withdrawals and transfers are blocked for +// a specific collateral pool. type QueryGetWithdrawalAndTransfersBlockedInfoRequest struct { CollateralPoolAddress string `protobuf:"bytes,1,opt,name=collateral_pool_address,json=collateralPoolAddress,proto3" json:"collateral_pool_address,omitempty"` } From 4f37c5e21cd82996167aaaf91e3309caf5b4b8db Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Wed, 20 Mar 2024 12:15:19 -0600 Subject: [PATCH 07/16] Update x/clob unit tests. --- protocol/testutil/constants/clob_pair.go | 36 ++++ protocol/testutil/constants/subaccounts.go | 32 +++ .../x/clob/keeper/process_operations_test.go | 185 ++++++++++++++++-- 3 files changed, 236 insertions(+), 17 deletions(-) diff --git a/protocol/testutil/constants/clob_pair.go b/protocol/testutil/constants/clob_pair.go index 10b42e79bf..7388f77918 100644 --- a/protocol/testutil/constants/clob_pair.go +++ b/protocol/testutil/constants/clob_pair.go @@ -127,4 +127,40 @@ var ( QuantumConversionExponent: -8, Status: clobtypes.ClobPair_STATUS_PAUSED, } + ClobPair_Iso = clobtypes.ClobPair{ + Id: 3, + Metadata: &clobtypes.ClobPair_PerpetualClobMetadata{ + PerpetualClobMetadata: &clobtypes.PerpetualClobMetadata{ + PerpetualId: 3, + }, + }, + StepBaseQuantums: 5, + SubticksPerTick: 5, + QuantumConversionExponent: -8, + Status: clobtypes.ClobPair_STATUS_ACTIVE, + } + ClobPair_Iso_Final_Settlement = clobtypes.ClobPair{ + Id: 3, + Metadata: &clobtypes.ClobPair_PerpetualClobMetadata{ + PerpetualClobMetadata: &clobtypes.PerpetualClobMetadata{ + PerpetualId: 3, + }, + }, + StepBaseQuantums: 5, + SubticksPerTick: 5, + QuantumConversionExponent: -8, + Status: clobtypes.ClobPair_STATUS_FINAL_SETTLEMENT, + } + ClobPair_Iso2 = clobtypes.ClobPair{ + Id: 4, + Metadata: &clobtypes.ClobPair_PerpetualClobMetadata{ + PerpetualClobMetadata: &clobtypes.PerpetualClobMetadata{ + PerpetualId: 4, + }, + }, + StepBaseQuantums: 5, + SubticksPerTick: 5, + QuantumConversionExponent: -8, + Status: clobtypes.ClobPair_STATUS_ACTIVE, + } ) diff --git a/protocol/testutil/constants/subaccounts.go b/protocol/testutil/constants/subaccounts.go index a0e125dcac..d7c2ee5db5 100644 --- a/protocol/testutil/constants/subaccounts.go +++ b/protocol/testutil/constants/subaccounts.go @@ -236,6 +236,22 @@ var ( }, }, } + Carl_Num0_1ISO_Short_49USD = satypes.Subaccount{ + Id: &Carl_Num0, + AssetPositions: []*satypes.AssetPosition{ + { + AssetId: 0, + Quantums: dtypes.NewInt(49_000_000), // $49 + }, + }, + PerpetualPositions: []*satypes.PerpetualPosition{ + { + PerpetualId: 3, + Quantums: dtypes.NewInt(-1_000_000_000), // -1 ISO + FundingIndex: dtypes.NewInt(0), + }, + }, + } Carl_Num0_599USD = satypes.Subaccount{ Id: &Carl_Num0, AssetPositions: []*satypes.AssetPosition{ @@ -463,6 +479,22 @@ var ( }, }, } + Dave_Num0_1ISO2_Short_499USD = satypes.Subaccount{ + Id: &Dave_Num0, + AssetPositions: []*satypes.AssetPosition{ + { + AssetId: 0, + Quantums: dtypes.NewInt(499_000_000), // $499 + }, + }, + PerpetualPositions: []*satypes.PerpetualPosition{ + { + PerpetualId: 4, + Quantums: dtypes.NewInt(-10_000_000), // -1 ISO2 + FundingIndex: dtypes.NewInt(0), + }, + }, + } Dave_Num0_599USD = satypes.Subaccount{ Id: &Dave_Num0, AssetPositions: []*satypes.AssetPosition{ diff --git a/protocol/x/clob/keeper/process_operations_test.go b/protocol/x/clob/keeper/process_operations_test.go index 3a257816cf..5ac3fe8c5a 100644 --- a/protocol/x/clob/keeper/process_operations_test.go +++ b/protocol/x/clob/keeper/process_operations_test.go @@ -66,7 +66,7 @@ type processProposerOperationsTestCase struct { expectedQuoteBalances map[satypes.SubaccountId]int64 expectedPerpetualPositions map[satypes.SubaccountId][]*satypes.PerpetualPosition expectedSubaccountLiquidationInfo map[satypes.SubaccountId]types.SubaccountLiquidationInfo - expectedNegativeTncSubaccountSeen bool + expectedNegativeTncSubaccountSeen map[string]bool expectedError error expectedPanics string } @@ -957,7 +957,9 @@ func TestProcessProposerOperations(t *testing.T) { expectedPerpetualPositions: map[satypes.SubaccountId][]*satypes.PerpetualPosition{ constants.Carl_Num0: constants.Carl_Num0_1BTC_Short_50499USD.GetPerpetualPositions(), }, - expectedNegativeTncSubaccountSeen: true, + expectedNegativeTncSubaccountSeen: map[string]bool{ + satypes.ModuleAddress.String(): true, + }, }, "Zero-fill deleveraging succeeds when the account is negative TNC and has a position in final settlement" + " market. It updates the last negative TNC subaccount seen block number in state": { @@ -996,8 +998,9 @@ func TestProcessProposerOperations(t *testing.T) { constants.Carl_Num0: constants.Carl_Num0_1BTC_Short_50499USD.GetPerpetualPositions(), constants.Dave_Num0: constants.Dave_Num0_1BTC_Long_50000USD.GetPerpetualPositions(), }, - - expectedNegativeTncSubaccountSeen: true, + expectedNegativeTncSubaccountSeen: map[string]bool{ + satypes.ModuleAddress.String(): true, + }, }, "Zero-fill deleveraging succeeds when there's multiple zero-fill deleveraging events for the same subaccount " + "and perpetual ID": { @@ -1041,7 +1044,9 @@ func TestProcessProposerOperations(t *testing.T) { expectedPerpetualPositions: map[satypes.SubaccountId][]*satypes.PerpetualPosition{ constants.Carl_Num0: constants.Carl_Num0_1BTC_Short_50499USD.GetPerpetualPositions(), }, - expectedNegativeTncSubaccountSeen: true, + expectedNegativeTncSubaccountSeen: map[string]bool{ + satypes.ModuleAddress.String(): true, + }, }, "Zero-fill deleverage succeeds after the same subaccount is partially deleveraged": { perpetuals: []*perptypes.Perpetual{ @@ -1103,7 +1108,151 @@ func TestProcessProposerOperations(t *testing.T) { }, }, }, - expectedNegativeTncSubaccountSeen: true, + expectedNegativeTncSubaccountSeen: map[string]bool{ + satypes.ModuleAddress.String(): true, + }, + }, + "Zero-fill deleveraging succeeds when the account is negative TNC and updates the last negative TNC subaccount " + + "seen block number in state for an isolated perpetual collateral pool if the subaccount is isolated to the " + + "isolated perpetual": { + perpetuals: []*perptypes.Perpetual{ + &constants.IsoUsd_IsolatedMarket, + }, + perpetualFeeParams: &constants.PerpetualFeeParams, + clobPairs: []types.ClobPair{ + constants.ClobPair_Iso, + }, + subaccounts: []satypes.Subaccount{ + // deleverageable since TNC = -$1 + constants.Carl_Num0_1ISO_Short_49USD, + }, + marketIdToOraclePriceOverride: map[uint32]uint64{ + constants.IsoUsd_IsolatedMarket.Params.MarketId: 5_000_000_000, // $50 / ISO + }, + rawOperations: []types.OperationRaw{ + clobtest.NewMatchOperationRawFromPerpetualDeleveragingLiquidation( + types.MatchPerpetualDeleveraging{ + Liquidated: constants.Carl_Num0, + PerpetualId: 3, + Fills: []types.MatchPerpetualDeleveraging_Fill{}, + }, + ), + }, + + expectedProcessProposerMatchesEvents: types.ProcessProposerMatchesEvents{ + BlockHeight: blockHeight, + }, + expectedQuoteBalances: map[satypes.SubaccountId]int64{ + constants.Carl_Num0: constants.Carl_Num0_1ISO_Short_49USD.GetUsdcPosition().Int64(), + }, + expectedPerpetualPositions: map[satypes.SubaccountId][]*satypes.PerpetualPosition{ + constants.Carl_Num0: constants.Carl_Num0_1ISO_Short_49USD.GetPerpetualPositions(), + }, + expectedNegativeTncSubaccountSeen: map[string]bool{ + satypes.ModuleAddress.String(): false, + constants.IsoCollateralPoolAddress.String(): true, + }, + }, + "Zero-fill deleveraging succeeds when the account is negative TNC and has a position in final settlement" + + " market. It updates the last negative TNC subaccount seen block number in state for an isolated perpetual" + + " collateral pool if the subaccount is isolated to the isolated perpetual": { + perpetuals: []*perptypes.Perpetual{ + &constants.BtcUsd_100PercentMarginRequirement, + &constants.IsoUsd_IsolatedMarket, + }, + perpetualFeeParams: &constants.PerpetualFeeParams, + clobPairs: []types.ClobPair{ + constants.ClobPair_Btc, + constants.ClobPair_Iso_Final_Settlement, + }, + subaccounts: []satypes.Subaccount{ + // deleveragable: TNC = -$1. + constants.Carl_Num0_1ISO_Short_49USD, + constants.Dave_Num0_1BTC_Long_50000USD, + }, + marketIdToOraclePriceOverride: map[uint32]uint64{ + constants.IsoUsd_IsolatedMarket.Params.MarketId: 5_000_000_000, // $50 / ISO + }, + rawOperations: []types.OperationRaw{ + clobtest.NewMatchOperationRawFromPerpetualDeleveragingLiquidation( + types.MatchPerpetualDeleveraging{ + Liquidated: constants.Carl_Num0, + PerpetualId: 3, + Fills: []types.MatchPerpetualDeleveraging_Fill{}, + }, + ), + }, + expectedProcessProposerMatchesEvents: types.ProcessProposerMatchesEvents{ + BlockHeight: blockHeight, + }, + expectedQuoteBalances: map[satypes.SubaccountId]int64{ + constants.Carl_Num0: constants.Carl_Num0_1ISO_Short_49USD.GetUsdcPosition().Int64(), + constants.Dave_Num0: constants.Dave_Num0_1BTC_Long_50000USD.GetUsdcPosition().Int64(), + }, + expectedPerpetualPositions: map[satypes.SubaccountId][]*satypes.PerpetualPosition{ + constants.Carl_Num0: constants.Carl_Num0_1ISO_Short_49USD.GetPerpetualPositions(), + constants.Dave_Num0: constants.Dave_Num0_1BTC_Long_50000USD.GetPerpetualPositions(), + }, + expectedNegativeTncSubaccountSeen: map[string]bool{ + satypes.ModuleAddress.String(): false, + constants.IsoCollateralPoolAddress.String(): true, + }, + }, + "Zero-fill deleveraging succeeds when there's multiple zero-fill deleveraging events for the different subaccount " + + "and perpetual ID. It updates the last negative TNC subaccount seen block number in state for both isolated " + + "perpetual collateral pools if the subaccounts are isolated to different isolated perpetuals": { + perpetuals: []*perptypes.Perpetual{ + &constants.IsoUsd_IsolatedMarket, + &constants.Iso2Usd_IsolatedMarket, + }, + perpetualFeeParams: &constants.PerpetualFeeParams, + clobPairs: []types.ClobPair{ + constants.ClobPair_Iso, + constants.ClobPair_Iso2, + }, + subaccounts: []satypes.Subaccount{ + // deleverageable since TNC = -$1 + constants.Carl_Num0_1ISO_Short_49USD, + // deleverageable since TNC = -$1 + constants.Dave_Num0_1ISO2_Short_499USD, + }, + marketIdToOraclePriceOverride: map[uint32]uint64{ + constants.IsoUsd_IsolatedMarket.Params.MarketId: 5_000_000_000, // $50 / ISO + constants.Iso2Usd_IsolatedMarket.Params.MarketId: 5_000_000_000, // $500 / ISO2 + }, + rawOperations: []types.OperationRaw{ + clobtest.NewMatchOperationRawFromPerpetualDeleveragingLiquidation( + types.MatchPerpetualDeleveraging{ + Liquidated: constants.Carl_Num0, + PerpetualId: 3, + Fills: []types.MatchPerpetualDeleveraging_Fill{}, + }, + ), + clobtest.NewMatchOperationRawFromPerpetualDeleveragingLiquidation( + types.MatchPerpetualDeleveraging{ + Liquidated: constants.Dave_Num0, + PerpetualId: 4, + Fills: []types.MatchPerpetualDeleveraging_Fill{}, + }, + ), + }, + + expectedProcessProposerMatchesEvents: types.ProcessProposerMatchesEvents{ + BlockHeight: blockHeight, + }, + expectedQuoteBalances: map[satypes.SubaccountId]int64{ + constants.Carl_Num0: constants.Carl_Num0_1ISO_Short_49USD.GetUsdcPosition().Int64(), + constants.Dave_Num0: constants.Dave_Num0_1ISO2_Short_499USD.GetUsdcPosition().Int64(), + }, + expectedPerpetualPositions: map[satypes.SubaccountId][]*satypes.PerpetualPosition{ + constants.Carl_Num0: constants.Carl_Num0_1ISO_Short_49USD.GetPerpetualPositions(), + constants.Dave_Num0: constants.Dave_Num0_1ISO2_Short_499USD.GetPerpetualPositions(), + }, + expectedNegativeTncSubaccountSeen: map[string]bool{ + satypes.ModuleAddress.String(): false, + constants.IsoCollateralPoolAddress.String(): true, + constants.Iso2CollateralPoolAddress.String(): true, + }, }, "Succeeds order removal operations with previous stateful orders": { perpetuals: []*perptypes.Perpetual{ @@ -2396,17 +2545,19 @@ func runProcessProposerOperationsTestCase( require.Equal(t, fillAmount, actualFillAmount) } - // Verify the negative TNC subaccount seen block. - seenNegativeTncSubaccountBlock, exists := ks.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock( - ctx, - satypes.ModuleAddress, - ) - if tc.expectedNegativeTncSubaccountSeen { - require.True(t, exists) - require.Equal(t, uint32(ctx.BlockHeight()), seenNegativeTncSubaccountBlock) - } else { - require.False(t, exists) - require.Equal(t, uint32(0), seenNegativeTncSubaccountBlock) + for collateralPoolAddress, expectedNegativeTncSubaccountSeen := range tc.expectedNegativeTncSubaccountSeen { + // Verify the negative TNC subaccount seen block. + seenNegativeTncSubaccountBlock, exists := ks.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock( + ctx, + sdk.MustAccAddressFromBech32(collateralPoolAddress), + ) + if expectedNegativeTncSubaccountSeen { + require.True(t, exists) + require.Equal(t, uint32(ctx.BlockHeight()), seenNegativeTncSubaccountBlock) + } else { + require.False(t, exists) + require.Equal(t, uint32(0), seenNegativeTncSubaccountBlock) + } } mockIndexerEventManager.AssertExpectations(t) From 715dbe03943fbad224e1ee334df027f8917bb702 Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Thu, 21 Mar 2024 21:12:04 -0400 Subject: [PATCH 08/16] Address nits. --- protocol/x/clob/keeper/process_operations.go | 6 +- protocol/x/clob/types/expected_keepers.go | 2 +- ...hdrawal_and_transfers_blocked_info_test.go | 37 +++- .../keeper/negative_tnc_subaccount.go | 24 ++- .../keeper/negative_tnc_subaccount_test.go | 44 +++-- .../x/subaccounts/keeper/subaccount_test.go | 164 ++++++++++-------- 6 files changed, 169 insertions(+), 108 deletions(-) diff --git a/protocol/x/clob/keeper/process_operations.go b/protocol/x/clob/keeper/process_operations.go index 818b0412c4..a99c8b6c0e 100644 --- a/protocol/x/clob/keeper/process_operations.go +++ b/protocol/x/clob/keeper/process_operations.go @@ -694,13 +694,9 @@ func (k Keeper) PersistMatchDeleveragingToState( metrics.GetLabelForBoolValue(metrics.IsLong, position.GetIsLong()), metrics.GetLabelForBoolValue(metrics.DeliverTx, true), ) - collateralPoolAddress, err := k.subaccountsKeeper.GetCollateralPoolFromPerpetualId(ctx, perpetualId) - if err != nil { - return err - } k.subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock( ctx, - collateralPoolAddress, + perpetualId, lib.MustConvertIntegerToUint32(ctx.BlockHeight()), ) return nil diff --git a/protocol/x/clob/types/expected_keepers.go b/protocol/x/clob/types/expected_keepers.go index 662c989d8f..469a47f767 100644 --- a/protocol/x/clob/types/expected_keepers.go +++ b/protocol/x/clob/types/expected_keepers.go @@ -61,7 +61,7 @@ type SubaccountsKeeper interface { ) SetNegativeTncSubaccountSeenAtBlock( ctx sdk.Context, - collateralPoolAddr sdk.AccAddress, + perpetualId uint32, blockHeight uint32, ) TransferFeesToFeeCollectorModule(ctx sdk.Context, assetId uint32, amount *big.Int, perpetualId uint32) error diff --git a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go index ef704aabd7..1f2d132e37 100644 --- a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go +++ b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go @@ -51,7 +51,11 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { `Negative TNC subaccount seen in state returns withdrawals and transfers unblocked after the delay`: { setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 7) + sk.SetNegativeTncSubaccountSeenAtBlock( + ctx, + constants.BtcUsd_NoMarginRequirement.Params.Id, + 7, + ) }, request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ @@ -66,9 +70,13 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, }, `Negative TNC subaccount seen in state returns withdrawals and transfers unblocked - after the delay (for isolated collateral pool address)`: { + after the delay (for isolated perpetual)`: { setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock(ctx, constants.IsoCollateralPoolAddress, 5) + sk.SetNegativeTncSubaccountSeenAtBlock( + ctx, + constants.IsoUsd_IsolatedMarket.Params.Id, + 5, + ) }, request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ @@ -120,7 +128,11 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { `Negative TNC subaccount and chain outage seen in state returns withdrawals and transfers unblocked after the max block number + delay (negative TNC subaccount block greater)`: { setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 27) + sk.SetNegativeTncSubaccountSeenAtBlock( + ctx, + constants.BtcUsd_NoMarginRequirement.Params.Id, + 27, + ) bk.SetAllDowntimeInfo( ctx, &blocktimetypes.AllDowntimeInfo{ @@ -157,7 +169,11 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { `Negative TNC subaccount and chain outage seen in state returns withdrawals and transfers unblocked after the max block number + delay (chain outage block greater)`: { setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 37) + sk.SetNegativeTncSubaccountSeenAtBlock( + ctx, + constants.BtcUsd_NoMarginRequirement.Params.Id, + 37, + ) bk.SetAllDowntimeInfo( ctx, &blocktimetypes.AllDowntimeInfo{ @@ -194,7 +210,11 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { `Negative TNC subaccount and chain outage seen in state returns withdrawals and transfers unblocked after the max block number + delay (both blocks equal)`: { setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 3) + sk.SetNegativeTncSubaccountSeenAtBlock( + ctx, + constants.BtcUsd_NoMarginRequirement.Params.Id, + 3, + ) bk.SetAllDowntimeInfo( ctx, &blocktimetypes.AllDowntimeInfo{ @@ -230,7 +250,10 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, } { t.Run(testName, func(t *testing.T) { - ctx, keeper, _, _, _, _, _, blocktimeKeeper, _ := keepertest.SubaccountsKeepers(t, true) + ctx, keeper, pricesKeeper, perpetualsKeeper, _, _, _, blocktimeKeeper, _ := keepertest.SubaccountsKeepers(t, true) + keepertest.CreateTestMarkets(t, ctx, pricesKeeper) + keepertest.CreateTestLiquidityTiers(t, ctx, perpetualsKeeper) + keepertest.CreateTestPerpetuals(t, ctx, perpetualsKeeper) tc.setup(ctx, *keeper, *blocktimeKeeper) response, err := keeper.GetWithdrawalAndTransfersBlockedInfo(ctx, tc.request) if tc.err != nil { diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go index 121852cdb8..53f055c250 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go @@ -14,13 +14,13 @@ import ( // seen in state for the given collateral pool address and a boolean for whether it exists in state. func (k Keeper) GetNegativeTncSubaccountSeenAtBlock( ctx sdk.Context, - collateralPoolAddr sdk.AccAddress, + collateralPoolAddress sdk.AccAddress, ) (uint32, bool) { store := prefix.NewStore( ctx.KVStore(k.storeKey), []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix), ) - return k.getNegativeTncSubaccountSeenAtBlock(store, collateralPoolAddr) + return k.getNegativeTncSubaccountSeenAtBlock(store, collateralPoolAddress) } // getNegativeTncSubaccountSeenAtBlock is a helper function that takes a store and returns the last @@ -28,10 +28,10 @@ func (k Keeper) GetNegativeTncSubaccountSeenAtBlock( // and a boolean for whether it exists in state. func (k Keeper) getNegativeTncSubaccountSeenAtBlock( store storetypes.KVStore, - collateralPoolAddr sdk.AccAddress, + collateralPoolAddress sdk.AccAddress, ) (uint32, bool) { b := store.Get( - collateralPoolAddr, + collateralPoolAddress, ) blockHeight := gogotypes.UInt32Value{Value: 0} exists := false @@ -48,7 +48,7 @@ func (k Keeper) getNegativeTncSubaccountSeenAtBlock( // This function will panic if the old block height is greater than the new block height. func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( ctx sdk.Context, - collateralPoolAddr sdk.AccAddress, + perpetualId uint32, blockHeight uint32, ) { store := prefix.NewStore( @@ -56,8 +56,18 @@ func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix), ) + collateralPoolAddress, err := k.GetCollateralPoolFromPerpetualId(ctx, perpetualId) + if err != nil { + panic( + fmt.Sprintf( + "SetNegativeTncSubaccountSeenAtBlock: non-existent perpetual id %d", + perpetualId, + ), + ) + } + // Panic if the stored block height value exists and is greater than the new block height value. - currentValue, exists := k.getNegativeTncSubaccountSeenAtBlock(store, collateralPoolAddr) + currentValue, exists := k.getNegativeTncSubaccountSeenAtBlock(store, collateralPoolAddress) if exists && blockHeight < currentValue { panic( fmt.Sprintf( @@ -70,7 +80,7 @@ func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( blockHeightValue := gogotypes.UInt32Value{Value: blockHeight} store.Set( - collateralPoolAddr.Bytes(), + collateralPoolAddress.Bytes(), k.cdc.MustMarshal(&blockHeightValue), ) } diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go index b303e17188..6e1494d34f 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go @@ -13,6 +13,11 @@ import ( ) func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { + testPerpetualIds := []uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id, + constants.Iso2Usd_IsolatedMarket.Params.Id, + constants.BtcUsd_NoMarginRequirement.Params.Id, + } testCollateralPoolAddresses := []sdk.AccAddress{ constants.IsoCollateralPoolAddress, constants.Iso2CollateralPoolAddress, @@ -42,8 +47,8 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, "Block height can be updated": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - for _, collateralPoolAddr := range testCollateralPoolAddresses { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 1) + for i, collateralPoolAddr := range testCollateralPoolAddresses { + k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 1) block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) require.True(t, exists) require.Equal( @@ -62,8 +67,8 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, "Block height can be updated more than once": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - for _, collateralPoolAddr := range testCollateralPoolAddresses { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 1) + for i, collateralPoolAddr := range testCollateralPoolAddresses { + k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 1) block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) require.True(t, exists) require.Equal( @@ -72,7 +77,7 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 2) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 2) block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) require.True(t, exists) require.Equal( @@ -81,7 +86,7 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 3) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 3) block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) require.True(t, exists) require.Equal( @@ -90,7 +95,7 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 10) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 10) block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) require.True(t, exists) require.Equal( @@ -111,8 +116,8 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, "Block height can be updated to same block height": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - for _, collateralPoolAddr := range testCollateralPoolAddresses { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 0) + for i, collateralPoolAddr := range testCollateralPoolAddresses { + k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 0) block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) require.True(t, exists) require.Equal( @@ -121,7 +126,7 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, 0) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 0) block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) require.True(t, exists) require.Equal( @@ -143,7 +148,7 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { "Block height can be updated to different block heights for each collateral pool address": { setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { for i, collateralPoolAddr := range testCollateralPoolAddresses { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, uint32(i)) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], uint32(i)) block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) require.True(t, exists) require.Equal( @@ -152,7 +157,7 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr, uint32(2*i+1)) + k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], uint32(2*i+1)) block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) require.True(t, exists) require.Equal( @@ -176,7 +181,10 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { // Setup keeper state and test parameters. - ctx, subaccountsKeeper, _, _, _, _, _, _, _ := keepertest.SubaccountsKeepers(t, true) + ctx, subaccountsKeeper, pricesKeeper, perpetualsKeeper, _, _, _, _, _ := keepertest.SubaccountsKeepers(t, true) + keepertest.CreateTestMarkets(t, ctx, pricesKeeper) + keepertest.CreateTestLiquidityTiers(t, ctx, perpetualsKeeper) + keepertest.CreateTestPerpetuals(t, ctx, perpetualsKeeper) // Set the tracer on the multistore to verify the performed writes are correct. traceDecoder := &tracer.TraceDecoder{} @@ -195,13 +203,15 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { func TestGetSetNegativeTncSubaccountSeenAtBlock_PanicsOnDecreasingBlock(t *testing.T) { // Setup keeper state and test parameters. - ctx, subaccountsKeeper, _, _, _, _, _, _, _ := keepertest.SubaccountsKeepers(t, true) - - subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 2) + ctx, subaccountsKeeper, pricesKeeper, perpetualsKeeper, _, _, _, _, _ := keepertest.SubaccountsKeepers(t, true) + keepertest.CreateTestMarkets(t, ctx, pricesKeeper) + keepertest.CreateTestLiquidityTiers(t, ctx, perpetualsKeeper) + keepertest.CreateTestPerpetuals(t, ctx, perpetualsKeeper) + subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, uint32(0), 2) require.PanicsWithValue( t, "SetNegativeTncSubaccountSeenAtBlock: new block height (1) is less than the current block height (2)", - func() { subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, types.ModuleAddress, 1) }, + func() { subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, uint32(0), 1) }, ) } diff --git a/protocol/x/subaccounts/keeper/subaccount_test.go b/protocol/x/subaccounts/keeper/subaccount_test.go index bd82a737e1..65b32eb7c3 100644 --- a/protocol/x/subaccounts/keeper/subaccount_test.go +++ b/protocol/x/subaccounts/keeper/subaccount_test.go @@ -2411,7 +2411,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { // Negative TNC subaccount state currentBlock uint32 - negativeTncSubaccountSeenAtBlock map[string]uint32 + negativeTncSubaccountSeenAtBlock map[uint32]uint32 // Update type updateType types.UpdateType @@ -2420,6 +2420,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { expectedQuoteBalance: big.NewInt(100), expectedSuccess: true, expectedSuccessPerUpdate: []types.UpdateResult{types.Success}, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + }, updates: []types.Update{ { AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), @@ -2444,8 +2447,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100, + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100, }, updateType: types.Deposit, @@ -2455,6 +2458,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { expectedQuoteBalance: big.NewInt(100), expectedSuccess: true, expectedSuccessPerUpdate: []types.UpdateResult{types.Success}, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + }, updates: []types.Update{ { AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), @@ -2479,8 +2485,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -2490,6 +2496,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { expectedQuoteBalance: big.NewInt(100), expectedSuccess: true, expectedSuccessPerUpdate: []types.UpdateResult{types.Success}, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + }, updates: []types.Update{ { AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(100)), @@ -2514,8 +2523,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 0, + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 0, }, updateType: types.Deposit, @@ -2545,8 +2554,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100, + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100, }, updateType: types.Withdrawal, @@ -2577,8 +2586,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -2622,8 +2631,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, }, @@ -2666,8 +2675,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 0, + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 0, }, updateType: types.Withdrawal, @@ -2680,6 +2689,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { expectedSuccessPerUpdate: []types.UpdateResult{types.Success}, perpetuals: []perptypes.Perpetual{ constants.BtcUsd_SmallMarginRequirement, + constants.IsoUsd_IsolatedMarket, }, perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ firstSubaccountId: {&constants.PerpetualPosition_OneBTCLong}, @@ -2711,8 +2721,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.IsoCollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -2746,8 +2756,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.IsoCollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -2790,10 +2800,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.IsoCollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, - types.ModuleAddress.String(): 0, + constants.BtcUsd_NoMarginRequirement.Params.Id: 0, }, updateType: types.Withdrawal, @@ -2836,10 +2846,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.IsoCollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, - types.ModuleAddress.String(): 100 - + constants.BtcUsd_NoMarginRequirement.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, }, @@ -2885,9 +2895,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.IsoCollateralPoolAddress.String(): 0, - constants.Iso2CollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id: 0, + constants.Iso2Usd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -2934,10 +2944,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.IsoCollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, - constants.Iso2CollateralPoolAddress.String(): 100 - + constants.Iso2Usd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -2987,8 +2997,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: false, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100, + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100, }, updateType: types.Match, @@ -3038,8 +3048,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: false, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -3089,8 +3099,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: false, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 0, + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 0, }, updateType: types.Match, @@ -3122,8 +3132,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100, + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100, }, updateType: types.Match, }, @@ -3155,8 +3165,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -3189,8 +3199,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 0, + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 0, }, updateType: types.Match, @@ -3202,7 +3212,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.WithdrawalsAndTransfersBlocked, types.WithdrawalsAndTransfersBlocked, }, - perpetuals: []perptypes.Perpetual{}, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + }, perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, @@ -3223,8 +3235,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100, + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100, }, updateType: types.Transfer, @@ -3237,7 +3249,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.WithdrawalsAndTransfersBlocked, types.WithdrawalsAndTransfersBlocked, }, - perpetuals: []perptypes.Perpetual{}, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + }, perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, @@ -3258,8 +3272,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -3273,7 +3287,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.NewlyUndercollateralized, types.Success, }, - perpetuals: []perptypes.Perpetual{}, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + }, perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, @@ -3294,8 +3310,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, }, @@ -3308,7 +3324,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.NewlyUndercollateralized, types.Success, }, - perpetuals: []perptypes.Perpetual{}, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, + }, perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, expectedPerpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{}, expectedAssetPositions: map[types.SubaccountId][]*types.AssetPosition{}, @@ -3329,8 +3347,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - types.ModuleAddress.String(): 0, + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.BtcUsd_NoMarginRequirement.Params.Id: 0, }, updateType: types.Transfer, @@ -3346,6 +3364,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, perpetuals: []perptypes.Perpetual{ constants.IsoUsd_IsolatedMarket, + constants.Iso2Usd_IsolatedMarket, }, perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ secondSubaccountId: {&constants.PerpetualPosition_OneISOLong}, @@ -3371,8 +3390,8 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.Iso2CollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.Iso2Usd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -3389,6 +3408,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.WithdrawalsAndTransfersBlocked, }, perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, constants.IsoUsd_IsolatedMarket, }, perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ @@ -3415,10 +3435,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.IsoCollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, - types.ModuleAddress.String(): 0, + constants.BtcUsd_NoMarginRequirement.Params.Id: 0, }, updateType: types.Transfer, @@ -3435,6 +3455,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { types.WithdrawalsAndTransfersBlocked, }, perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_SmallMarginRequirement, constants.IsoUsd_IsolatedMarket, }, perpetualPositions: map[types.SubaccountId][]*types.PerpetualPosition{ @@ -3461,10 +3482,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.IsoCollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, - types.ModuleAddress.String(): 100 - + constants.BtcUsd_NoMarginRequirement.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, }, @@ -3510,9 +3531,9 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.IsoCollateralPoolAddress.String(): 0, - constants.Iso2CollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id: 0, + constants.Iso2Usd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -3559,10 +3580,10 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { msgSenderEnabled: true, currentBlock: 100, - negativeTncSubaccountSeenAtBlock: map[string]uint32{ - constants.IsoCollateralPoolAddress.String(): 100 - + negativeTncSubaccountSeenAtBlock: map[uint32]uint32{ + constants.IsoUsd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS, - constants.Iso2CollateralPoolAddress.String(): 100 - + constants.Iso2Usd_IsolatedMarket.Params.Id: 100 - types.WITHDRAWAL_AND_TRANSFERS_BLOCKED_AFTER_NEGATIVE_TNC_SUBACCOUNT_SEEN_BLOCKS + 1, }, @@ -3646,10 +3667,11 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { subaccountId := *subaccounts[0].Id // Set the negative TNC subaccount seen at block in state if it's greater than 0. - for collateralPoolAddress, negativeTncSubaccountSeenAtBlock := range tc.negativeTncSubaccountSeenAtBlock { + for perpetualId, negativeTncSubaccountSeenAtBlock := range tc.negativeTncSubaccountSeenAtBlock { if negativeTncSubaccountSeenAtBlock != 0 { keeper.SetNegativeTncSubaccountSeenAtBlock( - ctx, sdk.MustAccAddressFromBech32(collateralPoolAddress), + ctx, + perpetualId, negativeTncSubaccountSeenAtBlock, ) } From afb48cc486ffe4bdcae3d74ce574ff459b403f5c Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Thu, 21 Mar 2024 21:20:52 -0400 Subject: [PATCH 09/16] Fix constant naming. --- protocol/testutil/constants/clob_pair.go | 6 +++--- protocol/x/clob/keeper/process_operations_test.go | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/protocol/testutil/constants/clob_pair.go b/protocol/testutil/constants/clob_pair.go index 7388f77918..15c4c5b669 100644 --- a/protocol/testutil/constants/clob_pair.go +++ b/protocol/testutil/constants/clob_pair.go @@ -127,7 +127,7 @@ var ( QuantumConversionExponent: -8, Status: clobtypes.ClobPair_STATUS_PAUSED, } - ClobPair_Iso = clobtypes.ClobPair{ + ClobPair_3_Iso = clobtypes.ClobPair{ Id: 3, Metadata: &clobtypes.ClobPair_PerpetualClobMetadata{ PerpetualClobMetadata: &clobtypes.PerpetualClobMetadata{ @@ -139,7 +139,7 @@ var ( QuantumConversionExponent: -8, Status: clobtypes.ClobPair_STATUS_ACTIVE, } - ClobPair_Iso_Final_Settlement = clobtypes.ClobPair{ + ClobPair_3_Iso_Final_Settlement = clobtypes.ClobPair{ Id: 3, Metadata: &clobtypes.ClobPair_PerpetualClobMetadata{ PerpetualClobMetadata: &clobtypes.PerpetualClobMetadata{ @@ -151,7 +151,7 @@ var ( QuantumConversionExponent: -8, Status: clobtypes.ClobPair_STATUS_FINAL_SETTLEMENT, } - ClobPair_Iso2 = clobtypes.ClobPair{ + ClobPair_4_Iso2 = clobtypes.ClobPair{ Id: 4, Metadata: &clobtypes.ClobPair_PerpetualClobMetadata{ PerpetualClobMetadata: &clobtypes.PerpetualClobMetadata{ diff --git a/protocol/x/clob/keeper/process_operations_test.go b/protocol/x/clob/keeper/process_operations_test.go index 5ac3fe8c5a..8f24b10654 100644 --- a/protocol/x/clob/keeper/process_operations_test.go +++ b/protocol/x/clob/keeper/process_operations_test.go @@ -1120,7 +1120,7 @@ func TestProcessProposerOperations(t *testing.T) { }, perpetualFeeParams: &constants.PerpetualFeeParams, clobPairs: []types.ClobPair{ - constants.ClobPair_Iso, + constants.ClobPair_3_Iso, }, subaccounts: []satypes.Subaccount{ // deleverageable since TNC = -$1 @@ -1163,7 +1163,7 @@ func TestProcessProposerOperations(t *testing.T) { perpetualFeeParams: &constants.PerpetualFeeParams, clobPairs: []types.ClobPair{ constants.ClobPair_Btc, - constants.ClobPair_Iso_Final_Settlement, + constants.ClobPair_3_Iso_Final_Settlement, }, subaccounts: []satypes.Subaccount{ // deleveragable: TNC = -$1. @@ -1207,8 +1207,8 @@ func TestProcessProposerOperations(t *testing.T) { }, perpetualFeeParams: &constants.PerpetualFeeParams, clobPairs: []types.ClobPair{ - constants.ClobPair_Iso, - constants.ClobPair_Iso2, + constants.ClobPair_3_Iso, + constants.ClobPair_4_Iso2, }, subaccounts: []satypes.Subaccount{ // deleverageable since TNC = -$1 From 9a10ee51b979591d8b08a529a05b0be493adcd34 Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:57:06 -0400 Subject: [PATCH 10/16] Change store key from collateral pool addresses to suffices based on perpetual ids. --- .../dydxprotocol/subaccounts/query.lcd.ts | 4 +- .../codegen/dydxprotocol/subaccounts/query.ts | 18 +-- proto/dydxprotocol/subaccounts/query.proto | 5 +- protocol/x/clob/e2e/withdrawal_gating_test.go | 5 +- protocol/x/clob/keeper/process_operations.go | 6 +- .../x/clob/keeper/process_operations_test.go | 47 +++--- protocol/x/clob/types/expected_keepers.go | 2 +- protocol/x/perpetuals/keeper/perpetual.go | 5 + ...y_withdrawal_and_transfers_blocked_info.go | 7 +- ...hdrawal_and_transfers_blocked_info_test.go | 62 +++++--- .../keeper/negative_tnc_subaccount.go | 61 ++++++-- .../keeper/negative_tnc_subaccount_test.go | 147 ++++++++++++------ protocol/x/subaccounts/keeper/subaccount.go | 48 +++--- .../x/subaccounts/keeper/subaccount_test.go | 3 +- .../x/subaccounts/types/expected_keepers.go | 1 + protocol/x/subaccounts/types/keys.go | 3 + protocol/x/subaccounts/types/query.pb.go | 133 +++++++--------- 17 files changed, 331 insertions(+), 226 deletions(-) diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.lcd.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.lcd.ts index edfa4c2775..045342f671 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.lcd.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.lcd.ts @@ -47,8 +47,8 @@ export class LCDQueryClient { params: {} }; - if (typeof params?.collateralPoolAddress !== "undefined") { - options.params.collateral_pool_address = params.collateralPoolAddress; + if (typeof params?.perpetualId !== "undefined") { + options.params.perpetual_id = params.perpetualId; } const endpoint = `dydxprotocol/subaccounts/withdrawals_and_transfers_blocked_info`; diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.ts index d7ac251143..0464bd1359 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/query.ts @@ -49,20 +49,20 @@ export interface QuerySubaccountAllResponseSDKType { /** * QueryGetWithdrawalAndTransfersBlockedInfoRequest is a request type for * fetching information about whether withdrawals and transfers are blocked for - * a specific collateral pool. + * a collateral pool associated with the passed in perpetual id. */ export interface QueryGetWithdrawalAndTransfersBlockedInfoRequest { - collateralPoolAddress: string; + perpetualId: number; } /** * QueryGetWithdrawalAndTransfersBlockedInfoRequest is a request type for * fetching information about whether withdrawals and transfers are blocked for - * a specific collateral pool. + * a collateral pool associated with the passed in perpetual id. */ export interface QueryGetWithdrawalAndTransfersBlockedInfoRequestSDKType { - collateral_pool_address: string; + perpetual_id: number; } /** * QueryGetWithdrawalAndTransfersBlockedInfoRequest is a response type for @@ -287,14 +287,14 @@ export const QuerySubaccountAllResponse = { function createBaseQueryGetWithdrawalAndTransfersBlockedInfoRequest(): QueryGetWithdrawalAndTransfersBlockedInfoRequest { return { - collateralPoolAddress: "" + perpetualId: 0 }; } export const QueryGetWithdrawalAndTransfersBlockedInfoRequest = { encode(message: QueryGetWithdrawalAndTransfersBlockedInfoRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.collateralPoolAddress !== "") { - writer.uint32(10).string(message.collateralPoolAddress); + if (message.perpetualId !== 0) { + writer.uint32(8).uint32(message.perpetualId); } return writer; @@ -310,7 +310,7 @@ export const QueryGetWithdrawalAndTransfersBlockedInfoRequest = { switch (tag >>> 3) { case 1: - message.collateralPoolAddress = reader.string(); + message.perpetualId = reader.uint32(); break; default: @@ -324,7 +324,7 @@ export const QueryGetWithdrawalAndTransfersBlockedInfoRequest = { fromPartial(object: DeepPartial): QueryGetWithdrawalAndTransfersBlockedInfoRequest { const message = createBaseQueryGetWithdrawalAndTransfersBlockedInfoRequest(); - message.collateralPoolAddress = object.collateralPoolAddress ?? ""; + message.perpetualId = object.perpetualId ?? 0; return message; } diff --git a/proto/dydxprotocol/subaccounts/query.proto b/proto/dydxprotocol/subaccounts/query.proto index 2a998d32b2..7533366d0f 100644 --- a/proto/dydxprotocol/subaccounts/query.proto +++ b/proto/dydxprotocol/subaccounts/query.proto @@ -57,10 +57,9 @@ message QuerySubaccountAllResponse { // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a request type for // fetching information about whether withdrawals and transfers are blocked for -// a specific collateral pool. +// a collateral pool associated with the passed in perpetual id. message QueryGetWithdrawalAndTransfersBlockedInfoRequest { - string collateral_pool_address = 1 - [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + uint32 perpetual_id = 1; } // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a response type for diff --git a/protocol/x/clob/e2e/withdrawal_gating_test.go b/protocol/x/clob/e2e/withdrawal_gating_test.go index 65ea83db65..f549da2cd3 100644 --- a/protocol/x/clob/e2e/withdrawal_gating_test.go +++ b/protocol/x/clob/e2e/withdrawal_gating_test.go @@ -252,10 +252,11 @@ func TestWithdrawalGating_NegativeTncSubaccount_BlocksThenUnblocks(t *testing.T) tApp.App.SubaccountsKeeper.GetSubaccount(ctx, *expectedSubaccount.Id), ) } - negativeTncSubaccountSeenAtBlock, exists := tApp.App.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock( + negativeTncSubaccountSeenAtBlock, exists, err := tApp.App.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock( ctx, - satypes.ModuleAddress, + constants.BtcUsd_NoMarginRequirement.Params.Id, ) + require.NoError(t, err) require.Equal(t, tc.expectedWithdrawalsGated, exists) require.Equal(t, tc.expectedNegativeTncSubaccountSeenAtBlock, negativeTncSubaccountSeenAtBlock) diff --git a/protocol/x/clob/keeper/process_operations.go b/protocol/x/clob/keeper/process_operations.go index a99c8b6c0e..0b67620210 100644 --- a/protocol/x/clob/keeper/process_operations.go +++ b/protocol/x/clob/keeper/process_operations.go @@ -694,11 +694,13 @@ func (k Keeper) PersistMatchDeleveragingToState( metrics.GetLabelForBoolValue(metrics.IsLong, position.GetIsLong()), metrics.GetLabelForBoolValue(metrics.DeliverTx, true), ) - k.subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock( + if err = k.subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock( ctx, perpetualId, lib.MustConvertIntegerToUint32(ctx.BlockHeight()), - ) + ); err != nil { + return err + } return nil } diff --git a/protocol/x/clob/keeper/process_operations_test.go b/protocol/x/clob/keeper/process_operations_test.go index 8f24b10654..242c75de91 100644 --- a/protocol/x/clob/keeper/process_operations_test.go +++ b/protocol/x/clob/keeper/process_operations_test.go @@ -66,7 +66,7 @@ type processProposerOperationsTestCase struct { expectedQuoteBalances map[satypes.SubaccountId]int64 expectedPerpetualPositions map[satypes.SubaccountId][]*satypes.PerpetualPosition expectedSubaccountLiquidationInfo map[satypes.SubaccountId]types.SubaccountLiquidationInfo - expectedNegativeTncSubaccountSeen map[string]bool + expectedNegativeTncSubaccountSeen map[uint32]bool expectedError error expectedPanics string } @@ -957,8 +957,8 @@ func TestProcessProposerOperations(t *testing.T) { expectedPerpetualPositions: map[satypes.SubaccountId][]*satypes.PerpetualPosition{ constants.Carl_Num0: constants.Carl_Num0_1BTC_Short_50499USD.GetPerpetualPositions(), }, - expectedNegativeTncSubaccountSeen: map[string]bool{ - satypes.ModuleAddress.String(): true, + expectedNegativeTncSubaccountSeen: map[uint32]bool{ + constants.BtcUsd_20PercentInitial_10PercentMaintenance.Params.Id: true, }, }, "Zero-fill deleveraging succeeds when the account is negative TNC and has a position in final settlement" + @@ -998,8 +998,8 @@ func TestProcessProposerOperations(t *testing.T) { constants.Carl_Num0: constants.Carl_Num0_1BTC_Short_50499USD.GetPerpetualPositions(), constants.Dave_Num0: constants.Dave_Num0_1BTC_Long_50000USD.GetPerpetualPositions(), }, - expectedNegativeTncSubaccountSeen: map[string]bool{ - satypes.ModuleAddress.String(): true, + expectedNegativeTncSubaccountSeen: map[uint32]bool{ + constants.BtcUsd_100PercentMarginRequirement.Params.Id: true, }, }, "Zero-fill deleveraging succeeds when there's multiple zero-fill deleveraging events for the same subaccount " + @@ -1044,8 +1044,8 @@ func TestProcessProposerOperations(t *testing.T) { expectedPerpetualPositions: map[satypes.SubaccountId][]*satypes.PerpetualPosition{ constants.Carl_Num0: constants.Carl_Num0_1BTC_Short_50499USD.GetPerpetualPositions(), }, - expectedNegativeTncSubaccountSeen: map[string]bool{ - satypes.ModuleAddress.String(): true, + expectedNegativeTncSubaccountSeen: map[uint32]bool{ + constants.BtcUsd_20PercentInitial_10PercentMaintenance.Params.Id: true, }, }, "Zero-fill deleverage succeeds after the same subaccount is partially deleveraged": { @@ -1108,14 +1108,15 @@ func TestProcessProposerOperations(t *testing.T) { }, }, }, - expectedNegativeTncSubaccountSeen: map[string]bool{ - satypes.ModuleAddress.String(): true, + expectedNegativeTncSubaccountSeen: map[uint32]bool{ + constants.BtcUsd_20PercentInitial_10PercentMaintenance.Params.Id: true, }, }, "Zero-fill deleveraging succeeds when the account is negative TNC and updates the last negative TNC subaccount " + "seen block number in state for an isolated perpetual collateral pool if the subaccount is isolated to the " + "isolated perpetual": { perpetuals: []*perptypes.Perpetual{ + &constants.BtcUsd_NoMarginRequirement, &constants.IsoUsd_IsolatedMarket, }, perpetualFeeParams: &constants.PerpetualFeeParams, @@ -1148,9 +1149,9 @@ func TestProcessProposerOperations(t *testing.T) { expectedPerpetualPositions: map[satypes.SubaccountId][]*satypes.PerpetualPosition{ constants.Carl_Num0: constants.Carl_Num0_1ISO_Short_49USD.GetPerpetualPositions(), }, - expectedNegativeTncSubaccountSeen: map[string]bool{ - satypes.ModuleAddress.String(): false, - constants.IsoCollateralPoolAddress.String(): true, + expectedNegativeTncSubaccountSeen: map[uint32]bool{ + constants.BtcUsd_NoMarginRequirement.Params.Id: false, + constants.IsoUsd_IsolatedMarket.Params.Id: true, }, }, "Zero-fill deleveraging succeeds when the account is negative TNC and has a position in final settlement" + @@ -1193,15 +1194,16 @@ func TestProcessProposerOperations(t *testing.T) { constants.Carl_Num0: constants.Carl_Num0_1ISO_Short_49USD.GetPerpetualPositions(), constants.Dave_Num0: constants.Dave_Num0_1BTC_Long_50000USD.GetPerpetualPositions(), }, - expectedNegativeTncSubaccountSeen: map[string]bool{ - satypes.ModuleAddress.String(): false, - constants.IsoCollateralPoolAddress.String(): true, + expectedNegativeTncSubaccountSeen: map[uint32]bool{ + constants.BtcUsd_NoMarginRequirement.Params.Id: false, + constants.IsoUsd_IsolatedMarket.Params.Id: true, }, }, "Zero-fill deleveraging succeeds when there's multiple zero-fill deleveraging events for the different subaccount " + "and perpetual ID. It updates the last negative TNC subaccount seen block number in state for both isolated " + "perpetual collateral pools if the subaccounts are isolated to different isolated perpetuals": { perpetuals: []*perptypes.Perpetual{ + &constants.BtcUsd_NoMarginRequirement, &constants.IsoUsd_IsolatedMarket, &constants.Iso2Usd_IsolatedMarket, }, @@ -1248,10 +1250,10 @@ func TestProcessProposerOperations(t *testing.T) { constants.Carl_Num0: constants.Carl_Num0_1ISO_Short_49USD.GetPerpetualPositions(), constants.Dave_Num0: constants.Dave_Num0_1ISO2_Short_499USD.GetPerpetualPositions(), }, - expectedNegativeTncSubaccountSeen: map[string]bool{ - satypes.ModuleAddress.String(): false, - constants.IsoCollateralPoolAddress.String(): true, - constants.Iso2CollateralPoolAddress.String(): true, + expectedNegativeTncSubaccountSeen: map[uint32]bool{ + constants.BtcUsd_NoMarginRequirement.Params.Id: false, + constants.IsoUsd_IsolatedMarket.Params.Id: true, + constants.Iso2Usd_IsolatedMarket.Params.Id: true, }, }, "Succeeds order removal operations with previous stateful orders": { @@ -2545,12 +2547,13 @@ func runProcessProposerOperationsTestCase( require.Equal(t, fillAmount, actualFillAmount) } - for collateralPoolAddress, expectedNegativeTncSubaccountSeen := range tc.expectedNegativeTncSubaccountSeen { + for perpetualId, expectedNegativeTncSubaccountSeen := range tc.expectedNegativeTncSubaccountSeen { // Verify the negative TNC subaccount seen block. - seenNegativeTncSubaccountBlock, exists := ks.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock( + seenNegativeTncSubaccountBlock, exists, err := ks.SubaccountsKeeper.GetNegativeTncSubaccountSeenAtBlock( ctx, - sdk.MustAccAddressFromBech32(collateralPoolAddress), + perpetualId, ) + require.NoError(t, err) if expectedNegativeTncSubaccountSeen { require.True(t, exists) require.Equal(t, uint32(ctx.BlockHeight()), seenNegativeTncSubaccountBlock) diff --git a/protocol/x/clob/types/expected_keepers.go b/protocol/x/clob/types/expected_keepers.go index 469a47f767..a79e87f4a4 100644 --- a/protocol/x/clob/types/expected_keepers.go +++ b/protocol/x/clob/types/expected_keepers.go @@ -63,7 +63,7 @@ type SubaccountsKeeper interface { ctx sdk.Context, perpetualId uint32, blockHeight uint32, - ) + ) error TransferFeesToFeeCollectorModule(ctx sdk.Context, assetId uint32, amount *big.Int, perpetualId uint32) error TransferInsuranceFundPayments( ctx sdk.Context, diff --git a/protocol/x/perpetuals/keeper/perpetual.go b/protocol/x/perpetuals/keeper/perpetual.go index 1603f5d8bf..5de08fc2f1 100644 --- a/protocol/x/perpetuals/keeper/perpetual.go +++ b/protocol/x/perpetuals/keeper/perpetual.go @@ -31,6 +31,11 @@ import ( gometrics "github.com/hashicorp/go-metrics" ) +func (k Keeper) IsIsolatedPerpetual(ctx sdk.Context, perpetualId uint32) (bool, error) { + insuranceFundName, err := k.GetInsuranceFundName(ctx, perpetualId) + return insuranceFundName == types.InsuranceFundName, err +} + // GetInsuranceFundName returns the name of the insurance fund account for a given perpetual. // For isolated markets, the name is "insurance-fund:". // For cross markets, the name is "insurance-fund". diff --git a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go index 2c8cac4045..a017d8b954 100644 --- a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go +++ b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info.go @@ -25,10 +25,13 @@ func (k Keeper) GetWithdrawalAndTransfersBlockedInfo( ) chainOutageSeenAtBlock, chainOutageExists := downtimeInfo.BlockInfo.Height, downtimeInfo.BlockInfo.Height > 0 && downtimeInfo.Duration > 0 - negativeTncSubaccountSeenAtBlock, negativeTncSubaccountSeenAtBlockExists := k.GetNegativeTncSubaccountSeenAtBlock( + negativeTncSubaccountSeenAtBlock, negativeTncSubaccountSeenAtBlockExists, err := k.GetNegativeTncSubaccountSeenAtBlock( ctx, - sdktypes.MustAccAddressFromBech32(req.CollateralPoolAddress), + req.PerpetualId, ) + if err != nil { + return nil, err + } // Withdrawals and transfers are blocked at non-zero block iff a chain outage or negative TNC subaccount exists. withdrawalsAndTransfersBlockedUntilBlock := uint32(0) diff --git a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go index 1f2d132e37..d04e94e939 100644 --- a/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go +++ b/protocol/x/subaccounts/keeper/grpc_query_withdrawal_and_transfers_blocked_info_test.go @@ -20,7 +20,7 @@ import ( func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { for testName, tc := range map[string]struct { // Setup. - setup func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) + setup func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) error // Parameters. request *types.QueryGetWithdrawalAndTransfersBlockedInfoRequest @@ -30,16 +30,20 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { err error }{ "Nil request returns an error": { - setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) {}, + setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) error { + return nil + }, err: status.Error(codes.InvalidArgument, "invalid request"), }, `No negative TNC subaccount or chain outage in state returns withdrawals and transfers unblocked at block 0`: { - setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) {}, + setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) error { + return nil + }, request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ - CollateralPoolAddress: types.ModuleAddress.String(), + PerpetualId: uint32(constants.BtcUsd_NoMarginRequirement.Params.Id), }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ @@ -50,8 +54,8 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, `Negative TNC subaccount seen in state returns withdrawals and transfers unblocked after the delay`: { - setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock( + setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) error { + return sk.SetNegativeTncSubaccountSeenAtBlock( ctx, constants.BtcUsd_NoMarginRequirement.Params.Id, 7, @@ -59,7 +63,7 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ - CollateralPoolAddress: types.ModuleAddress.String(), + PerpetualId: uint32(constants.BtcUsd_NoMarginRequirement.Params.Id), }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ @@ -71,8 +75,8 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, `Negative TNC subaccount seen in state returns withdrawals and transfers unblocked after the delay (for isolated perpetual)`: { - setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock( + setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) error { + return sk.SetNegativeTncSubaccountSeenAtBlock( ctx, constants.IsoUsd_IsolatedMarket.Params.Id, 5, @@ -80,7 +84,7 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ - CollateralPoolAddress: constants.IsoCollateralPoolAddress.String(), + PerpetualId: uint32(constants.IsoUsd_IsolatedMarket.Params.Id), }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ @@ -91,7 +95,7 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, }, `Chain outage seen in state returns withdrawals and transfers unblocked after the delay`: { - setup: func(ctx sdktypes.Context, k sakeeper.Keeper, bk btkeeper.Keeper) { + setup: func(ctx sdktypes.Context, k sakeeper.Keeper, bk btkeeper.Keeper) error { bk.SetAllDowntimeInfo( ctx, &blocktimetypes.AllDowntimeInfo{ @@ -112,10 +116,11 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, }, }) + return nil }, request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ - CollateralPoolAddress: types.ModuleAddress.String(), + PerpetualId: constants.BtcUsd_NoMarginRequirement.Params.Id, }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ @@ -127,12 +132,15 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, `Negative TNC subaccount and chain outage seen in state returns withdrawals and transfers unblocked after the max block number + delay (negative TNC subaccount block greater)`: { - setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock( + setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) error { + err := sk.SetNegativeTncSubaccountSeenAtBlock( ctx, constants.BtcUsd_NoMarginRequirement.Params.Id, 27, ) + if err != nil { + return nil + } bk.SetAllDowntimeInfo( ctx, &blocktimetypes.AllDowntimeInfo{ @@ -153,10 +161,11 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, }, }) + return nil }, request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ - CollateralPoolAddress: types.ModuleAddress.String(), + PerpetualId: constants.BtcUsd_NoMarginRequirement.Params.Id, }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ @@ -168,12 +177,15 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, `Negative TNC subaccount and chain outage seen in state returns withdrawals and transfers unblocked after the max block number + delay (chain outage block greater)`: { - setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock( + setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) error { + err := sk.SetNegativeTncSubaccountSeenAtBlock( ctx, constants.BtcUsd_NoMarginRequirement.Params.Id, 37, ) + if err != nil { + return err + } bk.SetAllDowntimeInfo( ctx, &blocktimetypes.AllDowntimeInfo{ @@ -194,10 +206,11 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, }, }) + return nil }, request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ - CollateralPoolAddress: types.ModuleAddress.String(), + PerpetualId: constants.BtcUsd_NoMarginRequirement.Params.Id, }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ @@ -209,12 +222,15 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, `Negative TNC subaccount and chain outage seen in state returns withdrawals and transfers unblocked after the max block number + delay (both blocks equal)`: { - setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) { - sk.SetNegativeTncSubaccountSeenAtBlock( + setup: func(ctx sdktypes.Context, sk sakeeper.Keeper, bk btkeeper.Keeper) error { + err := sk.SetNegativeTncSubaccountSeenAtBlock( ctx, constants.BtcUsd_NoMarginRequirement.Params.Id, 3, ) + if err != nil { + return err + } bk.SetAllDowntimeInfo( ctx, &blocktimetypes.AllDowntimeInfo{ @@ -235,10 +251,11 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { }, }, }) + return nil }, request: &types.QueryGetWithdrawalAndTransfersBlockedInfoRequest{ - CollateralPoolAddress: types.ModuleAddress.String(), + PerpetualId: constants.BtcUsd_NoMarginRequirement.Params.Id, }, response: &types.QueryGetWithdrawalAndTransfersBlockedInfoResponse{ @@ -254,7 +271,8 @@ func TestQueryWithdrawalAndTransfersBlockedInfo(t *testing.T) { keepertest.CreateTestMarkets(t, ctx, pricesKeeper) keepertest.CreateTestLiquidityTiers(t, ctx, perpetualsKeeper) keepertest.CreateTestPerpetuals(t, ctx, perpetualsKeeper) - tc.setup(ctx, *keeper, *blocktimeKeeper) + err := tc.setup(ctx, *keeper, *blocktimeKeeper) + require.NoError(t, err) response, err := keeper.GetWithdrawalAndTransfersBlockedInfo(ctx, tc.request) if tc.err != nil { require.ErrorIs(t, err, tc.err) diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go index 53f055c250..9d81b39b7e 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go @@ -7,6 +7,7 @@ import ( storetypes "cosmossdk.io/store/types" sdk "github.com/cosmos/cosmos-sdk/types" gogotypes "github.com/cosmos/gogoproto/types" + "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" ) @@ -14,13 +15,33 @@ import ( // seen in state for the given collateral pool address and a boolean for whether it exists in state. func (k Keeper) GetNegativeTncSubaccountSeenAtBlock( ctx sdk.Context, - collateralPoolAddress sdk.AccAddress, + perpetualId uint32, +) (uint32, bool, error) { + store := prefix.NewStore( + ctx.KVStore(k.storeKey), + []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix), + ) + + suffix, err := k.getNegativeTncSubaccountStoreSuffx(ctx, perpetualId) + if err != nil { + return 0, false, err + } + + blockHeight, exists := k.getNegativeTncSubaccountSeenAtBlock(store, suffix) + return blockHeight, exists, nil +} + +// Internal helper method to read the store using a store suffix. +func (k Keeper) getNegativeTncSubaccountSeenAtBlockWithSuffix( + ctx sdk.Context, + storeSuffix string, ) (uint32, bool) { store := prefix.NewStore( ctx.KVStore(k.storeKey), []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix), ) - return k.getNegativeTncSubaccountSeenAtBlock(store, collateralPoolAddress) + + return k.getNegativeTncSubaccountSeenAtBlock(store, storeSuffix) } // getNegativeTncSubaccountSeenAtBlock is a helper function that takes a store and returns the last @@ -28,10 +49,10 @@ func (k Keeper) GetNegativeTncSubaccountSeenAtBlock( // and a boolean for whether it exists in state. func (k Keeper) getNegativeTncSubaccountSeenAtBlock( store storetypes.KVStore, - collateralPoolAddress sdk.AccAddress, + storeSuffix string, ) (uint32, bool) { b := store.Get( - collateralPoolAddress, + []byte(storeSuffix), ) blockHeight := gogotypes.UInt32Value{Value: 0} exists := false @@ -50,24 +71,19 @@ func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( ctx sdk.Context, perpetualId uint32, blockHeight uint32, -) { +) error { store := prefix.NewStore( ctx.KVStore(k.storeKey), []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix), ) - collateralPoolAddress, err := k.GetCollateralPoolFromPerpetualId(ctx, perpetualId) + storeSuffix, err := k.getNegativeTncSubaccountStoreSuffx(ctx, perpetualId) if err != nil { - panic( - fmt.Sprintf( - "SetNegativeTncSubaccountSeenAtBlock: non-existent perpetual id %d", - perpetualId, - ), - ) + return err } // Panic if the stored block height value exists and is greater than the new block height value. - currentValue, exists := k.getNegativeTncSubaccountSeenAtBlock(store, collateralPoolAddress) + currentValue, exists := k.getNegativeTncSubaccountSeenAtBlock(store, storeSuffix) if exists && blockHeight < currentValue { panic( fmt.Sprintf( @@ -80,7 +96,24 @@ func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( blockHeightValue := gogotypes.UInt32Value{Value: blockHeight} store.Set( - collateralPoolAddress.Bytes(), + []byte(storeSuffix), k.cdc.MustMarshal(&blockHeightValue), ) + + return nil +} + +func (k Keeper) getNegativeTncSubaccountStoreSuffx( + ctx sdk.Context, + perpetualId uint32, +) (string, error) { + isIsolated, err := k.perpetualsKeeper.IsIsolatedPerpetual(ctx, perpetualId) + if err != nil { + return "", err + } + if isIsolated { + return types.CrossCollateralSuffix, nil + } else { + return lib.UintToString(perpetualId), nil + } } diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go index 6e1494d34f..1a9fa31759 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go @@ -4,6 +4,7 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" keepertest "github.com/dydxprotocol/v4-chain/protocol/testutil/keeper" "github.com/dydxprotocol/v4-chain/protocol/testutil/tracer" @@ -18,22 +19,23 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { constants.Iso2Usd_IsolatedMarket.Params.Id, constants.BtcUsd_NoMarginRequirement.Params.Id, } - testCollateralPoolAddresses := []sdk.AccAddress{ - constants.IsoCollateralPoolAddress, - constants.Iso2CollateralPoolAddress, - types.ModuleAddress, + testSuffices := []string{ + lib.UintToString(constants.IsoUsd_IsolatedMarket.Params.Id), + lib.UintToString(constants.Iso2Usd_IsolatedMarket.Params.Id), + types.CrossCollateralSuffix, } tests := map[string]struct { // Setup. - setupTestAndPerformAssertions func(ctx sdk.Context, s keeper.Keeper) + setupTestAndPerformAssertions func(ctx sdk.Context, s keeper.Keeper) error // Expectations. expectedMultiStoreWrites []string }{ "Block height defaults to zero if not set and doesn't exist": { - setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - for _, collateralPoolAddr := range testCollateralPoolAddresses { - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) error { + for _, perpetualId := range testPerpetualIds { + block, exists, err := k.GetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId) + require.NoError(t, err) require.False(t, exists) require.Equal( t, @@ -41,15 +43,20 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) } + return nil }, expectedMultiStoreWrites: []string{}, }, "Block height can be updated": { - setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - for i, collateralPoolAddr := range testCollateralPoolAddresses { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 1) - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) error { + for _, perpetualId := range testPerpetualIds { + err := k.SetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId, 1) + if err != nil { + return err + } + block, exists, err := k.GetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId) + require.NoError(t, err) require.True(t, exists) require.Equal( t, @@ -57,19 +64,24 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) } + return nil }, expectedMultiStoreWrites: []string{ - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + string(constants.IsoCollateralPoolAddress), - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + string(constants.Iso2CollateralPoolAddress), - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + string(types.ModuleAddress), + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + testSuffices[0], + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + testSuffices[1], + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + testSuffices[2], }, }, "Block height can be updated more than once": { - setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - for i, collateralPoolAddr := range testCollateralPoolAddresses { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 1) - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) error { + for _, perpetualId := range testPerpetualIds { + err := k.SetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId, 1) + if err != nil { + return nil + } + block, exists, err := k.GetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId) + require.NoError(t, err) require.True(t, exists) require.Equal( t, @@ -77,8 +89,12 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 2) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + err = k.SetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId, 2) + if err != nil { + return nil + } + block, exists, err = k.GetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId) + require.NoError(t, err) require.True(t, exists) require.Equal( t, @@ -86,8 +102,12 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 3) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + err = k.SetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId, 3) + if err != nil { + return nil + } + block, exists, err = k.GetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId) + require.NoError(t, err) require.True(t, exists) require.Equal( t, @@ -95,8 +115,12 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 10) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + err = k.SetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId, 10) + if err != nil { + return nil + } + block, exists, err = k.GetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId) + require.NoError(t, err) require.True(t, exists) require.Equal( t, @@ -104,21 +128,26 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) } + return nil }, expectedMultiStoreWrites: append( - getWriteKeys(constants.IsoCollateralPoolAddress, 4), + getWriteKeys(testSuffices[0], 4), append( - getWriteKeys(constants.Iso2CollateralPoolAddress, 4), - getWriteKeys(types.ModuleAddress, 4)..., + getWriteKeys(testSuffices[1], 4), + getWriteKeys(testSuffices[2], 4)..., )..., ), }, "Block height can be updated to same block height": { - setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - for i, collateralPoolAddr := range testCollateralPoolAddresses { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 0) - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) error { + for _, perpetualId := range testPerpetualIds { + err := k.SetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId, 0) + if err != nil { + return err + } + block, exists, err := k.GetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId) + require.NoError(t, err) require.True(t, exists) require.Equal( t, @@ -126,8 +155,12 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], 0) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + err = k.SetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId, 0) + if err != nil { + return err + } + block, exists, err = k.GetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId) + require.NoError(t, err) require.True(t, exists) require.Equal( t, @@ -135,21 +168,26 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) } + return nil }, expectedMultiStoreWrites: append( - getWriteKeys(constants.IsoCollateralPoolAddress, 2), + getWriteKeys(testSuffices[0], 2), append( - getWriteKeys(constants.Iso2CollateralPoolAddress, 2), - getWriteKeys(types.ModuleAddress, 2)..., + getWriteKeys(testSuffices[1], 2), + getWriteKeys(testSuffices[2], 2)..., )..., ), }, "Block height can be updated to different block heights for each collateral pool address": { - setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) { - for i, collateralPoolAddr := range testCollateralPoolAddresses { - k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], uint32(i)) - block, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + setupTestAndPerformAssertions: func(ctx sdk.Context, k keeper.Keeper) error { + for i, perpetualId := range testPerpetualIds { + err := k.SetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId, uint32(i)) + if err != nil { + return err + } + block, exists, err := k.GetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId) + require.NoError(t, err) require.True(t, exists) require.Equal( t, @@ -157,8 +195,12 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) - k.SetNegativeTncSubaccountSeenAtBlock(ctx, testPerpetualIds[i], uint32(2*i+1)) - block, exists = k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddr) + err = k.SetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId, uint32(2*i+1)) + if err != nil { + return err + } + block, exists, err = k.GetNegativeTncSubaccountSeenAtBlock(ctx, perpetualId) + require.NoError(t, err) require.True(t, exists) require.Equal( t, @@ -166,13 +208,14 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { block, ) } + return nil }, expectedMultiStoreWrites: append( - getWriteKeys(constants.IsoCollateralPoolAddress, 2), + getWriteKeys(testSuffices[0], 2), append( - getWriteKeys(constants.Iso2CollateralPoolAddress, 2), - getWriteKeys(types.ModuleAddress, 2)..., + getWriteKeys(testSuffices[1], 2), + getWriteKeys(testSuffices[2], 2)..., )..., ), }, @@ -190,10 +233,11 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { traceDecoder := &tracer.TraceDecoder{} ctx.MultiStore().SetTracer(traceDecoder) - tc.setupTestAndPerformAssertions( + err := tc.setupTestAndPerformAssertions( ctx, *subaccountsKeeper, ) + require.NoError(t, err) // Verify the writes were done in the expected order. traceDecoder.RequireKeyPrefixWrittenInSequence(t, tc.expectedMultiStoreWrites) @@ -207,18 +251,19 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock_PanicsOnDecreasingBlock(t *testi keepertest.CreateTestMarkets(t, ctx, pricesKeeper) keepertest.CreateTestLiquidityTiers(t, ctx, perpetualsKeeper) keepertest.CreateTestPerpetuals(t, ctx, perpetualsKeeper) - subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, uint32(0), 2) + err := subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, uint32(0), 2) + require.NoError(t, err) require.PanicsWithValue( t, "SetNegativeTncSubaccountSeenAtBlock: new block height (1) is less than the current block height (2)", - func() { subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, uint32(0), 1) }, + func() { _ = subaccountsKeeper.SetNegativeTncSubaccountSeenAtBlock(ctx, uint32(0), 1) }, ) } -func getWriteKeys(address sdk.AccAddress, times int) []string { +func getWriteKeys(suffix string, times int) []string { writeKeys := make([]string, times) for i := 0; i < times; i++ { - writeKeys[i] = types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + string(address) + writeKeys[i] = types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + suffix } return writeKeys } diff --git a/protocol/x/subaccounts/keeper/subaccount.go b/protocol/x/subaccounts/keeper/subaccount.go index 96db67ba17..bf04f14ab5 100644 --- a/protocol/x/subaccounts/keeper/subaccount.go +++ b/protocol/x/subaccounts/keeper/subaccount.go @@ -563,13 +563,13 @@ func (k Keeper) internalCanUpdateSubaccounts( // - There was a negative TNC subaccount seen for any of the collateral pools of subaccounts being updated // - There was a chain outage that lasted at least five minutes. if updateType == types.Withdrawal || updateType == types.Transfer { - collateralPoolAddresses, err := k.getCollateralPoolAddresses(ctx, settledUpdates) + negativeTncSubaccountStoreSuffices, err := k.getNegativeTncSubaccountStoreSuffices(ctx, settledUpdates) if err != nil { return false, nil, err } lastBlockNegativeTncSubaccountSeen, negativeTncSubaccountExists := k.getLastBlockNegativeSubaccountSeen( ctx, - collateralPoolAddresses, + negativeTncSubaccountStoreSuffices, ) currentBlock := uint32(ctx.BlockHeight()) @@ -966,41 +966,49 @@ func applyUpdatesToPositions[ return result, nil } -// getCollateralPoolAddresses gets a slice of collateral pool addresses for the subaccounts in the -// slice of `settledUpdate`s passed in. -// The slice will be de-duplicated and will contain unique collateral pool addresses. -func (k Keeper) getCollateralPoolAddresses( +// getNegativeTncSubaccountStoreSuffices gets a slice of negative tnc subaccount store suffices for +// the subaccounts in the slice of `settledUpdate`s passed in. +// The slice will be de-duplicated and will contain unique store suffices. +func (k Keeper) getNegativeTncSubaccountStoreSuffices( ctx sdk.Context, settledUpdates []settledUpdate, -) ([]sdk.AccAddress, error) { - collateralPoolAddressMap := make(map[string]bool) - collateralPoolAddresses := make([]sdk.AccAddress, 0) +) ( + suffices []string, + err error, +) { + sufficesMap := make(map[string]bool) + suffices = make([]string, 0) for _, u := range settledUpdates { - collateralPoolAddress, err := k.getCollateralPoolForSubaccount(ctx, u.SettledSubaccount) - if err != nil { - return nil, err + var suffix string + if len(u.SettledSubaccount.PerpetualPositions) == 0 { + suffix = types.CrossCollateralSuffix + } else { + suffix, err = k.getNegativeTncSubaccountStoreSuffx(ctx, u.SettledSubaccount.PerpetualPositions[0].PerpetualId) + if err != nil { + return nil, err + } } - if _, exists := collateralPoolAddressMap[collateralPoolAddress.String()]; !exists { - collateralPoolAddresses = append(collateralPoolAddresses, collateralPoolAddress) - collateralPoolAddressMap[collateralPoolAddress.String()] = true + if _, exists := sufficesMap[suffix]; !exists { + suffices = append(suffices, suffix) + sufficesMap[suffix] = true } } - return collateralPoolAddresses, nil + return suffices, nil } // getLastBlockNegativeSubaccountSeen gets the last block where a subaccount with negative total net -// collateral was seen for a slice of collateral pool addresses. +// collateral was seen for a slice of negative tnc subaccount store suffices. func (k Keeper) getLastBlockNegativeSubaccountSeen( ctx sdk.Context, - collateralPoolAddresses []sdk.AccAddress, + negativeTncSubaccountStoreSuffices []string, ) ( lastBlockNegativeSubaccountSeen uint32, negativeSubaccountExists bool, ) { lastBlockNegativeSubaccountSeen = uint32(0) negativeSubaccountExists = false - for _, collateralPoolAddress := range collateralPoolAddresses { - blockHeight, exists := k.GetNegativeTncSubaccountSeenAtBlock(ctx, collateralPoolAddress) + for _, storeSuffix := range negativeTncSubaccountStoreSuffices { + blockHeight, exists := k.getNegativeTncSubaccountSeenAtBlockWithSuffix(ctx, storeSuffix) if exists && blockHeight > lastBlockNegativeSubaccountSeen { lastBlockNegativeSubaccountSeen = blockHeight negativeSubaccountExists = true diff --git a/protocol/x/subaccounts/keeper/subaccount_test.go b/protocol/x/subaccounts/keeper/subaccount_test.go index 65b32eb7c3..92057b401b 100644 --- a/protocol/x/subaccounts/keeper/subaccount_test.go +++ b/protocol/x/subaccounts/keeper/subaccount_test.go @@ -3669,11 +3669,12 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { // Set the negative TNC subaccount seen at block in state if it's greater than 0. for perpetualId, negativeTncSubaccountSeenAtBlock := range tc.negativeTncSubaccountSeenAtBlock { if negativeTncSubaccountSeenAtBlock != 0 { - keeper.SetNegativeTncSubaccountSeenAtBlock( + err := keeper.SetNegativeTncSubaccountSeenAtBlock( ctx, perpetualId, negativeTncSubaccountSeenAtBlock, ) + require.NoError(t, err) } } diff --git a/protocol/x/subaccounts/types/expected_keepers.go b/protocol/x/subaccounts/types/expected_keepers.go index 4d30eb8174..e9ee2906fb 100644 --- a/protocol/x/subaccounts/types/expected_keepers.go +++ b/protocol/x/subaccounts/types/expected_keepers.go @@ -74,6 +74,7 @@ type PerpetualsKeeper interface { GetAllPerpetuals(ctx sdk.Context) []perptypes.Perpetual GetInsuranceFundName(ctx sdk.Context, perpetualId uint32) (string, error) GetInsuranceFundModuleAddress(ctx sdk.Context, perpetualId uint32) (sdk.AccAddress, error) + IsIsolatedPerpetual(ctx sdk.Context, perpetualId uint32) (bool, error) } // BankKeeper defines the expected interface needed to retrieve account balances. diff --git a/protocol/x/subaccounts/types/keys.go b/protocol/x/subaccounts/types/keys.go index f09a752c39..0d6089d20a 100644 --- a/protocol/x/subaccounts/types/keys.go +++ b/protocol/x/subaccounts/types/keys.go @@ -16,4 +16,7 @@ const ( // NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix is the prefix for the store key that // stores the last block a negative TNC subaccount was seen in state for a specific collateral pool. NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix = "NegSA:" + // Suffix for the store key to the last block a negative TNC subaccount was seen in state for the + // cross collateral pool. + CrossCollateralSuffix = "cross" ) diff --git a/protocol/x/subaccounts/types/query.pb.go b/protocol/x/subaccounts/types/query.pb.go index 3927ca4817..9c0bc41dc2 100644 --- a/protocol/x/subaccounts/types/query.pb.go +++ b/protocol/x/subaccounts/types/query.pb.go @@ -229,9 +229,9 @@ func (m *QuerySubaccountAllResponse) GetPagination() *query.PageResponse { // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a request type for // fetching information about whether withdrawals and transfers are blocked for -// a specific collateral pool. +// a collateral pool associated with the passed in perpetual id. type QueryGetWithdrawalAndTransfersBlockedInfoRequest struct { - CollateralPoolAddress string `protobuf:"bytes,1,opt,name=collateral_pool_address,json=collateralPoolAddress,proto3" json:"collateral_pool_address,omitempty"` + PerpetualId uint32 `protobuf:"varint,1,opt,name=perpetual_id,json=perpetualId,proto3" json:"perpetual_id,omitempty"` } func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) Reset() { @@ -271,11 +271,11 @@ func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) XXX_DiscardUnknown() var xxx_messageInfo_QueryGetWithdrawalAndTransfersBlockedInfoRequest proto.InternalMessageInfo -func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) GetCollateralPoolAddress() string { +func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) GetPerpetualId() uint32 { if m != nil { - return m.CollateralPoolAddress + return m.PerpetualId } - return "" + return 0 } // QueryGetWithdrawalAndTransfersBlockedInfoRequest is a response type for @@ -358,51 +358,50 @@ func init() { } var fileDescriptor_adc19ff1d5b72954 = []byte{ - // 697 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x4f, 0xd4, 0x40, - 0x14, 0xdf, 0x2e, 0x7f, 0x12, 0xc7, 0x70, 0x99, 0x20, 0x2c, 0x8d, 0x59, 0xc9, 0x66, 0x05, 0x34, - 0xd0, 0xba, 0x80, 0x31, 0x31, 0x21, 0x71, 0xf7, 0x20, 0x8a, 0x07, 0x70, 0xc1, 0x90, 0x98, 0x98, - 0x66, 0xda, 0x0e, 0xa5, 0x71, 0x98, 0x59, 0x3a, 0x53, 0xfe, 0x84, 0x70, 0x31, 0x5e, 0xbc, 0x99, - 0xf8, 0x01, 0xbc, 0x7a, 0x35, 0xfa, 0x21, 0x38, 0x12, 0xbd, 0x78, 0x32, 0x06, 0xfc, 0x08, 0x7e, - 0x00, 0xb3, 0x33, 0xd3, 0x6d, 0x17, 0x6c, 0x76, 0x35, 0xde, 0x3a, 0xf3, 0xde, 0xef, 0xbd, 0xdf, - 0xef, 0x37, 0xef, 0x15, 0x54, 0xfd, 0x43, 0xff, 0xa0, 0x15, 0x31, 0xc1, 0x3c, 0x46, 0x6c, 0x1e, - 0xbb, 0xc8, 0xf3, 0x58, 0x4c, 0x05, 0xb7, 0x77, 0x63, 0x1c, 0x1d, 0x5a, 0x32, 0x04, 0x4b, 0xd9, - 0x2c, 0x2b, 0x93, 0x65, 0x4e, 0x78, 0x8c, 0xef, 0x30, 0xee, 0xc8, 0xa0, 0xad, 0x0e, 0x0a, 0x64, - 0x8e, 0x06, 0x2c, 0x60, 0xea, 0xbe, 0xfd, 0xa5, 0x6f, 0xaf, 0x07, 0x8c, 0x05, 0x04, 0xdb, 0xa8, - 0x15, 0xda, 0x88, 0x52, 0x26, 0x90, 0x08, 0x19, 0x4d, 0x30, 0xb7, 0x55, 0x05, 0xdb, 0x45, 0x1c, - 0x2b, 0x06, 0xf6, 0x5e, 0xcd, 0xc5, 0x02, 0xd5, 0xec, 0x16, 0x0a, 0x42, 0x2a, 0x93, 0x75, 0xee, - 0xad, 0x5c, 0xea, 0xe9, 0xb7, 0x4a, 0xad, 0x78, 0x60, 0xe2, 0x69, 0xbb, 0xd8, 0x32, 0x16, 0xeb, - 0x9d, 0x58, 0x13, 0xef, 0xc6, 0x98, 0x0b, 0x68, 0x81, 0x21, 0xb6, 0x4f, 0x71, 0x54, 0x32, 0x26, - 0x8d, 0x99, 0x2b, 0x8d, 0xd2, 0x97, 0xcf, 0x73, 0xa3, 0x5a, 0x48, 0xdd, 0xf7, 0x23, 0xcc, 0xf9, - 0xba, 0x88, 0x42, 0x1a, 0x34, 0x55, 0x1a, 0x1c, 0x03, 0xc3, 0x34, 0xde, 0x71, 0x71, 0x54, 0x2a, - 0x4e, 0x1a, 0x33, 0x23, 0x4d, 0x7d, 0xaa, 0x60, 0x30, 0x2e, 0x9b, 0x64, 0x3b, 0xf0, 0x16, 0xa3, - 0x1c, 0xc3, 0x15, 0x00, 0x52, 0x4e, 0xb2, 0xcf, 0xd5, 0xf9, 0xaa, 0x95, 0x67, 0xaa, 0x95, 0x56, - 0x68, 0x0c, 0x9e, 0x7c, 0xbf, 0x51, 0x68, 0x66, 0xd0, 0x1d, 0x2d, 0x75, 0x42, 0x2e, 0x6b, 0x79, - 0x08, 0x40, 0xea, 0x93, 0x6e, 0x34, 0x65, 0x69, 0x35, 0x6d, 0x53, 0x2d, 0xf5, 0xac, 0xda, 0x54, - 0x6b, 0x0d, 0x05, 0x58, 0x63, 0x9b, 0x19, 0x64, 0xe5, 0xa3, 0x01, 0xcc, 0x0b, 0x62, 0xea, 0x84, - 0xe4, 0xea, 0x19, 0xf8, 0x77, 0x3d, 0x70, 0xb9, 0x8b, 0x72, 0x51, 0x52, 0x9e, 0xee, 0x49, 0x59, - 0x11, 0xe9, 0xe2, 0xfc, 0xda, 0x00, 0x77, 0x92, 0x57, 0xde, 0x0c, 0xc5, 0xb6, 0x1f, 0xa1, 0x7d, - 0x44, 0xea, 0xd4, 0xdf, 0x88, 0x10, 0xe5, 0x5b, 0x38, 0xe2, 0x0d, 0xc2, 0xbc, 0x97, 0xd8, 0x7f, - 0x4c, 0xb7, 0x58, 0x62, 0xd8, 0x1a, 0x18, 0xf7, 0x18, 0x21, 0x48, 0xe0, 0x08, 0x11, 0xa7, 0xc5, - 0x18, 0x71, 0x90, 0x7a, 0xf4, 0x9e, 0xe3, 0x70, 0x2d, 0x05, 0xae, 0x31, 0x46, 0x74, 0xb0, 0xf2, - 0xbe, 0x08, 0x6a, 0x7f, 0x41, 0x43, 0x3b, 0xba, 0x0a, 0x6e, 0x52, 0x1c, 0x20, 0x11, 0xee, 0x61, - 0x47, 0x50, 0xcf, 0x49, 0x0d, 0x72, 0x38, 0xc6, 0xd4, 0x41, 0xc2, 0x71, 0xdb, 0x30, 0xc9, 0x6a, - 0xa4, 0x39, 0x99, 0x24, 0x6f, 0x50, 0x2f, 0x75, 0x77, 0x1d, 0x63, 0x5a, 0x17, 0xb2, 0x3c, 0xbc, - 0x0f, 0x4c, 0x6f, 0x1b, 0x85, 0xd4, 0x61, 0xb1, 0x40, 0x01, 0xbe, 0x50, 0x45, 0x4d, 0xee, 0x98, - 0xcc, 0x58, 0x95, 0x09, 0x59, 0xec, 0x0b, 0x30, 0xbb, 0xdf, 0x61, 0xce, 0x1d, 0x44, 0x7d, 0x47, - 0x24, 0xe4, 0x9d, 0x98, 0xba, 0x8a, 0x7f, 0x5a, 0x6d, 0x40, 0x56, 0x9b, 0xce, 0x60, 0xb2, 0x72, - 0x9f, 0x25, 0x00, 0x5d, 0x7e, 0xfe, 0xd7, 0x20, 0x18, 0x92, 0x0e, 0xc1, 0x4f, 0x06, 0x00, 0x29, - 0x7d, 0xb8, 0x90, 0x3f, 0x42, 0xb9, 0xeb, 0x6b, 0xd6, 0x7a, 0x80, 0x2e, 0xaf, 0x63, 0x65, 0xe9, - 0xd5, 0xd7, 0x9f, 0xef, 0x8a, 0xf7, 0xe0, 0x5d, 0xbb, 0x8f, 0x5f, 0x88, 0x7d, 0x24, 0xd7, 0xfe, - 0xd8, 0x3e, 0x52, 0x7b, 0x7e, 0x0c, 0x3f, 0x18, 0x60, 0xa4, 0x6b, 0x2f, 0x7a, 0x12, 0xff, 0xd3, - 0xae, 0x9a, 0x8b, 0x7d, 0x13, 0xcf, 0xac, 0x5e, 0x65, 0x56, 0x72, 0x9f, 0x82, 0xd5, 0x7e, 0xb8, - 0xc3, 0x37, 0x45, 0x50, 0xed, 0x67, 0x0e, 0xe1, 0x4a, 0x6f, 0xeb, 0xfb, 0xdd, 0x29, 0xf3, 0xc9, - 0x7f, 0xa9, 0xa5, 0xf5, 0x3e, 0x92, 0x7a, 0x1b, 0xf0, 0x41, 0xbe, 0xde, 0xfc, 0x59, 0x4d, 0x26, - 0x35, 0xa4, 0x5b, 0xac, 0xb1, 0x79, 0x72, 0x56, 0x36, 0x4e, 0xcf, 0xca, 0xc6, 0x8f, 0xb3, 0xb2, - 0xf1, 0xf6, 0xbc, 0x5c, 0x38, 0x3d, 0x2f, 0x17, 0xbe, 0x9d, 0x97, 0x0b, 0xcf, 0x97, 0x82, 0x50, - 0x6c, 0xc7, 0xae, 0xe5, 0xb1, 0x9d, 0xee, 0x2e, 0x7b, 0x8b, 0x73, 0x72, 0x45, 0xec, 0xce, 0xcd, - 0x41, 0x57, 0x67, 0x71, 0xd8, 0xc2, 0xdc, 0x1d, 0x96, 0xd1, 0x85, 0xdf, 0x01, 0x00, 0x00, 0xff, - 0xff, 0x79, 0x40, 0x83, 0x76, 0x4c, 0x07, 0x00, 0x00, + // 687 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x4f, 0xd4, 0x4e, + 0x18, 0xde, 0x2e, 0x7f, 0x92, 0xdf, 0xf0, 0xe3, 0x32, 0x21, 0xb8, 0x34, 0x66, 0xc5, 0xcd, 0x0a, + 0x68, 0xa0, 0x75, 0x01, 0x63, 0x62, 0x42, 0xe2, 0xee, 0x41, 0x04, 0x0f, 0x68, 0x81, 0x90, 0x98, + 0x98, 0x66, 0xda, 0xbe, 0x94, 0xc6, 0x32, 0x53, 0x3a, 0x53, 0xfe, 0x84, 0x70, 0xf1, 0xe6, 0xcd, + 0xc4, 0x0f, 0xe0, 0xd5, 0xab, 0xd1, 0x0f, 0xc1, 0x91, 0xe8, 0xc5, 0x93, 0x31, 0xe0, 0x47, 0xf0, + 0x03, 0x98, 0x9d, 0xb6, 0xdb, 0x2e, 0xd8, 0xec, 0x6a, 0xbc, 0xb5, 0x33, 0xef, 0xf3, 0xbc, 0xcf, + 0xf3, 0xf4, 0x7d, 0x8b, 0xea, 0xce, 0x91, 0x73, 0x18, 0x84, 0x4c, 0x30, 0x9b, 0xf9, 0x3a, 0x8f, + 0x2c, 0x62, 0xdb, 0x2c, 0xa2, 0x82, 0xeb, 0x7b, 0x11, 0x84, 0x47, 0x9a, 0xbc, 0xc2, 0x95, 0x7c, + 0x95, 0x96, 0xab, 0x52, 0x27, 0x6c, 0xc6, 0x77, 0x19, 0x37, 0xe5, 0xa5, 0x1e, 0xbf, 0xc4, 0x20, + 0x75, 0xcc, 0x65, 0x2e, 0x8b, 0xcf, 0xdb, 0x4f, 0xc9, 0xe9, 0x75, 0x97, 0x31, 0xd7, 0x07, 0x9d, + 0x04, 0x9e, 0x4e, 0x28, 0x65, 0x82, 0x08, 0x8f, 0xd1, 0x14, 0x73, 0x27, 0x66, 0xd0, 0x2d, 0xc2, + 0x21, 0x56, 0xa0, 0xef, 0x37, 0x2c, 0x10, 0xa4, 0xa1, 0x07, 0xc4, 0xf5, 0xa8, 0x2c, 0x4e, 0x6a, + 0x6f, 0x17, 0x4a, 0xcf, 0x9e, 0xe3, 0xd2, 0x9a, 0x8d, 0x26, 0x9e, 0xb5, 0xc9, 0x96, 0x41, 0xac, + 0x77, 0xee, 0x0c, 0xd8, 0x8b, 0x80, 0x0b, 0xac, 0xa1, 0x21, 0x76, 0x40, 0x21, 0xac, 0x28, 0x93, + 0xca, 0xcc, 0x7f, 0xad, 0xca, 0xe7, 0x4f, 0x73, 0x63, 0x89, 0x91, 0xa6, 0xe3, 0x84, 0xc0, 0xf9, + 0xba, 0x08, 0x3d, 0xea, 0x1a, 0x71, 0x19, 0x1e, 0x47, 0xc3, 0x34, 0xda, 0xb5, 0x20, 0xac, 0x94, + 0x27, 0x95, 0x99, 0x51, 0x23, 0x79, 0xab, 0x01, 0xba, 0x26, 0x9b, 0xe4, 0x3b, 0xf0, 0x80, 0x51, + 0x0e, 0x78, 0x15, 0xa1, 0x4c, 0x93, 0xec, 0x33, 0x32, 0x5f, 0xd7, 0x8a, 0x42, 0xd5, 0x32, 0x86, + 0xd6, 0xe0, 0xe9, 0xb7, 0x1b, 0x25, 0x23, 0x87, 0xee, 0x78, 0x69, 0xfa, 0xfe, 0x55, 0x2f, 0x8f, + 0x10, 0xca, 0x72, 0x4a, 0x1a, 0x4d, 0x69, 0x89, 0x9b, 0x76, 0xa8, 0x5a, 0xfc, 0x59, 0x93, 0x50, + 0xb5, 0xa7, 0xc4, 0x85, 0x04, 0x6b, 0xe4, 0x90, 0xb5, 0x0f, 0x0a, 0x52, 0x2f, 0x99, 0x69, 0xfa, + 0x7e, 0xa1, 0x9f, 0x81, 0xbf, 0xf7, 0x83, 0x97, 0xbb, 0x24, 0x97, 0xa5, 0xe4, 0xe9, 0x9e, 0x92, + 0x63, 0x21, 0x5d, 0x9a, 0x37, 0xd1, 0xdd, 0xf4, 0x23, 0x6f, 0x79, 0x62, 0xc7, 0x09, 0xc9, 0x01, + 0xf1, 0x9b, 0xd4, 0xd9, 0x08, 0x09, 0xe5, 0xdb, 0x10, 0xf2, 0x96, 0xcf, 0xec, 0x97, 0xe0, 0xac, + 0xd0, 0x6d, 0x96, 0xe6, 0x75, 0x13, 0xfd, 0x1f, 0x40, 0x18, 0x80, 0x88, 0x88, 0x6f, 0x7a, 0x8e, + 0x4c, 0x6c, 0xd4, 0x18, 0xe9, 0x9c, 0xad, 0x38, 0xb5, 0x77, 0x65, 0xd4, 0xf8, 0x03, 0xde, 0x24, + 0xa1, 0x35, 0x74, 0x8b, 0x82, 0x4b, 0x84, 0xb7, 0x0f, 0xa6, 0xa0, 0xb6, 0x99, 0x19, 0x36, 0x39, + 0x00, 0x35, 0x89, 0x30, 0xad, 0x36, 0x2c, 0xe9, 0x38, 0x99, 0x16, 0x6f, 0x50, 0x3b, 0x4b, 0x6b, + 0x1d, 0x80, 0x36, 0x85, 0xa4, 0xc7, 0x0f, 0x90, 0x6a, 0xef, 0x10, 0x8f, 0x9a, 0x2c, 0x12, 0xc4, + 0x85, 0x4b, 0x2c, 0xf1, 0x24, 0x8e, 0xcb, 0x8a, 0x35, 0x59, 0x90, 0xc7, 0xbe, 0x40, 0xb3, 0x07, + 0x1d, 0xe5, 0xdc, 0x24, 0xd4, 0x31, 0x45, 0x2a, 0xde, 0x8c, 0xa8, 0x15, 0xeb, 0xcf, 0xd8, 0x06, + 0x24, 0xdb, 0x74, 0x0e, 0x93, 0xb7, 0xbb, 0x99, 0x02, 0x12, 0xfa, 0xf9, 0x9f, 0x83, 0x68, 0x48, + 0x26, 0x84, 0x3f, 0x2a, 0x08, 0x65, 0xf2, 0xf1, 0x42, 0xf1, 0x48, 0x14, 0xae, 0xa3, 0xda, 0xe8, + 0x01, 0xba, 0xba, 0x5e, 0xb5, 0xa5, 0x57, 0x5f, 0x7e, 0xbc, 0x2d, 0xdf, 0xc7, 0xf7, 0xf4, 0x3e, + 0x7e, 0x09, 0xfa, 0xb1, 0x5c, 0xe3, 0x13, 0xfd, 0x38, 0xde, 0xdb, 0x13, 0xfc, 0x5e, 0x41, 0xa3, + 0x5d, 0x73, 0xde, 0x53, 0xf8, 0xef, 0x76, 0x4f, 0x5d, 0xec, 0x5b, 0x78, 0x6e, 0x95, 0x6a, 0xb3, + 0x52, 0xfb, 0x14, 0xae, 0xf7, 0xa3, 0x1d, 0xbf, 0x2e, 0xa3, 0x7a, 0x3f, 0x73, 0x88, 0x57, 0x7b, + 0x47, 0xdf, 0xef, 0x92, 0xa8, 0x4f, 0xfe, 0x09, 0x57, 0xe2, 0xf7, 0xb1, 0xf4, 0xdb, 0xc2, 0x0f, + 0x8b, 0xfd, 0x16, 0xcf, 0x6a, 0x3a, 0xa9, 0x1e, 0xdd, 0x66, 0xad, 0xad, 0xd3, 0xf3, 0xaa, 0x72, + 0x76, 0x5e, 0x55, 0xbe, 0x9f, 0x57, 0x95, 0x37, 0x17, 0xd5, 0xd2, 0xd9, 0x45, 0xb5, 0xf4, 0xf5, + 0xa2, 0x5a, 0x7a, 0xbe, 0xe4, 0x7a, 0x62, 0x27, 0xb2, 0x34, 0x9b, 0xed, 0x76, 0x77, 0xd9, 0x5f, + 0x9c, 0x93, 0x2b, 0xa2, 0x77, 0x4e, 0x0e, 0xbb, 0x3a, 0x8b, 0xa3, 0x00, 0xb8, 0x35, 0x2c, 0x6f, + 0x17, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0xed, 0x0b, 0x2a, 0xec, 0x1c, 0x07, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -737,12 +736,10 @@ func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) MarshalToSizedBuffer( _ = i var l int _ = l - if len(m.CollateralPoolAddress) > 0 { - i -= len(m.CollateralPoolAddress) - copy(dAtA[i:], m.CollateralPoolAddress) - i = encodeVarintQuery(dAtA, i, uint64(len(m.CollateralPoolAddress))) + if m.PerpetualId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.PerpetualId)) i-- - dAtA[i] = 0xa + dAtA[i] = 0x8 } return len(dAtA) - i, nil } @@ -861,9 +858,8 @@ func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) Size() (n int) { } var l int _ = l - l = len(m.CollateralPoolAddress) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) + if m.PerpetualId != 0 { + n += 1 + sovQuery(uint64(m.PerpetualId)) } return n } @@ -1312,10 +1308,10 @@ func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) Unmarshal(dAtA []byte } switch fieldNum { case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CollateralPoolAddress", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PerpetualId", wireType) } - var stringLen uint64 + m.PerpetualId = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1325,24 +1321,11 @@ func (m *QueryGetWithdrawalAndTransfersBlockedInfoRequest) Unmarshal(dAtA []byte } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.PerpetualId |= uint32(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.CollateralPoolAddress = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) From f15a0d54dddcc6388b13229edd3781ba7d62b956 Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Fri, 22 Mar 2024 10:38:16 -0400 Subject: [PATCH 11/16] Fix syntax error from merging main. --- protocol/x/subaccounts/keeper/subaccount.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/x/subaccounts/keeper/subaccount.go b/protocol/x/subaccounts/keeper/subaccount.go index 7669ecbbdc..acc36df87d 100644 --- a/protocol/x/subaccounts/keeper/subaccount.go +++ b/protocol/x/subaccounts/keeper/subaccount.go @@ -991,7 +991,7 @@ func applyUpdatesToPositions[ // The slice will be de-duplicated and will contain unique store suffices. func (k Keeper) getNegativeTncSubaccountStoreSuffices( ctx sdk.Context, - settledUpdates []settledUpdate, + settledUpdates []SettledUpdate, ) ( suffices []string, err error, From ad896cc5225035d5c2a1334e4daf6c9dea9f6d79 Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:14:45 -0400 Subject: [PATCH 12/16] Re-organize negative tnc subaccount functions. --- .../keeper/negative_tnc_subaccount.go | 51 +++++++++++++++++++ protocol/x/subaccounts/keeper/subaccount.go | 51 ------------------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go index 9d81b39b7e..ef54342f8a 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go @@ -117,3 +117,54 @@ func (k Keeper) getNegativeTncSubaccountStoreSuffx( return lib.UintToString(perpetualId), nil } } + +// getNegativeTncSubaccountStoreSuffices gets a slice of negative tnc subaccount store suffices for +// the subaccounts in the slice of `settledUpdate`s passed in. +// The slice will be de-duplicated and will contain unique store suffices. +func (k Keeper) getNegativeTncSubaccountStoreSuffices( + ctx sdk.Context, + settledUpdates []SettledUpdate, +) ( + suffices []string, + err error, +) { + sufficesMap := make(map[string]bool) + suffices = make([]string, 0) + for _, u := range settledUpdates { + var suffix string + if len(u.SettledSubaccount.PerpetualPositions) == 0 { + suffix = types.CrossCollateralSuffix + } else { + suffix, err = k.getNegativeTncSubaccountStoreSuffx(ctx, u.SettledSubaccount.PerpetualPositions[0].PerpetualId) + if err != nil { + return nil, err + } + } + if _, exists := sufficesMap[suffix]; !exists { + suffices = append(suffices, suffix) + sufficesMap[suffix] = true + } + } + return suffices, nil +} + +// getLastBlockNegativeSubaccountSeen gets the last block where a subaccount with negative total net +// collateral was seen for a slice of negative tnc subaccount store suffices. +func (k Keeper) getLastBlockNegativeSubaccountSeen( + ctx sdk.Context, + negativeTncSubaccountStoreSuffices []string, +) ( + lastBlockNegativeSubaccountSeen uint32, + negativeSubaccountExists bool, +) { + lastBlockNegativeSubaccountSeen = uint32(0) + negativeSubaccountExists = false + for _, storeSuffix := range negativeTncSubaccountStoreSuffices { + blockHeight, exists := k.getNegativeTncSubaccountSeenAtBlockWithSuffix(ctx, storeSuffix) + if exists && blockHeight > lastBlockNegativeSubaccountSeen { + lastBlockNegativeSubaccountSeen = blockHeight + negativeSubaccountExists = true + } + } + return lastBlockNegativeSubaccountSeen, negativeSubaccountExists +} diff --git a/protocol/x/subaccounts/keeper/subaccount.go b/protocol/x/subaccounts/keeper/subaccount.go index acc36df87d..5d42803851 100644 --- a/protocol/x/subaccounts/keeper/subaccount.go +++ b/protocol/x/subaccounts/keeper/subaccount.go @@ -985,54 +985,3 @@ func applyUpdatesToPositions[ return result, nil } - -// getNegativeTncSubaccountStoreSuffices gets a slice of negative tnc subaccount store suffices for -// the subaccounts in the slice of `settledUpdate`s passed in. -// The slice will be de-duplicated and will contain unique store suffices. -func (k Keeper) getNegativeTncSubaccountStoreSuffices( - ctx sdk.Context, - settledUpdates []SettledUpdate, -) ( - suffices []string, - err error, -) { - sufficesMap := make(map[string]bool) - suffices = make([]string, 0) - for _, u := range settledUpdates { - var suffix string - if len(u.SettledSubaccount.PerpetualPositions) == 0 { - suffix = types.CrossCollateralSuffix - } else { - suffix, err = k.getNegativeTncSubaccountStoreSuffx(ctx, u.SettledSubaccount.PerpetualPositions[0].PerpetualId) - if err != nil { - return nil, err - } - } - if _, exists := sufficesMap[suffix]; !exists { - suffices = append(suffices, suffix) - sufficesMap[suffix] = true - } - } - return suffices, nil -} - -// getLastBlockNegativeSubaccountSeen gets the last block where a subaccount with negative total net -// collateral was seen for a slice of negative tnc subaccount store suffices. -func (k Keeper) getLastBlockNegativeSubaccountSeen( - ctx sdk.Context, - negativeTncSubaccountStoreSuffices []string, -) ( - lastBlockNegativeSubaccountSeen uint32, - negativeSubaccountExists bool, -) { - lastBlockNegativeSubaccountSeen = uint32(0) - negativeSubaccountExists = false - for _, storeSuffix := range negativeTncSubaccountStoreSuffices { - blockHeight, exists := k.getNegativeTncSubaccountSeenAtBlockWithSuffix(ctx, storeSuffix) - if exists && blockHeight > lastBlockNegativeSubaccountSeen { - lastBlockNegativeSubaccountSeen = blockHeight - negativeSubaccountExists = true - } - } - return lastBlockNegativeSubaccountSeen, negativeSubaccountExists -} From 1416c16f00c2ca82aefe3c0e0773f77eff3c8b15 Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:20:36 -0400 Subject: [PATCH 13/16] Slight refactor. --- .../subaccounts/keeper/negative_tnc_subaccount.go | 14 +++++++++++--- protocol/x/subaccounts/keeper/subaccount.go | 9 ++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go index ef54342f8a..59f533208e 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go @@ -149,14 +149,22 @@ func (k Keeper) getNegativeTncSubaccountStoreSuffices( } // getLastBlockNegativeSubaccountSeen gets the last block where a subaccount with negative total net -// collateral was seen for a slice of negative tnc subaccount store suffices. +// collateral was seen for subaccounts in a slice of settled updates. func (k Keeper) getLastBlockNegativeSubaccountSeen( ctx sdk.Context, - negativeTncSubaccountStoreSuffices []string, + settledUpdates []SettledUpdate, ) ( lastBlockNegativeSubaccountSeen uint32, negativeSubaccountExists bool, + err error, ) { + negativeTncSubaccountStoreSuffices, err := k.getNegativeTncSubaccountStoreSuffices( + ctx, + settledUpdates, + ) + if err != nil { + return uint32(0), false, err + } lastBlockNegativeSubaccountSeen = uint32(0) negativeSubaccountExists = false for _, storeSuffix := range negativeTncSubaccountStoreSuffices { @@ -166,5 +174,5 @@ func (k Keeper) getLastBlockNegativeSubaccountSeen( negativeSubaccountExists = true } } - return lastBlockNegativeSubaccountSeen, negativeSubaccountExists + return lastBlockNegativeSubaccountSeen, negativeSubaccountExists, nil } diff --git a/protocol/x/subaccounts/keeper/subaccount.go b/protocol/x/subaccounts/keeper/subaccount.go index 5d42803851..36c6752db9 100644 --- a/protocol/x/subaccounts/keeper/subaccount.go +++ b/protocol/x/subaccounts/keeper/subaccount.go @@ -583,14 +583,13 @@ func (k Keeper) internalCanUpdateSubaccounts( // - There was a negative TNC subaccount seen for any of the collateral pools of subaccounts being updated // - There was a chain outage that lasted at least five minutes. if updateType == types.Withdrawal || updateType == types.Transfer { - negativeTncSubaccountStoreSuffices, err := k.getNegativeTncSubaccountStoreSuffices(ctx, settledUpdates) + lastBlockNegativeTncSubaccountSeen, negativeTncSubaccountExists, err := k.getLastBlockNegativeSubaccountSeen( + ctx, + settledUpdates, + ) if err != nil { return false, nil, err } - lastBlockNegativeTncSubaccountSeen, negativeTncSubaccountExists := k.getLastBlockNegativeSubaccountSeen( - ctx, - negativeTncSubaccountStoreSuffices, - ) currentBlock := uint32(ctx.BlockHeight()) // Panic if the current block is less than the last block a negative TNC subaccount was seen. From 85542d2a8379e0353450010baffe10abe116b770 Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:57:07 -0400 Subject: [PATCH 14/16] Fix misspellings. --- .../keeper/negative_tnc_subaccount.go | 24 ++++++++--------- .../keeper/negative_tnc_subaccount_test.go | 26 +++++++++---------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go index 59f533208e..382212781a 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go @@ -118,18 +118,18 @@ func (k Keeper) getNegativeTncSubaccountStoreSuffx( } } -// getNegativeTncSubaccountStoreSuffices gets a slice of negative tnc subaccount store suffices for +// getNegativeTncSubaccountStoresuffixes gets a slice of negative tnc subaccount store suffixes for // the subaccounts in the slice of `settledUpdate`s passed in. -// The slice will be de-duplicated and will contain unique store suffices. -func (k Keeper) getNegativeTncSubaccountStoreSuffices( +// The slice will be de-duplicated and will contain unique store suffixes. +func (k Keeper) getNegativeTncSubaccountStoresuffixes( ctx sdk.Context, settledUpdates []SettledUpdate, ) ( - suffices []string, + suffixes []string, err error, ) { - sufficesMap := make(map[string]bool) - suffices = make([]string, 0) + suffixesMap := make(map[string]bool) + suffixes = make([]string, 0) for _, u := range settledUpdates { var suffix string if len(u.SettledSubaccount.PerpetualPositions) == 0 { @@ -140,12 +140,12 @@ func (k Keeper) getNegativeTncSubaccountStoreSuffices( return nil, err } } - if _, exists := sufficesMap[suffix]; !exists { - suffices = append(suffices, suffix) - sufficesMap[suffix] = true + if _, exists := suffixesMap[suffix]; !exists { + suffixes = append(suffixes, suffix) + suffixesMap[suffix] = true } } - return suffices, nil + return suffixes, nil } // getLastBlockNegativeSubaccountSeen gets the last block where a subaccount with negative total net @@ -158,7 +158,7 @@ func (k Keeper) getLastBlockNegativeSubaccountSeen( negativeSubaccountExists bool, err error, ) { - negativeTncSubaccountStoreSuffices, err := k.getNegativeTncSubaccountStoreSuffices( + negativeTncSubaccountStoresuffixes, err := k.getNegativeTncSubaccountStoresuffixes( ctx, settledUpdates, ) @@ -167,7 +167,7 @@ func (k Keeper) getLastBlockNegativeSubaccountSeen( } lastBlockNegativeSubaccountSeen = uint32(0) negativeSubaccountExists = false - for _, storeSuffix := range negativeTncSubaccountStoreSuffices { + for _, storeSuffix := range negativeTncSubaccountStoresuffixes { blockHeight, exists := k.getNegativeTncSubaccountSeenAtBlockWithSuffix(ctx, storeSuffix) if exists && blockHeight > lastBlockNegativeSubaccountSeen { lastBlockNegativeSubaccountSeen = blockHeight diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go index 1a9fa31759..2f0230c69a 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount_test.go @@ -19,7 +19,7 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { constants.Iso2Usd_IsolatedMarket.Params.Id, constants.BtcUsd_NoMarginRequirement.Params.Id, } - testSuffices := []string{ + testsuffixes := []string{ lib.UintToString(constants.IsoUsd_IsolatedMarket.Params.Id), lib.UintToString(constants.Iso2Usd_IsolatedMarket.Params.Id), types.CrossCollateralSuffix, @@ -68,9 +68,9 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, expectedMultiStoreWrites: []string{ - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + testSuffices[0], - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + testSuffices[1], - types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + testSuffices[2], + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + testsuffixes[0], + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + testsuffixes[1], + types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix + testsuffixes[2], }, }, "Block height can be updated more than once": { @@ -132,10 +132,10 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, expectedMultiStoreWrites: append( - getWriteKeys(testSuffices[0], 4), + getWriteKeys(testsuffixes[0], 4), append( - getWriteKeys(testSuffices[1], 4), - getWriteKeys(testSuffices[2], 4)..., + getWriteKeys(testsuffixes[1], 4), + getWriteKeys(testsuffixes[2], 4)..., )..., ), }, @@ -172,10 +172,10 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, expectedMultiStoreWrites: append( - getWriteKeys(testSuffices[0], 2), + getWriteKeys(testsuffixes[0], 2), append( - getWriteKeys(testSuffices[1], 2), - getWriteKeys(testSuffices[2], 2)..., + getWriteKeys(testsuffixes[1], 2), + getWriteKeys(testsuffixes[2], 2)..., )..., ), }, @@ -212,10 +212,10 @@ func TestGetSetNegativeTncSubaccountSeenAtBlock(t *testing.T) { }, expectedMultiStoreWrites: append( - getWriteKeys(testSuffices[0], 2), + getWriteKeys(testsuffixes[0], 2), append( - getWriteKeys(testSuffices[1], 2), - getWriteKeys(testSuffices[2], 2)..., + getWriteKeys(testsuffixes[1], 2), + getWriteKeys(testsuffixes[2], 2)..., )..., ), }, From 3452f8927132362c15b4ce94516c8d8fd73e3e1b Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Fri, 22 Mar 2024 12:58:42 -0400 Subject: [PATCH 15/16] Fix remaining misspelled function name. --- protocol/x/subaccounts/keeper/negative_tnc_subaccount.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go index 382212781a..04bc0867b3 100644 --- a/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go +++ b/protocol/x/subaccounts/keeper/negative_tnc_subaccount.go @@ -22,7 +22,7 @@ func (k Keeper) GetNegativeTncSubaccountSeenAtBlock( []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix), ) - suffix, err := k.getNegativeTncSubaccountStoreSuffx(ctx, perpetualId) + suffix, err := k.getNegativeTncSubaccountStoreSuffix(ctx, perpetualId) if err != nil { return 0, false, err } @@ -77,7 +77,7 @@ func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( []byte(types.NegativeTncSubaccountForCollateralPoolSeenAtBlockKeyPrefix), ) - storeSuffix, err := k.getNegativeTncSubaccountStoreSuffx(ctx, perpetualId) + storeSuffix, err := k.getNegativeTncSubaccountStoreSuffix(ctx, perpetualId) if err != nil { return err } @@ -103,7 +103,7 @@ func (k Keeper) SetNegativeTncSubaccountSeenAtBlock( return nil } -func (k Keeper) getNegativeTncSubaccountStoreSuffx( +func (k Keeper) getNegativeTncSubaccountStoreSuffix( ctx sdk.Context, perpetualId uint32, ) (string, error) { @@ -135,7 +135,7 @@ func (k Keeper) getNegativeTncSubaccountStoresuffixes( if len(u.SettledSubaccount.PerpetualPositions) == 0 { suffix = types.CrossCollateralSuffix } else { - suffix, err = k.getNegativeTncSubaccountStoreSuffx(ctx, u.SettledSubaccount.PerpetualPositions[0].PerpetualId) + suffix, err = k.getNegativeTncSubaccountStoreSuffix(ctx, u.SettledSubaccount.PerpetualPositions[0].PerpetualId) if err != nil { return nil, err } From d6bca1ad05e0712e51c3101fc24dfdc60253b3be Mon Sep 17 00:00:00 2001 From: Vincent Chau <99756290+vincentwschau@users.noreply.github.com> Date: Fri, 22 Mar 2024 14:43:12 -0400 Subject: [PATCH 16/16] Fix issues from merge. --- .../x/clob/keeper/process_operations_test.go | 20 ++++++++-------- protocol/x/subaccounts/keeper/oimf_test.go | 1 - .../x/subaccounts/keeper/subaccount_test.go | 24 +++++++++---------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/protocol/x/clob/keeper/process_operations_test.go b/protocol/x/clob/keeper/process_operations_test.go index 3bbd49b2e8..6d1e0072fb 100644 --- a/protocol/x/clob/keeper/process_operations_test.go +++ b/protocol/x/clob/keeper/process_operations_test.go @@ -1116,9 +1116,9 @@ func TestProcessProposerOperations(t *testing.T) { "Zero-fill deleveraging succeeds when the account is negative TNC and updates the last negative TNC subaccount " + "seen block number in state for an isolated perpetual collateral pool if the subaccount is isolated to the " + "isolated perpetual": { - perpetuals: []*perptypes.Perpetual{ - &constants.BtcUsd_NoMarginRequirement, - &constants.IsoUsd_IsolatedMarket, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_NoMarginRequirement, + constants.IsoUsd_IsolatedMarket, }, perpetualFeeParams: &constants.PerpetualFeeParams, clobPairs: []types.ClobPair{ @@ -1158,9 +1158,9 @@ func TestProcessProposerOperations(t *testing.T) { "Zero-fill deleveraging succeeds when the account is negative TNC and has a position in final settlement" + " market. It updates the last negative TNC subaccount seen block number in state for an isolated perpetual" + " collateral pool if the subaccount is isolated to the isolated perpetual": { - perpetuals: []*perptypes.Perpetual{ - &constants.BtcUsd_100PercentMarginRequirement, - &constants.IsoUsd_IsolatedMarket, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_100PercentMarginRequirement, + constants.IsoUsd_IsolatedMarket, }, perpetualFeeParams: &constants.PerpetualFeeParams, clobPairs: []types.ClobPair{ @@ -1203,10 +1203,10 @@ func TestProcessProposerOperations(t *testing.T) { "Zero-fill deleveraging succeeds when there's multiple zero-fill deleveraging events for the different subaccount " + "and perpetual ID. It updates the last negative TNC subaccount seen block number in state for both isolated " + "perpetual collateral pools if the subaccounts are isolated to different isolated perpetuals": { - perpetuals: []*perptypes.Perpetual{ - &constants.BtcUsd_NoMarginRequirement, - &constants.IsoUsd_IsolatedMarket, - &constants.Iso2Usd_IsolatedMarket, + perpetuals: []perptypes.Perpetual{ + constants.BtcUsd_NoMarginRequirement, + constants.IsoUsd_IsolatedMarket, + constants.Iso2Usd_IsolatedMarket, }, perpetualFeeParams: &constants.PerpetualFeeParams, clobPairs: []types.ClobPair{ diff --git a/protocol/x/subaccounts/keeper/oimf_test.go b/protocol/x/subaccounts/keeper/oimf_test.go index 16bcce5eb7..6282188f05 100644 --- a/protocol/x/subaccounts/keeper/oimf_test.go +++ b/protocol/x/subaccounts/keeper/oimf_test.go @@ -343,7 +343,6 @@ func TestGetDeltaOpenInterestFromPerpMatchUpdates(t *testing.T) { tc.expectedUpdatedPerpId, updatedPerpId, ) - fmt.Printf("deltaOpenInterest: %+v, tc.expectedDelta: %+v\n", deltaOpenInterest == nil, tc.expectedDelta == nil) require.Zerof( t, tc.expectedDelta.Cmp(deltaOpenInterest), diff --git a/protocol/x/subaccounts/keeper/subaccount_test.go b/protocol/x/subaccounts/keeper/subaccount_test.go index f30dcd501e..1999d6b6f0 100644 --- a/protocol/x/subaccounts/keeper/subaccount_test.go +++ b/protocol/x/subaccounts/keeper/subaccount_test.go @@ -2918,7 +2918,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { collateral pool`: { expectedQuoteBalance: big.NewInt(-100), expectedSuccess: true, - expectedSuccessPerUpdate: []types.UpdateResult{types.Success, types.Success}, + expectedSuccessPerUpdate: []types.UpdateResult{types.Success}, perpetuals: []perptypes.Perpetual{ constants.BtcUsd_SmallMarginRequirement, constants.IsoUsd_IsolatedMarket, @@ -2949,16 +2949,6 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { { AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(-100)), }, - { - SubaccountId: secondSubaccountId, - AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(25_000_000_000)), // $25,000 - PerpetualUpdates: []types.PerpetualUpdate{ - { - PerpetualId: uint32(0), - BigQuantumsDelta: big.NewInt(-50_000_000), // .5 BTC - }, - }, - }, }, msgSenderEnabled: true, @@ -3323,7 +3313,7 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, expectedQuoteBalance: big.NewInt(0), expectedSuccess: true, - expectedSuccessPerUpdate: []types.UpdateResult{types.Success}, + expectedSuccessPerUpdate: []types.UpdateResult{types.Success, types.Success}, perpetuals: []perptypes.Perpetual{ constants.BtcUsd_NoMarginRequirement, }, @@ -3357,6 +3347,16 @@ func TestUpdateSubaccounts_WithdrawalsBlocked(t *testing.T) { }, }, }, + { + SubaccountId: secondSubaccountId, + AssetUpdates: testutil.CreateUsdcAssetUpdate(big.NewInt(25_000_000_000)), // $25,000 + PerpetualUpdates: []types.PerpetualUpdate{ + { + PerpetualId: uint32(0), + BigQuantumsDelta: big.NewInt(-50_000_000), // .5 BTC + }, + }, + }, }, msgSenderEnabled: false,