Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: rewards overhaul #1876

Merged
merged 27 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5b43bb5
feat: add vesting spec
cdummett Aug 3, 2023
ab6a302
feat: add activity spec
cdummett Aug 3, 2023
da05d5a
feat: update reward distribution
cdummett Aug 7, 2023
80229e1
feat: address vesting feedback
cdummett Aug 7, 2023
7ae6bc5
feat: update reward metrics
cdummett Aug 7, 2023
6f75ebc
feat: add validator power metric
cdummett Aug 8, 2023
05a7c96
feat: add new entity scoping
cdummett Aug 8, 2023
1ff1e3f
refactor: linting and spellcheck fixes
cdummett Aug 8, 2023
11dd0ba
refactor: address network param feedback
cdummett Aug 8, 2023
b75b4f1
refactor: fix formatting
cdummett Aug 8, 2023
37554b5
feat: update the validator ranking metric
cdummett Aug 8, 2023
771f14c
fix: correct variable name
cdummett Aug 10, 2023
cefc499
feat: add vested multiplier
cdummett Aug 14, 2023
ff72db2
feat: change total rewards calc as per feedback
cdummett Aug 14, 2023
29c50f8
feat: remove logarithmic functions
cdummett Aug 14, 2023
9fac4b2
refactor: rename open-interest metric to position metric
cdummett Aug 14, 2023
3855351
fix: fix linting and spellcheck
cdummett Aug 14, 2023
bbe8e92
feat: add validation for k
cdummett Aug 15, 2023
2f18f45
feat: address feedback
cdummett Aug 15, 2023
2824977
feat: address exponential feedback
cdummett Aug 15, 2023
4154bcb
feat: switch rank exponential distribution to table
cdummett Aug 15, 2023
a6e14e8
feat: address feedback
cdummett Aug 15, 2023
f83d1cd
feat: apply suggestion
cdummett Aug 16, 2023
1a29685
feat: add limits
cdummett Aug 16, 2023
99c66bd
feat: clarify requirements not applied for certain metrics
cdummett Aug 16, 2023
1c35a92
feat: switch reward accounts to per unique transfer
cdummett Aug 22, 2023
4e8202b
refactor: clarification of lock period
cdummett Aug 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
226 changes: 194 additions & 32 deletions protocol/0056-REWA-rewards_overview.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Reward framework

