# Deploy checklist — gkd_chain

Step-by-step deploy + initialization for the `gkd_chain` program. **Handles real SOL — do a devnet
dry-run and ideally a security audit first.** I only ever need **public keys**; you run the signing
commands yourself.

## 0. What you provide

| Item | What | Notes |
|---|---|---|
| Founder/creator pubkey | wallet that receives the 49% creator split | public key only |
| Admin/deployer keypair | deploys + initializes + upgrade authority | **you** hold/sign this |
| Program keypair | the program's address | reuse `target/deploy/gkd_chain-keypair.json` or generate a new one |
| Pyth SOL/USD account | price feed for the weekly $0.10 re-peg | the feed account pubkey on the target cluster |
| (optional) 2/3 multisig | 3 member pubkeys | for fee override + pause |
| (optional) charity ops | charity wallet pubkeys | added later via `whitelist_charity` |

`8qCpYyRjdG8Y1jW5fu77XZ3qkWErgABhscEuuY4mRjnr` is the **devnet-only** creator wallet. Never use it
as the mainnet founder/creator pubkey; mainnet initialization requires a separately supplied wallet.

## 1. Program id

The repo currently uses a placeholder id. Pick the program keypair you will deploy, then sync the id:

```bash
solana address -k target/deploy/gkd_chain-keypair.json     # your real program id
# put that id in BOTH:
#   programs/gkd_chain/src/lib.rs   -> declare_id!("<ID>")
#   Anchor.toml                     -> [programs.mainnet]/[programs.devnet] gkd_chain = "<ID>"
#   src/chain/chain_config.js       -> programId
```

Rebuild after changing `declare_id!` (Windows toolchain workaround — see POOL_MECHANISM.md):

```bash
rustup toolchain link 1.84.1-sbpf-solana-v1.51 "$HOME/.cache/solana/v1.51/platform-tools/rust"
export PATH="$HOME/.cargo/bin:$PATH"
( cd programs/gkd_chain && cargo-build-sbf --skip-tools-install )
```

## 2. Devnet dry-run first (free, no real SOL) — strongly recommended

`tools/dryrun_local.js` runs the full core init sequence (config → pools → token → record →
leaderboard → season) and verifies every account/PDA on a live validator.

- **Local validator** (fastest): on Windows enable *Developer Mode* (or run elevated) so
  `solana-test-validator` can create its symlinks, then:
  ```bash
  solana-test-validator --reset
  solana program deploy target/deploy/gkd_chain.so --program-id target/deploy/gkd_chain-keypair.json --url localhost
  node tools/dryrun_local.js
  ```
- **Devnet** (no Developer Mode needed): `solana config set --url devnet`, fund the deployer
  (`solana airdrop` in small chunks until you have ~6 SOL), `solana program deploy ... --url devnet`,
  then `RPC_URL=https://api.devnet.solana.com node tools/dryrun_local.js`.

Expected: `DRY-RUN PASS ✅`. NFT/governance/fee-refresh paths need Metaplex/Pyth accounts and are
covered by `cargo test -p gkd_chain` + the Ed25519 layout cross-check.

Then validate the exact canonical browser client through the persistent strict verifier and the real
Devnet program:

```bash
npm run verifier:key:init
npm run verifier:set:devnet
node verifier/server.js
npm run test:devnet:browser
```

This pays a real Devnet entry fee, finalizes the event ledger, obtains the configured verifier's
canonical signature, submits `submit_verified_run` directly from the browser client, and confirms the
RunRecord and leaderboard PDAs. It does not prove authoritative gameplay physics; close that security
boundary before enabling score-derived mainnet rewards.

## 3. Mainnet deploy

```bash
solana config set --url mainnet-beta
solana balance                                  # deployer must hold enough SOL (program ~0.76 MB)
solana program deploy target/deploy/gkd_chain.so --program-id target/deploy/gkd_chain-keypair.json
```

Switch `Anchor.toml [provider].cluster = "mainnet-beta"` and `chain_config.js` cluster too.

`chain_config.js` intentionally keeps the mainnet program id empty. Add the audited mainnet id to
the `GKD_PROGRAM_IDS["mainnet-beta"]` entry only after deployment and full PDA initialization. The
validated devnet id must never be copied into the mainnet entry.

## 4. Initialize (admin signs, in order)

1. `initialize_config(creator_wallet, normal_fee_lamports=270000)`
2. `initialize_pools()`            — Game Pool + Charity Pool PDAs
3. `initialize_token()`            — $420POP mint (authority = PDA)
4. `initialize_record_state()`
5. `initialize_leaderboard()`
6. `initialize_fee_gov(members, threshold=2, target_usd_micros=100000, pyth_sol_usd)`
7. `initialize_season(season_id, mint_cap, score_target, reward_per_run)` — per epoch, caps from
   `HUMAN_SEASON_CAPS × 10^9` (season 33 = Chaos cap × 10^9)
8. **`set_verifier(<verifier pubkey>)`** — turns on the on-chain anti-cheat score signature gate
9. (optional) `whitelist_charity(operator, name)` per charity

`tools/gate_e_submit_run.js` already performs steps 1, 4, 5, 7 automatically when submitting a run;
the rest are one-time admin calls.

## 5. Go-live wiring

- Run the verifier with `STRICT_GATE_D=true`, `REQUIRE_ENTRY_TX=true`,
  `ALLOW_BROWSER_COMPAT=false`, and `ENABLE_MEMO_SUBMIT=false`.
- Keep `VERIFIER_SECRET_KEY_B64` in HSM/KMS-backed production secret storage; its pubkey must equal
  step 8. Never commit or expose the secret.
- Replace the local JSON ledger with a durable transactional database and run the verifier as a
  monitored, redundant service.
- Use a dedicated production RPC with rate limits/failover; do not depend on a public RPC endpoint.
- `chain_config.js`: `cluster`, `programId`, `usePoolProgram=true`, `showLeaderboard=true`.
- Confirm the browser sends `submit_verified_run` directly with a self-contained Ed25519 instruction
  before it. The program tolerates wallet-added ComputeBudget prefixes but never accepts a signature
  instruction after the submit; keep the legacy memo relay disabled.
- Confirm entry fee flows into the Pool PDA and the real top-3 leaderboard renders.
- Transfer program/admin authority to the approved multisig and complete the independent audit before
  adding the mainnet program id.

## Cost note

A ~0.76 MB program is deployed as an upgradeable buffer (~2× rent-exempt). Fund the deployer
generously and verify the exact lamports with a deploy dry-run; you can later reclaim/close the
buffer if needed.
