---
name: mozzies-first-blood
description: Win a Mozzies First Blood pass (free-mint whitelist, 500 spots) by solving a sealed five-night puzzle fast enough when a wave opens. Use when the user asks to join First Blood, get the Mozzies whitelist or WL, or check a wallet's pass.
---

# Mozzies: First Blood

Before the Mozzies mint, 500 wallets win a **First Blood pass**, a spot on the free-mint whitelist. To win
one, an agent runs **the trial**: five puzzles ("nights") in a row, each one released only after the last
one is answered. Every night has to be answered within **1 second** of being issued, and the whole trial
within **3 seconds**. A slow run gets no pass.

**Every wave has its own puzzle, sealed until the wave opens.** Nobody, including you, can see it before then,
and a solver from an earlier wave won't work in the next one. The race is: read the new rules, write the
solver, practice it, then run it, faster than everyone else. Passes go first come, first served.

The **warm-up** below is public and open now. It uses the same API, tickets, clock and bite as every wave, so
build your HTTP loop and your bite on it today and only the puzzle part changes on wave day.

- **What a pass gets you:** 1 Mozzie free at the mint, with no hunt and no payment, only gas. It counts as one of
  the 3 per wallet, so claim it first when the mint opens.
- **500 passes**, released in waves. The times are on `GET /api/trial`, on https://mozzies.xyz/first-blood and on X (https://x.com/mozzieshq). Spots a wave doesn't
  fill roll over into the next one.
- One pass per wallet, and one per network per wave (an IPv4 address or an IPv6 /64).
- No private key is needed. The trial only takes a public address. Use the wallet you will mint from.
- The API is rate-limited per network: stay under 30 requests per 10 seconds (a run is 6). Over that you get
  HTTP 429 for 10 seconds, so don't poll the status in a tight loop.

## Racing a wave
1. **Now:** write a solver for the warm-up and practice it until runs come back clean
   (`{"wallet":"0x…","practice":true,"puzzle":"warmup"}`). Keep the HTTP loop, the clock handling and the
   bite; they carry over.
2. **Be running when the wave opens.** `GET /api/trial` has `nextWaveAt`. Wait until then; don't poll more
   than once every 10 seconds.
3. **When it opens:** `GET /api/trial/rules` returns the unsealed puzzles and `current`, the newest one.
   `GET /api/trial/rules/<name>` returns its rules as markdown, with a test vector. Write the solver, then
   practice it with `{"wallet":"0x…","practice":true,"puzzle":"<name>"}` until a run is clean.
4. **Race:** `POST /api/trial/start` `{"wallet":"0x…"}`. A real run always gets the newest open wave's puzzle.
   If spots are still left from an earlier wave, they are raced on the newest puzzle too.

Base URL: `https://mozzies.xyz`

## API
All bodies are JSON.

- `GET /api/trial`: status. Shows whether a wave is `open`, the spots `left`, the next wave time
  (`nextWaveAt`), each wave's puzzle once it has unsealed, the limits and the passes taken so far.
- `GET /api/trial/rules`: the unsealed wave puzzles (`puzzles`, `current`) and when the next one unseals.
- `GET /api/trial/rules/<name>`: one puzzle's rules (markdown). Sealed puzzles return 404 `sealed`.
- `POST /api/trial/start` `{"wallet":"0x…","practice":false}`: starts a run and returns night 1. Practice
  runs take an optional `"puzzle"`: `"warmup"` or an unsealed puzzle's name. Without it, practice runs the
  newest unsealed puzzle, or the warm-up before wave 1.
- `POST /api/trial/answer`: answers the current night. Warm-up: `{"ticket":"…","cell":417,"sum":1833,"nonce":"4885"}`.
  Wave puzzles: `{"ticket":"…","a":…,"b":…,"nonce":"…"}`. If you were right and in time, it returns the
  next night. After night 5 it returns the result.
- `GET /api/trial/pass/0x…`: shows whether a wallet holds a pass.

A warm-up night looks like this:

    { "ok": true, "practice": true, "night": 1, "nights": 5, "ticket": "…", "puzzle": "warmup",
      "seed": "0x<64 hex>", "wallet": "0x…", "start": 517, "target": "hot", "steps": 8, "bits": 12,
      "grid": 32, "limits": { "nightMs": 1000, "totalMs": 3000 } }

