Skip to content

feat(gacha): add provably-fair gacha (pack-pull) example - #664

Merged
amilz merged 29 commits into
mainfrom
feat/add-gacha-pino
Aug 4, 2026
Merged

feat(gacha): add provably-fair gacha (pack-pull) example#664
amilz merged 29 commits into
mainfrom
feat/add-gacha-pino

Conversation

@amilz

@amilz amilz commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Adds a complete provably-fair gacha (loot-box / pack-pull) game example — the on-chain mechanic behind Solana RWA pack platforms like Collector Crypt and Phygitals. An admin configures a pool of fixed-weight reward tiers and a fixed entry fee; buyers open pulls revealed via RFC 9381 ECVRF anchored in the deployed cc-vrf registry by CPI, and prizes are minted as Token-2022 NFTs carrying a rarity metadata field.

What's included

  • Pinocchio program — full commit-reveal lifecycle (init_pool, buy_pull, settle_pull, refund_pull, claim_prize, withdraw_fees) with Anchor-compatible self-CPI events and a hand-built CPI into cc-vrf's commit_proof_with_beta.
  • Codama pipeline + clients — IDL-driven TypeScript and Rust client generation, plus a @solana/gacha kit plugin used by both scripts and the webapp.
  • Test coverage — LiteSVM integration suite (lifecycle + negatives) and a Light-stack suite exercising the real settle_pull → cc-vrf → Light CPI chain with genuine validity proofs; Rust↔TS parity for select_tier/derive_alpha pinned by shared fixtures.
  • Next.js webapp — buy/reveal/verify UI with a server-side pull orchestrator (submit → settle → mint), SIMD All-Stars collectible card reveal, and an admin panel for pool creation and fee withdrawal.
  • Docs — trust-model writeup (detection-not-prevention randomness model), READMEs, and CI wiring.

Trust model

The program accepts the registered operator's signed beta, while buyer entropy in alpha, fixed weights, one-reveal-per-pull enforcement via cc-vrf/Light, and a refund escape hatch close the gaps detection alone leaves open. Verification is fully reproducible off-chain from emitted events.

Closes DEV-776

amilz added 22 commits July 29, 2026 15:32
Rebuild the gacha example as a Collector Crypt-style commit-reveal:
alpha binds buyer entropy (SHA-256(pull || client_seed)), fixed tier
weights make outcomes settle-order independent, and settle_pull anchors
each reveal in the deployed cc-vrf registry by CPI — one commit per
pull enforced by Light Protocol address uniqueness against a frozen
operator record. Adds claim_prize (Token-2022 NFT carrying a rarity
metadata field), refund_pull (post-deadline liveness escape),
withdraw_fees (capped by pending-pull liabilities), and regenerated
IDL/clients with cross-language alpha/tier parity fixtures.
36 tests covering init/buy/refund/withdraw with exact balance math,
settle and claim negatives (all pre-CPI, so dummy Light accounts
suffice), full claim Token-2022 TLV decode via fabricated settled
pulls, and an IDL-driven demote-writable harness across all six
instructions.
…path

light-program-test suite (standalone workspace: litesvm 0.7 cannot
share a graph with the 0.12 suite) running the full
settle_pull -> cc-vrf -> Light CPI chain with genuine validity proofs:
settle happy path with registry commit decode, replay rejected at both
the program and registry layers, unfrozen and unregistered authorities
rejected, claim after a real settle, and refund-after-settle rejected.

just light-bootstrap provisions the environment (spl_noop restore, CDN
proving-key download, pinned prover started directly — the CLI's
start-prover points the binary at a dead key URL), and light-test
joins the aggregate test recipe so CI runs it.
Rewrite CLAUDE.md around the detection-not-prevention randomness model
and the on-chain-verified cc-vrf caveats, update the example READMEs,
drop the inert nested workflows, and register the example in
.ghaignore so the root justfile workflow drives CI.
@amilz amilz self-assigned this Aug 3, 2026
@amilz
amilz requested a review from dev-jodee as a code owner August 3, 2026 17:20
@linear

