How Payrail works
Everything here is read from the contracts. If this page and the contracts ever disagree, the contracts win.
Overview
A route is a small contract with its own address that splits whatever lands in it between up to 6 destinations, by fixed shares. Send it creator fees, sales, sponsorships or any HYPE payment, and every payout follows the split.
Each destination has a name, a type and where it goes: a wallet, a treasury, creators, a reserve, or a coin buy that swaps its share into a coin on Elysium and sends the coins to a wallet. Payouts run on every payment or on a schedule you pick. The money never passes through a Payrail wallet.
Create a route
Give it a name (up to 48 characters) and 1 to 6 destinations. Each destination is a name (up to 32 characters), a type, the address it pays and a share in basis points; a coin buy also names the coin. Shares must add up to exactly 10,000 (100%). Each wallet can appear once (a coin buy for the same wallet once per coin), and a route cannot pay itself or the zero address.
Choose Editable to keep the right to change the split, or Locked to freeze it forever. The route gets its address in the same transaction.
Paying in
Three ways, all equal:
Plain transfer. Send HYPE to the route address from any wallet or contract. It waits until someone pays it out.
pay(). Send HYPE with the call and everything waiting is paid out in the same transaction.
Tokens. Transfer any standard ERC-20 to the route address, then call distributeToken(token).
Payouts
Anyone can call distribute() once the schedule allows. The protocol fee comes off first, then each destination gets its share in basis points. The last destination takes the rounding dust, so every wei is accounted for.
Each push gets 100,000 gas. If a destination refuses the transfer or runs out of gas, its share is set aside for it and the rest still pay out. It collects with claim(token) any time. Amounts set aside are never paid out twice.
Every payout is stored in the contract with its time, block, token, amount, fee, split version and caller.
import { createWalletClient, custom } from "viem";
const wallet = createWalletClient({ transport: custom(window.ethereum) });
await wallet.writeContract({
address: ROUTE, // the route address
abi: routeAbi,
functionName: "distribute", // pays out all HYPE waiting
account,
chain,
});Schedule and keeper
A route pays out on every payment, or at most once every hour, day or week, and you can add a minimum: nothing pays out until that much HYPE is waiting. The contract enforces both, so an early payout simply fails.
The Payrail keeper checks every route and runs payouts and coin buys as soon as they are due, paying the gas itself. It cannot move funds anywhere but through the split. If it ever stops, anyone can still press pay out once a payout is due.
Coin buys
A coin buy destination holds its share on each payout. The keeper (or the route owner) then swaps it into the chosen coin through KyberSwap on Elysium, which routes the pools the launchpads trade on, and the coins go straight to the destination's wallet. Every buy needs a minimum output taken from a live quote, so a bad price reverts instead of filling.
Only swap routers Payrail allowlists can be called, they can spend at most what is held, and the coins must arrive in the destination wallet. If a coin has no pool, the owner can send the held share to the wallet as HYPE instead.
Editing and locking
The owner of an editable route can replace its split. Each change bumps the version (v0, v1, v2) and every earlier version stays readable with splitsAt(v). A new split applies from the next payout.
lock() freezes the split and the schedule forever. Ownership can be transferred. The owner can never withdraw: money only leaves through the split.
Fees
The protocol fee on new routes is · of each payout. It is written into each route when it is created, can never rise on that route, and the contract caps it at 1%.
Contracts
Network: Elysium Testnet, chain id 99801.
Contracts publish at launch.
Route
| pay() payable | Send HYPE and pay out everything waiting in the same transaction. |
| distribute() | Pay out all HYPE waiting. Anyone can call once the schedule allows. |
| distributeToken(token) | Pay out all of an ERC-20 waiting. Anyone can call once the interval allows. |
| executeBuy(token, coin, to, router, data, minOut) | Owner or keeper. Swaps what is held for a coin buy through an allowlisted router; the coins must reach `to` and be at least minOut. |
| releaseBuy(token, coin, to) | Owner only. Sends what is held for a coin buy to its wallet as is, with no swap. |
| setSchedule(interval, minPayout) | Owner only, while not locked. |
| due(token) / nextPayoutAt(token) | Whether a payout would run now, and when the next one may. |
| claim(token) | Collect an amount that could not be pushed to you. |
| setSplits(splits) | Owner only, while not locked. Bumps the version. |
| lock() | Owner only. Freezes the split and the schedule forever. |
| transferOwnership(to) | Owner only. Moves edit and lock rights. |
| pending(token) | What is waiting to be paid out (balance minus amounts set aside). |
| splits() / splitsAt(v) | The current split, or any earlier version. |
| payoutsPage(offset, limit) | Payout history, newest first. |
| info() | Owner, name, lock, fee, schedule, waiting, held for buys, routed, payouts and split in one call. |
| queued(token, key) / bought(coin, to) | Held for a coin buy, and lifetime coins bought for a wallet. |
| owed(token, who) / paidTo(token, who) | Set aside for a destination, and lifetime amount sent to it. |
Factory
| createRoute(name, splits, locked, interval, minPayout) | Creates a route with its own address. Emits RouteCreated. |
| isKeeper(address) / isRouter(address) | The keepers allowed to run coin buys and the swap routers they may use. |
| routeCount() | How many routes exist. |
| routesPage(offset, limit) | Route addresses, newest first. |
| routesOf(owner) | Routes created by an address. |
| routesPaying(who) | Routes that have ever listed an address as a destination. |
| isRoute(address) | True only for routes made by this factory. |
Integrations
Creator fees. Set a route as the fee recipient of a coin on a launchpad. Fees land in the route and split on the next payout.
Sales and services. Use the route address as the place customers pay.
Routes into routes. A destination can be another route, so a studio can split its share again inside its own team.
Safety
What can happen: anyone can pay a route out once due, the keeper or owner can run coin buys at a quoted minimum, the owner of an editable route can change the split and schedule for future payouts, and destinations collect what was set aside for them.
What cannot: nobody can withdraw from a route, change a locked split, raise a route's fee, or pay the same amount twice.
Limits: a destination contract that always refuses transfers keeps its share set aside until it can receive. Tokens with transfer fees or rebasing balances are not supported, and a token that blocks transfers cannot be paid out.