# Orb Community Arena

> Local readiness review: October 1, 2026. New practice rounds use Control v4. Separate v4 contracts are compiled and tested locally; the deployed Community League keeps v2 until an explicit migration. See [the readiness report](orb-production-readiness-2026-10-01.md).

Two Orb communities compete for a 12 × 8 territory map in three-minute Core Control rounds, coordinating in the existing voice rooms. The community contract enforces moves, energy, scores, deadlines and ERC-721 winner trophies on Monad testnet. Orb remains the membership issuer: this is a hybrid application.

## Modes and identity

- **Community league** (default): attested registration/admission, optional sponsored sessions, a confirmed-state map, independent viewer and NFT claims. Until a contract is configured, an explicit waiting screen offers practice.
- **Practice:** existing database-backed multiplayer, membership checks, concurrent-write protection, profile achievements and a feed recap. These achievements are not NFTs. The map plays from the keyboard (arrows select a sector and move focus, `C` / `A` / `R` pick claim, attack or reinforce, Enter confirms the selected sector), and the screen polls with the version it already holds: a match that has not changed is answered with a few bytes (`GET /api/orb/arena?id=…&since=<version>` returns `{unchanged, version, now}`), the whole match only when something moved. `node scripts/test-arena-practice-ui.mjs` drives both in a browser.
- **Open test rounds:** the earlier contract with freely chosen team labels and wallet-reviewed moves. Those labels do not prove community membership.

The UI supports English and Portuguese. Narrow screens split the map and controls into tabs. Voice calls remain mounted while navigating. Confirmed moves come from chain state.

The Orb community owner obtains a short-lived registration ticket after the server checks the Orb session, Privy token, embedded-wallet ownership, community ownership and bans. Its wallet registers a unique opaque community ID, name and owner onchain. Names may duplicate; IDs cannot. A registered owner can transfer its onchain identity and challenge another community.

Admission binds the exact contract, chain, round, wallet, team and deadline. A round-specific HMAC member ID prevents the same Orb account entering twice through different wallets without publishing the account's internal ID. Teams stay fixed. Both teams need a member before the host starts. An active winner can claim exactly one trophy after the deadline; draws award none. Trophy metadata, including round and community IDs, is onchain.

Membership is attested at entry. A later ban blocks sponsorship, but cannot stop an admitted player's direct onchain moves. Multiple Orb accounts remain possible: this is not proof of one human per player. Onchain ownership/name do not automatically follow Orb changes. Ownership transfer is available in the contract, not yet in the UI. The issuer address is fixed; loss or compromise requires migration. Existing round rules and trophies do not depend on continued issuer availability.

## Sessions and sponsorship

A player reviews setSession once per round. A temporary random key stays only in that tab's React ref. It is never written to browser storage or the server database. Its authority covers only signed game moves: no transfers, approvals, trades, enrollment, community transfers or trophy claims. Reload discards the key. Revocation/replacement increments the player nonce, preventing old unused signatures from reviving when a key is reused. A compromised browser could still spend that session's game energy until revocation or expiry.

Every signed move covers chain, contract, round, player, sector, action, nonce and deadline. The API accepts only register/admit/relay, checks both Orb and Privy identities, rejects cross-site requests and rate limits writes.

The relay verifies exact bytecode, issuer, membership, signature, nonce and expiry, then simulates actSigned. It signs only zero-value transactions to the configured contract. Raw transactions are persisted before broadcast; retries return the same hash. A database lease serializes sponsor nonces across workers. Reserve this sponsor wallet for this service.

Limits: 1,000 sponsored moves/day globally; 100/player/round/hour; at most 350,000 gas for v2 or 900,000 gas for v4, and estimated 0.03 **test MON** per transaction in either version. The v4 gas cap allows estimation headroom for supply-path calculations; it does not bypass the fee cap. Registration, entry, round creation/start, session authorization and trophy claims still use the player's testnet gas. Without a sponsor, direct moves use wallet review. Do not describe the entire application as gasless.

## Local setup

Run:

    npm run arena:compile
    npm run arena:observer
    npm run arena:setup
    npm run dev:arena

Setup creates separate issuer/sponsor keys and a member-ID salt in ignored .env.arena.local, without overwriting an existing file. Keep it private and back it up securely. dev:arena loads local Privy settings, defaults to file:work/orb-hackathon.db, applies migrations and serves port 3112. It rejects non-file databases.

Open http://localhost:3112/?view=arena. Practice works before public testnet deployment.

### Activate Monad testnet

1. Fund the public sponsor address printed by arena:setup with testnet MON, along with participating Orb wallets. Never commit private keys or paste them into the app.
2. Run npm run arena:deploy:testnet. It validates chain, balance and bytecode, deploys the contract and stores its address in .env.arena.local. It refuses an existing deployment address.
3. Restart npm run dev:arena. Two community owners register, one creates a challenge and shares its invitation.
4. Join both sides, start the round, authorize quick play, verify moves/receipts and claim a winning trophy after expiry.

The constructor permits only Monad testnet 10143 and local test chain 31337. This October 1 review performed no public-chain deployment. Public RPC capacity, actual network latency and onboarding through two real funded Privy accounts still need end-to-end validation. Deployment is an explicit operator command, never an effect of opening a page.

### Control v4 migration