linear Bot commented Aug 3, 2026

Copy link
Copy Markdown

DEV-776

@greptile-apps

greptile-apps Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Too many files changed for review. (166 files found, 100 file limit)

Bypass the limit by tagging @greptile-apps to review.

amilz added 4 commits August 3, 2026 10:21
The gacha pinocchio example is a self-contained nested workspace, so its crates escape the root fmt/clippy coverage and fail the workspace-membership check. List them in .workspace-ignore, matching the world-cup precedent.
amilz added 2 commits August 3, 2026 12:00
A prior prettier pass reformatted idl/gacha.json (2-space to 4-space),
which the codama generator does not reproduce, so the check-generated CI
job failed on IDL drift. Regenerate with the actual generator output.
The root prettier check reformats games/gacha/pinocchio/idl/gacha.json,
but the codama generator emits it in a different style, so the gacha
check-generated job and the root prettier check cannot both pass. Exclude
the generated IDL from the root prettier check.
dev-jodee
dev-jodee previously approved these changes Aug 4, 2026
Comment thread games/gacha/pinocchio/tests/integration-tests/src/utils/constants.rs Outdated
Comment thread games/gacha/pinocchio/tests/integration-tests/src/utils/pda.rs Outdated
Comment thread games/gacha/pinocchio/SECURITY.md Outdated
Comment thread games/gacha/pinocchio/LICENSE Outdated
Comment thread games/gacha/pinocchio/tests/integration-tests/src/utils/constants.rs Outdated
Comment thread games/gacha/pinocchio/program/src/state/common.rs
Comment thread games/gacha/pinocchio/program/src/state/pool.rs
Comment thread games/gacha/pinocchio/program/src/state/pull.rs
Comment thread games/gacha/pinocchio/program/src/ccvrf.rs Outdated
Comment thread games/gacha/pinocchio/program/src/instructions/claim_prize.rs
- Drop the per-example LICENSE and SECURITY.md; both live at the repo root and
  the program's security_txt already points at the repo-level policy.
- Source the Light system program, account-compression program and authority,
  registered-program PDA, and the v2 address tree from light-sdk-types rather
  than hand-copied base58 literals. cc-vrf publishes no crate, so its own
  program ID, CPI authority, and instruction discriminator stay local.
- Split the Token-2022 mint and token-metadata CPIs out of claim_prize into
  instructions/helpers/prize_nft, and move the account guards and PDA creation
  into helpers/checks and helpers/account so helpers/mod.rs is declarations
  only. claim_prize drops from 279 to 142 lines.
- Declare Pull's PDA seeds in Codama so both generated clients derive it, and
  delete the hand-written findPullPda from the TypeScript client.
- Derive pool, vault, pull, and prize-mint addresses in the integration tests
  through gacha-client's generated find_pda helpers, so a seed the IDL gets
  wrong fails the suite instead of shipping. Take the system, Token-2022, and
  ATA program IDs from the crates that declare them.
- Use solana_address::Address across the tests and drop solana-pubkey, whose
  4.x Pubkey is a re-export of the same type.
- Document that utils/idl.rs drives the account-meta demotion tests.
- Bump @codama/renderers-rust to 3.1.3. 3.1.1 rendered numeric PDA seeds as
  decimal strings instead of to_le_bytes, so Pull::find_pda in the Rust client
  disagreed with both the program and the TypeScript client.
- Ignore webapp/.next in eslint.

AccountDiscriminator keeps its 0-based numbering. Renumbering closes the gap
where a zeroed account passes the Pool check, but it would strand the live
devnet pool and its pulls, whose PDAs cannot be re-initialized once allocated.

Also lands the in-flight devnet burst-randomness script and its justfile
recipes, which shared the working tree.
@amilz
amilz merged commit 5f48511 into main Aug 4, 2026
18 checks passed
@amilz
amilz deleted the feat/add-gacha-pino branch August 4, 2026 18:51
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