Freight Chain · Solana program freightchain_pools

Pool escrow

Every paid ride is a ticket into a prize pool. The pool is an account on Solana that holds the entry fees itself and publishes its rules once: price, minimum riders, deadlines, the split, and where the money may go. If not enough riders commit in time, everyone gets their money back, and nobody needs our permission to make that happen.

Program written · 44 tests pass Devnet deploy next Not audited · not on mainnet
Where the money goes

The vault holds it, the rules move it

A player's ticket payment goes straight into the pool's vault. The vault is a program-derived address: no private key exists for it, so only the program's own rules can move money out. Four exits exist, and each one is a rule written into the program. The game server watches what happens and prepares transactions for people to sign. It never holds or moves the money.

Pool rules price · minimum · deadlines split · treasuries · fixed at creation governs Pool vault program-owned account no private key exists PDA ["vault", pool_id] Player wallets each purchase signed by the player buy_ticket price × qty Buyers refund full price, if the pool fails Winners pay_prize admin-signed, capped Seed treasury close_pool seeds the next pool Fee treasury close_pool operating fee Game server reads events, credits tickets, builds unsigned transactions events, read-only transaction to sign
Every arrow that moves money starts or ends at the vault. None of them touches the game server: its two lines are dashed because it only reads what the program announced and hands players transactions to sign in their own wallet.
The life of a pool

Five states, and who can move it

A pool opens with a commitment goal, for example 10 riders. It goes live the moment the 10th ticket is bought. If the deadline passes first, it turns into a refund pool. Every path ends either with the pot split by the rules or with every buyer paid back.

automatic anyone can trigger admin only final state Open Active Settled Refunding Cancelled minimum sold on the purchase that reaches it close_pool admin, after the play deadline anyone after +14 d, if prizes paid fail_pool deadline missed: anyone or cancel_pool: admin expire_pool anyone, 14 days after the play deadline, no prize paid close_pool anyone, once all refunded while Refunding: anyone can send refund, the money always lands with the buyer
Both ways out of a stuck pool are teal. A pool that misses its goal and a pool the operator abandons after it went live both end in refunds that anyone can trigger. Only the normal settlement of a live pool needs the admin.
The clock

Deadlines are written into the pool

The program reads the chain's own clock, so these windows are enforced on chain and cannot be moved later. The durations below are the proposed defaults; each pool fixes its own at creation.

create_pool prep_deadline play_deadline +14 days about 30 days for example 7 days 14-day grace Open tickets sell; the pool must reach its minimum or everyone is refunded Active rides count for prizes, tickets still sell Settlement admin pays the winners and closes the pool Safety net anyone can expire or close it
The last window needs nobody's key. If the operator never settles, 14 days after the play deadline any wallet can start the refunds (no prize paid yet) or finish the split to the declared treasuries (some prizes paid).
The split

A 1 SOL pot, cut by the rules

The pot is every ticket sold plus any sponsorship. The pool states its split in basis points when it is created; this example uses the proposed 70 / 20 / 10. Shares are rounded down, and the rounding remainder goes to fees, so the pieces always add up to the pot exactly.

Prize share 70% · pay_prize, capped on chain close_pool · declared treasuries 1st place0.25 SOL 2nd0.15 SOL 3rd0.10 Top 200.20 SOL Next pool seed0.20 SOL Fees0.10 Example pot: 20 tickets × 0.04 SOL + 0.20 SOL sponsorship = 1.00 SOL The 25 / 15 / 10 / 20 cut inside the prize share comes from the game's ranking. The program enforces the 70% ceiling.
The program caps the total, not the ranking. Prize payouts can never add up to more than the prize share. Which wallets win is decided off chain from the server-checked results and signed by the admin, so that part is trust in the operator, stated below.
What a player can count on

Guarantees, and the rule behind each

Your entry fee is held by the program, not by us.

It sits in the pool's vault from the moment you buy.

Enforced byThe vault is a program-derived address with no private key. Only the program's instructions can sign for it.

If the pool misses its goal, you get every lamport back.

You don't have to wait for us to start it.

Enforced byfail_pool and refund are open to any wallet once the deadline passes under the minimum. The refund pays the full ticket price to you and returns the ticket account's rent to whoever paid it.

Nobody can redirect your refund.

Whoever sends the refund, the money lands in your wallet.

Enforced byThe ticket account's address is derived from your wallet, and the program checks the receiver against it. Each ticket refunds once: refunding closes it.

The rules can't change after you buy.

Price, minimum, deadlines, split and treasuries are fixed.

Enforced byThese pool fields are written at create_pool and no instruction can edit them. Only the status and the counters move.

Prizes can never exceed the prize share.

The pot can't be paid out twice or drained through payouts.

Enforced bypay_prize refuses any payout that would take the running total above the prize share of the pot, and refuses payouts before the play deadline.

An operator who disappears can't trap or take the money.

Lost keys or a shutdown still end in refunds or the declared split.

Enforced by14 days after the play deadline, anyone can call expire_pool to refund an unpaid pool. Sweeping an unpaid prize share to a treasury is refused with MustExpire. The admin key can also be handed over in two signed steps.

Money only goes where the pool said it would.

No instruction can send funds to an address of the caller's choosing.

Enforced byclose_pool checks each receiver against the treasuries stored in the pool, and it must leave the vault at exactly zero.

A pause can't block your refund.

Pausing exists for emergencies, not for holding money.

Enforced byThe pause switch stops new pools, ticket sales and sponsorship only. Refunds, prizes and closing always work.

You pay the ticket price and nothing else.

Account rent comes back, and network fees can be covered for you.

Enforced byThe buyer and the fee payer are separate signers, so a sponsor can pay the fee and the ticket rent. Rent is returned to whoever paid it. Server-side gas sponsorship is designed, not built yet.
Who can do what

Permissions at a glance

ActionWhoWhenMoney goes to
Buy a ticketPlayerOpen pool before its prep deadline, active pool before its play deadlineThe vault
Sponsor a poolAnyoneSame windows as buyingThe vault
Fail a pool that missed its goalAnyoneAfter the prep deadline, under the minimumNothing moves yet
Refund a ticketAnyoneWhile the pool is refundingThe buyer, plus rent back to its payer
Cancel an open poolAdminBefore it goes liveNothing moves yet; refunds follow
Pay a prizeAdminAfter the play deadlineA winner, within the prize share
Close and splitAdmin AnyoneAdmin after the play deadline; anyone 14 days later if prizes were paidThe declared seed and fee treasuries
Expire an unsettled poolAnyone14 days after the play deadline, no prize paidNothing moves yet; full refunds follow
Move any moneyGame serverNeverIt holds no key that can
What the program does not promise

Where trust in us is still needed

  • Who wins. Rankings come from the game server's checks: a server-kept clock and a speed limit on reported distance. That is not proof of human play, and a modified game client can still lie within those limits. The admin signs each payout.
  • Which winner gets paid. The program caps the total paid out. It cannot tell a rightful winner from any other wallet, so the admin could pay a wrong address within the cap.
  • The treasuries. The seed and fee treasuries are wallets the operator controls. The pool fixes their addresses, not what happens to the money afterwards.
  • Maturity. The program is tested on a local Solana simulator (44 tests). It is not deployed yet, not audited, and planned for devnet only.