Route buy prize remainder to Last Buy category #485

Merged
PlasticDigits merged 2 commits from fix/313-buy-prize-remainder-last-buy into main 2026-06-14 07:10:11 +00:00
PlasticDigits commented 2026-06-14 05:36:35 +00:00 (Migrated from gitlab.com)

Summary

  • Change ArenaBuyRouting.splitBuyAmount so amount % 4 remainder wei routes to Last Buy (cat 0) instead of WarBow (cat 3).
  • Update ArenaPrizeRouting.t.sol unit/fuzz tests, including new testFuzz_remainder_lands_on_cat0.
  • Align PARAMETERS.md, arena-v2.md, time-arena.md, fee-routing, security, and invariants docs with the approved remainder rule (#313).

Verification checklist

Acceptance item Command / evidence Result
amount % 4 wei routes to Last Buy vault/tranche test_split_remainder_to_last_buy_and_t10_tranche asserts cat 0 share = 253 for amount 1003 PASS
Fuzz proves remainder on cat 0 cd contracts && forge test --match-test testFuzz_remainder_lands_on_cat0 PASS (256 runs)
All Forge routing tests updated and pass cd contracts && forge test --match-contract ArenaPrizeRouting PASS (7/7)
Integration buy routing unchanged except remainder bucket cd contracts && forge test --match-test buy_routes PASS (2/2)
Fuzz: four category shares sum to amount exactly testFuzz_splitBuy_no_dust in ArenaPrizeRouting PASS (256 runs)
PARAMETERS.md matches code Row: remainder → Last Buy PASS
Product docs reflect Last Buy remainder rule docs/product/arena-v2.md, docs/product/time-arena.md PASS

Related issue: #313


Note

Medium Risk
Changes on-chain prize accounting for every buy when gross DOUB is not divisible by 4; scope is small and well-tested but affects real vault balances and Last Buy vs WarBow funding.

Overview
Buy prize routing now sends the amount % 4 wei from ArenaBuyRouting.splitBuyAmount to Last Buy (category 0) instead of WarBow (category 3). The 25%/25%/25%/25% split and 70/20/10 epoch tranches per category are unchanged; only which bucket gets the cross-category remainder moves.

Tests in ArenaPrizeRouting.t.sol were updated (e.g. test_split_remainder_to_last_buy_and_t10_tranche for amount 1003 → cat 0 share 253) and testFuzz_remainder_lands_on_cat0 was added so fuzz runs prove remainder always lands on cat 0 with no dust across the four categories.

Docs (PARAMETERS.md, docs/onchain/fee-routing-and-governance.md, docs/onchain/security-and-threat-model.md, product arena specs) now state the approved remainder rule for GitLab #313.

Reviewed by Cursor Bugbot for commit 24dca3ef0b. Bugbot is set up for automated code reviews on this repo. Configure here.

## Summary - Change `ArenaBuyRouting.splitBuyAmount` so `amount % 4` remainder wei routes to **Last Buy (cat 0)** instead of WarBow (cat 3). - Update `ArenaPrizeRouting.t.sol` unit/fuzz tests, including new `testFuzz_remainder_lands_on_cat0`. - Align `PARAMETERS.md`, `arena-v2.md`, `time-arena.md`, fee-routing, security, and invariants docs with the approved remainder rule ([#313](https://gitlab.com/PlasticDigits/yieldomega/-/issues/313)). ## Verification checklist | Acceptance item | Command / evidence | Result | |-----------------|-------------------|--------| | `amount % 4` wei routes to Last Buy vault/tranche | `test_split_remainder_to_last_buy_and_t10_tranche` asserts cat 0 share = 253 for amount 1003 | PASS | | Fuzz proves remainder on cat 0 | `cd contracts && forge test --match-test testFuzz_remainder_lands_on_cat0` | PASS (256 runs) | | All Forge routing tests updated and pass | `cd contracts && forge test --match-contract ArenaPrizeRouting` | PASS (7/7) | | Integration buy routing unchanged except remainder bucket | `cd contracts && forge test --match-test buy_routes` | PASS (2/2) | | Fuzz: four category shares sum to `amount` exactly | `testFuzz_splitBuy_no_dust` in ArenaPrizeRouting | PASS (256 runs) | | `PARAMETERS.md` matches code | Row: remainder → Last Buy | PASS | | Product docs reflect Last Buy remainder rule | `docs/product/arena-v2.md`, `docs/product/time-arena.md` | PASS | Related issue: [#313](https://gitlab.com/PlasticDigits/yieldomega/-/issues/313) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes on-chain prize accounting for every buy when gross DOUB is not divisible by 4; scope is small and well-tested but affects real vault balances and Last Buy vs WarBow funding. > > **Overview** > **Buy prize routing** now sends the **`amount % 4`** wei from **`ArenaBuyRouting.splitBuyAmount`** to **Last Buy (category 0)** instead of WarBow (category 3). The 25%/25%/25%/25% split and **70/20/10** epoch tranches per category are unchanged; only which bucket gets the cross-category remainder moves. > > **Tests** in **`ArenaPrizeRouting.t.sol`** were updated (e.g. **`test_split_remainder_to_last_buy_and_t10_tranche`** for amount **1003** → cat 0 share **253**) and **`testFuzz_remainder_lands_on_cat0`** was added so fuzz runs prove remainder always lands on cat 0 with no dust across the four categories. > > **Docs** (**`PARAMETERS.md`**, **`docs/onchain/fee-routing-and-governance.md`**, **`docs/onchain/security-and-threat-model.md`**, product arena specs) now state the approved remainder rule for GitLab **#313**. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 24dca3ef0b06cf7a028fb83bf435282a4e6f722a. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
project_80561744_bot_5118c68a88bff95eacb6ab1c47c19cae commented 2026-06-14 05:36:43 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
project_80561744_bot_5118c68a88bff95eacb6ab1c47c19cae commented 2026-06-14 05:36:50 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-14 05:42:58 +00:00 (Migrated from gitlab.com)

Security review — MR !485

Commit reviewed: f306d4d73939392e873232f37f9252aa0d7aeba7

Scope: ArenaBuyRouting.splitBuyAmount remainder bucket change (cat 3 → cat 0), associated Forge fuzz/unit tests, and documentation/invariant updates (#313).

Method: Diff review; traced splitBuyAmount through TimeArena._routeDoubPrizeSplit (sole on-chain caller); verified fund conservation fuzz (testFuzz_splitBuy_no_dust, testFuzz_remainder_lands_on_cat0); confirmed no indexer/frontend mirrors of category-remainder math; checked for reentrancy, access-control, overflow, and economic manipulation surfaces on the changed path.

Outcome: FINDINGS: 0 medium+

Security review: no medium+ findings on this diff.

Inline threads: none (no findings to anchor).

Notes:

  • Change is a one-line pure-math routing rule: amount % 4 remainder wei moves from WarBow (cat 3) to Last Buy (cat 0). splitPrizeTopUpAmount and tranche 70/20/10 math are unchanged.
  • Invariants hold: category shares still sum exactly to amount; _pullDoubExact ERC20 parity and nonReentrant buy guards are unchanged; remainder magnitude is bounded 0–3 wei per buy (not a meaningful theft or griefing vector).
  • Prior security-review threads on this MR: none to re-report.
## Security review — MR !485 **Commit reviewed:** `f306d4d73939392e873232f37f9252aa0d7aeba7` **Scope:** `ArenaBuyRouting.splitBuyAmount` remainder bucket change (cat 3 → cat 0), associated Forge fuzz/unit tests, and documentation/invariant updates ([#313](https://gitlab.com/PlasticDigits/yieldomega/-/issues/313)). **Method:** Diff review; traced `splitBuyAmount` through `TimeArena._routeDoubPrizeSplit` (sole on-chain caller); verified fund conservation fuzz (`testFuzz_splitBuy_no_dust`, `testFuzz_remainder_lands_on_cat0`); confirmed no indexer/frontend mirrors of category-remainder math; checked for reentrancy, access-control, overflow, and economic manipulation surfaces on the changed path. **Outcome:** `FINDINGS: 0` medium+ Security review: **no medium+ findings** on this diff. **Inline threads:** none (no findings to anchor). **Notes:** - Change is a one-line pure-math routing rule: `amount % 4` remainder wei moves from WarBow (cat 3) to Last Buy (cat 0). `splitPrizeTopUpAmount` and tranche 70/20/10 math are unchanged. - Invariants hold: category shares still sum exactly to `amount`; `_pullDoubExact` ERC20 parity and `nonReentrant` buy guards are unchanged; remainder magnitude is bounded 0–3 wei per buy (not a meaningful theft or griefing vector). - Prior security-review threads on this MR: none to re-report.
PlasticDigits commented 2026-06-14 06:54:17 +00:00 (Migrated from gitlab.com)

added 100 commits

  • f306d4d7...862964db - 99 commits from branch main
  • 24dca3ef - Merge branch 'main' into fix/313-buy-prize-remainder-last-buy

Compare with previous version

added 100 commits <ul><li>f306d4d7...862964db - 99 commits from branch <code>main</code></li><li>24dca3ef - Merge branch &#39;main&#39; into fix/313-buy-prize-remainder-last-buy</li></ul> [Compare with previous version](/PlasticDigits/yieldomega/-/merge_requests/115/diffs?diff_id=1850611226&start_sha=f306d4d73939392e873232f37f9252aa0d7aeba7)
PlasticDigits commented 2026-06-14 06:54:19 +00:00 (Migrated from gitlab.com)

Resolved merge conflicts with main (merge commit 24dca3ef).

Conflicts (6 docs): PARAMETERS.md, fee-routing-and-governance.md, security-and-threat-model.md, arena-v2.md, time-arena.md, invariants-and-business-logic.md — kept main wording (issue #313 links, #314 AdminSellVault removal, testFuzz_split_remainder_on_cat0 test name).

Cleanup: dropped duplicate testFuzz_remainder_lands_on_cat0 from ArenaPrizeRouting.t.sol (identical to testFuzz_split_remainder_on_cat0 on main).

Sanity: forge test --match-contract ArenaPrizeRouting — 7/7 PASS.

Resolved merge conflicts with `main` (merge commit `24dca3ef`). **Conflicts (6 docs):** `PARAMETERS.md`, `fee-routing-and-governance.md`, `security-and-threat-model.md`, `arena-v2.md`, `time-arena.md`, `invariants-and-business-logic.md` — kept `main` wording (issue #313 links, #314 AdminSellVault removal, `testFuzz_split_remainder_on_cat0` test name). **Cleanup:** dropped duplicate `testFuzz_remainder_lands_on_cat0` from `ArenaPrizeRouting.t.sol` (identical to `testFuzz_split_remainder_on_cat0` on `main`). **Sanity:** `forge test --match-contract ArenaPrizeRouting` — 7/7 PASS.
project_80561744_bot_5118c68a88bff95eacb6ab1c47c19cae commented 2026-06-14 06:54:41 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-06-14 06:56:52 +00:00 (Migrated from gitlab.com)

Security review — MR !485

Commit reviewed: 24dca3ef0b06cf7a028fb83bf435282a4e6f722a

Scope: ArenaBuyRouting.splitBuyAmount remainder-bucket change (category 3 → category 0 / Last Buy) in commit f306d4d7, merge-resolution with main at 24dca3ef, associated Forge fuzz/unit tests, and documentation/invariant updates (#313). Current MR diff vs base is limited to an e2e build stamp; substantive on-chain change reviewed from MR history and origin/main parity.

Method: Diff and commit-history review; traced splitBuyAmount through TimeArena._routeDoubPrizeSplit (sole on-chain caller); verified fund-conservation fuzz (testFuzz_splitBuy_no_dust, testFuzz_split_remainder_on_cat0); confirmed buy / buyWithCred nonReentrant guards and _pullDoubExact ERC20 parity unchanged; checked indexer/frontend for off-chain mirrors of category-remainder math (none).

Outcome: FINDINGS: 0 medium+

Security review: no medium+ findings on this diff.

Inline threads: none (no findings to anchor).

Notes:

  • Change is a one-line pure-math routing rule: amount % 4 remainder wei (0–3 per buy) moves from WarBow (cat 3) to Last Buy (cat 0). splitPrizeTopUpAmount and 70/20/10 tranche math are unchanged; total routed DOUB still equals amount exactly.
  • No new external-call surfaces, access-control paths, or attacker-controlled sinks beyond existing buy flows; remainder magnitude is not a meaningful theft, griefing, or MEV extraction vector.
  • Prior security-review thread on this MR (commit f306d4d7): still no medium+ findings — re-verified on 24dca3ef.
## Security review — MR !485 **Commit reviewed:** `24dca3ef0b06cf7a028fb83bf435282a4e6f722a` **Scope:** `ArenaBuyRouting.splitBuyAmount` remainder-bucket change (category 3 → category 0 / Last Buy) in commit `f306d4d7`, merge-resolution with `main` at `24dca3ef`, associated Forge fuzz/unit tests, and documentation/invariant updates ([#313](https://gitlab.com/PlasticDigits/yieldomega/-/issues/313)). Current MR diff vs base is limited to an e2e build stamp; substantive on-chain change reviewed from MR history and `origin/main` parity. **Method:** Diff and commit-history review; traced `splitBuyAmount` through `TimeArena._routeDoubPrizeSplit` (sole on-chain caller); verified fund-conservation fuzz (`testFuzz_splitBuy_no_dust`, `testFuzz_split_remainder_on_cat0`); confirmed `buy` / `buyWithCred` `nonReentrant` guards and `_pullDoubExact` ERC20 parity unchanged; checked indexer/frontend for off-chain mirrors of category-remainder math (none). **Outcome:** `FINDINGS: 0` medium+ Security review: **no medium+ findings** on this diff. **Inline threads:** none (no findings to anchor). **Notes:** - Change is a one-line pure-math routing rule: `amount % 4` remainder wei (0–3 per buy) moves from WarBow (cat 3) to Last Buy (cat 0). `splitPrizeTopUpAmount` and 70/20/10 tranche math are unchanged; total routed DOUB still equals `amount` exactly. - No new external-call surfaces, access-control paths, or attacker-controlled sinks beyond existing `buy` flows; remainder magnitude is not a meaningful theft, griefing, or MEV extraction vector. - Prior security-review thread on this MR (commit `f306d4d7`): still **no medium+ findings** — re-verified on `24dca3ef`.
PlasticDigits (Migrated from gitlab.com) merged commit 2f6522d04b into main 2026-06-14 07:10:11 +00:00
PlasticDigits commented 2026-06-14 07:10:12 +00:00 (Migrated from gitlab.com)

mentioned in commit 2f6522d04b

mentioned in commit 2f6522d04b2828b36b9a8133ea177de77d80f35e
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega!485
No description provided.