Home › Docs › Money and security
Deposits, withdrawals and 2FA
How KEEP moves between your wallet and the game: deposits, withdrawal limits and statuses, authenticator 2FA, custody, and proof of reserves.
This page explains how KEEP moves between your Solana wallet and your in-game balance, what the withdrawal limits and statuses mean, and how two-factor authentication (2FA) fits in. It also describes, in plain words, how the game holds your KEEP and how you can check that it is fully backed.
Everything here runs on Solana devnet during the playtest. Devnet SOL and devnet KEEP are test-net tokens with no real-world value. Nothing on this page is a mainnet promise.
Quick facts
- Deposits need only a signed-in wallet; no land required. Your balance credits once the transfer is finalized on-chain (about 15–30 seconds).
- Withdrawals need a paid land deed. Minimum 500 KEEP per request, 2% fee, one withdrawal per rolling 24 hours.
- Your daily withdrawal limit depends on your Keep level: 50,000 KEEP at Keep 1 up to 250,000 KEEP at Keep 20.
- Standard withdrawals freeze your KEEP for 24 hours (cancellable any time during the hold), then pay out automatically.
- An authenticator app that has been enabled for 24 hours lets you skip the hold with an INSTANT withdrawal. Email codes never unlock instant.
- The game server holds no signing keys. Payouts are signed by a separate, database-blind signer with its own ceilings, and no KEEP leaves unless the custody wallet covers every player's balance.
- BUY KEEP WITH SOL is currently disabled.
Where your KEEP lives
Your in-game KEEP is a balance in the game's ledger, backed 1:1 by a custody ("hot") wallet on Solana devnet. Deposited KEEP and KEEP you earn in play share one balance and one withdrawal allowance. Deposited KEEP is treated as a liability owed back to you; it is never used to fund rewards.
Shards are the building currency. You can convert KEEP to shards 1:1 on the KEEP WALLET screen, but that conversion is one-way: shards are never withdrawable, and only the GOLD FORGE turns shards back into KEEP. See Economy: Shards and KEEP and Gold Forge.

Depositing KEEP
Open KEEP WALLET → DEPOSIT KEEP, enter a whole-KEEP amount, and sign the transfer in your wallet. That is the whole flow from your side.
Behind the scenes the game creates a deposit intent with a one-time reference key, your wallet signs a standard SPL token transfer to the custody wallet's KEEP account, and the game credits your balance only once that transaction reaches finalized commitment.
Rules worth knowing:
- You do not need land to deposit. Only a signed-in wallet.
- Whole KEEP only. Credits are posted in whole KEEP; any fraction below 1 KEEP stays uncredited in custody, so send round amounts.
- The server decides when you are credited, not the client. The UI polls every few seconds and shows the status
pending → finalized → credited. If something goes wrong you will seeexpiredorfailed. - Intent lifetime is 30 minutes. If you start a deposit and do not sign within that window, start a fresh one. An existing intent is reused only if at least 10 minutes remain on it.
- Where a second RPC provider is configured, both providers must agree on the finalized payment before credit (optional on devnet, mandatory on mainnet).
Tip: if a deposit takes longer than the usual 15–30 seconds, your KEEP is not lost; the verifier keeps checking until the intent expires, and a finalized transfer will credit.
Withdrawing KEEP
Open KEEP WALLET → WITHDRAW KEEP. The screen shows the exact quote before you sign: minimum, fee, what you will receive, and whether the request will be standard (frozen 24H, cancellable) or instant.
Who can withdraw
You need an active, paid land base. Land ownership is what unlocks withdrawals; see Land deeds and the globe. The destination must be a normal wallet address (program-derived addresses are rejected); the payout goes to that wallet's KEEP token account.
Amounts, fee and limits
| Rule | Value |
|---|---|
| Minimum per request | 500 KEEP |
| Fee | 2% of the gross request (burned); you receive the remaining 98% |
| Frequency | One non-failed withdrawal per rolling 24 hours per wallet |
| Daily cap | By Keep level (table below), rolling 24 hours |
| Whole-balance withdrawals | Allowed if the amount fits your cap |
Example: requesting 1,000 KEEP burns 20 KEEP as the fee and sends 980 KEEP to your wallet.
The daily cap depends on the level of your Keep. If you own more than one base, the strongest active paid base sets the limit; allowances never add across bases.
| Keep level | Daily cap (KEEP) | Keep level | Daily cap (KEEP) |
|---|---|---|---|
| 1 | 50,000 | 11 | 155,000 |
| 2 | 60,000 | 12 | 166,000 |
| 3 | 71,000 | 13 | 176,000 |
| 4 | 82,000 | 14 | 187,000 |
| 5 | 92,000 | 15 | 197,000 |
| 6 | 103,000 | 16 | 208,000 |
| 7 | 113,000 | 17 | 218,000 |
| 8 | 124,000 | 18 | 229,000 |
| 9 | 134,000 | 19 | 239,000 |
| 10 | 145,000 | 20 | 250,000 |
Cancelled and refunded withdrawals do not count toward your cap or your once-per-24h cooldown. There is no shared, cross-player daily pool; each wallet has its own allowance.
Signing the request
Every withdrawal carries a fresh wallet signature over the exact intent: gross, fee, net, destination, standard-or-instant mode, and the unbonding hours. The payout worker re-verifies that proof independently before the custody side signs anything. The signature is valid for 5 minutes; wait longer and the UI asks you to sign again.
Why: the signature ties the payout to what you actually approved. Even if someone got hold of a session, they could not redirect a withdrawal to a different address or amount without your wallet.
Standard withdrawals (24-hour unbonding)
- You submit the request. The gross amount is frozen immediately into withdrawal escrow; it is unspendable and cannot be raided.
- The row shows UNBONDING for 24 hours. You can press CANCEL at any time during this hold and the full gross returns to your balance.
- When the hold ends, the payout worker picks the row up (it polls roughly every 10 seconds), signs one transaction, broadcasts it, and confirms it at finalized. The row becomes SENT with a transaction signature, or FAILED.

