BASIS
Documentation

The decentralized inference market

liverouting gated

Basis is a decentralized inference market. Contributor GPU workers publish a signed model offer — the models they serve, an ask price in USDC-pegged credits per 1M tokens, and their capacity — and Basis verifies the signature, the ask-price rails, the freshness, and a canary before an offer can route. Compute price is stable in credits; $BASIS settles dynamically at quote time. The market is opening: signed price publishing is live and durable, while production worker routing is still gated. Verification is graduated evidence — never a cryptographic proof of which model produced an answer.

What the market is

Any GPU can register a worker, sign a price manifest, and ask to serve OpenAI-compatible jobs for $BASIS rewards. The market is the set of current worker offers, each with the models it serves, the price it asks, and a read-time verification state. Basis does not set a single price for a worker model — a worker sets its own ask, and the network bounds that ask with rails and surfaces it with an honest verification label.

When no worker has published, the market is honestly empty: the API returns an empty list plus the network default price (the fallback a gateway-served job is metered at), never a fabricated worker.

In a permissionless market you cannot cryptographically prove, from a worker's free-form text output alone, which model produced it. A worker can quietly serve a cheaper, smaller, or quantized model — or proxy your request to a real model's API — and no text-based check rules that out with certainty. So Basis's verification is graduated evidence, never proof: verified means “passed Basis's canary + freshness checks,” never “cryptographically proven to run model X.” The full study is in docs/research/worker-verification.md.

The signed offer manifest

A worker broadcasts a manifest of the models it serves, its ask prices, and capacity, signed with its reward wallet. Signing with the reward wallet binds the offer to the address that will be paid — without the worker ever sending its private key. The price fields are integer raw micro-credits per 1M tokens (decimal strings, never JS numbers): one whole credit is 1,000,000 raw micro-credits, so 58 whole credits / 1M is 58000000.

json
{
  "manifest_version": 1,
  "worker_id": "worker-example",
  "reward_wallet": "0xYourEvmRewardAddress",
  "hardware": { "gpu_model": "RTX 4090", "vram_gb": 24 },
  "models": [
    {
      "model_id": "llama-3.1-8b",
      "runtime": "ollama",
      "prompt_credits_per_1m": "58000000",
      "output_credits_per_1m": "115000000",
      "min_job_credits": "50000000",
      "max_context_tokens": 8192,
      "max_output_tokens": 2048,
      "concurrency": 4
    }
  ],
  "valid_until": "2026-06-26T12:00:00Z",
  "nonce": "a-unique-nonce",
  "signature": "0x…"   // EIP-191 personal_sign by reward_wallet over the
                       //   canonical (sorted-key) JSON with "signature" removed
}
Manifest fields
  • worker_idThe registered worker this offer is for.
  • reward_walletThe EVM address that signs the manifest AND receives rewards. Must match the registered worker wallet.
  • hardwareSelf-reported gpu_model + vram_gb. Present and sane, but unverifiable without remote attestation — bounded, not proven, by the canary throughput check.
  • models[]Each: model_id, runtime, prompt/output credits per 1M, min_job_credits, max_context_tokens, max_output_tokens, concurrency.
  • valid_untilISO 8601 expiry. Clamped to now + the max offer TTL (24h). The offer reads expired once it passes.
  • noncePer-manifest nonce for anti-replay within a worker's price history.
  • signatureEIP-191 personal_sign by reward_wallet over the canonical sorted-key JSON with signature excluded. The one cryptographically verified field.

The EIP-191 signature recovering the reward wallet is the one place the market has cryptographic verification: it proves the offer came from the address that will be paid. Everything downstream — the canary, throughput sanity, hardware — is graduated evidence, not proof. The reward wallet is a public 0x… address only; the signing key never leaves the worker host.

Verification states

Every offer reads as one of five states. Three are stored (self_reported / verified / rejected); two are overlaid at read time against the clock and the worker's heartbeat — so a stored verified offer reads stale the moment the worker goes offline, or expired once valid_until passes. A canary that ages out drops a verified offer back to self_reported — verification is a freshness window, not a permanent badge.

self_reportedlive

Proves: Valid EIP-191 signature (recovers the reward wallet) + prices within the rails + not expired + worker online. The offer is authentic and credibly priced.

Does not prove: Capability is not proven. The worker may serve a different, cheaper, or quantized model, or proxy. Hardware is self-reported.

verifiedlive

Proves: Everything self_reported proves, plus the offer passed a recent deterministic Basis canary — coherent output at a plausible throughput/TTFT for the advertised model and hardware — within the freshness window.

