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

[TRA-621] Sweep bank funds of megavault into subaccount. #2293

Merged
merged 3 commits into from
Sep 19, 2024

Conversation

vincentwschau
Copy link
Contributor

@vincentwschau vincentwschau commented Sep 19, 2024

Changelist

Add function to sweep funds from bank balance to subaccount balance of megavault main vault. Execute in endblocker after refreshing vault orders.

Test Plan

Unit / E2E test.

Author/Reviewer Checklist

  • If this PR has changes that result in a different app state given the same prior state and transaction list, manually add the state-breaking label.
  • If the PR has breaking postgres changes to the indexer add the indexer-postgres-breaking label.
  • If this PR isn't state-breaking but has changes that modify behavior in PrepareProposal or ProcessProposal, manually add the label proposal-breaking.
  • If this PR is one of many that implement a specific feature, manually label them all feature:[feature-name].
  • If you wish to for mergify-bot to automatically create a PR to backport your change to a release branch, manually add the label backport/[branch-name].
  • Manually add any of the following labels: refactor, chore, bug.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced VaultKeeper functionality with integrated asset management and banking capabilities.
    • Introduced a mock AssetsKeeper for improved testing of asset management functionalities.
    • Added new methods to manage assets, including creation, modification, and retrieval.
    • Implemented a function to efficiently transfer USDC balances from the main vault to subaccounts.
    • New interfaces for AssetsKeeper and BankKeeper to improve asset and account management.
  • Bug Fixes

    • Improved error handling for asset transfers and balance checks.
  • Tests

    • Added unit tests for sweeping funds to ensure correct balance updates under various scenarios.
    • Enhanced testing capabilities for the vault keeper with additional mock components.
  • Documentation

    • Updated interfaces to provide clearer definitions of asset and banking interactions.

@vincentwschau vincentwschau requested a review from a team as a code owner September 19, 2024 01:17
Copy link

linear bot commented Sep 19, 2024

Copy link
Contributor

coderabbitai bot commented Sep 19, 2024

Walkthrough

The pull request introduces enhancements to the vault management system by integrating AssetsKeeper and BankKeeper into the VaultKeeper. It includes new mock implementations for testing, additional methods in interfaces, and a function for sweeping funds from main vault accounts to subaccounts. These changes improve the functionality and testing capabilities of the vault module, ensuring better asset management and banking interactions.

Changes

File Path Change Summary
protocol/app/app.go Added app.AssetsKeeper and app.BankKeeper parameters to vaultmodulekeeper.NewKeeper instantiation.
protocol/mocks/AssetsKeeper.go Introduced a mock implementation of the AssetsKeeper interface with methods for asset management, enhancing testing capabilities.
protocol/mocks/Makefile Added command to generate mock for AssetsKeeper using mockery.
protocol/testutil/keeper/vault.go Incorporated mocks.AssetsKeeper and mocks.BankKeeper into createVaultKeeper function for enhanced testing.
protocol/x/assets/types/types.go Added AssetsKeeper interface with methods for asset management, improving the structure for handling assets.
protocol/x/vault/abci.go Introduced keeper.SweepMainVaultBankBalance(ctx) function in EndBlocker for managing vault bank balances.
protocol/x/vault/keeper/keeper.go Added assetsKeeper and bankKeeper fields to Keeper struct and modified the constructor to accept these parameters.
protocol/x/vault/keeper/sweep_funds.go Defined SweepMainVaultBankBalance function to transfer USDC from the main vault's bank account to its subaccount.
protocol/x/vault/keeper/sweep_funds_test.go Added unit tests for SweepMainVaultBankBalance functionality, covering various scenarios for balance management.
protocol/x/vault/types/expected_keepers.go Introduced AssetsKeeper and BankKeeper interfaces with methods for asset retrieval and balance fetching, enhancing keeper functionality.
protocol/x/vault/types/megavault.go Refactored initialization of MegavaultMainSubaccount for improved readability and maintainability.

Possibly related PRs

Suggested labels

indexer, proto

Suggested reviewers

  • tqin7

Poem

🐰 In the vault where treasures gleam,
Assets and banks now work as a team.
With mocks and tests, we leap and bound,
Sweeping funds, joyfully found!
A hop, a skip, to manage with flair,
In our vault, there's magic in the air! ✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    -- I pushed a fix in commit <commit_id>, please review it.
    -- Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    -- @coderabbitai generate unit testing code for this file.
    -- @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    -- @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    -- @coderabbitai read src/utils.ts and generate unit testing code.
    -- @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    -- @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Outside diff range and nitpick comments (3)
