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

feat(x/protocolpool)!: allow any coins in continuous funds #21916

Merged
merged 13 commits into from
Nov 11, 2024

Conversation

facundomedica
Copy link
Member

@facundomedica facundomedica commented Sep 25, 2024

Description

Previously only the bond denom could be used for continuous funds, now we allow any token.

We might want to add a param with a whitelist of tokens to avoid spam. Done with EnabledDistributionDenoms


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title, you can find examples of the prefixes below:
  • confirmed ! in the type prefix if API or client breaking change
  • targeted the correct branch (see PR Targeting)
  • provided a link to the relevant issue or specification
  • reviewed "Files changed" and left comments if necessary
  • included the necessary unit and integration tests
  • added a changelog entry to CHANGELOG.md
  • updated the relevant documentation or specification, including comments for documenting Go code
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

Please see Pull Request Reviewer section in the contributing guide for more information on how to review a pull request.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic, API design and naming, documentation is accurate, tests and test coverage

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a new DistributionAmount structure for handling multiple coins.
    • Added a new Params structure to manage distribution parameters.
    • Implemented the UpdateParams method for governance operations.
  • Improvements

    • Enhanced the handling of LastBalance and Amount fields to utilize structured types instead of primitive strings.
    • Improved validation logic for fund distributions to ensure robustness.
    • Simplified the initialization of Keeper by removing the StakingKeeper dependency.
  • Bug Fixes

    • Adjusted tests to reflect changes in data types and ensure accurate comparisons.
  • Chores

    • Removed references to the StakingKeeper interface and its mock implementations, streamlining the codebase.

Copy link
Contributor

coderabbitai bot commented Sep 25, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

The changes involve significant updates to the cosmos.protocolpool.v1 package, primarily focusing on the data structures used for handling balances and distributions. Key modifications include transitioning from primitive types like string and math.Int to more complex structures such as DistributionAmount, which allows for better representation of multiple coin types. Additionally, several methods and message definitions have been updated to accommodate these new structures, enhancing the overall functionality and flexibility of the protocol's financial handling.

Changes

File(s) Change Summary
api/cosmos/protocolpool/v1/genesis.pulsar.go, api/cosmos/protocolpool/v1/types.pulsar.go Updated GenesisState and Distribution structures to use DistributionAmount instead of string for balance fields, affecting multiple methods for handling these fields as messages.
x/protocolpool/keeper/genesis.go, x/protocolpool/keeper/keeper.go, x/protocolpool/keeper/msg_server.go Removed StakingKeeper dependencies, updated fund distribution logic to utilize DistributionAmount, and adjusted methods accordingly to reflect changes in how balances and distributions are managed.
x/protocolpool/proto/cosmos/protocolpool/v1/genesis.proto, x/protocolpool/proto/cosmos/protocolpool/v1/tx.proto Modified proto files to replace primitive types with DistributionAmount for financial fields, allowing for more complex data representation.
x/protocolpool/testutil/expected_keepers_mocks.go, x/protocolpool/types/expected_keepers.go Removed mock implementations for StakingKeeper and its interface, indicating a decoupling from staking-related functionalities.

Possibly related PRs

  • chore(x/staking): revert proto breakage #21666: The changes in this PR involve modifications to the genesis.proto file, specifically altering the GenesisState and Distribution message structures, which are directly related to the changes made in the main PR regarding the GenesisState and Distribution structures.
  • docs: remove invariants #22126: This PR discusses the removal of invariants, which may indirectly relate to the structural changes in the GenesisState and Distribution as it reflects a broader shift in how state management is approached in the SDK.
  • docs: pre,begin,end block #22127: This PR focuses on documentation updates related to the lifecycle methods in the Cosmos SDK, which includes BeginBlock and EndBlock, relevant to the overall structure and functionality of the SDK, including the changes made in the main PR.
  • docs(x/distribution): updates #22148: This PR updates documentation related to the distribution module, which is relevant as the main PR also modifies structures related to distribution, enhancing the understanding of how these changes fit into the broader context of the SDK.
  • fix(x/accounts/lockup): fix proto path #22319: This PR addresses import path changes related to the lockup module, which is relevant as it reflects the ongoing structural changes in the SDK that align with the modifications made in the main PR regarding data structures.

Suggested labels

C:x/accounts

Suggested reviewers

  • alpe
  • testinginprod
  • sontrinh16
  • kocubinski

📜 Recent review details

Configuration used: .coderabbit.yml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9574dc2 and 58b5c6d.

