Skip to content

Conversation

@mbreithecker
Copy link
Member

@mbreithecker mbreithecker commented Feb 10, 2025

Summary by CodeRabbit

• New Features
 – Integrated a comprehensive multi-coin rewards system that allows users to opt-in for rewards, manage distribution policies, and query reward parameters through the CLI.
 – Introduced functionality for toggling multi-coin rewards and setting distribution policies, with detailed event logging.
 – Enhanced genesis state support for initializing and exporting rewards configuration, including new parameters for distribution policies.
 – Added new commands for querying and managing multi-coin rewards through the CLI, including commands for toggling rewards and setting distribution policies.
 – Implemented a structured approach for handling pending rewards and redistributing unclaimed rewards based on defined policies.
 – Added a new module for managing multi-coin rewards, including support for protobuf messages and improved error handling.

• Chores
 – Updated dependencies and refined configuration settings, improving overall system stability and distribution processing.

• Tests
 – Added extensive tests to validate reward distribution logic, toggling functionality, and parameter updates.

@coderabbitai
Copy link

coderabbitai bot commented Feb 10, 2025

Walkthrough

This pull request integrates a comprehensive multi-coin rewards system throughout the application. It adds new modules, protobuf definitions, CLI commands, keeper logic, genesis handling, and gRPC query endpoints to support multi-coin rewards management. Additionally, dependency versions and configuration files have been updated, and various renaming and type adjustments have been made to align with the new functionality.

Changes

