Operators
Nym Mixnet Rewards

Nym Operators Rewards

⚠️

Nym Network Rewarded set selection had been upgraded recently. Make sure to read the chapter Rewarded Set Selection below carefully to fully understand all requirements to be rewarded!

ℹ️

The data on this page were last time updated on

Wednesday, May 28th 2025, 11:39:51 UTC

.

We are working on the final architecture of Fair Mixnet tokenomics implementation and its detailed documentation. The current design is called 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, in opposite to the past system, where only Mixnodes were able to receive delegations and rewards.

Please read the roadmap section below to see the planned development.

Rewards Logic & Overview

This is a quick summary, to understand the logic behind fundamentals like rewarded set selection, node performance, stake saturation, or rewards calculation, please read the chapters below.

  • The current reward system is called Naive rewarding - an intermediate step - where the operators of nym-node get rewarded from Mixmining pool (opens in a new tab), which emits

    5_241

    NYM per hour
  • Only nodes selected to rewarded set of Mixnet receive rewards
  • The rewarded 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, 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 (opens in a new tab) as listed below
  • 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:
📌

node_epoch_rewards = total_epoch_reward_budget (opens in a new tab) * node_work_fraction * node_stake_saturation * node_performance

We know that:
total_epoch_reward_budget (opens in a new tab) =

5_241


node_work_fraction = 1 / active_set_size
active_set_size (opens in a new tab) = 240

Therefore:
node_epoch_rewards =

5_241

* 1 / 240 * node_stake_saturation * node_performance

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 and Profit margin size. Read chapter 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 only.

However NymVPN client can choose any nym-node with --wireguard-enabled true flag (which passed wireguard probing test (opens in a new tab)) to route as dVPN Gateway, both entry and exit.

Rewarded Set Selection

