From 8f36ca07f44cb00e76a138cb4dfaa9e63b0ea010 Mon Sep 17 00:00:00 2001 From: Shrenuj Bansal Date: Wed, 6 Mar 2024 00:25:24 -0500 Subject: [PATCH] Move SA module address transfers to use perpetual based SA accounts Signed-off-by: Shrenuj Bansal --- protocol/testutil/constants/positions.go | 7 + protocol/x/clob/abci_test.go | 2 +- protocol/x/clob/keeper/liquidations_test.go | 28 ++- protocol/x/clob/keeper/mev_test.go | 7 + protocol/x/clob/keeper/orders_test.go | 4 +- .../process_operations_liquidations_test.go | 94 +++---- .../process_operations_long_term_test.go | 74 +++--- ...ess_operations_stateful_validation_test.go | 12 +- .../x/clob/keeper/process_single_match.go | 1 + protocol/x/clob/types/expected_keepers.go | 6 +- protocol/x/subaccounts/keeper/subaccount.go | 13 + protocol/x/subaccounts/keeper/transfer.go | 47 ++-- .../x/subaccounts/keeper/transfer_test.go | 232 +++++++++++++----- .../x/subaccounts/types/expected_keepers.go | 1 + 14 files changed, 342 insertions(+), 186 deletions(-) diff --git a/protocol/testutil/constants/positions.go b/protocol/testutil/constants/positions.go index 1489bb4770..125af3e227 100644 --- a/protocol/testutil/constants/positions.go +++ b/protocol/testutil/constants/positions.go @@ -73,6 +73,13 @@ var ( PerpetualId: 1, Quantums: dtypes.NewIntFromBigInt(BigNegMaxUint64()), // 18,446,744,070 ETH, -$55,340,232,210,000 notional. } + // Long position for arbitrary isolated market + PerpetualPosition_OneISOLong = satypes.PerpetualPosition{ + PerpetualId: 3, + Quantums: dtypes.NewInt(100_000_000), + FundingIndex: dtypes.NewInt(0), + } + // Asset Positions Usdc_Asset_0 = satypes.AssetPosition{ AssetId: 0, diff --git a/protocol/x/clob/abci_test.go b/protocol/x/clob/abci_test.go index 7af637abc2..44d2d9af36 100644 --- a/protocol/x/clob/abci_test.go +++ b/protocol/x/clob/abci_test.go @@ -1338,7 +1338,7 @@ func TestPrepareCheckState(t *testing.T) { constants.Usdc.Denom, ).Return(sdk.NewCoin(constants.Usdc.Denom, sdkmath.NewIntFromBigInt(new(big.Int)))) mockBankKeeper.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, mock.Anything, mock.Anything, diff --git a/protocol/x/clob/keeper/liquidations_test.go b/protocol/x/clob/keeper/liquidations_test.go index a69a7c817d..ec916312e1 100644 --- a/protocol/x/clob/keeper/liquidations_test.go +++ b/protocol/x/clob/keeper/liquidations_test.go @@ -235,25 +235,25 @@ func TestPlacePerpetualLiquidation(t *testing.T) { memClob := memclob.NewMemClobPriceTimePriority(false) mockBankKeeper := &mocks.BankKeeper{} mockBankKeeper.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.Anything, ).Return(nil) mockBankKeeper.On( "SendCoins", mock.Anything, authtypes.NewModuleAddress(satypes.ModuleName), - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + perptypes.InsuranceFundModuleAddress, mock.Anything, ).Return(nil) // Fee collector does not have any funds. mockBankKeeper.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - authtypes.FeeCollectorName, - satypes.ModuleName, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), + satypes.ModuleAddress, mock.Anything, ).Return(sdkerrors.ErrInsufficientFunds) // Give the insurance fund a 1M USDC balance. @@ -793,6 +793,13 @@ func TestPlacePerpetualLiquidation_PreexistingLiquidation(t *testing.T) { mock.Anything, mock.Anything, ).Return(nil) + bk.On( + "SendCoins", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(nil) bk.On( "GetBalance", mock.Anything, @@ -833,6 +840,13 @@ func TestPlacePerpetualLiquidation_PreexistingLiquidation(t *testing.T) { mock.Anything, mock.Anything, ).Return(nil) + bk.On( + "SendCoins", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(nil) bk.On( "GetBalance", mock.Anything, diff --git a/protocol/x/clob/keeper/mev_test.go b/protocol/x/clob/keeper/mev_test.go index 9c12550d27..6f0cd44d16 100644 --- a/protocol/x/clob/keeper/mev_test.go +++ b/protocol/x/clob/keeper/mev_test.go @@ -1244,6 +1244,13 @@ func TestGetMidPrices(t *testing.T) { mock.Anything, mock.Anything, ).Return(nil) + mockBankKeeper.On( + "SendCoins", + mock.Anything, + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(nil) ks := keepertest.NewClobKeepersTestContext(t, memclob, mockBankKeeper, indexer_manager.NewIndexerEventManagerNoop()) ctx := ks.Ctx.WithIsCheckTx(true) diff --git a/protocol/x/clob/keeper/orders_test.go b/protocol/x/clob/keeper/orders_test.go index 79998ab3fe..3bf0795743 100644 --- a/protocol/x/clob/keeper/orders_test.go +++ b/protocol/x/clob/keeper/orders_test.go @@ -647,7 +647,7 @@ func TestPlaceShortTermOrder(t *testing.T) { memClob := memclob.NewMemClobPriceTimePriority(false) mockBankKeeper := &mocks.BankKeeper{} mockBankKeeper.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, mock.Anything, mock.Anything, @@ -875,7 +875,7 @@ func TestAddPreexistingStatefulOrder(t *testing.T) { memClob := memclob.NewMemClobPriceTimePriority(false) mockBankKeeper := &mocks.BankKeeper{} mockBankKeeper.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, mock.Anything, mock.Anything, diff --git a/protocol/x/clob/keeper/process_operations_liquidations_test.go b/protocol/x/clob/keeper/process_operations_liquidations_test.go index ef86f581f1..b73dac4170 100644 --- a/protocol/x/clob/keeper/process_operations_liquidations_test.go +++ b/protocol/x/clob/keeper/process_operations_liquidations_test.go @@ -193,17 +193,17 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(10_000_000)), ).Return(nil) bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(satypes.ModuleName), - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + satypes.ModuleAddress, + perptypes.InsuranceFundModuleAddress, // Subaccount pays $250 to insurance fund for liquidating 1 BTC. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(250_000_000)), ).Return(nil).Once() @@ -271,10 +271,10 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(10_100_000)), ).Return(nil) bk.On( @@ -286,8 +286,8 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(perptypes.InsuranceFundName), - authtypes.NewModuleAddress(satypes.ModuleName), + perptypes.InsuranceFundModuleAddress, + satypes.ModuleAddress, // Insurance fund covers $1 loss for liquidating 1 BTC. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(1_000_000)), ).Return(nil).Once() @@ -357,17 +357,17 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(2_500_000)), ).Return(nil) bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(satypes.ModuleName), - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + satypes.ModuleAddress, + perptypes.InsuranceFundModuleAddress, // Subaccount pays $62.5 to insurance fund for liquidating 0.25 BTC. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(62_500_000)), ).Return(nil).Twice() @@ -455,10 +455,10 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(2_525_000)), ).Return(nil) bk.On( @@ -470,8 +470,8 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(perptypes.InsuranceFundName), - authtypes.NewModuleAddress(satypes.ModuleName), + perptypes.InsuranceFundModuleAddress, + satypes.ModuleAddress, // Insurance fund covers $0.25 loss for liquidating 0.25 BTC. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(250_000)), ).Return(nil).Twice() @@ -560,10 +560,10 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.Anything, ).Return(nil) bk.On( @@ -575,16 +575,16 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(satypes.ModuleName), - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + satypes.ModuleAddress, + perptypes.InsuranceFundModuleAddress, // Pays insurance fund $0.75 for liquidating 0.75 BTC. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(750_000)), ).Return(nil).Once() bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(perptypes.InsuranceFundName), - authtypes.NewModuleAddress(satypes.ModuleName), + perptypes.InsuranceFundModuleAddress, + satypes.ModuleAddress, // Insurance fund covers $0.25 loss for liquidating 0.25 BTC. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(250_000)), ).Return(nil).Once() @@ -664,10 +664,10 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.Anything, ).Return(nil) bk.On( @@ -679,8 +679,8 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(satypes.ModuleName), - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + satypes.ModuleAddress, + perptypes.InsuranceFundModuleAddress, // Pays insurance fund $0.378735 (capped by MaxLiquidationFeePpm) // for liquidating 0.75 BTC. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(378_735)), @@ -688,8 +688,8 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(satypes.ModuleName), - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + satypes.ModuleAddress, + perptypes.InsuranceFundModuleAddress, // Pays insurance fund $0.121265. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(121_265)), ).Return(nil).Once() @@ -777,17 +777,17 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(5_000_000)), ).Return(nil) bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(satypes.ModuleName), - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + satypes.ModuleAddress, + perptypes.InsuranceFundModuleAddress, // Subaccount pays $125 to insurance fund for liquidating 0.5 BTC. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(125_000_000)), ).Return(nil).Once() @@ -890,17 +890,17 @@ func TestProcessProposerMatches_Liquidation_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(1)), ).Return(nil) bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(satypes.ModuleName), - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + satypes.ModuleAddress, + perptypes.InsuranceFundModuleAddress, mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(25)), ).Return(nil) }, @@ -1263,17 +1263,17 @@ func TestProcessProposerMatches_Liquidation_Failure(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, mock.Anything, - authtypes.FeeCollectorName, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.Anything, ).Return(fmt.Errorf("transfer failed")) bk.On( "SendCoins", mock.Anything, mock.Anything, - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + perptypes.InsuranceFundModuleAddress, mock.Anything, ).Return(nil) }, diff --git a/protocol/x/clob/keeper/process_operations_long_term_test.go b/protocol/x/clob/keeper/process_operations_long_term_test.go index 13f1f8de11..f2ecafc3a5 100644 --- a/protocol/x/clob/keeper/process_operations_long_term_test.go +++ b/protocol/x/clob/keeper/process_operations_long_term_test.go @@ -37,10 +37,10 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 25_000_000+10_000_000, @@ -106,10 +106,10 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 25_000_000+10_000_000, @@ -186,10 +186,10 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 25_000_000+10_000_000, @@ -259,10 +259,10 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 25_000_000+10_000_000, @@ -333,10 +333,10 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 25_000_000+10_000_000, @@ -406,10 +406,10 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 12_500_000+5_000_000, @@ -484,10 +484,10 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 12_500_000+5_000_000, @@ -571,17 +571,17 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(10_000_000)), ).Return(nil) bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(satypes.ModuleName), - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + satypes.ModuleAddress, + perptypes.InsuranceFundModuleAddress, // Subaccount pays $250 to insurance fund for liquidating 1 BTC. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(250_000_000)), ).Return(nil).Once() @@ -659,17 +659,17 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(10_000_000)), ).Return(nil) bk.On( "SendCoins", mock.Anything, - authtypes.NewModuleAddress(satypes.ModuleName), - authtypes.NewModuleAddress(perptypes.InsuranceFundName), + satypes.ModuleAddress, + perptypes.InsuranceFundModuleAddress, // Subaccount pays $250 to insurance fund for liquidating 1 BTC. mock.MatchedBy(testutil_bank.MatchUsdcOfAmount(250_000_000)), ).Return(nil).Once() @@ -747,10 +747,10 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 12_500_000+5_000_000, @@ -838,10 +838,10 @@ func TestProcessProposerMatches_LongTerm_Success(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 12_500_000+5_000_000, diff --git a/protocol/x/clob/keeper/process_operations_stateful_validation_test.go b/protocol/x/clob/keeper/process_operations_stateful_validation_test.go index 3dfff5254c..f944523dc0 100644 --- a/protocol/x/clob/keeper/process_operations_stateful_validation_test.go +++ b/protocol/x/clob/keeper/process_operations_stateful_validation_test.go @@ -339,10 +339,10 @@ func TestProcessProposerMatches_LongTerm_StatefulValidation_Failure(t *testing.T }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 12_500_000+5_000_000, @@ -635,10 +635,10 @@ func TestProcessProposerMatches_Conditional_Validation_Failure(t *testing.T) { }, setupMockBankKeeper: func(bk *mocks.BankKeeper) { bk.On( - "SendCoinsFromModuleToModule", + "SendCoins", mock.Anything, - satypes.ModuleName, - authtypes.FeeCollectorName, + satypes.ModuleAddress, + authtypes.NewModuleAddress(authtypes.FeeCollectorName), mock.MatchedBy( testutil_bank.MatchUsdcOfAmount( 12_500_000+5_000_000, diff --git a/protocol/x/clob/keeper/process_single_match.go b/protocol/x/clob/keeper/process_single_match.go index 189465d3a5..9cd19a36b8 100644 --- a/protocol/x/clob/keeper/process_single_match.go +++ b/protocol/x/clob/keeper/process_single_match.go @@ -442,6 +442,7 @@ func (k Keeper) persistMatchedOrders( ctx, assettypes.AssetUsdc.Id, bigTotalFeeQuoteQuantums, + 0, ); err != nil { return takerUpdateResult, makerUpdateResult, errorsmod.Wrapf( types.ErrSubaccountFeeTransferFailed, diff --git a/protocol/x/clob/types/expected_keepers.go b/protocol/x/clob/types/expected_keepers.go index 81b4aef392..3c4c8b86a2 100644 --- a/protocol/x/clob/types/expected_keepers.go +++ b/protocol/x/clob/types/expected_keepers.go @@ -63,11 +63,7 @@ type SubaccountsKeeper interface { ctx sdk.Context, blockHeight uint32, ) - TransferFeesToFeeCollectorModule( - ctx sdk.Context, - assetId uint32, - amount *big.Int, - ) error + TransferFeesToFeeCollectorModule(ctx sdk.Context, assetId uint32, amount *big.Int, perpetualId uint32) error TransferInsuranceFundPayments( ctx sdk.Context, amount *big.Int, diff --git a/protocol/x/subaccounts/keeper/subaccount.go b/protocol/x/subaccounts/keeper/subaccount.go index 4ec9bb9158..57d37006b2 100644 --- a/protocol/x/subaccounts/keeper/subaccount.go +++ b/protocol/x/subaccounts/keeper/subaccount.go @@ -69,6 +69,19 @@ func (k Keeper) GetCollateralPoolForSubaccount(ctx sdk.Context, subaccountId typ return authtypes.NewModuleAddress(poolName), nil } +func (k Keeper) GetCollateralPoolFromPerpetualId(ctx sdk.Context, perpetualId uint32) (sdk.AccAddress, error) { + perpetual, err := k.perpetualsKeeper.GetPerpetual(ctx, perpetualId) + if err != nil { + return nil, err + } + + if perpetual.Params.MarketType == perptypes.PerpetualMarketType_PERPETUAL_MARKET_TYPE_ISOLATED { + return authtypes.NewModuleAddress(types.ModuleName + ":" + lib.UintToString(perpetual.GetId())), nil + } + + return authtypes.NewModuleAddress(types.ModuleName), nil +} + func (k Keeper) GetCollateralPoolNameForSubaccount(ctx sdk.Context, subaccountId types.SubaccountId) (string, error) { subaccount := k.GetSubaccount(ctx, subaccountId) if len(subaccount.PerpetualPositions) == 0 { diff --git a/protocol/x/subaccounts/keeper/transfer.go b/protocol/x/subaccounts/keeper/transfer.go index 6e6ef31e3b..8f7d474c28 100644 --- a/protocol/x/subaccounts/keeper/transfer.go +++ b/protocol/x/subaccounts/keeper/transfer.go @@ -123,11 +123,16 @@ func (k Keeper) DepositFundsFromAccountToSubaccount( return err } + collateralPoolAddr, err := k.GetCollateralPoolForSubaccount(ctx, toSubaccountId) + if err != nil { + return err + } + // Send coins from `fromModule` to the `subaccounts` module account. - if err := k.bankKeeper.SendCoinsFromAccountToModule( + if err := k.bankKeeper.SendCoins( ctx, fromAccount, - types.ModuleName, + collateralPoolAddr, []sdk.Coin{coinToTransfer}, ); err != nil { return err @@ -143,7 +148,7 @@ func (k Keeper) DepositFundsFromAccountToSubaccount( // WithdrawFundsFromSubaccountToAccount returns an error if the call to `k.CanUpdateSubaccounts()` // fails. Otherwise, deducts the asset quantums from the subaccount, translates the -// `assetId` and `quantums` into a `sdk.Coin`, and calls `bankKeeper.SendCoinsFromModuleToAccount()`. +// `assetId` and `quantums` into a `sdk.Coin`, and calls `bankKeeper.SendCoins()`. func (k Keeper) WithdrawFundsFromSubaccountToAccount( ctx sdk.Context, fromSubaccountId types.SubaccountId, @@ -181,10 +186,15 @@ func (k Keeper) WithdrawFundsFromSubaccountToAccount( return err } + collateralPoolAddr, err := k.GetCollateralPoolForSubaccount(ctx, fromSubaccountId) + if err != nil { + return err + } + // Send coins from `fromModule` to the `subaccounts` module account. - if err := k.bankKeeper.SendCoinsFromModuleToAccount( + if err := k.bankKeeper.SendCoins( ctx, - types.ModuleName, + collateralPoolAddr, toAccount, []sdk.Coin{coinToTransfer}, ); err != nil { @@ -201,11 +211,12 @@ func (k Keeper) WithdrawFundsFromSubaccountToAccount( // TransferFeesToFeeCollectorModule translates the assetId and quantums into a sdk.Coin, // and moves the funds from subaccounts module to the `fee_collector` module account by calling -// bankKeeper.SendCoinsFromModuleToModule(). Does not change any individual subaccount state. +// bankKeeper.SendCoins(). Does not change any individual subaccount state. func (k Keeper) TransferFeesToFeeCollectorModule( ctx sdk.Context, assetId uint32, quantums *big.Int, + perpetualId uint32, ) error { // TODO(DEC-715): Support non-USDC assets. if assetId != assettypes.AssetUsdc.Id { @@ -225,16 +236,21 @@ func (k Keeper) TransferFeesToFeeCollectorModule( return err } + collateralPoolAddr, err := k.GetCollateralPoolFromPerpetualId(ctx, perpetualId) + if err != nil { + return err + } + // Send coins from `subaccounts` to the `auth` module fee collector account. - fromModule := types.ModuleName - toModule := authtypes.FeeCollectorName + fromModule := collateralPoolAddr + toModule := authtypes.NewModuleAddress(authtypes.FeeCollectorName) if quantums.Sign() < 0 { // In the case of a liquidation, net fees can be negative if the maker gets a rebate. fromModule, toModule = toModule, fromModule } - if err := k.bankKeeper.SendCoinsFromModuleToModule( + if err := k.bankKeeper.SendCoins( ctx, fromModule, toModule, @@ -247,7 +263,7 @@ func (k Keeper) TransferFeesToFeeCollectorModule( } // TransferInsuranceFundPayments transfers funds in and out of the insurance fund to the subaccounts -// module by calling `bankKeeper.SendCoinsFromModuleToModule`. +// module by calling `bankKeeper.SendCoins`. // This function transfers funds // - from the insurance fund to the subaccounts module when `insuranceFundDelta` is negative. // - from the subaccounts module to the insurance fund when `insuranceFundDelta` is positive. @@ -276,8 +292,11 @@ func (k Keeper) TransferInsuranceFundPayments( // Determine the sender and receiver. // Send coins from `subaccounts` to the `insurance_fund` module account by default. - fromModule := types.ModuleName - toModule, err := k.perpetualsKeeper.GetInsuranceFundName(ctx, perpetualId) + fromModule, err := k.GetCollateralPoolFromPerpetualId(ctx, perpetualId) + if err != nil { + panic(err) + } + toModule, err := k.perpetualsKeeper.GetInsuranceFundModuleAddress(ctx, perpetualId) if err != nil { panic(err) } @@ -292,8 +311,8 @@ func (k Keeper) TransferInsuranceFundPayments( // module account features return k.bankKeeper.SendCoins( ctx, - authtypes.NewModuleAddress(fromModule), - authtypes.NewModuleAddress(toModule), + fromModule, + toModule, []sdk.Coin{coinToTransfer}, ) } diff --git a/protocol/x/subaccounts/keeper/transfer_test.go b/protocol/x/subaccounts/keeper/transfer_test.go index 58ed6ff53c..4913108407 100644 --- a/protocol/x/subaccounts/keeper/transfer_test.go +++ b/protocol/x/subaccounts/keeper/transfer_test.go @@ -30,7 +30,8 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun asset asstypes.Asset // Subaccount state. - assetPositions []*types.AssetPosition + assetPositions []*types.AssetPosition + perpetualPositions []*types.PerpetualPosition // Module account state. subaccountModuleAccBalance *big.Int @@ -46,12 +47,29 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun expectedAccAddressBalance *big.Int }{ "WithdrawFundsFromSubaccountToAccount: send from subaccount to an account address": { - testTransferFundToAccount: true, - asset: *constants.Usdc, - accAddressBalance: big.NewInt(2500), - subaccountModuleAccBalance: big.NewInt(600), - quantums: big.NewInt(500), - assetPositions: keepertest.CreateUsdcAssetPosition(big.NewInt(500)), + testTransferFundToAccount: true, + asset: *constants.Usdc, + accAddressBalance: big.NewInt(2500), + subaccountModuleAccBalance: big.NewInt(600), + quantums: big.NewInt(500), + assetPositions: keepertest.CreateUsdcAssetPosition(big.NewInt(500)), + perpetualPositions: []*types.PerpetualPosition{ + &constants.PerpetualPosition_OneBTCLong, + }, + expectedQuoteBalance: big.NewInt(0), // 500 - 500 + expectedSubaccountsModuleAccBalance: big.NewInt(100), // 600 - 100 + expectedAccAddressBalance: big.NewInt(3000), // 500 + 2500 + }, + "WithdrawFundsFromSubaccountToAccount: send from isolated subaccount to an account address": { + testTransferFundToAccount: true, + asset: *constants.Usdc, + accAddressBalance: big.NewInt(2500), + subaccountModuleAccBalance: big.NewInt(600), + quantums: big.NewInt(500), + assetPositions: keepertest.CreateUsdcAssetPosition(big.NewInt(500)), + perpetualPositions: []*types.PerpetualPosition{ + &constants.PerpetualPosition_OneISOLong, + }, expectedQuoteBalance: big.NewInt(0), // 500 - 500 expectedSubaccountsModuleAccBalance: big.NewInt(100), // 600 - 100 expectedAccAddressBalance: big.NewInt(3000), // 500 + 2500 @@ -73,17 +91,37 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun assetPositions: keepertest.CreateUsdcAssetPosition( big.NewInt(30_000_001), ), // $3.0001 + perpetualPositions: []*types.PerpetualPosition{ + &constants.PerpetualPosition_OneBTCLong, + }, expectedQuoteBalance: big.NewInt(10_000_001), // $1.0001, untransfered $0.0001 remains. expectedSubaccountsModuleAccBalance: big.NewInt(8_000_000), // $8 expectedAccAddressBalance: big.NewInt(4_500_000), // $2.5 + $2 }, "DepositFundsFromAccountToSubaccount: send from account to subaccount": { - testTransferFundToAccount: false, - asset: *constants.Usdc, - subaccountModuleAccBalance: big.NewInt(200), - accAddressBalance: big.NewInt(2000), - quantums: big.NewInt(500), - assetPositions: keepertest.CreateUsdcAssetPosition(big.NewInt(150)), + testTransferFundToAccount: false, + asset: *constants.Usdc, + subaccountModuleAccBalance: big.NewInt(200), + accAddressBalance: big.NewInt(2000), + quantums: big.NewInt(500), + assetPositions: keepertest.CreateUsdcAssetPosition(big.NewInt(150)), + perpetualPositions: []*types.PerpetualPosition{ + &constants.PerpetualPosition_OneBTCLong, + }, + expectedQuoteBalance: big.NewInt(650), // 150 + 500 + expectedSubaccountsModuleAccBalance: big.NewInt(700), // 200 + 500 + expectedAccAddressBalance: big.NewInt(1500), // 2000 - 500 + }, + "DepositFundsFromAccountToSubaccount: send from account to isolated subaccount": { + testTransferFundToAccount: false, + asset: *constants.Usdc, + subaccountModuleAccBalance: big.NewInt(200), + accAddressBalance: big.NewInt(2000), + quantums: big.NewInt(500), + assetPositions: keepertest.CreateUsdcAssetPosition(big.NewInt(150)), + perpetualPositions: []*types.PerpetualPosition{ + &constants.PerpetualPosition_OneISOLong, + }, expectedQuoteBalance: big.NewInt(650), // 150 + 500 expectedSubaccountsModuleAccBalance: big.NewInt(700), // 200 + 500 expectedAccAddressBalance: big.NewInt(1500), // 2000 - 500 @@ -99,13 +137,16 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun MarketId: uint32(0), AtomicResolution: int32(-5), // $1 = 100_000 quantums }, - subaccountModuleAccBalance: big.NewInt(2_000_000), // $2 - accAddressBalance: big.NewInt(9_000_000), // $9 - quantums: big.NewInt(502_100), // $5.021 - assetPositions: keepertest.CreateUsdcAssetPosition(big.NewInt(105_000)), // $1.05 - expectedQuoteBalance: big.NewInt(607_100), // $1.05 + $5.021 - expectedSubaccountsModuleAccBalance: big.NewInt(7_021_000), // $2 + $5.021 - expectedAccAddressBalance: big.NewInt(3_979_000), // $9 - $5.021 + subaccountModuleAccBalance: big.NewInt(2_000_000), // $2 + accAddressBalance: big.NewInt(9_000_000), // $9 + quantums: big.NewInt(502_100), // $5.021 + assetPositions: keepertest.CreateUsdcAssetPosition(big.NewInt(105_000)), // $1.05 + perpetualPositions: []*types.PerpetualPosition{ + &constants.PerpetualPosition_OneBTCLong, + }, + expectedQuoteBalance: big.NewInt(607_100), // $1.05 + $5.021 + expectedSubaccountsModuleAccBalance: big.NewInt(7_021_000), // $2 + $5.021 + expectedAccAddressBalance: big.NewInt(3_979_000), // $9 - $5.021 }, "DepositFundsFromAccountToSubaccount: new balance reaches max int64": { testTransferFundToAccount: false, @@ -116,6 +157,9 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun assetPositions: keepertest.CreateUsdcAssetPosition( new(big.Int).SetUint64(math.MaxUint64 - 100), ), + perpetualPositions: []*types.PerpetualPosition{ + &constants.PerpetualPosition_OneBTCLong, + }, expectedQuoteBalance: new(big.Int).Add( new(big.Int).SetUint64(math.MaxUint64), big.NewInt(400), @@ -135,9 +179,14 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun for name, tc := range tests { t.Run(name, func(t *testing.T) { - ctx, keeper, pricesKeeper, _, accountKeeper, bankKeeper, assetsKeeper, _, _ := keepertest.SubaccountsKeepers(t, true) + ctx, keeper, pricesKeeper, perpetualsKeeper, accountKeeper, bankKeeper, assetsKeeper, _, _ := + keepertest.SubaccountsKeepers(t, true) keepertest.CreateTestMarkets(t, ctx, pricesKeeper) + keepertest.CreateTestLiquidityTiers(t, ctx, perpetualsKeeper) + + keepertest.CreateTestPerpetuals(t, ctx, perpetualsKeeper) + // Set up Subaccounts module account. auth_testutil.CreateTestModuleAccount(ctx, accountKeeper, types.ModuleName, []string{}) @@ -162,18 +211,6 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun require.NoError(t, err) } - if tc.subaccountModuleAccBalance.Sign() > 0 { - err := bank_testutil.FundModuleAccount( - ctx, - types.ModuleName, - sdk.Coins{ - sdk.NewCoin(tc.asset.Denom, sdkmath.NewIntFromBigInt(tc.subaccountModuleAccBalance)), - }, - *bankKeeper, - ) - require.NoError(t, err) - } - _, err = assetsKeeper.CreateAsset( ctx, tc.asset.Id, @@ -188,9 +225,25 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun subaccount := createNSubaccount(keeper, ctx, 1, big.NewInt(1_000))[0] subaccount.AssetPositions = tc.assetPositions + subaccount.PerpetualPositions = tc.perpetualPositions keeper.SetSubaccount(ctx, subaccount) + collateralPoolAddr, err := keeper.GetCollateralPoolForSubaccount(ctx, *subaccount.Id) + require.NoError(t, err) + + if tc.subaccountModuleAccBalance.Sign() > 0 { + err := bank_testutil.FundAccount( + ctx, + collateralPoolAddr, + sdk.Coins{ + sdk.NewCoin(tc.asset.Denom, sdkmath.NewIntFromBigInt(tc.subaccountModuleAccBalance)), + }, + *bankKeeper, + ) + require.NoError(t, err) + } + // Test either WithdrawFundsFromSubaccountToAccount or DepositFundsFromAccountToSubaccount. if tc.testTransferFundToAccount { err = keeper.WithdrawFundsFromSubaccountToAccount( @@ -226,7 +279,7 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun ) // Check the subaccount module balance. - subaccountsModuleAccBalance := bankKeeper.GetBalance(ctx, types.ModuleAddress, tc.asset.Denom) + subaccountsModuleAccBalance := bankKeeper.GetBalance(ctx, collateralPoolAddr, tc.asset.Denom) require.Equal(t, sdk.NewCoin(tc.asset.Denom, sdkmath.NewIntFromBigInt(tc.expectedSubaccountsModuleAccBalance)), subaccountsModuleAccBalance, @@ -252,7 +305,8 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun asset asstypes.Asset // Subaccount state. - assetPositions []*types.AssetPosition + assetPositions []*types.AssetPosition + perpetualPositions []*types.PerpetualPosition // Module account state. subaccountModuleAccBalance *big.Int @@ -282,6 +336,18 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun assetPositions: keepertest.CreateUsdcAssetPosition(big.NewInt(500)), expectedErr: sdkerrors.ErrInsufficientFunds, }, + "WithdrawFundsFromSubaccountToAccount: isolated market subaccounts module account does not have enough balance": { + testTransferFundToAccount: true, + asset: *constants.Usdc, + subaccountModuleAccBalance: big.NewInt(400), + accAddressBalance: big.NewInt(5000), + quantums: big.NewInt(500), + assetPositions: keepertest.CreateUsdcAssetPosition(big.NewInt(500)), + perpetualPositions: []*types.PerpetualPosition{ + &constants.PerpetualPosition_OneISOLong, + }, + expectedErr: sdkerrors.ErrInsufficientFunds, + }, "WithdrawFundsFromSubaccountToAccount: transfer quantums is zero": { testTransferFundToAccount: true, asset: *constants.Usdc, @@ -362,8 +428,12 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun for name, tc := range tests { t.Run(name, func(t *testing.T) { - ctx, keeper, pricesKeeper, _, accountKeeper, bankKeeper, assetsKeeper, _, _ := keepertest.SubaccountsKeepers(t, true) + ctx, keeper, pricesKeeper, perpetualsKeeper, accountKeeper, bankKeeper, assetsKeeper, _, _ := + keepertest.SubaccountsKeepers(t, true) keepertest.CreateTestMarkets(t, ctx, pricesKeeper) + keepertest.CreateTestLiquidityTiers(t, ctx, perpetualsKeeper) + + keepertest.CreateTestPerpetuals(t, ctx, perpetualsKeeper) // Set up Subaccounts module account. auth_testutil.CreateTestModuleAccount(ctx, accountKeeper, types.ModuleName, []string{}) @@ -389,18 +459,6 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun require.NoError(t, err) } - if tc.subaccountModuleAccBalance.Sign() > 0 { - err := bank_testutil.FundModuleAccount( - ctx, - types.ModuleName, - sdk.Coins{ - sdk.NewCoin(tc.asset.Denom, sdkmath.NewIntFromBigInt(tc.subaccountModuleAccBalance)), - }, - *bankKeeper, - ) - require.NoError(t, err) - } - if !tc.skipSetUpUsdc { // Always create USDC as the first asset unless specificed to skip. err := keepertest.CreateUsdcAsset(ctx, assetsKeeper) @@ -423,9 +481,25 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun subaccount := createNSubaccount(keeper, ctx, 1, big.NewInt(1_000))[0] subaccount.AssetPositions = tc.assetPositions + subaccount.PerpetualPositions = tc.perpetualPositions keeper.SetSubaccount(ctx, subaccount) + collateralPoolAddr, err := keeper.GetCollateralPoolForSubaccount(ctx, *subaccount.Id) + require.NoError(t, err) + + if tc.subaccountModuleAccBalance.Sign() > 0 { + err := bank_testutil.FundAccount( + ctx, + collateralPoolAddr, + sdk.Coins{ + sdk.NewCoin(tc.asset.Denom, sdkmath.NewIntFromBigInt(tc.subaccountModuleAccBalance)), + }, + *bankKeeper, + ) + require.NoError(t, err) + } + // Test either WithdrawFundsFromSubaccountToAccount or DepositFundsFromAccountToSubaccount. if tc.testTransferFundToAccount { err = keeper.WithdrawFundsFromSubaccountToAccount( @@ -459,7 +533,7 @@ func TestWithdrawFundsFromSubaccountToAccount_DepositFundsFromAccountToSubaccoun ) // Check the subaccount module balance stays the same. - subaccountsModuleAccBalance := bankKeeper.GetBalance(ctx, types.ModuleAddress, tc.asset.Denom) + subaccountsModuleAccBalance := bankKeeper.GetBalance(ctx, collateralPoolAddr, tc.asset.Denom) require.Equal(t, sdk.NewCoin(tc.asset.Denom, sdkmath.NewIntFromBigInt(tc.subaccountModuleAccBalance)), subaccountsModuleAccBalance, @@ -487,8 +561,9 @@ func TestTransferFeesToFeeCollectorModule(t *testing.T) { feeModuleAccBalance *big.Int // Transfer details. - asset asstypes.Asset - quantums *big.Int + asset asstypes.Asset + quantums *big.Int + perpetualId uint32 // Expectations. expectedErr error @@ -503,6 +578,15 @@ func TestTransferFeesToFeeCollectorModule(t *testing.T) { expectedSubaccountsModuleAccBalance: big.NewInt(100), // 600 - 500 expectedFeeModuleAccBalance: big.NewInt(3000), // 500 + 2500 }, + "success - send to fee-collector module account from isolated market account": { + asset: *constants.Usdc, + feeModuleAccBalance: big.NewInt(2500), + subaccountModuleAccBalance: big.NewInt(600), + quantums: big.NewInt(500), + perpetualId: 3, // Isolated market perpetual ID + expectedSubaccountsModuleAccBalance: big.NewInt(100), // 600 - 500 + expectedFeeModuleAccBalance: big.NewInt(3000), // 500 + 2500 + }, "success - quantums is zero": { asset: *constants.Usdc, feeModuleAccBalance: big.NewInt(2500), @@ -520,6 +604,16 @@ func TestTransferFeesToFeeCollectorModule(t *testing.T) { expectedFeeModuleAccBalance: big.NewInt(2500), expectedErr: sdkerrors.ErrInsufficientFunds, }, + "failure - isolated markets subaccounts module does not have sufficient funds": { + asset: *constants.Usdc, + feeModuleAccBalance: big.NewInt(2500), + subaccountModuleAccBalance: big.NewInt(300), + quantums: big.NewInt(500), + perpetualId: 3, // Isolated market perpetual ID + expectedSubaccountsModuleAccBalance: big.NewInt(300), + expectedFeeModuleAccBalance: big.NewInt(2500), + expectedErr: sdkerrors.ErrInsufficientFunds, + }, "failure - asset ID doesn't exist": { feeModuleAccBalance: big.NewInt(1500), skipSetUpUsdc: true, @@ -553,9 +647,11 @@ func TestTransferFeesToFeeCollectorModule(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { - ctx, keeper, pricesKeeper, _, accountKeeper, bankKeeper, assetsKeeper, _, _ := keepertest.SubaccountsKeepers(t, true) + ctx, keeper, pricesKeeper, perpetualsKeeper, accountKeeper, bankKeeper, assetsKeeper, _, _ := + keepertest.SubaccountsKeepers(t, true) keepertest.CreateTestMarkets(t, ctx, pricesKeeper) - + keepertest.CreateTestLiquidityTiers(t, ctx, perpetualsKeeper) + keepertest.CreateTestPerpetuals(t, ctx, perpetualsKeeper) // Set up Subaccounts module account. auth_testutil.CreateTestModuleAccount(ctx, accountKeeper, types.ModuleName, []string{}) // Set up receiver module account. @@ -588,10 +684,13 @@ func TestTransferFeesToFeeCollectorModule(t *testing.T) { require.NoError(t, err) } + collateralPoolAddr, err := keeper.GetCollateralPoolFromPerpetualId(ctx, tc.perpetualId) + require.NoError(t, err) + if tc.subaccountModuleAccBalance.Sign() > 0 { - err := bank_testutil.FundModuleAccount( + err := bank_testutil.FundAccount( ctx, - types.ModuleName, + collateralPoolAddr, sdk.Coins{ sdk.NewCoin(tc.asset.Denom, sdkmath.NewIntFromBigInt(tc.subaccountModuleAccBalance)), }, @@ -620,11 +719,7 @@ func TestTransferFeesToFeeCollectorModule(t *testing.T) { require.NoError(t, err) } - err := keeper.TransferFeesToFeeCollectorModule( - ctx, - tc.asset.Id, - tc.quantums, - ) + err = keeper.TransferFeesToFeeCollectorModule(ctx, tc.asset.Id, tc.quantums, tc.perpetualId) if tc.expectedErr != nil { require.ErrorIs(t, @@ -636,7 +731,7 @@ func TestTransferFeesToFeeCollectorModule(t *testing.T) { } // Check the subaccount module balance. - subaccountsModuleAccBalance := bankKeeper.GetBalance(ctx, types.ModuleAddress, tc.asset.Denom) + subaccountsModuleAccBalance := bankKeeper.GetBalance(ctx, collateralPoolAddr, tc.asset.Denom) require.Equal(t, sdk.NewCoin(tc.asset.Denom, sdkmath.NewIntFromBigInt(tc.expectedSubaccountsModuleAccBalance)), subaccountsModuleAccBalance, @@ -790,14 +885,17 @@ func TestTransferInsuranceFundPayments(t *testing.T) { ) require.NoError(t, err) - insuranceFundName, err := perpsKeeper.GetInsuranceFundName(ctx, tc.perpetual.GetId()) + insuranceFundAddr, err := perpsKeeper.GetInsuranceFundModuleAddress(ctx, tc.perpetual.GetId()) + require.NoError(t, err) + + collateralPoolAddr, err := keeper.GetCollateralPoolFromPerpetualId(ctx, tc.perpetual.GetId()) require.NoError(t, err) // Mint asset in the receipt/sender module account for transfer. if tc.insuranceFundBalance > 0 { err := bank_testutil.FundAccount( ctx, - authtypes.NewModuleAddress(insuranceFundName), + insuranceFundAddr, sdk.Coins{ sdk.NewInt64Coin(constants.Usdc.Denom, tc.insuranceFundBalance), }, @@ -807,9 +905,9 @@ func TestTransferInsuranceFundPayments(t *testing.T) { } if tc.subaccountModuleAccBalance > 0 { - err := bank_testutil.FundModuleAccount( + err := bank_testutil.FundAccount( ctx, - types.ModuleName, + collateralPoolAddr, sdk.Coins{ sdk.NewInt64Coin(constants.Usdc.Denom, tc.subaccountModuleAccBalance), }, @@ -845,7 +943,7 @@ func TestTransferInsuranceFundPayments(t *testing.T) { } // Check the subaccount module balance. - subaccountsModuleAccBalance := bankKeeper.GetBalance(ctx, types.ModuleAddress, constants.Usdc.Denom) + subaccountsModuleAccBalance := bankKeeper.GetBalance(ctx, collateralPoolAddr, constants.Usdc.Denom) require.Equal( t, sdk.NewInt64Coin(constants.Usdc.Denom, tc.expectedSubaccountsModuleAccBalance), @@ -854,7 +952,7 @@ func TestTransferInsuranceFundPayments(t *testing.T) { // Check the fee module account balance has been updated as expected. toModuleBalance := bankKeeper.GetBalance( - ctx, authtypes.NewModuleAddress(insuranceFundName), + ctx, insuranceFundAddr, constants.Usdc.Denom, ) require.Equal(t, diff --git a/protocol/x/subaccounts/types/expected_keepers.go b/protocol/x/subaccounts/types/expected_keepers.go index 40a21e203d..4d30eb8174 100644 --- a/protocol/x/subaccounts/types/expected_keepers.go +++ b/protocol/x/subaccounts/types/expected_keepers.go @@ -73,6 +73,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) } // BankKeeper defines the expected interface needed to retrieve account balances.