Skip to content

Conversation

meetrick
Copy link
Contributor

@meetrick meetrick commented Aug 30, 2025

Description

Closes: #25144

  • Update TrackDelegation and TrackUndelegation methods to return errors
  • Modify all vesting account implementations accordingly
  • Add proper error handling in bank keeper
  • Update tests to expect errors instead of panics

Summary by CodeRabbit

  • Bug Fixes

    • Delegation and undelegation with vesting accounts now return clear errors for invalid inputs (e.g., zero amounts, insufficient funds), preventing crashes and ensuring account state remains consistent.
    • Improved user-facing error messages during vesting-related operations.
  • Refactor

    • Standardized error handling across all vesting account types and banking flows for consistent behavior.
    • Ensures accounts are only updated on successful operations, improving reliability and predictability for delegation/undelegation actions.

Copy link
Contributor

coderabbitai bot commented Aug 30, 2025

📝 Walkthrough

Walkthrough

Adds error returns to VestingAccount.TrackDelegation and TrackUndelegation interfaces. Updates all vesting account implementations to validate inputs and return errors instead of panicking. Propagates and handles these errors in x/bank keeper. Updates tests accordingly. Interfaces adjusted in both x/auth/vesting and x/bank/types.

Changes

Cohort / File(s) Summary
Vesting interfaces
x/auth/vesting/exported/exported.go, x/bank/types/vesting.go
VestingAccount interface methods TrackDelegation and TrackUndelegation now return error; comments updated to describe error cases.
Vesting implementations
x/auth/vesting/types/vesting_account.go
All vesting account types updated: TrackDelegation/TrackUndelegation now return error; input validation added; propagate BaseVestingAccount errors.
Bank keeper error handling
x/bank/keeper/keeper.go
BaseKeeper.trackDelegation/trackUndelegation updated to handle and wrap errors from VestingAccount methods; SetAccount called only on success.
Tests
x/auth/vesting/types/vesting_account_test.go
Tests updated to assert returned errors instead of panics; all call sites adapted to new signatures.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Msg/Module as Caller (Bank)
  participant Keeper as BankKeeper
  participant VA as VestingAccount

  Note over Keeper,VA: Delegation flow with error returns
  Msg/Module->>Keeper: trackDelegation(addr, amt)
  Keeper->>VA: TrackDelegation(blockTime, balance, amt)
  alt ok
    VA-->>Keeper: nil
    Keeper->>Keeper: SetAccount(updated)
    Keeper-->>Msg/Module: nil
  else error
    VA-->>Keeper: error
    Keeper-->>Msg/Module: wrapped error
  end
Loading
sequenceDiagram
  autonumber
  participant Msg/Module as Caller (Bank)
  participant Keeper as BankKeeper
  participant VA as VestingAccount

  Note over Keeper,VA: Undelegation flow with error returns
  Msg/Module->>Keeper: trackUndelegation(addr, amt)
  Keeper->>VA: TrackUndelegation(amt)
  alt ok
    VA-->>Keeper: nil
    Keeper->>Keeper: SetAccount(updated)
    Keeper-->>Msg/Module: nil
  else error
    VA-->>Keeper: error
    Keeper-->>Msg/Module: wrapped error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Change VestingAccount interface to return errors instead of panicking (#25144)
Update all vesting account implementations to return/propagate errors (#25144)
Update x/bank keeper to handle errors from TrackDelegation/TrackUndelegation (#25144)

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
x/bank/keeper/keeper.go (2)

130-151: Prevent partial state updates: reject non-positive amounts before any balance mutations.

If TrackDelegation returns an error (e.g., non-positive amounts), we’ve already deducted balances in the loop above, leading to inconsistent state. Add an explicit positivity check so TrackDelegation shouldn’t error after we mutate balances.

   if !amt.IsValid() {
     return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, amt.String())
   }
+  // Reject zero/negative amounts up-front to avoid TrackDelegation errors after deductions.
+  if !amt.IsAllPositive() {
+    return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, "amount must be > 0")
+  }

   balances := sdk.NewCoins()

Follow-up (optional, safer): call k.trackDelegation before setBalance and perform a best-effort rollback (TrackUndelegation) if a later write fails. Can provide a patch if you want to go that route.


179-189: Same issue on undelegation: reject non-positive amounts before mutating the module account balance.

Avoid subtracting from the module account and then returning on TrackUndelegation error.

   if !amt.IsValid() {
     return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, amt.String())
   }
+  if !amt.IsAllPositive() {
+    return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, "amount must be > 0")
+  }
🧹 Nitpick comments (7)
x/auth/vesting/exported/exported.go (1)

25-31: Doc phrasing: prefer “non-positive amount” and avoid duplicating specifics across packages.

Nit: use “non-positive amount” instead of “zero amount” to match typical SDK validation language and mirror the same wording in x/bank/types. Also consider keeping the comment generic (“returns an error if the operation is invalid”) to reduce drift between this interface and the mirror in x/bank/types.

Apply:

-// Returns an error if the delegation is invalid (e.g., zero amount or insufficient funds).
+// Returns an error if the delegation is invalid (e.g., non-positive amount or insufficient funds).
...
-// Returns an error if the undelegation is invalid (e.g., zero amount).
+// Returns an error if the undelegation is invalid (e.g., non-positive amount).
x/bank/types/vesting.go (1)

23-29: Keep wording consistent with exported interface (use “non-positive amount”).

Mirror the phrasing used in x/auth/vesting/exported to avoid doc drift.