protocol/x/assets/types/types.go (2)

9-32: Consider adding documentation comments for the AssetsKeeper interface and its methods

The AssetsKeeper interface and its methods are exported and would benefit from GoDoc comments. Adding documentation will improve code readability and help other developers understand the purpose and usage of each method.

Apply this diff to add documentation comments:

 type AssetsKeeper interface {
+	// ConvertAssetToCoin converts a specified quantity of an asset into its coin representation.
 	ConvertAssetToCoin(ctx sdk.Context, assetId uint32, quantums *big.Int) (*big.Int, sdk.Coin, error)
+	
+	// CreateAsset creates a new asset with the given parameters.
 	CreateAsset(
 		ctx sdk.Context,
 		assetId uint32,
 		symbol string,
 		denom string,
 		denomExponent int32,
 		hasMarket bool,
 		marketId uint32,
 		atomicResolution int32,
 	) (
 		Asset,
 		error,
 	)
+	
+	// GetAsset retrieves an asset by its ID.
 	GetAsset(ctx sdk.Context, id uint32) (Asset, bool)
+	
+	// GetAllAssets retrieves all existing assets.
 	GetAllAssets(ctx sdk.Context) []Asset
+	
+	// IsPositionUpdatable checks if a position can be updated for a given asset ID.
 	IsPositionUpdatable(ctx sdk.Context, id uint32) (bool, error)
+	
+	// ModifyAsset updates an existing asset's market properties.
 	ModifyAsset(ctx sdk.Context, id uint32, hasMarket bool, marketId uint32) (Asset, error)
 }

10-10: Ensure consistent naming for asset ID parameters

The parameter for asset IDs is inconsistently named (assetId vs. id). For clarity and consistency, consider using a uniform naming convention across all methods.

Apply this diff to standardize the parameter names:

 ConvertAssetToCoin(ctx sdk.Context, assetId uint32, quantums *big.Int) (*big.Int, sdk.Coin, error)
 CreateAsset(
 	ctx sdk.Context,
 	assetId uint32,
 	// ...
 )
-GetAsset(ctx sdk.Context, id uint32) (Asset, bool)
+GetAsset(ctx sdk.Context, assetId uint32) (Asset, bool)

-IsPositionUpdatable(ctx sdk.Context, id uint32) (bool, error)
+IsPositionUpdatable(ctx sdk.Context, assetId uint32) (bool, error)

-ModifyAsset(ctx sdk.Context, id uint32, hasMarket bool, marketId uint32) (Asset, error)
+ModifyAsset(ctx sdk.Context, assetId uint32, hasMarket bool, marketId uint32) (Asset, error)

Also applies to: 13-13, 25-25, 29-29, 31-31

protocol/x/vault/keeper/sweep_funds.go (1)

10-11: Correct the function comment to match the function name and capitalize "USDC".

The function comment refers to SweepMainVaultBankBalances, but the actual function name is SweepMainVaultBankBalance. Additionally, "usdc" should be capitalized as "USDC" for consistency.

Apply the following diff to correct the comment:

-// SweepMainVaultBankBalances deposits any usdc balance from the Megavault main vault bank balance
+// SweepMainVaultBankBalance deposits any USDC balance from the Megavault main vault bank balance
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between b37ff5e and 716603a.

Files selected for processing (11)
  • protocol/app/app.go (1 hunks)
  • protocol/mocks/AssetsKeeper.go (1 hunks)
  • protocol/mocks/Makefile (1 hunks)
  • protocol/testutil/keeper/vault.go (1 hunks)
  • protocol/x/assets/types/types.go (1 hunks)
  • protocol/x/vault/abci.go (1 hunks)
  • protocol/x/vault/keeper/keeper.go (3 hunks)
  • protocol/x/vault/keeper/sweep_funds.go (1 hunks)
  • protocol/x/vault/keeper/sweep_funds_test.go (1 hunks)
  • protocol/x/vault/types/expected_keepers.go (2 hunks)
  • protocol/x/vault/types/megavault.go (1 hunks)
Files skipped from review due to trivial changes (2)
  • protocol/mocks/AssetsKeeper.go
  • protocol/x/vault/types/megavault.go
Additional comments not posted (10)
protocol/x/vault/abci.go (1)

