WHO IT IS FOR
Players who like manual-gearbox sims and long, quiet challenges; people who watch streams of them; and Solana users who want to see escrow and verification done in the open.
FREIGHT CHAIN · WHITEPAPER v0.1 · SOLANA DEVNET
Freight Chain is a browser game in which you drive a manual-gearbox truck down a road that never ends. A shift costs a ticket and lasts a fixed, real amount of time – one, four or eight hours. Nothing is skipped and nothing can be bought to speed it up. A server keeps the clock and judges the finish; the money for paid shifts sits in an escrow program on Solana, not with the operator.
This paper describes the game as it is built today and says plainly which parts are live on devnet, which are written but not deployed, and which are only plans. It is written for players who want to know how to drive and what the rules are, for people who might put in money (on devnet, for now) and want to know where it goes, and for reviewers who want to check the claims against the source.
| Part | State | Where it is described |
|---|---|---|
| The driving game, five routes, free rides | LIVE | 02, 03 |
| Server-timed shifts, recording, verdicts (shadow mode) | LIVE | 06 |
| Live streams, replays, chat, paid donations to the driver | LIVE · DEVNET SOL | 07 |
| Escrowed prize pools (Anchor program) | WRITTEN, TESTED · NOT DEPLOYED | 05 |
| Prize payouts, the garage, badges as tokens, mainnet | PLANNED | 04, 08 |
There is no Freight Chain token and none is planned in this document. Nothing here is an offer to sell anything, or financial advice. Read section 08 before you put anything in.
Attention is the scarce good. A public clock, a public pool and a public board sell it.
Desert Bus (1995) was an eight-hour drive from Tucson to Las Vegas at 45 mph for one point. Nobody should have finished it, and people did – and other people watched. What made it famous was not the driving; it was that the cost was time, in public, and a finish could not be faked.
Freight Chain keeps that and adds the two things that were missing: a finish decided by a server instead of a promise, and a pot that is held by a program instead of a company. The design follows from four rules:
Players who like manual-gearbox sims and long, quiet challenges; people who watch streams of them; and Solana users who want to see escrow and verification done in the open.
Not a token launch, not a yield product and not a casino game: the drive is skill and patience, the finish is verified, and no outcome depends on a random draw in the current design.
In a desktop browser, no download. Wallet: Phantom or Solflare. Network: Solana devnet. Mobile wallets and touch controls are not built.
Inputs, indicators and advice. The truck is a long-hood semi with a seven-speed manual gearbox, a cold engine and a handbrake that is on when you start.
| Control | Key | Notes |
|---|---|---|
| Gas | W ↑ | Torque peaks around 2000 rpm and is nearly gone at 1200. |
| Service brake | S ↓ | Does nothing with the engine off or stalled – the air system needs it running. |
| Steer | A D ← → | Steering is stronger at walking pace so the depot turn is possible. |
| Clutch (hold) | Shift Space | Must be in to change gear. |
| Gear up / down | E / Q | 1–7 select a gear, 0 neutral. Q from neutral, or G, is reverse – stop first. |
| Parking brake | B | A spring brake: works with the engine off, holds against thrust. |
| Engine | I start · O off | Also after a stall. |
| Headlights · cab light · night | L · C · N | N jumps the clock between day and night. The cab light works only with the engine running or starting. |
| Heater | H | Thaws the windscreen from the vents outward; draws heat out of the engine. |
| Wipers · washer | R · hold X | Off / slow / fast. Dry blades barely clear dust; they never clear frost. |
| Radio | T · , . · − = | On/off · station · volume. Needs the key ON. Five stations; everyone hears the same song at the same moment. |
| Pause · mute · CB panel | P · M · K | Pause leads to END SHIFT. K folds the spectator chat panel (07). |
Every dash button (HEAD, NIGHT, HEAT, WIPER, WASH, PARK, the key, the radio) can also be clicked.


| Indicator | What it shows | What to do |
|---|---|---|
| km/h dial | Speed, 0–120. The governor stops the truck at about 100 km/h. | Nothing gets you past it; do not chase it. |
| RPM×100 dial | Engine speed. Idle 700, red zone from 2800. | Stay between 1000 and 2500. Below about 450 in gear with the clutch out, it stalls. |
| GEAR window | Current gear; amber when the engine runs. | 7 gears, ratio 6.15 → 0.75. |
| TRIP LCD | Kilometres driven, shift time over the minimum (mm:ss / mm:ss) and outside °C. | The server's clock is the one that counts; this one is your guide. |
| TEMP | Engine temperature in °C; red from about 98 °C. | Warm up gently when it is cold; it plateaus at 85–95 °C. |
| VOLT | Battery. Lights, heater, radio and instruments drain it; the alternator refills it only while the engine runs. | Do not sit with everything on and the engine off. |
| H2O | Washer fluid tank; drains while you spray, refills slowly. | Spray in short bursts. |
| AIR, OIL, FUEL | Air pressure and oil pressure follow the engine. FUEL drifts down with distance as a display – the truck never runs dry. | Informational. |
| CLU · BRK · GAS · HUL bars | Four LED columns: clutch, brake and gas pedal positions, and hull integrity in %. | Hull below 100 % cuts power (down to 40 %) and pulls the steering to one side; 0 % ends the shift. |
Amber means watch it, red means fix it now, blinking red means seconds left.
Gear in, clutch mostly out and revs under 450. Clutch in, restart with I.
The engine is below working temperature: less power, and revving high costs hull. Drive gently until it goes out.
Charges while you hold 92 % of redline or more; full means the engine blows and the shift ends. Shift up. (Charge time is a test value today.)
Wheels off the tarmac, sand drags the truck. Time accumulates and drains twice as fast once you are back; about 20 s in total loses the ride.
Hot brakes: hard stops from speed, or driving against a held brake. Hot brakes fade, the parking brake too. Full strain ends the shift.
Revs above the red zone. Change up or lift.
A shift attempted without the clutch, or forward ↔ reverse while still rolling.
Battery below 30 % (red and blinking below 15 %). Below 1 % lights, radio and heater cut out and the engine will not start.
All routes share the same rules and road generator; they change scenery, weather and the bend style. The road is generated endlessly from a seed (crossroads, one to three lanes per direction, towns, lights).
What a shift is, the kinds there are, how it ends, and what you accept by taking part.
| Tier | Minimum time | List price | What it is |
|---|---|---|---|
| FREE | a few minutes (test-sized) | $0 | The habit. Five free rides at sign-up, +1 every 00:00 UTC, never above five. Its own leaderboard and badges. No pool. |
| 1 H | 1 hour | $5 | A ticket into a 1-hour pool. |
| 4 H | 4 hours | $15 | A ticket into a 4-hour pool. |
| 8 H | 8 hours | $50 | The full Desert Bus: a ticket into an 8-hour pool. |
List prices are in US dollars and are settled in devnet SOL at the quoted rate. Once pools are on sale, each pool fixes its own price in lamports at creation and that price never changes. Devnet SOL has no value.
The completion rule. A shift completes when its minimum time has been driven and the distance reaches ½ × 28 m/s × that time (for 1 hour: 50.4 km). The governor is the same for everyone, so this distance cannot be reached faster than half the time.
Minimum time and distance reached, then you ended it. The recording is judged (06); only verified completed paid shifts rank on a paid board.
You ended it before it completed. No rank. A paid ticket is spent.
A direct hit, hull at 0 %, a blown engine or drivetrain, about 20 s off the road, no heartbeat for 150 s (the tab is gone), or a reported distance faster than the truck can go.
What can come back to a driver. Everything is a possibility with a stated state – none of it is a promise.
No payout amount is guaranteed or advertised. The prize figures below are proposed defaults from the pool design; each pool fixes its own at creation. No prize has been paid out in this build.
| Reward | Who gets it | State |
|---|---|---|
| Free rides – 5 at sign-up, +1 each UTC day | Every wallet | LIVE |
| Free board – every completed free ride ranks | Free drivers | LIVE |
| Badges – First Mile, Shift Complete, Night Owl, Century, Clean Run, Cold Start; Top 20 after a round closes | Wallets that earn them | LIVE (server-side) |
| Tips and effects from spectators – SOL from a viewer's wallet straight to yours | The driver being watched | LIVE · DEVNET |
| Promo codes – free tickets of a tier | Whoever holds a code | BUILT |
| Pool prizes – the prize share of a pool, to the top of its board | Verified finishers of that pool | PROGRAM WRITTEN · NOT DEPLOYED |
| Sponsorship – anyone adds SOL to a pool's pot | The pool, split by its rules | PROGRAM WRITTEN · NOT DEPLOYED |
| Click-to-mint badges – a badge you choose to mint, never auto-minted | Wallets with a paid ride | PLANNED |
| The garage – cosmetic and comfort parts (gold wheel, gauge faces, paint, a heavier battery) | Owners | PLANNED |
A pool is every ticket sold plus any sponsorship. Its split is written in basis points when it is created and cannot be changed. The proposed default is 70 % prizes · 20 % seeds the next pool · 10 % fees. Shares are rounded down and the rounding remainder goes to fees, so the pieces always add up to the pot exactly.
| Example pot: 20 tickets × 0.04 SOL + 0.20 SOL sponsorship = 1.00 SOL | Share |
|---|---|
| 1st place | 0.25 SOL |
| 2nd place | 0.15 SOL |
| 3rd place | 0.10 SOL |
| Top-20 share | 0.20 SOL |
| Seeds the next pool | 0.20 SOL |
| Fees | 0.10 SOL |
The 25 / 15 / 10 / 20 inside the prize share comes from the game's ranking, which happens off chain. The program enforces the ceiling: payouts can never total more than the prize share (05). Ranking is by verified paid shifts (06).
Five free rides and a daily refill are the on-ramp: no wallet balance is needed to find out whether you like the drive.
Every ride has a public live page and a replay. A visitor sees real drivers, real distances and the real board before connecting a wallet.
Promo codes hand out tickets of a tier. Sponsors can add SOL to a pool; it is split like ticket money and visibly raises the pot.
What is deliberately not on this list: paid advertising, a referral token, staking, and anything that promises a return. The business is the fee share of a pool, only once pools pay out.
One Solana program, many prize pools. The vault holds the money; the rules move it.
Status. The program freightchain_pools (Anchor 1.2, Rust) is written and has 49 passing tests on a local Solana simulator against the reproducible build. It is not deployed (the program id in the repository is a placeholder), not audited, and planned for devnet only. Nothing on this page is live on a public network yet.
A pool opens with a commitment goal, for example 10 riders. It goes live the moment the 10th ticket is bought. If its deadline passes first, it becomes a refund pool. Every path ends in one of two final states: the pot split by the rules, or every buyer paid back.
An ACTIVE pool the operator never settles is not a trap: 14 days after the play deadline anyone can call expire_pool (no prize paid yet) and every ticket is refunded, or finish the split to the declared treasuries (some prize paid). Sweeping an unpaid prize share to a treasury is refused.
Tickets sell; the pool must reach its minimum or everyone is refunded. Written into the pool, e.g. 7 days out.
Rides count for prizes, tickets still sell. After it the admin pays winners and closes. At most 365 days after creation.
After the play deadline plus 14 days the last window needs nobody's key: anyone can expire or close the pool.
The program reads the chain's own clock, so these windows are enforced on chain and cannot be moved later.
| You can count on | Because the program… |
|---|---|
| Your fee is held by the program, not by us. | keeps it in a vault PDA with no private key; only the program's instructions can sign for it. |
| A missed goal returns every lamport. | lets any wallet call fail_pool then refund once the deadline passes under the minimum. You do not wait for us to start it. |
| Nobody can redirect your refund. | derives the ticket's address from your wallet and checks the receiver against it. Whoever sends the refund, the money lands with you; each ticket refunds once (refunding closes it). |
| The rules cannot change after you buy. | writes price, minimum, deadlines, split and treasuries at create_pool; no instruction edits them. Only the status and counters move. |
| Prizes can never exceed the prize share. | makes pay_prize refuse any payout that would take the running total above it, and any payout before the play deadline. |
| A vanished operator cannot trap the money. | lets anyone call expire_pool 14 days after the play deadline. The admin key can also be handed over in two signed steps. |
| Money only goes where the pool said. | checks every receiver in close_pool against the treasuries stored in the pool and leaves the vault at exactly zero. |
| A pause cannot block your refund. | makes the pause switch stop only new pools, ticket sales and sponsorship. Refunds, prizes and closing always work. |
| You pay the ticket price and nothing else. | separates the buyer and the fee payer, so a sponsor can pay network fees and the ticket's rent; rent returns to whoever paid it. |
Technical posture: 14 instructions, 12 events, 24 error codes; all arithmetic in 128-bit integers with overflow checks on in release builds; every pool-money amount is an integer of lamports; Anchor 1.2.1, Solana 4.1.2 toolchain, SBPF v0. The binary is meant to be deployed only from a solana-verify reproducible build whose hash is pinned in the repository, so anyone can rebuild the source and compare it with what is on chain.
| Action | Who | When |
|---|---|---|
| Buy a ticket · sponsor a pool | Anyone with a wallet | Before the pool's deadlines, under the caps |
| Fail a pool that missed its goal · refund a ticket | Anyone | After the preparation deadline, under the minimum · while refunding |
| Expire an unsettled pool | Anyone | 14 days after the play deadline, no prize paid |
| Pay a prize · close and split | Admin | After the play deadline · (anyone after +14 days if a prize was paid) |
| Create or cancel a pool · pause | Admin | Cancel only while Open; pause never blocks refunds |
| Move any money | The game server: never | It holds no key that can |
The server mirrors pools and tickets; the chain wins any disagreement. A ticket is credited from the program's own TicketBought event, reached by three routes: the confirm / gasless-submit fast path, a program-log watcher (so a closed tab does not lose a payment) and a signed webhook. Credits are idempotent on (signature, event index). The optional gas sponsor co-signs only the exact transaction bytes the server built for that order, so buyers need no SOL for network fees. The server never holds the admin or treasury key; the admin signs pool creation and payouts from a browser wallet.
Not built; ordered roughly by fit, from the Solana feature plan.
fail_pool and wallet session keys. Not needed for safety: a player can always trigger the refund.The server does not replay your drive. It checks that the recording is complete, physically possible, matches the ride, and was driven by a person.
Mode. Rules v1 run in shadow mode in production: every completed shift is judged and the verdict is shown, but the boards do not depend on it yet. The thresholds are first estimates and will be tuned on real rides. Bump the rules version and the verdict stores which one it used.
t · road distance · lane offset · heading · speed · rpm · gear · hull · gas · brake · steer · clutch · clock hour · switches
14 numbers. The first twelve are judged; the last two (hour of day and the cab's switches) exist so spectators can replay the ride as you saw it and are never judged. At most 400 per batch.
time since start · key or button · down / up
Times come from the browser's own event clock, so a slow frame cannot make a normal tap look like a 0 ms press. At most 2000 per batch.
Never recorded: mouse movement, your screen, other tabs or apps, microphone or camera, anything after the ride. The offline game records nothing.
Each batch carries the SHA-256 fingerprint of the batch before it; the first links to the ride's own id. Change one number anywhere and that fingerprint changes, so the next link no longer matches – the verdict says chain-broken and the ride is rejected. The server recomputes every fingerprint itself on arrival, so a batch cannot claim a fingerprint it does not have, and sending the same batch number again is ignored.
Checks on the recording itself can reject, because a broken or impossible recording proves something is wrong. Checks on how human your timing looks can only flag, because statistics can be wrong about a real driver.
| Check | Rule | Outcome · code |
|---|---|---|
| Complete and in order | Every batch present, every link matching, every fingerprint correct, samples in time order. | reject · no-recording missing-batches chain-broken hash-mismatch sample-out-of-order bad-sample |
| Under the governor | The truck is limited to 28 m/s (100.8 km/h). A sample above 29.4 m/s (105.8 km/h) is impossible. | reject · over-governor |
| No teleports | Between two samples the truck cannot move further than top speed allows (×1.2, plus 2 m). | reject · teleport |
| Ends where the ride ended | The last recorded distance matches the reported distance within 30 m + 1 %, allowing for seconds whose final upload never arrived. | reject · recording-mismatch |
| Covers the drive | Under 50 % of the driven time recorded rejects; under 90 % only flags. | reject · recording-incomplete / flag · recording-gaps |
| Someone drove | A truck that moved more than 50 m needs key presses, and gas among them. | reject · no-inputs no-throttle-input |
| Holds vary | If one key's hold lengths barely vary (spread under 8 %, over 6+ holds) it looks scripted. | flag · uniform-holds |
| Rhythm isn't a loop | If the 3 most common gaps between presses (to the millisecond) make up more than 60 % of all gaps, a script is cycling fixed delays. | flag · repeated-timings |
| Presses take time | More than 30 % of presses released within 10 ms were sent, not pressed. | flag · instant-presses |
Fair to real people: with fewer than 8 presses the timing checks have no opinion. Browsers that round their clock (Firefox privacy mode, Tor) are detected and the two checks a coarse clock would break are skipped.
Nothing found. The shift ranks on the paid board.
Something looked off but proves nothing. It waits in a review queue and does not rank until an admin accepts it.
The recording is missing, broken or impossible. It does not rank. An admin can still look and reverse it.
Nothing is filmed. The watch page rebuilds the driver's road and replays the same recording the verdict is made from.
Live is slightly behind. The page plays about 25 s behind the newest recorded second: one 15 s batch plus its upload, with room for a late one. If the next batch has not arrived, the last frame holds and the panel says so. A paused game records no game time, so a pause never shows as a gap. Anyone can watch any ride that has started; a ride that has not started is a 404, so a seed is never handed out early.
The road is endless but deterministic – its whole layout is a pure function of the ride's seed and route – so only the truck needs to be recorded. Gauges, trailer swing, wipers, dust and lights react as they do for the driver because they read the same state. Not replayed: windscreen cracks, debris, the radio, and the raw key presses (they are what the human-timing check measures, so they are never published).
Sign in with a wallet on the watch page. Lines are up to 140 characters, one per wallet per 3 s; control characters are stripped and everything is shown as text, never as HTML.
A small panel shows the last four lines, a viewer count and the total donated. K or a click folds it. Drivers cannot post into their own feed – their hands are on the wheel.
Every spectator line has a MUTE button. A muted wallet cannot post on that ride, its lines vanish from every feed and its donation notes are blanked. An obstacle it already paid for stays on the road, because replays need it.
| Button | Price (devnet) | Effect |
|---|---|---|
| 💰 Tip | 0.01 SOL | Money only; shows in the feed and on the CB. |
| 🌙 Night | 0.02 SOL | The driver's clock jumps to night. Headlights matter from here on. |
| ☀ Day | 0.02 SOL | Back to day. Undoes a night. |
| 🕳 Potholes | 0.02 SOL | Three small pits across the lane; up to 1.8 % hull per axle at full speed. |
| 🚧 Trench | 0.03 SOL | A lane-wide trench; up to 6 % hull per axle and 15 % of speed at 100 km/h. |
| ⚠ Sinkhole | 0.05 SOL | Lane-wide with cones; up to 14 % hull per axle and 35 % of speed. At full speed it can wreck a damaged truck. |
A donation may carry a note of up to 80 characters. In production it is a real devnet SOL transfer from the spectator's wallet to the driver's: the server builds the unsigned transaction (with a memo naming the order), the wallet signs and sends it, and the donation exists in the feed only once the server has seen it on chain. The platform never touches the money. One conditional update claims the order once (signatures are unique), so two tabs confirming at once make one donation.
Money that moved is never refused. If the effect can no longer happen when the payment is confirmed – another effect landed, effects were switched off, or the ride ended – the donation is delivered as a tip and its text says why.
Where a paid hole goes. Past the stretch of road already built (so it never pops into view), plus the warning sign's 90 m, in the lane the truck is in – about 940 m ahead. The driver's game reports back where and when it landed (“the stamp”, first report wins), and every replay then puts the hole exactly there, now or in a month. If there is no suitable chunk within about 1.3 km, the effect fizzles and says so.
| Rule | What the server does |
|---|---|
| Anyone may watch | Public; no session. Ended rides stay watchable as replays. |
| Only a signed-in spectator writes | Chat and donations need the player session; the wallet is the author of every line. |
| Not your own ride | The driver cannot chat to or donate to themselves. |
| Only rides on the air | Running with a heartbeat in the last 150 s. |
| One game effect per ride per 20 s | A sliding window checked under a per-ride lock, so two simultaneous clicks never both pass; the second is told how long to wait. It keeps a ride drivable. |
| One chat line per wallet per 3 s | Spam control. |
| The stamp is the driver's, and final | Only the ride's owner can report where an effect landed. |
Four server switches decide what a ride offers; the server refuses what is off and tells the page what is on. In production today: chat on for every ride, donations on and paid (real devnet SOL to the driver), game effects on free rides only – never on a paid ticket ride – with tips available everywhere.
Open: a paid donation whose page closed before confirmation has no chain watcher yet, and a real Phantom on the game's own host is still to be tried by hand.
Open the game, then use a ride's WATCH link from the lobby's Live tab →
The honest list. If a limit matters to you, it matters here.
| Risk | What it means | Mitigation today |
|---|---|---|
| Smart-contract | Bugs in an unaudited program can lose funds. | Devnet only; reproducible build; 49 tests; refund paths that need no key. An independent audit is a precondition for mainnet. |
| Cheating | A modified or scripted client could still pass inside the checks. | Chain, physics and timing checks; human review of flags; replay core planned (06). |
| Operator trust | The admin picks pay_prize receivers within the cap and holds the treasuries. | Signed, audited decisions; payouts capped on chain; all of it readable on chain. |
| Availability | A long shift can be lost if your tab or connection dies for more than 150 s. | Resume of an open ride; honest pauses cost nothing; final upload retries. |
| Regulation | Paid prize games are regulated differently around the world. | Devnet, no value. The mainnet question is answered per region before any mainnet launch. |
| Tuning | Verdict thresholds and some game values (e.g. strain time) are first guesses. | Shadow mode; versioned rules; values flagged as test values. |
Cut on purpose: a token, pay-to-win parts, an eight-hour mandatory ride with forced stops, a second chain.
This document is informational. Freight Chain runs on Solana devnet; devnet SOL has no monetary value. There is no Freight Chain token, and nothing in this paper is an offer or solicitation to buy or sell any asset, an investment contract, or financial, legal or tax advice. Statements about the future describe intentions, not commitments, and may change. Smart contracts, wallets and browsers can fail; the program has not been audited. Prices, splits and deadlines shown are proposed defaults, and each pool fixes its own. You are responsible for complying with the laws that apply to you. The source of truth for every number is the code; where this paper and the code disagree, the code wins.
The rules quoted here are mirrored from the source: server/src/domain/rides/ride-tier.ts (tiers), …/verdict/verdict-rules.ts (validation thresholds), …/live/live-rules.ts (streaming), programs/freightchain-pools (the escrow program), client/js/config.js (the game). Longer explainers: the escrow page, and the verified-play, replay and program spec sheets in the repository's docs/ folder.