Ten hostiles hold a container yard. You have three minutes to clear it. A full tactical FPS that runs in your browser tab — no download, no install, no launcher. Free to play, right now — no invite code, no wallet, no sign-up.
Staking stays off until the contract is audited.
Four decisions. Everything between them is automatic.
Sign a free message to prove the wallet is yours. No transaction, no gas. Your player record is created by the contract the first time you deposit — there is no account to fund and no storage rent to pay.
Skirmish 1v1 at 0.0002 ETH, Duel 1v1, or Squad 5v5. Training is free and always open if you'd rather warm up against bots first.
You see the exact numbers before you commit — what you risk, what a win pays, and the rake. Cancel any time while queuing for a full refund.
Winnings land in your in-game balance so you can queue again without gas. Withdraw to your wallet whenever you like.
Stakes are fixed per mode so nobody can be pulled into a bracket they didn't choose.
The same duel at a fifth of the stake. Where placement is played — open to everyone.
Free-for-all. First to 10 kills takes it.
Team deathmatch. First team to 40 kills. Payout splits by personal score.
The full game against bots. No stake, no reward, no wallet needed.
Rake is 5% of the pot. The economy is closed and zero-sum: ETH paid out never exceeds ETH staked minus rake, so trading kills between your own accounts only burns rake. Matchmaking is server-side and random — you cannot pick your opponent.
What runs today, what is being built, and what is still only a plan. Each phase gates the next.
No dates. Phase 4 unlocks when the audit passes, not on a calendar — a shipping date is a bad reason to put a player's ETH behind unreviewed code.
HEXOPS is one file: a custom Three.js renderer and hand-written shaders running directly in a browser tab. No launcher, no install, no account. A fully rendered 3D match loads in seconds — on the machine you already have.
Stakes are designed to sit in the HexOps contract on Robinhood Chain — the contract's own balance is the vault — not in a company ledger, and settlement is a single on-chain transaction per match. The contract is written but unaudited and undeployed — no funds are held anywhere today.
Nothing is purchasable that changes how you shoot — no gear tiers, no NFT boosts, no paid advantage. Winning takes the pot minus rake; inside a team it splits by personal score. Elo decides who you are matched against, never what you are paid.
There are no audio files and no texture downloads. Every gunshot, footstep and impact is synthesized live through the Web Audio API, and the yard is generated at runtime — which is why the whole game ships as a single page instead of a multi-megabyte asset bundle.
How the economy, the contract and match integrity actually work — including what is not built yet.
HEXOPS is a closed, zero-sum economy. There is no token, no emission schedule and no faucet: the only ETH that can ever leave a match is ETH that players staked into it. Every payout is funded by an opposing player's loss, minus the protocol rake. This is a deliberate constraint — an economy that mints rewards from nothing is one that pays farmers faster than it pays players, and it always collapses.
| Term | Definition | Example — 1v1 @ 0.001 ETH |
|---|---|---|
| Pot | Sum of every player's entry stake | 0.002 ETH |
| Rake | Protocol fee, 5% of pot (platform_fee_bps, hard-capped at 10%) | 0.0001 ETH |
| Distributable | Pot − rake | 0.0019 ETH |
| Winner take | Full distributable in 1v1 | +0.0009 ETH net |
| Loser | Forfeits stake | −0.001 ETH |
The winning team divides the distributable pot in proportion to personal score, so carrying your team pays more than being carried:
score = kills × 1 + assists × 0.5 − deaths × 0.5, floored at 0.
For any match: Σ payouts + rake = Σ stakes. The contract never transfers more than
the escrow holds, and every state-changing call ends by asserting
address(this).balance ≥ totalLiabilities + pendingTreasury — the vault can never
hold less than it owes players.
HexOps is a single Solidity contract (^0.8.24) on Robinhood Chain, an
Arbitrum-Orbit L2 whose gas and stakes are both ETH. One contract holds everything: its own
ETH balance is the vault, and vaultBalance() just reads
address(this).balance. There is no separate vault account to fund, no storage
rent, and nothing to keep alive — EVM storage is paid for once at write time and then simply
exists. Arithmetic is checked by the compiler; there is no unchecked block on any
balance.
The contract is not upgradeable and sits behind no proxy. That is deliberate: an upgrade
key is a key that can rewrite the rules holding your money, and the honest way to remove that
risk is to not have the key at all. What remains is the authority — the backend's hot
key that creates and settles matches — and it is rotated in two steps
(transferAuthority nominates, acceptAuthority is signed by the
nominee), so a fat-fingered address cannot strand the contract.
Config — one struct. Authority, pending authority, treasury, rake in basis
points, entry-fee bounds, match timeout, the pause flag, lifetime volume and fees, and
totalLiabilities.totalLiabilities — the sum of every player balance plus every live escrow, and
nothing else. It is the provable amount the contract owes players, maintained on every
movement rather than computed by iteration.players[address] — career kills, wins, lifetime earned/lost, Elo, the in-game
ETH balance, the one-shot stake authorization, and any anticheat hold.matches[matchId] — escrow record, roster with teams, status, per-participant
score and payout. Match ids are strictly increasing, so a settled id can never be reused.pendingTreasury — fees the contract tried to push to the treasury and could
not. Pullable with claimTreasury(); see below.deposit() / withdraw(amount) — moves ETH between your wallet and
the contract. Both are signed by you; no authority can move a player's balance out.
withdraw is never pausable. A pause that traps money is a rug lever, so
the pause flag gates deposit, authorizeStake,
createMatch and settleMatch — and stops there.authorizeStake(maxStake, ttlSecs) / revokeStakeAuthorization() —
player-signed consent to be staked, capped in size and short-lived (30 minutes maximum;
the backend asks for ten). createMatch consumes it: one authorization, one
match, then it is zeroed.createMatch — authority only. Debits each roster wallet's available
balance into escrow. This is bookkeeping inside one contract, not a transfer, so
totalLiabilities does not move.settleMatch — authority only. Credits every participant, losers included,
updates stats and Elo, and takes the house's cut as the difference between the escrow and
the sum of payouts — refused outright if it exceeds either fee ceiling. The fee is
pushed to the treasury inside the same call; there is no sweep step and no fee
sitting in the contract waiting for someone to remember it. If the treasury cannot receive
ETH the amount goes to pendingTreasury rather than reverting, because a broken
payout address must not brick settlement for the players in the match.voidMatch / refundTimedOutMatch — full refunds, no fee. The second
is permissionless: once the match timeout has elapsed, anyone may call it. A backend
outage can never strand an escrow.lockPayout / releasePayout — the anticheat hold. It is a reserve
inside your own balance, and there is deliberately no function that can move a locked
balance anywhere but back to its owner. A lock expires on its own: nobody has to send
a transaction to free it, because available() simply ignores a lapsed one.receive() reverts. ETH enters only through deposit(), so nothing
can land in the contract without a player record to own it.The contract works in wei because msg.value does, but it requires every amount to
be a whole number of gwei. That is what lets the backend's ledger keep doing its money
arithmetic in integers — a wei is far too small to fit a JavaScript safe integer, a gwei is
not — so the mirror and the chain can be compared for exact equality rather than approximately.
Rating is computed in pure integer arithmetic against a precomputed expectancy table. Floating point in the EVM does not exist and fixed-point rounding differs between implementations; deterministic settlement requires integers.
A browser client is fully under the player's control. Any design that trusts what the client reports is not an anti-cheat design — it is an honour system with extra steps. HEXOPS is therefore built around a single rule: the client sends input, never outcomes.
These are sanity checks, not anti-cheat. The numbers still originate on the client, and the code says so in as many words. Presenting them as more than that would be dishonest.
Three staked modes, deliberately separated because they need different economics. Free-for-all is easy to collude in; team play is not. SKIRMISH and DUEL are the same format at different stakes, which is the only bracket that means anything while the population is too thin for Elo to say much.
| Mode | Format | Stake | Win condition |
|---|---|---|---|
| SKIRMISH | 1v1 free-for-all | 0.0002 ETH (about $0.50) | Bust the other player or lead at 5:00 |
| DUEL | 1v1 free-for-all | 0.001 ETH (about $2.50) | Bust the other player or lead at 5:00 |
| SQUAD | 5v5 team deathmatch | 0.0004 ETH (about $1.00) | Bust the other five or lead at 8:00 |
| TRAINING | Solo vs AI | None | Clear 10 hostiles, 5 min cap |
The dollar figures are indicative only: the stakes were set against ETH at roughly $2,500, and they are denominated in ETH, not in dollars. If ETH moves far enough that a SKIRMISH stops being pocket change, the ladder gets retuned — the numbers above are the current ones, not a promise.
Players start at Elo 1000. Rating transferred to the winner is K × (1 − expected)
with K = 32, always at least 1 point, and the loser never falls below a floor of 100. The
transfer is symmetric: the winner gains exactly what the loser loses, so the pool neither
inflates nor drains.
| Vector | Countermeasure |
|---|---|
| Kill-trading between own wallets | Zero-sum pot; collusion only burns rake |
| Picking a weak opponent | Random server-side matchmaking |
| Alt accounts / smurfing | Stake required up front; Elo-banded queue |
| Idling for a payout | Idle kick, stake forfeit |
| Rage-quitting a losing match | Disconnect scored as a loss FIX PENDING |
| Fabricated results | Server-authoritative scoring; client never reports kills |
Global ELO Leaderboard of HEXOPS Combatants
| Rank | Operator Wallet | ELO Rating | Total Wins |
|---|
A few percent of every settled match funds development and server costs. This is that money, read live from the chain — and the addresses to verify it without trusting us.
Loading treasury figures…
Stakes and in-game balances sit in the HexOps contract — its own ETH balance is the vault. The treasury is a separate address, and no treasury key can move a wei out of the contract: only the contract's own code can, and only to settle a match, refund one, or honour a withdrawal you signed. Every state-changing call ends by asserting the contract holds at least totalLiabilities, the amount it says it owes players.
The fee limit is not a promise on a web page. settleMatch checks it on chain: a settlement that tries to take more than the ceiling is refused outright, not quietly trimmed. Behind it sits a second ceiling fixed at deployment that no authority, including ours, can raise afterwards.
The fee is pushed to the treasury wallet inside settleMatch itself — there is no sweep step to forget. The second figure is the exception that proves it: if the treasury cannot receive ETH, the fee is parked in pendingTreasury instead of reverting the settlement, and stays claimable. Treasury money pays for development, servers, RPC and audits — nothing else.
Every number above is derived from these addresses. Open one in the block explorer and you are reading the chain, not our server.
Press play. The beta is open to everyone — no invite code, no payment, nothing to install, no transaction to sign, and no wallet needed until staking ships.
It was, while the escrow contract went into audit and the server-authoritative match loop was built. The gate has done its job, so the game is open — staked matches stay locked until Phase 3 clears.
No. The beta is the complete game — same map, same weapons, same AI — and costs nothing. A wallet only matters later, for staked matches.
None. Staking is disabled and no on-chain settlement is live. Nothing on this site can currently charge or pay you.
Yes, once staking ships. A staked match puts real ETH at risk: losing forfeits your entry. Never stake more than you can afford to lose.
The economy is zero-sum — payouts never exceed stakes minus rake, so trading kills between your own wallets only burns rake. Matchmaking is server-side and random, so you cannot choose your opponent.
HEXOPS is in closed testing while the escrow contract is audited and the server-authoritative match loop is hardened. Join the list and we send an invite code when the next wave opens.
Paste the code from your invite. It unlocks the game on this browser.
We'll send your invite code when the next wave opens.
LOADING ORDNANCE…