RACK protocol.
RACK turns a staked position on Robinhood Chain into a daily allowance of inference capacity, runs jobs against real models, and signs every output. This page is the complete specification of what the contract does, what the service does, and what neither can do.
Overview
Three parts, each with one job:
- The token. RACK, an ordinary ERC-20 launched on Pons V2. It has no special role in the system beyond being measurable.
- The vault.
RackVault, an immutable contract that holds stakes and exposesunitsPerDay(address). It has no owner and no upgrade path. - The service. This site and its API. It verifies wallets, reads the vault, meters units, runs jobs on provider models, stores outputs under their hash and signs receipts.
Token
RACK is launched on Pons V2, the bonding-curve launchpad on Robinhood Chain (chain id 4663, an Ethereum L2 with ETH as gas). Supply is fixed at one billion by the launchpad; there is no mint, no tax and no admin function. The contract address is published here, on the status page and in the footer at launch.
Vault
RackVault is deployed once against the token. Its full interface:
function stake(uint256 amount) external; // needs approve() first
function unstake(uint256 amount) external; // any amount, any time
function unstakeAll() external;
function unitsPerDay(address) external view returns (uint256);
function positionOf(address) external view returns (uint256 balance, uint256 units, uint64 since);
function balanceOf(address) external view returns (uint256);
function totalStaked() external view returns (uint256);
function stakers() external view returns (uint256);
uint256 constant RACK_PER_UNIT = 10,000e18;
uint256 constant MAX_UNITS = 300;There is no owner, pause, fee, cooldown or lock-up. The vault credits what actually arrives (so a fee-on-transfer token could never mint phantom units), follows checks-effects-interactions, and tolerates ERC-20s that return nothing. The source and the exact compiler input ship with the service and are verified on Blockscout. Tests run the contract in an in-process EVM covering every branch.
Capacity
A unit is the meter. unitsPerDay = min(300, floor(staked / 10,000)). Units are counted per UTC day and reset at 00:00 UTC; nothing rolls over. Each workload costs a whole number of units:
| Workload | Units | Trial | Prompt limit | Delivery |
|---|---|---|---|---|
| Image | 1 | yes | 1,500 chars | queued, stored |
| Text | 1 | yes | 6,000 chars | streamed |
| Code | 2 | no | 8,000 chars | streamed |
| Speech | 2 | no | 1,200 chars | queued, stored |
| Video | 6 | no | 1,000 chars | queued, stored |
Every verified wallet also gets 2 trial units a day for the workloads marked as included, capped per connection so the allowance cannot be farmed with fresh wallets. A job that fails is never charged. The cap of 300 units is the one opinion in the contract: without it a wallet holding a tenth of the supply would take ten thousand units a day and the queue would belong to one address.
Sessions
To run jobs, a wallet signs one message a day. The text names the wallet, this site, a nonce the service issued, and an expiry 24 hours out. It is an EIP-191 personal_sign, which wallets display in full; it is not a transaction, costs no gas, and cannot move tokens or grant approvals. The service verifies the signature against the address (ERC-1271 aware, so smart wallets work), consumes the nonce, and returns an HMAC token. Sessions are stateless: nothing is stored server-side.
Jobs
A job is a workload plus a prompt. Text and code run on Claude through the official Anthropic SDK and stream back as server-sent events. Image, speech and video run on fal.ai; the service fetches the result, hashes it, stores it under its own hash and serves it from here, so the client never depends on a provider URL. Media jobs pass through a small concurrency gate so a burst cannot open unbounded provider work. The models behind each workload are shown live on the status page; a workload whose credential is missing reports offline rather than failing quietly.
Receipts
Every finished job carries a receipt: a fixed-format text signed by the operator key.
rack receipt v1
job: <id>
wallet: <0x…>
workload: <image|text|code|speech|video>
model: <provider model id>
prompt: sha256:<hex>
output: sha256:<hex of the output bytes>
at: <ISO 8601>The JSON receipt adds signer and signature. Recover the signer from the signature with any EIP-191 library and compare it with the operator address on the status page. Because outputs are stored under their hash, the file at the link is the file the receipt names and cannot be swapped later. Verify a receipt.
API
| Route | Auth | Description |
|---|---|---|
| GET /api/status | — | Chain, token, vault, workloads, signer, queue and totals. |
| GET /api/session?address= | — | A message to sign (nonce, 10 minute validity). |
| POST /api/session | — | {address, message, signature} → {token, expires}. |
| GET /api/me | Bearer | Allowance (position, spent, left) and recent jobs. ?fresh=1 re-reads the vault. |
| POST /api/jobs | Bearer | {workload, prompt, publish}. Text: SSE (start, delta, done | error). Media: 202 {job}, then poll. |
| GET /api/jobs/:id | optional | A job. Owner sees everything; others only if published. |
| GET /api/showcase | — | Published jobs, paginated. |
| POST /api/verify | — | {receipt} → recovered signer, operator, ledger match. |
| GET /o/:file | — | Output bytes, immutable, content-addressed. |
| GET /api/coin | — | Curve price, market cap, staked share, stakers. |
Trust model
| The operator can | The operator cannot |
|---|---|
|
|
The operator holds one key that matters: the receipt signer. It holds no funds and can move nothing. If it were lost, existing receipts stay valid (they name their signer); if rotated, the status page shows the new address.
Risk
RACK is a token on a bonding curve and can lose all of its value. Nothing here is a promise of return, and the token is not an investment contract: it is a metered utility whose only guarantee is that a staked position converts to units at the rate written in the contract, and that outputs are signed. Provider costs are paid from the launch's creator fees; if those stop, workloads go offline and the status page says so.