Telegraph Hackathon — Season I
A contract that buys its own evidence and pays itself.
One codebase, three tracks: a weather miner, a 16 KB scoring module, and a parametric cover on Base Sepolia that reads a storm risk from the network and settles the claim with nobody in the loop.
amanat-miner.vercel.app · 0x39D2bae5…5Cd7E
The thing being tested
Does the quality flywheel actually turn?
Miners are ranked, demand routes to the better ones, earnings follow the ranking, and the layer compounds. That is the claim. Everything here was built to use it for real and then to measure whether it held.
The interesting results are the places it did not — and every one of them is reproducible from a public API.
Track 1 — the miner
Two answers at once: prose a scorer can grade, scalars a contract can settle on.
- Requests served
- 392#1 of 127 live miners
- Intents
- 3forecast, check, storm alert
- Dependencies
- 0node builtins and fetch
Every answer carries an ensemble band across 51 ECMWF members, sea state, the nearest named cyclone, an Ed25519 attestation over the settle fields, and a backtest against the reanalysis archive. Registration 280.
Track 2 — the scoring module
1 400 lines of no_std Rust that grade an answer as a measurement, not as text.
38.2 °C, 100.8 F and 311.35 K are the same reading. Being 0.3° out is right; being 30° out is wrong. No allocator, no imports, every buffer static.
- Compiled size
- 16 KBchampions on the same board are 24–29 MB
- Champion slots taken
- 5each by beating the incumbent margin
- Attacks held
- 14 / 1432 unit tests, native
Track 2 — what measuring the champion found
The seated GAME_RESULT champion cannot tell who won.
ground truth New York Knicks beat Boston Celtics 112-108 (final) answer Boston Celtics beat the New York Knicks 112-108 champion 1.0000 ← same two teams, same two numbers
Right figures, wrong side, full marks. On 31 cases built from what the three live GAME_RESULT miners actually return, the champion’s average margin is −0.0490 — it ranks wrong answers above right ones. Reading which way the result verb points takes that to 0.3617.
Track 3 — the application
The loop closes without a human in it.
openPolicy → requestCheck → createJob(keccak256("STORM_ALERT"))
→ protocol routes, validators finalise
→ subnetMessage → risk ≥ 0.75 ? pay : decline
Plus a storm board screening ten shipping lanes through the Engine twice a day, and a zero-dependency CLI that can ask the network instead of us.
- ERC-8183 jobs on this network
- 18ten of them ours
- Paid Engine calls a day
- 30ten lanes, three legs, twice
What four on-chain jobs found
A job asking for a storm risk came back as a TLS certificate error.
reason: No hostname was supplied with this request, so the
TLS/SSL certificate could not be analyzed.
Four jobs, two intents, one answer. The job reached livecert — rank 1
on STORM_ALERT, ten endpoints, and no on_chain.request mapping at
all. With nothing to map a latitude onto, the node falls back to that
miner’s first endpoint and sends no parameters.
The same miner answers the same question correctly through the Engine minutes
apart, from /storm-alert, at risk 0.79 — over the 0.75 trigger. The policy
would have paid.
How much of the network that closes
Every intent we can audit is closed.
- Intents whose leader is confirmed unable to receive a job
- all of themof those whose registration can be read
- Miners publishing a YAML nobody outside the node can fetch
- 32 / 128at http://127.0.0.1:8099/
- Miners that can receive one on STORM_ALERT
- 2 of 7skywire-storm-alert, and us
And rank is what causes it. Rank is earned on the off-chain rail, where a generalist serving fifteen intents does well — and that same rank then routes on-chain jobs to a miner that cannot serve one.
The fix is a filter, not a redesign: route on-chain jobs only among miners
declaring on_chain.request. That set is computable from the public YAMLs
in one pass, and /api/jobable computes it.
Check any of it
Nothing here is a claim you have to take.
curl amanat-miner.vercel.app/api/jobable # the on-chain rail, live curl amanat-miner.vercel.app/api/survey # measured bar vs displayed score curl amanat-miner.vercel.app/api/board # ten lanes, screened through Telegraph node app/storm.mjs "Cebu" --telegraph # ask the network, not us
- Every figure on the site is read from the chain or the node at load.
- Every bug above is written up with its reproduction in
docs/bug-report.md— including the two theories that were wrong first.