For a node to be rewarded, the node must be part of a Rewarded set (opens in a new tab) (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 are composed of 120 gateways (50 entry and 70 exit) and 120 mixnodes (40 for each of 3 mixnet layers).

Nodes selected into the rewarded set are chosen probabilisticaly, and their selection chances increase the larger nodes weight is. Weight value is always between 0 and 1 and it's calculated by multiplying these parameters, each of them also having a value between 0 and 1 (some are floats, some are binary):

1. Performance: This value consists of:

  • Config score: highest (1) when the node is running the latest version of the software, has T&C's accepted and self described API endpoint available
  • Routing : highest (1) when the node is consistently online and correctly processes all the received traffic (100% of time)

2. Stake saturation: combining bond and delegated stake (a float number between 0 and 1 representing percentage)

Node weight is calculated with this formula:

📌

active_set_selection_weight = stake_saturation * ( node_performance ^ 20 )

For the rewarded set selection weight, good performance is much more essential than stake saturation, because it's lifted to 20th power in the selection algorhitm.

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 = 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
node_4 = 0.95 ^ 20 * 1.0 = 0.358
node_5 = 0.90 ^ 20 * 1.0 = 0.122

As you can see the performance is much more important during the Rewarded set selection. A node with 100% performance but only 50% stake saturation has much bigger chance to be chosen than a node with 95% performance and 100% stake saturation and incomparably bigger chance than 90% performing node with 100% stake saturation.

The nodes are chosen probababilistically in each epoch (60 min), so even nodes with lower performance will eventually be chosen, just much less often, as their chances decrease. Note that the score helps prioritize some nodes over others. If all available nodes have the same score, then the selection is done uniformly at random. By raising the node performance to 20, values of these parameters that are below one incur a heavy penalization for the node’s selection chances.


Explanation

The nodes are selected probabilistically, that means that even nodes with lower weight have a small chace to get slected. The probabilistic alorithm follows this logic:

  1. Summarize all nodes weight together
  2. Make a random selection roll for the first slot in the active set
  3. If a node is selected, take all its weight away from the draft queue
  4. Repeat points 1. - 3. for each slot in the active set

Example

We know that nodes weight is a float between 0 and 1. For simplification we will use integers in this example and much smaller set.

  • Total nodes: 8
  • Rewarded set: 4
  • Nodes weight:
    • node1 = 5
    • node2 = 5
    • node3 = 10
    • node4 = 10
    • node5 = 20
    • node6 = 40
    • node7 = 50
    • node8 = 60
  1. Summarize all nodes weight together:
weight_total = 5 + 5 + 10 + 10 + 20 + 40 + 50 + 60
weight_total = 200
  1. Roll a dice from 1 to 200:
  • Imagine the nodes are in line each representing the weight like index:
    • node1 = 1-5
    • node2 = 6-10
    • node3 = 11-20
    • node4 = 21-30
    • node5 = 31-50
    • node6 = 51-90
    • node7 = 91-150
    • node8 = 151-200
  • Say the function resulted in number 170
  1. Add node8 to the rewarded set and take it out of the lottery, summarize all the weights again:
weight_total = 5 + 5 + 10 + 10 + 20 + 40 + 50
weight_total = 140
  1. Roll a dice from 1 to 140:
  • Say the function resulted in number 4
  1. Add node1 to the rewarded set and take it out of the lottery, summarize all the weights again:
weight_total = 5 + 10 + 10 + 20 + 40 + 50
weight_total = 135
  1. Roll a dice from 1 to 135:
  • Say the function resulted in number 72
  1. Add node6 to the rewarded set and take it out of the lottery, summarize all the weights again:
weight_total = 5 + 10 + 10 + 20 + 50
weight_total = 95
  1. Roll a dice from 1 to 95:
  • Say the function resulted in number 21
  1. Add node4 to the rewarded set
  2. Rewarded set of 4 nodes is selected with these nodes to be chosen:
    1. node8
    2. node1
    3. node6
    4. node4
  3. After an epoch - 60 minutes - pull all bonded nodes and repeat the exact same process with their current weights

In reality we have mixing nodes selected into 3 layers. To increase security, there is an additional function in place where a node cannot be assigned to the same layer in two following epochs.

Below we break down performance calculation and show examples.

Node Performance Calculation

Performance is a value between 0 and 1. The final performance number is a result of multiplying config score and routing score.

📌

node_performance = config_score * routing_score

Performance value is an average of last 24h.

💡

All parameters regarding performance score can be browsed or pull live from:

https://validator.nymtech.net/api/v1/nym-nodes/annotation/<NODE_ID>

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 (opens in a new tab) and search your node using identity_key or bonding Nyx account address (denoted as owner).

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:

  1. If the node binary is nym-node (not legacy nym-mixnode or nym-gateway): 1 if True, 0 if False
  2. If Terms & Conditions are accepted: 1 if True, 0 if False
  3. If the nodes self described endpoint is available: 1 if True, 0 if False
  4. Version of nym-node binary: decreasing weight for outdated versions, as explained below

The config_score calculation formula:

📌

config_score = is_tc_accepted * is_nym-node_binary * self_described_api_available * ( 0.995 ^ ( ( X * versions_behind) ^ 1.65 ) )

First three points have binary values of either 0 or 1, with a following logic:

Run nym-node binaryT&C's acceptedSelf described availableValue
TrueTrueTrue1
TrueFalseFalse0
TrueTrueFalse0
FalseTrueTrue0
FalseFalseTrue0
TrueFalseTrue0
FalseFalseFalse0
FalseTrueFalse0

Only if ALL conditions above are True the node can have any chance to be selected, as otherwise the probability will always be 0.

ℹ️

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!

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 the repository (opens in a new tab). 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:

📌

0.995 ^ ( ( X * versions_behind ) ^ 1.65 )

where:
X = 1; for patches
X = 10; for minor versions
X = 100; for major versions

The exact parameters are live accessible on /v1/status/config-score-details (opens in a new tab).

Our versioning convention is: major_version . minor_version . patch

For example nym-node on version 1.2.0 is on 1st major version, 2nd minor and 0 patches.

Note that the X multiplier heavily lowers the config_score when nodes are outdated with respect to more significant updates. See the the table and graph below:

Version behindPatches (X = 1)Minor versions (X = 10)Major versions (X = 100)
0 (current version)1.01.01.0
10.9950.79940.0000
20.98440.49530.0000
30.96980.25360.0000
40.95180.11020.0000
50.93110.04130.0000

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

If you want to understand more about NYM supply, read tokenomics page first.

Stake saturation is a node reputation done in a form of self bond or stakers delegation. Optimal stake saturation level is calculated as:

📌

stake_saturation_level = staking_target / rewarded_set_size

rewarded_set_size = active_set_size + standby_set_size

With current circulating supply of

811_308_857

NYM, staking target of

248_179_643

NYM, divided by the sum of nodes in the rewarded set (opens in a new tab), the stake saturation level is

1_034_081

NYM per node.

Node stake saturation is a value between 0 and 1 following this logic.

Node stake saturation formula:

📌

node_stake_saturation = node_total_stake / stake_saturation_level

There is a caveat that the maximum value can be 1. In practice it means that:

  1. If node_total_stake < stake_saturation_level then node_stake_saturation will be a float between 0 and 1

  2. If node_total_stake = stake_saturation_level then node_stake_saturation will be 1

  3. If node_total_stake > stake_saturation_level then node_stake_saturation will be 1 due the capping function working as anti-whale prevention.

  • This results in a smaller ROI per every staked (self bond or delegation) NYM token on that node, as the maximum rewards is capped and in this case distributed in between more staked tokens.
  • For example if node_total_stake = 2 * stake_saturation_level then the reward per staked token will be 50% in comparison to a case where node_total_stake = stake_saturation_level, in other words with 100% over-saturation, ROI is half the maximum.

Rewards Calculation

Once the rewarded set (opens in a new tab) (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

5_241

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 and performance. This is how rewards get distributed between nodes in the rewarded set.

Node rewards calculation formula:

📌

node_epoch_rewards = total_epoch_reward_budget (opens in a new tab) * node_performance * node_stake_saturation * ( node_work_fraction + α * ( ( node_bond_size / stake_saturation_level (opens in a new tab) ) / rewarded_set_size ) ) * 1 / ( 1 + α )

Where:
total_epoch_reward_budget (opens in a new tab) =

5_241


node_work_fraction = 1 / rewarded_set_size
rewarded_set_size (opens in a new tab) = 240
stake_saturation_level (opens in a new tab) =

1_034_081


α = 0.3

Therefore:
node_epoch_rewards =

5_241

* node_performance * node_stake_saturation * ( ( 1 / 240 ) + 0.3 * ( ( node_bond_size /

1_034_081

) / 240 ) ) * 1 / ( 1 + 0.3 )

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 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.

Try to calculate rewards yourself

Epoch Reward Calculator

Node epoch rewards (if active):
0.000000 NYM

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.

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.

💡

All parameters regarding node performance score can be browsed or pull live from:

https://validator.nymtech.net/api/v1/nym-nodes/annotation/<NODE_ID>

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 (opens in a new tab) and search your node using identity_key or bonding Nyx account address (denoted as owner).

Rewards Distribution

Once the rewards are assigned per each node 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 (this value is set by the operator in the bonding wallet node settings)
  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

📌

1 epoch = 60 min
1 interval = 720 epochs

The logic is that interval is 30 days:
24 epochs * 30 days = 720

The Operators Cost (O.C). is a value denominated in NYM, that a node operator requires to get paid before the rewards get distributed. The cost is estimated per one month. However, it's paid only in epochs when the node is active. To calculate how O.C. works, we use a value called interval which represents 30 days (approximate month), or more precisely 720 epochs. To get covered a full O.C, the node would have to be active for the entire month.

O.C. real revenue formula

Therefore every epoch a node is active, the operator gets:

📌

epoch_operator_cost_revenue = operators_cost / epochs_per_interval

that is:

epoch_operator_cost_revenue = operators_cost / 720

To calculate O.C. per month, multiply it by number of active epochs:

📌

monthly_operator_cost_revenue = ( operator_cost / 720 ) * active_epochs

Roadmap

We are working on the final architecture of Fair Mixnet tokenomics implementation, following the decision made by the node operators (opens in a new tab). The current design is called Naive rewarding. This is an intermediate step, expecting operators to migrate to nym-node in Mixnet smart contract and be able to recieve delegations and earn rewards for any nym-node functionality, in opposite to the past system, where only Mixnodes were able to recieve delegations and rewards.

On November 5th 2024, we presented a release roadmap in live Operators Townhall (opens in a new tab) where we explained in detail the steps of Nym node and tokenomics development and the effect it will have on node operators and put it into a rough timeline.

Naive Rewarding

Naive rewarding is the current tokenomics design. The table below lists features and logic of this design.

Fair Mixnet

Fair Mixnet is the final architecture model that we work towards. The table below lists features and logic of the design once implemented.