Instant withdrawals (skip the hold)
An instant withdrawal skips the 24-hour hold. It requires all of the following:
- An authenticator app (TOTP) enrolled on your account, enabled for at least 24 hours. The screen shows AUTHENTICATOR MATURING until then.
- A valid 6-digit authenticator code entered with the request.
- The server's instant flag on (it is off only when payouts are globally paused or custody is not configured).
Email codes are never accepted for instant withdrawals; only the authenticator works. The code is consumed at the same moment your KEEP is frozen, so a wrong code costs one attempt but freezes nothing.
"Instant" means no 24-hour hold, not a synchronous transfer: the request is queued for the payout worker's next pass (within seconds), and you will see INSTANT WITHDRAWAL QUEUED FOR PAYOUT. Instant is opt-in per request; with an authenticator enabled you can still choose a standard withdrawal.
Statuses and what they mean
| Status | Meaning | What you can do |
|---|---|---|
| UNBONDING | Gross frozen; waiting for the 24h hold (or the next worker pass if instant) | CANCEL to get the gross back |
| PAYOUT QUEUED | Hold is over; waiting for the worker | Nothing; it will process shortly |
| PROCESSING | Transaction being signed or broadcast | Wait |
| SENT | Finalized on-chain; transaction signature shown | Check your wallet |
| FAILED | Payout did not land; your KEEP is still held in escrow | REFUND if offered, otherwise contact support |
| CANCELLED | You cancelled during unbonding; gross returned | Nothing |
| REFUNDED | A failed row was refunded to your balance | Nothing |
On FAILED rows, the REFUND button appears only when the server can prove nothing was transferred (for example, the transaction was never broadcast, or it finalized with an error). If the outcome is uncertain, refund is blocked with a "may already have been paid on-chain — contact support" message rather than risk paying you twice. Refunded failures that were the game's fault (RPC outage, custody account short) do not charge your cap or cooldown.
Rows with an unknown outcome (for example, an expired blockhash) are held in PROCESSING for an operator to investigate; they are never auto-refunded.
Why a payout might pause
Two safety brakes sit in front of every payout. They are not your personal limit, but you may notice them:
- Coverage gate. No KEEP leaves custody unless the hot wallet's KEEP account (finalized, unencumbered) is at least equal to the total of every player's balance plus all escrows. If anything is unknown, it fails closed.
- Signer ceilings. The signer enforces its own maximum per transfer, per wallet per 24 hours, and across all payouts per 24 hours. On devnet these are currently set to 250,000 / 250,000 / 1,000,000 KEEP. They are deployment settings rather than game constants and may change without notice. The aggregate ceiling is an operator loss breaker that can pause later payouts in a day.
There is also a global kill switch; when it is off, new requests return "withdrawals open when the liquidity pool goes live" and the payout queue holds. On devnet it is on.
Two-factor authentication
Open PROFILE → SECURITY & KEY EXPORT → ACCOUNT EMAIL · 2FA. Every change to a factor requires a fresh wallet signature, and once you have one factor, adding or changing another requires a step-up with the existing one.