39-39: Integration of SweepMainVaultBankBalance into EndBlocker is appropriate

The addition of keeper.SweepMainVaultBankBalance(ctx) after keeper.RefreshAllVaultOrders(ctx) correctly implements the sweeping of the megavault's main vault bank balance into the subaccount balance during end-of-block processing, aligning with the PR objectives.

protocol/x/vault/keeper/sweep_funds.go (1)

12-48: Function implementation looks good.

The SweepMainVaultBankBalance function correctly transfers any USDC balance from the Megavault's main vault bank account to its main vault subaccount, with appropriate error handling.

protocol/testutil/keeper/vault.go (1)

65-66: Ensure mocks.AssetsKeeper and mocks.BankKeeper are Properly Mocked

The &mocks.AssetsKeeper{} and &mocks.BankKeeper{} are instantiated as empty structs when creating the vault keeper. To prevent nil pointer dereferences or unintended behavior during testing, ensure that all methods expected to be called on these mocks are properly set up with the necessary mock behaviors.

To identify which methods need to be mocked, run the following script to find all method calls to AssetsKeeper and BankKeeper within the vault keeper:

This script searches for method invocations on assetsKeeper and bankKeeper within the vault keeper module. Verify that all these methods are appropriately mocked in your test setup.

protocol/x/vault/types/expected_keepers.go (3)

4-4: Importing the "context" package

The addition of the "context" package is necessary for the BankKeeper interface. This ensures that all context types are properly referenced.


17-25: AssetsKeeper interface addition is well-defined

The new AssetsKeeper interface with the GetAsset method is correctly defined and follows the existing code patterns.


96-102: DepositFundsFromAccountToSubaccount method addition is appropriate

The addition of the DepositFundsFromAccountToSubaccount method to the SubaccountsKeeper interface is well-structured and consistent with existing interface definitions.

protocol/app/app.go (1)

1181-1182: Verify the updated VaultKeeper initialization parameters

The vaultmodulekeeper.NewKeeper function now includes app.AssetsKeeper and app.BankKeeper as parameters. Ensure that this change aligns with the updated function signature in the vaultmodulekeeper package and that all other instantiations of NewKeeper are updated accordingly throughout the codebase.

Run the following script to verify the function usage:

Verification successful

To gather more information and ensure a comprehensive verification, I'll run additional scripts to check the points mentioned in the analysis.


To address the unexpected results and locate the correct NewKeeper function for the vault module, I'll run an additional script to search for the relevant files and function definition.


Based on the analysis of the NewKeeper function definition and its usage, I can now provide a final response.

VaultKeeper initialization parameters are correct and consistent

The updated VaultKeeper initialization in app.go correctly includes the new parameters app.AssetsKeeper and app.BankKeeper. These changes align with the NewKeeper function signature in the vault module (protocol/x/vault/keeper/keeper.go). All required parameters, including app.ClobKeeper, are present in the call site.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all calls to `vaultmodulekeeper.NewKeeper` include the new parameters.

# Test: Search for the function calls. Expect: All calls should have the new parameters.
rg --type go 'vaultmodulekeeper\.NewKeeper\(' -A 5

Length of output: 324


Script:

#!/bin/bash

# Search for any other instances of NewKeeper in the codebase
echo "Searching for other instances of NewKeeper:"
rg --type go 'NewKeeper\(' -g '!app.go'

# Examine the NewKeeper function definition in the vaultmodulekeeper package
echo -e "\nExamining NewKeeper function definition:"
rg --type go '^func NewKeeper\(' -g '**/vaultmodulekeeper/*.go' -A 10

# Search for references to VaultKeeper that might need updates
echo -e "\nSearching for VaultKeeper references:"
rg --type go 'VaultKeeper' -g '!app.go'

Length of output: 10563


Script:

#!/bin/bash

# Search for vault keeper files
echo "Searching for vault keeper files:"
fd -e go keeper protocol/x/vault

# Search for NewKeeper function in vault module files
echo -e "\nSearching for NewKeeper function in vault module:"
rg --type go '^func NewKeeper\(' protocol/x/vault -A 10

# Check for any TODO comments related to VaultKeeper
echo -e "\nChecking for TODO comments related to VaultKeeper:"
rg --type go 'TODO.*VaultKeeper'

Length of output: 1285

protocol/x/vault/keeper/keeper.go (3)

19-20: Addition of assetsKeeper and bankKeeper to the Keeper struct is appropriate.

