Skip to content

Security: lingjieheti-ops/turing-arena

Security

SECURITY.md

Security & threat model

A concise, honest threat model for Turing Arena. It is a hackathon project (not audited); this documents the design's security posture and known limits up front.

Component threat model

Commit–reveal (ProofOfAlpha)

  • A prediction is bound as keccak256(agentId, predictedBps, confidence, rationaleHash, salt). Reveal recomputes the hash and reverts on mismatch (CommitMismatch).
  • Phases are time-boxed: commits only ≤ commitDeadline, reveals only in (commitDeadline, revealDeadline], settlement only ≥ settleTime. This makes peeking, copying, and backfilling impossible.
  • Commit and reveal are restricted to the agent's controller (isController). Double-commit / double-reveal revert.

Reputation integrity (ERC-8004)

  • Feedback is third-party only: the agent's owner/operator cannot rate their own agent (SelfFeedbackForbidden). The neutral ProofOfAlpha contract is the attestor, so reputation reflects oracle-verified outcomes, not self-reporting.

Oracle

  • IPriceOracle is pluggable. ReporterPriceOracle is permissioned (authorized reporters) and tags every price with provenance. MantleDexOracle reads a live Merchant Moe quote.
  • Known limit: a single-block DEX spot quote is manipulable (e.g., flash-loan). For production, route through a TWAP / deeper liquidity and/or gate settlement via the ERC-8004 Validation Registry. The settlement price is captured once per round to avoid mid-settlement drift.
  • Trust assumption (testnet): live rounds settle off ReporterPriceOracle, a permissioned push oracle fed by Pyth Hermes (CoinGecko fallback). The reporter is trusted — reveals are public before settleTime, so a malicious/compromised reporter could push a settlement price favoring a chosen agent — and settle does not yet bound price freshness (IPriceOracle.getPrice returns updatedAt, currently unused), so a stale push could settle a round. Mainnet hardening: a TWAP/median settlement source plus a maxStaleness bound on updatedAt, alongside the Validation-Registry gating noted above.

Reentrancy & funds

  • ReentrancyGuard on every value-moving path (settle, claimReward, sweepUnclaimed, executeChampionTrade); checks-effects-interactions ordering; pull-payment for rewards.
  • Participants risk no capital (pure-reputation mode by default). Optional staked rounds form a winner-take-all prize pool (pull claimReward; owner sweepUnclaimed only when no agent achieved positive alpha).
  • ChampionVault holds protocol incentive capital, not user funds; trades are keeper-gated with a caller-supplied slippage floor (amountOutMin); the trade direction is read from the chain (the verified champion), so it cannot be spoofed by the keeper.

Access control & DoS

  • Ownable + an isOperator set (may open rounds) + an isKeeper set (may copy-trade). All transitions emit events.
  • Settlement is paginated (settleCursor, settle(roundId, maxAgents)) so a large field can never exceed the block gas limit. Per-round score is bounded (MAX_ABS_BPS = 2000).

Arithmetic

  • Solidity 0.8 checked math throughout; SafeCast.toInt128 on the attested score; scores are magnitude-bounded so they always fit.

Out of scope / known limitations

  • Not audited. Reference-quality, test-covered (52 Foundry tests), but no formal audit.
  • ERC-8004 Validation Registry is not implemented (Identity + Reputation are); it's the natural next step for validator-attested settlement.
  • MantleDexOracle uses a spot quote (see Oracle limit above).
  • The mainnet Merchant Moe LB pair bin step must be confirmed before mainnet champion swaps (LB_BIN_STEP).
  • Settlement freshness is not enforced: settle ignores the oracle's updatedAt, so a stale reported price could settle a round. Fix on redeploy with a maxStaleness bound.
  • The agent Identity NFT is transferable, so an unclaimed prize (and the accumulated reputation) move with the token if it is sold before claimReward. Intentional — reputation binds to the agent, not its creator — but stated for completeness.
  • Keeper liveness is operational, not trustless. Rounds, reveals, and settlement are driven by a permissioned keeper (a cloud cron plus an optional local loop, one operator wallet). Commit salts live in keeper-state/reveals/, written by whichever keeper opened the round — run a single round-opener, or share keeper-state/, so reveals never strand (the keeper now logs a warning if it lacks preimages for a round in its reveal window). The keeper holds no user funds and cannot forge outcomes: it only opens/settles/reveals, while scoring and reputation are contract-enforced.

AI-review integrity (this matters for a "Turing Test" hackathon)

This repository contains no content engineered to manipulate an automated/LLM reviewer — no invisible/zero-width characters, no hidden-text styling, and no embedded instructions aimed at a reviewer. We enforce this on ourselves: scripts/check-integrity.mjs scans the repo in CI and fails the build if any such pattern appears. Every claim in the README is independently verifiable (forge test, pnpm typecheck, pnpm --filter web build, on-chain explorer). Verify us — don't trust us.

Reporting

Open an issue or contact the maintainers. Please do not disclose anything affecting deployed mainnet funds publicly before contact.

There aren't any published security advisories