[{"content":"\nTake a classic arcade game, zero-knowledge proofs on my favorite blockchain, and a high score challenge, and you have the perfect recipe for a weekend of deterministic insanity. ^^\nkalien.xyz by Kalepail is a remake of the 1979 Atari classic Asteroids, warp-powered by ZK proofs on Stellar.\nThe mission: engineer a frame-perfect Asteroids run and escape the field with over 1 million KALIEN in a single tape. My weapon of choice: a CUDA-powered beam search.\nMission accomplished. Read below.\nThe Tape: 1 Million KALIEN, Zero Deaths Stellar transaction / Boundless proof / Tape replay\nClear phase 5,301 frames, 44,640 pts Farm phase 30,699 frames, 1,038,220 pts Avg farm rate 33.82 pts/frame Avg spawn timer 229.7 Best sustained rate 40.54 pts/frame (~1,900 frames) Avg pts per kill 865 pts (84.2% small, 15.8% large — RNG was kind this time) Deaths 0 Final score 1,082,860 The below-average small saucer rate got compensated by a favorable cosmic alignment in spawn timing (229.7 avg vs an expected 240). The beam cleared wave 7 in 5,301 frames, then farmed for the remaining 30,699 frames without a scratch.\nWatching the cumulative score closely track the theoretical curve was quite satisfying too:\nBut the more interesting question is: how far can this mission go?\nThe Math: Reading the Stars Kalien\u0026rsquo;s TypeScript engine is a faithful modern implementation of Asteroids and it comes with an anti-lurking mechanism (the classic lurking strategy actually forced Atari to issue a patched EPROM). The game enters lurk pressure mode if you stop killing asteroids and that pressure mode can be used as a scoring accelerator.\nIn lurk mode:\nAvg pts per kill: 911 (0.9 × 990 + 0.1 × 200) Avg spawn wait: 60 frames (timer resets to randomInt(180, 300), fire threshold 180, effective wait = randomInt(0, 120)) Kill cooldown: 10 frames (SHIP_BULLET_COOLDOWN_FRAMES) Avg cycle: 70 frames (avg spawn wait + cooldown) Given 3 concurrent saucers at wave 7, the expected average rate assuming perfect execution is: 3 × 911 / 70 = 39.04 pts/frame.\nSo with perfect execution and average RNG, the expected ceiling is ~1,289,000 (39.04 pts/frame). Getting past ~1,398,000 requires seed hunting for very favorable RNG rolls. Wave 8 or 9 (faster spawn rates) could present better crossovers on some seeds, but the time cost of clearing those extra waves is generally too high.\nThe Code I started by tweaking the built-in autopilot on kalien.xyz (just local overrides), running the beam search in the browser, and got to 350K+. But the frame rate degraded with browser performance hitting its limit.\nIt was time to bring in the mothership: C++ and CUDA.\nBeam search is the perfect fit for GPU where we can run thousands of expansions simultaneously, pruning using a fitness function.\nThe real pain point was porting the simulation to CUDA (even with AI assistance) because with ZK there is no tolerance. Just a small divergence from the original implementation, any bit off gets the proof rejected.\nAlso, porting bugs are subtle by nature. The one that cost me the most time was a child ordering issue in sim.cuh: CUDA fixed-size array means naive child assignment after a split reverses iteration order vs JS. To track this one down I had to compare the JS and CUDA runs frame by frame. The ZK verifier doesn\u0026rsquo;t do close enough but that is also the whole point.\nNow even the broken, unoptimized debug version was immediately scoring 500K+ locally and generating runs in seconds. So it was encouraging enough to keep pushing. Getting the CUDA simulation cycle-accurate took more iterations than I expected, but paid off eventually.\nFitness: The Best Defense Is Offense. With the simulation working, the initial ceiling seemed to be somewhere around 800–950K, depending on RNG.\nFrom that point I started to systematically record all runs frame by frame, comparing them after tweaking the beam fitness one signal at a time. Claude made the iteration loop fast enough that experimenting with the signal space was actually efficient.\nThe bottleneck was due to classic Asteroids instinct: play safe, don\u0026rsquo;t die. Every frame spent evading is a frame not spent farming, and in a fixed-length run, pts/frame is the only thing that matters.\nSo, the breakthrough came from reweighting the fitness function to penalize evasion heavily and reward aggression. Scores jumped past 1M almost immediately after adding that single line.\nf += (float)sim.saucerCount * 1000.0f; The full source is available at kalien-beam, MIT licensed. Feel free to use it, improve it, and farm your KALIEN, one million at a time ^^\nThere is more to build here too. CPU and OpenCL support are on the list to open this up to hardware beyond NVIDIA and get more people KALIEN hunting. Also, I experimented with a compute shader early on (during my browser experiments) but performance was very poor.\nBut as always, the bigger takeaway is not the score. What I learned will surely be useful for the next major release of Cyberbrawl. Honestly, I can\u0026rsquo;t wait to bring ZK proofs to a TCG. And if you beat my score in the meantime, let me know, I might just have to come back for another run ☺️\nTL;DR Goal: produce a deterministic replay scoring 1M+ KALIEN Implemented a CUDA-powered beam search to explore thousands of runs per frame Ported the Kalien engine to CUDA bit-perfect for ZK verification Final tape: 1,082,860 points, zero deaths Links\nTape Replay: Tape replay ZK Proof: Boundless proof Stellar tx: Stellar transaction Source (kalien-beam): kalien-beam Game: kalien.xyz Source (kalien): github.com/kalepail/kalien ","permalink":"https://kyungj.in/posts/million-kalien-tape-stellar-zk-gaming/","summary":"Engineering a 1M+ score in a ZK-powered Asteroids game on Stellar using a CUDA beam search.","title":"The One Million KALIEN Tape: A ZK Gaming Quest Through an Asteroid Field on Stellar"},{"content":"In my previous post I introduced xray.games, a trustless arcade on Stellar. In this article, I break down the core design decisions behind xray.games circuits, from parabola witnesses to hint-driven architectures where the prover does the heavy lifting.\nZK circuits punish brute-force thinking, and with their unbounded inputs, games hit that wall hardest.\nThis article focuses on circuit structure, witness design, and lessons from designing specifically for gameplay verification with the goal of keeping circuits practical yet attack-resistant.\nAll circuits discussed below are available in both Noir (w/ Poseidon2) and Circom (2.1.9 w/ circomlib Poseidon and comparators) in this repo.\nThe Chain Runner Circuit Sorry, your browser doesn't support embedded videos. Chain Runner is an infinite vertical runner where players control a sticky blob. To prove gameplay, a naive design approach would record raw player input (i.e. timing, duration, direction) then replay them inside the circuit, simulating against the same physics rules (gravity, friction etc.).\nHowever, this approach has two major problems:\nA script could easily brute-force and optimize input sequences directly against the circuit. It would not even need to run or know anything about the game. Survival is trivial for bots. A script does not make the mistakes that humans naturally make with imperfect timing. If score correlates with survival time, bots gain a massive advantage. Parabolas as Witness Between player inputs, the blob follows deterministic parabolic motion under constant gravity and friction. So a better design is to use these parabolic arcs as primitives for feeding the circuit.\nThe physics engine naturally produces them during gameplay so authentic sessions have them readily available while a cheating script must implement a correct physics simulation to produce valid inputs.\nEach parabola is captured as:\nx, y // position at start of parabola vx, vy // velocity from_state // entering blob state (jumping, falling, wall-sliding) to_state // exiting blob state hint // simulation step of exit point The circuit re-simulates physics from these parabolas and checks:\nEach parabola follows the correct equations of motion. Parabolas are sequential (e.g., no teleport). State transitions are valid and do not violate level geometry. The level data is unaltered (recomputing level_hash) Hints and Search Avoidance ZK systems are optimized for verification, not search. Encoding a search requires expressing the entire search space as constraints, it is costly. PLONKish backends with lookup tables and custom gates, or maybe even folding schemes for repeated computation, can mitigate constraint growth, but unbounded search remains costly, which is where hints come in.\nHints allow the prover to provide a candidate value computed off-circuit. Circuits treat them as untrusted input (non-asserted) and enforce constraints that validate them, avoiding the need to encode the search itself.\nFor Chain Runner, each parabola carries a hint indicating the simulation step at which the exit point occurs. Without it, the circuit would need to evaluate every step of the parabola to find the transition point (O(n²) across all).\nWith the hint, the circuit jumps directly to the claimed exit step and verifies correctness.\nCircuit Constraints Difference With hints 415,864 baseline With unconstrained hints (Brillig) 415,912 +0.01% Without hints 527,437 +26.8% Noir unconstrained functions (Brillig) offer another option with the circuit computing the hint internally with zero constraint cost. Overall, a nice optimization for Chain Runner, but it is not critical. For Chain Slicer, hints were essential (see below).\nDeterministic Levels The level is procedurally generated from a seed (Poseidon2 hashing) provided by the smart contract. It is encoded into a compact byte array (two rows pack into one byte: [left₀:2][right₀:2][left₁:2][right₁:2]).\nIf the level data can be tampered with, none of the other checks matter as an attacker could simply craft a level that guarantees a high score. By verifying in-circuit, we can ensure the player face the intended geometry and seeding from contract ensures fairness for all sides.\nThe circuit receives the packed array and computes a Poseidon2 hash:\nfn hash_level(level: [u8; MAX_BYTES], length: u32) -\u0026gt; Field { let mut hash: Field = 0; let mut acc: Field = 0; let mut count: u32 = 0; for i in 0..MAX_BYTES { if i \u0026lt; length { acc = acc * 256 + level[i] as Field; count += 1; if count == 31 { hash = hash2(hash, acc); acc = 0; count = 0; } } } if count \u0026gt; 0 { hash = hash2(hash, acc); } hash } This is exactly the kind of work circuits excel at because hashing is cheap in constraints, making it a natural fit for circuit verification.\nSliding Window Scoring As mentioned earlier, survival alone is trivial for a bot because timing is usually cheap to script. To counter this, I decided to use a sliding window with score counting unique bumper block hits within the window, not survival time or height.\nThe rationale is that maximizing bumper hits within a fixed window requires spatial search. The player must choose trajectories that reach scoring blocks, not just trajectories that avoid death.\nThis shift favors human visual pattern recognition over brute-force optimization via scripting, because the search space becomes combinatorial and constrained by physics.\nThe Chain Slicer Circuit Sorry, your browser doesn't support embedded videos. Chain Slicer is a geometry puzzle. Players partition polygons with line segments, ensuring that each resulting region contains only one object.\nThe circuit must verify:\nThe original level geometry is unchanged. The partitioning segments obey the game rules. The resulting partitions are valid. Each partition contains exactly one object. My first implementation simply mirrored the client\u0026rsquo;s verification logic inside the circuit. Every geometric relationship was brute-forced: segment intersections, edge traversal, partition reconstruction, containment checks. But with loop unrolling kicking in, the Noir circuit exceeded 100MB.\nI learned that what is trivial in normal code (if-else, loop) becomes constraints that multiply very fast in ZK circuits.\nDon\u0026rsquo;t Compute, Verify As mentioned earlier, ZK circuits are optimized for verifying claims, not for computation.\nSo I went back to the drawing board (which here, meant opening MS Paint) to reframe the slicer problem and that simple drawing gave me the solution.\nInstead of rebuilding the partitioning logic in-circuit, we can just validate the final structure (green). Given an initial polygon (blue), a set of partitioning segments (red), a list of claimed partitions, we have one rule to enforce: every partition edge must coincide with either an edge of the original polygon or one of the slicing segments.\nThe change didn\u0026rsquo;t require additional public inputs. The original level geometry is already provided as the circuit recomputes the level hash and partitioning segments and partitions are available as private inputs.\nUsing Hints to Collapse Search To further prevent an O(n²) search across vertices and edges, each edge carries a hint specifying its source. This reduced the circuit to roughly 5MB, with 273,511 constraints.\nThe circuit directly verifies colinearity against the hinted edge with each verification becoming O(1):\nif hint.source_type == 0 { let polygon = polygons[hint.source_index]; let index = hint.edge_index; edge_on_line(edge_start, edge_end, polygon.vertices[index], polygon.vertices[(index + 1) % polygon.vertex_count]) } else { let segment = segments[hint.source_index]; let start = Point { x: segment.x1, y: segment.y1 }; let end = Point { x: segment.x2, y: segment.y2 }; edge_on_line(edge_start, edge_end, start, end) } The tradeoff is that the prover does a bit more work. Alternatively here also, Noir unconstrained functions could compute hints directly inside the circuit at zero constraint cost. But the prover is the game client so it is already computing all geometry and collecting hints is trivial for authentic gameplay.\nObject placement uses the same pattern: the prover hints which partition contains each object, the circuit verifies with a winding-number point-in-polygon test.\nSummary Design Choice What It Prevents What the Attacker Must Do Parabola-based witness Input brute-forcing against the circuit Implement a correct physics engine and produce valid arcs Sliding window scoring Survival bots / grinding Must perform combinatorial trajectory search Deterministic level hashing Level tampering Match exact seeded geometry Edge provenance hints Geometry violations Provide valid edge provenance for every partition edge Object containment checks Invalid solutions Produce partitions passing winding-number containment The biggest lesson I would carry forward: don\u0026rsquo;t let the verifier do work the prover can do first.\nWatch my walkthrough on Youtube.\nOpen Source The xray.games contracts and circuits are open source — grab the code.\nLinks xray.games GitHub xray.games Live X-Ray, Protocol 25 Ohloss Stellar Game Studio ","permalink":"https://kyungj.in/posts/proving-gameplay-zk-circuit-design-xray-games-stellar/","summary":"ZK circuits punish brute-force thinking. In this article, I break down the core design decisions behind xray.games, from parabola witnesses to hint-driven architectures where the prover does the heavy lifting.","title":"Proving Gameplay: Zero-Knowledge Circuit Design for xray.games on Stellar"},{"content":" xray.games is live — a trustless arcade where player skill is proven entirely onchain through zero-knowledge proofs and deterministic simulations on Stellar.\nZK circuits typically focus on proving low-cost, tractable statements with known upper bounds (hash preimages, range checks, Merkle inclusion) where circuit shape is predictable.\nThe ZK circuits and contracts behind xray.games solve a different class of problem where the computational structure is dynamic, recursive, heavily shaped by player input from arbitrary polygon partitioning, edge-boundary containment, object physics, level integrity checks.\nGaming has historically pushed technical boundaries, but most computation-heavy workloads remain impractical onchain due to execution costs. Dark Forest, a pioneer in ZK gaming, burned through 7,000 ETH in gas (on Ropsten) during their seven-day beta.\nNow take the cheapest smart contract platform in crypto. Give it native ZK primitives with the X-Ray protocol. Do the math.\nThe Arcade Over the past decade I\u0026rsquo;ve designed and released 14 games. My most recent, Cyberbrawl, is a fast-paced TCG built on Stellar, focused on real ownership and P2P trading.\nxray.games is an opportunity to reimagine some of those ideas, and to push Cyberbrawl itself toward trustless gameplay.\nThree games are already live on the arcade:\nChain Slicer Chain Slicer is a spin-off of a geometry puzzle I created years ago. The game ranked #2 in the 2014 top 10 HTML5 games (when HTML5 was still experimental, and we were trying to push its limits), received a $40K Honorable Mention at the Linux Foundation \u0026amp; Samsung Tizen App Challenge (MWC Barcelona), and is still played daily on Coolmath Games, Famobi, ABCya, Math Playground and other gaming portals.\nThe original game shipped with 120 handcrafted levels with progressive difficulty, but over time video walkthroughs have enumerated every solution. For a trustless, skill-based arcade, static levels are a dead end, making procedural puzzle generation a requirement.\nDesigning a generator that produces puzzles which are both complex and provably solvable was one of the most interesting parts of this project, with Poseidon2 making the generation deterministic.\nChain Snooker The second game, Chain Snooker, is a spin-off of my Soroban Snooker demo, rebuilt with new graphics and significant fixes to the physics simulation. The client now uses the same fixed-point arithmetic as the contract, enabling optimistic score calculation with accurate feedback.\nChain Snooker features onchain pool physics validation, Ohloss integration, and is already live for play and faction warfare.\nChain Runner The third game is a vertical runner inspired by my earlier title Sticky Goo. I tweaked the rules to make it more accessible (e.g., removing vertical obstacles) while shifting the scoring model from height reached to stellar coins collected. The idea is to make scripted runs harder as high scores now require a spacial search component rather than simply maximizing survival time.\nThis was probably the most challenging and interesting circuit to design: it reconstructs parabolas from points and velocity data to validate the gameplay physics against the level layout.\nThe Circuits The circuits are available in both Noir (w/ Poseidon2) and Circom (2.1.9 w/ circomlib Poseidon and comparators).\nThe first working version for the Slicer circuit was simply mirroring my original game verification logic inside the circuit, compact code, written a decade ago and battle-tested through millions of play sessions, but it brute-forced every geometric relationship. It compiled but was completely unusable as loop unrolling pushed the Noir circuit past 100MB and blew up at runtime.\nTo make this work, the circuit was redesigned around a hint-based architecture. Witness hints reduced verification from O(n²) brute-force checking to O(n). This slightly increases prover complexity but shrinks the compiled circuit from ~100MB to ~4MB.\nBackend Constraints/Width Compiled Size Circom 458,578 3.5MB Noir 273,511 4.3MB Stellar natively supports BN254 pairings for Groth16, enabling full onchain verification of Circom proofs. Noir is more constraint-efficient for this workload, but currently lacks native support on Stellar. An alternative path would be integrating an external verifier such as ultrahonk_soroban_contract.\nSession Lifecycle \u0026amp; Trust Model Gameplay on xray.games is deterministic, reproducible, and verifiable onchain.\nThis is achieved through Poseidon2-seeded deterministic sessions with dual ZK proof submission paths: direct trustless or server-delegated with commit/reveal.\nNote: fairness in statistical distributions can be audited publicly (e.g. via open sourcing). This model does not address it.\nNo oracles or server-side validation is required. In xray.games, the server is a convenience layer, not a trust assumption. Players can either delegate proof generation and submission to the server, or download the prover, generate proofs locally, and submit directly to the contract.\nOhloss: Enroll and Represent Players can optionally login via their Ohloss wallet to engage in faction-based warfare (note: at the time of writing I have not yet tested against the official ohloss contract).\nOhloss, designed by @kalepail, is a gamified DeFi protocol where players deposit into a yield vault, earn faction points, pick a faction and wager FP against each other.\nSolving Synchronicity Ohloss flow is designed around synchronous matches where both players are present.\nThat works well for scheduled duels but can be impractical for sustaining active gameplay in always-on models where players drop in on their own schedule.\nTo address this, xray.games contracts implement asynchronous matchmaking, removing the need for scheduling coordination while maintaining the faction rivalry mechanics that make Ohloss engaging.\nNot enrolled yet? Pick a faction. Go represent!\n2-Player Edition A dedicated 2-player edition of Chain Slicer built with the Stellar Game Studio is live at sgs.xray.games (source), integrating Chain Slicer with the Game Hub contract on testnet.\nConclusion Gameplay is one of the hardest things to prove onchain: it is unbounded, shaped by player input, and computationally explosive. On most blockchains, that makes verification impractical.\nBuilt on Stellar, xray.games takes the real approach, embracing dynamic simulation and ZK proofs onchain for trustless gameplay verification.\nFinal boss cleared. Let\u0026rsquo;s grab the loot!\nSee you in the arcade.\nOpen Source The xray.games contracts and circuits are open source — grab the code.\nLinks xray.games GitHub xray.games Live X-Ray, Protocol 25 Ohloss Stellar Game Studio ","permalink":"https://kyungj.in/posts/trustless-gaming-stellar-xray-games/","summary":"Building a trustless arcade on Stellar where player skill is proven onchain — from ZK circuit design and hint-based optimization to deterministic session seeding and onchain physics simulation.","title":"Trustless Gaming on Stellar — X-Ray Pushed ZK Past the Final Boss"},{"content":" Google Play: A Bigger Arena We have been here since the early days, and seeing Cyberbrawl arrive on Google Play marks a real shift for us.\nBack in 2020, I spent nearly an hour on the phone with Apple Review trying to explain what we were building. The conversation went nowhere. A few days later, our app was removed from the store. Anything touching blockchain was treated as radioactive.\nFast forward to July 2023: Google Play updated its policy to permit blockchain-based digital content, including NFTs, within apps and games. Ownership models are no longer assumed to be extractive by default!\nI have written before about how blockchain can serve game design honestly with efficient infrastructures like Stellar — and Google\u0026rsquo;s policy change is a step toward this future where blockchain can coexist with mainstream game distribution.\nFor Cyberbrawl, more players mean stronger competition, deeper ranked ladders, and importantly more feedback for balancing.\nYet, Google Play does more than give games visibility; it provides an infrastructure that scales, plus native notifications for tournaments and events. This is where web distribution hits its ceiling.\nIt changes how our game lives.\nWhat It Unlocks Cyberbrawl\u0026rsquo;s arrival on Google Play unlocks two reward tracks.\nEarly Access Pre-registration is now live on Google Play in most regions. Players who pre-register will receive early access ahead of the official launch.\nEveryone who joins early access through Google Play will unlock a special card back, along with ION and SHARD packs to get started.\n→ Pre-register on Google Play\nThe Vanguard Tournament The Vanguard Tournament registration is now open on Discord.\nRegistration closes December 31st at midnight. Post your battle ID in the #vanguard-tournament channel to enter.\nParticipants will receive a Competitor Pack, including ION for crafting, and a badge for the arena.\nThe tournament includes a $1,000 prize pool for top competitors.\nOnce registration closes, tournament details—seeding, brackets, and rewards—will be available in the Battle Nexus in-game. All matches will be replayable, just like our previous tournament.\nYou can start preparing now: practice vs AI and build your arena decks.\nJoin the Discord. Mark your calendar. The arena opens soon.\nIn the meantime, check out the last Cyberbrawl Grand Finals and study how the best players do it.\nSee you in the arena.\nCyberbrawl Grand Finals | Marlo vs Tarakanalada\n","permalink":"https://kyungj.in/posts/cyberbrawl-googleplay-unlocks/","summary":"Cyberbrawl on Google Play, pre-registration is live, and the Vanguard Tournament opens the arena gates.","title":"Cyberbrawl on Google Play: What It Unlocks"},{"content":"Regardless of scale, shipping a game is always a challenge that requires a precise balance of art and engineering. Over time, I have come to think that game design is to software what storytelling is to language.\nCyberbrawl, my latest project, was no exception. It pushed me at every turn, even more so with the extra layer of building on Stellar where onchain experimentation rarely comes with a blueprint.\nHowever, I strongly believe that while blockchain adds intriguing possibilities, it doesn\u0026rsquo;t alter how a game\u0026rsquo;s core is actually built.\nCyberbrawl: Build Your Tournament Decks, Enroll \u0026amp; Compete!\nHype Is Not a Game Loop I still see many blockchain games treating the chain itself as source of meaningful participation with teams obsessing over tokens, mint schedules and economies before they have anything playable. That mindset has produced a whole ecosystem of onchain (sic, vanity) metrics.\nThis approach may help create the initial burst of hype. But the truth is that working backward from hype into a coherent game is extremely hard. A few manage it (e.g., the No Man\u0026#39;s Sky turnaround miracle) but those are the exception.\nHype-first design is a huge bet; and I would rather know the game before going all in.\nThe Core Loop Is Still the Only Layer That Matters A game reveals its core early; that\u0026rsquo;s why I always start with the simplest prototypes. They help in two important ways:\nThe creative process constantly tempts you with illusions: another clever mechanic, another cool feature. Scoping discipline helps, but the real shortcut is trusting prototypes over ideas. Once you have a playable prototype, you begin to notice the things that matter like tension, resolution, depth. When the core loop works, every other layer (graphics, content, effects\u0026hellip;) becomes leverage. And this applies to any project size. In fact, the smaller the loop, the harder the craft because tension lives in thinner margins. Just a small gravity tweak in Flappy Bird, an increased spawn rate in a tower defense, can completely break the game.\nMy projects have always reminded me that the core loop is nonnegotiable.\nCyberbrawl also started with a simple prototype, no fancy graphics, no effects, no blockchain. If the core loop doesn\u0026rsquo;t work, no amount of production or extra layers can fix it.\nPlay Transcends Layer Zero Play is not a universal language because it resonates differently based on the audience. That\u0026rsquo;s why my first question is always: who is this game for?\nMost of my design choices for Cyberbrawl were shaped by the answer to this question. The game sits inside a TCG framework, a genre that typically appeals to midcore or hardcore players—but I wanted it closer to casual-midcore, a space that feels more web-native and less niche.\nAs a longtime Hearthstone fan, I am familiar with the genre rituals: long turns, meta knowledge, punishing Legend rank grinding. Those hardcore elements are engaging for most TCG players but none survive a casual audience. Knowing your players is not optional.\nClimb to Legend Rank – Hearthstone – full stream on my channel\nI was in a meeting with a major Korean game publisher looking to move into blockchain, and they asked me which chain players prefer, or why I picked Stellar. The truth is, ETH vs Solana vs Immutable is merely noise. It does nothing to define your target audience because the heart of a game experience never lives on layer zero. And in fact, no amount of onchain polish can replace knowing what players come for.\nI actually think major publishers are the best positioned to push this space forward precisely because they deal with real games, real players.\nPlay Is Crafted, Not Minted Cyberbrawl was forged from day one for that casual-midcore, web-native audience.\nThe first requirement was: no broken decks. I wanted players to be able to jump into a match without needing meta knowledge or spreadsheets, right after clicking the Play button. So, the shuffle algorithm was built to avoid clumping and enforce functional curves.\nThe energy system came from the same mindset. In Cyberbrawl, energy creates a natural pressure curve instead of leaning on the usual mana tax. It is transient. You can drain it, coalesce it, redistribute it. That fluidity gives all cards built-in comboability (e.g., Barricade can convert Biohazard Damage into Armor) and turns the hand into an energy surface. Casual players can read this system very easily, while midcore players find plenty of tactical depth in the flows.\nIt is easy for blockchain games to lean too heavily on tokens and onchain mechanics, but that rarely aligns with what a real game audience wants. When engagement is built around tokens and transactions rather than a crafted play experience, the result speaks to crypto users rather than players.\nDo Not Gas Your Game Out Flow is fragile. And blockchain adds a lot of friction via consensus delays, security requirements, ad hoc UX. Even 5 second finality on Stellar is too disruptive inside a core loop. That\u0026rsquo;s why, when designing Cyberbrawl, I made sure the loop never needed blockchain.\nAnd this extends beyond games. Take the hype around the x402 protocol, it\u0026rsquo;s easy to imagine an army of x402-enabled AI agents stuck waiting on micropayment confirmations. That design (or lack of) also assumes that agents can\u0026rsquo;t simply decouple payment from execution. Honestly, simple recurring subscriptions give you proper encapsulation: more flexible, more secure, more scalable, and with no latency.\nIn my experience, crossing layer boundaries without proper encapsulation tends to cause problems. Essentially, if you drag consensus into your game loop, the experience will suffocate.\nNow I believe that when blockchain is kept at the right layer, properly encapsulated, it strengthens and enables use cases never possible before: ownership, permanence, identity, provability, payments.\nAnd practically, platforms like Stellar, with their focus on cost-efficiency and speed, allow us to achieve this quietly in the background.\nPlayers Want Fun As players, we remember fun. That\u0026rsquo;s why the cycle of tension and resolution is so important in games.\nIn Cyberbrawl, the entire roster is shaped around it. Overload cards create explosive tempo spikes, Biohazard and Shockwave deliver the big-number bursts players love (or hate), drain cards punish greed, Overclock expands the energy surface for late-game swings. Every component is there to support the emotional peaks that make a match stay with us.\nBy contrast, I have seen plenty of blockchain reward models trying to atomize fun into micro-ticks. They confuse frequency with tension. What keeps me jumping back, seasons after seasons, into the PvP madness of rated Arena in World of Warcraft, is uncertainty, anticipation, the surge. PvP Rated Arena, Season 3\nFun doesn\u0026rsquo;t require finality. Minting cards before the game is like printing Olympic medals before deciding the discipline and the rules.\nBlockchain Is the Continuity Layer Now blockchain finality can preserve what fun produces, as long as it does not disrupt the loop that orchestrates fun in the first place.\nI believe that blockchain shines when it quietly extends the player\u0026rsquo;s experience beyond the game:\nletting achievements, progress, skill, and reputation cross over to new experiences. giving players decentralized ownership over the items they earn, craft, or discover. Used at this layer, the chain does not alienate play. On the contrary, it gives players a kind of continuity they never had before: a sense of persistence, that what they build, earn, collect does not reset with every patch or sequel.\nThis is exactly the layer where I use blockchain in my games.\nIf you are curious and want to learn more, catch the latest Cyberbrawl Grand Finals, try the game and join the next tournament.\nMost of all, have fun! See you in the arena.\nCyberbrawl Grand Finals | Marlo vs Tarakanalada\nThanks for reading!\n","permalink":"https://kyungj.in/posts/blockchain-game-design-cyberbrawl-stellar/","summary":"The heart of a game experience never lives on layer zero. In this article I reflect on how Cyberbrawl was built to preserve play with blockchain.","title":"Fun Does Not Need Finality: Blockchain Game Design with Cyberbrawl on Stellar"},{"content":"Soroban is so lean that a fully invocable smart contract fits in 65 bytes. And that\u0026rsquo;s 65 bytes of zero utility yet the best kind of holiday project ^^\nGrab the code on GitHub.\nFor those who prefer to get straight to the point, here\u0026rsquo;s my WAT:\n(module (func (export \u0026#34;\u0026#34;) (result i64) i64.const 2)) Binary:\n0061736d010000000105016000017e030201000704010000000a0601040042020b 001e11636f6e7472616374656e766d6574617630000000000000001400000000 Upload/Invoke Transactions (mainnet):\nTx 938c6619dd407eaf303eb79687585fc793c47b6c6aa19ba14e5708e9f6041d1d Tx f4c1d2abf2a777d44304a6c89df1a69d0ecb805d22618ffd77382f295ca12a55 Tx 21dd674460387f0e0775a42e73401d508d31751d8a1d8b9c27d72ba6f8e5a907 Tiny Soroban challenge This morning I came across this post in the Stellar Developer discord server and decided to take on the challenge for the weekend:\nkalepail \u0026gt; Fun over-Christmas challenge. Can you beat my smallest invokable soroban contract high score of 66 bytes? https://futurenet.steexp.com/contract/CC4QBKSZKUJNVHMAOYRV4SSE24WRFQ3VAL4IX6PONPBSOFHQFC5F6IDB/code-wat\nThe WAT looks like this:\n(module (type (;0;) (func (result i64))) (func (;0;) (type 0) (result i64) i64.const 2) (export \u0026#34;r\u0026#34; (func 0))) Looking at it closely, it seemed there was no room for compacting the module further: one export, one function, mandatory return type for an invokable contract and 1 byte length function name.\nWASM binary generated: 34 bytes.\n[magic:4][version:4][type_sec:7][func_sec:5][export_sec:6][code_sec:8]\nSo, I first tried to strip the custom sections but the smart contract was rejected with the following error:\n0: [Diagnostic Event] topics:[error, Error(WasmVm, InvalidInput)], data:\u0026#34;contract missing metadata section\u0026#34; Then, I found this in the reference Soroban documentation:\nhttps://soroban.stellar.org/docs/reference Contracts must contain a Wasm custom section with name contractenvmetav0 and containing a serialized SCEnvMetaEntry\nThe minimum size for this section alone is 32 bytes. The only way to reduce the binary size, given these current Soroban specifications, was to find a way to shrink the module code.\nSolution Here is what the wasm spec says:\nname ::= char∗ (if|utf8(char∗)|\u0026lt;2^32)\nFunction names (utf8(char∗)) can have a length of zero. So hypothetically, we could take one byte off the 34 bytes (export section).\nSo, the WAT can be written more compactly like this, resulting in the same output except for the export section, which can now be one byte shorter:\n(module (func (export \u0026#34;\u0026#34;) (result i64) i64.const 2)) And the generated binary:\n0061736d010000000105016000017e030201000704010000000a0601040042020b [magic:4][version:4][type_sec:7][func_sec:5][export_sec:5][code_sec:7]\nAppending the meta section, we get:\n0061736d010000000105016000017e030201000704010000000a0601040042020b 001e11636f6e7472616374656e766d6574617630000000000000001400000000 When you build the transaction, just specify an empty string for the contract call.\nnew Contract(StrKey.encodeContract( Address.fromScAddress( response.returnValue.address()).toBuffer())) .call(\u0026#34;\u0026#34;) Upload and Invoke it If you want to experiment further, you can write your WAT code directly at the top of the script. It will convert it to WASM binary and append the contractenvmetav0 section, so no need to use external tools.\n// Try some new WAT here: const wat = ` (module (func (export \u0026#34;\u0026#34;) (result i64) i64.const 2))`; ","permalink":"https://kyungj.in/posts/tiny-soroban/","summary":"Soroban is so lean that a fully invocable smart contract fits in 65 bytes. I took on this playful Christmas holiday challenge: crafting the tiniest invocable Soroban smart contract on Stellar.","title":"The Tiniest Smart Contract: 65 Bytes Stellar Contract"}]