These new dependencies will enhance the functionality of the Keeper by integrating asset management and banking capabilities.


35-36: Updated NewKeeper function signature to include new dependencies.

Including assetsKeeper and bankKeeper in the constructor ensures that the Keeper is properly initialized with the necessary modules.


49-50: Assignment of new dependencies in the Keeper initialization is correct.

The assetsKeeper and bankKeeper are correctly assigned to their respective fields in the Keeper struct.

Comment on lines +27 to +33
type BankKeeper interface {
GetBalance(
ctx context.Context,
addr sdk.AccAddress,
denom string,
) sdk.Coin
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent use of context types in BankKeeper interface

The BankKeeper interface's GetBalance method uses context.Context instead of sdk.Context, which is inconsistent with other interfaces in this file that use sdk.Context. This inconsistency might lead to confusion or potential errors due to the different context implementations.

Apply this diff to align the context type:

 type BankKeeper interface {
     GetBalance(
-        ctx context.Context,
+        ctx sdk.Context,
         addr sdk.AccAddress,
         denom string,
     ) sdk.Coin
 }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type BankKeeper interface {
GetBalance(
ctx context.Context,
addr sdk.AccAddress,
denom string,
) sdk.Coin
}
type BankKeeper interface {
GetBalance(
ctx sdk.Context,
addr sdk.AccAddress,
denom string,
) sdk.Coin
}

@@ -63,3 +63,4 @@ mock-gen:
@go run github.com/vektra/mockery/v2 --name=OracleClient --dir=$(GOPATH)/pkg/mod/github.com/skip-mev/slinky@$(SLINKY_VERSION)/service/clients/oracle --recursive --output=./mocks
@go run github.com/vektra/mockery/v2 --name=ExtendVoteHandler --dir=$(GOPATH)/pkg/mod/github.com/dydxprotocol/cosmos-sdk@$(COSMOS_VERSION)/types --recursive --output=./mocks
@go run github.com/vektra/mockery/v2 --name=UpdateMarketPriceTxDecoder --dir=./app/process --recursive --output=./mocks
@go run github.com/vektra/mockery/v2 --name=AssetsKeeper --dir=./x//types --recursive --output=./mocks
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct the directory path in the mock generation command

The --dir argument in the mock generation command contains an extra slash (//) which may cause issues when generating the mock for AssetsKeeper. It should point to the correct directory where AssetsKeeper is defined.

Apply this diff to fix the directory path:

-	@go run github.com/vektra/mockery/v2 --name=AssetsKeeper --dir=./x//types --recursive --output=./mocks
+	@go run github.com/vektra/mockery/v2 --name=AssetsKeeper --dir=./x/assets/types --recursive --output=./mocks
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@go run github.com/vektra/mockery/v2 --name=AssetsKeeper --dir=./x//types --recursive --output=./mocks
@go run github.com/vektra/mockery/v2 --name=AssetsKeeper --dir=./x/assets/types --recursive --output=./mocks

Comment on lines +23 to +102
func TestSweepMainVaultBankBalance(t *testing.T) {
tests := map[string]struct {
// Bank balance of main vault
bankBalance int64
// Subaccount balance of main vault
subaccountBalance *big.Int
// Expected bank balance of main vault
expectedBankBalance int64
// Expected subaccount balance of main vault
expectedSubaccountBalance *big.Int
}{
"Zero bank balance, zero subaccount balance": {
bankBalance: 0,
subaccountBalance: big.NewInt(0),
expectedBankBalance: 0,
expectedSubaccountBalance: big.NewInt(0),
},
"100_000_000 quantums bank balance, zero subaccount balance": {
bankBalance: 100_000_000,
subaccountBalance: big.NewInt(0),
expectedBankBalance: 0,
expectedSubaccountBalance: big.NewInt(100_000_000),
},
"100_000_000 quantums bank balance, 50_000_000 subaccount balance": {
bankBalance: 100_000_000,
subaccountBalance: big.NewInt(50_000_000),
expectedBankBalance: 0,
expectedSubaccountBalance: big.NewInt(150_000_000),
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// Initialize vaults with their equities.
tApp := testapp.NewTestAppBuilder(t).WithGenesisDocFn(func() (genesis types.GenesisDoc) {
genesis = testapp.DefaultGenesis()
testapp.UpdateGenesisDocWithAppStateForModule(
&genesis,
func(genesisState *satypes.GenesisState) {
genesisState.Subaccounts = []satypes.Subaccount{
{
Id: &vaulttypes.MegavaultMainSubaccount,
AssetPositions: []*satypes.AssetPosition{
testutil.CreateSingleAssetPosition(
assettypes.AssetUsdc.Id,
tc.subaccountBalance,
),
},
},
}
},
)
testapp.UpdateGenesisDocWithAppStateForModule(
&genesis,
func(genesisState *banktypes.GenesisState) {
genesisState.Balances = append(genesisState.Balances, banktypes.Balance{
Address: vaulttypes.MegavaultMainAddress.String(),
Coins: sdktypes.Coins{
sdktypes.NewCoin(constants.Usdc.Denom, sdkmath.NewInt(tc.bankBalance)),
},
})
},
)
return genesis
}).Build()
ctx := tApp.InitChain()
k := tApp.App.VaultKeeper

k.SweepMainVaultBankBalance(ctx)

mainVaultSubaccount := tApp.App.SubaccountsKeeper.GetSubaccount(ctx, vaulttypes.MegavaultMainSubaccount)
require.Equal(t, tc.expectedSubaccountBalance, mainVaultSubaccount.AssetPositions[0].Quantums.BigInt())
mainVaultBankBalance := tApp.App.BankKeeper.GetBalance(
ctx,
vaulttypes.MegavaultMainAddress,
constants.Usdc.Denom,
).Amount
require.Equal(t, sdkmath.NewIntFromBigInt(big.NewInt(tc.expectedBankBalance)), mainVaultBankBalance)
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider Refactoring Common Setup Code to Reduce Duplication

The TestSweepMainVaultBankBalance function contains setup code for initializing the test application and configuring the genesis state (lines 55-86). This setup is similar to the one in TestSweepMainVaultBankBalance_EndBlock. To improve maintainability and reduce code duplication, consider refactoring this setup code into shared helper functions or methods.

Comment on lines +104 to +219
},
"100_000_000 quantums bank balance, zero subaccount balance": {
bankBalance: 100_000_000,
subaccountBalance: 0,
expectedBankBalance: 0,
expectedSubaccountBalance: big.NewInt(100_000_000),
},
"100_000_000 quantums bank balance, 50_000_000 subaccount balance": {
bankBalance: 100_000_000,
subaccountBalance: 50_000_000,
expectedBankBalance: 0,
expectedSubaccountBalance: big.NewInt(150_000_000),
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
tApp := testapp.NewTestAppBuilder(t).WithGenesisDocFn(func() (genesis types.GenesisDoc) {
genesis = testapp.DefaultGenesis()
testapp.UpdateGenesisDocWithAppStateForModule(
&genesis,
func(genesisState *satypes.GenesisState) {
genesisState.Subaccounts = []satypes.Subaccount{
{
Id: &vaulttypes.MegavaultMainSubaccount,
AssetPositions: []*satypes.AssetPosition{
testutil.CreateSingleAssetPosition(
assettypes.AssetUsdc.Id,
big.NewInt(0),
),
},
},
}
},
)
return genesis
}).Build()

// Fund the subaccount and bank balance of megavault
ctx := tApp.AdvanceToBlock(2, testapp.AdvanceToBlockOptions{})
if tc.subaccountBalance > 0 {
var msg proto.Message
depositMsg := sendingtypes.MsgDepositToSubaccount{
Sender: constants.AliceAccAddress.String(),
Recipient: vaulttypes.MegavaultMainSubaccount,
AssetId: constants.Usdc.Id,
Quantums: tc.subaccountBalance,
}
msg = &depositMsg
for _, checkTx := range testapp.MustMakeCheckTxsWithSdkMsg(
ctx,
tApp.App,
testapp.MustMakeCheckTxOptions{
AccAddressForSigning: constants.AliceAccAddress.String(),
Gas: 1000000,
FeeAmt: constants.TestFeeCoins_5Cents,
},
msg,
) {
resp := tApp.CheckTx(checkTx)
require.Condition(t, resp.IsOK, "Expected CheckTx to succeed. Response: %+v", resp)
}
}
if tc.bankBalance > 0 {
var msg proto.Message
bankSendMsg := banktypes.MsgSend{
FromAddress: constants.AliceAccAddress.String(),
ToAddress: vaulttypes.MegavaultMainAddress.String(),
Amount: sdktypes.Coins{
sdktypes.NewCoin(constants.Usdc.Denom, sdkmath.NewInt(tc.bankBalance)),
},
}
msg = &bankSendMsg
for _, checkTx := range testapp.MustMakeCheckTxsWithSdkMsg(
ctx,
tApp.App,
testapp.MustMakeCheckTxOptions{
AccAddressForSigning: constants.AliceAccAddress.String(),
Gas: 1000000,
FeeAmt: constants.TestFeeCoins_5Cents,
},
msg,
) {
resp := tApp.CheckTx(checkTx)
require.Condition(t, resp.IsOK, "Expected CheckTx to succeed. Response: %+v", resp)
}
}
// Advance block to execute EndBlocker
ctx = tApp.AdvanceToBlock(3, testapp.AdvanceToBlockOptions{})

mainVaultSubaccount := tApp.App.SubaccountsKeeper.GetSubaccount(ctx, vaulttypes.MegavaultMainSubaccount)
require.Equal(t, tc.expectedSubaccountBalance, mainVaultSubaccount.AssetPositions[0].Quantums.BigInt())
mainVaultBankBalance := tApp.App.BankKeeper.GetBalance(
ctx,
vaulttypes.MegavaultMainAddress,
constants.Usdc.Denom,
).Amount
require.Equal(t, sdkmath.NewIntFromBigInt(big.NewInt(tc.expectedBankBalance)), mainVaultBankBalance)
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consolidate Duplicate Test Setup Code

In TestSweepMainVaultBankBalance_EndBlock, the initialization and genesis state configuration (lines 136-155) duplicate code from TestSweepMainVaultBankBalance. Refactoring this shared code into helper functions will enhance readability and make future maintenance easier.

Comment on lines +158 to +205
ctx := tApp.AdvanceToBlock(2, testapp.AdvanceToBlockOptions{})
if tc.subaccountBalance > 0 {
var msg proto.Message
depositMsg := sendingtypes.MsgDepositToSubaccount{
Sender: constants.AliceAccAddress.String(),
Recipient: vaulttypes.MegavaultMainSubaccount,
AssetId: constants.Usdc.Id,
Quantums: tc.subaccountBalance,
}
msg = &depositMsg
for _, checkTx := range testapp.MustMakeCheckTxsWithSdkMsg(
ctx,
tApp.App,
testapp.MustMakeCheckTxOptions{
AccAddressForSigning: constants.AliceAccAddress.String(),
Gas: 1000000,
FeeAmt: constants.TestFeeCoins_5Cents,
},
msg,
) {
resp := tApp.CheckTx(checkTx)
require.Condition(t, resp.IsOK, "Expected CheckTx to succeed. Response: %+v", resp)
}
}
if tc.bankBalance > 0 {
var msg proto.Message
bankSendMsg := banktypes.MsgSend{
FromAddress: constants.AliceAccAddress.String(),
ToAddress: vaulttypes.MegavaultMainAddress.String(),
Amount: sdktypes.Coins{
sdktypes.NewCoin(constants.Usdc.Denom, sdkmath.NewInt(tc.bankBalance)),
},
}
msg = &bankSendMsg
for _, checkTx := range testapp.MustMakeCheckTxsWithSdkMsg(
ctx,
tApp.App,
testapp.MustMakeCheckTxOptions{
AccAddressForSigning: constants.AliceAccAddress.String(),
Gas: 1000000,
FeeAmt: constants.TestFeeCoins_5Cents,
},
msg,
) {
resp := tApp.CheckTx(checkTx)
require.Condition(t, resp.IsOK, "Expected CheckTx to succeed. Response: %+v", resp)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplify Funding Logic in Tests

The funding logic for the subaccount and bank balance of the Megavault (lines 158-205) involves repeated patterns for message creation and transaction execution. To improve clarity and reduce repetition, consider creating helper functions to handle the funding of subaccounts and bank balances within your tests.

func (k Keeper) SweepMainVaultBankBalance(
ctx sdk.Context,
) {
usdcAsset, exists := k.assetsKeeper.GetAsset(ctx, assettypes.AssetUsdc.Id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can also just use assetstypes.AssetUsdc to be simpler? don't need to pass in AssetsKeeper anymore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Led to a flaky simulation test when I removed it, going to add it back in for now.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Outside diff range and nitpick comments (2)
protocol/app/app.go (2)

Line range hint 1181-1192: The authority for conducting upgrades is correctly set.

The VaultKeeper is instantiated with the governance and delaymsg module accounts as the authority for conducting upgrades, which looks good.

Consider refactoring if the VaultKeeper is taking on too many responsibilities.

The VaultKeeper has dependencies on several other keepers (AssetsKeeper, BankKeeper, ClobKeeper, DelayMsgKeeper, PerpetualsKeeper, PricesKeeper, SendingKeeper, SubaccountsKeeper), which might indicate tight coupling and potential violation of the single responsibility principle.

In the future, consider evaluating if the VaultKeeper is taking on too many responsibilities and if it can be refactored to have fewer dependencies. However, more context is needed to make a definitive assessment.


Line range hint 1181-1192: Add the FeeTiersKeeper to the VaultKeeper instantiation for consistency.

The FeeTiersKeeper is set to the VaultKeeper in the line after this code segment:

app.FeeTiersKeeper.SetVaultKeeper(app.VaultKeeper)

For consistency and to avoid potential issues if the VaultKeeper needs to interact with the FeeTiersKeeper, consider adding the FeeTiersKeeper to the VaultKeeper instantiation as well:

app.VaultKeeper = *vaultmodulekeeper.NewKeeper(
    // ...
    app.FeeTiersKeeper,
    // ...
)
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between e907a8b and 384c3e1.

Files selected for processing (5)
  • protocol/app/app.go (1 hunks)
  • protocol/testutil/keeper/vault.go (1 hunks)
  • protocol/x/vault/keeper/keeper.go (3 hunks)
  • protocol/x/vault/keeper/sweep_funds.go (1 hunks)
  • protocol/x/vault/types/expected_keepers.go (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • protocol/x/vault/keeper/sweep_funds.go
Additional comments not posted (9)
protocol/testutil/keeper/vault.go (1)

65-66: LGTM!

The addition of mocks.AssetsKeeper and mocks.BankKeeper as dependencies in the createVaultKeeper function is a good practice for enhancing the testing capabilities of the vault keeper.

By using mocks for these dependencies, you can:

  • Isolate the testing of the vault keeper from the actual implementations of the assets and bank modules.
  • Simulate various scenarios and edge cases without relying on the real modules.
  • Improve the robustness and maintainability of the testing framework.

This change facilitates more comprehensive unit testing and provides a controlled environment for the vault keeper's operations.

protocol/x/vault/keeper/keeper.go (4)

19-19: LGTM!

The addition of the assetsKeeper field to the Keeper struct is a valid change that aligns with the provided summary. It integrates asset management capabilities into the Keeper.


20-20: LGTM!

The addition of the bankKeeper field to the Keeper struct is a valid change that aligns with the provided summary. It integrates banking capabilities into the Keeper.


35-36: LGTM!

The addition of the assetsKeeper and bankKeeper parameters to the NewKeeper constructor function is a valid change that aligns with the provided summary. It allows for the initialization of the corresponding fields in the Keeper struct, supporting the integration of asset management and banking capabilities.


49-50: LGTM!

The initialization of the assetsKeeper and bankKeeper fields in the NewKeeper constructor function is a valid change that aligns with the provided summary. It ensures that the Keeper struct is properly initialized with the provided asset management and banking capabilities.

protocol/x/vault/types/expected_keepers.go (3)

17-25: LGTM!

The AssetsKeeper interface and its GetAsset method are well-defined, with consistent usage of sdk.Context and appropriate return types.


96-102: LGTM!

The addition of the DepositFundsFromAccountToSubaccount method to the SubaccountsKeeper interface is well-implemented, with consistent usage of sdk.Context and other types. This method aligns with the PR objectives of facilitating the transfer of funds from a main account to a subaccount.


27-33: Inconsistent use of context types in BankKeeper interface

The BankKeeper interface's GetBalance method uses context.Context instead of sdk.Context, which is inconsistent with other interfaces in this file that use sdk.Context. This inconsistency might lead to confusion or potential errors due to the different context implementations.

Apply this diff to align the context type:

 type BankKeeper interface {
     GetBalance(
-        ctx context.Context,
+        ctx sdk.Context,
         addr sdk.AccAddress,
         denom string,
     ) sdk.Coin
 }

Likely invalid or redundant comment.

protocol/app/app.go (1)

1181-1182: LGTM!

The VaultKeeper is correctly instantiated with dependencies on the AssetsKeeper and BankKeeper, which it likely needs to interact with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

2 participants