From de47982585cde24559417afc7964d2cbc70d01c8 Mon Sep 17 00:00:00 2001
From: import this <97586125+serinko@users.noreply.github.com>
Date: Fri, 16 May 2025 08:34:10 +0000
Subject: [PATCH] [DOCs/operators]: Updated tokenomics, reward calculator &
release notes v2025.9-appenzeller (#5769)
* correct expression about node stake
* typo fix
* sharpen overview
* detail rewards formula
* make calculator into standalone jsx component and import it
* finish pr for review
* fix alpha example with correct formula
* work in comments
---
.../calculators/reward-calculator.jsx | 120 ++++++++++++
.../operators/snippets/stake-saturation.mdx | 5 +
.../nyx-outputs/circulating-supply.md | 2 +-
.../nyx-outputs/epoch-reward-budget.md | 2 +-
.../nyx-outputs/stake-saturation.md | 2 +-
.../nyx-outputs/staking-target.md | 2 +-
.../nyx-outputs/staking_supply.md | 1 +
.../nyx-outputs/token-table.md | 6 +-
.../outputs/api-scraping-outputs/time-now.md | 2 +-
.../docs/pages/operators/changelog.mdx | 34 +++-
.../pages/operators/nodes/nym-node/setup.mdx | 8 +-
.../docs/pages/operators/tokenomics.mdx | 13 +-
.../operators/tokenomics/mixnet-rewards.mdx | 171 +++++++++++++-----
.../scripts/api-scraping/api_targets.py | 2 +-
.../scripts/next-scripts/python-prebuild.sh | 2 +
15 files changed, 305 insertions(+), 67 deletions(-)
create mode 100644 documentation/docs/components/operators/interactive/calculators/reward-calculator.jsx
create mode 100644 documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/staking_supply.md
diff --git a/documentation/docs/components/operators/interactive/calculators/reward-calculator.jsx b/documentation/docs/components/operators/interactive/calculators/reward-calculator.jsx
new file mode 100644
index 0000000000..baa8e746a4
--- /dev/null
+++ b/documentation/docs/components/operators/interactive/calculators/reward-calculator.jsx
@@ -0,0 +1,120 @@
+import React, { useState } from 'react'
+
+export default function RewardsCalculator() {
+ const [a, setA] = useState(0)
+ const [b, setB] = useState(0)
+ const [c, setC] = useState(0)
+ const [d, setD] = useState(0)
+ const [e, setE] = useState(0)
+
+ const result =
+ e !== 0
+ ? `${(
+ a * b * c * ((1 / 240) + 0.3 * ((d / e) / 240)) * 1 / (1 + 0.3)
+ ).toFixed(4)} NYM`
+ : 'â'
+
+ return (
+
+
+ Epoch Reward Calculator
+
+
+
+
+
+ Node epoch rewards (if active):
+
+ {result}
+
+
+ )
+}
+
diff --git a/documentation/docs/components/operators/snippets/stake-saturation.mdx b/documentation/docs/components/operators/snippets/stake-saturation.mdx
index 789caabe50..48788e99c9 100644
--- a/documentation/docs/components/operators/snippets/stake-saturation.mdx
+++ b/documentation/docs/components/operators/snippets/stake-saturation.mdx
@@ -3,6 +3,7 @@ import StakingScaleFactor from 'components/outputs/api-scraping-outputs/nyx-outp
import StakeSaturation from 'components/outputs/api-scraping-outputs/nyx-outputs/stake-saturation.md';
import CirculatingSupply from 'components/outputs/api-scraping-outputs/nyx-outputs/circulating-supply.md';
import { Callout } from 'nextra/components';
+import StakingSupply from 'components/outputs/api-scraping-outputs/nyx-outputs/staking_supply.md';
Stake saturation is a node reputation done in a form of self bond or stakers delegation. Optimal stake saturation level is calculated as:
@@ -12,7 +13,11 @@ Stake saturation is a node reputation done in a form of self bond or stakers del
> **rewarded_set_size = active_set_size + standby_set_size**
+{/*
With current circulating supply of NYM, staking target of NYM, divided by the sum of nodes in the [rewarded set](https://validator.nymtech.net/api/v1/epoch/reward_params), the stake saturation level is NYM per node.
+*/}
+
+With current circulating supply of NYM, staking target of NYM, divided by the sum of nodes in the [rewarded set](https://validator.nymtech.net/api/v1/epoch/reward_params), the stake saturation level is NYM per node.
Node stake saturation is a value between `0` and `1` following this logic.
diff --git a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/circulating-supply.md b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/circulating-supply.md
index 1b6a785503..988b2034ec 100644
--- a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/circulating-supply.md
+++ b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/circulating-supply.md
@@ -1 +1 @@
-809_964_694
+811_308_857
diff --git a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/epoch-reward-budget.md b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/epoch-reward-budget.md
index a2e81ba166..9fae781574 100644
--- a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/epoch-reward-budget.md
+++ b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/epoch-reward-budget.md
@@ -1 +1 @@
-5_278
+5_241
diff --git a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/stake-saturation.md b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/stake-saturation.md
index c634d45eef..f3b0263af2 100644
--- a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/stake-saturation.md
+++ b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/stake-saturation.md
@@ -1 +1 @@
-1_031_281
+1_034_081
diff --git a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/staking-target.md b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/staking-target.md
index 0e3bff71e0..b64d58743f 100644
--- a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/staking-target.md
+++ b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/staking-target.md
@@ -1 +1 @@
-404_982_347
+405_654_428
diff --git a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/staking_supply.md b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/staking_supply.md
new file mode 100644
index 0000000000..416fde1c57
--- /dev/null
+++ b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/staking_supply.md
@@ -0,0 +1 @@
+248_179_643
diff --git a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/token-table.md b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/token-table.md
index d4f4e8203d..2aaa77a0e5 100644
--- a/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/token-table.md
+++ b/documentation/docs/components/outputs/api-scraping-outputs/nyx-outputs/token-table.md
@@ -1,7 +1,7 @@
| **Item** | **Description** | **Amount in NYM** |
|:-------------------|:------------------------------------------------------|--------------------:|
| Total Supply | Maximum amount of NYM token in existence | 1_000_000_000 |
-| Mixmining Reserve | Tokens releasing for operators rewards | 190_035_305 |
+| Mixmining Reserve | Tokens releasing for operators rewards | 188_691_142 |
| Vesting Tokens | Tokens locked outside of cicrulation for future claim | 0 |
-| Circulating Supply | Amount of unlocked tokens | 809_964_694 |
-| Stake Saturation | Optimal size of node self-bond + delegation | 1_031_281 |
+| Circulating Supply | Amount of unlocked tokens | 811_308_857 |
+| Stake Saturation | Optimal size of node self-bond + delegation | 1_034_081 |
diff --git a/documentation/docs/components/outputs/api-scraping-outputs/time-now.md b/documentation/docs/components/outputs/api-scraping-outputs/time-now.md
index b9c6c02d55..ecd1f0283b 100644
--- a/documentation/docs/components/outputs/api-scraping-outputs/time-now.md
+++ b/documentation/docs/components/outputs/api-scraping-outputs/time-now.md
@@ -1 +1 @@
-Wednesday, April 30th 2025, 12:26:39 UTC
+Thursday, May 15th 2025, 13:46:20 UTC
diff --git a/documentation/docs/pages/operators/changelog.mdx b/documentation/docs/pages/operators/changelog.mdx
index 51f4484ba1..124d45b9e2 100644
--- a/documentation/docs/pages/operators/changelog.mdx
+++ b/documentation/docs/pages/operators/changelog.mdx
@@ -47,6 +47,38 @@ This page displays a full list of all the changes during our release cycle from
+## `v2025.9-appenzeller`
+
+- [Release Binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2025.9-appenzeller)
+- [`nym-node`](nodes/nym-node.mdx) version `1.11.0`
+
+```shell
+nym-node
+Binary Name: nym-node
+Build Timestamp: 2025-05-13T14:48:01.050934949Z
+Build Version: 1.11.0
+Commit SHA: 3f6acbfd6658cb8ada8db218ba037c3c2b744b9d
+Commit Date: 2025-05-13T11:42:50.000000000+02:00
+Commit Branch: HEAD
+rustc Version: 1.86.0
+rustc Channel: stable
+cargo Profile: release
+```
+
+### Operators Updates & Tools
+
+- [Reward page updated](tokenomics/mixnet-rewards#rewards-logic--calculation) with [detailed explanation of rewards calculation](tokenomics/mixnet-rewards#rewards-calculation)
+- [Nym Explorer v2 upgraded](https://nym.com/explorer) with new search, interactive map and advanced filters
+
+### Features
+
+- [Add contains ticketbook data db query](https://github.com/nymtech/nym/pull/5670)
+- [Add `/account/{address}`](https://github.com/nymtech/nym/pull/5673): Meant to replace `https://explorer.nymtech.net/api/v1/tmp/unstable/account/{address}` for Explorer v2
+
+### Bugfix
+
+- [Use node saturation instead of its stake for selection weight](https://github.com/nymtech/nym/pull/5717)
+
## `v2025.8-tourist`
- [Release Binaries](https://github.com/nymtech/nym/releases/tag/nym-binaries-v2025.8-tourist)
@@ -107,8 +139,6 @@ cargo Profile: release
- [Add reserved byte to reply surb serialisation](https://github.com/nymtech/nym/pull/5731)
-### Bugfix
-
## `v2025.7-tex`
diff --git a/documentation/docs/pages/operators/nodes/nym-node/setup.mdx b/documentation/docs/pages/operators/nodes/nym-node/setup.mdx
index addec9250e..656fd04f2a 100644
--- a/documentation/docs/pages/operators/nodes/nym-node/setup.mdx
+++ b/documentation/docs/pages/operators/nodes/nym-node/setup.mdx
@@ -20,10 +20,10 @@ This documentation page provides a guide on how to set up and run a [NYM NODE](.
```sh
nym-node
Binary Name: nym-node
-Build Timestamp: 2025-04-29T11:36:50.614557168Z
-Build Version: 1.10.0
-Commit SHA: e594630314d4676cbe9bba9ab07bd405a9cf679a
-Commit Date: 2025-04-29T12:19:54.000000000+02:00
+Build Timestamp: 2025-05-13T14:48:01.050934949Z
+Build Version: 1.11.0
+Commit SHA: 3f6acbfd6658cb8ada8db218ba037c3c2b744b9d
+Commit Date: 2025-05-13T11:42:50.000000000+02:00
Commit Branch: HEAD
rustc Version: 1.86.0
rustc Channel: stable
diff --git a/documentation/docs/pages/operators/tokenomics.mdx b/documentation/docs/pages/operators/tokenomics.mdx
index 4cd29cd03e..c582a41be0 100644
--- a/documentation/docs/pages/operators/tokenomics.mdx
+++ b/documentation/docs/pages/operators/tokenomics.mdx
@@ -12,6 +12,7 @@ import StakingTarget from 'components/outputs/api-scraping-outputs/nyx-outputs/s
import StakingScaleFactor from 'components/outputs/api-scraping-outputs/nyx-outputs/staking-scale-factor.md';
import StakeSaturation from 'components/outputs/api-scraping-outputs/nyx-outputs/stake-saturation.md';
import StakeSaturationSnippet from 'components/operators/snippets/stake-saturation.mdx';
+import StakingSupply from 'components/outputs/api-scraping-outputs/nyx-outputs/staking_supply.md';
import EpochRewardBudget from 'components/outputs/api-scraping-outputs/nyx-outputs/epoch-reward-budget.md';
import { TimeNow } from 'components/time-now.tsx';
import { AccordionTemplate } from 'components/accordion-template.tsx';
@@ -53,9 +54,9 @@ Besides the Mixnet itself, Nym Network is secured by its own blockchain Nyx (IBC
* **Incentives:** Distribute rewards to decentralised nodes based on mixing and routing (work). This dynamic ensures that the network is as robust as possible - the nodes are chosen every hour according to their performance.
-* **Network take over defense:** Another decisive factor for a node to be chosen to the network active set is reputation. Reputation is a size of stake (delegation) where delegators earn proportional percentage of nodes rewards. Nodes without reputation are not chosen to take part in the network active set.
+* **Network take over defense:** Another decisive factor for a node to be chosen to the network active set is reputation. Reputation is a size of stake (self bond + delegation stake) where delegators earn proportional percentage of nodes rewards. Nodes without reputation are not chosen to take part in the network active set.
-* **Centralisation defense:** Any node can only have a certain stake (called stake saturation) to earn maximum rewards, increasing stake level per node leads to decreasing rewards for the operator and all delegators. This feature makes it more difficult for whales to over-stake their nodes or to attract more delegators (stakers) as they would become dis-advantaged.
+* **Centralisation defense:** Any node can only have a certain stake called [stake saturation](#stake-saturation) (self bond + delegation stake) to earn maximum rewards, increasing node stake level beyond this point leads to decreasing rewards for the operator and all delegators. This feature makes it more difficult for whales to over-stake their nodes or to attract more delegators (stakers) as they would become dis-advantaged.
To learn more about rewards calculation and distribution, read the next page [*Nym Mixnet Rewards*](tokenomics/mixnet-rewards.mdx).
@@ -117,9 +118,15 @@ A number of aimed NYM tokens to be staked in the network. The staking target a i
> **staking_target = staking_supply_scale_factor \* circulating_supply**
+{/*
Staking supply scale factor is currently it's set to be .
-The value of this variable can be changed to optimize the metrics of the network. With a current circulating supply of NYM and staking supply scale factor , the staking target is NYM.
+The value of this variable can is changed from time to time to optimize the metrics of the network. With a current circulating supply of NYM and staking supply scale factor , the staking target is NYM.
+*/}
+
+Staking supply scale factor is currently at 30.5%.
+
+The value of this variable is changed from time to time to optimize the metrics of the network. With a current circulating supply of NYM and staking supply scale factor 30.5%, the staking target is NYM.
#### Stake saturation
diff --git a/documentation/docs/pages/operators/tokenomics/mixnet-rewards.mdx b/documentation/docs/pages/operators/tokenomics/mixnet-rewards.mdx
index f542db24ff..bb9522ab3c 100644
--- a/documentation/docs/pages/operators/tokenomics/mixnet-rewards.mdx
+++ b/documentation/docs/pages/operators/tokenomics/mixnet-rewards.mdx
@@ -7,10 +7,15 @@ import { MigrateTabs } from 'components/operators/nodes/node-migrate-command-tab
import NyxPercentStake from 'components/outputs/nyx-outputs/nyx-percent-stake.md';
import NyxTotalStake from 'components/outputs/nyx-outputs/nyx-total-stake.md';
import EpochRewardBudget from 'components/outputs/api-scraping-outputs/nyx-outputs/epoch-reward-budget.md';
+import StakeSaturation from 'components/outputs/api-scraping-outputs/nyx-outputs/stake-saturation.md';
import StakeSaturationSnippet from 'components/operators/snippets/stake-saturation.mdx';
+import CirculatingSupply from 'components/outputs/api-scraping-outputs/nyx-outputs/circulating-supply.md';
+import StakingTarget from 'components/outputs/api-scraping-outputs/nyx-outputs/staking-target.md';
import { TimeNow } from 'components/time-now.tsx';
import { AccordionTemplate } from 'components/accordion-template.tsx';
import { Clt } from 'components/callout-custom/CalloutCustom.jsx';
+import React, { useState, useEffect } from 'react';
+import RewardsCalculator from 'components/operators/interactive/calculators/reward-calculator.jsx';
# Nym Operators Rewards
@@ -23,7 +28,7 @@ import { Clt } from 'components/callout-custom/CalloutCustom.jsx';
* Nym tokenomics are based on the research paper [*Reward Sharing for Mixnets*](https://nymtech.net/nym-cryptoecon-paper.pdf)
* For a more comprehensive overview, live data and supply graphs, visit [*explorer.nym.spectredao.net/token*](https://explorer.nym.spectredao.net/token)
-We are working on the final architecture of [*Fair Mixnet*](#fair-mixnet) tokenomics implementation and its detailed documentation. **The current design is called [*Naive rewarding*](#naive-rewarding).** It is an intermediate step, allowing operators to migrate to `nym-node` in Mixnet smart contract and for the first time recieve delegations and earn rewards for any `nym-node` [functionality](../nodes/nym-node/setup#functionality-mode), in opposite to the past system, where only Mixnodes were able to recieve delegations and rewards.
+We are working on the final architecture of [*Fair Mixnet*](#fair-mixnet) tokenomics implementation and its detailed documentation. **The current design is called [*Naive rewarding*](#naive-rewarding).** It is an intermediate step, allowing operators to migrate to `nym-node` in Mixnet smart contract and for the first time receive delegations and earn rewards for any `nym-node` [functionality](../nodes/nym-node/setup#functionality-mode), in opposite to the past system, where only Mixnodes were able to receive delegations and rewards.
**Please read the [roadmap section below](#roadmap) to see the planned development.**
@@ -44,33 +49,46 @@ To make it easier for the reader, we use a highlighting line on the left side, w
*/}
+
Nodes bonded with vesting tokens are [not allowed to join rewarded set](https://github.com/nymtech/nym/pull/5129) - read more on [Nym operators forum](https://forum.nymtech.net/t/vesting-accounts-are-no-longer-supported/827).
-## Overview
+## Rewards Logic & Overview
-This is a quick summary, to understand the full picture, please see detailed [*Rewards Logic & Calculation*](#rewards-logic--calculation) chapter below.
+This is a quick overview, to understand the logic behind fundamentals like [rewarded set selection](#rewarded-set-selection), [node performance](#node-performance-calculation), [stake saturation](#stake-saturation), or [rewards calculation](#rewards-calculation), please read the chapters below.
-* The operators of `nym-node` get rewarded from [Mixmining pool](https://validator.nymtech.net/api/v1/epoch/reward_params), which emits NYM per hour.
-* The [rewarded set](../tokenomics.mdx#active-set) of `nym-nodes` selected for Nym network routing and mixing is currently 240 nodes in total and it's selected for each new epoch (60 min). The number can be adjusted - look here for the current value: [validator.nymtech.net/api/v1/epoch/reward_params](https://validator.nymtech.net/api/v1/epoch/reward_params)
-* `nym-nodes` can run in mode `entry-gateway`, `exit-gateway` and `mixnode`, which are positioned into layers
-* NymVPN users can chose to route through Nym Network in two ways:
- - Mixnet: 5 layers routing and mixing - full privacy
- - Wireguard: 2 layers routing, skipping 3 mixing layers - fast mode
-* **The current reward system is [*Naive rewarding*](#naive-rewarding) - an intermediate step - where each layer get's rewarded the same**
-* In the final model, nodes will get rewarded based on their layer position and the work they do (collected user tickets), where and the reward distribution per layer will be according to a [decision made by the operators](https://forum.nymtech.net/t/poll-what-should-be-the-split-of-mixmining-rewards-among-the-layers-of-the-nym-mixnet/407) as follows:
- - 5-hop: 16%-16%-16%-16%-36%
- - 2-hop: 33%-67%
-* Currently Gateways earn rewards only from taking a part in the rewarded set. The operators can sign up to a grant program as a substitution for 2-hop (Wireguad) routing.
-* To read more about the final design and future implementation, see [*Roadmap*](#roadmap) chapter for more details.
+* **The current reward system is called [*Naive rewarding*](#naive-rewarding) - an intermediate step - where the operators of `nym-node` get rewarded from [Mixmining pool](https://validator.nymtech.net/api/v1/epoch/reward_params), which emits NYM per hour**
+* **Only nodes selected to [rewarded set](../tokenomics.mdx#active-set) of Mixnet receive rewards**
+* The [rewarded set](../tokenomics.mdx#active-set) of the Mixnet is currently **240 nodes in total and it's selected for each new epoch (60 min)**, from all the nodes registered (bonded) in the network
+* Each node gets the same proportion of work factor because of the *naive* distribution of work
+* In the [final model](#roadmap), nodes will get rewarded based on their layer position and the work they do (collected user tickets), where the work factor distribution per layer will be according to a [decision made by the operators](https://forum.nymtech.net/t/poll-what-should-be-the-split-of-mixmining-rewards-among-the-layers-of-the-nym-mixnet/407) as [listed below](#nym-network-rewarded-set-distribution)
+* If a node is selected to the rewarded set, it will be rewarded in the end of the epoch, based on this reward calculation formula:
-## Rewards Logic & Calculation
+
+> **node_epoch_rewards = [total_epoch_reward_budget](https://validator.nymtech.net/api/v1/epoch/reward_params) \* node_work_fraction \* [node_stake_saturation](#stake-saturation) \* [node_performance](#node-performance-calculation)**
+>
+> We know that:
+> **[total_epoch_reward_budget](https://validator.nymtech.net/api/v1/epoch/reward_params) = **
+> **node_work_fraction = 1 / active_set_size**
+> **[active_set_size](https://validator.nymtech.net/api/v1/epoch/reward_params) = 240**
+>
+> Therefore:
+> **node_epoch_rewards = \* 1 / 240 \* [node_stake_saturation](#stake-saturation) \* [node_performance](#node-performance-calculation)**
+
-**Note that in the current intermediate model we use one active set to reward all nodes and they are asigned same work factor of 1 / 240, whether they work as Mixnode or Gateway of any kind, in both 2-hop and 5-hop mode (hence *naive rewarding*). In reality it means that all nodes are rewarded within 5-hop reward scheme only.**
+In reality there is a an additional value called **α**, giving a premium to nodes with a higher self bond. And additionally an operator gets more rewards based on [*Operators cost*](#rewards-distribution) and [*Profit margin*](#rewards-distribution) size. **Read chapter [Rewards calculation](#rewards-calculation) to be able to navigate in all the details relevant for operators and delegators.**
+
+
+**In the current intermediate model we use one active set to reward all nodes and they are assigned same work factor of 1 / 240**, whether they work as Mixnode or Gateway of any kind, in both 2-hop and 5-hop mode (hence *naive rewarding*).
+
+**In reality it means that all nodes are rewarded within the [Mixnet (5-hop) reward set](#rewarded-set-selection) only.**
**However NymVPN client can choose any `nym-node` with `--wireguard-enabled true` flag (which passed [wireguard probing test](https://harbourmaster.nymtech.net)) to route as dVPN Gateway, both entry and exit.**
+
+
+{/*
### Nym Network rewarded set distribution
@@ -97,13 +115,17 @@ This is a quick summary, to understand the full picture, please see detailed [*R
```
+
+
| **Network layer** | **1** | **2** | **3** | **4** | **5** |
| :-- | :---: | :---: | :---: | :---: | :---: |
| Node functionality in layer | Entry Gateway | Mixnode | Mixnode | Mixnode | Exit Gateway |
-| Nodes in [active set](tokenomics.mdx#active-set) | 50 | 40 | 40 | 40 | 70 |
-| Naive rewarding: Rewards distribution per node | 1 / 240 | 1 / 240 | 1 / 240 | 1 / 240 | 1 / 240 |
-| Final model: Rewards distribution per node | 0.16 / 240 | 0.16 / 240 | 0.16 / 240 | 0.16 / 240 | 0.36 / 240 |
+| Nodes in [active set](#rewarded-set-selection) | 50 | 40 | 40 | 40 | 70 |
+| Naive rewarding \*: Maximum work fraction per node | 1 / 240 | 1 / 240 | 1 / 240 | 1 / 240 | 1 / 240 |
+| Final model \*\*: Layer multiplier | 0.16 | 0.16 | 0.16 | 0.16 | 0.36 |
+> \* Only nodes chosen to the [rewarded set](#rewarded-set-selection) will be rewarded in Mixnet mode (5-hop).
+> \*\* In the final model the nodes routing as Exit Gateway get premium rewards due to the complexity and legal challenges coming along operating this type of node. Read [roadmap section](#roadmap) in the bottom of the page to get a detailed breakdown of the final implementation.
@@ -124,25 +146,27 @@ This is a quick summary, to understand the full picture, please see detailed [*R
| :-- | :---: | :---: |
| Node functionality in layer | Entry Gateway | Exit Gateway |
| Naive rewarding: Nodes in [active set](tokenomics.mdx#active-set) | only Mixnet mode | only Mixnet mode |
-| Naive rewarding: Rewards distribution per node | only Mixnet mode | only Mixnet mode |
-| Final model: Rewards distribution per node | 0.33 \* collected_user_tickets | 0.67 \* collected_user_tickets |
+| Naive rewarding\*: Maximum work fraction per node | only Mixnet mode | only Mixnet mode |
+| Final model\*\*: Layer multiplier | 0.33 | 0.67 |
+> \* In the current state called [*Naive rewarding*](#naive-rewarding) only nodes in the Mixnet [rewarded set](#rewarded-set-selection) get rewarded.
+> \*\* In the final model the nodes routing as Exit Gateway get premium rewards due to the complexity and legal challenges coming along operating this type of node. Read [roadmap section](#roadmap) in the bottom of the page to get a detailed breakdown of the final implementation.
+*/}
-### Rewarded Set Selection
+## Rewarded Set Selection
For a node to be rewarded, the node must be part of a [Rewarded set](https://validator.nymtech.net/api/v1/epoch/reward_params) (which currently = active set) in the first place. The Rewarded set is freshly selected at the start of each epoch (every 60 min), and it consists of 240 Nym nodes that are probabilistically chosen from all the available nodes. These 240 nodes include 120 gateways and 120 mixnodes (40 for each of 3 mixnet layers).
-Nodes selected into the rewarded set are chosen probabilisticaly are randomly selected, and their selection chances increase the larger nodes weight is. Weight value is always between `0` and `1` and it's calculated from these parameters:
+Nodes selected into the rewarded set are chosen probabilisticaly are randomly selected, and their selection chances increase the larger nodes weight is. Weight value is always between `0` and `1` and it's calculated from these parameters, each of them having a value between `0` and `1` (some are floats, some are binary):
1. [Performance](#node-performance-calculation): This value consists of:
- [Config score](#config-score-calculation): highest (`1`) when the node is running the latest version of the software, has [T&C's accepted](../nodes/nym-node/setup.mdx#terms--conditions) and self described API endpoint available
-- [Routing ](#routing-score-calculation): highest (`1`) when the node is consistently online and correctly processes all the received traffic
-2. [Stake saturation](#stake-saturation): including bond and delegated stake
-
+- [Routing ](#routing-score-calculation): highest (`1`) when the node is consistently online and correctly processes all the received traffic (100% of time)
+2. [Stake saturation](#stake-saturation): combining bond and delegated stake (a float number representing percentage)
**Node weight is calculated with this formula:**
@@ -155,7 +179,7 @@ For the rewarded set selection weight, good [performance](#node-performance-calc
For a comparison we made an example with 5 nodes, where first number is node performance and second stake saturation (assuming all of them [`config_score`](#config-score-calculation)) = 1 for simplification):
-
+
> node_1 = 1.00 ^ 20 \* 1.0 = **1**
> node_2 = 1.00 ^ 20 \* 0.5 = **0.5**
> node_3 = 0.99 ^ 20 \* 1.0 = **0.818**
@@ -246,7 +270,7 @@ In reality we have mixing nodes selected into 3 layers. To increase security, th
Below we break down [performance calculation](#node-performance-calculation) and show examples.
-### Node Performance Calculation
+## Node Performance Calculation
Performance is a value between `0` and `1`. The final performance number is a result of multiplying [config score](#config-score-calculation) and [routing score](#routing-score-calculation).
@@ -264,7 +288,7 @@ All parameters regarding performance score can be browsed or pull live from:
In case you don't know your nodes `NODE_ID`, it's easy to find as long as your node is bonded. Visit [validator.nymtech.net/api/v1/nym-nodes/bonded](https://validator.nymtech.net/api/v1/nym-nodes/bonded) and search your node using `identity_key` or bonding Nyx account address (denoted as `owner`).
-#### Config Score Calculation
+### Config Score Calculation
Config score is in place to ensure that the node configuration is done properly so the node is eligible for taking part in Nym network. The API looks into these paramteres:
@@ -298,7 +322,7 @@ First three points have binary values of either `0` or `1`, with a following log
Besides these values, the API also checks whether the node is bonded in Mixnet smart contract as a Nym Node or legacy node (Mixnode or Gateway). **Only nodes bonded as Nym Node in Mixnet smart contract can be selected to the Rewrded set. Thus, if you haven't migrated your node yet, please [follow these steps](../nodes/nym-node/bonding#migrate-to-nym-node-in-mixnet-smart-contract)!**
Callout>
-##### Versions Behind Calculation
+#### Versions Behind Calculation
From release `2024.14-crunch` (`nym-node v1.2.0`), the `config_score` parameter takes into account also nodes version (denoted as `versions_behind`). The "current version" is the one marked as `Latest` in our repository. The parameter `versions_behind` indicates the number of versions between the `Latest` version and the version run by the node, and it is factored into the config score with this formula:
@@ -333,57 +357,106 @@ Note that the `X` multiplier heavily lowers the `config_score` when nodes are ou
As you can see above, the algorithm is designed to give maximum selection score (`1`) to the latest version, while non-upgraded nodes receive a lower score. The score decreases faster when the node has failed to make a major version upgrade, and slower when the node is behind only with minor updates. This scoring de-prioritizes the selection of outdated nodes, even if their saturation and performance are high. Nodes are selected probabilistically in each epoch (60 min), according to their scores, to be part of the Rewarded set. This scoring mechanism gives priority to the operators running up-to-date nodes, ensuring that the network is as updated as possible.
-#### Routing Score Calculation
+### Routing Score Calculation
Routing score is measured by Nym Network Monitor which sends thousands of packages through different routes every 15 minutes and measures how many were dropped on the way. Test result represents percentage of packets succesfully returned which are then converted into floats bettween `0` and `1`.
-### Stake Saturation
+## Stake Saturation
> If you want to understand more about NYM supply, read [tokenomics page](../tokenomics#tokenomics) first.
-### Rewards Calculation
+## Rewards Calculation
-Once the rewarded set (currently 120 Mixnodes and 120 Gateways) is selected, the nodes can start to route and mix packets in the Nym Network. Each hour a total of NYM is distributed between the layers from Mixmining pool. Currently in our *Naive rewarding* intermediate design, all layers get a same portion, therefore each node is *naively* assigned same working factor and therefore earns 1/240 of the rewards per epoch.
+Once the [rewarded set](https://validator.nymtech.net/api/v1/epoch/reward_params) (currently 120 Mixnodes and 120 Gateways) is selected, the nodes can start to route and mix packets in the Nym Network. Each hour a total of NYM is distributed between the layers from Mixmining pool. Currently in our *Naive rewarding* intermediate design, all layers get a same portion, therefore each node is *naively* assigned same working factor and therefore earns 1/240 of the rewards per epoch.
If a node is active in the rewarded set, it will receive rewards in the end of the epoch, the size is dependant on [stake saturation](../tokenomics.mdx#stake-saturation) and [performance](#performance-calculation). This is how rewards get distributed between nodes in the rewarded set.
-**Rewards distribution formula:**
+**Node rewards calculation formula:**
-> **node_epoch_rewards = reward_budget * 1 / active_set_size * (stake_saturation * performance)**
+> **node_epoch_rewards = [total_epoch_reward_budget](https://validator.nymtech.net/api/v1/epoch/reward_params) \* [node_performance](#node-performance-calculation) \* [node_stake_saturation](#stake-saturation) \* ( node_work_fraction + α \* ( ( node_bond_size / [stake_saturation_level](https://validator.nymtech.net/api/v1/epoch/reward_params) ) / rewarded_set_size ) ) \* 1 / ( 1 + α )**
>
-> In the current state:
->
-> **node_epoch_rewards = * 1 / 240 * (stake_saturation * performance)**
+> Where:
+> **[total_epoch_reward_budget](https://validator.nymtech.net/api/v1/epoch/reward_params) = **
+> **node_work_fraction = 1 / rewarded_set_size**
+> **[rewarded_set_size](https://validator.nymtech.net/api/v1/epoch/reward_params) = 240**
+> **[stake_saturation_level](https://validator.nymtech.net/api/v1/epoch/reward_params) = **
+> **α = 0.3**
+>
+> Therefore:
+> **node_epoch_rewards = \* [node_performance](#node-performance-calculation) \* [node_stake_saturation](#stake-saturation) \* ( ( 1 / 240 ) + 0.3 \* ( ( node_bond_size / ) / 240 ) ) \* 1 / ( 1 + 0.3 )**
-Performance and stake saturation play an equally decisive role in the size of rewards earned after the epoch. The closer a node is to maximum value (`1`) of each of these parameters, the more rewards it will get.
+Performance and stake saturation (both are a float between `0` and `1` representing percentage) play an equally decisive role in the size of rewards earned after the epoch. The closer a node is to maximum value (`1`) of each of these parameters, the more rewards it will get.
+
+
+
+Operators aim to get [stake saturation](#stake-saturation) on their nodes as close to maximum value `1` as possible. The value of node stake is composed of **delegations** (stake from others or self) and **bond** (tokens locked by the operator on top of the node when registering it to the network).
+
+Constant **α** is a in place to increase rewards for nodes with higher bond. Minimum value of bond is 100 NYM. The higher bond an operator locks, the more skin in the game they have and therefore they receive a small premium.
+
+Let's compare 3 nodes to see their rewards, for simplicity all of them having maximum performance and stake saturation, being active in the same epoch with reward budget of 5_000 NYM, stake saturation level is 1_000_000_000 NYM and node work fraction 1 / 240. The only variable is then the size of their bond. The formula will look like this:
+
+```
+node_epoch_rewards = 5_000 * 1 * 1 * ( ( 1 / 240 ) + 0.3 * ( ( node_bond_size / 1_000_000 ) / 240 ) ) * 1 / ( 1 + 0.3 )
+```
+
+Bond size of our 3 example nodes:
+
+```
+node1_bond_size = 100 NYM
+node2_bond_size = 250_000 NYM
+node3_bond_size = 1_000_000 NYM
+```
+Rewards calculation:
+
+```
+node1_epoch_rewards = 5_000 * 1 * 1 * ( ( 1 / 240 ) + 0.3 * ( ( 100 / 1_000_000 ) / 240 ) ) * 1 / ( 1 + 0.3 )
+node2_epoch_rewards = 5_000 * 1 * 1 * ( ( 1 / 240 ) + 0.3 * ( ( 250_000 / 1_000_000 ) / 240 ) ) * 1 / ( 1 + 0.3 )
+node3_epoch_rewards = 5_000 * 1 * 1 * ( ( 1 / 240 ) + 0.3 * ( ( 1_000_000 / 1_000_000 ) / 240 ) ) * 1 / ( 1 + 0.3 )
+```
+
+The result:
+```
+node1_epoch_rewards = 16.0261 NYM
+node2_epoch_rewards = 17.2275 NYM
+node3_epoch_rewards = 20.8333 NYM
+```
+
+Difference between the smallest possible bond 100 NYM and a maximum bond 1mm NYM (equal full stake saturation point) is about 23% of increase in epoch rewards.
+ AccordionTemplate>
+
+**Try to calculate rewards yourself**
+
+
+
+> Nym documentation pages are rendered statically (like in Nextra or Next.js static export mode), that's why we don't fetch from APIs at runtime, therefore on chain data must be filled by the user at the moment to ensure they are up to date.
+
+**Rewards are sent to the Nyx account used for bonding the node and each delegator automatically by the end of an epoch in which the node was part of the rewarded set,** following the logic [described below](#rewards-distribution).
Given that there is a highly unlikely chance of all nodes having maximum stake saturation and performance, in majority of cases there will be some part of the reward budget left undistributed. This "change" is then kept in the [Mixmining reserve](../tokenomics#tokenomics).
-All parameters regarding performance score can be browsed or pull live from:
+All parameters regarding node performance score can be browsed or pull live from:
`https://validator.nymtech.net/api/v1/nym-nodes/annotation/`
In case you don't know your nodes `NODE_ID`, it's easy to find as long as your node is bonded. Visit [validator.nymtech.net/api/v1/nym-nodes/bonded](https://validator.nymtech.net/api/v1/nym-nodes/bonded) and search your node using `identity_key` or bonding Nyx account address (denoted as `owner`).
-**Rewards are send to the Nyx account used for bonding the node and each delegator automatically by the end of an epoch in which the node was part of the rewarded set,** following the logic [described below](#rewards-distribution).
-#### Rewards Distribution
-
-Once the [rewards are asigned per each node](#rewards-calculation) they need to be distributed between the operator of the node and delegators (people who staked their NYM on that node). The distribution is pretty straightforward and it happens in the following order:
+### Rewards Distribution
+Once the [rewards are assigned per each node](#rewards-calculation) they need to be distributed between the operator of the node and delegators (people who staked their NYM on that node). The distribution is pretty straightforward and it happens in the following order:
1. **Operators Cost (O.C.)**: How many NYM the operator requests to cover their costs per month, [divided by `720`](#nyx-epoch-vs-interval) (this value is set by the operator in the bonding wallet node settings)
-2. **Profit Margin (P.M.)**: What's the extra % cut the operator requests (this value is set by the operator in the bonding wallet node settings)
-3. **Bond & Stake proportionaly**: The remaining rewards are distributed proportionaly to the weight of every stake (including self bond, self delegation and each delegation).
+2. **Profit Margin (P.M.)**: The extra % cut that the operator requests (this value is set by the operator in the bonding wallet node settings, smallest value is 20% to prevent race to bottom)
+3. **Bond & Stake proportionally**: The remaining rewards are distributed proportionally to the weight of every stake (including self bond, self delegation and each delegation).
-##### Nyx Epoch vs Interval
+#### Nyx Epoch vs Interval
> **1 epoch = 60 min**
diff --git a/documentation/scripts/api-scraping/api_targets.py b/documentation/scripts/api-scraping/api_targets.py
index d7491dec27..c4cab82172 100644
--- a/documentation/scripts/api-scraping/api_targets.py
+++ b/documentation/scripts/api-scraping/api_targets.py
@@ -269,7 +269,7 @@ def parser_main():
action="store_true",
help="A multiplier of staking supply scale factor and circulating supply"
)
-
+
parser_calculate.add_argument(
"-s", "--separator",
type=str,
diff --git a/documentation/scripts/next-scripts/python-prebuild.sh b/documentation/scripts/next-scripts/python-prebuild.sh
index eb217cadb7..6fba03160f 100755
--- a/documentation/scripts/next-scripts/python-prebuild.sh
+++ b/documentation/scripts/next-scripts/python-prebuild.sh
@@ -21,6 +21,8 @@ python api_targets.py validator --api mainnet --endpoint epoch/reward_params --v
python api_targets.py validator --api mainnet --endpoint epoch/reward_params --value interval stake_saturation_point --separator _ > ../../docs/components/outputs/api-scraping-outputs/nyx-outputs/stake-saturation.md &&
+python api_targets.py validator --api mainnet --endpoint epoch/reward_params --value interval staking_supply --separator _ > ../../docs/components/outputs/api-scraping-outputs/nyx-outputs/staking_supply.md &&
+
python api_targets.py validator --api mainnet --endpoint epoch/reward_params --value interval epoch_reward_budget --format markdown --separator _ > ../../docs/components/outputs/api-scraping-outputs/nyx-outputs/epoch-reward-budget.md &&
python api_targets.py time_now > ../../docs/components/outputs/api-scraping-outputs/time-now.md &&