-// Returns an error if the delegation is invalid (e.g., zero amount or insufficient funds).
+// Returns an error if the delegation is invalid (e.g., non-positive amount or insufficient funds).
...
-// Returns an error if the undelegation is invalid (e.g., zero amount).
+// Returns an error if the undelegation is invalid (e.g., non-positive amount).
x/bank/keeper/keeper.go (2)

151-153: Avoid double-wrapping errors; keep one contextual layer.

trackDelegation/trackUndelegation already return an error wrapped with account context. Wrapping again here duplicates “failed to track …” verbiage.

-  if err := k.trackDelegation(ctx, delegatorAddr, balances, amt); err != nil {
-    return errorsmod.Wrap(err, "failed to track delegation")
-  }
+  if err := k.trackDelegation(ctx, delegatorAddr, balances, amt); err != nil {
+    return err
+  }
...
-  if err := k.trackUndelegation(ctx, delegatorAddr, amt); err != nil {
-    return errorsmod.Wrap(err, "failed to track undelegation")
-  }
+  if err := k.trackUndelegation(ctx, delegatorAddr, amt); err != nil {
+    return err
+  }

Also applies to: 188-190


441-451: Remove “TODO: COMPLETED” blocks.

These are noisy commit notes in production code. The surrounding code and commit history already convey this change.

-    // TODO: ✅ COMPLETED - Changed VestingAccount interface to return errors instead of panicking
-    // - Updated TrackDelegation(blockTime time.Time, balance, amount sdk.Coins) to return error
-    // - Updated TrackUndelegation(amount sdk.Coins) to return error
-    // - Added error handling here instead of letting panics occur
-    // - This was a breaking change that required updating all vesting account implementations

Also applies to: 466-474

x/auth/vesting/types/vesting_account.go (2)

60-74: Use typed SDK errors for consistency and clearer upstream handling; fix comment grammar.

Return sdkerrors (wrapped) instead of fmt.Errorf and tweak the comment wording.

-func (bva *BaseVestingAccount) TrackDelegation(balance, vestingCoins, amount sdk.Coins) error {
+func (bva *BaseVestingAccount) TrackDelegation(balance, vestingCoins, amount sdk.Coins) error {
   for _, coin := range amount {
     baseAmt := balance.AmountOf(coin.Denom)
     vestingAmt := vestingCoins.AmountOf(coin.Denom)
     delVestingAmt := bva.DelegatedVesting.AmountOf(coin.Denom)

-    // Return error if the delegation amount is zero or if the base coins does not
-    // exceed the desired delegation amount.
-    if coin.Amount.IsZero() {
-      return fmt.Errorf("delegation attempt with zero coins")
-    }
-    if baseAmt.LT(coin.Amount) {
-      return fmt.Errorf("delegation attempt with insufficient funds: balance %s, requested %s", baseAmt, coin.Amount)
-    }
+    // Return error if the delegation amount is non-positive or if the base balance is insufficient.
+    if coin.Amount.IsZero() {
+      return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, "delegation amount must be > 0")
+    }
+    if baseAmt.LT(coin.Amount) {
+      return errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, "balance %s, requested %s", baseAmt, coin.Amount)
+    }

Additional imports required at the top of this file:

import (
  // ...
  errorsmod "cosmossdk.io/errors"
  sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

103-109: Typed error for undelegation zero-amount case.

Match the delegation path and SDK error conventions.

-    if coin.Amount.IsZero() {
-      return fmt.Errorf("undelegation attempt with zero coins")
-    }
+    if coin.Amount.IsZero() {
+      return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, "undelegation amount must be > 0")
+    }
x/auth/vesting/types/vesting_account_test.go (1)

159-166: Tests updated to assert errors: LGTM; consider asserting NoError everywhere the new API returns error.

Most sites now use require.NoError/require.Error—good. There are still a few calls that ignore the error (e.g., Lines 145–148, 152–155, 565–576). For consistency with the new contract, assert errors at those sites too.

Example patch for one site:

- cva.TrackDelegation(now, origCoins, origCoins)
+ err := cva.TrackDelegation(now, origCoins, origCoins)
+ require.NoError(t, err)

If you want, I can sweep the file and send a patch normalizing all TrackDelegation/TrackUndelegation calls.

Also applies to: 164-168, 172-176, 187-201, 197-201, 207-211, 215-229, 221-231, 313-324, 330-334, 345-359, 365-369, 373-381, 386-390, 582-593, 600-609, 613-617, 633-647, 653-667, 671-675, 677-687, 743-747, 758-768, 766-770, 774-778, 789-793, 799-805, 809-813, 817-821, 823-833, 830-834

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge Base: Disabled due to Reviews > Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between b6b58e4 and 529f9cf.

📒 Files selected for processing (5)
  • x/auth/vesting/exported/exported.go (1 hunks)
  • x/auth/vesting/types/vesting_account.go (8 hunks)
  • x/auth/vesting/types/vesting_account_test.go (9 hunks)
  • x/bank/keeper/keeper.go (2 hunks)
  • x/bank/types/vesting.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (1)
x/auth/vesting/types/vesting_account.go (1)

243-245: Wrappers delegating to BaseVestingAccount look good.

Thin adapters returning error are correct and keep behavior centralized.

Also applies to: 348-350, 447-449, 503-505

… return errors instead of panicking

- Update TrackDelegation and TrackUndelegation methods to return errors
- Modify all vesting account implementations accordingly
- Add proper error handling in bank keeper
- Update tests to expect errors instead of panics

Signed-off-by: Hwangjae Lee <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

x/bank: Clarify intent for TrackDelegation/TrackUndelegation TODO comments
1 participant