From a9f83a8231134112426f8c47bb6ce880841c8ecd Mon Sep 17 00:00:00 2001 From: Tian Qin Date: Thu, 19 Sep 2024 17:53:23 -0400 Subject: [PATCH] emit transfer event on vault allocation, retrieval, and withdrawal --- .../keeper/msg_server_allocate_to_vault.go | 21 ++++++++--- .../msg_server_allocate_to_vault_test.go | 22 ++++++++++++ .../keeper/msg_server_retrieve_from_vault.go | 21 ++++++++--- .../msg_server_retrieve_from_vault_test.go | 28 +++++++++++++++ protocol/x/vault/keeper/withdraw.go | 36 +++++++++++++------ protocol/x/vault/types/errors.go | 5 +++ protocol/x/vault/types/expected_keepers.go | 7 ---- 7 files changed, 113 insertions(+), 27 deletions(-) diff --git a/protocol/x/vault/keeper/msg_server_allocate_to_vault.go b/protocol/x/vault/keeper/msg_server_allocate_to_vault.go index d7ff60f66cb..cfd8a42934a 100644 --- a/protocol/x/vault/keeper/msg_server_allocate_to_vault.go +++ b/protocol/x/vault/keeper/msg_server_allocate_to_vault.go @@ -8,6 +8,7 @@ import ( "github.com/dydxprotocol/v4-chain/protocol/lib" assetstypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types" clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" + sendingtypes "github.com/dydxprotocol/v4-chain/protocol/x/sending/types" "github.com/dydxprotocol/v4-chain/protocol/x/vault/types" ) @@ -16,6 +17,14 @@ func (k msgServer) AllocateToVault( goCtx context.Context, msg *types.MsgAllocateToVault, ) (*types.MsgAllocateToVaultResponse, error) { + if msg.QuoteQuantums.Sign() <= 0 { + return nil, errorsmod.Wrapf( + types.ErrInvalidQuoteQuantums, + "amount must be positive, got %s", + msg.QuoteQuantums.String(), + ) + } + ctx := lib.UnwrapSDKContext(goCtx, types.ModuleName) operator := k.GetOperatorParams(ctx).Operator @@ -53,12 +62,14 @@ func (k msgServer) AllocateToVault( } // Transfer from main vault to the specified vault. - if err := k.Keeper.subaccountsKeeper.TransferFundsFromSubaccountToSubaccount( + if err := k.Keeper.sendingKeeper.ProcessTransfer( ctx, - types.MegavaultMainSubaccount, - *msg.VaultId.ToSubaccountId(), - assetstypes.AssetUsdc.Id, - msg.QuoteQuantums.BigInt(), + &sendingtypes.Transfer{ + Sender: types.MegavaultMainSubaccount, + Recipient: *msg.VaultId.ToSubaccountId(), + AssetId: assetstypes.AssetUsdc.Id, + Amount: msg.QuoteQuantums.BigInt().Uint64(), // validated to be positive above. + }, ); err != nil { return nil, err } diff --git a/protocol/x/vault/keeper/msg_server_allocate_to_vault_test.go b/protocol/x/vault/keeper/msg_server_allocate_to_vault_test.go index b6279a183c3..c2e755d8428 100644 --- a/protocol/x/vault/keeper/msg_server_allocate_to_vault_test.go +++ b/protocol/x/vault/keeper/msg_server_allocate_to_vault_test.go @@ -67,6 +67,28 @@ func TestMsgAllocateToVault(t *testing.T) { QuoteQuantums: dtypes.NewInt(100), }, }, + "Failure - Operator Authority, allocating zero quantums": { + operator: constants.AliceAccAddress.String(), + mainVaultQuantums: 100, + subVaultQuantums: 15, + msg: &vaulttypes.MsgAllocateToVault{ + Authority: constants.AliceAccAddress.String(), + VaultId: constants.Vault_Clob0, + QuoteQuantums: dtypes.NewInt(0), + }, + expectedErr: "QuoteQuantums must be positive", + }, + "Failure - Operator Authority, allocating negative quantums": { + operator: constants.AliceAccAddress.String(), + mainVaultQuantums: 100, + subVaultQuantums: 15, + msg: &vaulttypes.MsgAllocateToVault{ + Authority: constants.AliceAccAddress.String(), + VaultId: constants.Vault_Clob0, + QuoteQuantums: dtypes.NewInt(-1), + }, + expectedErr: "QuoteQuantums must be positive", + }, "Failure - Operator Authority, Insufficient quantums to allocate to Vault Clob 0, Existing vault params": { operator: constants.AliceAccAddress.String(), mainVaultQuantums: 100, diff --git a/protocol/x/vault/keeper/msg_server_retrieve_from_vault.go b/protocol/x/vault/keeper/msg_server_retrieve_from_vault.go index d4586eda70a..886ceb45b36 100644 --- a/protocol/x/vault/keeper/msg_server_retrieve_from_vault.go +++ b/protocol/x/vault/keeper/msg_server_retrieve_from_vault.go @@ -7,6 +7,7 @@ import ( "github.com/dydxprotocol/v4-chain/protocol/lib" assetstypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types" + sendingtypes "github.com/dydxprotocol/v4-chain/protocol/x/sending/types" "github.com/dydxprotocol/v4-chain/protocol/x/vault/types" ) @@ -15,6 +16,14 @@ func (k msgServer) RetrieveFromVault( goCtx context.Context, msg *types.MsgRetrieveFromVault, ) (*types.MsgRetrieveFromVaultResponse, error) { + if msg.QuoteQuantums.Sign() <= 0 { + return nil, errorsmod.Wrapf( + types.ErrInvalidQuoteQuantums, + "amount must be positive, got %s", + msg.QuoteQuantums.String(), + ) + } + ctx := lib.UnwrapSDKContext(goCtx, types.ModuleName) operator := k.GetOperatorParams(ctx).Operator @@ -33,12 +42,14 @@ func (k msgServer) RetrieveFromVault( } // Transfer from specified vault to main vault. - if err := k.Keeper.subaccountsKeeper.TransferFundsFromSubaccountToSubaccount( + if err := k.Keeper.sendingKeeper.ProcessTransfer( ctx, - *msg.VaultId.ToSubaccountId(), - types.MegavaultMainSubaccount, - assetstypes.AssetUsdc.Id, - msg.QuoteQuantums.BigInt(), + &sendingtypes.Transfer{ + Sender: *msg.VaultId.ToSubaccountId(), + Recipient: types.MegavaultMainSubaccount, + AssetId: assetstypes.AssetUsdc.Id, + Amount: msg.QuoteQuantums.BigInt().Uint64(), // validated to be positive above. + }, ); err != nil { return nil, err } diff --git a/protocol/x/vault/keeper/msg_server_retrieve_from_vault_test.go b/protocol/x/vault/keeper/msg_server_retrieve_from_vault_test.go index a5082e55f62..526e3143fb8 100644 --- a/protocol/x/vault/keeper/msg_server_retrieve_from_vault_test.go +++ b/protocol/x/vault/keeper/msg_server_retrieve_from_vault_test.go @@ -59,6 +59,34 @@ func TestMsgRetrieveFromVault(t *testing.T) { QuoteQuantums: dtypes.NewInt(3_500_000), }, }, + "Failure - Operator Authority, Retrieve zero quantums from Vault Clob 1": { + operator: constants.AliceAccAddress.String(), + mainVaultQuantums: 0, + subVaultQuantums: 3_500_000, + vaultParams: &vaulttypes.VaultParams{ + Status: vaulttypes.VaultStatus_VAULT_STATUS_CLOSE_ONLY, + }, + msg: &vaulttypes.MsgRetrieveFromVault{ + Authority: constants.AliceAccAddress.String(), + VaultId: constants.Vault_Clob1, + QuoteQuantums: dtypes.NewInt(0), + }, + expectedErr: vaulttypes.ErrInvalidQuoteQuantums.Error(), + }, + "Failure - Operator Authority, Retrieve negative quantums from Vault Clob 1": { + operator: constants.AliceAccAddress.String(), + mainVaultQuantums: 0, + subVaultQuantums: 3_500_000, + vaultParams: &vaulttypes.VaultParams{ + Status: vaulttypes.VaultStatus_VAULT_STATUS_CLOSE_ONLY, + }, + msg: &vaulttypes.MsgRetrieveFromVault{ + Authority: constants.AliceAccAddress.String(), + VaultId: constants.Vault_Clob1, + QuoteQuantums: dtypes.NewInt(-1), + }, + expectedErr: vaulttypes.ErrInvalidQuoteQuantums.Error(), + }, "Failure - Insufficient quantums to retrieve from Vault Clob 0 with no open position": { operator: constants.AliceAccAddress.String(), mainVaultQuantums: 0, diff --git a/protocol/x/vault/keeper/withdraw.go b/protocol/x/vault/keeper/withdraw.go index 3ac55b56c3b..12e80c93115 100644 --- a/protocol/x/vault/keeper/withdraw.go +++ b/protocol/x/vault/keeper/withdraw.go @@ -11,6 +11,7 @@ import ( assetstypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types" perptypes "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals/types" pricestypes "github.com/dydxprotocol/v4-chain/protocol/x/prices/types" + sendingtypes "github.com/dydxprotocol/v4-chain/protocol/x/sending/types" satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" "github.com/dydxprotocol/v4-chain/protocol/x/vault/types" ) @@ -225,12 +226,25 @@ func (k Keeper) WithdrawFromMegavault( redeemedFromSubVault.Mul(redeemedFromSubVault, new(big.Rat).Sub(lib.BigRat1(), slippage)) quantumsToTransfer := new(big.Int).Quo(redeemedFromSubVault.Num(), redeemedFromSubVault.Denom()) - err = k.subaccountsKeeper.TransferFundsFromSubaccountToSubaccount( + if quantumsToTransfer.Sign() <= 0 { + log.InfoLog( + ctx, + "Megavault withdrawal: quantums to transfer is non-positive. Skipping this vault", + "Vault ID", + vaultId, + "Quantums", + quantumsToTransfer, + ) + continue + } + err = k.sendingKeeper.ProcessTransfer( ctx, - *vaultId.ToSubaccountId(), - types.MegavaultMainSubaccount, - assetstypes.AssetUsdc.Id, - quantumsToTransfer, + &sendingtypes.Transfer{ + Sender: *vaultId.ToSubaccountId(), + Recipient: types.MegavaultMainSubaccount, + AssetId: assetstypes.AssetUsdc.Id, + Amount: quantumsToTransfer.Uint64(), // validated to be positive above. + }, ) if err != nil { log.ErrorLogWithError( @@ -261,12 +275,14 @@ func (k Keeper) WithdrawFromMegavault( } // 5. Transfer from main vault to destination subaccount. - err = k.subaccountsKeeper.TransferFundsFromSubaccountToSubaccount( + err = k.sendingKeeper.ProcessTransfer( ctx, - types.MegavaultMainSubaccount, - toSubaccount, - assetstypes.AssetUsdc.Id, - redeemedQuoteQuantums, + &sendingtypes.Transfer{ + Sender: types.MegavaultMainSubaccount, + Recipient: toSubaccount, + AssetId: assetstypes.AssetUsdc.Id, + Amount: redeemedQuoteQuantums.Uint64(), // validated to be positive above. + }, ) if err != nil { log.ErrorLogWithError( diff --git a/protocol/x/vault/types/errors.go b/protocol/x/vault/types/errors.go index b68028ece25..4d8643d4f81 100644 --- a/protocol/x/vault/types/errors.go +++ b/protocol/x/vault/types/errors.go @@ -145,4 +145,9 @@ var ( 28, "Insufficient redeemed quote quantums", ) + ErrInvalidQuoteQuantums = errorsmod.Register( + ModuleName, + 29, + "QuoteQuantums must be positive", + ) ) diff --git a/protocol/x/vault/types/expected_keepers.go b/protocol/x/vault/types/expected_keepers.go index 643d8b012e9..85c11387160 100644 --- a/protocol/x/vault/types/expected_keepers.go +++ b/protocol/x/vault/types/expected_keepers.go @@ -111,11 +111,4 @@ type SubaccountsKeeper interface { ctx sdk.Context, id satypes.SubaccountId, ) satypes.Subaccount - TransferFundsFromSubaccountToSubaccount( - ctx sdk.Context, - senderSubaccountId satypes.SubaccountId, - recipientSubaccountId satypes.SubaccountId, - assetId uint32, - quantums *big.Int, - ) error }