Docs/Examples/Forecaster Leaderboard

ForecasterLeaderboard (Prediction Accuracy Tracker)

Third hop in the 3-contract chain — scores prediction accuracy and distributes weekly prizes to top forecasters.


Overview

ForecasterLeaderboard is the third and final contract in the KaijuLeague → KaijuOracle → ForecasterLeaderboard chain. It reads settled KaijuOracle rounds, tracks per-address prediction accuracy over seasons, and distributes a prize pool to the top N forecasters at the end of each season.

PropertyValue
Base contractAutoLoopCompatible (no VRF)
VRF usageNone — reads accuracy data from KaijuOracle
Gas per tick~574k (3 forecasters, 1 round processed)
Sourceautoloop/src/games/ForecasterLeaderboard.sol
Tests32 passing (unit + fuzz)

Why This Is the Most Interesting AutoLoop Demo

ForecasterLeaderboard introduces four independent reasons a neutral keeper is structurally required:

  1. Adversarial distribution timing: a forecaster currently in 2nd place wants to delay distribution until they accumulate more correct predictions. A forecaster in 1st place wants it now. No player-controlled trigger is neutral.

  2. Cross-contract 3-hop dependency: distribution requires reading KaijuOracle's settled rounds, which in turn depend on KaijuLeague's clash outcomes. A player could fire distribution after a favorable round before rivals have committed to the next round.

  3. Free-rider on processing gas: processing rounds costs gas. Every individual forecaster prefers to let someone else pay while waiting to see if they accumulate enough correct predictions.

  4. Prize-pool timing attack: a player who can trigger distribution can choose a block where they have the most favorable rank.

This is a coordination problem spanning three contracts that no individual player can solve — only a neutral keeper.

The 3-Contract Chain

KaijuLeague (AutoLoop + VRF)
  └─ clashWinners(clashId) mapping
  
KaijuOracle (AutoLoop, no VRF)
  └─ reads clashWinners from KaijuLeague
  └─ roundParticipants[roundId][] for leaderboard indexing
  └─ revealedKaijus[roundId][address] for accuracy scoring
  
ForecasterLeaderboard (AutoLoop, no VRF)
  └─ reads settled rounds from KaijuOracle
  └─ scores per-address accuracy
  └─ distributes prize pool to top N each season

Season Model

  • Each season spans distributionInterval seconds (1 hour on testnet, 1 week on mainnet).
  • On each tick, up to maxRoundsPerTick oracle rounds are processed for accuracy.
  • Top topN forecasters by seasonCorrect share the prize pool equally.
  • Ties are broken by lifetimeCorrect.
  • After distribution, season counters reset and a new season opens.
  • Unclaimed prizes remain claimable indefinitely.

Settlement Logic

function shouldProgressLoop() external view override returns (bool, bytes memory) {
    loopIsReady = block.timestamp >= nextDistributionAt;
    progressWithData = abi.encode(currentSeason);
}

function progressLoop(bytes calldata data) external override {
    // 1. Process settled oracle rounds → update accuracy scores
    // 2. Find top N forecasters by seasonCorrect
    // 3. Distribute prize pool proportionally
    // 4. Reset season counters
    // 5. Advance nextDistributionAt
}

Revenue Model

  • protocolRakeBps (5%) on each prize pool distribution → protocolFeeBalance
  • Rounds with all zero-correct forecasters send distributable amount to protocol
  • Anyone can fund the prize pool via fundPrizePool() or direct ETH send
  • AutoLoop gas fees on each distribution tick

Deploy

# Deploy KaijuLeague and KaijuOracle first
ORACLE_ADDR=<deployed KaijuOracle address>

forge create src/games/ForecasterLeaderboard.sol:ForecasterLeaderboard \
  --constructor-args $ORACLE_ADDR 3600 3 50 500 \
  --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast

Args: kaijuOracle, distributionInterval, topN, maxRoundsPerTick, protocolRakeBps.

Dashboard

Play ForecasterLeaderboard on the AutoLoop Dashboard.

See also: KaijuOracle and KaijuLeague.