Reward epochs and fees
Mining projects pay out per epoch, from the project’s own vault, in the project’s own reward token.
sequenceDiagram participant V as Validators participant H as Hub participant PV as ProjectVault (Sepolia) participant M as Miner Note over V: epoch E closes V->>V: leader proposes receipt v2; others recompute from their finality votes and attest on exact match V->>H: POST /v1/nodes/epoch-receipts (attested receipt) H->>H: check quorum, hashes, caps, fee split, payout addresses H->>PV: settleEpoch(totals, merkle_root) Note over PV: challenge window (1 h): guardian may veto M->>H: GET /v1/me/claims (amount + proof) M->>H: POST /v1/me/withdrawals/claims (gasless) H->>PV: claimMany(...) → tokens to the miner Note over PV: release(E): developer and treasury shares paid out
1. Compute units
Section titled “1. Compute units”For every task round of the project finalized in epoch E with record F:
for each voter v in F.voters: units[v.payout_address] += max(1, ceil(F.gas_used / gas_per_unit))gas_per_unit is 1,000,000 on the testnet. Then the project’s caps apply: max_recipients_per_epoch
(the largest earners are kept) and max_units_per_epoch (everyone is scaled down proportionally).
2. Amounts
Section titled “2. Amounts”epoch_cap = floor(daily_emission × epoch_secs / 86400)
per-unit: g_i = units_i × reward_per_unit, scaled down if Σ g_i > epoch_capepoch-pool: g_i = floor(epoch_cap × units_i / Σ units)
miner amount_i = floor(g_i × fee_split_bp.miner / 10000)developer = floor(G × fee_split_bp.developer / 10000)treasury = G − Σ amount_i − developer (absorbs rounding dust)The fee split is in basis points and must sum to 10,000, with the miner share at least 5,000. Example from
the live reference project: per-unit, 1 NECTA per unit, split 8500 / 1000 / 500, so a miner earns
0.85 NECTA per verified unit, the developer 0.10 and the treasury 0.05.
3. Epoch receipt v2 and settlement
Section titled “3. Epoch receipt v2 and settlement”After close(E) = (E+1)·epoch_secs + round_secs + 120 + max_skew + settle, a validator leader proposes the
receipt (v: 2, with project_id, consensus_hash, reward_token, compute_units with amounts,
totals, and a merkle_root); the other validators recompute it from their own finality votes and attest
only on an exact match; the epoch votes are counted by SecureWeave. The Hub verifies the quorum and that every recipient is a payout address from that
epoch’s snapshot, then calls ProjectVault.settleEpoch. The full receipt with signatures is public:
curl -s https://testnet-rpc.necter.network/v1/explorer/epochs/<project_id>/<epoch>4. Claims
Section titled “4. Claims”Payouts are pull: each epoch has a Merkle root of (project_id, epoch, miner, amount) leaves.
leaf = keccak256(keccak256(abi.encode(bytes32 project_id, uint64 epoch, address miner, uint256 amount)))Claims open after the vault’s challenge window (vault_challenge_secs = 1 hour), during which the guardian
can veto a bad settlement. GET /v1/me/claims lists your claimable entries with proofs;
POST /v1/me/withdrawals/claims claims up to 100 at once through the Hub’s relayer, so miners pay no gas.
The developer and treasury shares are paid by release(epoch) after the same window.
Runway and underfunding
Section titled “Runway and underfunding”runway_epochs = floor((vault_balance − reserved) / epoch_cap)If the free balance is below one epoch_cap when a snapshot is built, the project is marked
underfunded: its tasks run as validator rounds (no miner units) and the store shows it as paused until
you top up the vault. A settlement that exceeds the free balance reverts and is retried after the next
Funded event. Vault and funding