Protocol Parameters, Pledge and Sybil Resistance

I have been evaluating the recently released protocol parameters for Shelley mainnet and how pledge affects rewards given these values.

I work better with examples than abstract formulas so here are some examples for a fully saturated pool.

Reserve: 14000m
Total stake: 22000m
Tx fees: 0

Rewards available in epoch: 29.26m
Pool saturation: 146.67m

Pledge: 0m Rewards: 150051 Benefit: 0%
Pledge: 0.01m Rewards: 150054 Benefit: 0%
Pledge: 0.05m Rewards: 150067 Benefit: 0.01%
Pledge: 0.1m Rewards: 150082 Benefit: 0.02%
Pledge: 0.2m Rewards: 150113 Benefit: 0.04%
Pledge: 0.5m Rewards: 150205 Benefit: 0.1%
Pledge: 1m Rewards: 150358 Benefit: 0.2%
Pledge: 2m Rewards: 150665 Benefit: 0.41%
Pledge: 5m Rewards: 151586 Benefit: 1.02%
Pledge: 10m Rewards: 153121 Benefit: 2.05%

The problem with this is that the a0 reward benefit effect is pretty much linear related to pledge.
This does not strongly incentivize pool operators to put some pledge (such as 50k or 200k ADA) when the benefit is so small compared to 0 pledge.
The benefit only becomes meaningful for whale associated pools with 5m, 10m, or more pledged.
This defeats the purpose of preventing Sybil attacks.
The reward formula should be adjusted to have something like a y = square root of x shape rather than linear in terms of the reward benefit of increased pledge.
This way you have a steeper increase for lower ranges of pledges that will incentivize pool operators to have some meaningful pledge while leveling out as pledge increases so as not to overly reward whale pools that are not providing any additional Sybil attack prevention.
If this is not changed then I feel we will need to institute a minimum pledge of at least 10k ADA.

The output above was generated by the following simple php code.
Please correct me if my translation of the formula in section 5.5 of Design Specification for Delegation and Incentive in Cardano to code is incorrect.


// Assumptions
$reserve = 14000000000;
$total_stake = 22000000000;
$fees = 0;

echo "Assumptions\n";
echo "Reserve: " . round($reserve / 1000000, 2) . "m\n";
echo "Total stake: " . round($total_stake / 1000000, 2) . "m\n";
echo "Tx fees: " . $fees . "\n";
echo "\n";

//$pledges = array(0, 100000, 200000, 500000, 1200000, 2200000, 3200000, 4200000, 5200000, 6200000);
$pledges = array(0, 10000, 50000, 100000, 200000, 500000, 1000000, 2000000, 5000000, 10000000);
$default_pledge = 0;

$k = 150;
$rho = 0.0022;
$a0 = 0.3;
$tau = .05;
$R = (($reserve * $rho) + $fees) * (1 - $tau);
$z0 = 1 / $k;
$o = $z0; // for fully saturated pool
$saturation = round($total_stake / $k);

echo "Rewards available in epoch: " . round($R / 1000000, 2) . "m\n";
echo "Pool saturation: " . round($saturation / 1000000, 2) . "m\n";
echo "\n";

$default_s = $default_pledge / $total_stake;
$default_optimal_rewards = ($R / (1 + $a0)) * ($o + ($default_s * $a0 * (($o - ($default_s * (($z0 - $o) / $z0))) / $z0)));

