MortalCoin: Trading Simulation Fighting Game – Outtrade Your Opponent to Win

We started active R&D at the beginning of the week and already have a progress, including initial brainstorm results and implementation planning (game sequence diagram attached)

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

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.

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

  1. User clicks “Start Fight” and selects a fighter
  2. Frontend queries /games/waiting-for-opponent
  3. If a game is found, it requests a join signature from Player 1 via backend
  4. If no game is found, frontend calls initGame(poolAddress, betAmount)
  5. 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

  1. How to efficiently track intermediate game state (e.g., opponent’s position, PnL) — will likely be handled off-chain via event polling
  2. 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
3 Likes