Fix buyWithCred to contribute 35 CRED to epoch pool per buy #311

Closed
opened 2026-06-13 07:34:17 +00:00 by PlasticDigits · 21 comments
PlasticDigits commented 2026-06-13 07:34:17 +00:00 (Migrated from gitlab.com)

Parent

Gap analysis follow-up from #309.

Current codebase

  • DOUB buy calls _accrueCharmAndCred → epochCredPool[ep] += CRED_PER_BUY (35e18) plus CHARM weight (TimeArena.sol L690–694).
  • CRED buyWithCred calls _accrueCharmOnly — adds epochCharmWad but does not contribute to epochCredPool (TimeArena.sol L553–563, L711–717).
  • Invariant INV-TIME-ARENA-CRED-NO-POOL documents current behavior; tests in TimeArena.t.sol assert pool unchanged after buyWithCred.

Why needed

Approved: CRED buys should add 35 CRED to the epoch pool and generate CHARM (claimable by charm holders). Buys purchase CHARM; CHARM utility is claiming CRED. Current dilution lets CRED-only buyers claim pro-rata from DOUB-funded pools.

Constraints / guardrails

  • CRED_PER_BUY = 35e18 constant unchanged unless spec explicitly revises.
  • buyWithCred still burns/spends player CRED; only pool accrual changes.
  • Preserve INV-TIME-ARENA-CRED-NO-POOL semantics inversion — update invariant doc after fix.
  • CHARM accrual path must remain consistent with DOUB buys.

Relevant files

  • contracts/src/arena/TimeArena.sol — buyWithCred, _accrueCharmOnly, _accrueCharmAndCred, epochCredPool
  • contracts/test/TimeArena.t.sol — test_buy_with_cred, test_cred_accrue_on_doub_buy
  • docs/testing/invariants-and-business-logic.md — CRED pool invariants
  • bash scripts/verify-cred-buy-anvil.sh
  1. On buyWithCred, accrue both CHARM weight and CRED_PER_BUY into epochCredPool for the active epoch (mirror DOUB buy pool contribution).
  2. Update/rename invariant to reflect intentional economics.
  3. Add explicit test: after buyWithCred, epochCredPool increases by 35e18 and CRED claim pro-rata is fair.

Acceptance criteria

  • Each buyWithCred adds 35 CRED to epochCredPool[epoch].
  • CHARM weight accrual unchanged in intent.
  • claimCred pro-rata math fair for mixed DOUB/CRED buyers.
  • Invariant doc updated; old CRED-NO-POOL removed or revised.

Test plan

  • cd contracts && forge test --match-test cred / buy_with_cred.
  • bash scripts/verify-cred-buy-anvil.sh.
  • cd indexer && cargo test if indexer decodes pool-related fields.

Attack / abuse test plan

  • CRED-only buyer cannot extract more than fair share after fix.
  • Epoch boundary: buyWithCred at roll boundary credits correct epoch pool.
  • Double-claim: claimCred still one-shot per epoch per wallet.

Verification criteria

  • Forge test explicitly asserts epochCredPool delta after buyWithCred.
  • verify-cred-buy-anvil.sh PASS.
  • No economic regression in test_cred_accrue_on_doub_buy mixed scenarios.