⛔ Files ignored due to path filters (2)
  • client/v2/internal/testpb/msg_grpc.pb.go is excluded by !**/*.pb.go
  • client/v2/internal/testpb/query_grpc.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (1)
  • api/cosmos/protocolpool/v1/genesis.pulsar.go (38 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
api/cosmos/protocolpool/v1/genesis.pulsar.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

🔇 Additional comments (4)
api/cosmos/protocolpool/v1/genesis.pulsar.go (4)

Line range hint 177-187: Skip review - issue already addressed

A past review comment already covers the naming convention issue for field descriptors.


1485-1492: Well-documented changes to GenesisState

The changes effectively support the PR objective of allowing any coins in continuous funds:

  • LastBalance field now uses DistributionAmount to support multiple denominations
  • New Params field is added with clear documentation explaining its purpose for controlling distribution denominations

1555-1560: Well-structured Distribution type with clear documentation

The changes effectively support distribution tracking:

  • Time field is well-documented, explaining its purpose for tracking distribution timing for non-expired funds
  • Amount field uses DistributionAmount to support multiple denominations

1678-1694: Consistent protobuf type definitions

The protobuf type definitions are well-structured:

  • New types (DistributionAmount, Params) are properly registered
  • Dependencies are correctly ordered in the type indices

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.

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.

x.Amount = *clv.list
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.protocolpool.v1.DistributionAmount"))

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.protocolpool.v1.DistributionAmount"))
}
panic(fmt.Errorf("message cosmos.protocolpool.v1.DistributionAmount does not contain field %s", fd.FullName()))

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
@facundomedica facundomedica marked this pull request as ready for review September 25, 2024 23:55
@facundomedica facundomedica requested review from hieuvubk, alpe and a team as code owners September 25, 2024 23:55
Copy link
Contributor

@facundomedica your pull request is missing a changelog!

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: 12

🧹 Outside diff range and nitpick comments (16)
x/protocolpool/keeper/genesis_test.go (3)

35-35: LGTM! Consider adding a constant for the coin denom.

The change to use DistributionAmount with sdk.NewCoins aligns well with the PR objective of allowing any coins in continuous funds. This provides more flexibility in representing different coin types.

Consider defining a constant for the "stake" denom at the package level to improve maintainability:

const testDenom = "stake"

Then use it in the test:

Amount: types.DistributionAmount{Amount: sdk.NewCoins(sdk.NewCoin(testDenom, math.NewInt(100)))},

43-43: LGTM! Consider using a variable for consistency.

The change to use DistributionAmount for LastBalance is consistent with the previous change and aligns with the PR objectives.

For better consistency and to make the relationship between the distributed amount and last balance clearer, consider using a variable:

distributionAmount := math.NewInt(100)
lastBalanceAmount := math.NewInt(1)

gs.Distributions = append(gs.Distributions, &types.Distribution{
    Amount: types.DistributionAmount{Amount: sdk.NewCoins(sdk.NewCoin(testDenom, distributionAmount))},
    Time:   &time.Time{},
})

gs.LastBalance = types.DistributionAmount{Amount: sdk.NewCoins(sdk.NewCoin(testDenom, lastBalanceAmount))}

This makes it easier to adjust the test scenario and clearly shows that the last balance is less than the distribution amount.


52-52: LGTM! Consider using a variable for the expected amount.

The updated assertion correctly checks the specific coin amount in the new LastBalance structure.

To improve clarity and maintain consistency with the earlier suggestions, consider using a variable for the expected amount:

expectedLastBalance := math.OneInt()
suite.Require().Equal(expectedLastBalance, exportedGenState.LastBalance.Amount.AmountOf(testDenom))

This makes the expected value more explicit and easier to update if needed.

x/protocolpool/types/genesis.go (1)

Line range hint 1-78: Overall assessment: Changes look good, but ensure comprehensive testing.

The modifications to the NewGenesisState function, particularly the LastBalance field initialization, are consistent with the PR objectives of allowing any coins in continuous funds. The changes adhere to Golang coding standards and the Uber Golang style guide.

However, given that this change affects a fundamental structure (GenesisState), it's crucial to:

  1. Thoroughly test the impact of this change on all components that interact with GenesisState.
  2. Update any relevant documentation to reflect the new LastBalance type and initialization.
  3. Consider adding or updating unit tests to cover the new LastBalance behavior.

Consider adding a comment above the NewGenesisState function explaining the rationale behind initializing LastBalance with an empty set of coins, as this might not be immediately obvious to other developers.

x/protocolpool/proto/cosmos/protocolpool/v1/types.proto (1)

46-54: LGTM: New DistributionAmount message added with appropriate options.

The new DistributionAmount message is well-structured and aligns with the PR objective of allowing any coins in continuous funds. The use of repeated cosmos.base.v1beta1.Coin with appropriate Gogoproto and Amino options ensures compatibility and consistent behavior.

Consider adding a brief comment above the amount field to describe its purpose and any constraints (e.g., "Stores multiple coin types for distribution. Must not be empty."). This would enhance the self-documentation of the proto file.

 message DistributionAmount {
+  // Stores multiple coin types for distribution. Must not be empty.
   repeated cosmos.base.v1beta1.Coin amount = 1 [
     (gogoproto.nullable)     = false,
     (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
     (amino.dont_omitempty)   = true,
     (amino.encoding)         = "legacy_coins"
   ];
 }
x/protocolpool/keeper/msg_server.go (1)

160-162: LGTM with a minor suggestion for clarity.

The initialization of RecipientFundDistribution with an empty coin set is correct and aligns with the new flexibility to handle multiple coin types. This change supports the PR objective of allowing any coins in continuous funds.

For improved clarity and consistency with Go conventions, consider using a composite literal directly:

err = k.RecipientFundDistribution.Set(ctx, recipient, types.DistributionAmount{Amount: sdk.Coins{}})

This minor change eliminates the need for the NewCoins() function call while achieving the same result.

x/protocolpool/keeper/keeper_test.go (2)

143-150: LGTM: Updated type handling in TestIterateAndUpdateFundsDistribution

The changes correctly reflect the transition from math.Int to types.DistributionAmount. The test logic has been appropriately updated to check the Amount field of the new type.

Consider adding a test case for a DistributionAmount with multiple coins to ensure the new type is fully exercised.


211-220: LGTM: Updated type handling in TestSetToDistribute

The changes correctly reflect the transition to using DistributionAmount. The test logic has been appropriately updated to check the Amount field of the new type.

Consider adding a test case with multiple coins in the DistributionAmount to ensure the new type is fully tested.

x/protocolpool/keeper/genesis.go (2)

58-58: Consider renaming fields for clarity

In lines 58 and 60, the code references distribution.Amount.Amount, which can be confusing due to the repeated use of Amount. To improve readability and maintainability, consider renaming one of the Amount fields in the DistributionAmount struct. For example, you could rename the inner Amount field to Coins, resulting in distribution.Amount.Coins.

Apply this diff to rename the field:

-type DistributionAmount struct {
-    Amount sdk.Coins
-}
+type DistributionAmount struct {
+    Coins sdk.Coins
+}

This change will require updating all usages of distribution.Amount.Amount to distribution.Amount.Coins.

Also applies to: 60-60


Line range hint 121-127: Avoid variable shadowing of the err variable in the closure

In the anonymous function passed to k.Distributions.Walk, the named return parameter err error shadows the err variable in the outer scope. This can lead to confusion and potential errors. According to the Uber Go Style Guide, it's recommended to avoid shadowing variables.

Consider removing the named return parameters or renaming them to prevent shadowing.

Apply this diff:

-err = k.Distributions.Walk(ctx, nil, func(key time.Time, value types.DistributionAmount) (stop bool, err error) {
+err = k.Distributions.Walk(ctx, nil, func(key time.Time, value types.DistributionAmount) (stop bool, walkErr error) {

Since the err variable is not used inside the function body, you could also omit the named return parameter:

-err = k.Distributions.Walk(ctx, nil, func(key time.Time, value types.DistributionAmount) (stop bool, err error) {
+err = k.Distributions.Walk(ctx, nil, func(key time.Time, value types.DistributionAmount) (bool, error) {

This avoids shadowing the outer err variable and improves code clarity.

x/protocolpool/keeper/keeper.go (1)

153-154: Address the TODO comment regarding allowed denominations

There is a TODO comment indicating the need to handle cases where the balance does not contain any of the allowed denominations. Please implement this logic to ensure proper functioning and prevent potential issues with unsupported denominations.

Would you like assistance in implementing this check? I can help draft the necessary code or open a GitHub issue to track this task.

x/protocolpool/keeper/msg_server_test.go (2)

486-488: Redundant Setting of Zero Distribution Amounts

In lines 486-488, both RecipientFundDistribution and Distributions are set to sdk.NewCoins(), which represents an empty coin set. Since these are default zero values, consider removing these explicit initializations to reduce redundancy.


Line range hint 832-847: Optimize Redundant Initializations in Test Setup

In lines 832-847, RecipientFundDistribution is set to sdk.NewCoins() for multiple recipients during test setup. Since the distributions default to empty, these explicit initializations might be unnecessary. Removing them could simplify the test setup.

api/cosmos/protocolpool/v1/types.pulsar.go (1)

1370-1370: Avoid leading underscores and underscores in type names; prefer CamelCase.

The type _DistributionAmount_1_list begins with an underscore and uses underscores in its name, which goes against Go naming conventions. According to the Uber Go Style Guide, underscores should be avoided in names. Consider renaming the type to distributionAmountList or DistributionAmountList.

Apply this diff to rename the type:

-type _DistributionAmount_1_list struct {
+type distributionAmountList struct {
     // fields...
 }

Ensure all references to this type are updated accordingly.

api/cosmos/protocolpool/v1/tx.pulsar.go (2)

7467-7469: Fix the indentation of the withdrawn_allocated_fund field.

The withdrawn_allocated_fund field is not properly indented. It should be aligned with the other fields in the MsgCancelContinuousFundResponse message.

Apply this diff to fix the indentation:

-    WithdrawnAllocatedFund []*v1beta1.Coin `protobuf:"bytes,4,rep,name=withdrawn_allocated_fund,json=withdrawnAllocatedFund,proto3" json:"withdrawn_allocated_fund,omitempty"`
+	WithdrawnAllocatedFund []*v1beta1.Coin `protobuf:"bytes,4,rep,name=withdrawn_allocated_fund,json=withdrawnAllocatedFund,proto3" json:"withdrawn_allocated_fund,omitempty"`

7561-7563: Fix the indentation of the amount field.

The amount field is not properly indented. It should be aligned with the other fields in the MsgWithdrawContinuousFundResponse message.

Apply this diff to fix the indentation:

-    Amount []*v1beta1.Coin `protobuf:"bytes,1,rep,name=amount,proto3" json:"amount,omitempty"`
+	Amount []*v1beta1.Coin `protobuf:"bytes,1,rep,name=amount,proto3" json:"amount,omitempty"`
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 3856e77 and 03b6445.

🔇 Files ignored due to path filters (3)
  • x/protocolpool/types/genesis.pb.go is excluded by !**/*.pb.go
  • x/protocolpool/types/tx.pb.go is excluded by !**/*.pb.go
  • x/protocolpool/types/types.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (16)
  • api/cosmos/protocolpool/v1/genesis.pulsar.go (32 hunks)
  • api/cosmos/protocolpool/v1/tx.pulsar.go (26 hunks)
  • api/cosmos/protocolpool/v1/types.pulsar.go (6 hunks)
  • x/protocolpool/depinject.go (1 hunks)
  • x/protocolpool/keeper/genesis.go (2 hunks)
  • x/protocolpool/keeper/genesis_test.go (2 hunks)
  • x/protocolpool/keeper/keeper.go (10 hunks)
  • x/protocolpool/keeper/keeper_test.go (4 hunks)
  • x/protocolpool/keeper/msg_server.go (1 hunks)
  • x/protocolpool/keeper/msg_server_test.go (18 hunks)
  • x/protocolpool/proto/cosmos/protocolpool/v1/genesis.proto (2 hunks)
  • x/protocolpool/proto/cosmos/protocolpool/v1/tx.proto (2 hunks)
  • x/protocolpool/proto/cosmos/protocolpool/v1/types.proto (2 hunks)
  • x/protocolpool/testutil/expected_keepers_mocks.go (0 hunks)
  • x/protocolpool/types/expected_keepers.go (0 hunks)
  • x/protocolpool/types/genesis.go (1 hunks)
💤 Files not reviewed due to no reviewable changes (2)
  • x/protocolpool/testutil/expected_keepers_mocks.go
  • x/protocolpool/types/expected_keepers.go
🧰 Additional context used
📓 Path-based instructions (11)
api/cosmos/protocolpool/v1/genesis.pulsar.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

api/cosmos/protocolpool/v1/tx.pulsar.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

api/cosmos/protocolpool/v1/types.pulsar.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/depinject.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/genesis.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/genesis_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

x/protocolpool/keeper/keeper.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/keeper_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

x/protocolpool/keeper/msg_server.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/msg_server_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

x/protocolpool/types/genesis.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

📓 Learnings (1)
x/protocolpool/keeper/genesis.go (1)
Learnt from: likhita-809
PR: cosmos/cosmos-sdk#18471
File: x/protocolpool/keeper/genesis.go:12-51
Timestamp: 2023-11-22T12:32:39.368Z
Learning: - The user `likhita-809` has confirmed the changes suggested in the previous interaction.
- The file in question is `x/protocolpool/keeper/genesis.go` from a Cosmos SDK module.
- The changes involve optimizing the `InitGenesis` function by removing redundant code and ensuring proper handling of start times for budget proposals.
🔇 Additional comments not posted (64)
x/protocolpool/keeper/genesis_test.go (1)

Line range hint 1-52: Overall, the changes effectively test the new multi-coin functionality.

The updates to TestInitGenesis align well with the PR objective of allowing any coins in continuous funds. The test now uses DistributionAmount with sdk.NewCoins for both Distributions and LastBalance, which provides more flexibility in representing different coin types.

The test scenario effectively checks the case where the total to be distributed is greater than the last balance, and the assertion has been updated to check the specific coin amount in the new structure.

These changes ensure that the genesis functionality is properly tested with the new multi-coin support.

x/protocolpool/types/genesis.go (2)

9-10: LGTM: Import changes are appropriate and well-structured.

The addition of the SDK types import is consistent with the changes in the NewGenesisState function. The import statement follows the Uber Golang style guide recommendations for import grouping and aliasing.


17-17: LGTM: LastBalance initialization updated correctly, but verify impact.

The change from math.ZeroInt() to DistributionAmount{Amount: sdk.NewCoins()} for LastBalance initialization is correct and aligns with the PR objectives of allowing any coins in continuous funds. This modification reflects the transition from a simple integer to a more flexible coin-based structure.

To ensure this change doesn't introduce any issues, please run the following verification:

This will help identify any other parts of the codebase that might need to be updated to accommodate this change.

x/protocolpool/proto/cosmos/protocolpool/v1/types.proto (2)

11-11: LGTM: Import statement for Amino codec added.

The addition of the Amino import is appropriate for maintaining backwards compatibility in the Cosmos SDK ecosystem. This import will allow the use of Amino-specific annotations in the protocol definitions.


Line range hint 14-54: Verify integration of DistributionAmount with existing messages.

While the new DistributionAmount message allows for multiple coin types, the existing Budget and ContinuousFund messages still use single-coin fields (e.g., claimed_amount, budget_per_tranche). This might lead to inconsistencies in how funds are handled across different parts of the protocol.

Please review and confirm:

  1. Whether Budget and ContinuousFund messages should be updated to use DistributionAmount for consistency.
  2. How DistributionAmount will be integrated with existing functionality.

To assist in this verification, you can run the following script to check for potential inconsistencies:

This script will help identify areas where the new DistributionAmount might need to be integrated or where existing single-coin usage might need to be reviewed.

x/protocolpool/depinject.go (1)

61-61: LGTM. Verify impact on dependent modules.

The removal of StakingKeeper from the NewKeeper function call aligns with the changes in the ModuleInputs struct. This modification appears intentional and consistent with the module's new design.

However, this is a breaking change that may affect other parts of the system relying on the old Keeper structure.

To ensure this change doesn't introduce unintended side effects, please run the following script to check for any remaining references to StakingKeeper in the protocolpool module:

Additionally, verify that all dependent modules have been updated to accommodate this change in the Keeper structure.

✅ Verification successful

Change Verified: No remaining references to StakingKeeper in x/protocolpool.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for remaining references to StakingKeeper in the protocolpool module

# Test: Search for StakingKeeper references in the protocolpool module
rg --type go 'StakingKeeper' x/protocolpool

Length of output: 43


Script:

#!/bin/bash
# Description: Search the entire codebase for references to StakingKeeper

rg --type go 'StakingKeeper'

Length of output: 43919

x/protocolpool/proto/cosmos/protocolpool/v1/tx.proto (3)

158-160: Approved: Enhanced flexibility for withdrawn funds

The change from a single coin to a repeated field of coins for withdrawn_allocated_fund aligns well with the PR objective. This modification allows for multiple types of coins to be withdrawn when canceling a continuous fund, increasing the flexibility of the protocol.

Note that this is a breaking change, as mentioned in the PR title, and will require updates to any code interacting with this message.


172-174: Approved: Multi-coin support for withdrawals

The modification of the amount field to a repeated field of coins in MsgWithdrawContinuousFundResponse is consistent with the PR's goal. This change enables the withdrawal of multiple types of coins from a continuous fund, enhancing the protocol's flexibility.

As with the previous change, this is a breaking change that will require updates to dependent code.


Line range hint 1-176: Verify related code updates

The changes in this file successfully implement multi-coin support for continuous funds in both cancellation and withdrawal operations. These modifications align well with the PR objectives and are correctly implemented in the Protocol Buffers definitions.

However, as these are breaking changes, it's crucial to ensure that:

  1. The corresponding Go code generated from these Proto definitions is updated accordingly.
  2. All parts of the codebase that interact with MsgCancelContinuousFundResponse and MsgWithdrawContinuousFundResponse are updated to handle multiple coins.
  3. Tests are updated or added to cover these new multi-coin scenarios.
  4. Documentation is updated to reflect these changes.

To verify the impact of these changes, you can run the following script:

This script will help identify areas of the codebase that might need to be updated in light of these changes.

x/protocolpool/keeper/keeper_test.go (3)

38-42: LGTM: Removal of stakingKeeper field

The removal of the stakingKeeper field from the KeeperTestSuite struct is consistent with the changes described in the AI summary. This modification streamlines the test suite by removing unnecessary dependencies.


Line range hint 231-235: LGTM: Consistent type update in TestSetToDistribute

The change to use types.DistributionAmount in the Walk function is consistent with the previous modifications. The test logic remains valid and continues to provide good coverage.


Line range hint 1-238: Overall assessment: Changes are well-implemented and sufficiently tested

The modifications in this file consistently reflect the transition from using math.Int to types.DistributionAmount for handling distribution amounts. The test coverage has been appropriately updated to accommodate these changes, and the overall structure of the tests remains sound.

Key points:

  1. Removal of stakingKeeper dependency aligns with the PR objectives.
  2. Test logic has been correctly updated to work with the new DistributionAmount type.
  3. Existing test coverage appears sufficient for the changes made.

Suggestions for improvement:

  1. Consider adding test cases that exercise DistributionAmount with multiple coins to ensure comprehensive coverage of the new type's capabilities.

The changes adhere to Golang style guidelines and maintain the overall quality of the test suite.

x/protocolpool/keeper/keeper.go (16)

24-25: LGTM!

The definitions of authKeeper and bankKeeper in the Keeper struct are appropriate and follow standard conventions.


36-38: LGTM!

The addition of RecipientFundDistribution, Distributions, and LastBalance fields to the Keeper struct is correctly implemented, and their types are appropriately defined using the collections package.


70-72: LGTM!

The initialization of the new collections maps and items in the NewKeeper function aligns with the existing code patterns and is correctly implemented.


165-168: LGTM!

The calculation of amountToDistribute using SafeSub and the handling of potential negative results are correctly implemented.


183-188: LGTM!

The logic for transferring funds to the community pool when there are no continuous funds, and resetting LastBalance, is correctly implemented.


194-194: LGTM!

Recording the distribution amount with the current block time is appropriate and correctly implemented.


199-199: LGTM!

Updating LastBalance with the current balance ensures accurate tracking for future distributions.


221-223: LGTM!

Initialization of variables toDistribute, poolFunds, and fullAmountToDistribute is properly set up for subsequent calculations.


225-225: LGTM!

Iterating over k.Distributions to calculate allocations is correctly implemented.


266-266: LGTM!

Resetting LastBalance after clearing distributions ensures consistent state for future calculations.


271-271: LGTM!

Transferring streamAmt to the stream account is correctly handled.


279-279: LGTM!

Transferring poolFunds to the community pool is appropriately implemented.


301-301: LGTM!

Initializing toClaim with zero coins for new recipients is correct.


307-308: LGTM!

Updating the recipient's claimable amount in RecipientFundDistribution is correctly implemented.


115-135: Verify callers handle new return type of withdrawRecipientFunds

The withdrawRecipientFunds function now returns sdk.Coins instead of sdk.Coin. Ensure that all callers of this function have been updated to handle the new return type to avoid potential runtime errors.

Run the following script to find all usages of withdrawRecipientFunds and check for proper handling:

#!/bin/bash
# Description: Find all calls to `withdrawRecipientFunds` and verify they handle `sdk.Coins`.

# Test: Search for function calls to `withdrawRecipientFunds`. Expect: Callers expect `sdk.Coins`.
rg --type go 'withdrawRecipientFunds\(' -A 5

45-45: Verify that stakingKeeper is no longer used in the codebase

The stakingKeeper parameter has been removed from the NewKeeper function signature. Ensure that all references to stakingKeeper have been removed throughout the codebase to prevent any undefined references or build errors.

Run the following script to confirm that stakingKeeper is not referenced elsewhere:

x/protocolpool/keeper/msg_server_test.go (5)

398-398: Correct Update to withdrawnAmount Type

The variable withdrawnAmount has been appropriately updated from sdk.Coin to sdk.Coins to handle multiple coin types, aligning with the new data structures introduced in the codebase.


Line range hint 426-442: Consistent Initialization of RecipientFundDistribution

The initialization of RecipientFundDistribution with sdk.NewCoins() ensures that the distribution amounts are correctly represented as empty coin sets for multiple coin types. This change maintains consistency across the codebase.


628-631: Ensure Accurate Assertions After Multiple Withdrawals

At lines 628-631, assertions are made on toClaim.Amount for recipient2 and recipient3. Verify that these assertions correctly reflect the expected state after withdrawals, and ensure that funds are accurately distributed among all recipients.


991-1007: Correct Handling of Expired Continuous Funds

In the TestWithdrawExpiredFunds function (lines 991-1007), the logic correctly prevents withdrawal of expired funds and handles cancellations without errors. The test accurately verifies that repeated cancellations do not result in errors or unintended fund distribution.


508-508: Confirm Necessity of Empty Expiry in Test Case

In line 508, the test case sets an empty expiry for the continuous fund. Verify whether an empty expiry is acceptable in the business logic and that it does not introduce unintended behavior.

Run the following script to search for uses of continuous funds without expiry:

api/cosmos/protocolpool/v1/genesis.pulsar.go (25)

265-266: Handling of LastBalance in Range method is appropriate

The check for x.LastBalance != nil and subsequent processing ensures that the LastBalance field is correctly included during iteration. This follows standard practice and is compliant with the Uber Go Style Guide.


297-297: Correct implementation of Has method for LastBalance

The Has method accurately checks the presence of LastBalance by verifying if it is not nil. This is the appropriate way to handle optional fields in Go.


321-321: Proper clearing of LastBalance in Clear method

Setting x.LastBalance = nil correctly clears the field, ensuring that subsequent calls recognize it as unset. This adheres to best practices for managing optional fields.


354-354: Accurate retrieval of LastBalance in Get method

The Get method correctly retrieves the LastBalance field by returning its proto message representation. This implementation is standard and effective.


390-390: Type assertion in Set method is safe and appropriate

Assigning x.LastBalance after asserting the value's type to *DistributionAmount is appropriate here, assuming correct usage of the API. There is no immediate risk of a type assertion panic in this context.


427-431: Correct initialization of LastBalance in Mutable method

The method ensures that LastBalance is initialized when nil, which prevents potential nil pointer dereferences when accessing it later. Returning the proto message reflects standard practice.


458-459: Proper creation of new DistributionAmount in NewField

The creation of a new DistributionAmount instance and returning its proto message is correct and follows the expected pattern for this method.


544-545: Efficient size calculation of LastBalance in ProtoMethods

The Size function accurately includes the size of LastBalance when it is not nil. This contributes to correct serialization behavior.


599-609: Correct marshaling of LastBalance

The code properly marshals LastBalance when it is not nil, handling errors appropriately. The implementation aligns with the standard serialization process.


Line range hint 766-796: Accurate unmarshaling of LastBalance

During unmarshaling, the code correctly initializes LastBalance if it's nil and unmarshals data into it. Error handling is properly managed, ensuring robustness.


870-870: Initialization of fd_Distribution_amount is correct

The field descriptor for amount in the Distribution message is properly declared and initialized, which is essential for reflection operations.

Also applies to: 877-877


951-956: Appropriate handling of Amount in Range method of Distribution

The method correctly checks if x.Amount is not nil and processes it accordingly during iteration. This conforms to best practices.


974-975: Correct implementation of Has method for Amount

The Has method properly determines the presence of the Amount field by checking for nil, which is appropriate for optional fields.


994-995: Proper clearing of Amount in Clear method

Setting x.Amount = nil effectively clears the Amount field, ensuring it's unset in subsequent operations.


1040-1041: Safe type assertion in Set method for Amount

The assignment to x.Amount with type assertion to *DistributionAmount is appropriate and assumes correct usage of proto reflection.


1068-1071: Proper initialization of Amount in Mutable method

Ensuring x.Amount is initialized when nil prevents nil pointer exceptions and is a correct approach in the Mutable method.


1088-1090: Correct instantiation in NewField method

Creating a new DistributionAmount instance and returning its proto message aligns with standard implementation for creating new fields.


1164-1167: Accurate size calculation of Amount

Including the size of x.Amount in the total size when not nil is essential for accurate serialization.


1197-1198: Proper marshaling of Amount

The code marshals x.Amount correctly when it is present, handling potential errors suitably.


1211-1223: Correct marshaling of Time in Distribution

Marshaling of x.Time is handled appropriately, ensuring that the timestamp is correctly serialized.


Line range hint 1274-1342: Robust unmarshaling logic in Distribution

The unmarshaling code properly handles both Time and Amount fields, initializing them when necessary and managing errors effectively.


1406-1406: Definition of LastBalance field is appropriate

Changing LastBalance to be of type *DistributionAmount allows for richer data representation and aligns with the intended functionality.


1447-1451: Correct implementation of GetLastBalance method

The getter method accurately returns x.LastBalance and handles the case where x is nil, ensuring reliability.


1466-1467: Proper definition of Time and Amount fields in Distribution

Defining Time and Amount as pointers allows for optional fields and aligns with protobuf conventions.


1490-1499: Correct getter methods for Distribution fields

The GetTime and GetAmount methods correctly return their respective fields, handling nil cases appropriately.

api/cosmos/protocolpool/v1/tx.pulsar.go (6)

5511-5515: Verify the cardinality of withdrawn_allocated_fund.

The withdrawn_allocated_fund field is defined as a repeated field. Ensure that it is semantically correct for this field to contain multiple coins. If it should only hold a single coin amount, consider changing it to a non-repeated field.


Line range hint 7511-7515: Verify the cardinality of withdrawn_allocated_fund.

Similar to the previous comment, ensure that the withdrawn_allocated_fund field should indeed be a repeated field semantically. If it should only hold a single coin amount, change it to a non-repeated field.


Line range hint 7584-7588: Verify the cardinality of amount.

The amount field is defined as a repeated field. Ensure that it is semantically correct for this field to contain multiple coins. If it should only hold a single coin amount, consider changing it to a non-repeated field.


7728-7730: Fix the indentation of the withdrawn_allocated_fund field.

The withdrawn_allocated_fund field is not properly indented. It should be aligned with the other fields in the MsgCancelContinuousFundResponse message.

Apply this diff to fix the indentation:

-        WithdrawnAllocatedFund []*v1beta1.Coin `protobuf:"bytes,4,rep,name=withdrawn_allocated_fund,json=withdrawnAllocatedFund,proto3" json:"withdrawn_allocated_fund,omitempty"`
+	WithdrawnAllocatedFund []*v1beta1.Coin `protobuf:"bytes,4,rep,name=withdrawn_allocated_fund,json=withdrawnAllocatedFund,proto3" json:"withdrawn_allocated_fund,omitempty"`

7746-7748: Fix the indentation of the amount field.

The amount field is not properly indented. It should be aligned with the other fields in the MsgWithdrawContinuousFundResponse message.

Apply this diff to fix the indentation:

-        Amount []*v1beta1.Coin `protobuf:"bytes,1,rep,name=amount,proto3" json:"amount,omitempty"`
+	Amount []*v1beta1.Coin `protobuf:"bytes,1,rep,name=amount,proto3" json:"amount,omitempty"`

6465-6514: 🛠️ Refactor suggestion

Refactor the internal list type into a reusable utility.

Similar to the previous comment, consider extracting the _MsgWithdrawContinuousFundResponse_1_list type and its methods into a reusable utility type to improve code modularity and reduce duplication.

(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
google.protobuf.Timestamp time = 1 [(gogoproto.stdtime) = true];
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Altering field numbers in Protobuf messages breaks compatibility

Changing the field number of time from 6 to 1 in the Distribution message can result in data corruption or parsing errors. Field numbers in Protobuf are used to identify fields in the binary format, and modifying them disrupts compatibility with existing data and clients that use the previous numbering.

Instead of renumbering existing fields, add new fields with new field numbers, and, if necessary, deprecate the old fields to maintain backward compatibility.

Comment on lines 68 to 70
if data.LastBalance.Amount.IsAnyGT(totalToBeDistributed) || !totalToBeDistributed.DenomsSubsetOf(data.LastBalance.Amount) {
return errors.New("total to be distributed is greater than the last balance" + fmt.Sprint(data.LastBalance.Amount, totalToBeDistributed))
}
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 26, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix the logical inconsistency in the condition and error message

There's a mismatch between the condition being checked and the error message returned. The condition data.LastBalance.Amount.IsAnyGT(totalToBeDistributed) checks if the last balance amount is greater than the total to be distributed. However, the error message states "total to be distributed is greater than the last balance," which implies the opposite.

To correct this, the condition should check if totalToBeDistributed.IsAnyGT(data.LastBalance.Amount) instead.

Apply this diff to fix the condition:

-if data.LastBalance.Amount.IsAnyGT(totalToBeDistributed) || !totalToBeDistributed.DenomsSubsetOf(data.LastBalance.Amount) {
+if totalToBeDistributed.IsAnyGT(data.LastBalance.Amount) || !totalToBeDistributed.DenomsSubsetOf(data.LastBalance.Amount) {
    return errors.New("total to be distributed is greater than the last balance" + fmt.Sprint(data.LastBalance.Amount, totalToBeDistributed))
}

This change ensures that the error is returned when the total to be distributed exceeds the last balance, aligning the condition with the error message.

📝 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
if data.LastBalance.Amount.IsAnyGT(totalToBeDistributed) || !totalToBeDistributed.DenomsSubsetOf(data.LastBalance.Amount) {
return errors.New("total to be distributed is greater than the last balance" + fmt.Sprint(data.LastBalance.Amount, totalToBeDistributed))
}
if totalToBeDistributed.IsAnyGT(data.LastBalance.Amount) || !totalToBeDistributed.DenomsSubsetOf(data.LastBalance.Amount) {
return errors.New("total to be distributed is greater than the last balance" + fmt.Sprint(data.LastBalance.Amount, totalToBeDistributed))
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm confused a bit about the 1st condition, should return an error when totalToBeDistributed > lastBalance?

Copy link
Contributor

Choose a reason for hiding this comment

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

@hieuvubk, you're correct. The error should be returned when totalToBeDistributed is greater than data.LastBalance.Amount. Currently, the condition:

if data.LastBalance.Amount.IsAnyGT(totalToBeDistributed) || !totalToBeDistributed.DenomsSubsetOf(data.LastBalance.Amount) {
    return errors.New("total to be distributed is greater than the last balance" + fmt.Sprint(data.LastBalance.Amount, totalToBeDistributed))
}

checks if data.LastBalance.Amount is greater than totalToBeDistributed, which is the opposite of the intended logic based on the error message.

To fix this inconsistency, the condition should be:

if totalToBeDistributed.IsAnyGT(data.LastBalance.Amount) || !totalToBeDistributed.DenomsSubsetOf(data.LastBalance.Amount) {
    return errors.New("total to be distributed is greater than the last balance" + fmt.Sprint(data.LastBalance.Amount, totalToBeDistributed))
}

This change ensures that an error is returned when totalToBeDistributed exceeds data.LastBalance.Amount, aligning the condition with the error message and the expected behavior.

/_/\
( •.• )

🚀<
A curious rabbit pondering over the code!

Copy link
Contributor

Choose a reason for hiding this comment

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

Why not simply go with fmt.Errorf instead which is typically used in these scenarios? For example:

fmt.Errorf("an amount to be distributed is greater than the last balance: %s > %s", totalToBeDistributed, data.LastBalance.Amount))

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Member Author

Choose a reason for hiding this comment

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

This was actually for testing, but I think it can be useful if we ever encounter this, I'll modify it.

Comment on lines 239 to 242
for _, denom := range amount.Amount.Denoms() {
am := sdk.NewCoin(denom, f.Percentage.MulInt(amount.Amount.AmountOf(denom)).TruncateInt())
toDistribute[f.Recipient] = toDistribute[f.Recipient].Add(am)
fullAmountToDistribute = fullAmountToDistribute.Add(am)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Review the use of TruncateInt() in distribution calculations

When calculating each recipient's share, TruncateInt() is used after multiplying by the percentage. This could lead to loss of fractional amounts. Consider whether this aligns with the expected financial logic, or if using RoundInt() would be more appropriate to minimize discrepancies.

@@ -595,7 +595,7 @@ func (suite *KeeperTestSuite) TestWithdrawContinuousFund() {
},
recipientAddress: []sdk.AccAddress{recipient, recipient2, recipient3},
expErr: false,
withdrawnAmount: sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(30000)),
withdrawnAmount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(30000))),
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent Handling of Multiple Recipient Addresses

In the test case starting at line 598, recipientAddress is a slice containing multiple addresses, but MsgWithdrawContinuousFund accepts a single RecipientAddress. This could lead to confusion or logic errors. Consider adjusting the test to process each recipient individually or modify the message to handle multiple recipients if intended.

suite.Require().NoError(err)
suite.mockStreamFunds(math.NewInt(0))
},
recipientAddress: []sdk.AccAddress{recipient},
expErr: false,
withdrawnAmount: sdk.NewCoin(sdk.DefaultBondDenom, math.ZeroInt()),
withdrawnAmount: nil,
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Clarify Representation of Zero withdrawnAmount

The withdrawnAmount is set to nil on line 494. To maintain consistency and clarity, consider using sdk.NewCoins() to represent zero amounts instead of nil.

Apply this diff to standardize the representation:

-   withdrawnAmount:  nil,
+   withdrawnAmount:  sdk.NewCoins(),
📝 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
withdrawnAmount: nil,
withdrawnAmount: sdk.NewCoins(),

Comment on lines +1370 to +1372
type _DistributionAmount_1_list struct {
list *[]*v1beta1.Coin
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid using pointers to slices; slices are reference types in Go.

In the struct _DistributionAmount_1_list, the field list is declared as *[]*v1beta1.Coin. Since slices in Go are reference types, using a pointer to a slice is unnecessary and adds complexity. Consider changing the field to use a slice directly.

Apply this diff to simplify the struct definition:

 type _DistributionAmount_1_list struct {
-    list *[]*v1beta1.Coin
+    list []*v1beta1.Coin
 }

Adjust the methods accordingly to reflect this change.

📝 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 _DistributionAmount_1_list struct {
list *[]*v1beta1.Coin
}
type _DistributionAmount_1_list struct {
list []*v1beta1.Coin
}

Comment on lines +1606 to +1613
value := &_DistributionAmount_1_list{list: &x.Amount}
return protoreflect.ValueOfList(value)
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.protocolpool.v1.DistributionAmount"))
}
panic(fmt.Errorf("message cosmos.protocolpool.v1.DistributionAmount does not contain field %s", fd.FullName()))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid using panic for error handling; return errors instead.

Using panic in the Mutable method for handling invalid field descriptors is discouraged. Panics can cause unexpected crashes and are harder to recover from. Instead, modify the method to return an error or handle the situation gracefully without panicking.

Consider refactoring the code as follows:

 func (x *fastReflection_DistributionAmount) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
     switch fd.FullName() {
     case "cosmos.protocolpool.v1.DistributionAmount.amount":
         if x.Amount == nil {
             x.Amount = []*v1beta1.Coin{}
         }
         value := &_DistributionAmount_1_list{list: &x.Amount}
         return protoreflect.ValueOfList(value)
     default:
         if fd.IsExtension() {
-            panic(fmt.Errorf("proto3 declared messages do not support extensions: %s", fd.FullName()))
+            // Handle the error appropriately without panicking
+            return protoreflect.Value{}
         }
-        panic(fmt.Errorf("message cosmos.protocolpool.v1.DistributionAmount does not contain field %s", fd.FullName()))
+        // Handle the error appropriately without panicking
+        return protoreflect.Value{}
     }
 }

Adjust the method's return type and callers as necessary to handle the absence of a valid value.

Committable suggestion was skipped due to low confidence.

Comment on lines +5360 to +5409
var _ protoreflect.List = (*_MsgCancelContinuousFundResponse_4_list)(nil)

type _MsgCancelContinuousFundResponse_4_list struct {
list *[]*v1beta1.Coin
}

func (x *_MsgCancelContinuousFundResponse_4_list) Len() int {
if x.list == nil {
return 0
}
return len(*x.list)
}

func (x *_MsgCancelContinuousFundResponse_4_list) Get(i int) protoreflect.Value {
return protoreflect.ValueOfMessage((*x.list)[i].ProtoReflect())
}

func (x *_MsgCancelContinuousFundResponse_4_list) Set(i int, value protoreflect.Value) {
valueUnwrapped := value.Message()
concreteValue := valueUnwrapped.Interface().(*v1beta1.Coin)
(*x.list)[i] = concreteValue
}

func (x *_MsgCancelContinuousFundResponse_4_list) Append(value protoreflect.Value) {
valueUnwrapped := value.Message()
concreteValue := valueUnwrapped.Interface().(*v1beta1.Coin)
*x.list = append(*x.list, concreteValue)
}

func (x *_MsgCancelContinuousFundResponse_4_list) AppendMutable() protoreflect.Value {
v := new(v1beta1.Coin)
*x.list = append(*x.list, v)
return protoreflect.ValueOfMessage(v.ProtoReflect())
}

func (x *_MsgCancelContinuousFundResponse_4_list) Truncate(n int) {
for i := n; i < len(*x.list); i++ {
(*x.list)[i] = nil
}
*x.list = (*x.list)[:n]
}

func (x *_MsgCancelContinuousFundResponse_4_list) NewElement() protoreflect.Value {
v := new(v1beta1.Coin)
return protoreflect.ValueOfMessage(v.ProtoReflect())
}

func (x *_MsgCancelContinuousFundResponse_4_list) IsValid() bool {
return x.list != nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor the internal list type into a reusable utility.

Consider extracting the _MsgCancelContinuousFundResponse_4_list type and its methods into a reusable utility type. This will make the code more modular and reduce duplication if similar list types are needed elsewhere.

Copy link
Contributor

@hieuvubk hieuvubk left a comment

Choose a reason for hiding this comment

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

overall lgtm, one condition in genesis need to check

Comment on lines 68 to 70
if data.LastBalance.Amount.IsAnyGT(totalToBeDistributed) || !totalToBeDistributed.DenomsSubsetOf(data.LastBalance.Amount) {
return errors.New("total to be distributed is greater than the last balance" + fmt.Sprint(data.LastBalance.Amount, totalToBeDistributed))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm confused a bit about the 1st condition, should return an error when totalToBeDistributed > lastBalance?

Copy link
Contributor

@alpe alpe left a comment

Choose a reason for hiding this comment

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

Nice work!
I am not very familiar with the module but I added some comments that may be helpful.
Are you planning to add a migration? That would be very helpful for existing chains.

You also mentioned an accept list to prevent spam. How is this going to be implemented and maintained?


if data.LastBalance.Amount.IsAnyGT(totalToBeDistributed) || !totalToBeDistributed.DenomsSubsetOf(data.LastBalance.Amount) {
Copy link
Contributor

Choose a reason for hiding this comment

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

last balance should always be >= total to be distributed.

Simplest thing would be to flip the check: totalToBeDistributed.IsAnyGT(last balance)
This includes the denoms implicite so that you can drop the DenomsSubsetOf check

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right about the inverted comparison, but I still need DenomsSubsetOf, see:

// IsAnyGT returns true iff for any denom in coins, the denom is present at a
// greater amount in coinsB.
//
// e.g.
// {2A, 3B}.IsAnyGT{A} = true
// {2A, 3B}.IsAnyGT{5C} = false
// {}.IsAnyGT{5C} = false
// {2A, 3B}.IsAnyGT{} = false

This case {}.IsAnyGT{5C} = false shows that if totalToBeDistributed has 1foo but LastBalance contains 1bar, it will be false.

Comment on lines 68 to 70
if data.LastBalance.Amount.IsAnyGT(totalToBeDistributed) || !totalToBeDistributed.DenomsSubsetOf(data.LastBalance.Amount) {
return errors.New("total to be distributed is greater than the last balance" + fmt.Sprint(data.LastBalance.Amount, totalToBeDistributed))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not simply go with fmt.Errorf instead which is typically used in these scenarios? For example:

fmt.Errorf("an amount to be distributed is greater than the last balance: %s > %s", totalToBeDistributed, data.LastBalance.Amount))

remaining := math.LegacyOneDec().Sub(percentageToDistribute).MulInt(amount).RoundInt()
poolFunds = poolFunds.Add(remaining)
for _, denom := range amount.Amount.Denoms() {
remaining := sdk.NewCoin(denom, math.LegacyOneDec().Sub(percentageToDistribute).MulInt(amount.Amount.AmountOf(denom)).TruncateInt())
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar code was used before but is another round down which has a rest that is not distributed.
Better remaining = amount - distributed amount

Copy link
Member Author

Choose a reason for hiding this comment

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

should be fixed now

@julienrbrt julienrbrt added the backport/v0.52.x PR scheduled for inclusion in the v0.52's next stable release label Sep 27, 2024
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: 9

🧹 Outside diff range and nitpick comments (5)
x/protocolpool/keeper/genesis.go (1)

Line range hint 120-125: Wrap error when exporting distributions for better context

Wrapping errors with contextual information enhances debuggability and maintains consistency in error handling.

Apply this diff to wrap the error:

 if err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to export distributions: %w", err)
 }
x/protocolpool/keeper/keeper.go (4)

37-37: Update the field comment for accuracy

The comment for the Distributions field mentions key: time.Time, denom | value: amounts, but the key is time.Time and the value is types.DistributionAmount. Consider updating the comment to accurately reflect the key and value types.


Line range hint 221-316: Refactor IterateAndUpdateFundsDistribution for clarity

The IterateAndUpdateFundsDistribution function is lengthy and handles multiple responsibilities, including collecting continuous funds, calculating distributions, updating recipient distributions, and removing expired funds. Consider refactoring this function into smaller, well-named helper functions to improve readability and maintainability.


194-199: Check for errors when setting distributions

Ensure that the error returned by k.Distributions.Set includes sufficient context. Currently, the error message is:

return fmt.Errorf("error while setting Distributions: %w", err)

Consider providing more details about the key or the amount being set to aid in debugging.


253-253: Duplicate percentage check

The check for percentageToDistribute exceeding 1.0 is performed earlier at line 247. Consider refactoring or removing redundant checks to streamline the code.

📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 6ac84b6 and ba997eb.

📒 Files selected for processing (3)
  • x/protocolpool/keeper/genesis.go (2 hunks)
  • x/protocolpool/keeper/genesis_test.go (2 hunks)
  • x/protocolpool/keeper/keeper.go (10 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
x/protocolpool/keeper/genesis.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/genesis_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

x/protocolpool/keeper/keeper.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

📓 Learnings (1)
x/protocolpool/keeper/genesis.go (2)
Learnt from: likhita-809
PR: cosmos/cosmos-sdk#18471
File: x/protocolpool/keeper/genesis.go:12-51
Timestamp: 2024-10-08T15:31:05.486Z
Learning: - The user `likhita-809` has confirmed the changes suggested in the previous interaction.
- The file in question is `x/protocolpool/keeper/genesis.go` from a Cosmos SDK module.
- The changes involve optimizing the `InitGenesis` function by removing redundant code and ensuring proper handling of start times for budget proposals.
Learnt from: likhita-809
PR: cosmos/cosmos-sdk#18471
File: x/protocolpool/keeper/genesis.go:12-51
Timestamp: 2023-11-22T12:32:39.368Z
Learning: - The user `likhita-809` has confirmed the changes suggested in the previous interaction.
- The file in question is `x/protocolpool/keeper/genesis.go` from a Cosmos SDK module.
- The changes involve optimizing the `InitGenesis` function by removing redundant code and ensuring proper handling of start times for budget proposals.
🔇 Additional comments (4)
x/protocolpool/keeper/genesis.go (2)

57-59: Logic for accumulating total distribution amount is correct

The code correctly initializes totalToBeDistributed with sdk.NewCoins() and aggregates each distribution amount appropriately.


67-69: Validation logic for distribution amounts is accurate

The condition properly checks if totalToBeDistributed exceeds data.LastBalance.Amount or if there are denominations not present in data.LastBalance.Amount. This ensures that the system does not distribute more than what is available.

x/protocolpool/keeper/keeper.go (2)

115-135: Ensure proper handling of multiple coins in withdrawRecipientFunds

The function withdrawRecipientFunds now returns sdk.Coins instead of sdk.Coin, indicating support for multiple coin denominations. Verify that all downstream code and callers of this function properly handle multiple coins to prevent potential issues with coin denomination mismatches.


Line range hint 225-255: Ensure proper distribution when percentageToDistribute sum is less than 1

When the total percentageToDistribute is less than 1.0, the remaining funds are calculated and added to poolFunds. Verify that this logic aligns with the expected financial distribution model, and that all fractions of the funds are accounted for accurately.

Comment on lines +35 to 37
Amount: types.DistributionAmount{Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(100)))},
Time: &time.Time{},
})
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding test cases with multiple denominations

While the test initializes the Distribution with a single coin of denomination "stake", the goal of the PR is to allow any coins in continuous funds. To ensure comprehensive test coverage, please add test cases that include multiple denominations. This will help verify that distributions handle various coin types correctly.

Time: &time.Time{},
})

err := suite.poolKeeper.InitGenesis(suite.ctx, gs)
suite.Require().ErrorContains(err, "total to be distributed is greater than the last balance")

// Set last balance
gs.LastBalance = math.NewInt(1)
gs.LastBalance = types.DistributionAmount{Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(101)))}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extend LastBalance to include multiple denominations in tests

Currently, gs.LastBalance is set using a single coin with denomination "stake". To fully test the new functionality that permits any coins, consider including multiple denominations in LastBalance. This will ensure that the initialization logic handles a variety of coins appropriately.

@@ -49,5 +49,5 @@
suite.Require().NoError(err)
suite.Require().Equal(gs.ContinuousFund, exportedGenState.ContinuousFund)
suite.Require().Equal(gs.Budget, exportedGenState.Budget)
suite.Require().Equal(math.OneInt(), exportedGenState.LastBalance)
suite.Require().Equal(math.NewInt(101), exportedGenState.LastBalance.Amount.AmountOf("stake"))
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance assertions to cover multiple denominations

The assertion on line 52 checks the amount of "stake" in exportedGenState.LastBalance. To validate that ExportGenesis correctly handles multiple coin denominations, please add assertions for other denominations. This will help confirm that the exported state accurately reflects all types of coins in the LastBalance.

Comment on lines +113 to 114
lastBalance, err := k.LastBalance.Get(ctx)
if err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Wrap error when retrieving last balance for better context

When returning errors, it's recommended to wrap them with additional context to aid in debugging and provide clarity.

Apply this diff to wrap the error:

 if err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to get last balance: %w", err)
 }

Committable suggestion was skipped due to low confidence.

}

return nil
}

if err = k.Distributions.Set(ctx, k.HeaderService.HeaderInfo(ctx).Time, amountToDistribute); err != nil {
if err = k.Distributions.Set(ctx, k.HeaderService.HeaderInfo(ctx).Time, types.DistributionAmount{Amount: amountToDistribute}); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Confirm uniqueness of timestamp keys in Distributions

Using k.HeaderService.HeaderInfo(ctx).Time as the key in Distributions.Set may lead to key collisions if multiple distributions occur within the same timestamp granularity. Consider ensuring that the timestamps used as keys are unique or incorporate additional logic to prevent accidental overwrites.

Comment on lines 251 to 255
poolFunds = poolFunds.Add(amount.Amount.Sub(fullAmountToDistribute...)...)
for _, denom := range amount.Amount.Denoms() {
remaining := sdk.NewCoin(denom, math.LegacyOneDec().Sub(percentageToDistribute).MulInt(amount.Amount.AmountOf(denom)).TruncateInt())
poolFunds = poolFunds.Add(remaining)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Review calculation of poolFunds to avoid double-counting

In lines 251 and 254, poolFunds is being adjusted twice:

  • Line 251 subtracts fullAmountToDistribute from amount.Amount and adds the result to poolFunds.
  • Lines 253-255 calculate remaining and add it to poolFunds.

This may result in double-counting the remaining funds. Consider consolidating the calculations to ensure that poolFunds accurately reflects the undistributed amounts without duplication.

poolFunds = poolFunds.Add(remaining)
poolFunds = poolFunds.Add(amount.Amount.Sub(fullAmountToDistribute...)...)
for _, denom := range amount.Amount.Denoms() {
remaining := sdk.NewCoin(denom, math.LegacyOneDec().Sub(percentageToDistribute).MulInt(amount.Amount.AmountOf(denom)).TruncateInt())
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle potential negative values in remaining funds calculation

When calculating remaining:

remaining := sdk.NewCoin(denom, math.LegacyOneDec().Sub(percentageToDistribute).MulInt(amount.Amount.AmountOf(denom)).TruncateInt())

If percentageToDistribute exceeds 1.0, the subtraction could result in a negative value, leading to incorrect coin amounts. Ensure that percentageToDistribute does not exceed 1.0 before performing this calculation.

Comment on lines +165 to +168
amountToDistribute, anyNegative := currentBalance.SafeSub(lastBalance.Amount...)
if anyNegative {
return errors.New("error while calculating the amount to distribute, result can't be negative")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Validate SafeSub operation to prevent unexpected errors

The use of SafeSub may produce unexpected results if lastBalance.Amount contains denominations not present in currentBalance. This could cause anyNegative to be true even if overall balances are positive. Consider aligning denominations before subtraction or handling missing denominations explicitly.

Comment on lines +183 to +188
if err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ProtocolPoolDistrAccount, types.ModuleName, amountToDistribute); err != nil {
return err
}

if !lastBalance.IsZero() { // only reset if the last balance is not zero (so we leave it at zero/nil)
return k.LastBalance.Set(ctx, math.ZeroInt())
if !lastBalance.Amount.IsZero() { // only reset if the last balance is not zero (so we leave it at zero)
return k.LastBalance.Set(ctx, types.DistributionAmount{Amount: sdk.NewCoins()})
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve condition nesting in SetToDistribute

The nested if statements can be simplified to enhance readability:

if !hasContinuousFunds {
    if err := ...; err != nil {
        return err
    }
    if !lastBalance.Amount.IsZero() {
        return k.LastBalance.Set(ctx, types.DistributionAmount{Amount: sdk.NewCoins()})
    }
    return nil
}

Consider flattening the conditions or adding comments to clarify the flow.

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 (6)
x/protocolpool/keeper/keeper.go (6)

45-45: Consistent updates to NewKeeper function

The changes in the NewKeeper function signature and the initialization of collections are consistent with the modifications in the Keeper struct. This ensures proper handling of the new DistributionAmount type.

Consider adding error handling for the collections.NewMap and collections.NewItem calls to improve robustness.

Also applies to: 70-72


115-115: Enhanced flexibility in fund withdrawal

The modifications to withdrawRecipientFunds function, particularly the change to return sdk.Coins, align well with the PR objective of allowing any coins in continuous funds. The error handling has been improved, and the use of DistributionAmount is consistent with earlier changes.

Consider using a custom error type for the "error while distributing funds" case to improve error handling consistency.

Also applies to: 120-122, 125-127, 131-133, 135-135


149-154: Improved multi-denomination support in SetToDistribute

The changes in the SetToDistribute function, particularly the use of sdk.Coins and IsZero(), enhance the support for multiple denominations and align with the PR objective. The error handling has been improved, making the code more robust.

Consider adding a comment explaining the TODO on line 153 to clarify the intended future improvement.

Also applies to: 158-158, 165-168, 183-188, 194-194, 199-199


221-229: Enhanced multi-denomination support in fund distribution

The modifications to the IterateAndUpdateFundsDistribution function significantly improve the handling of multiple denominations, aligning with the PR objective. The introduction of amountToDistribute and totalDistribution provides clearer tracking of distributed amounts.

Consider using sdk.NewCoins() instead of sdk.NewCoins() for initializing empty coin sets to potentially improve performance.

Also applies to: 239-245


264-264: Improved fund distribution logic

The changes in the fund distribution logic, particularly the use of IsZero() and the updated handling of multi-denomination amounts, enhance the function's robustness and align with the PR objective.

Consider adding error handling for the k.LastBalance.Set call on line 264 to improve the overall robustness of the function.

Also applies to: 269-270, 275-277


275-279: Consider explicit handling of potential negative values

While the use of sdk.Coins may prevent negative values, consider adding an explicit check to ensure poolFunds is not negative before sending coins to the module. This would improve the robustness of the function and prevent potential issues if the underlying implementation of sdk.Coins changes.

📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ba997eb and cdd876b.

📒 Files selected for processing (1)
  • x/protocolpool/keeper/keeper.go (10 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
x/protocolpool/keeper/keeper.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

🔇 Additional comments (5)
x/protocolpool/keeper/keeper.go (5)

24-25: Improved flexibility in fund handling

The changes to the Keeper struct, particularly the use of types.DistributionAmount for RecipientFundDistribution, Distributions, and LastBalance, align well with the PR objective of allowing any coins in continuous funds. This modification enhances the module's flexibility in handling various token types.

Also applies to: 36-38


299-299: Consistent handling of multi-denomination amounts

The changes in the handling of toClaim, particularly the initialization with sdk.NewCoins() and the use of the Add method, ensure consistent and correct handling of multi-denomination amounts. This aligns well with the PR objective and improves the overall robustness of the function.

Also applies to: 305-306


275-275: Improved calculation of poolFunds

The calculation of poolFunds has been updated to use totalDistribution.Sub(amountToDistribute...), which addresses the potential double-counting issue highlighted in a previous review. This change improves the accuracy of the fund distribution process.


165-168: Improve handling of mismatched denominations in SafeSub operation

While SafeSub prevents underflow errors, it may still produce unexpected results if lastBalance.Amount contains denominations not present in currentBalance. Consider aligning the denominations of currentBalance and lastBalance.Amount before performing the subtraction, or explicitly handle cases where denominations don't match.


243-243: ⚠️ Potential issue

Reconsider the use of TruncateInt() in distribution calculations

The use of TruncateInt() when calculating each recipient's share could lead to loss of fractional amounts. This may result in discrepancies, especially over time or with large amounts. Consider using RoundInt() instead, or implementing a more precise distribution mechanism that accounts for and redistributes any remaining fractional amounts.

x/protocolpool/keeper/keeper.go Fixed Show resolved Hide resolved
return nil
}

// if the balance does not have any of the allowed denoms, return early // TODO
Copy link
Member

Choose a reason for hiding this comment

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

shall this check be implemented now?

x/protocolpool/keeper/keeper.go Fixed Show resolved Hide resolved
if err != nil {
return err
}

currentBalance := k.bankKeeper.GetAllBalances(ctx, moduleAccount.GetAddress())
Copy link
Member

Choose a reason for hiding this comment

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

I guess we get the usual: WhaT iF tHe modUle aCCounT Has ManY DeNOM?
Which is that case will be relatively valid. Any way we can make the claimer pay for this call?
As this is call in begin block maybe not, but what prevents in a token factory enabled chain, to send to the module accounts 1 millions worthless tokens until it slows the chain.

Unless we make ProtocolPoolDistrAccount a blocked module account, like FeeCollector is.

Copy link
Member Author

Choose a reason for hiding this comment

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

As this is call in begin block maybe not, but what prevents in a token factory enabled chain, to send to the module accounts 1 millions worthless tokens until it slows the chain.

Yeah, I thought the same, realistically it shouldn't be needed but it could make things go wrong in the long run, so I guess I'll add the whitelist 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: 17

🧹 Outside diff range and nitpick comments (12)
x/protocolpool/types/keys.go (1)

34-34: LGTM. Consider adding a comment for clarity.

The addition of ParamsKey is consistent with the existing code structure and naming conventions. It maintains the sequential numbering of prefixes, which is good for readability and maintenance.

Consider adding a brief comment explaining the purpose of ParamsKey, similar to the comments for other constants in this file. This would enhance code documentation and maintainability.

x/protocolpool/types/genesis.go (3)

17-19: LGTM: Changes to GenesisState are appropriate.

The modifications to LastBalance and the addition of Params align with the PR objectives and enhance the flexibility of the protocol pool.

However, consider initializing Params with default values for consistency:

Params: DefaultParams(),

This assumes you have a DefaultParams() function, which is a common pattern in Cosmos SDK modules.


27-29: LGTM: Default Params initialization is appropriate.

The addition of Params with a default EnabledDistributionDenoms of ["stake"] is consistent with typical Cosmos SDK behavior and aligns with the potential implementation of a token whitelist.

Consider making this default value configurable:

Params: NewParams(DefaultEnabledDistributionDenoms),

Where DefaultEnabledDistributionDenoms could be a package-level variable:

var DefaultEnabledDistributionDenoms = []string{"stake"}

This approach would enhance flexibility for different deployments or testing scenarios.


Line range hint 33-85: Consider updating validation functions for new fields.

While the existing validation logic remains valid, it doesn't cover the new Params field or the changed LastBalance type in the GenesisState. Consider adding validation for these:

  1. In ValidateGenesis, add a check for Params:

    if err := gs.Params.Validate(); err != nil {
        return err
    }
  2. Add a Validate method to the Params struct:

    func (p Params) Validate() error {
        if len(p.EnabledDistributionDenoms) == 0 {
            return errors.New("EnabledDistributionDenoms cannot be empty")
        }
        for _, denom := range p.EnabledDistributionDenoms {
            if err := sdk.ValidateDenom(denom); err != nil {
                return err
            }
        }
        return nil
    }
  3. In ValidateGenesis, add a check for LastBalance:

    if err := gs.LastBalance.Validate(); err != nil {
        return err
    }

These additions will ensure the new fields are properly validated during genesis.

Would you like me to implement these changes or create a GitHub issue to track this task?

x/protocolpool/keeper/msg_server.go (1)

228-238: LGTM: Well-structured parameter update method

The new UpdateParams method is a well-structured addition that follows the existing patterns in the file. It correctly validates the authority before updating parameters, which is crucial for maintaining security.

A minor suggestion for improvement:

Consider wrapping the error returned from k.Params.Set() to provide more context:

if err := k.Params.Set(ctx, msg.Params); err != nil {
    return nil, fmt.Errorf("failed to set params: %w", err)
}

This change would make debugging easier by providing more information about where the error occurred.

x/protocolpool/keeper/keeper_test.go (4)

82-86: LGTM: Addition of Params setup in SetupTest

The addition of Params setup in the SetupTest method is a good practice. It ensures that the tests are run with a controlled and known initial configuration.

Consider adding a test case that verifies the behavior with multiple enabled distribution denoms to fully test the new functionality allowing any coins in continuous funds.


124-125: LGTM: Updated TestIterateAndUpdateFundsDistribution

The changes in the TestIterateAndUpdateFundsDistribution method, including the use of GetBalance, single Coin representation, and DistributionAmount, align well with the new functionality. The test logic effectively verifies the correct distribution of funds.

Consider adding test cases with multiple coin types to fully validate the new capability of handling any coins in continuous funds.

Also applies to: 148-155


184-185: LGTM: Updated TestSetToDistribute

The changes in the TestSetToDistribute method, including the use of GetBalance, single Coin representation, and DistributionAmount, are consistent with the new functionality and previous changes. The test effectively verifies the behavior of the SetToDistribute function.

To enhance test coverage:

  1. Consider adding test cases with multiple coin types to validate handling of various tokens.
  2. Add a test case where the balance includes multiple coin denominations to ensure correct handling of the new multi-coin capability.

Also applies to: 188-188, 216-216, 219-220, 225-225, 228-229, 236-236


Line range hint 1-243: Overall: Good updates, consider expanding test coverage

The changes in this test file consistently reflect the new functionality allowing any coins in continuous funds. The updates to use GetBalance instead of GetAllBalances, single Coin representation, and DistributionAmount are appropriate and maintain the integrity of the tests.

To further improve the test suite:

  1. Add test cases that use multiple coin types in continuous funds to fully validate the new multi-coin capability.
  2. Include scenarios where balances and distributions involve multiple coin denominations.
  3. Consider edge cases, such as distributions with very small percentages or with the maximum allowed number of coin types.

These additions would ensure comprehensive coverage of the new functionality and potential edge cases.

x/protocolpool/keeper/keeper.go (3)

Line range hint 24-39: LGTM: Keeper struct updates improve flexibility and decoupling

The changes to the Keeper struct, including the removal of stakingKeeper and the use of types.DistributionAmount, appear to enhance the module's flexibility in handling different coin denominations while reducing dependencies. This is a positive architectural change.

Consider documenting the rationale behind removing the stakingKeeper dependency, as this might impact other parts of the system that previously relied on this connection.


117-137: LGTM with suggestion: Improve error handling in withdrawRecipientFunds

The function has been updated to handle multi-denomination distributions, which is a good improvement. However, there's room for better error handling.

Consider wrapping the error in line 129 with more context:

-		return nil, fmt.Errorf("error while distributing funds: %w", err)
+		return nil, fmt.Errorf("error while distributing funds to recipient %s: %w", recipient, err)

This will provide more detailed information for debugging purposes.


Line range hint 230-317: LGTM with suggestions: IterateAndUpdateFundsDistribution updated for multi-denomination support

The function has been significantly refactored to support multiple denominations in distributions. This increases flexibility but also complexity.

Consider the following improvements:

  1. Extract the distribution calculation logic (lines 251-254) into a separate helper function for better readability and testability.
  2. Add comments explaining the purpose of amountToDistribute and allDistributions variables, as their roles might not be immediately clear.

Example refactoring:

func (k Keeper) calculateDistribution(amount types.DistributionAmount, f types.ContinuousFund) sdk.Coins {
    distribution := sdk.NewCoins()
    for _, denom := range amount.Amount.Denoms() {
        am := sdk.NewCoin(denom, f.Percentage.MulInt(amount.Amount.AmountOf(denom)).TruncateInt())
        distribution = distribution.Add(am)
    }
    return distribution
}

This would simplify the main function and make the distribution calculation logic easier to understand and test.

📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 99235e2 and e2f3fc8.

⛔ Files ignored due to path filters (4)
  • api/cosmos/protocolpool/v1/tx_grpc.pb.go is excluded by !**/*.pb.go
  • x/protocolpool/types/genesis.pb.go is excluded by !**/*.pb.go
  • x/protocolpool/types/tx.pb.go is excluded by !**/*.pb.go
  • x/protocolpool/types/types.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (14)
  • api/cosmos/protocolpool/v1/genesis.pulsar.go (38 hunks)
  • api/cosmos/protocolpool/v1/types.pulsar.go (6 hunks)
  • x/protocolpool/autocli.go (1 hunks)
  • x/protocolpool/keeper/keeper.go (10 hunks)
  • x/protocolpool/keeper/keeper_test.go (7 hunks)
  • x/protocolpool/keeper/msg_server.go (2 hunks)
  • x/protocolpool/keeper/msg_server_test.go (19 hunks)
  • x/protocolpool/proto/cosmos/protocolpool/v1/genesis.proto (1 hunks)
  • x/protocolpool/proto/cosmos/protocolpool/v1/tx.proto (4 hunks)
  • x/protocolpool/proto/cosmos/protocolpool/v1/types.proto (2 hunks)
  • x/protocolpool/testutil/expected_keepers_mocks.go (1 hunks)
  • x/protocolpool/types/expected_keepers.go (1 hunks)
  • x/protocolpool/types/genesis.go (1 hunks)
  • x/protocolpool/types/keys.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