foreach ($pledges as $pledge) {
  $s = $pledge / $total_stake;
  $optimal_rewards = ($R / (1 + $a0)) * ($o + ($s * $a0 * (($o - ($s * (($z0 - $o) / $z0))) / $z0)));

  echo "Pledge: " . round($pledge / 1000000, 2) . "m Rewards: " . round($optimal_rewards) . " Benefit: " . round(((($optimal_rewards / $default_optimal_rewards) - 1) * 100), 2) . "%\n";

echo "\n";

Agreed. Anything less than a few million in pledge has negligible returns.


I agree. It’s a bit confusing what this assignment scheme is trying to do.

Do we want to disincentivize 0 or near-0 pledge pools to prevent Sybil attacks?
Do we want to incentivize whales to put all their wealth in as few pools as possible to limit their representation?

If those are the priorities, why not just base it on pledge ranking rather than pledge amount?

Lets say our target is 1000 pools.
Pledge Ranking Chart

If we line the incentives like that, people will be bidding up on the pledges to try to squeeze into a higher pledge ranking, therefore naturally pushing down the visibility of low pledge pools (which would eliminate Sybil attacks).

And an additional thing that can be added is to exclude private pools from the ranking, but give them a benefit% based on the highest spot on the ranking that they exceed. That way, developer pools that want to silently over-saturate in a corner won’t take up a ranking spot.

hi im a bit of a noob but had an idea relating to pledge
what about factoring in the costs associated to running a stake pool as an added % of the rewards to build a compounding pledge mechanism that will increase the amount of pledge depending on the rewards received… if that makes sense…

You mean a pool within the pool? Came to the same conclusion. Not a bad idea indeed. It will all come down to trust, who to “pooledge” with…

1 Like

I came up with a couple alternative reward equations that use curves for the pledge benefit rather than the current linear benefit.

Alt2 substitutes the square root of pledge times the square root of crossover where crossover is the amount of pledge where the benefit is the same for the curve and the line.
That is sqrt(pledge) * sqrt(crossover) in place of pledge in the reward equation.

Alt3 substitutes the cube root of pledge times the square of the cube root of crossover.
That is pow(pledge, 1/3) * pow(crossover, 2/3) in place of pledge.

In the example below I use 5 million ADA pledge as the crossover point where the benefit of pledge is equal in all 3 formulas.

Reserve: 14b
Total stake: 22b
Tx fees: 0
Fully Saturated Pool
Rewards available in epoch: 29.3m
Pool saturation: 146.7m

Pledge  Rewards Benefit Alt2 Rw Alt2 Bn Alt3 Rw Alt3 Bn
0k      150051  0%      150051  0%      150051  0%
10k     150054  0%      150120  0.05%   150245  0.13%
50k     150067  0.01%   150205  0.1%    150382  0.22%
100k    150082  0.02%   150268  0.14%   150468  0.28%
200k    150113  0.04%   150358  0.2%    150576  0.35%
500k    150205  0.1%    150537  0.32%   150764  0.48%
1m      150358  0.2%    150738  0.46%   150949  0.6%
2m      150665  0.41%   151022  0.65%   151182  0.75%
5m      151586  1.02%   151586  1.02%   151586  1.02%
10m     153121  2.05%   152222  1.45%   151985  1.29%
20m     156190  4.09%   153121  2.05%   152487  1.62%
50m     165397  10.23%  154904  3.23%   153358  2.2%
100m    180744  20.46%  156914  4.57%   154217  2.78%
146.7m  195067  30%     158363  5.54%   154784  3.15%

Why does any of this matter?
With the current reward equation there are 2 major problems.

  1. Pools pledging less than 500k ADA see less than 0.1% reward benefit.
    This is not a strong incentive for pool operators as at current prices that is more than $60k USD.

  2. Private pools and whale pools get massive reward benefit without providing any additional protection against Sybil attacks. Why should a private pool make 29% more rewards than a pool with 5m ADA pledge while doing the same work?

The Alt2 and Alt3 versions show a much more reasonable distribution of pledge related rewards than the current version while encouraging meaningful pledges from more pool operators thus making the network more secure against Sybil attacks.

Which version of the reward function do you think is best?


Question. Is this part of the Staking Calculator? When I run simulations I get a different outcome.

for example 1% pool, with 50k pledge vs 600k pledge, everything else is 100% the same. I get a 1 ada difference. If it was the .1 vs .001 it should be more like 98 ada difference not 1 ada.

50k = 98642.38154
600k = 98643.613515

1 Like

One Idea i pitched like a month back was changing the goal posts for example. Rather than have .03 range be from 0 to saturation (or the highest pledge) have it be form 50k to like 5m , giving a much bigger difference in rewards for someone pledging 50k vs 500k vs 1m , making it better to have 1 pool with say 1m vs 10 pools with 100k , as the 10 100k pools will earn more than the 1 1m pledge pool due to min fixed fee. every time.

I created a feature request on the cardano-node github to get this idea into the
system somewhere.
It probably is more of a Cardano Improvement Proposal but I don’t know if there
is a process for that yet.

@Lars_Brunjes @pparent76 @AllisonFromm
I enjoyed your discussion of Pierre’s alternative rewards equation.
I would love to know what you think about my proposal to modify the current equation to have a curved pledge benefit rather than the current linear factor.

1 Like

Hi, I was concerned about the linear characteristic of a0 about half year ago and we had some discussion in the guild channel at that time.

But, I gave it a second thought as who will decide where the function of the shape would start having affect on the reward i.e. where the curve starts inclining and in what degree? I.e. as charles would say similar ‘who says who decides?”. There is no good choice at all. So, that is why I left it as it is.

My other concern was the ‘killing pool’ feature of the reward equation when for example a fully saturated private pool can kill and other fully saturated pool by staking its all stakes for short term to a fully saturated target pool that will cause the target pool’s would die in some epochs cos its rewards would drops down significantly and its delegators would leave. Of course the delegators could redelegate later and it cannot be sustained for long term cos the adversarial pool would loose money too but it might worth doing it anyway for some reason. So one possible idea for solving this that came up around the same time the previous one, that the over-saturator would be gradually punished but it would be hard to implement in the current design.

The problem with this is that the a0 reward benefit effect is pretty much linear related to pledge.

Hi, I was concerned about the linear characteristic of a0

With this factor in the official formula it is absolutely not linear.

I would love to know what you think about my proposal to modify the current equation to have a curved

If you upload an actual reward formula I can give you my thoughts about it, currently I’m not sure to see what you propose. But as you might have realized I’m not really in favor of a_0, so it is quite unlikely I will be in favor of it, unless you really found a clever way to make sense out of a_0! :wink:

(Also note that your proposal will have to match the fact that with it only Nash equilibrium are k equal-sized pool, which apparently is of critical importance for Cardano devs, and the slightest modification can destroy this property in a model, (and which I’m currently redacting a proof that my model is compliant)).

My other concern was the ‘killing pool’

One of the flaws of this model, that I called “DDoS on a pool”, in the other thread.

Thanks for the reply @_ilap !

As to who will decide where the curve crosses the line and how much it curves that, like any other parameter in the equation, is subject to the CIP process.

The crossover parameter is set to 5m ADA in my example which seems like a resonable place to start but is certainly debatable and different values can be easily tried and compared to clearly see the effect.

The choice of curve function is also debatable.
I think the cube root function provides stronger incentives to pool operators to pledge and thus increases Sybil attack resistance.
It also reduces the unnecessary over rewarding of private pools.
My twitter poll showed a strong preference for this.
That is obviously not a deciding factor but is indicative of what some people in the community think.

I don’t think the Oversaturate Pool attack is a real concern as it is so expensive and would in the end be self harming.
I also don’t think it is relevant to this propoosal since the change I suggest is only to the pledge benefit factor.

It depends on what you choose for the x coordinate, the R, the a0, the nOpt a.k.a k, the pledge i.e s', the whole stake i.e o', or is it a multivariable calculus i.e. more than one variables are used i.e. graphed as f(stake, pledge)? It depends on what you want to interpret

I think @shawnim was refering to a similar function described here and what I was responded to that:

For somebody 5m ADA (i.e. 500K USD) is nothing for others is an unreachable dreams.

Is not really expensive, but you need to understand how reward calculation correlates to the ledger i.e. blockchain, whihc is quite complex, check the Transition diagram I have created to have other SPOs getting their head around that

It is difficult for me to see the image you posted since I am legally blind but I believe it is the same formula as the maxPool function defined in section 11.8 Rewards Distribution Calculation of “A Formal Specification of the Cardano Ledger” and called f(s, σ) in section 5.5.2 of “Design Specification for Delegation and Incentives in Cardano”.

maxPool = (R / (1 + a0)) * (o + (s * a0 * ((o - (s * ((z0 - o) / z0))) / z0)))

R = ((reserve * rho) + fees) * (1 - tau)
z0 = 1 / k
s = pledge / total_stake

Note that “s” seems to be called “p” in the first specification above and “s” in the second.

There are 2 variations of my proposal (Alt2 and Alt3).
In both cases the maxPool function is unchanged but I change the meaning of “s”.

Alt2 substitutes the square root of pledge times the square root of crossover for pledge in the original definition.

s = (sqrt(pledge) * sqrt(crossover)) / total_stake

Alt3 substitutes the cube root of pledge times the square of the cube root of crossover.

s = (pow(pledge, 1/3) * pow(crossover, 2/3)) / total_stake

The new definitions of “s” introduce a new parameter called “crossover” which is the amount of pledge where the pledge benefit is the same for the curve as the original line.
So in Alt2 when
pledge = crossover
(sqrt(pledge) * sqrt(crossover)) / total_stake = pledge / total_stake
and similarly for Alt3
(pow(pledge, 1/3) * pow(crossover, 2/3)) / total_stake = pledge / total_stake

I hope that is a clear explanation of my reward equation proposals. I am a developer, not a mathematician, and do not have tools or skills to create fancy math equations with greek letters.
Please let me know if I have misinterpreted the formula or misunderstood the meaning of any of the parameters.

Thanks for taking a look!

The linear relationship that I was refering to in the current equation is that of the added rewards due to pledge versus pledge.

Sorry, was working and yep assumed.

It was clear anyway, I just reflected to him that you was referring to a linear function like that I showed and not any non-linear one.

Also, you only need one and not alt2 alt3, as they just alternate version of your pow function when the exponent is the following: (sqrt(pledge) * sqrt(crossover)) / total_stake = (pow(pledge, exp) * pow(crossover, 1-exp))/ total stake, when pledge=crossover and if the exponent is R={0…1}.
And the alt2 is when the exponent is 0 at the one side.

So, I was referring, who decides the exponent (the shape of the curve and what is he crossover)?
It’s not easy. Though, my solution was different as I wanted to change the curve of the 1/(s+sa0).

I meant, you can generalise it:

sqrt(pledge) * sqrt(crossover) 
= pow(pledge, 1/2) * pow(crossover, 1/2)
= pow(pledge, exp) * pow(crossover, 1-exp)

where exp=0.5 int the above example (i.e. Alt2) and exp R={0..1}
or exp=1/3 (Alt3), or any numbers from 0..1.

1 Like

(sqrt(pledge) * sqrt(crossover)) / total_stake = pledge / total_stake
(pow(pledge, 1/3) * pow(crossover, 2/3)) / total_stake = pledge / total_stake

This does not strongly incentivize pool operators to put some pledge (such as 50k or 200k ADA) when the benefit is so small compared to 0 pledge.

Thank’s for clarifying.

Ok I think I got what you want to do, and in some aspects it is similar to what I wanted to do initially (so you might want to check out what I am currently proposing).

I think you missed something important:

In the model with a0 if you do not have a competitive pledge you will loose your delegates because you have a bad RoS, and then if your pool is not anywhere close to saturation the benefit of having some pledge is virtually null, in the original model and in yours (because of the factor ((o - (s * ((z0 - o) / z0))) / z0 ). So much likely if you only have 10k 50k, 100k or 200k ADA, then your pool will end up being nowhere near saturation, so your pledge will almost not give you any benefit at all in the first place, whether in your scheme or in the official one, and it is useless to calculate what the benefit for the pledge would be if it was saturated which it will never be.

Now how high a competitive pledge is will not change in your model. Because the k pools that have the largest pledge also higher (sqrt(pledge) * sqrt(crossover)) / total_stake , and then higher RoS. So the competitive pledge will still be approximately the minimum on so that their are only k pools who have a pledge that high. They will attract delegates, then the other won’t be able to become close to saturation and will almost not have any positive effect for their pledge. In short this is a competition of who has the largest pledge. Whether this competition is done in linear space or in square root space does not change the winners.

Also how significant the difference in RoS will be between close-to-saturated pools depends a lot more on the chosen value for a_0 than whether or not we replace s like you said.

So my conclusion on this, in that in my mind we should not add complexity to complexity, I don’t think this proposal solves any of the problems of the reward scheme and formula with a_0 that I think is wrong in the first place.

In the scheme I propose the “benefit” of pledging more is obvious whatever the amount is, and equal whatever the size of the pool is (except of course if is already over-saturated, and has stake above 1/k) .