## Parent Gap analysis follow-up from [#309](https://gitlab.com/PlasticDigits/yieldomega/-/issues/309). ## Current codebase - DOUB `buy` calls `_accrueCharmAndCred` → `epochCredPool[ep] += CRED_PER_BUY` (35e18) plus CHARM weight (`TimeArena.sol` L690–694). - CRED `buyWithCred` calls `_accrueCharmOnly` — adds `epochCharmWad` but **does not** contribute to `epochCredPool` (`TimeArena.sol` L553–563, L711–717). - Invariant `INV-TIME-ARENA-CRED-NO-POOL` documents current behavior; tests in `TimeArena.t.sol` assert pool unchanged after `buyWithCred`. ## Why needed Approved: CRED buys should add 35 CRED to the epoch pool and generate CHARM (claimable by charm holders). Buys purchase CHARM; CHARM utility is claiming CRED. Current dilution lets CRED-only buyers claim pro-rata from DOUB-funded pools. ## Constraints / guardrails - `CRED_PER_BUY = 35e18` constant unchanged unless spec explicitly revises. - `buyWithCred` still burns/spends player CRED; only pool accrual changes. - Preserve `INV-TIME-ARENA-CRED-NO-POOL` semantics inversion — update invariant doc after fix. - CHARM accrual path must remain consistent with DOUB buys. ## Relevant files - `contracts/src/arena/TimeArena.sol` — `buyWithCred`, `_accrueCharmOnly`, `_accrueCharmAndCred`, `epochCredPool` - `contracts/test/TimeArena.t.sol` — `test_buy_with_cred`, `test_cred_accrue_on_doub_buy` - `docs/testing/invariants-and-business-logic.md` — CRED pool invariants - `bash scripts/verify-cred-buy-anvil.sh` ## Recommended direction 1. On `buyWithCred`, accrue both CHARM weight **and** `CRED_PER_BUY` into `epochCredPool` for the active epoch (mirror DOUB buy pool contribution). 2. Update/rename invariant to reflect intentional economics. 3. Add explicit test: after `buyWithCred`, `epochCredPool` increases by 35e18 and CRED claim pro-rata is fair. ## Acceptance criteria - [ ] Each `buyWithCred` adds 35 CRED to `epochCredPool[epoch]`. - [ ] CHARM weight accrual unchanged in intent. - [ ] `claimCred` pro-rata math fair for mixed DOUB/CRED buyers. - [ ] Invariant doc updated; old `CRED-NO-POOL` removed or revised. ## Test plan - `cd contracts && forge test --match-test cred` / `buy_with_cred`. - `bash scripts/verify-cred-buy-anvil.sh`. - `cd indexer && cargo test` if indexer decodes pool-related fields. ## Attack / abuse test plan - CRED-only buyer cannot extract more than fair share after fix. - Epoch boundary: `buyWithCred` at roll boundary credits correct epoch pool. - Double-claim: `claimCred` still one-shot per epoch per wallet. ## Verification criteria - Forge test explicitly asserts `epochCredPool` delta after `buyWithCred`. - `verify-cred-buy-anvil.sh` PASS. - No economic regression in `test_cred_accrue_on_doub_buy` mixed scenarios.
PlasticDigits commented 2026-06-13 07:34:43 +00:00 (Migrated from gitlab.com)

mentioned in issue #309

mentioned in issue #309
PlasticDigits commented 2026-06-13 08:05:15 +00:00 (Migrated from gitlab.com)

mentioned in merge request !460

mentioned in merge request !460
PlasticDigits commented 2026-06-13 09:28:50 +00:00 (Migrated from gitlab.com)

mentioned in commit 621957a6ec

mentioned in commit 621957a6ec058508c265e96ccbe743372fe004af
PlasticDigits commented 2026-06-13 12:58:34 +00:00 (Migrated from gitlab.com)

mentioned in commit 28fbbba370

mentioned in commit 28fbbba37045376e6af1aac1cc6700db0c483a28
PlasticDigits commented 2026-06-13 12:58:38 +00:00 (Migrated from gitlab.com)

mentioned in merge request !465

mentioned in merge request !465
project_80561744_bot_5118c68a88bff95eacb6ab1c47c19cae commented 2026-06-13 13:36:08 +00:00 (Migrated from gitlab.com)

mentioned in merge request !475

mentioned in merge request !475
PlasticDigits commented 2026-06-13 14:12:28 +00:00 (Migrated from gitlab.com)

mentioned in commit bc74435db9