api/cosmos/protocolpool/v1/genesis.pulsar.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

api/cosmos/protocolpool/v1/types.pulsar.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/autocli.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/keeper.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/keeper_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

x/protocolpool/keeper/msg_server.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/msg_server_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

x/protocolpool/testutil/expected_keepers_mocks.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/types/expected_keepers.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/types/genesis.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/types/keys.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

🪛 buf
x/protocolpool/proto/cosmos/protocolpool/v1/tx.proto

6-6: import "cosmos/protocolpool/v1/types.proto": file does not exist

(COMPILE)

🔇 Additional comments (36)
x/protocolpool/types/genesis.go (1)

9-10: LGTM: Import changes are appropriate.

The addition of the sdk import is necessary for the new usage of sdk.NewCoins(). The import follows the Uber Go Style Guide for third-party package aliases.

x/protocolpool/keeper/msg_server.go (2)

160-160: LGTM: Improved flexibility for continuous fund distribution

This change aligns well with the PR objective of allowing any coins in continuous funds. By using types.DistributionAmount{Amount: sdk.NewCoins()} instead of math.ZeroInt(), the implementation now supports multiple coin types, enhancing the flexibility of the protocol pool functionality.


Line range hint 1-268: Overall assessment: Changes align with PR objectives and maintain code quality

