Skip to content

feat(rewards): dynamic campaign reward pool rebalancing - #1396

Merged
joelpeace48-cell merged 2 commits into
FinesseStudioLab:mainfrom
presidojay1:feat/1186-reward-pool-rebalance
Sep 25, 2026
Merged

joelpeace48-cell merged 2 commits into
FinesseStudioLab:mainfrom
presidojay1:feat/1186-reward-pool-rebalance

Conversation

@presidojay1

@presidojay1 presidojay1 commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds dynamic reward pool rebalancing to the rewards contract. An admin can move unspent rewards from an underperforming campaign track to a high-demand one in the same suite.

It builds on the existing per-campaign supply cap from #903 (CAMPAIGN_CAP / CAMPAIGN_ISSUED). A campaign's reward pool is its cap, and the unspent part is cap - issued. Rebalancing moves that unspent headroom between campaigns.

Changes (contracts/rewards/src/lib.rs)

rebalance_campaign_pool(admin, from_campaign, to_campaign, amount)

  • Admin only, via the existing require_admin.
  • Lowers from_campaign's cap by amount and raises to_campaign's cap by the same amount. The combined pool is unchanged, and rewards that were already issued are never touched.
  • Checks and the errors they return (all existing variants, so no changes to the error enum):
    • ZeroAmount: amount == 0.
    • InvalidSupplyCap: from == to, or either campaign is uncapped (cap 0 means unlimited, so there is no fixed pool to move).
    • CampaignSupplyCapExceeded: amount is more than the source's unspent pool, so issued rewards can't be moved.
    • Overflow: the destination cap would overflow u64 (checked_add).
  • Extends the instance TTL, like set_campaign_supply_cap does.
  • Emits (poolrbal, from, to) → (amount, new_from_cap, new_to_cap) so indexers can follow reallocations.

campaign_unspent_supply(campaign_id) -> u64

  • A view returning cap - issued, or 0 for uncapped campaigns.

Like set_campaign_supply_cap, rebalancing is an admin config change and is not blocked by pause.

Tests (contracts/rewards/src/pool_rebalance_test.rs)

  • It moves the pool and keeps the combined total unchanged.
  • It can't move rewards already issued (checked after crediting 700 of a 1,000 cap).
  • It rejects a zero amount, the same campaign, and uncapped source or destination.
  • It rejects a non-admin caller, and the state is unchanged afterwards.
  • It rejects a destination cap that would overflow.

Closes #1186
Closes #1187
Closes #1188
Closes #1189

presidojay1 and others added 2 commits September 26, 2026 00:31
rebalance_campaign_pool (admin) moves unspent supply-cap headroom from
one capped campaign to another, never touching issued rewards, and
emits a poolrbal event. campaign_unspent_supply exposes cap - issued.

Refs FinesseStudioLab#1186

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conservation of the combined pool, issued rewards cannot move, zero /
same / uncapped campaigns, non-admin, and destination cap overflow.

Closes FinesseStudioLab#1186

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@drips-wave

drips-wave Bot commented Sep 25, 2026

Copy link
Copy Markdown

@presidojay1 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@joelpeace48-cell
joelpeace48-cell merged commit 351b59d into FinesseStudioLab:main Sep 25, 2026
8 of 24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants