Scoring
The exact formula used to pick a winner (scoring v1). Every battle stores the version it was scored with, and the live score on each battle page uses the same code.
Only growth counts
When a battle opens, both posts are snapshotted (S0). At 24h they're fetched twice, 60 seconds apart, and the second reading is S1. Every number below is a delta, Δ = S1 − S0, so a post's existing likes and views earn nothing. If a metric goes down (unlikes, deleted replies), its delta counts as 0, never negative.
Metrics come from X's public counts for each post: likes, reposts, quotes, replies and views (impressions).
The formula
E = 1·Δlikes + 3·Δreposts + 3·Δquotes + 2·Δreplies R = 1000 · E / max(Δviews, 1000) rawShare = E_reply / (E_reply + E_original) rateShare = R_reply / (R_reply + R_original) score = 0.5 · rawShare + 0.5 · rateShare
- E is weighted engagement growth. Reposts and quotes count 3×, replies 2×, likes 1×. Views aren't in E.
- R is engagement per 1,000 new views. The view floor of 1,000 stops a post with a handful of views from getting an absurd rate.
- The 50/50 blend: raw share rewards actually pulling more attention; rate share cancels out the original's bigger audience. A huge account gets more views, not automatically more engagement per view.
- If both posts have zero E (or zero R), that share counts as 50% rather than dividing by zero.
Winner, tie, and minimum activity
| Condition | Result |
|---|---|
| E_reply + E_original < 10 | VOID, nothing happened (full refund) |
| score within ±0.5% of 50% | VOID, tie (full refund) |
| score > 50% | REPLY wins |
| score < 50% | ORIGINAL wins |
The score is stored in basis points (0–10,000), rounded to the nearest point. "Within ±0.5%" means |score_bps − 5000| < 50. A battle also voids if either post is deleted or unavailable at settlement. Voids are covered in Settlement.
Example
The REPLY pulls twice the engagement growth of the ORIGINAL, on half the new views. Computed with the live scoring code:
| Δlikes | Δreposts | Δquotes | Δreplies | Δviews | E | R | |
|---|---|---|---|---|---|---|---|
| ORIGINAL | 300 | 20 | 5 | 50 | 60,000 | 475 | 7.92 |
| REPLY | 600 | 40 | 10 | 100 | 30,000 | 950 | 31.67 |
rawShare = 950 / (950 + 475) = 66.7% rateShare = 31.67 / (31.67 + 7.92) = 80.0% score = 0.5·66.7% + 0.5·80.0% = 73.33% → REPLY wins
Spike flags
Metrics are polled throughout the battle: every 5 minutes for the first 2h and the last 4h, every 15 minutes in between (every 5 if the pot is over 1 SOL). After each poll, each post's latest interval is checked for signs of bought engagement:
- Engagement spike: the interval's E is more than 8× the median of the previous 6 intervals and more than 200. Needs at least 3 earlier intervals.
- Likes without reach: more than 100 new likes in the interval with likes ÷ views above 0.25.
A flag puts a public banner on the battle so bettors can see the engagement looks off. Flags never auto-void and settlement stays automatic: a flagged battle settles on schedule with the computed result. We can still void a battle before it settles if manipulation is obvious (full refunds).