Skip to content

Commit

Permalink
emit transfer event on vault allocation, retrieval, and withdrawal
Browse files Browse the repository at this point in the history
  • Loading branch information
tqin7 committed Sep 20, 2024
1 parent dde2216 commit 8c24dca
Show file tree
Hide file tree
Showing 19 changed files with 742 additions and 125 deletions.
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

0 comments on commit 8c24dca

Please sign in to comment.