File(s) Summary
api/kyve/multi_coin_rewards/module/module.pulsar.go Added new Go module with protobuf message handling, including methods for reflection, serialization, and Authority field management.
app/app.go, app/app_config.go Integrated multi-coin rewards module; updated keeper field types; added new keeper and configuration entries for module initialization.
app/upgrades/v2_0/store.go, app/upgrades/v2_0/upgrade.go Modified store upgrade process and upgrade handler to include multi-coin rewards; added function to ensure multi-coin distribution account.
config.yml, go.mod Introduced new multi_coin_rewards configuration parameters and updated dependencies with a custom Cosmos SDK replace directive.
proto/kyve/multi_coin_rewards/* Introduced new proto files (module.proto, events.proto, genesis.proto, params.proto, query.proto, tx.proto, types.proto) defining messages, services, and genesis state for multi-coin rewards.
x/multi_coin_rewards/client/cli/* Added new CLI commands for querying parameters and handling transactions to toggle rewards and set distribution policy.
x/multi_coin_rewards/genesis.go, x/multi_coin_rewards/keeper/* Implemented genesis state management and extensive keeper methods for pending rewards, queues, distribution logic, gRPC queries, and message server implementations.
x/multi_coin_rewards/module.go, x/multi_coin_rewards/types/* Established the module interface implementation; registered codecs, message types, error variables, and parameter management for the multi-coin rewards module.
x/query/, x/stakers/ Updated query and staker modules to adopt a custom DistributionKeeper interface, replacing previous Cosmos SDK dependencies.
testutil/integration/integration.go, util/expected_keepers.go, x/global/ante_test.go Added a new test field for validator addresses, introduced a new BankKeeper method, and updated the base gas cost in tests.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant CLI as CLI Command
    participant MS as MsgServer
    participant K as Keeper
    participant BM as Bank Module

    U->>CLI: Execute toggle multi-coin rewards command (true/false)
    CLI->>MS: Send MsgToggleMultiCoinRewards
    MS->>K: Validate request and check current rewards state
    alt Rewards need enabling
        K->>K: Retrieve and sum pending rewards
        K->>BM: Transfer pending rewards to user account
        K->>K: Mark rewards as enabled
    else Rewards need disabling
        K->>K: Remove user's reward enabling entry
    end
    MS->>CLI: Return response
    CLI->>U: Display success message
Loading
sequenceDiagram
    participant Gov as Governance/Authority
    participant CLI as CLI/TX Command
    participant MS as MsgServer
    participant K as Keeper
    participant EVT as Event System

    Gov->>CLI: Submit MsgUpdateParams with new parameters payload
    CLI->>MS: Send MsgUpdateParams for processing
    MS->>K: Validate authority and unmarshal new parameters
    K->>K: Update stored parameters via SetParams
    K->>EVT: Emit EventUpdateParams (old & new parameters)
    MS->>CLI: Return successful response
Loading

Suggested reviewers

  • troykessler

Poem

Oh, what a hop in code today,
A rabbit’s delight in rewards array!
Multi-coin magic in each new line,
CLI and keeper in a structured design.
With every commit, we bound with glee,
ASCII carrots and bugs set free!
Hoppy code, hop on—the future’s bright!

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

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 generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

Copy link

@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: 15

🧹 Nitpick comments (36)
x/multi_coin_rewards/keeper/keeper.go (1)

71-74: Provide a more descriptive panic message or return an error.
Panicking halts the chain if schema initialization fails. This is typical for catastrophic module init failures, but returning (or logging) a more descriptive error message can help operators diagnose issues more quickly.

x/multi_coin_rewards/keeper/logic_distribution.go (4)

11-11: Use sdk.AccAddress instead of string for address.
Using an sdk.AccAddress for the "address" parameter would prevent invalid addresses from being passed in, improving type safety.

-func (k Keeper) addPendingRewards(ctx sdk.Context, address string, rewards sdk.Coins) {
+func (k Keeper) addPendingRewards(ctx sdk.Context, address sdk.AccAddress, rewards sdk.Coins) {

28-34: Avoid silent continuation.
The loop continues if the entry isn’t found, which can mask data inconsistencies or indexing bugs. Consider logging a warning.

 if !found {
+  k.Logger().Error("Queue entry not found", "index", index)
   return true
 }

56-59: Check the distribution policy’s validity earlier.
Validation of the distribution policy is done here, but if errors are frequent, consider a preflight check or caching.


84-89: Warn about nonexistent pools instead of failing distribution.
Returning an error cancels distribution entirely. Decide if partial distribution to valid pools is acceptable or maintain current approach where any invalid pool halts the process.

x/multi_coin_rewards/keeper/getters_compliance.go (2)

55-69: Check the returned "found" flag.
Currently, "GetMultiCoinPendingRewardsEntry"’s "found" flag isn’t used after retrieving an entry by index. Handling the case where the entry is missing could avoid referencing entries that no longer exist.


72-82: Safeguard against missing entries.
A "RemoveMultiCoinPendingRewardsEntry" call with a non-existent entry might silently no-op. If the queue logic is complex, consider logging or checking for existence first.

app/upgrades/v2_0/upgrade.go (1)

37-37: Added 'accountKeeper' parameter.

Expanding the function signature to include 'accountKeeper' will facilitate module account operations during the upgrade. Ensure that any upstream calls to this function are updated accordingly.

x/multi_coin_rewards/module.go (1)

150-167: Block-based distribution scheduling.

Triggering non-claimed rewards distribution every 50 blocks is straightforward. Check for potential performance implications if the distribution logic grows in complexity. Consider using a parameter instead of a hard-coded 50 for more flexibility if needed.

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

7-9: Embedding Keeper in 'msgServer'.

By embedding the keeper, the 'msgServer' has direct access to all keeper methods. Just ensure the keeper is not performing complex business logic that might be better placed in dedicated functions for clarity.

x/multi_coin_rewards/types/errors.go (1)

7-8: Fix incorrect comment.

The comment "staking errors" is incorrect as these errors are related to multi-coin rewards.

-// staking errors
+// multi-coin rewards errors
x/multi_coin_rewards/keeper/keeper_suite_test.go (1)

22-31: Consider using test assertions instead of panics.

While using panics in test helpers is acceptable, using test assertions would provide better error messages and test diagnostics.

Apply this diff to improve error handling:

-func payoutRewards(s *i.KeeperTestSuite, staker string, coins sdk.Coins) {
+func payoutRewards(s *i.KeeperTestSuite, staker string, coins sdk.Coins) error {
 	err := s.App().BankKeeper.MintCoins(s.Ctx(), mintTypes.ModuleName, coins)
 	if err != nil {
-		panic(err)
+		return fmt.Errorf("failed to mint coins: %w", err)
 	}
 	err = s.App().StakersKeeper.PayoutRewards(s.Ctx(), staker, coins, mintTypes.ModuleName)
 	if err != nil {
-		panic(err)
+		return fmt.Errorf("failed to payout rewards: %w", err)
 	}
+	return nil
 }

Then in the test:

err := payoutRewards(s, staker, coins)
Expect(err).To(BeNil())
x/multi_coin_rewards/keeper/msg_server_distribution_policy.go (1)

11-24: Consider emitting an event for policy changes.

While the function correctly validates and updates the policy, it should emit an event to track policy changes for better observability.

Apply this diff to add event emission:

 func (k msgServer) SetMultiCoinRewardDistributionPolicy(goCtx context.Context, policy *types.MsgSetMultiCoinRewardsDistributionPolicy) (*types.MsgSetMultiCoinRewardsDistributionPolicyResponse, error) {
 	ctx := sdk.UnwrapSDKContext(goCtx)
 	params := k.GetParams(ctx)

 	if params.MultiCoinDistributionPolicyAdminAddress != policy.Creator {
 		return nil, types.ErrMultiCoinDistributionPolicyInvalidAdminAddress
 	}

 	if err := k.MultiCoinDistributionPolicy.Set(ctx, *policy.Policy); err != nil {
 		return nil, errors.Wrap(err, types.ErrMultiCoinDistributionPolicyInvalid.Error())
 	}

+	ctx.EventManager().EmitEvent(
+		sdk.NewEvent(
+			types.EventTypeSetMultiCoinDistributionPolicy,
+			sdk.NewAttribute(types.AttributeKeyCreator, policy.Creator),
+			sdk.NewAttribute(types.AttributeKeyPolicy, policy.Policy.String()),
+		),
+	)
+
 	return &types.MsgSetMultiCoinRewardsDistributionPolicyResponse{}, nil
 }
x/multi_coin_rewards/client/cli/query.go (1)

8-9: Remove commented imports.

Clean up the code by removing the commented imports that are not being used.

-	// "strings"
-
-	// "github.com/cosmos/cosmos-sdk/client/flags"
-	// sdk "github.com/cosmos/cosmos-sdk/types"

Also applies to: 13-15

x/multi_coin_rewards/types/params.go (1)

5-6: Add proper documentation for the default value.

The comment for DefaultMultiCoinDistributionPendingTime should explain what this value represents (14 days in seconds) and its significance.

-// DefaultMultiCoinDistributionPendingTime ...
+// DefaultMultiCoinDistributionPendingTime represents the default pending time of 14 days in seconds
+// before a multi-coin distribution policy takes effect
x/multi_coin_rewards/client/cli/tx_toggle_multi_coin_rewards.go (1)

25-27: Consider using strconv.ParseBool for more flexible input validation.

The current validation only accepts "true" or "false". Using strconv.ParseBool would allow more user-friendly inputs like "1", "t", "TRUE", etc.

-if args[0] != "true" && args[0] != "false" {
-  return fmt.Errorf("value must be 'true' or 'false'")
+enabled, err := strconv.ParseBool(args[0])
+if err != nil {
+  return fmt.Errorf("value must be a valid boolean: %v", err)
}
x/multi_coin_rewards/types/keys.go (2)

24-32: Document magic numbers in key prefixes.

The byte arrays use magic numbers (8, 9) without explanation. Consider adding comments explaining their significance or using named constants.

+const (
+  // Key type identifiers
+  KEY_TYPE_PENDING_REWARDS = 8
+  KEY_TYPE_POLICY = 9
+)

-MultiCoinPendingRewardsEntryKeyPrefix = []byte{8, 0}
+MultiCoinPendingRewardsEntryKeyPrefix = []byte{KEY_TYPE_PENDING_REWARDS, 0}

34-37: Consider using iota for QUEUE_IDENTIFIER.

The type could be better implemented as an enum using iota for better type safety and maintainability.

-type QUEUE_IDENTIFIER []byte
+type QueueIdentifier int

const (
+  QueueIdentifierMultiCoinRewards QueueIdentifier = iota + 1
)

-var QUEUE_IDENTIFIER_MULTI_COIN_REWARDS QUEUE_IDENTIFIER = []byte{30, 5}
+var QUEUE_IDENTIFIER_MULTI_COIN_REWARDS = QueueIdentifierMultiCoinRewards
x/multi_coin_rewards/client/cli/tx_set_multi_coin_refund_policy.go (1)

17-19: Enhance command documentation.

The command's usage and description could be more descriptive. Consider adding:

  • Example usage
  • Policy format description
  • Required permissions
-		Use:   "set-multi-coin-distribution-policy [path-to-json-file]",
-		Short: "Broadcast message to update the distribution policy",
+		Use:   "set-multi-coin-distribution-policy [path-to-json-file]",
+		Short: "Update the multi-coin rewards distribution policy",
+		Long: `Update the distribution policy for multi-coin rewards.
+
+Example:
+  $ kyved tx multi-coin-rewards set-multi-coin-distribution-policy policy.json
+
+Policy JSON format:
+  {
+    "distribution_map": {
+      "ukex": "70",
+      "ukyve": "30"
+    }
+  }
+
+Required permissions: Must be executed by the policy admin address.`,
x/multi_coin_rewards/types/genesis.go (1)

20-33: Optimize map usage and improve error messages.

The validation logic could be optimized and error messages could be more descriptive.

+	// Pre-allocate map with expected size
+	multiCoinPendingRewardsMap := make(map[string]struct{}, len(gs.MultiCoinPendingRewardsEntries))
-	multiCoinPendingRewardsMap := make(map[string]struct{})

 	for _, elem := range gs.MultiCoinPendingRewardsEntries {
 		index := string(MultiCoinPendingRewardsKeyEntry(elem.Index))
 		if _, ok := multiCoinPendingRewardsMap[index]; ok {
-			return fmt.Errorf("duplicated index for multi coin pending rewards entry %v", elem)
+			return fmt.Errorf("duplicate index %d found in multi coin pending rewards entries", elem.Index)
 		}
 		if elem.Index > gs.QueueStatePendingRewards.HighIndex {
-			return fmt.Errorf(" multi coin pending rewards entry index too high: %v", elem)
+			return fmt.Errorf("index %d exceeds maximum allowed value %d", elem.Index, gs.QueueStatePendingRewards.HighIndex)
 		}
 		if elem.Index < gs.QueueStatePendingRewards.LowIndex {
-			return fmt.Errorf(" multi coin pending rewards entry index too low: %v", elem)
+			return fmt.Errorf("index %d is below minimum allowed value %d", elem.Index, gs.QueueStatePendingRewards.LowIndex)
 		}
x/multi_coin_rewards/keeper/logic_queue.go (1)

31-43: Improve queue processing loop condition and variable naming.

The loop condition and variable naming could be clearer. The variable commissionChangePerformed seems to be misnamed for the context.

-	for commissionChangePerformed := true; commissionChangePerformed; {
-		commissionChangePerformed = false
+	for shouldContinueProcessing := true; shouldContinueProcessing; {
+		shouldContinueProcessing = false
 
 		entryRemoved := processEntry(queueState.LowIndex + 1)
 
 		if entryRemoved {
 			if queueState.LowIndex < queueState.HighIndex {
 				queueState.LowIndex += 1
-				commissionChangePerformed = true
+				shouldContinueProcessing = true
 			}
 		}
 	}
x/multi_coin_rewards/keeper/msg_server_toggle.go (2)

35-38: Add validation before sending coins.

Verify that totalRewards is not empty before attempting to send coins to avoid unnecessary transactions.

+		if totalRewards.IsZero() {
+			// Skip bank transfer if no rewards to send
+			if err := k.MultiCoinRewardsEnabled.Set(ctx, accountAddress); err != nil {
+				return nil, err
+			}
+			return &types.MsgToggleMultiCoinRewardsResponse{}, nil
+		}
 		err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, accountAddress, totalRewards)
 		if err != nil {
 			return nil, err
 		}

55-56: Consider adding event emission.

Add event emission to track when multi-coin rewards are toggled.

+	ctx.EventManager().EmitEvent(
+		sdk.NewEvent(
+			types.EventTypeToggleMultiCoinRewards,
+			sdk.NewAttribute(types.AttributeKeyCreator, toggle.Creator),
+			sdk.NewAttribute(types.AttributeKeyEnabled, strconv.FormatBool(toggle.Enabled)),
+		),
+	)
 	return &types.MsgToggleMultiCoinRewardsResponse{}, nil
x/multi_coin_rewards/keeper/msg_server_update_params_test.go (3)

65-77: Consider adding more test cases for invalid authority.

The current test only checks one scenario with a dummy address. Consider adding tests for:

  • Empty authority
  • Malformed address
  • Authority with insufficient permissions

168-196: Enhance invalid payload test coverage.

The test could be expanded to include more edge cases:

  • Empty payload
  • Malformed JSON
  • Invalid types for both parameters
  • Missing required fields

46-51: Extract common setup code into helper functions.

The BeforeEach block contains repeated code that could be extracted into helper functions for better maintainability.

+func (s *KeeperTestSuite) setupTestValidator() sdk.AccAddress {
+    delegations, _ := s.App().StakingKeeper.GetAllDelegations(s.Ctx())
+    return sdk.MustAccAddressFromBech32(delegations[0].DelegatorAddress)
+}

 BeforeEach(func() {
     s = i.NewCleanChain()
-    delegations, _ := s.App().StakingKeeper.GetAllDelegations(s.Ctx())
-    voter = sdk.MustAccAddressFromBech32(delegations[0].DelegatorAddress)
+    voter = s.setupTestValidator()
 })
x/multi_coin_rewards/keeper/logic_distribution_test.go (2)

73-75: Replace magic number with a named constant.

The loop uses a hardcoded value of 100 iterations. This should be extracted into a named constant for better maintainability and clarity.

+const defaultCommitIterations = 100

-for i := 0; i < 100; i++ {
+for i := 0; i < defaultCommitIterations; i++ {
     s.CommitAfterSeconds(1)
 }

214-216: Add explanatory comments for weight values.

The weight values in the test case lack explanation. Consider adding comments to clarify the expected distribution ratios.

 {
     PoolId: 0,
-    Weight: math.LegacyMustNewDecFromStr("1"), // -> 16acoin
+    Weight: math.LegacyMustNewDecFromStr("1"), // 1/3 of total weight -> 16 acoin (33.33%)
 },
 {
     PoolId: 1,
-    Weight: math.LegacyMustNewDecFromStr("2"), // -> 33acoin
+    Weight: math.LegacyMustNewDecFromStr("2"), // 2/3 of total weight -> 33 acoin (66.67%)
 },
app/app_config.go (1)

188-190: Group related module accounts together.

Consider grouping the multi-coin rewards module accounts with other related modules for better organization.

 {Account: stakerstypes.ModuleName},
+{Account: multicoinrewardstypes.ModuleName},
+{Account: multicoinrewardstypes.MultiCoinRewardsRedistributionAccountName},
 {Account: teamtypes.ModuleName},
 {Account: funderstypes.ModuleName},
-{Account: multicoinrewardstypes.ModuleName},
-{Account: multicoinrewardstypes.MultiCoinRewardsRedistributionAccountName},
proto/kyve/multi_coin_rewards/v1beta1/params.proto (1)

7-15: Params Message Definition Quality:
The new "Params" message clearly defines the fields "multi_coin_distribution_policy_admin_address" and "multi_coin_distribution_pending_time". However, the comment for "multi_coin_distribution_pending_time" is rather terse. Enhancing it with more detail on its purpose would improve clarity.

proto/kyve/multi_coin_rewards/v1beta1/events.proto (2)

10-19: EventUpdateParams Message Clarity:
The "EventUpdateParams" message is well-formed, with clear definitions for the old and new parameters as well as the payload. If further context is needed for the payload’s content, consider expanding its comment.


21-22: TODO Reminder:
There is a TODO comment to add more events. Be sure to follow up on this to cover additional event scenarios in the module.

proto/kyve/multi_coin_rewards/v1beta1/types.proto (1)

11-58: Multi-Coin Rewards Types Definition:
The message types (QueueState, MultiCoinPendingRewardsEntry, MultiCoinDistributionPolicy, MultiCoinDistributionDenomEntry, and MultiCoinDistributionPoolWeightEntry) are well-structured and make effective use of gogoproto options. Verify that field types (for example, using int64 for creation_date) satisfy the required precision and that the custom type settings align with downstream usage.

proto/kyve/multi_coin_rewards/v1beta1/tx.proto (2)

39-47: MsgToggleMultiCoinRewards Naming Consistency:
The comment preceding this message refers to "MsgEnableMultiCoinReward", which differs from the actual message name "MsgToggleMultiCoinRewards." For clarity, update the comment to accurately reflect that the message toggles the multi-coin rewards status.


52-60: MsgSetMultiCoinRewardsDistributionPolicy Clarity:
The comment for this message appears to be a copy-paste from another message (mentioning enabling rewards) rather than describing its role in setting the distribution policy. Please update it to accurately describe its purpose.

config.yml (1)

72-75: Approved: Multi-Coin Rewards Configuration Added.
The new "multi_coin_rewards" section under genesis.app_state is properly integrated with parameters for pending time and the policy admin address. Consider adding inline comments or documentation in the config to explain the purpose of each new parameter for future maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f27380 and ac2b316.

⛔ Files ignored due to path filters (10)
  • go.sum is excluded by !**/*.sum
  • go.work.sum is excluded by !**/*.sum
  • x/multi_coin_rewards/types/events.pb.go is excluded by !**/*.pb.go
  • x/multi_coin_rewards/types/genesis.pb.go is excluded by !**/*.pb.go
  • x/multi_coin_rewards/types/params.pb.go is excluded by !**/*.pb.go
  • x/multi_coin_rewards/types/query.pb.go is excluded by !**/*.pb.go
  • x/multi_coin_rewards/types/query.pb.gw.go is excluded by !**/*.pb.gw.go
  • x/multi_coin_rewards/types/tx.pb.go is excluded by !**/*.pb.go
  • x/multi_coin_rewards/types/types.pb.go is excluded by !**/*.pb.go
  • x/stakers/types/genesis.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (57)
  • api/kyve/multi_coin_rewards/module/module.pulsar.go (1 hunks)
  • app/app.go (5 hunks)
  • app/app_config.go (6 hunks)
  • app/upgrades/v2_0/store.go (1 hunks)
  • app/upgrades/v2_0/upgrade.go (3 hunks)
  • config.yml (1 hunks)
  • go.mod (4 hunks)
  • proto/kyve/multi_coin_rewards/module/module.proto (1 hunks)
  • proto/kyve/multi_coin_rewards/v1beta1/events.proto (1 hunks)
  • proto/kyve/multi_coin_rewards/v1beta1/genesis.proto (1 hunks)
  • proto/kyve/multi_coin_rewards/v1beta1/params.proto (1 hunks)
  • proto/kyve/multi_coin_rewards/v1beta1/query.proto (1 hunks)
  • proto/kyve/multi_coin_rewards/v1beta1/tx.proto (1 hunks)
  • proto/kyve/multi_coin_rewards/v1beta1/types.proto (1 hunks)
  • proto/kyve/stakers/v1beta1/genesis.proto (1 hunks)
  • testutil/integration/integration.go (2 hunks)
  • util/expected_keepers.go (1 hunks)
  • x/global/ante_test.go (1 hunks)
  • x/multi_coin_rewards/client/cli/query.go (1 hunks)
  • x/multi_coin_rewards/client/cli/query_params.go (1 hunks)
  • x/multi_coin_rewards/client/cli/tx.go (1 hunks)
  • x/multi_coin_rewards/client/cli/tx_set_multi_coin_refund_policy.go (1 hunks)
  • x/multi_coin_rewards/client/cli/tx_toggle_multi_coin_rewards.go (1 hunks)
  • x/multi_coin_rewards/genesis.go (1 hunks)
  • x/multi_coin_rewards/keeper/exported.go (1 hunks)
  • x/multi_coin_rewards/keeper/getters_compliance.go (1 hunks)
  • x/multi_coin_rewards/keeper/getters_params.go (1 hunks)
  • x/multi_coin_rewards/keeper/getters_queue.go (1 hunks)
  • x/multi_coin_rewards/keeper/grpc_query.go (1 hunks)
  • x/multi_coin_rewards/keeper/keeper.go (1 hunks)
  • x/multi_coin_rewards/keeper/keeper_suite_test.go (1 hunks)
  • x/multi_coin_rewards/keeper/logic_distribution.go (1 hunks)
  • x/multi_coin_rewards/keeper/logic_distribution_test.go (1 hunks)
  • x/multi_coin_rewards/keeper/logic_queue.go (1 hunks)
  • x/multi_coin_rewards/keeper/msg_server.go (1 hunks)
  • x/multi_coin_rewards/keeper/msg_server_distribution_policy.go (1 hunks)
  • x/multi_coin_rewards/keeper/msg_server_distribution_policy_test.go (1 hunks)
  • x/multi_coin_rewards/keeper/msg_server_toggle.go (1 hunks)
  • x/multi_coin_rewards/keeper/msg_server_toggle_test.go (1 hunks)
  • x/multi_coin_rewards/keeper/msg_server_update_params.go (1 hunks)
  • x/multi_coin_rewards/keeper/msg_server_update_params_test.go (1 hunks)
  • x/multi_coin_rewards/module.go (1 hunks)
  • x/multi_coin_rewards/types/codec.go (1 hunks)
  • x/multi_coin_rewards/types/errors.go (1 hunks)
  • x/multi_coin_rewards/types/expected_keepers.go (1 hunks)
  • x/multi_coin_rewards/types/genesis.go (1 hunks)
  • x/multi_coin_rewards/types/keys.go (1 hunks)
  • x/multi_coin_rewards/types/message_set_multi_coin_refund_policy.go (1 hunks)
  • x/multi_coin_rewards/types/message_toggle_multi_coin_rewards.go (1 hunks)
  • x/multi_coin_rewards/types/msgs.go (1 hunks)
  • x/multi_coin_rewards/types/params.go (1 hunks)
  • x/multi_coin_rewards/types/types.go (1 hunks)
  • x/query/keeper/keeper.go (3 hunks)
  • x/query/module.go (1 hunks)
  • x/stakers/genesis.go (2 hunks)
  • x/stakers/module.go (1 hunks)
  • x/stakers/types/genesis.go (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • proto/kyve/stakers/v1beta1/genesis.proto
  • x/stakers/genesis.go
  • api/kyve/multi_coin_rewards/module/module.pulsar.go
🧰 Additional context used
🪛 Buf (1.47.2)
proto/kyve/multi_coin_rewards/module/module.proto

4-4: import "cosmos/app/v1alpha1/module.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/events.proto

5-5: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/types.proto

5-5: import "amino/amino.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/params.proto

3-3: Files with package "kyve.multi_coin_rewards.v1beta1" must be within a directory "kyve/multi_coin_rewards/v1beta1" relative to root but were in directory "proto/kyve/multi_coin_rewards/v1beta1".

(PACKAGE_DIRECTORY_MATCH)

proto/kyve/multi_coin_rewards/v1beta1/tx.proto

5-5: import "cosmos/msg/v1/msg.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/query.proto

5-5: import "amino/amino.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/genesis.proto

5-5: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Summary
🔇 Additional comments (68)
x/multi_coin_rewards/keeper/keeper.go (2)

26-26: Consider validating the "authority" value.
While it’s common to store the authority as a string, adding a simple validation or sanity check (e.g., verifying whether it’s a valid address) could help detect configuration mistakes early.


81-83: Logger instantiation looks good.
Returning the logger with a "module" string is consistent with Cosmos SDK patterns. No changes needed.

x/multi_coin_rewards/keeper/getters_compliance.go (2)

20-38: Handle duplicate entries with the same index.
Overwriting existing entries might cause data corruption if "pendingRewards.Index" is reused. Consider rejecting duplicates or logging a warning.


101-111: Ensure iteration is safe for large sets.
If a large number of addresses have multi-coin rewards enabled, this loop could become expensive. Lazy pagination or a streaming approach might be more scalable.
[performance]

app/upgrades/v2_0/upgrade.go (3)

7-10: Imports organization looks consistent!

The newly added imports for multi-coin rewards and the Cosmos SDK auth modules appear properly referenced. Confirm that you need both "authkeeper" and "authTypes"; if either is unused, it could be removed to reduce redundancy.


53-53: Ensure account creation logic is invoked at upgrade.

This call to 'EnsureMultiCoinDistributionAccount' is a solid approach to guarantee the module account is established. Verify there's no possibility of repeated calls inadvertently overwriting an existing valid setup.


61-76: Robust module account creation with fallback for existing accounts.

This function ensures the correct module account is present. Some considerations:
• If the existing account isn't a module account, the code forcibly transforms it. Ensure that it doesn't inadvertently overwrite attributes unrelated to multi-coin rewards.
• Remember to handle any possible type assertions on the existing module account if needed in the future.

x/multi_coin_rewards/module.go (4)

1-30: Imports look coherent and minimal.

All imported packages are used meaningfully for module definitions, CLI commands, keeper references, and the cosmos-sdk structures. No glaring duplicates found.


46-49: Clear definition of AppModuleBasic.

The minimal struct storing the codec is consistent with Cosmos SDK module patterns. Good job keeping it concise.


123-127: Registering gRPC services.

This approach ties the Msg and Query server to the Configurator effectively. Ensure all message types are registered in 'types/msgs.go' so they can be dispatched properly.


207-229: Dependency injection setup is well-structured.

The 'ProvideModule' function neatly aggregates and configures the keeper, populating the app module outputs. This is aligned with recommended depinject patterns. Great approach to setting a default authority.

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

13-15: Proper server constructor.

'NewMsgServerImpl' cleanly installs the keeper into the 'msgServer'. Great for testability and clarity. The rest of the file is minimal and follows standard Cosmos SDK conventions.

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

9-14: LGTM! Well-designed interface with clear method signatures.

The PoolKeeper interface is well-structured with:

  • Clear method names that describe their purpose
  • Appropriate error handling for critical operations
  • Consistent use of sdk.Context across methods
app/upgrades/v2_0/store.go (1)

6-6: LGTM! Proper integration of multi-coin rewards module in store upgrades.

The changes correctly add the multi-coin rewards module to the store upgrades for v2.0.

Also applies to: 12-12

x/multi_coin_rewards/client/cli/tx.go (1)

14-27: LGTM! Clean implementation following CLI best practices.

The command is well-structured with:

  • Standard Cobra command setup
  • Appropriate validation
  • Clear subcommand organization
x/multi_coin_rewards/client/cli/query_params.go (1)

13-35: LGTM! Well-structured CLI command implementation.

The command follows the standard Cosmos SDK CLI patterns, with proper error handling and query flags.

x/multi_coin_rewards/keeper/keeper_suite_test.go (1)

17-20: LGTM! Standard test suite setup.

The test suite is properly configured with failure handling and module name.

x/multi_coin_rewards/types/msgs.go (2)

14-17: LGTM! Safe to ignore error as address is validated in ValidateBasic.

The function correctly returns the authority address as the expected signer.


20-35: LGTM! Thorough message validation.

The function follows the standard pattern for message validation and properly handles all error cases.

x/multi_coin_rewards/client/cli/query.go (1)

17-32: LGTM!

The implementation follows standard Cosmos SDK CLI patterns and correctly sets up the query command for the multi-coin rewards module.

x/multi_coin_rewards/keeper/msg_server_update_params.go (1)

28-32: LGTM!

The event emission is correctly implemented with all necessary fields.

x/multi_coin_rewards/keeper/getters_queue.go (2)

9-21: LGTM!

The GetQueueState implementation correctly handles nil state and uses MustUnmarshal for state deserialization, which is appropriate for handling invalid state by panicking.


23-29: LGTM!

The SetQueueState implementation correctly serializes and stores the state using MustMarshal.

x/multi_coin_rewards/types/params.go (2)

19-25: Verify if empty admin address is intended in DefaultParams.

Please confirm if having an empty MultiCoinDistributionPolicyAdminAddress in DefaultParams is the intended behavior. If not, consider setting a default admin address.


27-37: LGTM!

The parameter validation correctly checks for valid Bech32 addresses when an admin address is provided.

x/multi_coin_rewards/types/codec.go (3)

10-14: LGTM! Message registration follows Cosmos SDK conventions.

The message type registration follows the standard Cosmos SDK pattern, using the correct module namespace prefix "kyve/multi_coin_rewards/".


16-20: LGTM! Interface registration is properly implemented.

The implementation correctly registers all message types as implementations of the sdk.Msg interface.


22-28: LGTM! Codec initialization is complete.

The initialization properly registers all necessary codecs: legacy amino, crypto, and SDK.

x/multi_coin_rewards/client/cli/tx_toggle_multi_coin_rewards.go (2)

29-32: LGTM! Message construction is correct.

The message is properly constructed with the creator's address and the parsed boolean value.


34-36: LGTM! Basic validation is properly implemented.

The implementation correctly validates the message before broadcasting.

x/multi_coin_rewards/types/message_toggle_multi_coin_rewards.go (1)

37-43: LGTM! Basic validation is properly implemented.

The implementation correctly validates the creator's address.

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

39-45: LGTM! Key generation utilities are properly implemented.

The implementation correctly uses the util package for consistent key generation.

x/multi_coin_rewards/client/cli/tx_set_multi_coin_refund_policy.go (1)

26-29: 🛠️ Refactor suggestion

Add file path validation.

The command reads a file without validating the path. Consider adding checks for:

  • File size limits to prevent memory exhaustion
  • File extension validation (.json)
  • Path traversal protection
-			file, err := os.ReadFile(args[0])
+			// Validate file path
+			if !strings.HasSuffix(args[0], ".json") {
+				return fmt.Errorf("file must have .json extension")
+			}
+			
+			// Get file info for size check
+			fileInfo, err := os.Stat(args[0])
+			if err != nil {
+				return fmt.Errorf("failed to get file info: %w", err)
+			}
+			
+			// Limit file size (e.g., 1MB)
+			if fileInfo.Size() > 1024*1024 {
+				return fmt.Errorf("file size exceeds 1MB limit")
+			}
+			
+			file, err := os.ReadFile(args[0])
x/multi_coin_rewards/types/message_set_multi_coin_refund_policy.go (1)

20-27: ⚠️ Potential issue

Handle GetSigners error gracefully.

The GetSigners method panics on invalid address. Consider returning an error instead.

-func (msg *MsgSetMultiCoinRewardsDistributionPolicy) GetSigners() []sdk.AccAddress {
+func (msg *MsgSetMultiCoinRewardsDistributionPolicy) GetSigners() ([]sdk.AccAddress, error) {
 	creator, err := sdk.AccAddressFromBech32(msg.Creator)
 	if err != nil {
-		panic(err)
+		return nil, errors.Wrapf(errorsTypes.ErrInvalidAddress, "invalid creator address: %s", err)
 	}
 
-	return []sdk.AccAddress{creator}
+	return []sdk.AccAddress{creator}, nil
 }

Likely invalid or redundant comment.

x/multi_coin_rewards/keeper/exported.go (1)

26-27: Verify coin operations for potential panics.

The Sub operation might panic if enabledRewards contains denominations not present in coins. Add validation to ensure safe coin operations.

+	// Verify that native denom exists in coins
+	if !coins.HasDenom(globalTypes.Denom) {
+		return sdk.Coins{}
+	}
 	enabledRewards := sdk.NewCoins(sdk.NewCoin(globalTypes.Denom, coins.AmountOf(globalTypes.Denom)))
+	// Verify subtraction is valid
+	if !coins.IsAllGTE(enabledRewards) {
+		return sdk.Coins{}
+	}
 	disabledRewards := coins.Sub(enabledRewards...)
x/multi_coin_rewards/types/types.go (1)

9-51: LGTM! Well-structured implementation with thorough validation.

The implementation includes comprehensive validation checks:

  • Positive weights validation
  • Duplicate pool IDs detection
  • Weight normalization
  • Duplicate denoms prevention
x/query/keeper/keeper.go (1)

31-31: LGTM! Clean type update for distribution keeper.

The change from distrkeeper.Keeper to util.DistributionKeeper is consistent across the keeper struct and constructor.

Also applies to: 51-51

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

76-80: LGTM! Consistent field renaming in validation logic.

The update from QueueStateStateFraction to QueueStateStakeFraction is applied consistently in the validation checks.

util/expected_keepers.go (1)

24-24: LGTM!

The addition of GetAllBalances method to the BankKeeper interface aligns with the Cosmos SDK's implementation and is necessary for the multi-coin rewards module.

x/multi_coin_rewards/keeper/msg_server_distribution_policy_test.go (4)

29-50: LGTM! Test setup is comprehensive.

The test setup properly initializes a clean chain, creates a pool, and sets up a validator with the required permissions.


52-54: LGTM! Test cleanup is well-handled.

The PerformValidityChecks() after each test ensures the chain state remains valid.


56-94: LGTM! Valid test case is well-structured.

The test verifies:

  1. Policy update with multiple entries
  2. Multiple denominations (acoin, bcoin, ccoin)
  3. Different weights for pools
  4. Proper parsing of the distribution map

96-226: LGTM! Invalid test cases cover essential error scenarios.

The test suite thoroughly validates error handling for:

  1. Duplicate denomination entries
  2. Duplicate pool entries for the same denomination
  3. Negative weights
  4. Zero weights

Each test properly verifies both the error message and the policy state.

x/stakers/module.go (1)

189-189: LGTM!

The update to use util.DistributionKeeper aligns with the module's integration of the multi-coin rewards system.

x/query/module.go (1)

182-182: LGTM!

The update to use util.DistributionKeeper is consistent with the changes in other modules and supports the multi-coin rewards integration.

testutil/integration/integration.go (1)

233-233: LGTM! Good addition of ValAddress field.

The addition of the ValAddress field to TestValidatorAddress struct improves the test utility by providing easy access to validator addresses.

x/global/ante_test.go (1)

294-295: Document why BaseCost changes with implementation.

The TODO comment raises a valid question about why BaseCost changes with implementation changes. Consider documenting the factors that influence this value to help future maintainers understand the relationship between implementation changes and gas costs.

x/multi_coin_rewards/keeper/msg_server_toggle_test.go (1)

1-311: Well-structured and comprehensive test coverage!

The test suite thoroughly covers various scenarios for multi-coin rewards, including:

  • Native and foreign rewards handling
  • Mixed rewards scenarios
  • Toggle functionality
  • Claim periods and pending rewards
  • Edge cases like empty claims

The tests follow the AAA pattern and include clear assertions.

app/app.go (2)

84-85: LGTM: Clean module import.

The multi-coin rewards module is properly imported with side-effects handling.


124-124: LGTM: Consistent keeper implementation.

The changes maintain consistency in the keeper implementation:

  • DistributionKeeper is now a pointer type, aligning with other keeper types
  • MultiCoinRewardsKeeper is properly integrated into the app structure

Also applies to: 156-156

proto/kyve/multi_coin_rewards/module/module.proto (2)

7-12: LGTM: Clean module definition.

The Module message is well-defined with:

  • Clear go import path option
  • Properly documented authority field with default behavior

4-4: 💡 Verification agent

Verify the import path resolution.

The static analysis tool indicates that the import file cosmos/app/v1alpha1/module.proto does not exist. Please verify that the import path is correct and the file is available in your proto files directory.

Run this script to check the import path:

❌ Verification inconclusive

🏁 Script executed:

#!/bin/bash
# Description: Check if the proto import file exists
fd -t f "module.proto" proto/cosmos/app/v1alpha1/

Length of output: 163


Import path resolution issue detected
It appears that the repository does not contain the directory (and consequently the file) referenced by cosmos/app/v1alpha1/module.proto. The error from the initial command indicates that the search path isn’t valid, which confirms that the expected directory “proto/cosmos/app/v1alpha1/” does not exist. This matches the static analysis tool’s warning.

To further verify, please run the following script to search the entire repository for the file with the expected path:

If this script produces no output, it confirms that the file does not exist at that location. In that case, please update the import in
• proto/kyve/multi_coin_rewards/module/module.proto
to point to the correct location if the file was relocated, or remove the import if it is no longer needed.


🏁 Script executed:

#!/bin/bash
# Search for the module.proto file anywhere in the repo and filter for the expected path pattern
find . -type f | grep -E "proto/cosmos/app/v1alpha1/module.proto"

Length of output: 187


Import Path Resolution Error Detected

Based on the searches performed:

  • A search for "proto/cosmos/app/v1alpha1/module.proto" did not return any matches.
  • A repository-wide search for files named "module.proto" within paths containing "cosmos" also did not locate the expected file.

This confirms that the import statement in
• proto/kyve/multi_coin_rewards/module/module.proto
pointing to cosmos/app/v1alpha1/module.proto does not resolve to an existing file.

Please update the import to use the correct file path or remove it if the file is no longer available.

🧰 Tools
🪛 Buf (1.47.2)

4-4: import "cosmos/app/v1alpha1/module.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/params.proto (1)

1-6: ⚠️ Potential issue

Directory Structure Compliance:
The package is declared as “kyve.multi_coin_rewards.v1beta1”, yet the file is located under "proto/kyve/multi_coin_rewards/v1beta1". According to Buf guidelines, it should reside in "kyve/multi_coin_rewards/v1beta1" relative to the repository root. Consider relocating the file to ensure proper package management.

🧰 Tools
🪛 Buf (1.47.2)

3-3: Files with package "kyve.multi_coin_rewards.v1beta1" must be within a directory "kyve/multi_coin_rewards/v1beta1" relative to root but were in directory "proto/kyve/multi_coin_rewards/v1beta1".

(PACKAGE_DIRECTORY_MATCH)

proto/kyve/multi_coin_rewards/v1beta1/events.proto (1)

5-5: ⚠️ Potential issue

Verify Import of gogoproto:
The import "gogoproto/gogo.proto" is reported as not found. Please verify that the dependency is available, or update the import path accordingly.

🧰 Tools
🪛 Buf (1.47.2)

5-5: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/genesis.proto (2)

11-26: GenesisState Message Structure:
The "GenesisState" message efficiently aggregates the module’s parameters, pending rewards entries, queue state, enabled coins, and the distribution policy. Double-check that the non-nullable constraints match the module’s initialization and validation requirements.


5-5: ⚠️ Potential issue

Verify gogoproto Import:
Similar to other files, the import "gogoproto/gogo.proto" isn’t found. Confirm that the correct dependency path is referenced or update it if needed.

🧰 Tools
🪛 Buf (1.47.2)

5-5: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/types.proto (1)

5-7: ⚠️ Potential issue

Dependency Import Verification:
The import "amino/amino.proto" is flagged as not existing. Please verify the correct path for this dependency or consider removing it if it’s unnecessary. Additionally, confirm that "gogoproto/gogo.proto" is accessible.

🧰 Tools
🪛 Buf (1.47.2)

5-5: import "amino/amino.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/tx.proto (3)

11-24: Msg Service Definition:
The "Msg" service is clearly defined with RPC methods for updating parameters, toggling rewards, and setting the distribution policy. Ensure that the corresponding message handlers implement the desired functionality correctly.


26-34: MsgUpdateParams Message:
This message concisely defines an authority (with its signer option) and a payload for updating parameters. Verify that the payload’s format meets the requirements for module parameter updates.


5-7: ⚠️ Potential issue

Verify Import Paths:
The import "cosmos/msg/v1/msg.proto" is reported as not existing. Verify that the correct import paths for Cosmos SDK message definitions are used, and similarly check the "cosmos_proto/cosmos.proto" import.

🧰 Tools
🪛 Buf (1.47.2)

5-5: import "cosmos/msg/v1/msg.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/query.proto (4)

14-30: Approved: gRPC Query Service Definition.
The Query service and its RPC methods (Params, MultiCoinDistributionPolicyQuery, MultiCoinStatus) are correctly defined with the appropriate HTTP options. The overall structure aligns with Cosmos SDK standards.


5-5: ⚠️ Potential issue

Critical: Verify Import Reference.
The import of "amino/amino.proto" is flagged by static analysis as missing. Please verify that the file exists under the expected path or update the import to the correct location to avoid compilation errors.

🧰 Tools
🪛 Buf (1.47.2)

5-5: import "amino/amino.proto": file does not exist

(COMPILE)


41-44: 🛠️ Refactor suggestion

Docstring Mismatch: Request Message Comment.
The comment on line 41 labels the message as "QueryMultiCoinDistributionPolicyRequest", yet the actual message defined on line 51 is "QueryMultiCoinStatusRequest". Please update the comment or rename the message so that documentation accurately reflects the message’s intent.


56-59: 🛠️ Refactor suggestion

Docstring Mismatch: Response Message Comment.
The comment on line 56 refers to a "QueryMultiCoinDistributionPolicyResponse" while the defined message is "QueryMultiCoinStatusResponse". For clarity and consistency, update the comment to reference the correct message name.

go.mod (4)

22-22: Approved: Dependency Update for cosmos-db.
The update to "github.com/cosmos/cosmos-db v1.1.1" appears to be in line with our requirements. Please verify compatibility with the multi-coin rewards module.


45-45: Approved: Updated spf13/cast Version.
The version bump for "github.com/spf13/cast" to v1.7.1 is noted. Ensure that components relying on this library are tested for any breaking changes.


110-110: Approved: Ledger-Cosmos-Go Version Bump.
The dependency "github.com/cosmos/ledger-cosmos-go" has been updated to v0.14.0. This update should support the enhancements brought by the multi-coin rewards functionality; please run integration tests to confirm full compatibility.


373-377: Verify: Custom Cosmos SDK Replacement Directive.
The replace directive for "github.com/cosmos/cosmos-sdk" now points to "github.com/KYVENetwork/cosmos-sdk v0.50.11-kyve-rc0". This customization is critical for integrating the new multi-coin rewards module. Please verify that all interfaces from the forked SDK are compatible with the rest of the code and consider updating the inline comment with a reference to any related issue or documentation.

Copy link
Member

@troykessler troykessler left a comment

Choose a reason for hiding this comment

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

Please add the module specs and include a description of the token flow (on which module accounts the rewards are moved on which steps) and a description of the policy map so users know how to submit proposals when updating it

Copy link

@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: 3

♻️ Duplicate comments (3)
x/multi_coin_rewards/genesis.go (2)

18-23: ⚠️ Potential issue

Replace panic with proper error handling in InitGenesis.

Instead of panicking on error, return an error to allow for graceful chain initialization.

-	for _, entry := range genState.MultiCoinEnabled {
-		err := k.MultiCoinRewardsEnabled.Set(ctx, sdk.MustAccAddressFromBech32(entry))
-		if err != nil {
-			panic(err)
-		}
-	}
+	for _, entry := range genState.MultiCoinEnabled {
+		addr, err := sdk.AccAddressFromBech32(entry)
+		if err != nil {
+			return fmt.Errorf("invalid address %s in genesis state: %w", entry, err)
+		}
+		if err := k.MultiCoinRewardsEnabled.Set(ctx, addr); err != nil {
+			return fmt.Errorf("failed to set enabled address %s: %w", entry, err)
+		}
+	}

37-41: ⚠️ Potential issue

Replace panic with proper error handling in ExportGenesis.

Instead of panicking on policy retrieval error, handle it gracefully.

 	policy, err := k.MultiCoinDistributionPolicy.Get(ctx)
 	if err != nil {
-		panic(err)
+		// Log error and continue with nil policy
+		genesis.MultiCoinDistributionPolicy = nil
+	} else {
+		genesis.MultiCoinDistributionPolicy = &policy
 	}
-	genesis.MultiCoinDistributionPolicy = &policy
x/multi_coin_rewards/keeper/grpc_query.go (1)

43-43: ⚠️ Potential issue

Handle error from GetMultiCoinPendingRewardsEntriesByIndex2.

The error from GetMultiCoinPendingRewardsEntriesByIndex2 is ignored, which could mask potential issues.

-	entries, _ := k.GetMultiCoinPendingRewardsEntriesByIndex2(sdk.UnwrapSDKContext(ctx), request.Address)
+	entries, err := k.GetMultiCoinPendingRewardsEntriesByIndex2(sdk.UnwrapSDKContext(ctx), request.Address)
+	if err != nil {
+		return nil, status.Errorf(codes.Internal, "failed to get pending rewards: %v", err)
+	}
🧹 Nitpick comments (11)
x/multi_coin_rewards/keeper/keeper_suite_test.go (1)

22-31: **Use Ginkgo’s assertion instead of panicking. **

Panicking on errors prevents graceful handling during tests. Consider using Ginkgo's expectations for consistency:

 func payoutRewards(s *i.KeeperTestSuite, staker string, coins sdk.Coins) {
-	err := s.App().BankKeeper.MintCoins(s.Ctx(), mintTypes.ModuleName, coins)
-	if err != nil {
-		panic(err)
-	}
+	Expect(
+		s.App().BankKeeper.MintCoins(s.Ctx(), mintTypes.ModuleName, coins),
+	).ToNot(HaveOccurred())

-	err = s.App().StakersKeeper.PayoutRewards(s.Ctx(), staker, coins, mintTypes.ModuleName)
-	if err != nil {
-		panic(err)
-	}
+	Expect(
+		s.App().StakersKeeper.PayoutRewards(s.Ctx(), staker, coins, mintTypes.ModuleName),
+	).ToNot(HaveOccurred())
 }
x/multi_coin_rewards/types/keys.go (1)

28-29: Add missing documentation for MultiCoinDistributionPolicyKey.

The comment for MultiCoinDistributionPolicyKey is incomplete. Add a description of what this key prefix is used for.

-	// MultiCoinDistributionPolicyKey
+	// MultiCoinDistributionPolicyKey is the key prefix for storing the multi-coin distribution policy.
x/multi_coin_rewards/keeper/grpc_query.go (1)

32-55: Improve context handling in MultiCoinStatus.

The context unwrapping is inconsistent. Use unwrapped context consistently throughout the method.

 func (k Keeper) MultiCoinStatus(ctx context.Context, request *types.QueryMultiCoinStatusRequest) (*types.QueryMultiCoinStatusResponse, error) {
+	sdkCtx := sdk.UnwrapSDKContext(ctx)
+
 	account, err := sdk.AccAddressFromBech32(request.Address)
 	if err != nil {
 		return nil, err
 	}

-	has, err := k.MultiCoinRewardsEnabled.Has(ctx, account)
+	has, err := k.MultiCoinRewardsEnabled.Has(sdkCtx, account)
 	if err != nil {
 		return nil, err
 	}

-	entries, _ := k.GetMultiCoinPendingRewardsEntriesByIndex2(sdk.UnwrapSDKContext(ctx), request.Address)
+	entries, err := k.GetMultiCoinPendingRewardsEntriesByIndex2(sdkCtx, request.Address)
+	if err != nil {
+		return nil, status.Errorf(codes.Internal, "failed to get pending rewards: %v", err)
+	}
x/multi_coin_rewards/spec/03_messages.md (1)

9-10: Add missing comma for better readability.

A comma should be added after "rewards" to improve readability.

Apply this diff:

-User can enable or disable the retrieval of multi-coin-rewards. If they 
-enable multi-coin rewards all current pending rewards will be claimed.
+User can enable or disable the retrieval of multi-coin-rewards. If they 
+enable multi-coin rewards, all current pending rewards will be claimed.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~10-~10: A comma might be missing here.
Context: ...oin-rewards. If they enable multi-coin rewards all current pending rewards will be cla...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

x/multi_coin_rewards/spec/07_exported.md (1)

11-16: Fix indentation in interface documentation.

The interface is well-defined, but there are inconsistencies in the indentation (hard tabs vs spaces).

Apply this diff to use consistent indentation:

 type MultiCoinRewardsKeeper interface {
 
     // HandleMultiCoinRewards checks if the user has opted in to receive multi-coin rewards
-	// and returns the amount which can get paid out.
-	HandleMultiCoinRewards(goCtx context.Context, withdrawAddress sdk.AccAddress, coins sdk.Coins) sdk.Coins
+    // and returns the amount which can get paid out.
+    HandleMultiCoinRewards(goCtx context.Context, withdrawAddress sdk.AccAddress, coins sdk.Coins) sdk.Coins
 }
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

14-14: Hard tabs
Column: 1

(MD010, no-hard-tabs)


15-15: Hard tabs
Column: 1

(MD010, no-hard-tabs)

x/multi_coin_rewards/spec/06_events.md (1)

18-25: Add descriptive documentation for event fields.

The event fields lack proper documentation. Please add clear descriptions for each field:

 message EventToggleMultiCoinRewards {
-  // address ...
+  // address represents the account that modified their multi-coin settings
   string address = 1;

-  // enabled ...
+  // enabled indicates whether multi-coin rewards are now enabled (true) or disabled (false) for this address
   bool enabled = 2;

-  // pending_rewards_claimed ...
+  // pending_rewards_claimed represents the amount of rewards that were claimed during this operation
   string pending_rewards_claimed = 3;
 }
proto/kyve/multi_coin_rewards/v1beta1/events.proto (1)

21-31: Add descriptive documentation for event fields.

For consistency with EventUpdateParams, please add proper documentation for EventToggleMultiCoinRewards and its fields:

-// EventToggleMultiCoinRewards ...
+// EventToggleMultiCoinRewards is an event emitted when a user modifies their multi-coin reward settings.
+// emitted_by: MsgToggleMultiCoinRewards
 message EventToggleMultiCoinRewards {
-  // address ...
+  // address represents the account that modified their multi-coin settings
   string address = 1;

-  // enabled ...
+  // enabled indicates whether multi-coin rewards are now enabled (true) or disabled (false) for this address
   bool enabled = 2;

-  // pending_rewards_claimed ...
+  // pending_rewards_claimed represents the amount of rewards that were claimed during this operation
   string pending_rewards_claimed = 3;
 }
x/multi_coin_rewards/spec/02_state.md (2)

12-14: Fix grammatical error in the user opt-in description.

There's a subject-verb agreement issue in the sentence.

-The users who have opted in for multi-coin rewards are stored as a key in
-the IAVL tree. There is no value associated with it. If the key exists,
-the users has opted in.
+The users who have opted in for multi-coin rewards are stored as keys in
+the IAVL tree. There is no value associated with them. If a key exists,
+the user has opted in.
🧰 Tools
🪛 LanguageTool

[grammar] ~14-~14: It looks like you are using the wrong form of the noun or the verb. Did you mean “user has” or “users have”?
Context: ...ociated with it. If the key exists, the users has opted in. - MultiCoinRewardsEnabled: `...

(NOUN_PLURAL_HAS)


27-45: Add examples to clarify the distribution policy structure.

Consider adding examples to demonstrate how the weights are used and their impact on distribution:

Example:
```protobuf
// For instance, if USDC rewards need to be distributed:
{
  entries: [
    {
      denom: "usdc",
      pool_weights: [
        { pool_id: 1, weight: "0.7" },  // 70% to pool 1
        { pool_id: 2, weight: "0.3" }   // 30% to pool 2
      ]
    }
  ]
}

</blockquote></details>
<details>
<summary>x/multi_coin_rewards/spec/01_concepts.md (1)</summary><blockquote>

`7-14`: **Polish the introduction paragraph.**

Several grammatical improvements can be made:

```diff
-For policy reasons not everybody can or is allowed to receive, hold and 
-control other tokens. Therefore, users need to opt-in for multi-coin rewards.
+For policy reasons, not everybody can or is allowed to receive, hold, and 
+control other tokens. Therefore, users need to opt in for multi-coin rewards.
 Because users could miss the opt-in, there is a grace-period in which multi-coin
 rewards can still be retrieved after a claim. If a user does not enable 
 multi-coin rewards and does not enable it within the grace-period after a claim,
 the multi-coin rewards get re-distributed to the existing pools according to
-a distribution policy which can be modified by an admin-address which is set
+a distribution policy that can be modified by an admin address that is set
 by the governance.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~7-~7: A comma might be missing here.
Context: ...-- order: 1 --> # Concepts For policy reasons not everybody can or is allowed to rece...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[grammar] ~8-~8: The word “opt-in” is a noun. The verb is spelled with a space.
Context: ... other tokens. Therefore, users need to opt-in for multi-coin rewards. Because users c...

(NOUN_VERB_CONFUSION)

x/multi_coin_rewards/spec/04_begin_block.md (1)

7-9: Add implementation details for the redistribution process.

Consider adding more details about:

  • How the redistribution is triggered (e.g., block height calculation)
  • What happens if redistribution fails
  • Performance considerations for large numbers of coins

Example addition:

The redistribution is triggered when `block_height % 50 == 0`. The process:
1. Retrieves all coins from the module account
2. For each coin:
   - Checks if it's covered by the policy
   - If covered, distributes according to weights
   - If not covered, leaves it in the account
3. Handles any failed distributions by logging errors
🧰 Tools
🪛 LanguageTool

[uncategorized] ~7-~7: Possible missing comma found.
Context: ...-- order: 4 --> # BeginBlock Every 50 blocks all coins in the `multi_coin_rewards_di...

(AI_HYDRA_LEO_MISSING_COMMA)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac2b316 and 8d340d2.

⛔ Files ignored due to path filters (2)
  • x/multi_coin_rewards/types/events.pb.go is excluded by !**/*.pb.go
  • x/multi_coin_rewards/types/params.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (24)
  • app/app.go (5 hunks)
  • app/upgrades/v2_0/upgrade.go (4 hunks)
  • proto/kyve/multi_coin_rewards/v1beta1/events.proto (1 hunks)
  • proto/kyve/multi_coin_rewards/v1beta1/params.proto (1 hunks)
  • x/multi_coin_rewards/client/cli/query.go (1 hunks)
  • x/multi_coin_rewards/genesis.go (1 hunks)
  • x/multi_coin_rewards/keeper/getters_queue.go (1 hunks)
  • x/multi_coin_rewards/keeper/grpc_query.go (1 hunks)
  • x/multi_coin_rewards/keeper/keeper.go (1 hunks)
  • x/multi_coin_rewards/keeper/keeper_suite_test.go (1 hunks)
  • x/multi_coin_rewards/keeper/logic_distribution.go (1 hunks)
  • x/multi_coin_rewards/keeper/logic_distribution_test.go (1 hunks)
  • x/multi_coin_rewards/keeper/msg_server_toggle.go (1 hunks)
  • x/multi_coin_rewards/keeper/msg_server_update_params.go (1 hunks)
  • x/multi_coin_rewards/spec/01_concepts.md (1 hunks)
  • x/multi_coin_rewards/spec/02_state.md (1 hunks)
  • x/multi_coin_rewards/spec/03_messages.md (1 hunks)
  • x/multi_coin_rewards/spec/04_begin_block.md (1 hunks)
  • x/multi_coin_rewards/spec/05_params.md (1 hunks)
  • x/multi_coin_rewards/spec/06_events.md (1 hunks)
  • x/multi_coin_rewards/spec/07_exported.md (1 hunks)
  • x/multi_coin_rewards/types/keys.go (1 hunks)
  • x/multi_coin_rewards/types/message_set_multi_coin_refund_policy.go (1 hunks)
  • x/multi_coin_rewards/types/message_toggle_multi_coin_rewards.go (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • x/multi_coin_rewards/spec/05_params.md
🚧 Files skipped from review as they are similar to previous changes (6)
  • x/multi_coin_rewards/client/cli/query.go
  • x/multi_coin_rewards/keeper/msg_server_update_params.go
  • x/multi_coin_rewards/keeper/logic_distribution_test.go
  • x/multi_coin_rewards/keeper/getters_queue.go
  • x/multi_coin_rewards/keeper/keeper.go
  • x/multi_coin_rewards/keeper/msg_server_toggle.go
🧰 Additional context used
🧠 Learnings (1)
x/multi_coin_rewards/keeper/logic_distribution.go (1)
Learnt from: troykessler
PR: KYVENetwork/chain#244
File: x/multi_coin_rewards/keeper/logic_distribution.go:45-47
Timestamp: 2025-02-11T09:41:07.954Z
Learning: In the KYVE codebase, prefer returning errors over panicking to allow proper error handling at the BeginBlock level, especially for operations that could fail like module-to-module transfers.
🪛 LanguageTool
x/multi_coin_rewards/spec/03_messages.md

[uncategorized] ~10-~10: A comma might be missing here.
Context: ...oin-rewards. If they enable multi-coin rewards all current pending rewards will be cla...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

x/multi_coin_rewards/spec/02_state.md

[grammar] ~14-~14: It looks like you are using the wrong form of the noun or the verb. Did you mean “user has” or “users have”?
Context: ...ociated with it. If the key exists, the users has opted in. - MultiCoinRewardsEnabled: `...

(NOUN_PLURAL_HAS)

x/multi_coin_rewards/spec/01_concepts.md

[uncategorized] ~7-~7: A comma might be missing here.
Context: ...-- order: 1 --> # Concepts For policy reasons not everybody can or is allowed to rece...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[grammar] ~8-~8: The word “opt-in” is a noun. The verb is spelled with a space.
Context: ... other tokens. Therefore, users need to opt-in for multi-coin rewards. Because users c...

(NOUN_VERB_CONFUSION)


[uncategorized] ~19-~19: A comma might be missing here.
Context: ...ing on a certain weight. To allow quick updates an admin address (other than the govern...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[style] ~21-~21: Unless you want to emphasize “not”, use “cannot” which is more common.
Context: ...hich can update the policy. The address can not drain any rewards, but only modify to w...

(CAN_NOT_PREMIUM)


[duplication] ~28-~28: Possible typo: you repeated a word.
Context: ...All tokens are directly paid out to the user 2. User has not opted in: Only the native token...

(ENGLISH_WORD_REPEAT_RULE)


[uncategorized] ~31-~31: Use a comma before “and” if it connects two independent clauses (unless they are closely connected and short).
Context: ...ule account. A queue entry is created and a user has a certain amount of time to ...

(COMMA_COMPOUND_SENTENCE_2)


[duplication] ~33-~33: Possible typo: you repeated a word.
Context: ... pending rewards are transferred to the user 2. User does not enable rewards within time: Th...

(ENGLISH_WORD_REPEAT_RULE)


[uncategorized] ~37-~37: Possible missing comma found.
Context: ...distributionmodule account. Every 50 blocks all coins inmulti_coin_rewards_distri...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~39-~39: A comma might be missing here.
Context: ...olicy. If tokens are not covered by the policy they remain inside the module account. ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

x/multi_coin_rewards/spec/04_begin_block.md

[uncategorized] ~7-~7: Possible missing comma found.
Context: ...-- order: 4 --> # BeginBlock Every 50 blocks all coins in the `multi_coin_rewards_di...

(AI_HYDRA_LEO_MISSING_COMMA)

🪛 markdownlint-cli2 (0.17.2)
x/multi_coin_rewards/spec/07_exported.md

14-14: Hard tabs
Column: 1

(MD010, no-hard-tabs)


15-15: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🪛 Buf (1.47.2)
proto/kyve/multi_coin_rewards/v1beta1/events.proto

5-5: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

proto/kyve/multi_coin_rewards/v1beta1/params.proto

3-3: Files with package "kyve.multi_coin_rewards.v1beta1" must be within a directory "kyve/multi_coin_rewards/v1beta1" relative to root but were in directory "proto/kyve/multi_coin_rewards/v1beta1".

(PACKAGE_DIRECTORY_MATCH)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Summary
🔇 Additional comments (20)
proto/kyve/multi_coin_rewards/v1beta1/params.proto (1)

14-15: Complete the documentation for multi_coin_distribution_pending_time.

The comment for this field is incomplete, making it unclear what this parameter represents. Please specify:

  1. The purpose of this pending time
  2. The time unit (seconds, blocks, etc.)

Example completion:

-  // multi_coin_distribution_pending_time ...
+  // multi_coin_distribution_pending_time specifies the duration (in seconds) that must elapse
+  // before changes to coin distribution weights take effect.
   uint64 multi_coin_distribution_pending_time = 2;
x/multi_coin_rewards/keeper/logic_distribution.go (4)

11-22: **Looks good! **

The addPendingRewards function concisely handles pending rewards. Storing creation timestamps ensures predictable reward distribution timing.


25-48: **Overall logic appears correct. **

The ProcessPendingRewardsQueue function employs a queue-based approach that aligns well with the module’s design. It checks for eligible entries based on CreationDate, then collects rewards for redistribution. This design is consistent and clear.


45-47: **Return an error rather than panic. **

This mirrors a past review comment on the same lines. In the KYVE codebase, prefer returning errors to allow higher-level handlers (e.g., BeginBlock) to manage them:

-if err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, types.MultiCoinRewardsRedistributionAccountName, collectedRewards); err != nil {
-	panic(err)
+if err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, types.MultiCoinRewardsRedistributionAccountName, collectedRewards); err != nil {
+	return // or wrap the error and handle it gracefully
 }

50-128: **LGTM! **

The DistributeNonClaimedRewards flow carefully checks for invalid pools and redistributes remaining coins as per the distribution map. The approach of returning errors instead of panicking is well-aligned with Cosmos SDK best practices.

x/multi_coin_rewards/keeper/keeper_suite_test.go (1)

17-20: **No issues with the test suite initialization. **

TestMultiCoinRewardsKeeper correctly sets up Ginkgo’s test runner. The module name is referenced properly in the suite description.

x/multi_coin_rewards/types/message_toggle_multi_coin_rewards.go (3)

15-18: **Serialization logic confirmed. **

The GetSignBytes method properly marshals and sorts JSON, supporting deterministic signatures.


20-27: **Return an error or empty slice instead of panicking. **

Panicking on invalid addresses may disrupt the application flow. This was flagged in a previous review as well. Consider returning an empty slice or appropriate error:

func (msg *MsgToggleMultiCoinRewards) GetSigners() []sdk.AccAddress {
  creator, err := sdk.AccAddressFromBech32(msg.Creator)
  if err != nil {
-    panic(err)
+    // return an empty slice or handle the error gracefully
  }
  return []sdk.AccAddress{creator}
}

37-43: **Validations look good. **

ValidateBasic correctly ensures the creator’s address is valid, returning a wrapped error on failure.

app/upgrades/v2_0/upgrade.go (4)

7-10: LGTM!

The new imports are correctly added for the multi-coin rewards module and auth types.


39-40: LGTM!

The CreateUpgradeHandler function signature is correctly updated to include the accountKeeper parameter, which is required for managing module accounts.


56-56: LGTM!

The EnsureMultiCoinDistributionAccount function is correctly called during the upgrade process to ensure the module account exists.


67-82: LGTM!

The EnsureMultiCoinDistributionAccount function implementation is well-structured and handles both cases:

  1. Creating a new module account if it doesn't exist
  2. Converting an existing account to a module account if it exists

The implementation follows best practices for module account management.

app/app.go (4)

84-85: LGTM!

The multi-coin rewards module is correctly imported with side-effects and its keeper.


124-124: LGTM!

The App struct is correctly updated with:

  1. Changed DistributionKeeper to pointer type
  2. Added new MultiCoinRewardsKeeper field

Also applies to: 156-156


302-302: LGTM!

The MultiCoinRewardsKeeper is correctly initialized in the New function.


412-412: LGTM!

The AccountKeeper is correctly passed to the upgrade handler.

x/multi_coin_rewards/spec/03_messages.md (1)

14-16: LGTM!

The admin policy is clearly documented, specifying that only the governance address or a trusted entity can set the distribution policy.

x/multi_coin_rewards/spec/07_exported.md (1)

7-9: LGTM!

The module exports are clearly documented with a concise introduction.

proto/kyve/multi_coin_rewards/v1beta1/events.proto (1)

5-5: Verify the gogoproto import path.

The static analysis indicates that the gogoproto import file is not found. Please verify the import path and ensure the dependency is properly set up in the project.

❌ Verification inconclusive

🏁 Script executed:

#!/bin/bash
# Check if gogoproto is properly set up
fd -t f "gogo.proto" 

Length of output: 20


I'll proceed to re-run the file search using a different command to verify if the gogoproto/gogo.proto file exists anywhere in the repository.


🏁 Script executed:

#!/bin/bash
# Using find to search for any file named "gogo.proto" in the repository
find . -type f -name "gogo.proto"

Length of output: 33


Gogoproto Import Path Issue

  • The search commands did not return any file matching “gogo.proto” in the repository.
  • The import "gogoproto/gogo.proto" in proto/kyve/multi_coin_rewards/v1beta1/events.proto appears invalid based on the current repository contents.
  • Please verify whether the dependency is supposed to be vendored into the repository or if the import path should be updated (for example, to a full path like "github.com/gogo/protobuf/gogoproto/gogo.proto") based on your dependency management.
🧰 Tools
🪛 Buf (1.47.2)

5-5: import "gogoproto/gogo.proto": file does not exist

(COMPILE)

Copy link

@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

🧹 Nitpick comments (4)
x/multi_coin_rewards/spec/01_concepts.md (4)

7-15: Improve grammar and readability.

A few grammatical improvements would enhance readability:

  • Line 8: Replace "opt-in" (noun) with "opt in" (verb) as it's being used as a verb
  • Line 7: Add a comma after "For policy reasons"

Apply this diff:

-For policy reasons not everybody can or is allowed to receive, hold and 
-control other tokens. Therefore, users need to opt-in for multi-coin rewards.
+For policy reasons, not everybody can or is allowed to receive, hold and 
+control other tokens. Therefore, users need to opt in for multi-coin rewards.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~7-~7: Possible missing comma found.
Context: ...-- order: 1 --> # Concepts For policy reasons not everybody can or is allowed to rece...

(AI_HYDRA_LEO_MISSING_COMMA)


[grammar] ~8-~8: The word “opt-in” is a noun. The verb is spelled with a space.
Context: ... other tokens. Therefore, users need to opt-in for multi-coin rewards. Because users c...

(NOUN_VERB_CONFUSION)


16-24: Improve grammar and emphasize security boundary.

The section effectively explains the distribution policy. Consider:

  • Replace "can not" with "cannot" for better grammar
  • Consider emphasizing the security boundary of the admin role

Apply this diff:

-The address can not drain any rewards, but only modify to which
+The address cannot drain any rewards, but only modify to which

Additionally, consider adding a note about implementing proper access controls to ensure the admin address cannot exceed its intended permissions.

🧰 Tools
🪛 LanguageTool

[style] ~21-~21: Unless you want to emphasize “not”, use “cannot” which is more common.
Context: ...hich can update the policy. The address can not drain any rewards, but only modify to w...

(CAN_NOT_PREMIUM)


25-35: Improve readability of the token flow section.

Add missing punctuation to improve readability:

  • Line 31: Add a comma before "and" in the compound sentence

Apply this diff:

-   created and a user has a certain amount of time to enable multi-coin-rewards.
+   created, and a user has a certain amount of time to enable multi-coin-rewards.
🧰 Tools
🪛 LanguageTool

[duplication] ~28-~28: Possible typo: you repeated a word.
Context: ...All tokens are directly paid out to the user 2. User has not opted in: Only the native token...

(ENGLISH_WORD_REPEAT_RULE)


[uncategorized] ~31-~31: Use a comma before “and” if it connects two independent clauses (unless they are closely connected and short).
Context: ...ule account. A queue entry is created and a user has a certain amount of time to ...

(COMMA_COMPOUND_SENTENCE_2)


[duplication] ~32-~32: Possible typo: you repeated a word.
Context: ... pending rewards are transferred to the user 2. User does not enable rewards within time: Th...

(ENGLISH_WORD_REPEAT_RULE)


36-38: Add rationale for block interval and improve grammar.

Consider:

  1. Add explanation for why 50 blocks was chosen as the interval
  2. Add missing comma in the conditional statement

Apply this diff:

-If tokens are not covered by the policy they remain inside the module account.
+If tokens are not covered by the policy, they remain inside the module account.

Please verify and document:

  1. Why was 50 blocks chosen as the interval?
  2. What's the expected time duration between redistributions based on the chain's block time?
  3. Are there any performance implications of this interval?
🧰 Tools
🪛 LanguageTool

[uncategorized] ~36-~36: Possible missing comma found.
Context: ...distributionmodule account. Every 50 blocks all coins inmulti_coin_rewards_distri...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~38-~38: A comma might be missing here.
Context: ...olicy. If tokens are not covered by the policy they remain inside the module account. ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d340d2 and 11e8e2e.

📒 Files selected for processing (1)
  • x/multi_coin_rewards/spec/01_concepts.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
x/multi_coin_rewards/spec/01_concepts.md

[uncategorized] ~7-~7: Possible missing comma found.
Context: ...-- order: 1 --> # Concepts For policy reasons not everybody can or is allowed to rece...

(AI_HYDRA_LEO_MISSING_COMMA)


[grammar] ~8-~8: The word “opt-in” is a noun. The verb is spelled with a space.
Context: ... other tokens. Therefore, users need to opt-in for multi-coin rewards. Because users c...

(NOUN_VERB_CONFUSION)


[style] ~21-~21: Unless you want to emphasize “not”, use “cannot” which is more common.
Context: ...hich can update the policy. The address can not drain any rewards, but only modify to w...

(CAN_NOT_PREMIUM)


[duplication] ~28-~28: Possible typo: you repeated a word.
Context: ...All tokens are directly paid out to the user 2. User has not opted in: Only the native token...

(ENGLISH_WORD_REPEAT_RULE)


[uncategorized] ~31-~31: Use a comma before “and” if it connects two independent clauses (unless they are closely connected and short).
Context: ...ule account. A queue entry is created and a user has a certain amount of time to ...

(COMMA_COMPOUND_SENTENCE_2)


[duplication] ~32-~32: Possible typo: you repeated a word.
Context: ... pending rewards are transferred to the user 2. User does not enable rewards within time: Th...

(ENGLISH_WORD_REPEAT_RULE)


[uncategorized] ~36-~36: Possible missing comma found.
Context: ...distributionmodule account. Every 50 blocks all coins inmulti_coin_rewards_distri...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~38-~38: A comma might be missing here.
Context: ...olicy. If tokens are not covered by the policy they remain inside the module account. ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: test / test
  • GitHub Check: Summary

@troykessler troykessler self-requested a review February 13, 2025 08:46
Copy link

@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

🧹 Nitpick comments (2)
x/multi_coin_rewards/module.go (2)

150-169: Consider adding additional logging in BeginBlock.

When DistributeNonClaimedRewards fails, the only feedback is an error log. It might be helpful to also log the current block height and any relevant context to facilitate diagnosis if repeated errors occur.


159-165: Evaluate potential impact of large pending queues.

The distribution logic triggers every 50 blocks. For high-throughput networks with many pending entries, you may want to ensure that distributing non-claimed rewards doesn’t become a performance bottleneck. Consider batching or a more granular approach if the queue can grow large.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 11e8e2e and 5fed65a.

⛔ Files ignored due to path filters (2)
  • go.sum is excluded by !**/*.sum
  • go.work.sum is excluded by !**/*.sum
📒 Files selected for processing (8)
  • go.mod (4 hunks)
  • x/multi_coin_rewards/keeper/exported.go (1 hunks)
  • x/multi_coin_rewards/keeper/logic_distribution.go (1 hunks)
  • x/multi_coin_rewards/keeper/msg_server_distribution_policy_test.go (1 hunks)
  • x/multi_coin_rewards/module.go (1 hunks)
  • x/multi_coin_rewards/types/genesis.go (1 hunks)
  • x/multi_coin_rewards/types/message_set_multi_coin_refund_policy.go (1 hunks)
  • x/multi_coin_rewards/types/types.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • x/multi_coin_rewards/keeper/msg_server_distribution_policy_test.go
  • x/multi_coin_rewards/types/genesis.go
  • x/multi_coin_rewards/keeper/logic_distribution.go
  • x/multi_coin_rewards/types/message_set_multi_coin_refund_policy.go
  • go.mod
🧰 Additional context used
🧠 Learnings (1)
x/multi_coin_rewards/keeper/exported.go (1)
Learnt from: troykessler
PR: KYVENetwork/chain#244
File: x/multi_coin_rewards/keeper/exported.go:19-23
Timestamp: 2025-02-11T09:41:10.529Z
Learning: When handling errors in reward distribution, prefer returning all rewards as a fallback to prevent potential loss of funds, rather than restricting to native rewards only.
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: lint / golangci
  • GitHub Check: test / test
  • GitHub Check: Summary
🔇 Additional comments (7)
x/multi_coin_rewards/types/types.go (4)

9-15: LGTM! Well-structured type declarations.

The types are well-defined with appropriate field types and visibility for their intended use.


17-19: Improve function name and documentation.

As mentioned in a previous review, consider renaming this function to better reflect its responsibilities. Additionally, the documentation could be more detailed.

Apply this diff to improve the documentation:

-// ParseAndNormalizeMultiCoinDistributionMap turns the list structured policy map into a go map and
-// normalizes the pool weights. Due to go maps indeterminism one can not store go-maps directly in state.
+// NormalizeMultiCoinDistributionPolicy validates and normalizes the distribution policy by:
+// 1. Converting the list-structured policy into a map for efficient lookups
+// 2. Validating pool weights (positive values, no duplicates)
+// 3. Normalizing weights for each denomination
+// Note: The input policy uses a list structure since Go maps are non-deterministic
+// and cannot be stored directly in blockchain state.
+func NormalizeMultiCoinDistributionPolicy(policy MultiCoinDistributionPolicy) (MultiCoinDistributionMap, error) {

22-43: LGTM! Thorough validation and normalization logic.

The code effectively:

  • Validates positive weights
  • Prevents duplicate pool IDs
  • Correctly normalizes weights using the total

45-50: LGTM! Proper duplicate check and map population.

The code correctly prevents duplicate denominations and provides clear error messages.

x/multi_coin_rewards/module.go (1)

210-214: Verify customized authority usage.

The code defaults to the governance authority unless a custom authority is provided. Ensure that external interactions (e.g., CLI commands or other modules) consistently handle cases where a custom authority is set, to avoid unintentional errors.

x/multi_coin_rewards/keeper/exported.go (2)

20-23: Return all coins as fallback to avoid potential loss of rewards.

When an error occurs in k.MultiCoinRewardsEnabled.Has, you currently discard the distribution by returning nil, err. Per your earlier learnings, consider logging the error and returning all coins as a fallback to prevent potential loss of funds.


31-43: Confirm that globalTypes.Denom always matches the intended native token.

You subtract only globalTypes.Denom from the total coins to produce enabledRewards. In scenarios where the native denom changes or multiple native denominations exist, this logic might not behave as expected. Verify that this is aligned with your chain’s design.

@mbreithecker mbreithecker merged commit 833603e into main Feb 13, 2025
5 checks passed
@mbreithecker mbreithecker deleted the mbreithecker/multi-coin-rewards branch February 13, 2025 11:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants