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:

Param
Default
Notes

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)

  • inflowUpvoteCountedShare

  • inflowDownvotes

  • inflowFlagsNoAction

  • inflowBondsSlashed

  • outflowNodeRewards

  • outflowOther (future)

5.2 Solidity Sketch

Notes

  • Actions and Disputes send funds into Vault via transferFrom.

  • NodeRewards pulls rewards via transferToNodeRewards on 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:

    1. Computes Vault net inflow since last rollover: delta = max(0, Vault.balanceOf() − lastVaultSnapshot)

    2. Computes **allocation = min(delta, delta * REWARDS_BPS_MAX / 10_000)`

    3. Calls Vault.transferToNodeRewards(allocation)

    4. Splits allocation into Uptime / Build / Serve buckets by configured BPS.

    5. 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 same root (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., k successful 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 = 0 and redistribute to build/uptime.

6.4 Solidity Sketch

Design choices

  • Pull model for rewards: claim() calls back into Vault.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)

  1. Register node with payout address, pubkey, and primary languages:

  2. Run CIN with those languages; build segments; announce snapshots each time you cut one:

  3. Peers/watchers attest roots and uptime.

  4. 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: metaHash includes 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 * netInflow per epoch.

    • NodeRewards cannot pull more than allocation.

  • Reentrancy‑safe: finalizeEpoch and claim are 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,000

  • Splits: 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,de

    • crumpet 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