How nodes get paid, what keeps them honest, and how pricing works in a decentralized inference market.
Just like centralized AI APIs, but the cluster operator sets the price.
The cluster operator (registry) sets two prices:
price_per_input_token — cost per token in the promptprice_per_output_token — cost per generated tokenWhen a client sends a request, the web server counts input and output tokens and reports usage to the registry. The total cost is computed as:
cost = (input_tokens × price_per_input_token)
+ (output_tokens × price_per_output_token)
| Parameter | Value |
|---|---|
| Input tokens | 50 |
| Output tokens | 200 |
| Input price | 0.0001 UNFED/token |
| Output price | 0.001 UNFED/token |
| Total cost | 0.205 UNFED |
Output tokens are ~10x more expensive because they require full autoregressive inference (one forward pass per token), while input tokens are batched in a single prefill pass.
From client payment to node payout, tracked on-chain.
Revenue flow: client deposits into UnfedEscrow.sol -> funds remain locked through usage accounting -> settlement window computes total revenue -> payouts are distributed to nodes proportional to weighted compute shares.
Before inference, the client deposits ERC-20 tokens into the
UnfedEscrow.sol contract. This covers the estimated cost
of the inference session.
After each inference, the web server reports input/output token counts
to the registry via the ReportUsage RPC. The registry
accumulates these into a running tally.
Periodically, the share chain daemon produces a settlement block. The payment contract calculates total revenue from token usage and distributes it to nodes proportionally by their weighted compute shares.
Nodes put skin in the game. Cheating costs real money.
Every compute, vision, MPC, and daemon node must stake at least min_stake
(default: 100 UNFED) in the UnfedEscrow.sol contract before
the registry will accept their registration.
A Solidity smart contract that manages staking, escrow, and slashing.
Functions: stake(), depositClient(),
postSettlement(), finalizeSettlement(),
challengeSettlement(), slashNode().
The stake token is any ERC-20 specified by the cluster operator in
ClusterConfig. For local testing, a mock UnfedToken
is deployed on Anvil.
Admission hardening: for on-chain pools, compute/vision/MPC nodes must prove stake-wallet ownership at registration using a signed canonical payload (with timestamp + nonce replay guards). This blocks stake-identity spoofing.
Continuous eligibility: stake checks are revalidated during live operation. Nodes that fall below eligibility are excluded from discovery until they re-stake.
The economic penalty that makes cheating unprofitable.
A receiving node detects an integrity anomaly (for example MPC auth failure or HE binding mismatch) and submits a signed suspicion report.
The report is submitted to the registry via
SubmitHESuspicionReport. The registry validates signatures,
idempotency keys, and evidence bindings.
The registry (as operator) calls slashNode() on the escrow
contract. The node's stake is reduced by slash_fraction
(e.g., 50%). Slashed funds are redistributed or burned.
If the remaining stake falls below min_stake, the node
can no longer register with the cluster. It must re-stake to continue.
This is the right of exclusion — the libertarian model.
Operator-attested model: The cluster operator (registry) is
the authority that calls slashNode(). This is trust-minimized
through context-free verification — the verifier's fraud proof is
independently verifiable.
How revenue is distributed among participating nodes, like mining pool payout methods.
Revenue is split based on each node's share of total weighted compute shares in the settlement period. Simple and fair, but susceptible to pool-hopping.
payout = revenue × (my_shares / total_shares)
Pay Per Last N Shares. Only the most recent pplns_window
shares count. Rewards consistent contributors and penalizes pool-hoppers.
Default window: 1000 shares.
payout = revenue × (my_recent_shares / last_N_shares)
Pay Per Share. Each share earns a fixed rate (pps_rate)
regardless of total pool revenue. The operator absorbs variance risk.
Good for nodes wanting predictable income.
payout = my_shares × pps_rate
Cluster-wide defaults with per-model overrides.
Set by the cluster operator. Defines default values for all economic parameters across the entire cluster.
{
"cluster_name": "my-unfed-cluster",
"default_min_stake": 100,
"default_slash_fraction": 0.5,
"default_price_per_input_token": 0.0001,
"default_price_per_output_token": 0.001,
"default_reward_scheme": "proportional",
...
}
Optional per-model overrides. Larger models might require higher stakes or charge more per token.
{
"model_id": "meta-llama/Llama-3-70B",
"min_stake": 500,
"price_per_input_token": 0.001,
"price_per_output_token": 0.01,
"reward_scheme": "pplns",
"pplns_window": 2000
}
Override rules: Any field defined in PoolConfig
takes precedence over the cluster default. The overridable fields include:
min_stake, slash_fraction, price_per_input_token,
price_per_output_token, reward_scheme, and all fee
oracle parameters.