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.
| Property | Value |
|---|---|
| Base contract | AutoLoopVRFCompatible |
| VRF usage | Fisher-Yates shuffle of pool |
| Gas per tick | ~80k–200k (scales with pool size) |
| Source | autoloop/src/agents/MatchmakingEngine.sol |
| Tests | 27 passing (unit + fuzz) |
Why AutoLoop Is Structurally Required
Match assignments are front-runnable if the trigger holder can see them first. Without VRF:
- Worker computes the Fisher-Yates pairing off-chain before submitting the transaction
- Worker sees that Player A (strong) is paired with Player B (weak) and Player C (strong) is paired with Player D (strong)
- 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.senderto the pool. Duplicate registrations are no-ops. - deregister(): removes
msg.senderfrom 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 → emitsMatchMade(player1, player2, matchId, seed)for each consecutive pair; odd player out is skipped. IncrementsmatchCount, updateslastMatch.
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 --broadcastArgs: 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.