The reward framework provides a mechanism for measuring and rewarding a number of key activities on the Vega network.
The reward framework provides a mechanism for measuring and rewarding individuals or [teams](./0083-RFPR-on_chain_referral_program.md#glossary) (collectively referred to within this spec as entities) for a number of key activities on the Vega network.
These rewards operate in addition to the main protocol economic incentives which come from
[fees](0029-FEES-fees.md) on every trade.
These fees are the fundamental income stream for [liquidity providers LPs](0042-LIQF-setting_fees_and_rewarding_lps.md) and [validators](./0061-REWP-pos_rewards.md).
Expand All @@ -20,38 +20,117 @@ Therefore, for example, to reward futures markets when they reach a lifetime tra

At a high level, rewards work as follows:

- Reward metrics are calculated for each combination of [reward type, party, market].
- The calculation used for the reward metric is specific to each reward type.
- Individual reward metrics are calculated for each combination of [reward type, party, market] and team reward metrics for each combination of [reward type, team, market].

At the end of the epoch:

1. Recurring reward transfers (set up by the parties funding the rewards) are made to the reward account(s) for a specific reward type, for one or more markets in scope where the total reward metric is `>0`. See [transfers](./0057-TRAN-transfers.md#recurring-transfers-to-reward-accounts).
1. Then the entire balance of each reward account is distributed to the parties with a non-zero reward metric for that reward type and market, pro-rata by their reward metric.
1. Then the entire balance of each reward account is distributed amongst entities with a non-zero reward metric for that reward type and market using the mechanism specified in the recurring transfer.
1. Distributed rewards are transferred to a [vesting account](./0085-RVST-rewards_vesting.md).

## Reward metrics
## Individual reward metrics

Fee-based reward metrics are scoped by [`reward type`, `market`, `party`] (this triplet can be thought of as a primary key for fee-based reward metrics).
Therefore a party may be in scope for the same reward type multiple times but no more than once per market per epoch.
Metrics will be calculated at the end of every epoch, for every eligible party, in each market for each reward type.
Individual reward metrics are scoped by [`recurring transfer`, `market`, `party`] (this triplet can be thought of as a primary key for fee-based reward metrics).

Therefore a party may be in scope for the same reward type multiple times per epoch.
Metrics will be calculated at the end of every epoch, for every eligible party, in each market, for each recurring transfer.
Metrics only need to be calculated where the [market, reward type] reward account has a non-zero balance of at least one asset.

Reward metrics will be calculated once for each party/market combination in the reward metric asset which is the [settlement asset](0070-MKTD-market-decimal-places.md) of the market.
This is the original precision for the metric source data.

### Market activity (fee based) reward metrics
For reward metrics relating to trading, an individual must meet the [staking requirement](./0057-TRAN-transfers.md#recurring-transfers-to-reward-accounts) **AND** [notional time-weighted average position requirement](./0057-TRAN-transfers.md#recurring-transfers-to-reward-accounts)) set in the recurring transfer. If they do not then their reward metric is set to `0`. Note, these requirements do not apply to the [validator ranking metric](#returns-volatility-metric) or the [market creation reward metric](#market-creation-reward-metrics).

For reward transfers where the [scope](./0057-TRAN-transfers.md#recurring-transfers-to-reward-accounts) is set to teams, each party must meet the minimum time in team requirement. That is, given a party has been in a team for $N$ epochs, if $N$ is strictly less than the network parameter `rewards.minimumEpochsInTeam` (an integer defaulting to `0`) their reward metric is set to `0`.

### Fee-based reward metrics

There will be three market activity reward metrics calculated based on fees (as a proxy for activity).
Each of these represents a reward type with its own segregated reward accounts for each market.
There will be three reward metrics calculated based on fees.

1. Sum of maker fees paid by the party on the market this epoch
1. Sum of maker fees received by the party on the market this epoch
1. Sum of LP fees received by the party on the market this epoch

These metrics apply only to the sum of fees for the epoch in question.
That is, the metrics are reset to zero for all parties at the end of the epoch.
If the reward account balance is 0 at the end of the epoch for a given market, any parties with non-zero metrics will not be rewarded for that epoch and their metric scores do not roll over (they are still zeroed).
If the reward account balance is `0` at the end of the epoch for a given recurring transfer, any parties with non-zero metrics will not be rewarded for that epoch and their metric scores do not roll over (they are still zeroed).

Fee-based reward metrics (the total fees paid/received by each party as defined above) are stored in [LNL checkpoints](./0073-LIMN-limited_network_life.md) and are restored after a checkpoint restart to ensure rewards are not lost.

### Average position metric

The average position metric, $m_{ap}$, measures each parties time-weighted average position over a number of epochs.

At the start of each epoch, the network must reset each parties time weighted average position for the epoch ($\bar{P}$) to `0`. Whenever a parties position changes during an epoch, **and** at the end of the epoch, this value should be updated as follows.

Let:

- $\bar{P}$ be the parties time weighted average position in the epoch so far
- $P_{n}$ be the parties position before their position changed
- $t_{n}$ be the time the party held the previous position in seconds
- $t$ be the amount of time elapsed in the current epoch so far


$$\bar{P} \leftarrow \bar{P} \cdot \left(1 - \frac{t_{n}}{t}\right) + \frac{|P_{n}| \cdot t_{n}}{t}$$

At the end of the epoch, the network must store the parties time weighted average position and then calculate their average position reward metric as follows.

Let:

- $m_{ap}$ be the parties average position reward metric
- $\bar{P_{i}}$ be the parties time weighted average position in the $i$-th epoch
- $N$ be the window length specified in the recurring transfer.

$$m_{ap} = \frac{\sum_{i}^{n}\bar{P_{i}}}{N}$$

### Relative return metric

The relative return metric, $m_{rr}$, measures each parties average relative return, weighted by their [time-weighted average position](#average-position-metric), over a number of epochs.

At the end of each epoch, the network must calculate and store the parties relative returns as follows.

Let:

- $r_i$ be the parties relative returns in the epoch
- $m2m_{wins}$ be the sum of all mark-to-market win transfers in the epoch
- $m2m_{losses}$ be the sum of all mark-to-market loss transfers in the epoch
- $\bar{P}$ be the parties time-weighted average position in the epoch.

$$r = \frac{|m2m_{wins}| - |m2m_{losses}|}{\bar{P}}$$

And calculate their average relative returns over the last $N$ epochs as follows.

Let:

- $m_{rr}$ be the parties relative return reward metric
- $r_i$ be the parties change in pnl in the i th epoch
- $N$ be the window length specified in the recurring transfer.

$$m_{rr} = \max(\frac{\sum_{i}^{n}{r_{i}}}{N}, 0)$$

### Returns volatility metric

The return volatility metric, $m_{rv}$, measures the volatility of a parties returns across a number of epochs.

At the end of an epoch, if a party has had net returns less than or equal to `0` over the last $N$ epochs (where $N$ is the window length specified in the recurring transfer), their reward metric $m_{rv}$ is set to `0`. Otherwise, the network should calculate the standard deviation of the set of each parties returns over the last $N$ epochs.

Given the set:

$$R = \{r_i \mid i = 1, 2, \ldots, N\}$$

The reward metric $m_{rv}$ is the standard deviation of the set $R$.

### Validator ranking metric

The validator ranking metric, $m_v$, measures the ranking score of consensus and standby validators.

At the end of each epoch, for each party who **is** a consensus or standby validator set their reward metric as follows.

$$m_v = ranking_score$$

If a party **is not** a consensus or standby validator, their reward metric is simply:

Market activity (fee based) reward metrics (the total fees paid/received by each party as defined above) are stored in [LNL checkpoints](./0073-LIMN-limited_network_life.md) and are restored after a checkpoint restart to ensure rewards are not lost.
$$m_v = 0$$

### Market creation reward metrics

Expand Down Expand Up @@ -82,41 +161,124 @@ This flag is used to prevent any given funder from funding a creation reward in

Market creation reward metrics (both each market's `cumulative volume` and the payout record flags to identify [funder, market scope, reward asset] combinations that have already been rewarded) are stored in [LNL checkpoints](./0073-LIMN-limited_network_life.md) and will be restored after a checkpoint restart.

Note this reward metric **is not** available for team rewards.

## Team reward metrics

All metrics (except [market creation](#market-creation-reward-metrics)) can be used to define the distribution of both individual rewards and team rewards.

A team’s reward metric is the weighted average metric score of the top performing `n` % of team members by number where `n` is specified when creating the recurring transfer (i.e. for a team of 100 parties with `n=0.1`, the 10 members with the highest metric score).


## Reward accounts

Trading reward accounts are defined by the reward asset (the asset in which the reward is paid out), the market, and the reward type (metric).
That is, there can be multiple rewards with the same type paid in different assets for the same market.
Trading reward accounts are defined by a hash of the fields specified in the recurring transfer funding the reward account (see the [transfers](./0057-TRAN-transfers.md#recurring-transfers-to-reward-accounts) spec for relevant details about each field). This allows multiple recurring transfers to fund the same reward pool.

Note as part of the recurring transfer a user specifies a settlement asset. The market settlement asset has nothing to do in in particular with the asset used to pay out a reward.

Note that the market settlement asset has nothing to do in particular with the asset used to pay out a reward for a market.
That is, a participant might receive rewards in the settlement asset of the market, in VEGA governance tokens, and in any number of other unrelated tokens (perhaps governance of "loyalty"/reward tokens issued by LPs or market creators, or stablecoins like DAI).

Reward accounts are funded by setting up recurring transfers, which may be set to occur only once for a one off reward.
These allow a reward type to be automatically funded on an ongoing basis from a pool of assets.
Recurring transfers can target groups of markets, or all markets for a settlement asset, in which case the amount paid to each market is determined pro-rata by the markets' relative total reward metrics for the given reward type. See [transfers](./0057-TRAN-transfers.md) for more detail.
Reward accounts are funded by setting up recurring transfers, which may be set to occur only once for a one off reward. These allow a reward type to be automatically funded on an ongoing basis from a pool of assets.
Recurring transfers can target groups of markets, or all markets for a settlement asset. See [transfers](./0057-TRAN-transfers.md) for more detail.

Reward accounts and balances must be saved in [LNL checkpoints](./0073-LIMN-limited_network_life.md) to ensure all funds remain accounted for across a restart.

## Reward distribution

All rewards are paid out at the end of each epoch *after* [recurring transfers](0057-TRAN-transfers.md) have been executed.
The entire reward account balance is paid out every epoch unless the total value of the metric over all parties is zero, in which case the balance will also be zero anyway (there are no fractional payouts).
There are no payout delays, rewards are paid out instantly at epoch end.
All rewards are distributed to [vesting accounts](./0085-RVST-rewards_vesting.md) at the end of each epoch *after* [recurring transfers](0057-TRAN-transfers.md) have been executed. Funds distributed to the vesting account will not start vesting until the [`lock period`](./0057-TRAN-transfers.md#recurring-transfers-to-reward-accounts) defined in the recurring transfer has expired.

Rewards will be distributed pro-rata by the party's reward metric value to all parties that have metric values `>0`. Note that for the market creation reward, the metric is defined to either be `0` or `1`, which will lead to equal payments for each eligible market under the pro-rata calculation. If we have reward account balance `R` and parties `p_1 – p_n` with non-zero metrics `m_1 – m_n` on the market in question:
The entire reward account balance is paid out every epoch unless the total value of the metric over all entities is zero, in which case the balance will also be zero anyway (there are no fractional payouts).

```math
[p_1, m_1]
[p_2, m_2]
...
[p_n, m_n]
Rewards are first [distributed amongst entities](#distributing-rewards-amongst-entities) (individuals or teams) and then any rewards distributed to teams are [distributed amongst team members](#distributing-rewards-amongst-team-members).

### Distributing rewards amongst entities

Rewards are distributed amongst entities based on the distribution method defined in the recurring transfer.

The protocol currently supports the following distribution strategies:

- [pro-rata]:(#distributing-pro-rata) distributed pro-rata by reward metric
- [rank]:(#distributing-based-on-rank) distributed by entities rank when ordered by reward metric

#### Distributing pro-rata

Rewards funded using the pro-rata strategy should be distributed pro-rata by each entities reward metric scaled by any active multipliers that party has, i.e.

Let:

- $d_{i}$ be the payout factor for entity $i$
- $r_{i}$ be the reward metric value for entity $i$
- $M_{i}$ be the sum of all reward payout multipliers for entity $i$ (reward payout multipliers include the [activity streak multiplier](./0086-ASPR-activity_streak_program.md#applying-the-activity-reward-multiplier) and [bonus rewards multiplier](./0085-RVST-rewards_vesting.md#determining-the-rewards-bonus-multiplier)).
- $s_{i}$ be the share of the rewards for entity $i$

$$d_{i}=r_{i} M_{i}$$

Note if the entity is a team, $M_{i}$ is set to `1` as reward payout multipliers are considered later when distributing rewards [amongst the team members](#distributing-rewards-amongst-team-members).

Calculate each entities share of the rewards, $s_{i}$ pro-rata based on $d_{i}$, i.e.

$$s_{i} = \frac{d_{i}}{\sum_{i=1}^{n}d_{i}}$$

#### Distributing based on rank

Rewards funded using the rank-distribution strategy should be distributed as follows.

1. Calculate each entity's reward metric.
2. Arrange all entities in a list in descending order based on their reward metric values and determine their rank. If multiple entities share the same reward metric value, they should be assigned the same rank. The next entity's rank should be adjusted to account for the shared rank among the previous entities. For instance, if two entities share rank 2, the next entity should be assigned rank 4 (since there are two entities with rank 2).
3. Set the entities `share_ratio` based on their position in the `rank_table` specified in the recurring transfer.
cdummett marked this conversation as resolved.
Show resolved Hide resolved
4. Calculate each entities share of the rewards.

```pseudo
Given:
rank_table = [
{"start_rank": 1, "share_ratio": 10},
{"start_rank": 2, "share_ratio": 5},
{"start_rank": 4, "share_ratio": 2},
{"start_rank": 10, "share_ratio": 1},
{"start_rank": 20, "share_ratio": 0},
]
rank=6

Then:
share_ratio=2
```

Then calculate `M := m_1 + m_2 + … + m_n` and transfer `R ✖️ m_i / M` to party `p_i` (for each `p_i`) at the end of the epoch.
Calculate each entities share of the rewards as follows.

Let:

- $d_{i}$ be the payout factor for entity $i$
- $s_{i}$ be the share of the rewards for entity $i$
- $r_{i}$ be the share ratio of entity $i$ as determined from the rank table
- $M_{i}$ be the sum of all reward payout multipliers for entity $i$ (reward payout multipliers include the [activity streak multiplier](./0086-ASPR-activity_streak_program.md#applying-the-activity-reward-multiplier) and [bonus rewards multiplier](./0085-RVST-rewards_vesting.md#determining-the-rewards-bonus-multiplier)).

$$d_{i}=M_{i} * r_{i}$$

Note if the entity is a team, $M_{i}$ is set to 1 as reward payout multipliers are considered later when distributing rewards [amongst the team members](#distributing-rewards-amongst-team-members).

Calculate each entities share of the rewards, $s_{i}$ pro-rata based on $d_{i}$, i.e.

$$s_{i} = \frac{d_{i}}{\sum_{i=1}^{n}d_{i}}$$

### Distributing rewards amongst team members

If rewards are distributed to a team, rewards must then be distributed between team members who had a reward metric, $m$, greater than `0` based on their payout multipliers.

Let:

- $d_{i}$ be the payout for team member $i$
- $s_{i}$ be the share of the rewards for team member $i$
- $m$ be the reward metric of the team member
- $M_{i}$ be the sum of all reward payout multipliers for entity $i$ (reward payout multipliers include the [activity streak multiplier](./0086-ASPR-activity_streak_program.md#applying-the-activity-reward-multiplier) and [bonus rewards multiplier](./0085-RVST-rewards_vesting.md#determining-the-rewards-bonus-multiplier)).

$$d_{i} = \begin{cases}
0 &\text{if } m = 0 \\
M_{i} &\text{if } m > 0
\end{cases}$$

If `M=0` (no-one incurred or received fees as specified by the metric type for the given market) then no transfer will have been made to the reward account and therefore there are no rewards to pay out.
The transfer will be retried the next epoch if it is still active.
Calculate each parties share of the rewards, $s_{i}$ pro-rata based on $d_{i}$, i.e.

Reward payouts will be calculated using the decimal precision of the reward payout asset. If this allows less precision than the reward metric asset (the market's settlement asset) then the ratios between reward payouts may not match exactly the ratio between the reward metrics for any two parties. All funds will always be paid out.
$$s_{i} = \frac{d_{i}}{\sum_{i=1}^{n}d_{i}}$$

## Acceptance criteria

Expand Down
Loading