Skip to content

fix: ensure reward community pool has funds#305

Merged
Thaleszh merged 12 commits into
mainfrom
fix/reward-community-pool-funds
Apr 2, 2026
Merged

fix: ensure reward community pool has funds#305
Thaleszh merged 12 commits into
mainfrom
fix/reward-community-pool-funds

Conversation

@Thaleszh

@Thaleszh Thaleszh commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Description

Ensures that the community pool has enough funds before taking from it.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

Has a regression test

PR Checklist:

Make sure each step was done:

  • Updated changelog with PR's intent
  • Lint with make lint-fix

@Thaleszh Thaleszh requested a review from jhelison as a code owner April 1, 2026 14:17
@coderabbitai

coderabbitai Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

BeginBlocker in x/rewards was changed to stop propagating errors for scheduled releases: failures are logged and the release schedule is marked inactive via a new Keeper.haltSchedule helper instead of returning errors. A pre-transfer check validates the community pool has sufficient balance per denom and SafeSub is used to avoid negative balances, halting the schedule on insufficiency. InitGenesis now logs a consistency check comparing the module bank balance to the genesis CommunityPool amount. A test was added that asserts schedules are halted when community funds are insufficient. The BankKeeper interface gained GetBalance.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: ensuring the community pool has sufficient funds before distributing rewards, which is the core issue addressed throughout the changeset.
Description check ✅ Passed The description directly relates to the changeset by stating the PR ensures the community pool has enough funds before taking from it, which aligns with all the code modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/reward-community-pool-funds

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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Apr 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 24 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
x/rewards/keeper/abci.go 0.00% 13 Missing ⚠️
x/rewards/keeper/genesis.go 0.00% 11 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@x/rewards/keeper/abci_test.go`:
- Around line 179-182: The insufficient-funds error-path returns immediately
after asserting an error but doesn't verify that state wasn't mutated; before
invoking the tested call in the test table row capture the pre-call state (fee
collector balance via bank keeper GetBalance using the fee collector module
account/address, and any relevant reward pool/schedule via keeper.GetRewardPool
/ keeper.GetSchedule or the corresponding getters used elsewhere in this test
file), then when tc.expectedError is true assert err is non-nil and assert the
post-call fee collector balance and reward pool/schedule equal the captured
pre-call values (replace the early return with these additional assertions) so
the test name "without transfer" is validated.

In `@x/rewards/keeper/genesis.go`:
- Around line 24-39: The code currently logs a mismatch between the module bank
balance and CommunityPool (denom := data.Params.TokenDenom, moduleAddr :=
authtypes.NewModuleAddress(types.ModuleName), bankBalance :=
k.bankKeeper.GetBalance(...), poolAmount :=
data.RewardPool.CommunityPool.AmountOf(denom).TruncateInt()) but continues;
change this to hard-fail during genesis initialization by replacing the
k.Logger(ctx).Error call with a panic (or return a genesis validation error)
that includes a clear message and the denom, bank_balance and community_pool
values so genesis aborts on mismatch rather than allowing corrupt state to
proceed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a7d3c679-6bcd-41aa-8821-cfa873a4485b

📥 Commits

Reviewing files that changed from the base of the PR and between 2c96c69 and 055dada.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • x/rewards/keeper/abci.go
  • x/rewards/keeper/abci_test.go
  • x/rewards/keeper/genesis.go
  • x/rewards/types/expected_keepers.go

Comment thread x/rewards/keeper/abci_test.go Outdated
Comment thread x/rewards/keeper/genesis.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
x/rewards/keeper/abci.go (1)

57-63: Prefer reusing existing Keeper.fundsAvailable check to avoid rule drift.

Line [57]–Line [63] duplicates the same community-pool sufficiency logic already implemented in x/rewards/keeper/validation.go (Line 48–Line 63). Calling that helper here would keep validation behavior/messages centralized.

Refactor sketch
-	// Verify the CommunityPool has sufficient balance for the denom before transferring
-	poolAmount := rewardPool.CommunityPool.AmountOf(amountToDistribute.Denom)
-	if math.LegacyNewDecFromInt(amountToDistribute.Amount).GT(poolAmount) {
-		return fmt.Errorf("community pool has insufficient balance for %s: pool has %s, need %s",
-			amountToDistribute.Denom, poolAmount, amountToDistribute.Amount)
-	}
+	// Verify the CommunityPool has sufficient balance before transferring
+	if err := k.fundsAvailable(ctx, amountToDistribute); err != nil {
+		return err
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@x/rewards/keeper/abci.go` around lines 57 - 63, Replace the duplicated
community-pool sufficiency check with a call to the existing
Keeper.fundsAvailable helper in validation.go; locate the check in abci.go
around the block that inspects rewardPool.CommunityPool and remove it, then call
k.fundsAvailable(...) with the same context, reward pool and amount/denom
parameters used in validation.go and return its error (or wrap it) so messages
and logic remain centralized and consistent with the validation helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@x/rewards/keeper/abci.go`:
- Around line 57-63: Replace the duplicated community-pool sufficiency check
with a call to the existing Keeper.fundsAvailable helper in validation.go;
locate the check in abci.go around the block that inspects
rewardPool.CommunityPool and remove it, then call k.fundsAvailable(...) with the
same context, reward pool and amount/denom parameters used in validation.go and
return its error (or wrap it) so messages and logic remain centralized and
consistent with the validation helper.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9ff1319f-e4bd-4db8-ac06-31b6ae771a83

📥 Commits

Reviewing files that changed from the base of the PR and between 055dada and 1c6f23a.

📒 Files selected for processing (2)
  • x/rewards/keeper/abci.go
  • x/rewards/keeper/genesis.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • x/rewards/keeper/genesis.go

Comment thread x/rewards/keeper/genesis.go
Comment thread x/rewards/keeper/abci.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
x/rewards/keeper/abci.go (1)

68-85: ⚠️ Potential issue | 🔴 Critical

Check the actual module balance before sending.

This guard still reads rewardPool.CommunityPool, but Line 76 spends the rewards module account via bankKeeper. If those drift, SendCoinsFromModuleToModule can still return an insufficient-funds error and BeginBlocker will still bubble it up, which reintroduces the chain-halt path this fix is trying to remove. Use bankKeeper.GetBalance on the module account for the insufficiency check, and compute the SafeSub result before the bank send.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@x/rewards/keeper/abci.go` around lines 68 - 85, The current check reads
rewardPool.CommunityPool but the actual spend happens via
k.bankKeeper.SendCoinsFromModuleToModule, so first compute the SafeSub result
using
rewardPool.CommunityPool.SafeSub(sdk.NewDecCoinsFromCoins(coinsToDistribute...))
and bail with k.haltSchedule(...) if hasNeg is true, then verify the module
account's actual bank balance by calling k.bankKeeper.GetBalance(ctx,
types.ModuleName, amountToDistribute.Denom) (use that balance for the
insufficiency check instead of rewardPool.CommunityPool), and only after both
checks succeed call k.bankKeeper.SendCoinsFromModuleToModule(ctx,
types.ModuleName, k.feeCollectorName, coinsToDistribute); this ensures you catch
both logical subtraction and on-chain module-account insufficiency before
attempting the bank send (reference rewardPool.CommunityPool, SafeSub,
amountToDistribute, coinsToDistribute, k.bankKeeper.GetBalance,
k.bankKeeper.SendCoinsFromModuleToModule, and k.haltSchedule).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@x/rewards/keeper/abci.go`:
- Around line 19-22: The current code has a redundant if-return branch around
k.ReleaseSchedule.Set in abci.go; replace the if block with a direct return of
the call by changing the block that checks setErr := k.ReleaseSchedule.Set(ctx,
schedule) and returns setErr on error followed by return nil to a single line:
return k.ReleaseSchedule.Set(ctx, schedule), ensuring no other logic is lost.

---

Duplicate comments:
In `@x/rewards/keeper/abci.go`:
- Around line 68-85: The current check reads rewardPool.CommunityPool but the
actual spend happens via k.bankKeeper.SendCoinsFromModuleToModule, so first
compute the SafeSub result using
rewardPool.CommunityPool.SafeSub(sdk.NewDecCoinsFromCoins(coinsToDistribute...))
and bail with k.haltSchedule(...) if hasNeg is true, then verify the module
account's actual bank balance by calling k.bankKeeper.GetBalance(ctx,
types.ModuleName, amountToDistribute.Denom) (use that balance for the
insufficiency check instead of rewardPool.CommunityPool), and only after both
checks succeed call k.bankKeeper.SendCoinsFromModuleToModule(ctx,
types.ModuleName, k.feeCollectorName, coinsToDistribute); this ensures you catch
both logical subtraction and on-chain module-account insufficiency before
attempting the bank send (reference rewardPool.CommunityPool, SafeSub,
amountToDistribute, coinsToDistribute, k.bankKeeper.GetBalance,
k.bankKeeper.SendCoinsFromModuleToModule, and k.haltSchedule).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3f5bd6db-e078-4441-b86d-9241f310a333

📥 Commits

Reviewing files that changed from the base of the PR and between 489ae43 and 9f90089.

📒 Files selected for processing (2)
  • x/rewards/keeper/abci.go
  • x/rewards/keeper/abci_test.go
✅ Files skipped from review due to trivial changes (1)
  • x/rewards/keeper/abci_test.go

Comment thread x/rewards/keeper/abci.go Outdated
jhelison
jhelison previously approved these changes Apr 2, 2026
@Thaleszh Thaleszh force-pushed the fix/reward-community-pool-funds branch from 6a60602 to 00365a3 Compare April 2, 2026 19:49
@Thaleszh Thaleszh merged commit ee8abf8 into main Apr 2, 2026
9 of 10 checks passed
@Thaleszh Thaleszh deleted the fix/reward-community-pool-funds branch April 2, 2026 20:13
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.

2 participants