CIP-31: CBFS Rent Schedule
Abstract
This CIP pins concrete CBY values for every parameter that CIP-9 (Runner Storage / CBFS) currently labelsTBD, adds a new RELAY_CHALLENGE_BOND field, makes the existing 10 / 1 / 89 burn / challenge-pool / Relay revenue split explicit in normative text, and defines the pro-rata weighting formula that distributes the 89% Relay share across active Relay Nodes.
This CIP does not introduce any new mechanism in CIP-9.
Motivation
- Let Relay operators run capacity-planning math before mainnet.
- Let storage-rate volatility (CBY-denominated rent vs USD/GB/yr reality) be observable, monitored, and Tier-0-adjustable on a documented cadence.
- Provide the challenger economic incentive that makes Proof-of-Retrievability honest in steady state.
- Bound the worst-case Relay-side loss in slashing events.
Specification
1. Storage Fee Rate
ceil(volume_size_bytes / 2^20) MiB. Per 1 GiB of stored data per year: 2,905 nano-CBY × 1,024 MiB × 365 epochs ≈ 1.086 CBY / GiB / year.
Backblaze B2 lists **7.64 / TiB / month — the units are not interchangeable and conflating them understates the multiple. Against that, the rate is 1.82× B2, and roughly 40% below S3 Standard (~$24 / TiB / month).
The rate is denominated in nano-CBY. USD figures below are the administered CBY rate defined in CIP-36 §6.6 applied to this constant, not a property of the constant itself; §6.6 is that rate’s only definition and this section does not restate it. At the current rate the fee is $0.163 / GiB / year. If the rate moves, the Tier-0 review below retunes this constant to keep the fee inside the band — which is what the band exists for.
The rate is denominated per MiB, not per byte: the smallest integer per-byte rate (1 nano-CBY/byte/epoch) is ≈ 391.9 CBY / GiB / year — ≈ $58.78 at the administered rate, roughly 650× commodity object storage — so per-byte granularity cannot express a competitive rate.
Mutability: Tier-0 governance, stored at 0x09 under key cip31.cbfs.storage_fee_per_mib_per_epoch. The governance value is authoritative wherever it is set; the constant above is the genesis default only, and any implementation that bills from a compiled-in constant rather than the parameter is non-conforming. The Tier-0 review cadence is 30-day post-TGE → 90-day steady state; the target band is [$0.05, $0.50] / GiB / year. The rate is nano-CBY and the band is USD, so token-price movement drifts the fee against the band by construction; the administered rate (CIP-36 §6.6) pins the conversion between reviews, and the Tier-0 review retunes the constant when the drift leaves the band.
2. Transfer Fee Rate
66,700 nano-CBY × 100 = 0.00667 CBY per read. Goes entirely to the serving Relay (no burn, no challenge-pool share).
Mutability: Tier-0, key cip31.cbfs.transfer_fee_per_mib.
3. Minimum Storage Balance
STORAGE_GRACE_EPOCHS per CIP-9 §10.3.
Mutability: formula-derived; the multiplier 1 (one epoch) is Tier-0-tunable via cip31.cbfs.min_storage_balance_epochs.
4. Fee Distribution Split (10 / 1 / 89)
For each epochly storage-fee batch collected from an account:
Implementation contract:
STORAGE_FEE_PLATFORM_BPS = 1000(10%)STORAGE_FEE_CHALLENGE_POOL_BPS = 100(1%)STORAGE_FEE_RELAY_BPS = 8900(89%)- Invariant:
STORAGE_FEE_PLATFORM_BPS + STORAGE_FEE_CHALLENGE_POOL_BPS + STORAGE_FEE_RELAY_BPS == 10000
cip31.cbfs.fee_split; the invariant MUST hold after any proposal.
Disposition of the 10% share. Storage and transfer fees are collected in CBY (§1, §2).
The share is therefore credited to the Platform Fee Account, system actor 0x18, and the parameter is cip31.cbfs.fee_split.platform_bps. This is a platform share in the marketplace sense — the owner pays, relays do the work, the platform takes a cut — and it is deliberately NOT called a treasury share: treasury elsewhere in Cowboy denotes the protocol treasury, and the two have different owners and different purposes.
It is credited rather than burned because burning is irreversible and crediting is not: a credited share can be burned later from the account, while a burned one cannot be recovered, and the credit preserves an on-chain record of accrued platform revenue that a burn destroys.
The address is fixed rather than governance-set, so no governance write can redirect the share and settlement needs no per-block state read to find it. Withdrawal authority is genesis-defined for the account under COW-2915 — 0x18 sits in the keyless reserved system range, so it needs an explicit genesis-configured owner or multisig rather than a recoverable key, and v1 defines accrual here while COW-2915’s resolution defines the exit path before mainnet genesis. Where a CBY sink is wanted, it is a buy-and-burn performed from that account, outside settlement and outside consensus.
This applies only to fees. Slashed Relay stake (§8) is denominated in CBY and its 10% share is still burned, which remains coherent: the stake is a token position, not a dollar claim.
5. Relay Pro-Rata Weight Formula
shard_count_iis the number of unique shards Relayicurrently holds and serves with valid PoR responses in the prior epoch.shard_age_in_epochs_iismin(epochs_since_assignment, MAX_SHARD_AGE_FOR_WEIGHTING)whereMAX_SHARD_AGE_FOR_WEIGHTING = 90epochs (~3 months at 1-day epochs). The cap prevents permanent first-mover advantage.
cip31.cbfs.relay_weight_formula. Tier-0 may not change the formula structure, only MAX_SHARD_AGE_FOR_WEIGHTING.
6. Minimum Relay Stake
0x0B). Sized to be meaningful relative to a professional Relay’s expected revenue: a Relay holding ~100 TiB of shards backs ~67 TiB of logical data at K + M = 4 + 2, earning ~5,450 CBY / month from the 89% pro-rata share — high enough to deter spam, low enough to admit professional operators.
At 33,000 CBY that is 6.06 months of revenue. The figure was 5,000 CBY when the storage fee was calibrated at CBY = $1; repricing the fee for the administered rate preserved relay revenue in USD but not the stake, which is a fixed CBY quantity, so it was resized with it. RELAY_CHALLENGE_BOND, CHALLENGER_BOUNTY and the three penalties were scaled by the same 6.6x, preserving every internal ratio — miss, fraud and eviction remain 1%, 10% and 40% of stake. POR_CHALLENGE_FEE is the one exception: 1 -> 7 is 7x, because 6.6 is not an integer and rounding down to 6 would have made the fee cheaper in real terms than it was. The break-even miss fraction therefore moves from 1/6 to 7/40, slightly against the challenger.
Mutability: Tier-0, key cip31.cbfs.min_relay_stake.
7. Relay Challenge Bond (new field)
por_challenge(shard_id, byte_offset, byte_length). This is new — CIP-9 §5.6 currently describes PoR challenges but specifies no challenger bond. Without a bond, a malicious actor can submit unlimited challenges to grief Relay Nodes (each forces a POR_RESPONSE_WINDOW Relay-side computation).
Lifecycle:
- Bond is escrowed at
0x0Bfor the duration of the challenge window. - If the Relay responds correctly within
POR_RESPONSE_WINDOWblocks: bond is refunded to the challenger minus aPOR_CHALLENGE_FEE = 7 CBY(kept by0x0Bas the per-challenge cost; deters frivolous challenges). - If the Relay fails or responds incorrectly: bond is refunded in full and the challenger additionally receives a
CHALLENGER_BOUNTY = 33 CBYfrom the PoR challenge pool (§4 above).- Pool-bounded (no underflow). The paid bounty is
min(CHALLENGER_BOUNTY, available_pool, epoch_cap_remaining), whereavailable_pool = pool_balance − reserveandepoch_cap_remaining = POR_BOUNTY_EPOCH_CAP − paid_this_epoch. If the challenge pool cannot cover the full bounty, the challenger receives only what the pool holds (the pool never goes negative and no bounty is minted beyond it).POR_BOUNTY_EPOCH_CAP(Tier-0,cip31.cbfs.por_bounty_epoch_cap, default unbounded) additionally bounds total bounties per rent epoch, preventing a pool drain from starving the challenge timer’s own pre-charge (§9). The challenger’s bond refund is unconditional and independent of pool balance.
- Pool-bounded (no underflow). The paid bounty is
- The Relay is slashed per §8 below.
cip31.cbfs.relay_challenge_bond. POR_CHALLENGE_FEE and CHALLENGER_BOUNTY are sub-keys, both Tier-0.
8. Slashing Schedule
The three CIP-9 §14 TBD penalty rows are pinned as:0x18 (§4), which is deliberately not a treasury share.
Mutability: All three penalty rows are Tier-0, keys cip31.cbfs.por_miss_penalty, cip31.cbfs.por_fraud_penalty, cip31.cbfs.relay_eviction_penalty.
9. Dispute Window
The on-chain dispute window for a Relay’s challenge response is 75 blocks (DISPUTE_WINDOW_BLOCKS per WP §13), aligned with CIP-2’s runner-result dispute window. After 75 blocks the response settles; no later reversal except via cryptographic EvidenceInvalidityAppeal (see CIP-32 once authored).
10. Parameter Storage at 0x09 Governance
All values above are stored at the Governance system actor (0x09) in the CIP-12 centralized governance-parameter store, under logical parameter paths cip31.cbfs.<name> (full on-chain key system:gov:param:cip31.cbfs.<name>). The Storage Manager system actor (0x0A per CIP-9 §11.1) reads these keys at the start of each rent-epoch to settle fees.
These are governance parameters. The challenge-pool balance, escrowed challenge bonds, and per-epoch counters are runtime state and live separately at the Relay Registry system actor (0x0B) under ras:* keys (see §4 and §7) — the 0x0B address in this CIP refers only to that escrow/pool/bond state, never to the parameters.
11. Genesis-defaults Summary Table
Rationale
Why a separate CIP rather than amending CIP-9 inline. CIP-9 owns the data plane (shards, manifests, erasure coding, PoR mechanics). CIP-31 owns the economic plane (rates, splits, bonds, slashing magnitudes). Splitting them lets governance touch the economic surface (Tier-0 / Tier-2) without re-opening the data-plane spec. This mirrors CIP-3 ↔ WP §13 (mechanism vs parameter values). Why these specific values. The storage rate is anchored to commodity object storage. Backblaze B2 (7.64 / TiB / month ≈ 0.28 / GiB / yr) is the ceiling users would otherwise pay for hot, durable storage. A Relay stores 1.5× raw bytes per logical byte (K + M = 4 + 2 erasure coding) and keeps 89% of fees, so its break-even fee is ≈ 1.7× its underlying storage cost: roughly 154 / TiB / yr reselling B2. The chosen rate (~0.01 per decimal GB).
Why RELAY_CHALLENGE_BOND = 66 CBY. Sized to 1/5 of POR_MISS_PENALTY, so a challenger who provokes a miss is net economically positive (+33 bounty − 7 challenge fee = +26 CBY per valid challenge) while a frivolous challenger loses the 7 CBY fee deterministically.
Security Considerations
- Challenge griefing. Without
RELAY_CHALLENGE_BONDa single attacker could submit thousands of cheap challenges per block. The bond + per-challenge fee (7 CBY) make this economically irrational below roughly one genuine miss per six attempts: a challenger nets+33 CBY(bounty) on a real miss and loses7 CBY(fee) on a correct response, so expected value is40p − 7at miss-fractionp, breaking even atp = 7/40 ≈ 0.175. - Rate cliff. Storage rate as a Tier-0 parameter means a single proposal could spike rent 10× in one epoch. The 30/90-day review cadence in §1 is documentation only; the protocol-level guardrail is CIP-12’s Tier-0 timelock (3 days) plus the per-epoch grace period (
STORAGE_GRACE_EPOCHS= 1 storage epoch =STORAGE_EPOCH_BLOCKS= 86,400 blocks ≈ 24 h) that lets evicted volumes recover. - Pro-rata gaming. The weight formula
shard_count × shard_ageis hard to game: shard assignment is VRF-controlled (CIP-9 §5.3), shard age accrues only with valid PoR responses, and the 90-epoch cap prevents permanent capture. - Slashed-stake recycling. The 10/1/89 split for slashed Relay stake (§8) sends 89% to the other Relays. This composes with the deflationary signal (10% burn) and provides an economic incentive for healthy Relays to call out misbehaving peers — without creating a perverse incentive to frame innocent peers (since the bounty is in the 1% challenge pool, not in the 89% pro-rata share).
Backwards Compatibility
This CIP introduces no semantic change to CIP-9. Every parameter named here is either:- a TBD row in CIP-9 §14 being filled in with a concrete value (10 of 13 rows), or
- a renaming / explicit-bps version of the schema already present (
STORAGE_FEE_BURN_RATE10% becomesSTORAGE_FEE_PLATFORM_BPS = 1000;POR_CHALLENGE_FEE_SHAREbecomesSTORAGE_FEE_CHALLENGE_POOL_BPS = 100), or - a brand-new field (
RELAY_CHALLENGE_BOND,POR_CHALLENGE_FEE,CHALLENGER_BOUNTY,MAX_SHARD_AGE_FOR_WEIGHTING) that supplements but does not replace CIP-9 mechanism.

