Vault & Node Rewards (Inflows, Epoch Accounting, Payouts)
Status: Concept for v0 / v0.1 Last updated: YYYY‑MM‑DD
1) Purpose & Scope
Two tightly‑coupled modules:
Vault — the protocol treasury that receives funds from actions and disputes, and allocates a DAO‑configured share to node incentives.
Node Rewards — the epoch system that accounts node work (build/uptime/serve) and pays out from the Vault allocation.
ELI5: All the little fees and penalties flow into a big jar (Vault). Each week, we pour some of the jar into rewards for librarians (nodes) who build and share the search indexes.
Out of scope: voting math (Actions), dispute logic (Disputes), article storage (AOM), UI.
2) Responsibilities & Non‑Goals
Vault
Receive all treasury inflows.
Track rolling balance snapshots to compute net inflow per epoch.
Transfer a DAO‑capped percentage to Node Rewards each epoch.
Node Rewards
Register nodes & their primary languages.
Accept snapshot announcements (roots) and attestations.
Compute per‑epoch shares (build/uptime/serve) and allow nodes to claim their payout.
Non‑Goals
Evaluating index quality beyond majority/committee acceptance (future).
On‑chain full per‑query accounting (future).
3) Economic Flows Recap (from finalized rules)
Vault inflows
Upvotes: 20% of the counted part (
min(amount, MAX_UP_WEIGHT))Dislike/DownVote: 100% of the fixed amount (25/50)
Flags: 100% of unrefunded flags (when DAO takes NoAction)
Publish bonds: 100% of slashed bonds (when DAO takes Action within grace)
Vault outflows
Node Rewards Pool: up to 40% of net inflow per epoch (DAO‑tunable)
Split 40% uptime / 40% build / 20% serve (DAO‑tunable)
(Future) Any other DAO‑approved programmatic spends
Definitions
Net inflow (epoch) =
max(0, VaultBalance(now) − VaultBalance(lastEpochStart))(ignores prior epoch’s NodeRewards transfers; see §6.2)
4) Parameters (DAO‑Timelocked)
From Config:
REWARDS_BPS_MAX
4000
basis points of net inflow (max 40%)
REWARDS_SPLIT_UPTIME_BPS
4000
40% of rewards to uptime
REWARDS_SPLIT_BUILD_BPS
4000
40% to build
REWARDS_SPLIT_SERVE_BPS
2000
20% to serve (optional)
EPOCH_SECONDS
7 days
epoch length
ATTEST_MIN_BUILDERS
2
roots need ≥2 builders agreeing (or committee)
ATTEST_MIN_PEERS
3
2‑of‑3 peer agreement recommended
SERVE_MAX_RECEIPTS_PER_NODE
cap
anti‑gaming cap per epoch
MIN_LANG_WEIGHT
1
weight per small language snapshot
LANG_WEIGHTS[code]
varies
optional per‑lang weight (EN > niche)
Governance can change splits/weights later without redeploys.
5) Vault — Design & Interfaces
5.1 Accounting Model
Vault has no complex ledger, just a balance of CRUMBS and category counters (for analytics).
NodeRewards pulls a capped share of the net inflow each epoch.
Counters (for observability only)
inflowUpvoteCountedShareinflowDownvotesinflowFlagsNoActioninflowBondsSlashedoutflowNodeRewardsoutflowOther(future)
5.2 Solidity Sketch
Notes
Actions and Disputes send funds into Vault via
transferFrom.NodeRewards pulls rewards via
transferToNodeRewardson epoch rollover (see §6.2).Counters are non‑authoritative analytics; the balance is the source for allocations.
6) Node Rewards — Design & Interfaces
6.1 Concepts
Node registration: A node registers its pubkey and primary languages (the ones it intends to build).
Snapshot announcement: Builders post
(lang, root, metaHash, ipfsCid)with a signature.Attestations: Other builders (and/or watchers/committee) sign that they agree the snapshot is valid.
Acceptance: A snapshot is accepted if it reaches
ATTEST_MIN_BUILDERS(≥2 builders) or passes a committee threshold (fallback for single‑builder languages).Epoch payout: At epoch end, rewards are computed and claimable by nodes.
6.2 Epoch Accounting
Timeline
Epochs are wall‑clock partitions of
EPOCH_SECONDS.On epoch rollover, NodeRewards:
Computes Vault net inflow since last rollover:
delta = max(0, Vault.balanceOf() − lastVaultSnapshot)Computes **allocation = min(delta, delta * REWARDS_BPS_MAX / 10_000)`
Calls
Vault.transferToNodeRewards(allocation)Splits
allocationinto Uptime / Build / Serve buckets by configured BPS.Calculates each node’s share and records claimable amounts.
Why snapshot + delta? Simple, auditable, avoids per‑inflow callbacks.
6.3 Shares (v0 / v0.1)
Build share (40%) — core, provable on‑chain
For each language
L, if there are ≥2 builders who submitted the sameroot(attested) in the epoch, award build credits to those builders.If only one builder exists for
L, require committee attestations (e.g., 2‑of‑N watcher keys).Language weights: optional
LANG_WEIGHTS[L]to reflect corpus size.Node’s build score =
Σ_{accepted snapshots by node} LANG_WEIGHTS[L].Build bucket split pro rata by this score.
Uptime share (40%) — watcher attestations
Off‑chain watchers (community‑run) periodically probe nodes (gRPC/HTTP2 health, snapshot freshness, serve a test query).
Watchers post batched Merkle attestation to chain per node per epoch (e.g.,
ksuccessful checks).Node qualifies if it passes minimum checks; uptime score = #valid checks (capped).
Uptime bucket split pro rata by uptime scores.
Serve share (20%) — optional v0.1
Nodes may submit a commitment hash of served receipts collected from clients (to avoid privacy issues).
Cap receipts per node at
SERVE_MAX_RECEIPTS_PER_NODE.Anti‑gaming: receipts must be signed by distinct client keys provided by the webapp SDK; duplicate client keys ignored per epoch.
Serve bucket split pro rata by accepted receipt count.
If serve receipts are not ready at v0, set
REWARDS_SPLIT_SERVE_BPS = 0and redistribute to build/uptime.
6.4 Solidity Sketch
Design choices
Pull model for rewards:
claim()calls back intoVault.transferToNodeRewards(total); Vault pays out.finalizeEpoch() can be called by anyone (permissionless); use time gates (
block.timestamp).Attestations: flexible — can be builders, peers, or watchers. The policy (minimum counts) lives in Config.
7) Node Lifecycle (Operator View)
Register node with payout address, pubkey, and primary languages:
Run CIN with those languages; build segments; announce snapshots each time you cut one:
Peers/watchers attest roots and uptime.
At epoch end, finalizeEpoch(); then claim your reward.
8) Integrity & Anti‑Gaming
Majority acceptance: A snapshot counts only if ≥ ATTEST_MIN_BUILDERS distinct nodes announced the same root (or committee fallback).
Version guard:
metaHashincludes renderer/analyzer versions; mismatches don’t count.Uptime attestations: require watcher signatures from a DAO‑managed allowlist (rotating keys). Caps per epoch to avoid spam.
Serve receipts: (if enabled) count unique client keys; commitments prevent dumping raw data on‑chain; cap per node per epoch.
Sybil resistance: Registration costs can be added later (small bond) if needed.
No double‑count: a node cannot earn build credit twice for the same (lang, root) in an epoch.
9) Security & Invariants
Vault funds conservation:
outflowNodeRewards ≤ REWARDS_BPS_MAX * netInflowper epoch.NodeRewards cannot pull more than
allocation.
Reentrancy‑safe:
finalizeEpochandclaimare guarded; CEI pattern.Time correctness: relies on
block.timestamp, not block counts (rollup friendly).Access control: Only Actions/Disputes can call inflow methods; only NodeRewards can pull payouts.
DoS considerations: Attestation caps per epoch; bounded loops (use mappings & iterative claims).
10) Performance Targets
finalizeEpoch(): O(#langs + #nodes active), designed to be under 5M gas with reasonable caps.
claim(): O(#epochs claimed); recommend batching ≤10 epochs per tx.
Off‑chain: announcements/attestations are small, infrequent (per snapshot).
11) Testing Checklist
Vault
Inflow routes: upvote share, downvotes, flags no‑action, bonds slashed increment counters and increase balance.
NodeRewards pull limited by allocation; counters updated.
NodeRewards
Registration: set pubkey/langs; deactivate/reactivate.
Announcements: invalid sigs rejected; meta version mismatches ignored; duplicates idempotent.
Attestations: counting policy enforced (≥2 builders or committee).
Uptime: watcher signatures verified; caps applied.
Serve (if enabled): cap and uniqueness enforced.
finalizeEpoch: allocation pulled, splits computed, claimables written; no double finalize.
claim: transfers exact sums; zero after claim; cannot overdraft Vault.
Property/Fuzz
Rewards never exceed cap (BPS) times net inflow.
No node can gain from announcing conflicting roots for same lang in same epoch.
Time skew: finalization robust to late calls and multi‑calls.
12) Example Epoch
Vault start balance: 1,000,000 CRUMBS
During epoch: +60,000 (upvote shares) +20,000 (downvotes) +5,000 (flags no‑action) +15,000 (bonds slashed) = +100,000
REWARDS_BPS_MAX = 4000→ allocation ≤ 40,000Splits: Uptime 16,000, Build 16,000, Serve 8,000
Suppose build scores sum to 80 (nodeA:40, nodeB:20, nodeC:20):
nodeA build = 8,000; nodeB = 4,000; nodeC = 4,000
Uptime scores sum to 200 (A:80, B:60, C:60):
nodeA uptime = 6,400; nodeB = 4,800; nodeC = 4,800
Serve (if enabled) sum 100 (A:20, B:60, C:20):
nodeA serve = 1,600; nodeB = 4,800; nodeC = 1,600
Totals: A=16,000; B=13,600; C=10,400 claimable.
13) Interfaces (Frontend/Operator)
Operator CLI
crumpet node register --pubkey <hex> --langs en,decrumpet node announce --lang en --root <hex> --ipfs <cid> --meta <hex> --sig <hex>crumpet node claim --epochs last:4
SDK (TS) for watchers
attestUptime(nodeAddr, checks, watcherSig)attestRoot(lang, root)(if watcher acts as committee)
14) Acceptance Criteria
Vault receives all intended inflows and exposes transfer entrypoint to NodeRewards.
NodeRewards can finalize epochs, pull capped allocation, compute fair shares, and pay claims.
Attestation policy (≥2 builders or committee) is enforced on‑chain for build credits.
Uptime attestations from allowlisted watchers are checked and capped.
Serve share can be enabled/disabled via Config without redeploy.
15) Changelog
v1: Initial Vault & Node Rewards with net‑inflow cap, epoch splits, snapshot/attestation model, watcher‑based uptime, optional serve receipts.
Last updated