Does not prove: NOT cryptographically proven to run model X. A close substitute, an intermittent swap, audit-aware routing, or a proxy can still pass a text probe. Model identity stays self-reported.

stalelive

Proves: Nothing currently — the worker's heartbeat is older than the live window (offline). Overlaid at read time.

Does not prove: Never routable. A stored verified offer reads stale the moment the worker stops heartbeating.

expiredlive

Proves: The manifest's valid_until has passed, so the price is no longer offered. Overlaid at read time.

Does not prove: Never routable. The worker must publish a fresh offer.

rejectedlive

Proves: The offer is invalid — bad signature, a rails violation, or a failed canary.

Does not prove: Never routable. It is not stored as a routable offer.

verified = “passed Basis's deterministic canary + freshness checks.” It is not “cryptographically proven to run model X.” Model identity and hardware remain self-reported in every state. No copy may upgrade verified to “proven,” “guaranteed,” or “trustless,” and the network is neither fully private nor fully decentralized.

Ask-price rails

Workers set their own prices, but Basis bounds them so an ask can't be absurd: a floor (a worker can't dump below physical GPU cost, which signals a scam or a peak-batch claim that will fail under real load) and a ceiling (the network won't route an extreme overcharge). The defaults are research-anchored to real 2026 market prices and are env-overridable. An ask below a floor or above the max is rejected; an ask in the warn band is routable but flagged high.

Ask-price rails (peg: 1 credit = $0.001 USDC)
  • Min prompt price

    10 credits / 1M · $0.010 / 1M

    Below the cheapest verified retail input — an ask under this is not credible. Prefill is cheap, so the floor is low.

  • Min output price

    20 credits / 1M · $0.020 / 1M

    Just under the derived healthy-batch 7B GPU floor and the cheapest retail output. Below this a real worker is underwater.

  • High-price warn

    6,000 credits / 1M (output) · $6.00 / 1M

    Around Claude-Sonnet output territory. An offer above this is flagged high — still routable, but surfaced to the caller/operator.

  • Max routable

    12,000 credits / 1M (output) · $12.00 / 1M

    Between the most expensive verified open serving and frontier flagships. Above this the offer is rejected — not routed.

  • Min job size

    50 credits · $0.050

    Anti-dust floor per job: every routed job bills at least this regardless of token count, covering fixed dispatch + receipt + settlement overhead.

  • Offer TTL (max)

    86,400 s (24h) ·

    valid_until is clamped to now + this. The credit→$BASIS quote TTL is a separate, shorter window (120 s) — only the $BASIS conversion is time-sensitive.

Floors are output-anchored because decode dominates GPU cost; the prompt floor is roughly half the output floor, matching the market input/output ratio. The full derivation, sources, and GPU-hour floor math are in docs/research/worker-market-pricing.md.

USDC-pegged credits vs dynamic $BASIS

Price in Basis has two layers, and keeping them separate is the honesty win. The compute price is stable: a worker's ask and the model price table are denominated in USDC-pegged credits (1 credit = $0.001), so a model's credit price does not lurch with token volatility. Only the credits → $BASIS settlement is dynamic: at quote time the credit total converts to $BASIS at the active pricing epoch's rate, the conversion freezes into a hashed snapshot, and the receipt records both the credit cost and the locked $BASIS amount.

  • Compute price (credits)

    STABLE

    USDC-pegged credits. Moves only when the network re-pegs an epoch or a worker re-quotes its ask. This is what a caller sees per model.

  • Settlement (credits → $BASIS)

    DYNAMIC

    basisPerCreditRaw, locked per quote at quote time. Token volatility lands only on the $BASIS amount, never on the credit-denominated compute price.

The credit→$BASIS quote is short-lived (a 120-second TTL) because $BASIS is volatile and a stale quote can't be honored. The credit price itself is not time-sensitive. The market API returns a worker's USD value per 1M (from the stable peg) and an indicative $BASIS amount at the active epoch rate — an estimate, never a promise. Until a price source is configured the live $BASIS conversion reports null and is never fabricated. Full pricing model: Credits.

Default network prices

These are the defaults the network advertises so a model always has a price even with zero workers online. A worker may ask less (down to the floor) and undercut the default. Anchored to real 2026 market prices plus a thin network margin (peg: 1 credit = $0.001 → credits/1M ≈ $/1M × 1000).

ModelPrompt credits/1MOutput credits/1M
  • Network default (gpt-4.1-mini proxy tier)$0.40 / $1.604601,840
  • Llama 3.1 8B / small 7–8B$0.05 / $0.1058115
  • Mistral ~24B$0.08 / $0.2092230
  • Llama 3.x 70B$0.20 / $0.40230460
  • DeepSeek V3 (MoE)$0.32 / $0.893681,024

The network default (the proxy tier, 460 / 1,840 credits/1M) is the price a gateway-served job is metered at when no worker offer applies. The full market survey and per-model anchors are in docs/research/worker-market-pricing.md.

Publish an offer

Register the worker first (POST /api/workers/register), then POST a signed manifest to /api/workers/prices. The manifest reward wallet must match the registered worker wallet, and when authentication is required it must also be a wallet linked to your account. Each publish is stored as an immutable offer at the next price version; a new price is a new version, never an edit, so a receipt that references an offer preserves the exact economics forever.

bash
# Publish a signed price/model manifest. The worker must already be registered
# (POST /api/workers/register), and the manifest reward_wallet must match the
# registered worker wallet. Basis verifies the EIP-191 signature recovers the
# reward wallet, the prices sit within the ask-price rails, and the manifest is
# not expired, then stores an IMMUTABLE offer at the next priceVersion.
curl -X POST https://basis.watch/api/workers/prices \
  -H "Content-Type: application/json" \
  -d @manifest.json
# → { "ok": true, "offerId": "worker-example:v1", "priceVersion": 1,
#     "state": "self_reported", "flags": [],
#     "note": "Offer published as self_reported. A canary can mark it verified;
#              capability is not cryptographically proven." }

A freshly published offer is self_reported — signature-valid and within the rails, but capability not proven. A deterministic Basis canary can later mark it verified; it never auto-upgrades. The full agent-driven worker setup is the basis-worker skill, and the practical run-a-worker flow is the worker guide.

Read the market

The market is public and secret-free. The market endpoint returns each worker's current offer with its read-time state and per-model economics; the per-worker endpoint returns one worker's current offer plus its price-version history.

bash
# The public market: each worker's CURRENT offer (latest price version) with the
# read-time verification state and per-model economics (USDC-pegged credit price,
# the stable USD value, and an indicative $BASIS amount at the active epoch rate).
# Honest empty state: no published offers → { "empty": true } + the network default.
curl -s https://basis.watch/api/workers/market

# One worker's offers (current + price-version history). 404 if it never published.
curl -s https://basis.watch/api/workers/worker-example/models
  • POST /api/workers/pricesPublish a signed price manifest. Verifies signature → rails → freshness, stores an immutable offer.
  • GET /api/workers/marketThe public market: every worker's current offer, verification state, and USD + indicative-$BASIS economics. Honest empty state.
  • GET /api/workers/{workerId}/modelsOne worker's current offer + price-version history. 404 if it never published.

Routing policy

The market exposes two routing policies. The default is verified_only: only offers that passed a fresh canary route. allow_self_reported is a strict opt-in for callers who knowingly accept unproven capability (cheapest-price experimentation, a user's own private worker) and must be labelled as self-reported capability, never as verified. stale / expired / rejected offers never route under any policy.

Verification governs routing and metering — it does not by itself release on-chain funds. Even a verified, routed, completed job's reward stays gated behind the five settlement gates (durable persistence, operator key, Base mainnet, the distributor configured, and an explicit BASIS_SETTLEMENT_MODE=live) and settles idempotently. Failed, rejected, and invalid-wallet jobs always earn zero.

Activation status

The market is opening, and the docs are honest about what is live versus gated. Read GET /api/launch-status and GET /api/workers/onboarding/status for runtime truth — never infer live state from this copy.

live

Signed price publishing

Workers publish signed offers; Basis verifies signature → rails → freshness and stores them durably. The market and per-worker read endpoints are live.

pending

Production worker routing

Opt-in and OFF in production — there is no hosted orchestrator, and BASIS_WORKER_ROUTING_ENABLED is unset, so a published offer does not receive production jobs yet (canReceiveJobs is false). Run an orchestrator locally/self-hosted to route.

pending

Paid inference / payment router

Paid $BASIS deposits and token payments need the live payment router plus a quote provider. Gated.

pending

On-chain settlement

Worker payouts stay gated on the five settlement gates — keeper dry-run by default.

pending

Inference-fee burn router

The BasisInferenceFeeRouter (10% burn / 90% worker on each inference payment) is implemented, tested, and fork-proven, but NOT deployed. On-chain burn awaits deploy + CreditVault.setSpendSink. It is SEPARATE from the Bankr creator-fee $BASIS-side 50/50 burn/stake rail.

The inference-fee burn (10% of each inference payment, via the implemented-not-deployed BasisInferenceFeeRouter) and the Bankr creator-fee $BASIS-side 50/50 (50% burned on-chain + 50% funded to the staking vault) are two distinct flows with different sources and different denominations — never conflated. See Tokenomics and Treasury.