WAGR
← All specifications
Specification

Security Model

The points where attacks land, and what stops them.

1. Threat Surface

SurfaceAttackMitigation
Wallet adapter RPCFrontend leaks Helius key in bundleHELIUS_RPC_URL is server-side only; client uses NEXT_PUBLIC_SOLANA_RPC (public RPC). CI greps .next/ for the key signature, failing the build if it leaks.
Vault drainTrader withdraws another holder's collateralVault is owned by the market PDA; only the program can call transferChecked. Each operation re-validates outcome balances.
Mint inflationAnchor program mints outcome shares outside CTFmint_authority = market_pda. The program only mints from split; merge and redeem only burn.
LMSR over-fillTrader buys at stale prices to drain vaultThe cost function is recomputed on chain at execution time using shares_q from the same account; an attacker cannot substitute a stale snapshot.
Optimistic griefingSpam proposals to lock collateralBond is non-refundable on failed challenge -- griefing pays the protocol.
DVM briberyWhale dominates a single disputeEffective stake = stake x reputation. New whales have score 1.0; persistent honest voters have score up to 4.0. A first-time vote cannot out-weigh established history at parity stake.
Race on closeTrader splits at the deadline boundarymarket.close(now) requires now >= resolution_deadline; the splits / merges check state == Open so the window cannot be straddled.
Token-2022 transfer hook abuseHostile transfer hook freezes the vaultCollateral must be a known mint without active transfer hooks. The CreateMarket instruction validates the mint's extension list.

2. Audit-Reply Self-Tests

Pre-deploy gate (scripts/verify-audit-blocks.mjs):

  1. README dependency parity -- if README mentions UMA, Pyth, Gnosis CTF, LMSR, or Token-2022, the corresponding Cargo.toml and package.json must declare a matching dependency.
  2. Placeholder grep -- no // Stub, unimplemented!(), println!("would ..."), // TODO, todo!(), empty function bodies in pub fn.
  3. Live-claim parity -- README's live marketsclaim must match the metadata service's /markets?state=Open row count at the time of the build.
  4. No auto-generated comments -- no // rev-xxx, // patch-N, // generated by markers.

The gate runs in CI on every push and locally before any GitHub push.

3. Bond Math

text
proposer_bond = market.resolution_source.bond
challenger_bond = matching
total_at_risk = 2 * bond

winner_payout = bond + (bond / 2)   # full bond back + half loser's
loser_payout  = 0
protocol_take = bond / 2            # the other half of loser's bond

The protocol-take half funds the DVM voter rewards in the same round, so honest voters are paid from griefers' bonds rather than from inflation.

4. Upgrade Authority

The Anchor program ships with a multisig upgrade authority. The signer set is published at docs/governance.md (TBD) and rotates via a 14-day timelock. The metadata service holds no signing authority over the program; it is a read-only mirror.

5. Replay & Re-org Resistance

  • All state transitions key off market_id (a u64) -- there is no nonce surface to replay.
  • Solana's finalisation guarantees mean that once a split/merge is confirmed, the program treats it as final for accounting; the metadata service waits for finalized before mirroring trade fills into Postgres.
  • A re-org that rewrites a finalised block would break Solana's invariants -- the program's correctness reduces to the chain's correctness.

6. Disclosure

Security disclosures: open a private security advisory on the public GitHub repository (security/advisories/new). Bug bounties scale with severity per the matrix at docs/bounty.md (TBD).

click for sound