The modifications in this file successfully implement the goal of allowing any coins in continuous funds. The new UpdateParams method adds necessary functionality for parameter updates. Both changes maintain the existing code structure and adhere to the Uber Go Style Guide.

Key points:

  1. The CreateContinuousFund method now supports multiple coin types.
  2. The new UpdateParams method provides a secure way to update parameters.

These changes enhance the flexibility and functionality of the protocol pool without compromising code quality or security.

x/protocolpool/keeper/keeper_test.go (3)

38-42: LGTM: Removal of stakingKeeper from KeeperTestSuite

The removal of the stakingKeeper field from the KeeperTestSuite struct is consistent with the changes allowing any coins in continuous funds. This simplification of the test suite structure aligns well with the new functionality.


100-101: LGTM: Updated mockWithdrawContinuousFund method

The changes in the mockWithdrawContinuousFund method, specifically the use of GetBalance instead of GetAllBalances and the representation of balance as a single Coin, align well with the new functionality. This approach is more precise and efficient for testing the withdrawal of continuous funds.


109-110: LGTM: Updated mockStreamFunds method

The changes in the mockStreamFunds method, including the use of GetBalance and the representation of balance as a single Coin, are consistent with the updates in other parts of the test suite. These changes appropriately reflect the new functionality allowing any coins in continuous funds.

