Tokenomics
This document specifies the economic model of the OpenInfra DePIN platform: what units exist, how value moves, what authority can change what, and the invariants that bound governance proposals so a single bad vote can’t take the network down.
It is the source of truth for the internal/tokenomics package, which
enforces the invariants below at proposal-validation time. Edits to the
bounds in this document must land in the same commit as the code change.
Status: Pilot Phase 7 (devnet). Mainnet deployment, Squads-multisig mint authority, and inflation/burn mechanics are deferred to a future revision of this document.
1. Units
Section titled “1. Units”1.1 Credit (internal accounting unit)
Section titled “1.1 Credit (internal accounting unit)”The credit is the unit the off-chain ledger denominates every entry in
(see internal/db/migrations/009_pilot_ledger.up.sql). Credits are signed
int64; the conservation invariant Σ debits + Σ credits + Σ fees = 0
holds per workload (verified in internal/settlement/settlement_test.go).
Credits are computed by pricing.Compute(vcpus, memoryMB, durationSec, ratePerCPUMicro, ratePerMBMicro):
| Component | Default rate | Meaning |
|---|---|---|
RATE_PER_CPU_MICRO | 1_000_000 | 1 credit per vCPU·second |
RATE_PER_MB_MICRO | 1_000 | 0.001 credit per MB·second |
Rates are micro-credits per unit-second (1 credit = 1 000 000 micro-credits) so the math stays integer-only.
1.2 OINFRA (onchain token)
Section titled “1.2 OINFRA (onchain token)”Devnet mint: 9Jkq8WdgUUp2AR4FeXwE6q4DRddoHGfcKREMeCE6wphT
Decimals: 6 (matches SPL convention)
Total supply (devnet): 1 000 000 OINFRA-test (no minting after genesis
on devnet — see §3.1 for mainnet policy).
The onchain bridge (internal/settlement.OnchainCron) converts
provider-credit ledger rows in the solana: namespace into SPL transfers
1 credit = 1 OINFRA base unit (i.e. 1 micro-OINFRA, since OINFRA has
6 decimals). The pegged 1:1 ratio is intentional for v1 so providers can
reason about earnings without a floating exchange rate; later revisions
may unpeg via a credit-burn / token-mint mechanism governed by §4.
1.3 Boundary
Section titled “1.3 Boundary”+--------------------+ pricing.Compute +-------------------+| workload usage | -----------------> | ledger (credits) || (vcpu·s, MB·s) | | |+--------------------+ +---------+----------+ | OnchainCron (1:1) v +-------------------+ | OINFRA (SPL) | +-------------------+Ledger writes are synchronous on heartbeat-observed completion (Block B);
SPL submission is asynchronous via the executor’s 5-minute ticker (Block
C). Until SPL submission succeeds, the ledger entry’s
settled_onchain_at is null — onchain mid-flight is idempotent because
MarkSettled is gated on WHERE settled_onchain_at IS NULL.
2. Authorities
Section titled “2. Authorities”| Authority | Today | Controls |
|---|---|---|
| Treasury hot wallet | <dataDir>/treasury.age (age-encrypted to host key) | Mint authority for OINFRA-test, signs all SPL transfers |
| Admin role (JWT) | Database row, manual seed | Credit minting (POST /api/v1/admin/credits/mint), invite issuance, host ban/unban |
| Governance (staked credit holders) | internal/governance | Catalog add/remove, parameter changes (within the bounds in §4), host ban/unban (via proposal), treasury spend |
| Operator (env vars) | cmd/api-server/main.go | RATE_PER_CPU_MICRO, RATE_PER_MB_MICRO, PLATFORM_FEE_BPS, SOLANA_MINT, OPENINFRA_DATA_DIR, OPENINFRA_HOST_KEY |
Phase-7 hardening migrates the treasury hot wallet to a 3-of-5 Squads
multisig and moves PLATFORM_FEE_BPS from env-var to governance config
(requires a schema migration; tracked in ARCHITECTURE.md pending).
3. Supply
Section titled “3. Supply”3.1 Devnet (v1)
Section titled “3.1 Devnet (v1)”Fixed supply of 1 000 000 OINFRA-test minted at genesis. No further mint operations. The treasury holds the entire supply minus what has been transferred out as provider rewards.
3.2 Mainnet (deferred to Phase 7)
Section titled “3.2 Mainnet (deferred to Phase 7)”Decisions still open and explicitly not ratified by this document:
- Initial supply at TGE.
- Whether supply is fixed, inflationary, or deflationary.
- If inflationary: emission curve (constant / decaying / halving) and destination of new mint (provider rewards / treasury / staker yield).
- If deflationary: burn source (fee skim / fixed schedule / governance- triggered).
- Vesting schedule for any team/treasury/investor allocation.
The Phase-7 revision of this document must specify each before the mainnet mint is created. Until then, all OINFRA references in code are OINFRA-test on Solana devnet.
4. Governable Parameters
Section titled “4. Governable Parameters”These are the parameters the DAO can change via a param_change
proposal. The bounds and per-proposal step limits below are enforced
by internal/tokenomics.Validate at proposal-submit time and again at
execute time. A proposal that violates either fails validation and never
reaches a vote.
| Key | Type | Min | Max | Max Δ per proposal | Rationale |
|---|---|---|---|---|---|
base_reward_rate | int64 | 0 | 1 000 000 000 | 100 000 000 | Reward emission per epoch; max-Δ caps a 10×/proposal shock |
fee_split_host_pct | bps (0-10000) | 5 000 | 9 500 | 1 000 | Host’s share of fees; min 50% so providers always get majority, max 95% so platform isn’t insolvent |
min_proposal_stake | int64 | 100 | 10 000 000 000 | 0 | No rate cap — small operators must be able to lower it |
voting_period_hours | int32 | 24 | 720 | 168 | 1 day floor (snap proposals impossible), 30 day ceiling (no proposal can stall forever); 1 week max change |
quorum_bps | bps | 500 | 7 500 | 1 000 | 5% min so a quiet network can still govern; 75% max so a small offline group can’t block all votes |
pass_threshold_bps | bps | 5 001 | 9 500 | 1 000 | Strict majority floor (5 001 = just over 50%); 95% max so unanimous-or-die isn’t a valid configuration |
veto_threshold_bps | bps | 1 000 | 5 000 | 1 000 | 10% min so a tiny faction can’t veto; 50% max so veto needs less than majority |
max_active_proposals | int32 | 1 | 100 | 0 | Anti-DoS for the voting UI; no rate cap (admins should be able to slash it instantly under attack) |
unbonding_period_hours | int32 | 24 | 2 160 | 168 | 1 day floor (no instant exit-and-attack), 90 day ceiling (no permanent lock); 1 week max change |
4.1 Why two-stage validation
Section titled “4.1 Why two-stage validation”ValidateBounds(key, proposed) runs at proposal submit and stops out-of-
range values from ever reaching the voting queue. ValidateTransition( key, current, proposed) runs at execute and stops a proposal that was
in-range when submitted but is now too aggressive against the (possibly
changed) current value. Both stages share the same Invariants map so
governance can never paint itself into a corner where a previously-valid
proposal becomes unstoppable.
4.2 Why platform_fee_bps isn’t in the list yet
Section titled “4.2 Why platform_fee_bps isn’t in the list yet”PLATFORM_FEE_BPS is currently an env var, not a governance_config
column. Moving it into governance requires a schema migration (Phase 7).
Until then it’s documented as operator-set, bounded by
settlement.MaxPlatformFeeBps = 5000 (50%) and defaulting to
settlement.DefaultPlatformFeeBps = 1000 (10%). The same bounds will
apply when it migrates to governance.
5. Treasury Policy
Section titled “5. Treasury Policy”5.1 Where fees go
Section titled “5.1 Where fees go”Every settled workload writes three ledger entries (debit / credit / fee):
workload_debit customer -> -amountprovider_credit provider -> +amount × (1 - platform_fee_bps/10000)platform_fee treasury -> +amount × platform_fee_bps/10000The treasury account is the namespaced address internal:treasury on
the ledger. There is no automatic mint or onchain transfer for the
treasury portion — it accumulates as off-chain credits.
5.2 Who can spend the treasury
Section titled “5.2 Who can spend the treasury”Only via a treasury_spend governance proposal (Block: governance Phase
2c). A passing proposal transfers from internal:treasury to a named
user account. The treasury cannot be spent by admin role or by the
operator directly — this is intentional and not negotiable in v1.
5.3 Mainnet treasury split (deferred)
Section titled “5.3 Mainnet treasury split (deferred)”Phase 7 must decide whether the treasury portion is:
- Burned (deflationary pressure)
- Held in treasury and onchain-mirrored on a cadence
- Distributed to stakers proportional to stake-time
- Some mix of the above
6. Invariants enforced by internal/tokenomics
Section titled “6. Invariants enforced by internal/tokenomics”For each governable key K:
Bound(K).Min <= proposed <= Bound(K).Max [ValidateBounds]Bound(K).MaxStepDelta == 0 OR |proposed - current| <= delta [ValidateTransition]A MaxStepDelta == 0 means rate-of-change is not capped (the key is
either non-disruptive to change, or has no meaningful “step” notion).
7. Emergency Policy
Section titled “7. Emergency Policy”Operations that must remain available even if governance is gridlocked:
| Operation | Authority | Code path |
|---|---|---|
| Ban a hostile host | Admin (immediately) or governance proposal | hosts.status = 'banned' |
| Pause SPL submission | Operator: unset SOLANA_MINT and restart api-server | Onchain executor declines to start without it |
| Pause workload acceptance | Admin: set all hosts to degraded | Scheduler skips non-active hosts |
| Drain treasury (mainnet only) | Squads multisig override (Phase 7); v1 has no override | n/a |
There is no emergency mint authority in v1. The treasury hot wallet holds the entire supply and the only path to add more is to deploy a new mint (effectively a fork).
8. Open Questions
Section titled “8. Open Questions”Listed here so they are not lost. Each must be answered before the section it belongs to is considered ratified for mainnet:
- §3.2 Inflation curve and emission destination
- §3.2 Vesting cliff and schedule for any non-public allocation
- §5.3 Treasury split policy on mainnet
- §4.2 Schema migration to move
platform_fee_bpsinto governance - §2 Squads multisig threshold (3-of-5 vs 4-of-7) and signer set
- §1.2 Whether to unpeg credits ↔ OINFRA after mainnet liquidity is established (and if so, the rate mechanism — TWAP, oracle, etc.)