Docs/Examples/Matchmaking Engine

MatchmakingEngine (Front-run-proof Pairing)

Uses VRF to pair players from a live pool — the trigger holder cannot preview match assignments before they're committed on-chain.


Overview

MatchmakingEngine maintains a registered player pool and periodically pairs players into matches using on-chain randomness. AutoLoop fires the match tick at the committed interval; the VRF proof is verified on-chain so no one — not the operator, not a worker — can see the pairing before it's final.

PropertyValue
Base contractAutoLoopVRFCompatible
VRF usageFisher-Yates shuffle of pool
Gas per tick~80k–200k (scales with pool size)
Sourceautoloop/src/agents/MatchmakingEngine.sol
Tests27 passing (unit + fuzz)

Why AutoLoop Is Structurally Required

Match assignments are front-runnable if the trigger holder can see them first. Without VRF:

  1. Worker computes the Fisher-Yates pairing off-chain before submitting the transaction
  2. Worker sees that Player A (strong) is paired with Player B (weak) and Player C (strong) is paired with Player D (strong)
  3. Worker withholds the transaction until it has placed bets on Player A winning, then submits

AutoLoop's VRF integration means the randomness is committed in the transaction itself and verified on-chain. The worker cannot see the pairing until the transaction is final. The match interval enforces that pairing happens on schedule — not when an operator decides conditions are favorable.

The same attack applies to any system where pairing or seeding order has economic value: esports brackets, ranked matchmaking, NFT tournament seeding.

Mechanics

  • register(): adds msg.sender to the pool. Duplicate registrations are no-ops.
  • deregister(): removes msg.sender from the pool using swap-and-pop (O(1)).
  • shouldProgressLoop(): pool.length >= 2 && block.timestamp - lastMatch >= matchInterval
  • progressLoop(progressWithData): calls _verifyAndExtractRandomness() → Fisher-Yates shuffle of pool using VRF seed → emits MatchMade(player1, player2, matchId, seed) for each consecutive pair; odd player out is skipped. Increments matchCount, updates lastMatch.

Revenue Model

  • AutoLoop gas fee on each tick
  • No protocol fee (pure pairing primitive — revenue comes from the game layer consuming match results)

Deploy

forge create src/agents/MatchmakingEngine.sol:MatchmakingEngine \
  --constructor-args 3600 \
  --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast

Args: matchInterval (seconds between match ticks). 3600 = 1 hour between match rounds.

After deploy, register with AutoLoop and fund the balance. Players call register() to join the pool.

Dashboard

View MatchmakingEngine on the AutoLoop Dashboard.