x/protocolpool/keeper/keeper.go (7)

Line range hint 46-74: LGTM: NewKeeper function updated consistently

The changes in the NewKeeper function correctly reflect the updates made to the Keeper struct. The removal of the stakingKeeper parameter and the use of types.DistributionAmount in initializations are consistent and appropriate.


Line range hint 331-352: LGTM: claimFunds function remains consistent

The claimFunds function has not undergone significant changes and continues to function as expected within the updated context of the module.


Line range hint 354-411: LGTM: getClaimableFunds function remains consistent

The getClaimableFunds function has not undergone significant changes and continues to operate correctly within the updated module context.


Line range hint 413-460: LGTM: calculateClaimableFunds function remains consistent

The calculateClaimableFunds function has not undergone significant changes and continues to operate correctly within the updated module context.


Line range hint 462-501: LGTM: validateAndUpdateBudgetProposal function remains consistent

The validateAndUpdateBudgetProposal function has not undergone significant changes and continues to operate correctly within the updated module context.


Line range hint 503-523: LGTM: validateContinuousFund function remains consistent

The validateContinuousFund function has not undergone significant changes and continues to operate correctly within the updated module context.


Line range hint 147-208: LGTM with considerations: SetToDistribute function updated with whitelist support

The function has been updated to support whitelisted denominations, which adds flexibility to the system. The balance calculation and distribution logic have been adjusted accordingly.

Consider the following edge cases:

  1. What happens if EnabledDistributionDenoms is empty?
  2. How does the system handle a scenario where a previously whitelisted denomination is removed?

To verify these scenarios, you could run the following script:

This will help identify if these edge cases are handled elsewhere in the codebase.

x/protocolpool/proto/cosmos/protocolpool/v1/genesis.proto (4)

20-20: Note: Previous compatibility concern still applies to 'last_balance' field

Changing the field type of last_balance from string to DistributionAmount may cause backward compatibility issues with existing clients and persisted data that expect a string. This could lead to serialization and deserialization problems.


27-27: Addition of 'params' field to 'GenesisState' is appropriate

The new params field is correctly added with a unique field number 5. This ensures backward compatibility and extends the functionality of the GenesisState message.


31-31: Note: Previous compatibility concern still applies to changing 'time' field number

Altering the field number of time from 6 to 1 in the Distribution message can break backward compatibility. Existing data and clients expect time to be associated with field number 6.


33-33: Note: Previous compatibility concern still applies to 'amount' field

Updating the type of the amount field from string to DistributionAmount may lead to deserialization issues with existing clients and data expecting a string. This can cause runtime errors or data loss when processing distributions.

x/protocolpool/proto/cosmos/protocolpool/v1/types.proto (1)

56-61: Ensure proper initialization and integration of Params message

The new Params message introduces the enabled_distribution_denoms field to whitelist allowed denominations for distribution. Please verify that:

  • The Params struct is properly registered with the parameter store.
  • Default parameter values are set appropriately.
  • Validation logic is implemented to ensure only valid denominations are allowed.
  • Any necessary migrations are handled if existing state is affected.

Run the following script to verify the integration:

x/protocolpool/testutil/expected_keepers_mocks.go (1)

132-145: New GetBalance methods are correctly implemented

The addition of GetBalance methods in both MockBankKeeper and MockBankKeeperMockRecorder correctly mocks the base method and follows the existing pattern used in the generated mock file. The implementation conforms to the Uber Go Style Guide.

x/protocolpool/keeper/msg_server_test.go (1)

398-398: Update withdrawnAmount to handle multiple coins

The withdrawnAmount variable has been updated to sdk.Coins to support multiple coin types, enhancing the flexibility of the withdrawal process. Ensure all references and assertions related to withdrawnAmount are updated accordingly throughout the tests.

api/cosmos/protocolpool/v1/genesis.pulsar.go (14)

267-268: Check for nil before using ProtoReflect()

In the Range method, you correctly check if x.LastBalance is not nil before proceeding. This ensures safe access to its methods.


279-284: Check for nil before using ProtoReflect()

In the Range method for Params, you correctly check if x.Params is not nil before accessing it. This follows safe coding practices.


305-309: Consistent nil checks in Has method

Nil checks for x.Params and x.LastBalance are correctly implemented in the Has method, ensuring the method accurately reports field population.


331-335: Consistent field clearing in Clear method

The Clear method correctly sets x.Params and x.LastBalance to nil, properly clearing the fields.


405-411: Properly setting fields in Set method

The Set method correctly assigns the incoming value to x.Params, ensuring that the Params field is updated appropriately.


444-459: Nil checks before field mutation in Mutable method

In the Mutable method, you properly check if x.Params is nil before instantiating a new Params object. This prevents potential nil pointer dereferences.


480-487: Consistent field initialization in NewField method

The NewField method correctly initializes new instances for LastBalance and Params, ensuring new fields are created properly.


Line range hint 569-582: Including new fields in size calculation

In the size calculation, you correctly include x.Params and x.LastBalance, ensuring accurate computation of the message size.


612-625: Handling Params in marshaling

The Marshal method appropriately handles x.Params, including nil checks and error handling, ensuring that Params is correctly serialized.


642-652: Including LastBalance in marshaling

You correctly marshal x.LastBalance with proper error handling, ensuring it's serialized when present.


1485-1490: Updating struct fields correctly

In the GenesisState struct, you've updated the LastBalance field to use *DistributionAmount and added the Params field. This change enhances the data structure's flexibility.


Line range hint 1527-1547: Getter methods should handle nil cases

In the GetLastBalance() and GetParams() methods, you correctly handle the possibility of nil values by returning nil if the fields are not set.


1553-1554: Correctly updating Distribution struct and getters

The Distribution struct now includes Amount as a pointer to DistributionAmount. The corresponding getter methods handle nil checks appropriately.

Also applies to: 1577-1586


1030-1035: ⚠️ Potential issue

Add nil check before accessing x.Amount

In the Range method for Distribution, ensure that x.Amount is not nil before calling ProtoReflect() to prevent nil pointer dereference.

Apply this diff to include a nil check:

 if x.Amount != nil {
     value := protoreflect.ValueOfMessage(x.Amount.ProtoReflect())
     if !f(fd_Distribution_amount, value) {
         return
     }
+} else {
+    return
 }

Likely invalid or redundant comment.

api/cosmos/protocolpool/v1/types.pulsar.go (2)

1368-1397: LGTM

The implementation of the _DistributionAmount_1_list struct and its methods appears correct and follows Go coding conventions.


2495-2502: LGTM

The DistributionAmount struct is properly defined, and the field Amount is appropriately typed as a slice of *v1beta1.Coin.

Comment on lines +92 to +99
{
RpcMethod: "UpdateParams",
Use: "update-params-proposal <params>",
Short: "Submit a proposal to update protocolpool module params. Note: the entire params must be provided.",
Example: fmt.Sprintf(`%s tx protocolpool update-params-proposal '{ "enabled_distribution_denoms": ["stake", "foo"] }'`, version.AppName),
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}},
GovProposal: true,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance clarity and provide more specific guidance for the UpdateParams command.

The new RPC command for UpdateParams is well-structured and consistent with other commands. However, consider the following improvements:

  1. Enhance readability of the example by splitting it across multiple lines.
  2. Provide more specific information in the short description about what parameters can be updated.
  3. Consider adding a note about parameter validation, if applicable.

Here's a suggested refactor:

 {
 	RpcMethod:      "UpdateParams",
 	Use:            "update-params-proposal <params>",
-	Short:          "Submit a proposal to update protocolpool module params. Note: the entire params must be provided.",
+	Short:          "Submit a proposal to update protocolpool module params (e.g., enabled_distribution_denoms). Note: the entire params must be provided.",
-	Example:        fmt.Sprintf(`%s tx protocolpool update-params-proposal '{ "enabled_distribution_denoms": ["stake", "foo"] }'`, version.AppName),
+	Example: fmt.Sprintf(`%s tx protocolpool update-params-proposal '
+{
+  "enabled_distribution_denoms": ["stake", "foo"]
+}'`, version.AppName),
 	PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}},
 	GovProposal:    true,
 },

Consider adding a note about parameter validation if it's handled elsewhere in the codebase.

📝 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
{
RpcMethod: "UpdateParams",
Use: "update-params-proposal <params>",
Short: "Submit a proposal to update protocolpool module params. Note: the entire params must be provided.",
Example: fmt.Sprintf(`%s tx protocolpool update-params-proposal '{ "enabled_distribution_denoms": ["stake", "foo"] }'`, version.AppName),
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}},
GovProposal: true,
},
{
RpcMethod: "UpdateParams",
Use: "update-params-proposal <params>",
Short: "Submit a proposal to update protocolpool module params (e.g., enabled_distribution_denoms). Note: the entire params must be provided.",
Example: fmt.Sprintf(`%s tx protocolpool update-params-proposal '
{
"enabled_distribution_denoms": ["stake", "foo"]
}'`, version.AppName),
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "params"}},
GovProposal: true,
},