mentioned in commit bc74435db9558298f2bd32140f3ed74867a9dcc5
PlasticDigits commented 2026-06-13 14:12:32 +00:00 (Migrated from gitlab.com)

mentioned in merge request !466

mentioned in merge request !466
PlasticDigits commented 2026-06-13 14:15:39 +00:00 (Migrated from gitlab.com)

mentioned in commit f68da432b9

mentioned in commit f68da432b949c07905d0162dd87020c4e991b9fa
PlasticDigits commented 2026-06-14 02:41:04 +00:00 (Migrated from gitlab.com)

mentioned in commit 9d384bf7f1

mentioned in commit 9d384bf7f1cfdf16a14b695e65f36fa6d1115a6f
PlasticDigits commented 2026-06-14 02:49:54 +00:00 (Migrated from gitlab.com)

mentioned in commit 7d862aafa1

mentioned in commit 7d862aafa1db0a44eb185681f39753d39694c0d5
PlasticDigits commented 2026-06-14 02:50:10 +00:00 (Migrated from gitlab.com)

mentioned in merge request !479

mentioned in merge request !479
PlasticDigits commented 2026-06-14 02:53:35 +00:00 (Migrated from gitlab.com)

mentioned in commit ac639db066

mentioned in commit ac639db066fab289e33d02b0b95b1322a3cd0b85
PlasticDigits commented 2026-06-14 02:53:37 +00:00 (Migrated from gitlab.com)

mentioned in merge request !476

mentioned in merge request !476
PlasticDigits commented 2026-06-14 05:07:40 +00:00 (Migrated from gitlab.com)

mentioned in commit 08492fd892

mentioned in commit 08492fd892d9ced7a6624a9a96850465f9dfaa1e
PlasticDigits commented 2026-06-14 05:58:03 +00:00 (Migrated from gitlab.com)

mentioned in merge request !491

mentioned in merge request !491
PlasticDigits commented 2026-06-14 06:56:15 +00:00 (Migrated from gitlab.com)

mentioned in commit 8ee5e455ac

mentioned in commit 8ee5e455ac7e096c3532a1b2c2eb273e4eebefa7
PlasticDigits commented 2026-06-14 06:56:34 +00:00 (Migrated from gitlab.com)

mentioned in merge request !486

mentioned in merge request !486
PlasticDigits commented 2026-06-14 06:57:48 +00:00 (Migrated from gitlab.com)

mentioned in commit 7fffda6109

mentioned in commit 7fffda6109c7252debe41fa5437b1e6ebe725358
PlasticDigits commented 2026-06-14 07:12:09 +00:00 (Migrated from gitlab.com)

mentioned in commit 1b4f62603a

mentioned in commit 1b4f62603ad71a96e2acde0b5efc0f0d7b33a6dd
PlasticDigits commented 2026-06-14 14:09:41 +00:00 (Migrated from gitlab.com)

Verification — #311 (PASS)

Verified buyWithCred contributes 35 CRED (CRED_PER_BUY) to epochCredPool per buy, matching DOUB buy pool economics.

Acceptance criteria

Criterion Result How verified
Each buyWithCred adds 35 CRED to epochCredPool[epoch] PASS TimeArena._buyCred calls _accrueCharmAndCred (L566); pool += CRED_PER_BUY (L700). Forge: test_buy_with_cred, test_buyWithCred_accrues_epoch_cred_pool. Anvil: verify-cred-buy-anvil.sh asserts pool_delta == 35e18.
CHARM weight accrual unchanged in intent PASS Same _accrueCharmAndCred path as DOUB buys (codeHash = 0, no referral). test_xp_buy_with_cred_same_as_doub PASS.
claimCred pro-rata fair for mixed DOUB/CRED buyers PASS test_buyWithCred_mixed_pro_rata_with_doub, test_cred_only_buyer_fair_share, test_cred_pro_rata_mixed_doub_and_cred_buyers PASS.
Invariant doc updated; CRED-NO-POOL superseded PASS INV-TIME-ARENA-CRED-POOL-ACCRUE / INV-TIME-ARENA-CRED-POOL-PARITY in docs/testing/invariants-and-business-logic.md; skills/play-time-arena-doub/SKILL.md updated.