`npm run arena:compile:control` builds **new** `OrbArenaControl` and `OrbCommunityArenaControl` artifacts. Legacy artifacts are preserved. The default `ORB_ARENA_RULES_VERSION=2` selects the deployed legacy contract; setting it to `4` selects the separately verified Control artifact. Invalid values fail closed.

To migrate, first finish/reconcile old rounds, unclaimed prizes and sponsor refunds, and preserve access to their original contracts. Deploy a new registry with the explicit version setting and a fresh private deployment configuration. The deploy command refuses an existing contract address. Communities must register on the new registry; old trophies remain attached to their original contract. The economy contract also binds a registry, so its configuration and any new pools must be reviewed together. Do not reuse an old pool with a new registry or overwrite an existing deployment in place. No environment value or public deployment was switched in this review.

## Independent viewer and local demonstration

/arena/watch.html?contract=ADDRESS&round=1 reads directly from the Monad testnet RPC without an Orb cookie, wallet or Orb API. Add `&rules=4` for a Control v4 contract. Host this static page with observer.js and the matching OrbCommunityArena.json / OrbCommunityArenaControl.json artifact to view it separately. Identity and economy viewers also accept `rules=4`. They verify runtime bytecode but still trust their RPC provider; they are not light clients.

npm run arena:demo starts a loopback-only Ganache EVM, deploys a contract, creates two fixture communities and performs real local contract moves. It prints a viewer URL and saves public demonstration details in ignored work/community-arena-demo.json. All coins/accounts are local fixtures. Custom loopback RPC URLs work only when the viewer itself is served on localhost.

## Rules and practical limits

Control v4 gives a round a clear objective: maintain the highlighted core while protecting the supply path to your base. Capturing it at the last second cannot steal the other team's accumulated control time.

- Neutral claims cost 1 energy; attacks cost 2 and remove a shield or capture the final shield; reinforcement costs 3, up to 3 shields. Energy starts at 10 and regenerates 1/second. Each player has a one-second action cooldown.
- Both bases are protected. Claims and attacks need a cardinally adjacent **connected** sector. Isolated pockets cannot score, expand, attack or reinforce until a route to their base is restored.
- Every action on a sector, including an enemy hit, postpones its repair availability by four seconds. A defender cannot erase sustained attacks with continuous cheap reinforcement.
- Each connected owned sector gives one territory point. The active connected core earns one permanent control point per 2.5 seconds held (0.4/s), doubled during the final phase. Fractions carry across actions and phases; total theoretical core points are 84. Score reads never award points based on polling frequency.
- The six cores follow G4, F5, H3, E6, I2, D7 in 30-second phases. Every core is nine cardinal steps from **both** starting bases, including on the empty board. Highest territory plus earned control score at 180 seconds wins; a tie remains a tie.
- Teams must have equal numbers, 1–6 per side, before starting. The active roster stays fixed. Disconnections do not remove a player; a disconnected player can reconnect.

Existing practice v1/v2/v3 saves and deployed v2 contracts retain their original rules. Legacy v2 awards +8 at each 30-second boundary, uses the earlier core locations, counts owned territory and permits reinforcement for 2 energy. Practice v3 adds supply-based scoring and a doubled final award but lets islands act. New v4 removes those last-second capture and island-growth incentives.

Snapshots are pinned to one block. Active visible rounds check for a new head every 750ms, inactive rounds every 3 seconds and failures back off to 5 seconds. Refreshes do not overlap; hidden tabs pause. Registry refreshes happen on registration, rather than after each move. The directory currently shows the latest 100 communities.

V4 computes connected supply with a bounded traversal of the 96-sector board and checkpoints control time before mutations. The tested 33-move EVM scenario used at most 314,639 gas per move; this is a scenario measurement, not a worst-case proof. Legacy v2 keeps incremental territory scores. Shared round state, a serialized sponsor, authentication, RPC limits and polling remain bottlenecks. This is **not a 10,000 TPS benchmark**. Scaling needs independent concurrent rounds, relayer capacity, event indexing and load tests. UI receipt times include RPC/sponsorship delay and are not consensus-finality measurements. Relay history currently has no retention worker.

## Validation

    npm run arena:compile
    npm run arena:test
    npm run arena:test:community
    npm run arena:compile:control
    npm run arena:test:control
    node scripts/test-arena-community-control.mjs
    node scripts/test-arena-control-journey.mjs
    # In PowerShell, use the same isolated DB as the local server:
    $env:TURSO_DATABASE_URL='file:work/orb-hackathon.db'
    npm run arena:test:api
    npm run build

Local EVM integration covers rules, expiry, signature tampering/replay, revoked/reused sessions, duplicate admission, ownership and transfer permissions, fixed relay destination/value, idempotent sponsorship, bans, independent reads and single NFT claims. HTTP tests use disposable fixtures and cover authentication, CSRF, required Privy proof, public config, concurrent practice claims and settlement. These contracts have automated tests, but no independent audit.

## Gameplay validation

Deterministic tests compare real v4 contract state to the practice engine after 33 moves, including core theft, siege, supply cuts, rescue and the final deadline. Both v2 and v4 browser journeys use two fixture wallets, real local contracts, cross-client moves, trophies and funded test rewards. These are correctness tests, not evidence that players enjoy the game. Play equal teams with friends and measure contested objectives and rematch interest before choosing further balance changes. No new monetary reward or paid gameplay advantage was added.