@@ -17,13 +17,10 @@ type AccountKeeper interface {

// BankKeeper defines the expected interface needed to retrieve account balances.
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.

⚠️ Potential issue

Consider removing the 'Get' prefix from the method name.

According to the Uber Go Style Guide, getter methods should avoid using the 'Get' prefix. It's recommended to rename the method GetBalance to Balance for consistency and clarity.

Apply this diff to rename the method:

 type BankKeeper interface {
-	GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin
+	Balance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin
 	GetAllBalances(ctx context.Context, addr sdk.AccAddress) sdk.Coins
 	SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins
 	SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
📝 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
GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin
Balance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin

@@ -8,6 +8,7 @@ import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
import "amino/amino.proto";
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid introducing dependency on deprecated Amino serialization

The import of amino/amino.proto reintroduces a dependency on the legacy Amino serialization format, which is being phased out in favor of Protobuf encoding in the Cosmos SDK. It's recommended to avoid using Amino unless absolutely necessary for backward compatibility.

Comment on lines +46 to +54
// DistributionAmount is used to store the coins of periodic distributions.
message DistributionAmount {
repeated cosmos.base.v1beta1.Coin amount = 1 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(amino.dont_omitempty) = true,
(amino.encoding) = "legacy_coins"
];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Reevaluate usage of deprecated Amino options in DistributionAmount message

The DistributionAmount message includes Amino-specific options such as (amino.dont_omitempty) and (amino.encoding), which depend on the legacy Amino serialization format. Since the Cosmos SDK is moving away from Amino, consider removing these options to avoid dependencies on deprecated technology.

@@ -3,6 +3,7 @@ package cosmos.protocolpool.v1;

option go_package = "cosmossdk.io/x/protocolpool/types";

import "cosmos/protocolpool/v1/types.proto";
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Importing Non-existent 'types.proto' File

The import statement at line 6 references cosmos/protocolpool/v1/types.proto, but this file does not exist in the codebase. This will lead to compilation errors.

🧰 Tools
🪛 buf

6-6: import "cosmos/protocolpool/v1/types.proto": file does not exist

(COMPILE)

@@ -174,6 +174,7 @@ var (
fd_GenesisState_budget protoreflect.FieldDescriptor
fd_GenesisState_last_balance protoreflect.FieldDescriptor
fd_GenesisState_distributions protoreflect.FieldDescriptor
fd_GenesisState_params protoreflect.FieldDescriptor
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ensure field descriptors follow Go naming conventions

The variables fd_GenesisState_params and fd_Distribution_amount use underscores, which is not in line with the Go naming conventions as outlined in the Uber Go Style Guide. Variable names should be in camelCase.

Apply this diff to align with the naming conventions:

- fd_GenesisState_params protoreflect.FieldDescriptor
+ fdGenesisStateParams protoreflect.FieldDescriptor

...

- fd_GenesisState_params = md_GenesisState.Fields().ByName("params")
+ fdGenesisStateParams = md_GenesisState.Fields().ByName("params")

Also applies to: 187-187

Comment on lines +1094 to +1096
case "cosmos.protocolpool.v1.Distribution.amount":
value := x.Amount
return protoreflect.ValueOfMessage(value.ProtoReflect())
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential nil pointer dereference in Get method

Similar to the GenesisState, in the Get method of fastReflection_Distribution, there is no nil check for x.Amount before calling value.ProtoReflect(). This could cause a nil pointer dereference if x.Amount is nil.

Apply this diff to prevent the nil pointer dereference:

 case "cosmos.protocolpool.v1.Distribution.amount":
+    if x.Amount == nil {
+        return protoreflect.Value{}
+    }
     value := x.Amount
     return protoreflect.ValueOfMessage(value.ProtoReflect())
📝 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
case "cosmos.protocolpool.v1.Distribution.amount":
value := x.Amount
return protoreflect.ValueOfMessage(value.ProtoReflect())
case "cosmos.protocolpool.v1.Distribution.amount":
if x.Amount == nil {
return protoreflect.Value{}
}
value := x.Amount
return protoreflect.ValueOfMessage(value.ProtoReflect())

Comment on lines +373 to +375
case "cosmos.protocolpool.v1.GenesisState.params":
value := x.Params
return protoreflect.ValueOfMessage(value.ProtoReflect())
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential nil pointer dereference in Get method

In the Get method of fastReflection_GenesisState, the case for "cosmos.protocolpool.v1.GenesisState.params" does not check if x.Params is nil before calling value.ProtoReflect(). This could result in a nil pointer dereference if x.Params is nil.

Apply this diff to safely handle the nil case:

 case "cosmos.protocolpool.v1.GenesisState.params":
+    if x.Params == nil {
+        return protoreflect.Value{}
+    }
     value := x.Params
     return protoreflect.ValueOfMessage(value.ProtoReflect())
📝 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
case "cosmos.protocolpool.v1.GenesisState.params":
value := x.Params
return protoreflect.ValueOfMessage(value.ProtoReflect())
case "cosmos.protocolpool.v1.GenesisState.params":
if x.Params == nil {
return protoreflect.Value{}
}
value := x.Params
return protoreflect.ValueOfMessage(value.ProtoReflect())

Comment on lines +949 to +956
fd_Distribution_amount protoreflect.FieldDescriptor
)

func init() {
file_cosmos_protocolpool_v1_genesis_proto_init()
md_Distribution = File_cosmos_protocolpool_v1_genesis_proto.Messages().ByName("Distribution")
fd_Distribution_amount = md_Distribution.Fields().ByName("amount")
fd_Distribution_time = md_Distribution.Fields().ByName("time")
fd_Distribution_amount = md_Distribution.Fields().ByName("amount")
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use consistent naming conventions for field descriptors

The variable fd_Distribution_amount should follow Go naming conventions. Consider renaming it to fdDistributionAmount.

Apply this diff for consistency:

- fd_Distribution_amount protoreflect.FieldDescriptor
+ fdDistributionAmount protoreflect.FieldDescriptor

...

- fd_Distribution_amount = md_Distribution.Fields().ByName("amount")
+ fdDistributionAmount = md_Distribution.Fields().ByName("amount")
📝 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
fd_Distribution_amount protoreflect.FieldDescriptor
)
func init() {
file_cosmos_protocolpool_v1_genesis_proto_init()
md_Distribution = File_cosmos_protocolpool_v1_genesis_proto.Messages().ByName("Distribution")
fd_Distribution_amount = md_Distribution.Fields().ByName("amount")
fd_Distribution_time = md_Distribution.Fields().ByName("time")
fd_Distribution_amount = md_Distribution.Fields().ByName("amount")
fdDistributionAmount protoreflect.FieldDescriptor
)
func init() {
file_cosmos_protocolpool_v1_genesis_proto_init()
md_Distribution = File_cosmos_protocolpool_v1_genesis_proto.Messages().ByName("Distribution")
fd_Distribution_time = md_Distribution.Fields().ByName("time")
fdDistributionAmount = md_Distribution.Fields().ByName("amount")

Comment on lines +2537 to +2539
// enabled_distribution_denoms lists the denoms that are allowed to be distributed.
// This is to avoid spending time distributing undesired tokens to continuous funds and budgets.
EnabledDistributionDenoms []string `protobuf:"bytes,1,rep,name=enabled_distribution_denoms,json=enabledDistributionDenoms,proto3" json:"enabled_distribution_denoms,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Update field comments to follow Go documentation conventions

The comments for the EnabledDistributionDenoms field should start with the field name and be full sentences, per the Uber Go Style Guide.

Apply this diff to update the comments:

-    // enabled_distribution_denoms lists the denoms that are allowed to be distributed.
-    // This is to avoid spending time distributing undesired tokens to continuous funds and budgets.
+    // EnabledDistributionDenoms lists the denominations that are allowed to be distributed.
+    // This avoids spending time distributing undesired tokens to continuous funds and budgets.
📝 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
// enabled_distribution_denoms lists the denoms that are allowed to be distributed.
// This is to avoid spending time distributing undesired tokens to continuous funds and budgets.
EnabledDistributionDenoms []string `protobuf:"bytes,1,rep,name=enabled_distribution_denoms,json=enabledDistributionDenoms,proto3" json:"enabled_distribution_denoms,omitempty"`
// EnabledDistributionDenoms lists the denominations that are allowed to be distributed.
// This avoids spending time distributing undesired tokens to continuous funds and budgets.
EnabledDistributionDenoms []string `protobuf:"bytes,1,rep,name=enabled_distribution_denoms,json=enabledDistributionDenoms,proto3" json:"enabled_distribution_denoms,omitempty"`

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: 18

🧹 Outside diff range and nitpick comments (16)
x/protocolpool/types/keys.go (1)

34-34: LGTM. Consider adding a comment for clarity.

The addition of ParamsKey is consistent with the existing code structure and naming conventions. It follows the sequential numbering pattern for prefixes.

For improved clarity, consider adding a brief comment explaining the purpose of ParamsKey, similar to comments provided for other constants in this file.

x/protocolpool/types/genesis.go (3)

17-19: LGTM: GenesisState initialization updated

The changes to LastBalance and the addition of Params align with the PR objective of allowing any coins in continuous funds.

However, consider initializing Params with default values instead of an empty struct for consistency with DefaultGenesisState().

You might want to update line 19 as follows:

Params: DefaultParams(),

This assumes you have a DefaultParams() function defined elsewhere in the package.


27-29: LGTM with suggestions: DefaultGenesisState updated with Params

The addition of Params with EnabledDistributionDenoms aligns with the PR objective of potentially implementing a whitelist of tokens to prevent spam.

Consider the following suggestions:

  1. The default value only includes "stake". Consider if this is sufficiently flexible for different network configurations.
  2. It might be beneficial to define these default values as constants elsewhere in the package for easier maintenance and reusability.

You might want to define a constant for the default enabled denominations:

const DefaultEnabledDenom = "stake"

// In DefaultGenesisState()
Params: &Params{
    EnabledDistributionDenoms: []string{DefaultEnabledDenom},
},

This would make it easier to update the default value in the future if needed.


Update Validation Functions to Include EnabledDistributionDenoms

The validation functions validateBudget and validateContinuousFund do not currently validate the EnabledDistributionDenoms field:

  1. validateBudget: Add validation to ensure that EnabledDistributionDenoms in Params is properly checked.
  2. validateContinuousFund: Implement checks to confirm that the coins used are within the EnabledDistributionDenoms list.

These updates are necessary to ensure that the new EnabledDistributionDenoms functionality is correctly validated during genesis.

🔗 Analysis chain

Line range hint 44-85: Consider updating validation functions

The validation functions validateBudget and validateContinuousFund remain unchanged. Consider updating these functions to accommodate the new changes:

  1. validateBudget: Add validation for the new Params field, particularly the EnabledDistributionDenoms.
  2. validateContinuousFund: Consider adding checks to ensure the coins used are in the EnabledDistributionDenoms list.

These updates would ensure the new functionality is properly validated during genesis.

To assist in identifying areas that might need updating, you can run the following command:

This will help identify if the new field is being used in validation functions across the package.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of EnabledDistributionDenoms in validation functions
rg --type go 'func.*validate.*|EnabledDistributionDenoms' x/protocolpool/types/

Length of output: 1583

x/protocolpool/autocli.go (1)

92-99: Approve with suggestions for improvement

The new UpdateParams command is well-structured and consistent with other commands in the file. However, consider the following improvements:

  1. Enhance the example's readability by using a multi-line string:
Example: fmt.Sprintf(`%s tx protocolpool update-params-proposal '
{
  "enabled_distribution_denoms": ["stake", "foo"]
}'`, version.AppName),
  1. Provide more details about the expected format of the params in the Short description:
Short: "Submit a proposal to update protocolpool module params. Params should be provided as a JSON object containing all module parameters.",

These changes would improve clarity and usability for developers interacting with the CLI.

x/protocolpool/keeper/msg_server.go (1)

228-238: LGTM: New UpdateParams method enhances configurability

The addition of the UpdateParams method is a valuable enhancement, allowing for dynamic updates to the protocol pool parameters. The implementation correctly validates the authority before applying changes.

Consider wrapping the error returned from k.Params.Set() with additional context:

if err := k.Params.Set(ctx, msg.Params); err != nil {
    return nil, fmt.Errorf("failed to set params: %w", err)
}

This would provide more informative error messages for debugging.

x/protocolpool/keeper/keeper_test.go (3)

82-86: LGTM: Initialization of poolKeeper params

The addition of parameter initialization for the poolKeeper is a good practice. It ensures that the keeper starts with known parameters for testing.

Consider extracting the default bond denom into a constant at the package level for easier maintenance and reusability across tests.


148-155: LGTM: Updated Walk function and assertions in TestIterateAndUpdateFundsDistribution

The changes to the Walk function and assertions correctly reflect the update in the data structure used for distribution amounts. The use of types.DistributionAmount and checking the Amount field is consistent with the modifications described in the AI summary.

Consider using s.Assert().Equal() instead of s.Require().Equal() for these assertions, as they don't affect the flow of the test and Assert is generally preferred for non-critical checks in tests.


216-216: LGTM: Updated assertions and Walk function in TestSetToDistribute

The changes to use sdk.Coins instead of math.Int and the update to the Walk function to use types.DistributionAmount are consistent with the overall modifications to the protocol pool's data structures. These changes correctly reflect the new approach to handling distribution amounts.

Consider adding a comment explaining the significance of the DistributionAmount type and its Amount field, as this change represents a significant shift in how distribution amounts are handled.

Also applies to: 219-220, 225-225, 228-229, 236-236

x/protocolpool/keeper/keeper.go (5)

Line range hint 46-74: LGTM: Consistent updates to NewKeeper function

The changes in the NewKeeper function correctly reflect the modifications made to the Keeper struct. The removal of the sk types.StakingKeeper parameter is consistent with the decoupling from staking-related functionality.

One minor suggestion for improvement:

Consider wrapping the panic calls with a custom function that includes the module name, to improve error traceability. For example:

func panicModuleAccountNotSet(accountName string) {
    panic(fmt.Sprintf("%s: %s", types.ModuleName, fmt.Sprintf(errModuleAccountNotSet, accountName)))
}

// Usage
if addr := ak.GetModuleAddress(types.ModuleName); addr == nil {
    panicModuleAccountNotSet(types.ModuleName)
}

This approach would make it easier to identify which module caused the panic in a larger application context.


117-137: LGTM: Improved multi-denomination support in withdrawRecipientFunds

The changes to withdrawRecipientFunds function successfully implement support for multiple coin denominations, aligning with the PR objective. The switch from sdk.Coin to sdk.Coins allows for more flexible fund distribution.

However, there's room for improvement in error handling:

Consider using errors.Join to combine multiple errors when appropriate, and ensure consistent error wrapping. For example:

if err != nil {
    return nil, errors.Join(err, fmt.Errorf("failed to distribute funds for recipient %s", recipient))
}

This approach provides more context and maintains a consistent error handling pattern throughout the codebase.


Line range hint 147-208: Approve with suggestions: Improved multi-denomination support in SetToDistribute

The changes to SetToDistribute function successfully implement support for multiple coin denominations and introduce a whitelist mechanism, which aligns with the PR objective and adds flexibility to the system.

However, there are a couple of points to consider:

  1. The early return condition on line 160 might be too strict. Consider allowing the function to continue even if the current balance is zero, as this might be a valid state in some scenarios. If early return is necessary, add a comment explaining why.

  2. The comparison between currentBalance and lastBalance.Amount on line 174 might not account for all scenarios with multiple denominations. Consider implementing a more robust comparison that handles cases where denominations might be present in one balance but not the other.

Example improvement for point 2:

amountToDistribute := sdk.NewCoins()
for _, coin := range currentBalance {
    lastAmount := lastBalance.Amount.AmountOf(coin.Denom)
    if coin.Amount.GT(lastAmount) {
        amountToDistribute = amountToDistribute.Add(sdk.NewCoin(coin.Denom, coin.Amount.Sub(lastAmount)))
    }
}
if amountToDistribute.IsZero() {
    return nil
}

This approach ensures that we're only distributing positive differences for each denomination.


Line range hint 230-285: Approve with concern: Improved multi-denomination support in IterateAndUpdateFundsDistribution

The changes to IterateAndUpdateFundsDistribution function successfully implement support for multiple coin denominations, which aligns with the PR objective. The logic for calculating distributions and remaining pool funds has been updated to handle multiple denominations correctly.

However, there's a potential issue to address:

On line 251, the use of TruncateInt() when calculating the amount to distribute for each denomination could lead to precision loss, especially for small percentages or amounts. This might result in some funds never being distributed due to consistent rounding down.

Consider using a more precise approach, such as keeping track of remainders and carrying them forward to the next distribution. For example:

remainders := make(map[string]sdk.Dec)
// ... in the distribution loop:
for _, denom := range amount.Amount.Denoms() {
    fullAmount := f.Percentage.MulInt(amount.Amount.AmountOf(denom)).Add(remainders[denom])
    intPart := fullAmount.TruncateInt()
    remainders[denom] = fullAmount.Sub(sdk.NewDecFromInt(intPart))
    am := sdk.NewCoin(denom, intPart)
    // ... rest of the distribution logic
}

This approach would help ensure that all funds are eventually distributed, minimizing the impact of rounding errors over time.


Line range hint 1-516: Summary: Successful implementation of multi-denomination support with some areas for improvement

The changes in this file successfully implement support for multiple denominations in the protocol pool module, achieving the main objective of the PR. Key improvements include:

  1. Removal of the staking keeper dependency, reducing coupling.
  2. Consistent use of types.DistributionAmount for flexible handling of multiple denominations.
  3. Updated logic in key functions like SetToDistribute and IterateAndUpdateFundsDistribution to support multiple coins.
  4. Improved efficiency in module transfers by avoiding zero-amount operations.

Areas for potential improvement:

  1. Address potential precision loss in distribution calculations, particularly in the IterateAndUpdateFundsDistribution function.
  2. Enhance error handling consistency throughout the module, particularly in the withdrawRecipientFunds function.
  3. Consider revising the early return condition in the SetToDistribute function to handle edge cases more robustly.

Overall, the changes represent a significant improvement in the module's functionality and align well with the PR objectives. Addressing the identified issues will further enhance the robustness and reliability of the implementation.

x/protocolpool/proto/cosmos/protocolpool/v1/types.proto (1)

46-54: Confirm the necessity of Gogoproto options

The amount field includes Gogoproto options like (gogoproto.nullable) = false and (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins". Ensure that these options are necessary for your use case, as excessive use of custom options can complicate maintenance.

api/cosmos/protocolpool/v1/types.pulsar.go (1)

2501-2501: Add a comment for the exported field Amount

Consider adding a comment for the exported field Amount to enhance code readability and maintain consistency with other structs.

You might add a comment like:

// Amount holds a list of coins representing the periodic distribution amounts.
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 99235e2 and 9574dc2.

⛔ Files ignored due to path filters (4)
  • api/cosmos/protocolpool/v1/tx_grpc.pb.go is excluded by !**/*.pb.go
  • x/protocolpool/types/genesis.pb.go is excluded by !**/*.pb.go
  • x/protocolpool/types/tx.pb.go is excluded by !**/*.pb.go
  • x/protocolpool/types/types.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (15)
  • api/cosmos/protocolpool/v1/genesis.pulsar.go (38 hunks)
  • api/cosmos/protocolpool/v1/types.pulsar.go (6 hunks)
  • x/protocolpool/autocli.go (1 hunks)
  • x/protocolpool/keeper/genesis.go (4 hunks)
  • x/protocolpool/keeper/keeper.go (10 hunks)
  • x/protocolpool/keeper/keeper_test.go (7 hunks)
  • x/protocolpool/keeper/msg_server.go (2 hunks)
  • x/protocolpool/keeper/msg_server_test.go (19 hunks)
  • x/protocolpool/proto/cosmos/protocolpool/v1/genesis.proto (1 hunks)
  • x/protocolpool/proto/cosmos/protocolpool/v1/tx.proto (4 hunks)
  • x/protocolpool/proto/cosmos/protocolpool/v1/types.proto (2 hunks)
  • x/protocolpool/testutil/expected_keepers_mocks.go (1 hunks)
  • x/protocolpool/types/expected_keepers.go (1 hunks)
  • x/protocolpool/types/genesis.go (1 hunks)
  • x/protocolpool/types/keys.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
api/cosmos/protocolpool/v1/genesis.pulsar.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

api/cosmos/protocolpool/v1/types.pulsar.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/autocli.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/genesis.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/keeper.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/keeper_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

x/protocolpool/keeper/msg_server.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/keeper/msg_server_test.go (2)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.


Pattern **/*_test.go: "Assess the unit test code assessing sufficient code coverage for the changes associated in the pull request"

x/protocolpool/testutil/expected_keepers_mocks.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/types/expected_keepers.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/types/genesis.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

x/protocolpool/types/keys.go (1)

Pattern **/*.go: Review the Golang code for conformity with the Uber Golang style guide, highlighting any deviations.

📓 Learnings (1)
x/protocolpool/keeper/genesis.go (2)
Learnt from: likhita-809
PR: cosmos/cosmos-sdk#18471
File: x/protocolpool/keeper/genesis.go:12-51
Timestamp: 2024-10-08T15:31:05.486Z
Learning: - The user `likhita-809` has confirmed the changes suggested in the previous interaction.
- The file in question is `x/protocolpool/keeper/genesis.go` from a Cosmos SDK module.
- The changes involve optimizing the `InitGenesis` function by removing redundant code and ensuring proper handling of start times for budget proposals.
Learnt from: likhita-809
PR: cosmos/cosmos-sdk#18471
File: x/protocolpool/keeper/genesis.go:12-51
Timestamp: 2023-11-22T12:32:39.368Z
Learning: - The user `likhita-809` has confirmed the changes suggested in the previous interaction.
- The file in question is `x/protocolpool/keeper/genesis.go` from a Cosmos SDK module.
- The changes involve optimizing the `InitGenesis` function by removing redundant code and ensuring proper handling of start times for budget proposals.
🪛 buf
x/protocolpool/proto/cosmos/protocolpool/v1/tx.proto

6-6: import "cosmos/protocolpool/v1/types.proto": file does not exist

(COMPILE)

🔇 Additional comments (63)
x/protocolpool/types/genesis.go (1)

9-9: LGTM: SDK types import added

The addition of the SDK types import is consistent with the changes in the struct fields and necessary for using sdk.NewCoins().

x/protocolpool/keeper/msg_server.go (2)

160-162: LGTM: Enhanced flexibility for continuous funds

This change aligns well with the PR objective of allowing any coins in continuous funds. By using types.DistributionAmount{Amount: sdk.NewCoins()} instead of math.ZeroInt(), the implementation now supports multiple coin denominations, enhancing the flexibility of token usage in the protocol pool.


Line range hint 1-262: Summary: Enhancements align with PR objectives

The changes in this file successfully implement the PR objectives:

  1. The modification in CreateContinuousFund allows for more flexible token usage in continuous funds.
  2. The new UpdateParams method enhances the module's configurability.

These changes improve the protocol pool's functionality without introducing any significant issues. The code maintains consistency with the existing style and error handling patterns.

x/protocolpool/keeper/keeper_test.go (5)

38-42: LGTM: Removal of stakingKeeper from KeeperTestSuite

The removal of the stakingKeeper field from the KeeperTestSuite struct is consistent with the changes described in the AI summary. This change simplifies the test suite by removing unnecessary dependencies.


100-101: LGTM: Updated balance retrieval in mockWithdrawContinuousFund

The change from GetAllBalances to GetBalance for a specific denomination is consistent with the updated functionality. This modification aligns well with the shift towards handling a single denomination in the continuous fund withdrawal process.


109-110: LGTM: Updated balance retrieval in mockStreamFunds

The modification from GetAllBalances to GetBalance for a specific denomination in the mockStreamFunds method is consistent with the previous changes. This update maintains the coherence of the test suite with the new single-denomination approach.


124-125: LGTM: Updated balance retrieval in TestIterateAndUpdateFundsDistribution

The change from GetAllBalances to GetBalance for a specific denomination in the TestIterateAndUpdateFundsDistribution method is consistent with the previous modifications. This change maintains the coherence of the test suite with the new single-denomination approach.


184-185: LGTM: Updated balance retrieval and coin transfer in TestSetToDistribute

The changes from GetAllBalances to GetBalance for a specific denomination and the update to the SendCoinsFromModuleToModule call are consistent with the previous modifications. These changes correctly reflect the shift to single-denomination handling in the protocol pool.

Also applies to: 188-188

x/protocolpool/keeper/keeper.go (3)

Line range hint 24-39: LGTM: Improved Keeper structure and flexibility

The changes to the Keeper struct look good. Removing the stakingKeeper dependency reduces coupling, while the use of types.DistributionAmount for RecipientFundDistribution, Distributions, and LastBalance allows for more flexible handling of multiple coin denominations. This change aligns well with the PR objective of allowing any coins in continuous funds.


277-287: LGTM: Improved efficiency in module transfers

The changes in this section are well-implemented and improve the efficiency of the module. The conditional checks for zero amounts before performing module transfers prevent unnecessary operations, which is a good practice. Additionally, the separation of transfers for distribution amounts and pool funds enhances the clarity and maintainability of the code.

These improvements align well with the overall goal of supporting multiple denominations in the protocol pool, while also optimizing the transfer operations.


307-314: LGTM: Correct implementation of multi-denomination support in recipient fund distribution

The changes in this section successfully implement the handling of multiple denominations in the recipient fund distribution. The use of types.DistributionAmount and the Add method for combining coins ensures that all denominations are properly accounted for when updating the claimable amounts for each recipient.

This implementation aligns well with the PR objective of allowing any coins in continuous funds and maintains consistency with the changes made in other parts of the module.

x/protocolpool/types/expected_keepers.go (1)

20-20: ⚠️ Potential issue

Adding GetBalance to BankKeeper interface may introduce breaking changes

Adding a new method to an interface requires all implementations of BankKeeper to implement this new method. Please ensure that all types implementing BankKeeper have been updated to include GetBalance to prevent build failures.

x/protocolpool/proto/cosmos/protocolpool/v1/genesis.proto (1)

27-27: Ensure Backward Compatibility with Added Params Field

Adding the Params field to the GenesisState message enhances configurability. Please ensure that the system handles cases where existing genesis files might not include this new field. Implement default values or update mechanisms to maintain compatibility with older genesis files.

x/protocolpool/keeper/genesis.go (3)

16-19: Parameters are set correctly with error handling

The added code properly sets the parameters from the genesis state and appropriately wraps the error to provide context, aligning with best practices.


63-63: Appropriate update to use sdk.Coins for totalToBeDistributed

Changing totalToBeDistributed from an Int to sdk.Coins correctly accommodates multiple coin types, enhancing the flexibility of the distribution logic.

Also applies to: 65-65


73-75: Validation logic for total distribution is correctly implemented

The condition now accurately checks if totalToBeDistributed exceeds data.LastBalance.Amount, which aligns with the error message and ensures that the distribution does not surpass the available balance.

x/protocolpool/testutil/expected_keepers_mocks.go (2)

132-138: Method GetBalance added to MockBankKeeper

The added method correctly mocks the GetBalance function, adhering to the standard pattern for GoMock implementations.


140-145: Recorder method GetBalance added to MockBankKeeperMockRecorder

The recorder method for GetBalance is properly implemented, matching the mock method signature and conforming to the expected GoMock structure.

x/protocolpool/proto/cosmos/protocolpool/v1/tx.proto (3)

165-165: Update 'withdrawn_allocated_fund' field to support multiple coins

The withdrawn_allocated_fund field in MsgCancelContinuousFundResponse has been changed to a repeated Coin, allowing representation of multiple coins.

This enhancement increases flexibility by supporting multiple coin types.


179-179: Modify 'amount' field to accept multiple coins

The amount field in MsgWithdrawContinuousFundResponse is updated to a repeated Coin, enabling it to handle multiple coins.

This change aligns with the goal of supporting any tokens in continuous funds.


184-202: Add 'MsgUpdateParams' messages to enable parameter updates

The new messages MsgUpdateParams and MsgUpdateParamsResponse are correctly defined to support governance operations for updating module parameters.

This addition enhances the module's governance capabilities, allowing for dynamic parameter updates.

x/protocolpool/keeper/msg_server_test.go (15)

398-398: Appropriate Update to withdrawnAmount Type

The change of withdrawnAmount from sdk.Coin to sdk.Coins reflects the updated representation of funds, allowing handling of multiple coin types.


426-427: Initialization of Recipient Fund Distribution

Setting the recipient's fund distribution with an empty sdk.NewCoins() correctly initializes the distribution amount.


486-487: Correct Initialization of Recipient Fund Distribution

The recipient's fund distribution is properly initialized with an empty amount using sdk.NewCoins().


488-490: Appropriate Setup for Zero Fund Distribution

Setting the distributions to zero and mocking stream funds with zero simulates the scenario where no funds are available for distribution.


508-512: Valid Setup for Fund Distribution

Initializing the recipient's fund distribution and setting up the distribution with a positive fund amount prepares the test for a valid withdrawal scenario.


533-537: Consistent Initialization for Fund Distribution

Consistently initializing recipient fund distributions and setting up distributions aligns with the updated handling of multiple coin types.


559-561: Proper Initialization for Multiple Continuous Funds

The setup correctly prepares multiple continuous funds with their respective recipients and percentages.


574-576: Initialization of Second Recipient Fund Distribution

Setting the second recipient's fund distribution ensures accurate test conditions for multiple fund withdrawals.


589-591: Initialization of Third Recipient Fund Distribution

Adding the third recipient's fund distribution completes the setup for testing distribution among multiple recipients.


797-797: Update to withdrawnFunds Type is Appropriate

Changing withdrawnFunds from sdk.Coin to sdk.Coins accommodates multiple coin types, aligning with the updated funds representation.


832-833: Correct Setup of Recipient Fund Distribution

Initializing the recipient's fund distribution with sdk.NewCoins() ensures accurate starting conditions for the test.


847-848: Setting Up Second Recipient's Fund Distribution

Properly setting up the second recipient's fund distribution prepares the test for scenarios involving multiple recipients.


884-885: Correct Initialization for Third Recipient's Fund Distribution

Setting up the third recipient's fund distribution completes the test setup for canceling continuous funds among multiple recipients.


1007-1007: Assertion is Appropriate

Using IsZero() to check that WithdrawnAllocatedFund is empty ensures accurate verification of the fund withdrawal status.


1042-1053: Added Test TestUpdateParams Enhances Coverage

The new test function TestUpdateParams effectively verifies the updating of pool parameters, ensuring that the functionality works as expected.

api/cosmos/protocolpool/v1/genesis.pulsar.go (26)

177-177: Ensure Field Descriptor for 'Params' Field is Correct

The field descriptor fd_GenesisState_params is added on line 177 and assigned on line 187. Verify that the field name "params" used in md_GenesisState.Fields().ByName("params") matches the actual field name in the GenesisState struct to prevent any issues during reflection.

Also applies to: 187-187


267-268: Include New Fields in 'Range' Method Iteration

In the Range method, the new fields LastBalance and Params are included correctly (lines 267-268 and 279-284). Ensure that the iteration handles nil values properly to prevent potential nil pointer dereferences.

Also applies to: 279-284


305-305: Update 'Has' Method for New Fields

The Has method now includes checks for LastBalance (line 305) and Params (line 309). This allows for accurate detection of whether these fields are set.

Also applies to: 308-309


331-331: Modify 'Clear' Method to Reset New Fields

In the Clear method, the new fields LastBalance (line 331) and Params (line 335) are set to nil. This ensures that calling Clear will reset these fields as expected.

Also applies to: 334-335


405-405: Ensure Proper Assignment in 'Set' Method

The Set method assigns the new fields LastBalance (line 405) and Params (line 411) correctly by casting the provided value to the appropriate type.

Also applies to: 410-411


444-448: Initialize New Fields in 'Mutable' Method

In the Mutable method, LastBalance (lines 445-448) and Params (lines 456-459) are initialized if they are nil. This ensures that mutable references can be safely used without causing nil pointer exceptions.

Also applies to: 455-459


480-481: Correct 'NewField' Method Implementation for New Fields

The NewField method correctly creates new instances of DistributionAmount (line 481) and Params (line 487) for the fields LastBalance and Params, respectively.

Also applies to: 485-487


569-570: Include New Fields in 'Size' Calculation

In the Size method, the size of LastBalance (lines 569-570) and Params (lines 579-582) is included when they are not nil. This ensures accurate size calculation for serialization.

Also applies to: 579-582


612-625: Handle New Fields in 'Marshal' Method

The Marshal method serializes Params (lines 612-625) and LastBalance (lines 642-652) when they are not nil. Ensure that error handling properly captures any issues during marshaling.

Also applies to: 642-652


Line range hint 809-839: Update 'Unmarshal' Method to Deserialize New Fields

The Unmarshal method now includes logic to deserialize LastBalance (lines 809-839). It correctly initializes the field if necessary and unmarshals the data.


875-909: Add Deserialization for 'Params' in 'Unmarshal' Method

Lines 875-909 incorporate deserialization logic for the Params field. The method ensures Params is initialized and properly handles potential errors during unmarshaling.


949-949: Define Field Descriptor for 'Amount' Field in 'Distribution'

The field descriptor fd_Distribution_amount is added on line 949 and assigned on line 956. Confirm that "amount" matches the field name in the Distribution struct to ensure correct reflection behavior.

Also applies to: 956-956


1030-1035: Include 'Amount' Field in 'Range' Method of 'Distribution'

In the Range method of fastReflection_Distribution, the new Amount field is included (lines 1030-1035). This allows iteration over all populated fields, including the new ones.


1053-1054: Update 'Has' Method for 'Distribution' Struct

The Has method now checks for the presence of the Amount field (line 1054), ensuring it correctly reports whether the field is set.


1073-1074: Modify 'Clear' Method in 'Distribution' Struct

In the Clear method, the Amount field is set to nil (line 1074), ensuring that clearing the message resets this field.


1094-1096: Verify 'Get' Method Implementation in 'Distribution'

Lines 1094-1096 correctly retrieve Time and Amount fields in the Get method of fastReflection_Distribution. This resolves the previous issue mentioned in past review comments.


1119-1120: Correct Type Casting in 'Set' Method

The Set method assigns the Amount field by casting the message to *DistributionAmount (line 1120). This ensures type safety and correctness.


1147-1150: Initialize 'Amount' Field in 'Mutable' Method

The Mutable method initializes x.Amount if it is nil (lines 1147-1150). This allows for safe mutable operations on the Amount field.


1167-1169: Implement 'NewField' Method for 'Amount' Field

In the NewField method, a new instance of DistributionAmount is created for Amount (lines 1167-1169). This provides a default value that can be assigned to the field.


1243-1246: Include 'Amount' in 'Size' Calculation

The Size method accounts for the Amount field when it is not nil (lines 1243-1246). This ensures accurate serialization size.


Line range hint 1276-1288: Serialize 'Amount' Field in 'Marshal' Method

In the Marshal method, the Amount field is serialized when present (lines 1276-1288). The method handles potential errors during marshaling.

Also applies to: 1290-1302


Line range hint 1353-1389: Deserialize 'Amount' Field in 'Unmarshal' Method

The Unmarshal method includes logic to deserialize the Amount field (lines 1353-1389), ensuring it's properly initialized and populated.


1485-1485: Add New Fields to 'GenesisState' Struct

The GenesisState struct includes new fields LastBalance *DistributionAmount (line 1485) and Params *Params (line 1490). Verify that the JSON tags and field options are correct.

Also applies to: 1490-1490


1527-1531: Update Getter Methods for New Fields in 'GenesisState'

The methods GetLastBalance (lines 1527-1531) and GetParams (lines 1541-1547) return the new fields correctly. Ensure these methods handle nil cases appropriately.

Also applies to: 1541-1547


1553-1554: Modify 'Distribution' Struct and Accessors for New 'Amount' Field

The Distribution struct now includes Amount *DistributionAmount (line 1554). The getter methods GetTime and GetAmount are updated accordingly (lines 1577-1581 and 1584-1586).

Also applies to: 1577-1581, 1584-1586


1614-1636: Ensure Protobuf Definitions Reflect Changes

In the protobuf definitions (lines 1614-1636), the last_balance and params fields are added with appropriate field numbers and types. Confirm that there are no conflicts with existing field numbers.

api/cosmos/protocolpool/v1/types.pulsar.go (1)

2495-2529: DistributionAmount struct implementation looks good

The DistributionAmount struct is well-defined and adheres to Go conventions.

@@ -8,6 +8,7 @@ import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
import "amino/amino.proto";
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid importing deprecated Amino encoding library

The import of "amino/amino.proto" introduces a dependency on Amino, which is deprecated in favor of Protobuf encoding in the Cosmos SDK. It's recommended to avoid using Amino in new code to ensure future compatibility and reduce technical debt.

Comment on lines +46 to +54
// DistributionAmount is used to store the coins of periodic distributions.
message DistributionAmount {
repeated cosmos.base.v1beta1.Coin amount = 1 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(amino.dont_omitempty) = true,
(amino.encoding) = "legacy_coins"
];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Reassess the use of Amino options in DistributionAmount

The amount field in the DistributionAmount message uses Amino-specific options such as (amino.dont_omitempty) and (amino.encoding) = "legacy_coins". Since Amino is deprecated, consider removing these options and relying solely on Protobuf serialization to align with current best practices.

Comment on lines +56 to +61
// Params defines the parameters for the protocolpool module.
message Params {
// enabled_distribution_denoms lists the denoms that are allowed to be distributed.
// This is to avoid spending time distributing undesired tokens to continuous funds and budgets.
repeated string enabled_distribution_denoms = 1;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding validation for enabled_distribution_denoms

In the Params message, the enabled_distribution_denoms field lacks explicit validation. To prevent potential misconfigurations, consider adding validation logic to ensure that only allowed denominations are included.

Comment on lines +126 to 128
err = k.Distributions.Walk(ctx, nil, func(key time.Time, value types.DistributionAmount) (stop bool, err error) {
genState.Distributions = append(genState.Distributions, &types.Distribution{
Time: &key,
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Wrap error when walking through distributions for enhanced clarity

Wrapping the error from k.Distributions.Walk(ctx, nil, ...) with context can provide better insight during debugging and maintain consistency in error handling.

Apply this diff to wrap the error:

 if err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to walk through distributions: %w", err)
 }

Committable suggestion was skipped due to low confidence.

Comment on lines +138 to +141
params, err := k.Params.Get(ctx)
if err != nil {
return nil, err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Wrap error when retrieving parameters for better context

To improve error handling and aid in debugging, consider wrapping the error returned by k.Params.Get(ctx) with additional context.

Apply this diff to wrap the error:

 if err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to get params: %w", err)
 }
📝 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
params, err := k.Params.Get(ctx)
if err != nil {
return nil, err
}
params, err := k.Params.Get(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get params: %w", err)
}

Comment on lines +446 to 447
err = suite.poolKeeper.Distributions.Set(suite.ctx, suite.ctx.HeaderInfo().Time, types.DistributionAmount{Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(100000)))})
suite.Require().NoError(err)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider Parameterizing Coin Denomination

Since the protocol now allows any token for continuous funds, consider making the coin denomination configurable rather than hardcoding sdk.DefaultBondDenom.

Apply this diff to parameterize the coin denomination:

- err = suite.poolKeeper.Distributions.Set(suite.ctx, suite.ctx.HeaderInfo().Time, types.DistributionAmount{Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(100000)))})
+ denom := <desired_denomination>
+ err = suite.poolKeeper.Distributions.Set(suite.ctx, suite.ctx.HeaderInfo().Time, types.DistributionAmount{Amount: sdk.NewCoins(sdk.NewCoin(denom, math.NewInt(100000)))})

Committable suggestion was skipped due to low confidence.

@@ -625,10 +625,10 @@
if len(tc.recipientAddress) > 1 {
toClaim, err := suite.poolKeeper.RecipientFundDistribution.Get(suite.ctx, tc.recipientAddress[1])
suite.Require().NoError(err)
suite.Require().Equal(toClaim, math.NewInt(20000))
suite.Require().Equal(toClaim.Amount, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(20000))))
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid Hardcoding Coin Denomination

To enhance flexibility, consider parameterizing the coin denomination instead of using the hardcoded "stake".

Apply this diff:

- suite.Require().Equal(toClaim.Amount, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(20000))))
+ denom := <desired_denomination>
+ suite.Require().Equal(toClaim.Amount, sdk.NewCoins(sdk.NewCoin(denom, math.NewInt(20000))))

Committable suggestion was skipped due to low confidence.

@@ -865,7 +865,7 @@
suite.Require().Error(err)
suite.Require().ErrorIs(err, collections.ErrNotFound)
},
withdrawnFunds: sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(20000)),
withdrawnFunds: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(20000))),
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Parameterize Coin Denomination in withdrawnFunds

Consider making the coin denomination configurable to reflect the allowance of any token in continuous funds.

Apply this diff:

- withdrawnFunds: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(20000))),
+ denom := <desired_denomination>
+ withdrawnFunds: sdk.NewCoins(sdk.NewCoin(denom, math.NewInt(20000))),

Committable suggestion was skipped due to low confidence.

@@ -351,13 +363,16 @@ func (x *fastReflection_GenesisState) Get(descriptor protoreflect.FieldDescripto
return protoreflect.ValueOfList(listValue)
case "cosmos.protocolpool.v1.GenesisState.last_balance":
value := x.LastBalance
return protoreflect.ValueOfString(value)
return protoreflect.ValueOfMessage(value.ProtoReflect())
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add Nil Checks in 'Get' Method for New Fields

In the Get method, lines 366 and 373-375 handle LastBalance and Params. To prevent potential nil pointer dereferences, consider adding checks to handle cases where these fields might be nil.

Apply this diff to add nil handling:

 case "cosmos.protocolpool.v1.GenesisState.last_balance":
+    if x.LastBalance == nil {
+        return protoreflect.Value{}
+    }
     value := x.LastBalance
     return protoreflect.ValueOfMessage(value.ProtoReflect())
 case "cosmos.protocolpool.v1.GenesisState.params":
+    if x.Params == nil {
+        return protoreflect.Value{}
+    }
     value := x.Params
     return protoreflect.ValueOfMessage(value.ProtoReflect())

Also applies to: 373-375

Comment on lines +2537 to +2538
// enabled_distribution_denoms lists the denoms that are allowed to be distributed.
// This is to avoid spending time distributing undesired tokens to continuous funds and budgets.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Correct the field comment to follow GoDoc conventions

The comment for the exported field EnabledDistributionDenoms should start with the field name capitalized, as per GoDoc guidelines.

Apply this diff to fix the comment:

-	// enabled_distribution_denoms lists the denoms that are allowed to be distributed.
+	// EnabledDistributionDenoms lists the denoms that are allowed to be distributed.
📝 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
// enabled_distribution_denoms lists the denoms that are allowed to be distributed.
// This is to avoid spending time distributing undesired tokens to continuous funds and budgets.
// EnabledDistributionDenoms lists the denoms that are allowed to be distributed.
// This is to avoid spending time distributing undesired tokens to continuous funds and budgets.

x.EnabledDistributionDenoms = *clv.list
default:
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.protocolpool.v1.Params"))

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
if fd.IsExtension() {
panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.protocolpool.v1.Params"))
}
panic(fmt.Errorf("message cosmos.protocolpool.v1.Params does not contain field %s", fd.FullName()))

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
Copy link
Contributor

@alpe alpe left a comment

Choose a reason for hiding this comment

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

Very nice work. 🏄
I added some minor comments about variable names but feel free to ignore them.

The default genesis though does not work for custom token denoms. We should provide a way to costomize this for chains. IMHO this needs to be solved before merging the changes.

toDistribute := map[string]math.Int{}
poolFunds := math.ZeroInt()
fullAmountToDistribute := math.ZeroInt()
toDistribute := map[string]sdk.Coins{}
Copy link
Contributor

Choose a reason for hiding this comment

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

naming is hard
personal preference: how about distributeToRecipient ?

Copy link
Member Author

Choose a reason for hiding this comment

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

accepting these changes 👌

poolFunds := math.ZeroInt()
fullAmountToDistribute := math.ZeroInt()
toDistribute := map[string]sdk.Coins{}
amountToDistribute := sdk.NewCoins() // amount assigned to distributions
Copy link
Contributor

Choose a reason for hiding this comment

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

personal preference: effectiveDistributionAmounts ?

fullAmountToDistribute := math.ZeroInt()
toDistribute := map[string]sdk.Coins{}
amountToDistribute := sdk.NewCoins() // amount assigned to distributions
allDistributions := sdk.NewCoins() // total amount distributed to the pool, to then calculate the remaining pool funds
Copy link
Contributor

Choose a reason for hiding this comment

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

personal preference: totalDistributionAmounts ?

percentageToDistribute := math.LegacyZeroDec()
allDistributions = allDistributions.Add(amount.Amount...)
Copy link
Contributor

Choose a reason for hiding this comment

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

personal preference: totalPercentageApplied ?

return nil, err
}

return &types.MsgUpdateParamsResponse{}, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

Adding/removing a denom from the list does not affect the Distributions stored but only future distributions. I assume this the expected behaviour but I wanted to check.

}
}

func DefaultGenesisState() *GenesisState {
return &GenesisState{
ContinuousFund: []*ContinuousFund{},
Budget: []*Budget{},
Params: &Params{
EnabledDistributionDenoms: []string{"stake"},
Copy link
Contributor

Choose a reason for hiding this comment

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

Blocker: We need a way to make this configurable by chains.

Not sure if sdk.DefaultBondDenom is still used but you can make this a constructor param and pass it from the app module

Copy link
Member Author

Choose a reason for hiding this comment

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

They can change this in the genesis file, but I'll change it to sdk.DefaultBondDenom, not sure what I thought about when I put there the string

@alpe
Copy link
Contributor

alpe commented Oct 17, 2024

The changes in this PR would be state breaking. The common way is to handle this, is to bump the module version and provide a state migration. See https://github.com/cosmos/cosmos-sdk/blob/main/x/group/migrations/v2/migrate.go for an example

@facundomedica
Copy link
Member Author

The changes in this PR would be state breaking. The common way is to handle this, is to bump the module version and provide a state migration. See https://github.com/cosmos/cosmos-sdk/blob/main/x/group/migrations/v2/migrate.go for an example

No need for migration as this module hasn't been published yet

Copy link
Member

@julienrbrt julienrbrt left a comment

Choose a reason for hiding this comment

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

utACK! some nits

Copy link
Member

Choose a reason for hiding this comment

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

would be great to add a test case for a non allowed denom

Copy link
Member Author

Choose a reason for hiding this comment

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

Non allowed denoms are just ignored in the case of continuous funds. In budgets there's no limit as to what denom you can use.

For example, we could be distributing ATOMs to continuous funds, but the community pool also contains USDC which can be still used for budgets and not distributed.

Copy link
Member Author

Choose a reason for hiding this comment

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

I still modified TestSetToDistribute to have 2 coins, just in case

// UpdateParams defines a governance operation for updating the x/protocolpool module parameters.
// The authority is defined in the keeper.
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse) {
option (cosmos_proto.method_added_in) = "cosmos-sdk 0.47";
Copy link
Member

Choose a reason for hiding this comment

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

should be changed to 0.52 or protocolpool v0.2.0

@julienrbrt julienrbrt added this pull request to the merge queue Nov 11, 2024
Merged via the queue into main with commit 13c234f Nov 11, 2024
77 of 78 checks passed
@julienrbrt julienrbrt deleted the facu/allow-all-coins-protopool branch November 11, 2024 18:12
mergify bot pushed a commit that referenced this pull request Nov 11, 2024
(cherry picked from commit 13c234f)

# Conflicts:
#	api/cosmos/protocolpool/v1/genesis.pulsar.go
#	api/cosmos/protocolpool/v1/tx.pulsar.go
#	api/cosmos/protocolpool/v1/tx_grpc.pb.go
#	api/cosmos/protocolpool/v1/types.pulsar.go
#	x/protocolpool/keeper/genesis.go
#	x/protocolpool/testutil/expected_keepers_mocks.go
alpe added a commit that referenced this pull request Nov 13, 2024
* main: (31 commits)
  docs: update links for https security protocol (#22514)
  build(deps): Bump github.com/bytedance/sonic from 1.12.3 to 1.12.4 in /log (#22513)
  feat(x/protocolpool)!: allow any coins in continuous funds (#21916)
  docs: Update protobuf  tx signing message format outer link (#22510)
  test(accounts): fix integration tests (#22418)
  chore(x): fix some typos in comment (#22508)
  build(deps): Bump cosmossdk.io/log from 1.4.1 to 1.5.0 (#22487)
  build(deps): Bump cosmossdk.io/core from 1.0.0-alpha.5 to 1.0.0-alpha.6 (#22502)
  build(deps): Bump golang.org/x/crypto from 0.28.0 to 0.29.0 (#22480)
  docs(adr75): server v2 (#21069)
  fix(server/v2): improve server stop (#22455)
  chore: prepare core changelog (#22495)
  refactor(store/v2): simplify genesis flow (#22435)
  build(deps): Bump google.golang.org/grpc from 1.67.1 to 1.68.0 (#22486)
  build(deps): Bump golang.org/x/sync from 0.8.0 to 0.9.0 (#22482)
  feat(x/circuit): Allow msg Reset with empty msgURL (#22459)
  build(deps): Bump actions/xxx-artifact from v3 to v4 (#22468)
  feat(stf/branch): simplify merged iterator (#22131)
  refactor(log): disable coloring in testing logger (#22466)
  chore(x/tx): update changelog to alpha.2 (#22465)
  ...
julienrbrt added a commit that referenced this pull request Nov 18, 2024
…21916) (#22512)

Co-authored-by: Facundo Medica <[email protected]>
Co-authored-by: Facundo <[email protected]>
Co-authored-by: Julien Robert <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport/v0.52.x PR scheduled for inclusion in the v0.52's next stable release C:CLI C:x/protocolpool
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants