Smart contracts and what lives on-chain
What Pixel Kingdom Wars puts on Solana (payments, Land Deeds, KEEP, weekly balance roots) versus the game server, with devnet addresses and verification tips.
Pixel Kingdom Wars is a server-authoritative game that uses Solana for a small, well-defined set of things: taking SOL payments, holding your Land Deed as an NFT, moving the KEEP token in and out, and publishing a weekly proof of player balances. Everything else — your base, army, raids, and shards — lives on the game server. This page explains where that line is drawn, what each on-chain program does, and how to check it yourself.
Everything described here runs on Solana devnet. Devnet SOL and devnet KEEP are test-net tokens with no real-world value, and there is no mainnet deployment.
Quick facts
- Two Anchor programs: shardkeep-core (live; SOL payment router, entry receipts, weekly balance roots) and shardkeep-distributor (deployed but not live).
- Land Deeds are Metaplex Core NFTs in one collection, minted by the server after a verified land payment.
- KEEP is a classic SPL token with 9 decimals; in-game balances are ledger entries, and deposits/withdrawals are ordinary token transfers.
- The program splits routed SOL 40% / 35% / 25% between liquidity, dev, and ops treasuries; some purchases go 100% to liquidity by direct transfer.
- The server sets prices. The program routes whatever it is sent; an underpayment is accepted on-chain but grants nothing in-game.
- No third-party audit has been completed, and no multisig admin is in place. Devnet only.
On-chain vs. off-chain
| Lives on Solana (devnet) | Lives on the game server |
|---|---|
| SOL payment routing and entry receipts (shardkeep-core) | Base layouts, structures, timers, Keep level |
| Weekly Merkle root of player KEEP balances | SHARDS, Mines, GOLD FORGE, armies, heroes, items |
| Land Deed NFTs and their collection (Metaplex Core) | Quests, clans, chat, mail, shop listings |
| The KEEP SPL mint; deposits and withdrawals | Raid snapshots, battle simulation, settlement, replays |
| The inactive distributor program | Sign-in, admission, rate limits, anti-cheat, ledger accounting |
Why: Putting every battle and building on-chain would make the game slow and expensive and would expose its rules to front-running. Keeping the game state on the server and using the chain only where ownership or money changes hands keeps play fast while still letting you hold your land and tokens in your own wallet.
One consequence worth knowing: gameplay never reads the NFT. Attackability, production, and in-game ownership are server state, so nothing you do to the deed in your wallet (freezing, delegating, listing) protects your base.
The shardkeep-core program
Program ID (devnet): mYYQFnpyGofG31y5oJkiKVmNwifbSXBMnQ5aUgQkL6b
This is the program your wallet talks to when you buy land, hire extra builders, or buy raid energy and shields. It does three jobs.
1. Route SOL payments
Every payment instruction sends SOL from your wallet to three treasury accounts in one transaction, using the split stored in the program's Config: 40% liquidity, 35% dev, 25% ops. The treasuries are fixed in Config, so a client cannot substitute its own addresses. Rounding dust always lands in the liquidity leg.
Each payment emits a PaymentMade event (wallet, kind, lamports, reference). The game server watches for that event, waits for the transaction to be finalized, and only then grants the item. If a transaction underpays, the program still accepts it but the server grants nothing — the server, not the chain, is the price authority.
| Instruction | Who signs | What it does |
|---|---|---|
pay_entry | you | One-time first-land purchase. Creates your Player receipt account; a second call fails on-chain. |
buy_sink(kind, amount) | you | Repeatable payment tagged with a kind (energy, shield, builder, extra deed, and so on). No counters. |
buy_builder, buy_expansion | you | Legacy paths capped at 2 each; the current client does not use them. |
2. Hold an entry receipt
pay_entry creates a Player account derived from your wallet address. Because it is created with init (not "init if needed"), one wallet gets exactly one entry receipt, enforced by the program itself. The server also uses this account as a fallback: if its scan for your payment reference ever misses, a finalized Player account is enough proof that you paid.
3. Post weekly balance roots
Once a week (Monday 00:10 UTC) the server snapshots every player's in-game KEEP balance, builds a Merkle root, and posts it with post_root. Each EpochRoot account is created once and cannot be rewritten. This is the start of a proof-of-liabilities system: the public GET /por endpoint shows coverage, and an authenticated GET /por/proof returns your inclusion proof. There is no in-game screen for this yet.
Admin instructions
set_paused blocks all payments; propose_admin / accept_admin transfer the admin key in two steps (the new admin must sign to accept). The program has no price-update instruction — the land price stored on-chain can only change through a program upgrade.
What each purchase does on-chain
| Purchase | On-chain path | Price (devnet SOL) | Where it goes |
|---|---|---|---|
| First land | pay_entry | 0.2 | 40/35/25 |
| Additional deed | buy_sink (kind 9) | 0.2 | 40/35/25 |
| Builders 2–6 | buy_sink (kind 8) | 0.5, 0.75, 1, 1.5, 3 | 40/35/25 |
| Raid energy ×1 / pack ×6 | buy_sink (kinds 3 / 7) | 0.03 / 0.09 | 40/35/25 |
| Shield +12 h | buy_sink (kind 4) | 0.05 | 40/35/25 |
| Warzone shield (48 h) | direct transfer + buy_sink (kind 6) in one tx | 10 | 50% liquidity direct, 50% via 40/35/25 |
Some purchases skip the program entirely and are plain SOL transfers, tagged with a reference key so the server can find them:
| Purchase | Price (devnet SOL) | Where it goes |
|---|---|---|
| Land expansions 1–6 | 0.15, 0.25, 0.40, 0.65, 1.00, 1.50 | 100% liquidity |
| Mine upgrade to L5 … L20 | 0.5 … 3.2 | 100% liquidity |
| GOLD FORGE upgrade to L2 … L20 | 0.10, +0.05 per level, up to 1.00 | 100% liquidity |
| Item-market buy | seller's price | 95% to seller, 5% fee treasury, one buyer-signed tx, no program |
See Economy: Shards and KEEP and Shop and marketplace for how these fit into play.
The shardkeep-distributor program (not live)
Program ID (devnet): 6Tgc32nfuEDwvVQii47eLKZXeu39evzG5142UheuxpKU
This is a one-claim Merkle distributor meant for a future token-generation event. An admin initializes a Distributor (per mint) with a root, a claim window, and a clawback date; a wallet proves its leaf (wallet, amount, version) with claim and receives tokens from the vault; set_root replaces the snapshot and bumps the version so old proofs stop working; clawback sweeps leftovers after the window closes. Each wallet can claim once per Distributor lifetime.
Today it is deployed but switched off: there is no Distributor account for the current KEEP mint, no vault, no funds, and no production code calls it. It is also not how gameplay rewards are paid — the emission pool that funds mining and the GOLD FORGE is a ledger account on the server, not this program.
Land Deeds (Metaplex Core)
Collection (devnet): 56RemMwZRxL7xMMV8TbiErZX2YfrnuY65x3t7sTQxKrT
Your deed is a Metaplex Core NFT — not a compressed NFT — minted by the server into the game's collection once your land payment is finalized. A few properties matter to players:
- Exactly-once minting. The deed's address is derived from your base's stable ID and stored before broadcast, so a retried transaction can never produce a second deed.
- Transferable. Each deed carries an admin-held freeze plugin that currently arrives thawed; trading is enabled.
- Living metadata. Name
Land Deed · xxxx…yyyy, symbolDEED. The image is a render of your actual base; traits (Location, Country, Tile, Keep Level, Buildings, Land, Founded) are rebuilt from live server state. Re-versioning the on-chain URI so wallets refresh depends on a deployment flag, so explorers may lag behind the in-game view. - 5% royalty, marketplace-honored. The royalty is written on the collection and copied to every deed, but the rule set is
None, so a direct wallet-to-wallet transfer pays nothing. - A deed conveys the whole base — structures, that base's SHARDS, army, heroes, items, trophies — but never your wallet's KEEP or SOL, identity, or clan. After buying on an external market, the buyer claims the base in-game; there is no custom escrow program.

Full details are on Land Deeds and the globe.
The KEEP token and custody
KEEP mint (devnet): 5GQh8Dg2BFtH3Yso5drRA2K8omw46m3KAQrhH3TMpWJC
KEEP is a classic SPL token (not Token-2022) with 9 decimals and Metaplex fungible metadata. Your in-game KEEP is a balance on the server's ledger; the game's payout hot wallet holds the only counted reserve.
- Deposit = an ordinary SPL transfer to the game's custody wallet with a reference account; you are credited the exact amount observed.
- Withdraw = the hot wallet sends KEEP back to your wallet. Fee 2% (the only KEEP that is ever burned), minimum 500 KEEP, 24-hour unbonding.
- Weekly balance roots (above) are the public check that the ledger adds up.
The design target in the game's constants is a fixed 1,000,000,000 KEEP supply with revoked authorities. The project's own docs (checked 2026-08-18) describe the live devnet mint as 500,000,000 KEEP minted with mint and freeze authority retained — a devnet state, not the final mainnet policy, which is undecided. All of it is devnet KEEP with no real value. See Deposits, withdrawals, and 2FA.
Addresses and PDAs at a glance
All addresses are from the published devnet registry (infra/devnet.addresses.json, updated 2026-08-18).
| What | Address (devnet) |
|---|---|
| shardkeep-core program | mYYQFnpyGofG31y5oJkiKVmNwifbSXBMnQ5aUgQkL6b |
| shardkeep-distributor program | 6Tgc32nfuEDwvVQii47eLKZXeu39evzG5142UheuxpKU |
| Core Config PDA | AEtsnqdSXDwGDBeovnD9XoutQmNptcPWC8ygieZSkKHH |
| KEEP mint | 5GQh8Dg2BFtH3Yso5drRA2K8omw46m3KAQrhH3TMpWJC |
| Land Deed collection | 56RemMwZRxL7xMMV8TbiErZX2YfrnuY65x3t7sTQxKrT |
| Treasury | Address (devnet) |
|---|---|
| Liquidity (40%, plus all direct transfers) | A1ja8GwrTM2KvS4tKJJaVaLk57xJeehuk2F9Exbz82QA |
| Dev (35%) | 5sYVCRd1onSre8EKujE5vDKa9KeF2KuJvPA3rpRonfif |
| Ops (25%) | fCTc8TgJCvHUkn1aaME2gDcs69LpgtVXq1rmBSvS3Bx |
Program-derived accounts, for developers:
- shardkeep-core:
Config=["config"];Player=["player", wallet];EpochRoot=["root", epoch as u64 little-endian]. - shardkeep-distributor:
Distributor=["distributor", mint]; vault authority =["vault"];ClaimStatus=["claim", distributor, claimant].
Program IDs are identical on localnet and devnet, and the TypeScript clients read them from the committed IDLs.
Who holds the keys
- Initialization of either program requires the signer to be the program's current upgrade authority, checked on-chain against the program's ProgramData account.
- After that, shardkeep-core is governed by
Config.admin(pause, post roots, two-step admin transfer). The distributor's admin has no rotation instruction at all — one of the reasons it stays off. - Admin, hot-wallet, and deed-ops keypairs are kept out of the repository. The identity of the devnet upgrade authority is therefore not something you can read from the code.
- A Squads multisig for admin was a research recommendation only; it is not implemented.
- No third-party audit has been completed.
Security posture in brief
Every program change must keep: release-mode overflow checks; a signer on every authority; typed accounts with owner and discriminator checks; canonical PDA seeds; init (never re-init) for receipts and roots; fixed treasury and mint constraints; multiply-before-divide basis-point math; an event for every value movement; and adversarial validator tests (wrong signers, substituted treasuries, duplicate entries, out-of-order purchases, pause bypass, forged Merkle proofs, node-as-leaf attacks, window timing).
On the server side: every payment is verified at finalized before any grant, payment events are only trusted from shardkeep-core's own execution frames so another program cannot forge one, and custody transactions are persisted before broadcast so retries resend identical bytes. Note that the Anchor validator tests are a manual release gate rather than a CI job.
How to verify on an explorer
- Open Solana Explorer or Solscan and switch the cluster to Devnet.
- Paste a program ID above. You should see the program account and, for shardkeep-core, the IDL.
- After a land purchase, open your wallet's transaction: it should show three SOL transfers to the treasury addresses above (for 0.2 SOL: 0.08 / 0.07 / 0.05) and a
PaymentMadeevent log. - Paste the KEEP mint to see its metadata, or the collection address to browse minted deeds; your own deed appears under your wallet's assets.

Tip: The exact-split check is the quickest way to confirm you signed the real program. If the transfers do not match the treasuries listed here, stop and ask in the community channels before signing anything else.