Authenticator app (TOTP)
Press SET UP AUTHENTICATOR, scan the QR code (or use the otpauth link) in any TOTP app, enter the 6-digit code, and press VERIFY & ENABLE. You will see "AUTHENTICATOR ENABLED · 24H SECURITY HOLD STARTED". After 24 hours the status flips to INSTANT WITHDRAWALS AVAILABLE.
- Codes are accepted within one 30-second step either side of the current time; a code cannot be reused for two requests.
- 5 failed 2FA attempts lock 2FA for 15 minutes. Sensitive 2FA and withdrawal endpoints are also rate-limited to 12 requests per minute per IP.
- DISABLE AUTHENTICATOR (with a current code) or re-enrolling resets the 24-hour maturity clock.
Why the 24-hour maturity? If an attacker gains control of your account and enrolls their own authenticator, they still cannot pull KEEP out instantly. Any withdrawal they start in that window is a standard, cancellable one you can see and stop.
Verified email
Under VERIFIED CONTACT EMAIL, enter your address, press SEND CODE, then VERIFY EMAIL with the 6-digit code. Codes last 10 minutes, burn after 5 wrong guesses, and can be resent every 30 seconds.
A verified email is a contact, recovery, factor-management and key-export proof. It is not a money factor: it never unlocks instant withdrawals.
Embedded wallets and private-key export
If you signed in with email or a social login, your wallet is an embedded wallet provided by Privy. You can export its private key, but only after enrolling Privy's own wallet MFA. The EXPORT PRIVATE KEY screen under SECURITY & KEY EXPORT asks you to SECURE WALLET WITH PRIVY MFA first, then to sign a fresh challenge (plus your authenticator or email code if you have one enrolled) before REVEAL MY KEY.
The key is shown inside Privy's own modal. It never passes through the game's code or servers. Export is never gated on purchases or land; it is a custody right. See Wallets and sign-in.
Custody model in plain words
- The public game API holds no keys.
- A database-connected worker decides which payouts are due and reserves a per-wallet allowance.
- A separate policy signer service, which cannot see the database, is the only process that mounts the custody key. It journals every signed transaction to an append-only log and enforces its own ceilings regardless of what the worker asks.
- Devnet custody uses a file-backed key. The configuration refuses to start on mainnet with file custody, or without a remote signer and two independent RPC vendors.
This is a devnet playtest: there is no mainnet deployment, no HSM/enclave custody yet, and no third-party audit. See Smart contracts and on-chain.
Proof of reserves
The game publishes a public endpoint, /por, with the latest Merkle root, coverage (reserve versus total liabilities) and custody evidence. A signed-in player can fetch their own inclusion proof from /por/proof. Each week a snapshot builds a Merkle tree over every wallet's liabilities (balance plus withdrawal, forge, league and mail escrows) and posts the root on-chain through the shardkeep-core program.
Only the custody wallet's canonical KEEP token account counts as reserve; liquidity pools, treasuries and extra accounts are excluded. At the last release the reserve was 499,699,242 KEEP against 3,480,504 KEEP of liabilities, with zero deficit; treat that as a point-in-time observation, not a guarantee.
There is no in-game proof-of-reserves page yet. The KEEP ECONOMY screen shows aggregate pool, escrow, withdrawn and deposited figures.
Devnet today, mainnet later
- KEEP is a classic SPL token with 9 decimals on devnet. Devnet supply is 500,000,000 KEEP with mint and freeze authority retained; the fixed 1B supply with revoked authorities is a target, not current chain fact.
- No mainnet game state exists. Moving balances to mainnet would need a fresh database or an owner-run migration.
- The planned liquidity-bootstrap withdrawal pause for mainnet month 1 is designed but not active.
- BUY KEEP WITH SOL shows TEMPORARILY UNAVAILABLE and is not live.
- Card on-ramps are not built. Swaps through the EXCHANGE tab in PROFILE › WALLET run on mainnet, are signed by you, and are not a game conversion desk.