Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

emit transfer event on vault allocation, retrieval, and withdrawal #2303

Merged
merged 1 commit into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion protocol/x/vault/keeper/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (k Keeper) MintShares(
) (mintedShares *big.Int, err error) {
// Quantums to deposit should be positive.
if quantumsToDeposit.Sign() <= 0 {
return nil, types.ErrInvalidDepositAmount
return nil, types.ErrInvalidQuoteQuantums
}
// Get existing TotalShares of the vault.
existingTotalShares := k.GetTotalShares(ctx).NumShares.BigInt()
Expand Down
4 changes: 2 additions & 2 deletions protocol/x/vault/keeper/deposit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,14 @@ func TestMintShares(t *testing.T) {
totalShares: big.NewInt(1),
owner: constants.AliceAccAddress.String(),
quantumsToDeposit: big.NewInt(0),
expectedErr: vaulttypes.ErrInvalidDepositAmount,
expectedErr: vaulttypes.ErrInvalidQuoteQuantums,
},
"Equity 0, TotalShares 0, Deposit -1": {
equity: big.NewInt(0),
totalShares: big.NewInt(0),
owner: constants.AliceAccAddress.String(),
quantumsToDeposit: big.NewInt(-1),
expectedErr: vaulttypes.ErrInvalidDepositAmount,
expectedErr: vaulttypes.ErrInvalidQuoteQuantums,
},
"Equity 1000, TotalShares 1, Deposit 100": {
equity: big.NewInt(1_000),
Expand Down
13 changes: 8 additions & 5 deletions protocol/x/vault/keeper/msg_server_allocate_to_vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -53,12 +54,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
}
Expand Down
142 changes: 116 additions & 26 deletions protocol/x/vault/keeper/msg_server_allocate_to_vault_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package keeper_test

import (
"bytes"
"math"
"math/big"
"testing"

abcitypes "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/types"
sdktypes "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"

"github.com/dydxprotocol/v4-chain/protocol/dtypes"
"github.com/dydxprotocol/v4-chain/protocol/lib"
testapp "github.com/dydxprotocol/v4-chain/protocol/testutil/app"
"github.com/dydxprotocol/v4-chain/protocol/testutil/constants"
assetstypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types"
satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types"
"github.com/dydxprotocol/v4-chain/protocol/x/vault/keeper"
vaulttypes "github.com/dydxprotocol/v4-chain/protocol/x/vault/types"
)

Expand All @@ -28,44 +31,83 @@ func TestMsgAllocateToVault(t *testing.T) {
vaultParams *vaulttypes.VaultParams
// Msg.
msg *vaulttypes.MsgAllocateToVault
// Expected error.
expectedErr string
// Signer of above msg.
signer string
// A string that CheckTx response should contain, if any.
checkTxResponseContains string
// Whether CheckTx fails.
checkTxFails bool
// Whether DeliverTx fails.
deliverTxFails bool
}{
"Success - Gov Authority, Allocate 50 to Vault Clob 0, Existing vault params": {
"Success - Allocate 50 to Vault Clob 0, Existing vault params": {
operator: constants.AliceAccAddress.String(),
mainVaultQuantums: 100,
subVaultQuantums: 0,
vaultParams: &vaulttypes.VaultParams{
Status: vaulttypes.VaultStatus_VAULT_STATUS_QUOTING,
},
msg: &vaulttypes.MsgAllocateToVault{
Authority: lib.GovModuleAddress.String(),
Authority: constants.AliceAccAddress.String(),
VaultId: constants.Vault_Clob0,
QuoteQuantums: dtypes.NewInt(50),
},
signer: constants.AliceAccAddress.String(),
},
"Success - Gov Authority, Allocate 77 to Vault Clob 1, Non-existent Vault Params": {
operator: constants.AliceAccAddress.String(),
"Success - Allocate 77 to Vault Clob 1, Non-existent Vault Params": {
operator: constants.BobAccAddress.String(),
mainVaultQuantums: 100,
subVaultQuantums: 15,
msg: &vaulttypes.MsgAllocateToVault{
Authority: lib.GovModuleAddress.String(),
Authority: constants.BobAccAddress.String(),
VaultId: constants.Vault_Clob1,
QuoteQuantums: dtypes.NewInt(77),
},
signer: constants.BobAccAddress.String(),
},
"Failure - Operator Authority, allocating more than max uint64 quantums": {
operator: constants.CarlAccAddress.String(),
mainVaultQuantums: 100,
subVaultQuantums: 15,
msg: &vaulttypes.MsgAllocateToVault{
Authority: constants.CarlAccAddress.String(),
VaultId: constants.Vault_Clob0,
QuoteQuantums: dtypes.NewIntFromBigInt(
new(big.Int).Add(
new(big.Int).SetUint64(math.MaxUint64),
new(big.Int).SetUint64(1),
),
),
},
checkTxResponseContains: "QuoteQuantums must be positive and less than 2^64",
checkTxFails: true,
signer: constants.CarlAccAddress.String(),
},
"Success - Operator Authority, Allocate all to Vault Clob 1, Existing vault params": {
"Failure - Operator Authority, allocating zero quantums": {
operator: constants.AliceAccAddress.String(),
mainVaultQuantums: 100,
subVaultQuantums: 15,
vaultParams: &vaulttypes.VaultParams{
Status: vaulttypes.VaultStatus_VAULT_STATUS_CLOSE_ONLY,
msg: &vaulttypes.MsgAllocateToVault{
Authority: constants.AliceAccAddress.String(),
VaultId: constants.Vault_Clob0,
QuoteQuantums: dtypes.NewInt(0),
},
checkTxResponseContains: "QuoteQuantums must be positive",
checkTxFails: true,
signer: constants.AliceAccAddress.String(),
},
"Failure - Operator Authority, allocating negative quantums": {
operator: constants.AliceAccAddress.String(),
mainVaultQuantums: 100,
subVaultQuantums: 15,
msg: &vaulttypes.MsgAllocateToVault{
Authority: constants.AliceAccAddress.String(),
VaultId: constants.Vault_Clob1,
QuoteQuantums: dtypes.NewInt(100),
VaultId: constants.Vault_Clob0,
QuoteQuantums: dtypes.NewInt(-1),
},
checkTxResponseContains: "QuoteQuantums must be positive",
checkTxFails: true,
signer: constants.AliceAccAddress.String(),
},
"Failure - Operator Authority, Insufficient quantums to allocate to Vault Clob 0, Existing vault params": {
operator: constants.AliceAccAddress.String(),
Expand All @@ -79,7 +121,9 @@ func TestMsgAllocateToVault(t *testing.T) {
VaultId: constants.Vault_Clob0,
QuoteQuantums: dtypes.NewInt(101),
},
expectedErr: "failed to apply subaccount updates",
signer: constants.AliceAccAddress.String(),
checkTxFails: false,
deliverTxFails: true,
},
"Failure - Operator Authority, No corresponding clob pair": {
operator: constants.AliceAccAddress.String(),
Expand All @@ -93,7 +137,9 @@ func TestMsgAllocateToVault(t *testing.T) {
},
QuoteQuantums: dtypes.NewInt(1),
},
expectedErr: vaulttypes.ErrClobPairNotFound.Error(),
signer: constants.AliceAccAddress.String(),
checkTxFails: false,
deliverTxFails: true,
},
"Failure - Invalid Authority, Non-existent Vault Params": {
operator: constants.BobAccAddress.String(),
Expand All @@ -104,7 +150,9 @@ func TestMsgAllocateToVault(t *testing.T) {
VaultId: constants.Vault_Clob1,
QuoteQuantums: dtypes.NewInt(77),
},
expectedErr: vaulttypes.ErrInvalidAuthority.Error(),
signer: constants.AliceAccAddress.String(),
checkTxFails: false,
deliverTxFails: true,
},
"Failure - Empty Authority, Existing vault params": {
operator: constants.BobAccAddress.String(),
Expand All @@ -115,7 +163,9 @@ func TestMsgAllocateToVault(t *testing.T) {
VaultId: constants.Vault_Clob1,
QuoteQuantums: dtypes.NewInt(77),
},
expectedErr: vaulttypes.ErrInvalidAuthority.Error(),
signer: constants.BobAccAddress.String(),
checkTxResponseContains: vaulttypes.ErrInvalidAuthority.Error(),
checkTxFails: true,
},
}

Expand Down Expand Up @@ -170,18 +220,60 @@ func TestMsgAllocateToVault(t *testing.T) {
}).Build()
ctx := tApp.InitChain()
k := tApp.App.VaultKeeper
ms := keeper.NewMsgServerImpl(k)

// Allocate to vault.
_, err := ms.AllocateToVault(ctx, tc.msg)
// Invoke CheckTx.
CheckTx_MsgAllocateToVault := testapp.MustMakeCheckTx(
ctx,
tApp.App,
testapp.MustMakeCheckTxOptions{
AccAddressForSigning: tc.signer,
Gas: constants.TestGasLimit,
FeeAmt: constants.TestFeeCoins_5Cents,
},
tc.msg,
)
checkTxResp := tApp.CheckTx(CheckTx_MsgAllocateToVault)

// Check that CheckTx response log contains expected string, if any.
if tc.checkTxResponseContains != "" {
require.Contains(t, checkTxResp.Log, tc.checkTxResponseContains)
}
// Check that CheckTx succeeds or errors out as expected.
if tc.checkTxFails {
require.Conditionf(t, checkTxResp.IsErr, "Expected CheckTx to error. Response: %+v", checkTxResp)
return
}
require.Conditionf(t, checkTxResp.IsOK, "Expected CheckTx to succeed. Response: %+v", checkTxResp)

// Advance to next block (and check that DeliverTx is as expected).
nextBlock := uint32(ctx.BlockHeight()) + 1
if tc.deliverTxFails {
// Check that DeliverTx fails on `msgDepositToMegavault`.
ctx = tApp.AdvanceToBlock(nextBlock, testapp.AdvanceToBlockOptions{
ValidateFinalizeBlock: func(
context sdktypes.Context,
request abcitypes.RequestFinalizeBlock,
response abcitypes.ResponseFinalizeBlock,
) (haltChain bool) {
for i, tx := range request.Txs {
if bytes.Equal(tx, CheckTx_MsgAllocateToVault.Tx) {
require.True(t, response.TxResults[i].IsErr())
} else {
require.True(t, response.TxResults[i].IsOK())
}
}
return false
},
})
} else {
ctx = tApp.AdvanceToBlock(nextBlock, testapp.AdvanceToBlockOptions{})
}

// Check expectations.
mainVault := tApp.App.SubaccountsKeeper.GetSubaccount(ctx, vaulttypes.MegavaultMainSubaccount)
subVault := tApp.App.SubaccountsKeeper.GetSubaccount(ctx, *tc.msg.VaultId.ToSubaccountId())
require.Len(t, subVault.AssetPositions, 1)
if tc.expectedErr != "" {
require.ErrorContains(t, err, tc.expectedErr)

if tc.deliverTxFails {
// Verify that main vault and sub vault balances are unchanged.
require.Len(t, mainVault.AssetPositions, 1)
require.Equal(
Expand All @@ -204,8 +296,6 @@ func TestMsgAllocateToVault(t *testing.T) {
require.False(t, exists)
}
} else {
require.NoError(t, err)

// Verify that main vault and sub vault balances are updated.
expectedMainVaultQuantums := tc.mainVaultQuantums - tc.msg.QuoteQuantums.BigInt().Uint64()
if expectedMainVaultQuantums == 0 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,15 +211,15 @@ func TestMsgDepositToMegavault(t *testing.T) {
depositAmount: big.NewInt(0),
msgSigner: constants.Alice_Num0.Owner,
checkTxFails: true,
checkTxResponseContains: "Deposit amount is invalid",
checkTxResponseContains: vaulttypes.ErrInvalidQuoteQuantums.Error(),
expectedOwnerShares: nil,
},
{
depositor: constants.Bob_Num0,
depositAmount: big.NewInt(-1),
msgSigner: constants.Bob_Num0.Owner,
checkTxFails: true,
checkTxResponseContains: "Deposit amount is invalid",
checkTxResponseContains: vaulttypes.ErrInvalidQuoteQuantums.Error(),
expectedOwnerShares: nil,
},
{
Expand All @@ -230,7 +230,7 @@ func TestMsgDepositToMegavault(t *testing.T) {
),
msgSigner: constants.Bob_Num0.Owner,
checkTxFails: true,
checkTxResponseContains: "Deposit amount is invalid",
checkTxResponseContains: vaulttypes.ErrInvalidQuoteQuantums.Error(),
expectedOwnerShares: nil,
},
},
Expand Down
13 changes: 8 additions & 5 deletions protocol/x/vault/keeper/msg_server_retrieve_from_vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -33,12 +34,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
}
Expand Down
Loading
Loading