I ask MNDE holders for support of my proposal that changes our Delegation Strategy so that it becomes transparent, iterable and simple (no change of the Marinade stake pool contract needed).
What do you propose?
- Replace the scoring software of the Delegation Strategy:
- Formalize the algorithmic part of the Delegation Strategy and update/simplify overall rules and parameters
- Liquid Self-stake part of our pool:
- Open it to all mSOL holders
- Allow mSOL holders to direct stake to their validator of preference
- The percentage of the stake allocated to mSOL voting will be set at 20%
- User-selected validator must:
- Minimum amount of non-Marinade stake on the validator in all of the past 10 epochs: 100 SOL
- Maximum observed commission in all of the past 10 epochs ≤ 10 %
- Not blacklisted for running vote-lagging upgrades, commission rugs
- Running one of the version from the list specified by Marinade team (changes in the list to be announced in discord - we will mostly follow Solana Foundation’s Delegation Program’s guidelines)
- MNDE gauges controlled part of our pool:
- Gauges control 20 % of the stake (unchanged)
- Only MNDE votes on eligible validators count:
- Minimum amount of non-Marinade stake on the validator in all of the past 10 epochs: 100 SOL
- Maximum observed commission in all of the past 10 epochs ≤ 10 %
- Must be within 75th percentile of the score assigned by the algorithmic part of the Delegation Strategy
- Not blacklisted for running vote-lagging upgrades, commission rugs
- Running one of the version from the list specified by Marinade team (changes in the list to be announced in discord - we will mostly follow Solana Foundation’s Delegation Program’s guidelines)
- No validator can receive more than 10 % of the TVL governed directly by MNDE (So the cap in SOL at the time of writing this proposal is roughly 668 k * 0.1 ~ 66.8 k SOL)
- If there is an overflow of MNDE votes for an eligible validator, the overflow is split proportionally between eligible validators proportionally based on the received votes.
- If there is fewer than 10 eligible validators voted for (e.g. 8 validators, each reaching the cap), the overflow goes towards algorithmic staking.
- Algorithmic stake
-
Only eligible validators can receive stake:
- Minimum amount of non-Marinade stake on the validator in the past 10 epochs: 1000 SOL
- Maximum observed commission in the past 10 epochs ≤ 10 %
- Not blacklisted for running vote-lagging upgrades, commission rugs
- Running one of the version from the list specified by Marinade team (changes in the list to be announced in discord - we will mostly follow Solana Foundation’s Delegation Program’s guidelines)
-
Top 100 validators who are eligible for Algorithmic stake by Marinade receive stake proportionally to the score assigned.
-
The score is calculated for each validator as a weighted (w) average of normalized components (c):
-
Min-max normalization is applied on each of the components and each component then becomes a number between 0 and 1 ⇒ the overall score is also a number between 0 - 1 (We might multiply that by 10 or 100 for UI purposes). This assures each component has the same magnitude and can be affected by the set of weights in a predictable way.
-
The proposed weights applied to data between epochs 396 and 405 give similar estimated results in regards to mSOL performance (less than 0.5 % difference ⇒ negligible) and similar (or arguably better results) for decentralization support within the ecosystem ⇒ this makes it in my opinion a good starting point as the outcome for mSOL holders remains the same and we can easily build/explore on top of this simple and transparent model.
-
- Liquid Self-stake part of our pool:
Weight | Component |
---|---|
10 | Commission-adjusted credits averaged over the past 10 epochs |
2 | Stake concentration by data center averaged over the past 10 epochs |
1 | Skip rate averaged over the past 10 epochs; If a validator at any given epoch had fewer than 200 leader slots, minimum of their skip rate and cluster stake-weighted skip rate is used instead. |
What is the rationale behind the proposal?
Our Delegation Strategy (DS) began as a fork of https://github.com/solana-foundation/stake-o-matic by Solana Labs until it reached its current state and it could use some improvements.
What is wrong with the current DS?
- It is a single piece of software that combines data collection, many data transformations and scoring; it has acquired lots of technical debt over time ⇒ difficult to navigate even for us, who develop/maintain the system.
- Its output is stored in https://github.com/marinade-finance/staking-status as text files = low transparency
- the scoring is a bit too complex and difficult to understand ⇒ low transparency
- It is not possible to replicate the scoring output that happened in the past (because data collection and scoring are done at the same time) ⇒ low transparency
- It is difficult for validators to understand what to change to receive the stake from Marinade ⇒ low transparency
- When MNDE gauges overflow the cap per validator, the overflow does not necessarily go towards other MNDE voted validators, which results in MNDE controlling less stake ⇒ confusing behavior
- The scoring DB is stored as sqlite DB on github, where we are hitting GH limits of 100 MB per file ⇒ technical issues
- It does not understand commission rugs automatically.
- We currently stake with the same number of validators as we did when the SOL price was $ 200 ⇒ Now most of the validators that we stake with receive less than 10k SOL and that is too little to make a difference.
How the planned changes improve DS:
- The data collection is split from the scoring (We already have a new system for data collection we use for our Validator dashboards)
- The scoring itself then becomes: CSV file with input, a short R script producing scores and interesting graphs
- The formula in the R script and its parameters can be easily iterated over ⇒ this leads to great transparency as any past scoring result can be easily verified and compared with alternative parameters
- The output of the scoring will be available as:
- A separate section on each of the validator’s detail in our dashboards
- An overall report with simple steps on how to reproduce the results and play with them a bit
- Stake distributed by MNDE gauges will be in usual cases spread only over validators who have votes
- It is easy to make it understand commission rugs
What is the expected positive impact of this change?
While the performance of the algorithmic staking algorithm remains the same, it is much easier to iterate over and is much more transparent. E.g. if we decide to take into account MEV rewards from Jito, mTransaction, Solana-MEV or Firedancer it is easy to model the change and immediately see the impact. (We already collect MEV rewards for each Jito validator but since the rewards are very small as of now and impact even on Jito’s own APY is less than 0.1% (E.g. APY could change from 7 % to 7.007 %) we do not take MEV rewards into account for our own staking yet)
Algorithmic stake distribution should remain similar in nature:
You can compare with e.g. stake distribution within the whole Solana cluster (which is quite alarming):
R script to compute scores yourself
validators <- read.csv("403-412.csv")
validators$normalized_dc_concentration <- normalize(1 - validators$avg_dc_concentration)
validators$normalized_grace_skip_rate <- normalize(1 - validators$avg_grace_skip_rate)
validators$normalized_adjusted_credits <- normalize(validators$avg_adjusted_credits)
MARINADE_VALIDATORS_COUNT <- 100
WEIGHT_ADJUSTED_CREDITS <- 10
WEIGHT_GRACE_SKIP_RATE <- 1
WEIGHT_DC_CONCENTRATION <- 2
validators$score <- (0
+ validators$normalized_dc_concentration * WEIGHT_DC_CONCENTRATION
+ validators$normalized_grace_skip_rate * WEIGHT_GRACE_SKIP_RATE
+ validators$normalized_adjusted_credits * WEIGHT_ADJUSTED_CREDITS
) / (WEIGHT_ADJUSTED_CREDITS + WEIGHT_GRACE_SKIP_RATE + WEIGHT_DC_CONCENTRATION)
validators$eligible_algo_stake <- TRUE
validators$eligible_algo_stake[validators$max_commission > 10] = FALSE
validators$eligible_algo_stake[validators$minimum_stake < 1000] = FALSE
sorted_validators[sorted_validators$eligible_algo_stake == TRUE,]
validators$rank <- rank(-validators$score)
sorted_validators <- validators[order(validators$rank),]
marinade_validators = head(sorted_validators[sorted_validators$eligible_algo_stake == TRUE,], MARINADE_VALIDATORS_COUNT)
Disclaimer: The snapshot has been a bit simplified: e.g. some of the suspected vote laggers are already removed. In the production code this will be done properly, so after each scoring run, the snapshot will be available in full.