Appearance
playSKPK Token
What was decided
The PMF beta runs on playSKPK — a fresh 6-decimal, no-backing SPL mint on numero-token, granted directly to players instead of bought/wrapped from a USDC-backed chip. The real-money chip is not deployed in the beta (it returns later, rebranded SKPK).
Three decisions:
A no-backing mint + an idempotent
grant.grant(amount, claim_id)is grant-authority-gated (the cage signs) and idempotent perclaim_idvia agrant_markerPDA — a replay of the same claim reverts"already in use"and mints nothing. This is the same once-only guard used by the corerake_markerand bettingclaim_marker, and it is the chip-claim-board's no-double-mint floor. Theclaim_idthreads game-server → cage → grant.The cage's chip mint is a per-deploy fact, not runtime-agnostic. A single
CHIP_TOKENenv (playskpk|tskpk, unset →tskpk), captured at module load, drives achipMint()resolver through the whole fund path (table/custody/betting vaults + every player chip ATA). The four fund programs are mint-generic, so they need only atskpk_mint→playskpk_mintfield rename; the cage decides which mint per deploy. The beta inits only playSKPK (init_playskpk, noinit_mints), so the SKUSDC faucet/wrap real-money surface is structurally absent, not merely unused.CHIP_TOKENis fail-closed.resolveChipTokenthrows on any unrecognized value at cage boot (and in the harness/standup/devnet reads), so a typo (playSKPK, a trailing space) can never silently run the beta on the real-money chip. This closed a HIGH-severity silent fallback that the happy-path tests could not see (a falsification finding).
Key tradeoffs accepted
- Two chips coexist during the beta. The parameterized
chipMint()keeps the real-money TSKPK path + its ~30-test cage-e2e working alongside playSKPK. This is coexistence "added during migration," so its deliberate retirement is captured as theplayskpk-full-migrationplan, sequenced at the tail ofagent-pmf-beta— the coexistence would otherwise become permanent backcompat. settleandwithdraware alternate exits, not a sequence. In the cage model,settle(a hand payout) concludes the player; the full fund path is proven as adeposit → withdrawcustody round-trip plus a separatedeposit → settle, not an (impossible)deposit → settle → withdraw.- Mainnet is a separate, irreversible step. Everything here is proven on a disposable
solana-test-validator/ devnet; the mainnet deploy + INIT_AUTHORITY prod-swap + key ceremony live inmainnet-solana-deploy.
Verified
The full play loop runs on playSKPK against a live validator: grant (A1/A2), deposit + withdraw custody round-trip (A5), a settled hand paying from the playSKPK vault (A5b), and the refused real-money faucet (A7) — with the TSKPK cage-e2e core staying green (the beta path is CHIP_TOKEN-gated). resolveChipToken has a unit test (A9) proving 8 typo variants all throw.
References
- Full ADR + impl + retrospective:
.indusk/planning/archive/playskpk-token/ - Guide: Smart Contracts → playSKPK
- Changelog: playSKPK cage grant
- Retirement of the coexistence:
.indusk/planning/playskpk-full-migration/