Skip to content

fix(core): preserve null gold in DonateGoldExecution constructor (#4092) - #4892

Open
berkelmali wants to merge 1 commit into
openfrontio:mainfrom
berkelmali:fix/donate-gold-null-coercion
Open

fix(core): preserve null gold in DonateGoldExecution constructor (#4092)#4892
berkelmali wants to merge 1 commit into
openfrontio:mainfrom
berkelmali:fix/donate-gold-null-coercion

Conversation

@berkelmali

Copy link
Copy Markdown
Contributor

PR 1: fix(core): preserve null gold in DonateGoldExecution constructor

Resolves #4092

Description:

In DonateGoldExecution.ts, the constructor previously initialized this.gold = toInt(goldNum ?? 0). When null was explicitly passed as goldNum (intended to trigger a default donation of 1/3 of the sender's gold), the nullish coalescing operator ?? 0 immediately converted null to 0, setting this.gold to 0n.

Consequently, in init(), the line this.gold ??= this.sender.gold() / 3n; failed to trigger because 0n is neither null nor undefined. As a result, calling DonateGoldExecution with null caused the player to donate 0 gold instead of 1/3 of their current gold balance.

This PR fixes the constructor to preserve null when goldNum is null:

this.gold = goldNum !== null ? toInt(goldNum) : null;

This allows init() to correctly evaluate this.gold ??= this.sender.gold() / 3n and donate 1/3 of the sender's gold.

Please complete the following:

  • I have added screenshots for all UI updates (N/A — Backend execution logic fix)
  • I process any text displayed to the user through translateText() and I've added it to the en.json file (N/A — No new user-facing strings)
  • I have added relevant tests to the test directory (tests/Donate.test.ts)
  • I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced

Please put your Discord username so you can be contacted if a bug or regression is found:

barfires

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

DonateGoldExecution now preserves null donation amounts so initialization can calculate the donation dynamically. A test verifies that the recipient receives at least one-third of the donor’s pre-donation gold.

Changes

Gold donation flow

Layer / File(s) Summary
Preserve and validate dynamic donation amounts
src/core/execution/DonateGoldExecution.ts, tests/Donate.test.ts
The execution retains null instead of converting it to zero. Non-null amounts still use integer conversion. The test covers the default donation calculation.
Estimated code review effort: 2 (Simple) ~10 minutes

Possibly related PRs

Suggested labels: Gameplay

Suggested reviewers: aotumuri

Poem

Null waits in the queue,
Gold divides when the tick arrives,
Allies share the gain.
Zero stays away,
Tests guard the golden path.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the core fix: preserving null gold in DonateGoldExecution.
Description check ✅ Passed The description accurately explains the constructor bug, the dynamic donation behavior, and the added test.
Linked Issues check ✅ Passed The changes preserve the null sentinel, restore dynamic one-third donation calculation, and retain non-null conversion as required by issue #4092.
Out of Scope Changes check ✅ Passed The changes are limited to the DonateGoldExecution constructor and a focused regression test for issue #4092.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch

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.

@github-actions github-actions Bot added the small-fix Small fix (≤ 50 lines) — auto-applied by PR gate label Aug 6, 2026

@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)
tests/Donate.test.ts (1)

141-143: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Make the test cover deferred calculation timing.

Line 143 constructs DonateGoldExecution after the donor balance is set. A regression that calculates the default amount in the constructor would pass this test. Construct the execution before changing the donor balance, then enqueue it after the change. Assert against the post-change balance to verify that init() uses the current gold.

Proposed test adjustment
-    donor.addGold(9000n);
+    const donation = new DonateGoldExecution(donor, rInfo.id, null);
+    donor.addGold(9000n);
     const goldBefore = donor.gold(), recBefore = recipient.gold();
-    game.addExecution(new DonateGoldExecution(donor, rInfo.id, null));
+    game.addExecution(donation);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Donate.test.ts` around lines 141 - 143, Update the test around
DonateGoldExecution to construct the execution before the donor balance is
changed, then add gold and enqueue the existing execution afterward. Assert the
recipient and donor balances using the post-change gold amount, verifying that
DonateGoldExecution.init() calculates the default donation at execution time
rather than construction time.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/Donate.test.ts`:
- Around line 141-143: Update the test around DonateGoldExecution to construct
the execution before the donor balance is changed, then add gold and enqueue the
existing execution afterward. Assert the recipient and donor balances using the
post-change gold amount, verifying that DonateGoldExecution.init() calculates
the default donation at execution time rather than construction time.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2e19fdee-c874-4f9f-af6b-915d61c993c3

📥 Commits

Reviewing files that changed from the base of the PR and between 5ed8bff and 72c2eef.

📒 Files selected for processing (2)
  • src/core/execution/DonateGoldExecution.ts
  • tests/Donate.test.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

small-fix Small fix (≤ 50 lines) — auto-applied by PR gate

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

[Bug / UX] Quick-donate sends 0 gold silently — null sentinel coerced to 0 in DonateGoldExecution constructor breaks dynamic donation contract

1 participant