reward_distributor.move
Emits VRAM tokens each window, distributed proportionally to miners' normalized OpenSkill weights.
Entry Functions
distribute
public entry fun distribute(
ledger: &ScoreLedger,
treasury: &mut TplrTreasury,
hparams: &Hparams,
window: u64,
ctx: &mut TxContext,
)
Reads normalized weights from score_ledger.move and mints emission_per_window tokens, distributing them to each miner's address proportional to their weight.
Reward Calculation
For each miner $i$ in window $t$:
Ordinal: $$\text{ord}_i = \mu_i - 3\sigma_i$$
Normalized weight: $$w_i = \frac{(\text{ord}i - \text{ord}{\min})^2}{\sum_j (\text{ord}j - \text{ord}{\min})^2}$$
Token emission: $$\text{reward}_i = w_i \cdot \text{emission_per_window}$$
The squaring amplifies the gap between high and median performers.
Validator Rewards
Validators also receive a fraction of emission_per_window proportional to their stake and submission completeness. A validator that submits scores for all $n$ miners receives more than one that submits scores for only $k < n$ miners.
Error Codes
| Code | Constant | Meaning |
|---|---|---|
| 1 | E_WINDOW_NOT_FINALIZED |
Scores not yet submitted for this window |
| 2 | E_ALREADY_DISTRIBUTED |
Rewards already distributed for this window |
| 3 | E_NO_ELIGIBLE_MINERS |
No miners with positive normalized weight |