double[] poolStartingAllocations;
double[] poolMevEfficiency;
poolStartingAllocations = new double[] { 0.3, 0.15, 0.14, 0.09, 0.06, 0.03, 0.23 };
poolMevEfficiency = new double[] { 1, 0.9, 0.85, 0.8, 0.75, 0.75, 0.7 };
const int BlocksPerDay = 7200;
const int BlocksPerYear = BlocksPerDay * 365;
const int EpochsPerYear = 82180;
const double MevPerBlock = 0.185;
const double StakedEth = 13000000;
Console.WriteLine("pbs");
Console.WriteLine("no pbs");
Console.WriteLine("no pbs or toxic mev");
Console.WriteLine("pbs dominant pool builder");
poolMevEfficiency[0] *= 1.1;
Console.WriteLine("pbs no pool builder");
poolMevEfficiency = new double[] { 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 };
var numbers = poolMevEfficiency.OrderByDescending(x => x).Take(2);
int bestExtractor = Array.FindIndex<double>(poolMevEfficiency, x => x == numbers.First());
int competingExtractor = Array.FindIndex<double>(poolMevEfficiency, x => x == numbers.Last());
var poolStakes = poolStartingAllocations.Select(x => x * StakedEth).ToArray<double>();
double sumPoolStakes = poolStakes.Sum();
double unmitigatedMev = 1 - mevMitigated;
for (int i = 0; i < poolStakes.Length; i++)
Console.Write($",pool {(char)((byte)'a' + i)}");
for (int b = 0; b <= BlocksPerYear * 50; b++)
var allocations = poolStakes.Select(x => Math.Round(x / sumPoolStakes, 5)).ToArray<double>();
Console.WriteLine("{0},{1}", sample++, string.Join(",", allocations));
countdown = BlocksPerYear;
double pickPool = rnd.NextDouble() * sumPoolStakes;
int blockProducer = poolStakes.Length - 1;
for (int p = 0; p < poolStakes.Length; p++)
double blockReward = StakingRewardPerBlock(sumPoolStakes);
AddToPoolStake(blockProducer, blockReward, sumPoolStakes, poolStakes);
double mev = MevPerBlock * unmitigatedMev;
sumPoolStakes = AddToPoolStake(blockProducer, mev * poolMevEfficiency[blockProducer], sumPoolStakes, poolStakes);
sumPoolStakes = AddToPoolStake(blockProducer, mev * poolMevEfficiency[competingExtractor], sumPoolStakes, poolStakes);
sumPoolStakes = AddToPoolStake(bestExtractor, mev * (poolMevEfficiency[bestExtractor] - poolMevEfficiency[competingExtractor]), sumPoolStakes, poolStakes);
static double AddToPoolStake(int poolIndex, double adjustment, double sumPoolStakes, double[] poolStakes)
poolStakes[poolIndex] += adjustment;
return sumPoolStakes + adjustment;
static double StakingRewardPerBlock(double sumPoolStakes)
double validators = sumPoolStakes / 32;
double annualized = EpochsPerYear * 512 / Math.Sqrt(validators * 32e9);
double baseRewardPerBlock = annualized / BlocksPerYear;
return baseRewardPerBlock * 4;