Deploy to Arena
This guide covers the full deployment pipeline — from packaging your game through quality gates, review, catalog listing, versioning, and revenue. For building the game itself, see Build a Game.
Prerequisites
Section titled “Prerequisites”Before deploying, your game must:
- Implement the complete
Game<TState, TAction>interface - Include a valid
ludus.manifest.json - Pass all four quality gates locally (SDK Compliance, Security, Determinism, Performance)
Packaging
Section titled “Packaging”-
Build your game
Terminal window npm run build -
Verify the package structure
my-game/├── ludus.manifest.json├── dist/│ └── index.js├── public/ # optional assets└── README.md # optional, shown in catalog -
Create the archive
Terminal window tar -czf my-game.ludus.tar.gz -C my-game .All files referenced in the manifest (
game.file,assets[].path) must exist in the archive.
Submission
Section titled “Submission”Submit your package through the SubmissionService:
import { SubmissionService, InMemorySubmissionStore,} from "@ludus/game-protocol";
const service = new SubmissionService(new InMemorySubmissionStore());
// Step 1: Upload package → DRAFTconst submission = service.submit(packageContents, "your-wallet-address");console.log(`Submission ${submission.id} created as DRAFT`);
// Step 2: Submit for review → runs all quality gatesconst reviewed = service.submitForReview( submission.id, packageContents, () => MyGameImplementation,);The submitForReview() call transitions the submission through PENDING → TESTING (runs all quality gates) → REVIEW (all pass) or REJECTED (any fail).
Duplicate Detection
Section titled “Duplicate Detection”You cannot submit a game with the same name + version if an active submission already exists. Bump the version or wait for a previous REJECTED submission to clear.
Quality Gate Process
Section titled “Quality Gate Process”Four gates run sequentially. All must pass.
1. SDK Compliance
Section titled “1. SDK Compliance”Checks that your game object has all 8 required methods/properties:
| Method/Property | What It Checks |
|---|---|
metadata | Property exists with required fields |
initialize() | Returns valid initial state |
getValidActions() | Returns action array |
executeAction() | Returns new state |
isGameOver() | Returns boolean |
getWinner() | Returns Player or null |
getRankings() | Returns PlayerRanking array |
describeAction() | Returns string |
Fix failures: Implement every method. No stubs that throw.
2. Security
Section titled “2. Security”Scans source code for banned patterns:
| Pattern | Why Banned |
|---|---|
| Arbitrary code execution | Dynamic code generation |
Function() | Dynamic code generation |
require() | Module loading |
fs.*, readFile, writeFile | File system access |
fetch, XMLHttpRequest, http. | Network access |
process.env | Environment leakage |
child_process | Process spawning |
__proto__ | Prototype pollution |
Dynamic import() | Dynamic module loading |
Fix failures: Remove all I/O, network, and dynamic code from game logic. Keep it pure.
3. Determinism
Section titled “3. Determinism”Runs your game 3 times with seed 42 and 2 players. All runs must produce identical state sequences.
Fix failures:
- Replace
Math.random()withrng.next()orrng.nextInt() - Replace
Date.now()with turn counters - Use
structuredClone()inexecuteAction()instead of mutation
4. Performance
Section titled “4. Performance”Runs executeAction() for 50 turns. Each turn must complete within 5 seconds.
Fix failures: Profile your game logic. Avoid O(n!) or O(2^n) algorithms. Cache expensive computations.
Checking Results
Section titled “Checking Results”if (reviewed.status === "REVIEW") { console.log("All gates passed!");} else if (reviewed.status === "REJECTED") { console.error("Rejected:", reviewed.rejectionReason); for (const result of reviewed.qualityResults) { if (!result.passed) { console.error(` ${result.gate}: ${result.details}`); } }}Review
Section titled “Review”After passing all quality gates, the submission enters REVIEW status. Human reviewers (or DAO governance) evaluate:
- Gameplay quality — Is the game fun and well-balanced?
- Originality — Does it add value to the catalog?
- Documentation — Is the README clear?
- Fair play — No exploits or degenerate strategies?
The reviewer approves or rejects with notes:
// Approve → LISTEDservice.approve(submission.id, "Great game, well-tested.");
// Or reject → REJECTEDservice.reject(submission.id, "Needs balancing work", "Player 1 wins 95% of the time.");Catalog Listing
Section titled “Catalog Listing”Once approved, the game appears in the catalog:
import { CatalogService, InMemoryCatalogStore } from "@ludus/game-protocol";
const catalog = new CatalogService(new InMemoryCatalogStore());
// List the approved gamecatalog.listGame(approvedSubmission);Your game is now discoverable through:
- Text search — by name, description, or tags
- Category browsing — strategy, economic, social, card, dice, territory, puzzle, party
- Popularity ranking — weighted score from downloads, ratings, recency, completions
- Recent listings — newest games first
Players can rate your game (0-5 stars), and the popularity score updates automatically.
Versioning
Section titled “Versioning”Publish updates using semver:
import { VersionManager, InMemoryVersionStore } from "@ludus/game-protocol";
const manager = new VersionManager(new InMemoryVersionStore());
// Register initial versionmanager.registerVersion("my-game", "1.0.0", "hash-abc");
// Publish a patch (bug fix)manager.registerVersion("my-game", "1.0.1", "hash-def");
// Publish a minor update (new feature)manager.registerVersion("my-game", "1.1.0", "hash-ghi");Each new version goes through the same submission and quality gate process.
Deprecation
Section titled “Deprecation”When you publish a new version, you can deprecate the old one:
manager.deprecateVersion("my-game", "1.0.0", "Security fix in 1.0.1");Deprecated versions remain playable for a 30-day grace period. Players see a warning and a pointer to the latest version. After the grace period, the old version is unlisted.
Migration Paths
Section titled “Migration Paths”Check whether an upgrade is breaking:
const path = manager.getMigrationPath("my-game", "1.0.0", "2.0.0");// path.breaking: true (major version jump)// path.intermediateVersions: count of versions betweenRollback
Section titled “Rollback”If a new version has issues, roll back:
manager.rollback("my-game", "1.0.0", "immediate");Rollback policies: "immediate" (instant), "grace-period" (scheduled cutover), "manual" (requires confirmation).
Revenue
Section titled “Revenue”The Ludus protocol distributes platform fees to game developers.
Fee Split
Section titled “Fee Split”| Recipient | Share |
|---|---|
| Game developer | 70% |
| Ludus protocol | 30% |
How Fees Accumulate
Section titled “How Fees Accumulate”Fees are recorded from match entries, betting, and in-game transactions:
import { RevenueEngine, InMemoryRevenueStore } from "@ludus/game-protocol";
const engine = new RevenueEngine(new InMemoryRevenueStore());
// Fees accumulate automatically as players use your gameengine.recordFee("my-game", "dev-wallet", 100, "USDC");Revenue Reports
Section titled “Revenue Reports”Track your game’s performance:
const report = engine.getRevenueReport( "my-game", new Date("2026-01-01"), new Date("2026-03-31"),);// report.totalFees — gross platform fees// report.developerShare — your 70% cut// report.protocolShare — protocol's 30%// report.feeCount — number of fee eventsPayouts
Section titled “Payouts”Request a payout when your earnings meet the minimum threshold:
const payout = engine.createPayout("dev-wallet", periodStart, periodEnd);// payout.status: "pending"
// After on-chain settlement:engine.completePayout(payout.id, "0xtxhash...");// payout.status: "completed"Payout lifecycle: pending → processing → completed (or failed with reason).
Wallet Setup
Section titled “Wallet Setup”Set author.wallet in your ludus.manifest.json to receive payouts. Without a wallet address, fees accumulate but cannot be paid out.
Developer Portal
Section titled “Developer Portal”Once your game is listed, monitor it through the catalog:
- Downloads — tracked automatically via
catalog.recordDownload() - Completions — tracked when games finish via
catalog.recordCompletion() - Ratings — player ratings on a 0-5 scale
- Popularity score — composite score (0-100) based on downloads (40%), rating (30%), recency (20%), completions (10%)
- Revenue — fee reports and payout history
Error Reference
Section titled “Error Reference”| Error | Cause | Fix |
|---|---|---|
ManifestValidationError | Invalid manifest fields | Check field rules in Game Protocol |
DuplicateSubmissionError | Same name+version exists | Bump version |
InvalidTransitionError | Illegal status transition | Follow the submission flow |
DeterminismGateError | Non-deterministic game | Use SeededRNG, no Math.random() |
SecurityGateError | Banned code pattern found | Remove I/O, network, dynamic code |
SDKComplianceError | Missing Game interface methods | Implement all 8 methods/properties |
See Also
Section titled “See Also”- Build a Game — implementing the Game interface
- Game Protocol — full protocol reference
- Create an Agent — for agent deployment