Test plan

Command Result
cd contracts && forge test --match-test cred PASS — 19 tests (16 TimeArena + 3 BuyRouter)
cd contracts && forge test --match-test buy_with_cred PASS — 2 tests
bash scripts/verify-cred-buy-anvil.sh PASS — === verify-cred-buy-anvil: OK ===
cd indexer && cargo test PASS — 69 tests (unit + integration_stage2)

Attack / abuse

Scenario Result Test
CRED-only buyer cannot over-claim PASS test_cred_only_buyer_fair_share
Epoch boundary credits correct pool PASS test_buyWithCred_epoch_boundary_credits_correct_pool, test_cred_accrue_buyWithCred_at_epoch_boundary
Double-claim still one-shot PASS test_claim_cred_* suite (no regression)
DOUB buy economics unchanged PASS test_cred_accrue_on_doub_buy

No repo changes required; closing as verified on main.

## Verification — #311 (PASS) Verified **`buyWithCred`** contributes **35 CRED** (`CRED_PER_BUY`) to `epochCredPool` per buy, matching DOUB buy pool economics. ### Acceptance criteria | Criterion | Result | How verified | |-----------|--------|--------------| | Each `buyWithCred` adds 35 CRED to `epochCredPool[epoch]` | **PASS** | `TimeArena._buyCred` calls `_accrueCharmAndCred` (L566); pool += `CRED_PER_BUY` (L700). Forge: `test_buy_with_cred`, `test_buyWithCred_accrues_epoch_cred_pool`. Anvil: `verify-cred-buy-anvil.sh` asserts `pool_delta == 35e18`. | | CHARM weight accrual unchanged in intent | **PASS** | Same `_accrueCharmAndCred` path as DOUB buys (`codeHash = 0`, no referral). `test_xp_buy_with_cred_same_as_doub` PASS. | | `claimCred` pro-rata fair for mixed DOUB/CRED buyers | **PASS** | `test_buyWithCred_mixed_pro_rata_with_doub`, `test_cred_only_buyer_fair_share`, `test_cred_pro_rata_mixed_doub_and_cred_buyers` PASS. | | Invariant doc updated; `CRED-NO-POOL` superseded | **PASS** | `INV-TIME-ARENA-CRED-POOL-ACCRUE` / `INV-TIME-ARENA-CRED-POOL-PARITY` in `docs/testing/invariants-and-business-logic.md`; `skills/play-time-arena-doub/SKILL.md` updated. | ### Test plan | Command | Result | |---------|--------| | `cd contracts && forge test --match-test cred` | **PASS** — 19 tests (16 TimeArena + 3 BuyRouter) | | `cd contracts && forge test --match-test buy_with_cred` | **PASS** — 2 tests | | `bash scripts/verify-cred-buy-anvil.sh` | **PASS** — `=== verify-cred-buy-anvil: OK ===` | | `cd indexer && cargo test` | **PASS** — 69 tests (unit + integration_stage2) | ### Attack / abuse | Scenario | Result | Test | |----------|--------|------| | CRED-only buyer cannot over-claim | **PASS** | `test_cred_only_buyer_fair_share` | | Epoch boundary credits correct pool | **PASS** | `test_buyWithCred_epoch_boundary_credits_correct_pool`, `test_cred_accrue_buyWithCred_at_epoch_boundary` | | Double-claim still one-shot | **PASS** | `test_claim_cred_*` suite (no regression) | | DOUB buy economics unchanged | **PASS** | `test_cred_accrue_on_doub_buy` | No repo changes required; closing as verified on `main`.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-14 14:09:41 +00:00
Sign in to join this conversation.
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#311
No description provided.