Skip to main content

Concept

We aim to build a secure, manipulation-resistant PvP arena using EVM-compatible smart contracts. All core actions such as betting, creating and joining games, opening/closing positions, and finalizing are performed on-chain. The backend plays a supporting role: validating on-chain activity, relaying messages between players, and tracking game states.

The current flow idea for on-chain gameplay is as follows:

Game sequence


Backend Responsibilities

Event Listener​

  • Listens to smart contract events
  • Tracks and syncs game states (pending, active, completed) with a centralized DB
  • Keeps game data fresh for frontend UX (matchmaking, game history, rewards)
  • Removes games if the creator goes offline

Game Status and Matchmaking API​

  • /api/game/create validates initGame transactions
  • /games/waiting-for-opponent returns available games to join
  • /api/game/start validates joinGame transactions

Signature Relay​

  • /api/position/signature provides backend EIP-712 signature for opening positions
  • WebSocket or long polling is used to relay signature requests:
    • Player 2 β†’ Backend β†’ Player 1 β†’ (Signs) β†’ Backend β†’ Player 2

Game Watchdog​

  • Tracks whether the game creator (Player 1) is online
  • Hides the game from the list if the creator is offline
  • During joinGame, the contract validates Player 1’s short-TTL signature, proving they were online and approved the join

Frontend Responsibilities

Game Start​

  • User clicks β€œStart Fight” and selects a fighter
  • Frontend queries /games/waiting-for-opponent
  • If a game is found, it requests a join signature from Player 1 via backend
  • If no game is found, frontend calls initGame(poolAddress, betAmount)
  • After the transaction is confirmed, backend validates it via /api/game/create

Matchmaking UI​

  • Displays a waiting screen with a countdown
  • Optionally subscribes to real-time updates via WebSocket

In-Game Trading​

  • openHashedPosition(gameId, directionHash, backendSignature) is used to open a position (direction is hidden initially)
  • Signature is retrieved from /api/position/signature
  • closePosition(gameId, direction, nonce) is used to reveal and close the position

🏁 Finalization​

  • Once both players have closed their positions, the creator finalizes the game via finalizeGame(gameId)
  • If someone is unresponsive, backend triggers forced finalization after timeout

Smart Contract Core Functions

  • initGame(poolAddress, betAmount) locks the bet and creates a game
  • joinGame(gameId, poolAddress, betAmount, joinSignature) lets the second player join
  • openHashedPosition(gameId, directionHash, backendSignature) opens a hashed position
  • closePosition(gameId, direction, nonce) reveals and settles the position
  • finalizeGame(gameId) settles rewards and closes the game

Game Pool Whitelist

  • The contract stores a whitelist of allowed DEX pools for each network
  • Only the owner can modify the list to prevent use of fake or manipulatable pools
  • The contract uses these whitelisted pools to fetch real-time prices for PnL and trade validation

Open Questions

  • How to efficiently track intermediate game state (e.g., opponent’s position, PnL) β€” will likely be handled off-chain via event polling

Fail-safes and Abuse Prevention​

  • Join TTL signatures required from Player 1
  • First-come, first-serve enforcement on backend and contract
  • Pool whitelist enforced in contract

Security Measures

  • Only whitelisted pools are used
  • All actions require confirmed on-chain transactions
  • TTL-based join signatures ensure liveness and prevent stolen entries
  • Backend signs position hashes to enable forced closure if needed