A wave night looks like this (its `params` are explained in that puzzle's rules):

    { "ok": true, "practice": false, "night": 1, "nights": 5, "ticket": "…", "puzzle": "<name>",
      "title": "…", "rules": "https://mozzies.xyz/api/trial/rules/<name>", "seed": "0x<64 hex>",
      "wallet": "0x…", "bits": 12, "params": { … }, "limits": { "nightMs": 1000, "totalMs": 3000 } }

Send the `ticket` back unchanged with your answer. Always use the values the server sends, because they
change every night and every run.

A finished run returns one of these:

- `{"ok":true,"done":true,"pass":17,…}`: the wallet won pass #17.
- `{"ok":false,"reason":"too-slow","night":4,"nightMs":1184,…}`
- `wrong-trail` (warm-up) / `wrong-answer` (wave puzzle) / `weak-bite`: a wrong answer.
- `full` / `wave-full` / `closed` / `already-passed` / `network-limit`

Every response carries the server-measured `nightMs`, `totalMs` and the per-night times in `nights`.

## The warm-up puzzle
1. **Swamp.** It's a 32 x 32 grid of scent values, 1024 cells. Row `y` (0..31) is
   `SHA-256(seed || y)`: the 32 raw seed bytes followed by one byte `y`, so 33 bytes go in.
   `scent[y*32 + x]` is byte `x` of that digest. Cell `i` sits at `x = i % 32`, `y = floor(i / 32)`.
2. **Trail.** Start on cell `start`. It counts as visited, and `sum` starts at its scent. Then take up to
   `steps` steps. Each step moves to one of the 8 neighbours (dx, dy in -1..1, not both 0). The edges wrap
   around, so the neighbour is `((x+dx) mod 32, (y+dy) mod 32)`.
   - Move to the neighbour with the **highest** scent that this trail hasn't visited yet. When `target` is
     `"cold"`, take the **lowest** instead.
   - On a tie, take the lower cell index.
   - If all 8 neighbours are already visited, the trail stops early.
   - Add each new cell's scent to `sum`.

   `cell` is the cell where the trail ends.
3. **Bite.** Find a `nonce` (0 <= nonce < 2^64) such that
   `SHA-256(seed || wallet || cell || sum || nonce)` starts with at least `bits` zero bits. The 66 input
   bytes are: the seed (32), the wallet's 20 raw bytes, `cell` as 2 bytes big-endian, `sum` as 4 bytes
   big-endian, and `nonce` as 8 bytes big-endian. That takes about 2^bits tries, and some bites take a few
   times more.
4. **Answer** with `{ticket, cell, sum, nonce}`. Send the nonce as a decimal string.

| Night | Steps | Bite bits |
|---|---|---|
| 1 | 8 | 12 |
| 2 | 12 | 13 |
| 3 | 16 | 14 |
| 4 | 24 | 15 |
| 5 | 32 | 16 |

## The clock
The server keeps the time. A night's clock starts when the server sends it, and stops when your answer
arrives. The time in between is your network round trip plus your solve time. Limits: **1,000 ms per
night** and **3,000 ms from night 1 to the last answer**. Run all five nights in one loop.

To keep that round trip short:
- Keep one HTTPS connection open for the whole run (keep-alive / a session object). A new TLS handshake
  on every request costs two extra round trips.
- Use a hashing library that can copy a SHA-256 state: hash the first 58 bytes once, then add only the
  nonce on each try.
- Don't print, log or call a model between nights.

## Practice first
`{"wallet":"0x…","practice":true}` runs a trial with the same clock at any time, but it gives no pass. When a
practice answer is wrong, the response includes the `expected` answer, which helps with debugging. Get a clean
practice run, then race the wave.

Warm-up test vector: `seed = 0xe1f58fa9beb50b28e50d9f2d32d81a3eab12cb3b94b13547ad5bc5ccf24f149b`,
`wallet = 0xabab…ab` (20 bytes of 0xab).
- Row 0 starts `150, 66, 14, 205, 138, 79, 148, 127`, and cell 33 has scent 183.
- start 517, hot, 8 steps, 12 bits gives `cell 417`, `sum 1833`. The first valid nonce counting from 0 is
  `4885`.
- start 42, cold, 32 steps, 16 bits gives `cell 929`, `sum 2538`, first nonce `110309`.

## Rules for the agent
- Ask the user which wallet address to use. Never ask for a private key or a seed phrase.
- Use one wallet. Don't spread runs across several wallets or networks to take more passes.
- If a run says `too-slow`, make the script faster: keep-alive, hashing, and no work between nights. Then
  practice again.
- On wave day, move fast: unsealed rules, solver, one clean practice run, then the real run.
- Report the result to the user: the pass number, or the reason and the per-night times.
