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

[FR] - Alternative pledge benefit factors in rewards equation #1518

Closed
shawnim opened this issue Jul 22, 2020 · 6 comments
Closed

[FR] - Alternative pledge benefit factors in rewards equation #1518

shawnim opened this issue Jul 22, 2020 · 6 comments
Labels
enhancement New feature or request

Comments

@shawnim
Copy link

shawnim commented Jul 22, 2020

Internal/Exernal
External

Describe the feature you'd like

A better pledge benefit factor in the reward equation that would increase incentives for pool operators to pledge thus increasing Sybil attack resistance while reducing exorbitant rewards for private and whale pools to a more reasonable amount.

Describe alternatives you've considered

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.

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

Below is the code used to generate the examples above.
Please correct me if I have translated the reward function incorrectly.

<?php

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

echo "Assumptions\n";
echo "Reserve: " . round($reserve / 1000000000, 1) . "b\n";
echo "Total stake: " . round($total_stake / 1000000000, 1) . "b\n";
echo "Tx fees: " . $fees . "\n";
echo "Fully Saturated Pool\n";

$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);
$crossover = 5000000; // The pledge where the curve crosses the line
$pledges = array(0, 10000, 50000, 100000, 200000, 500000, 1000000, 2000000, 5000000, 10000000, 20000000, 50000000, 100000000, $saturation);
$comparison_pledge = 0;
$comparison_s = $comparison_pledge / $total_stake;
$comparison_rewards = round(($R / (1 + $a0)) * ($o + ($comparison_s * $a0 * (($o - ($comparison_s * (($z0 - $o) / $z0))) / $z0))));

echo "Rewards available in epoch: " . round($R / 1000000, 1) . "m\n";
echo "Pool saturation: " . round($saturation / 1000000, 1) . "m\n";
echo "\n";
echo "Pledge\tRewards\tBenefit\tAlt2 Rw\tAlt2 Bn\tAlt3 Rw\tAlt3 Bn\n";

foreach ($pledges as $pledge) {
  if ($pledge < 1000000) {
    $pledge_str = round($pledge / 1000, 1) . "k";
  } else {
    $pledge_str = round($pledge / 1000000, 1) . "m";
  }

  // Current Formula
  $s = $pledge / $total_stake;
  $rewards = round(($R / (1 + $a0)) * ($o + ($s * $a0 * (($o - ($s * (($z0 - $o) / $z0))) / $z0))));
  $benefit = round(((($rewards / $comparison_rewards) - 1) * 100), 2);

  // Alternative 2 Square Root
  $alt2_multiplier = sqrt($crossover);
  $alt2_s = $alt2_multiplier * sqrt($pledge) / $total_stake;
  $alt2_rewards = round(($R / (1 + $a0)) * ($o + ($alt2_s * $a0 * (($o - ($alt2_s * (($z0 - $o) / $z0))) / $z0))));
  $alt2_benefit = round(((($alt2_rewards / $comparison_rewards) - 1) * 100), 2);

  // Alternative 3 Cube Root
  $alt3_multiplier = pow($crossover, (2 / 3));
  $alt3_s = $alt3_multiplier * pow($pledge, (1 / 3)) / $total_stake;
  $alt3_rewards = round(($R / (1 + $a0)) * ($o + ($alt3_s * $a0 * (($o - ($alt3_s * (($z0 - $o) / $z0))) / $z0))));
  $alt3_benefit = round(((($alt3_rewards / $comparison_rewards) - 1) * 100), 2);

  echo $pledge_str . "\t" . $rewards . "\t" . $benefit . "%\t" . $alt2_rewards . "\t" . $alt2_benefit . "%\t" . $alt3_rewards . "\t" . $alt3_benefit . "%\n";
}

echo "\n";

@shawnim shawnim added the enhancement New feature or request label Jul 22, 2020
@shawnim
Copy link
Author

shawnim commented Jul 22, 2020

I'm not sure if this should be a CIP or if there is a process for that yet but thought I would get it into the issue tracker since I have been discussing this on Twitter and the Cardano Forums.

@angelstakepool
Copy link

angelstakepool commented Jul 22, 2020

I have always thought that pledge should be treated differently. Currently there are no real incentives to pledge since the reward difference between 0 pledge and 500k pledge is insignificant, basically a small fraction of a percent.

This opens the way to scammers/bad actors as POs with absolutely no skin in the game, and no interest in sustainability of Cardano protocol; who will create a race to the bottom with negative consequences.

Pledge should be implemented as a non-linear relationship (reward potential vs pledge) in the range 0 to 500k; then linear all the way up to maximum pledge. At the same time I believe that max pledge should not be the saturation point, as it is now, because it simple means that private pools have a enormous advantage as compared to ordinary pools. Maybe an idea would be max pledge = 1/3 of saturation point

we have the a0 factor that can control the pledge importance. Under current implementation, when a0 increases from expected 0.3, the situation becomes even worse in favor of private pools. If a0 is decreased from 0.3, then 0 pledge pools would become even more important players. This shows that a linear relationships does not work. imo the only way that a linear relationship can work is making use of a min pledge (entry point)

@shawnim
Copy link
Author

shawnim commented Jul 23, 2020

Using a curve both below and above the crossover point instead of having a max pledge means there is no hard limit, only incentives which seems to have been a design goal.

@shawnim
Copy link
Author

shawnim commented Jul 23, 2020

From the discussion on the Cardano Forums at
https://forum.cardano.org/t/protocol-parameters-pledge-and-sybil-resistance/35100/21

I realized that I was using the active stake (estimated at 22b) rather than the total stake (estimated at 31b) in the rewards calculation.

Because the a0 pledge benefit is spread over the pledge range from 0 to saturation there is a dependence on k and total_stake.
Since k and total_stake will likely change over time it would be better to express crossover in terms of k and total_stake instead of a fixed number.

One possibility would be

crossover = total_stake / (k * crossover_factor)

where crossover_factor is any real number greater than 0.

Also, we can generalize the alternative approaches to parameterize the curve exponent.
This gives us

s = pow(pledge, (1 / curve_exp)) * pow(crossover, ((curve_exp - 1) / curve_exp)) / total_stake

The curve_exp could be set to any integer greater than 0 and when set to 1 produces the current rewards equation.

@shawnim
Copy link
Author

shawnim commented Aug 13, 2020

Hi all,
I submitted a Cardano Improvement Propopsal (CIP) for this idea.
You can see the pull request at: cardano-foundation/CIPs#12
The pull request contains the CIP and the PHP test code.

The Specification section of the proposal is as follows:

This is a modification of the maxPool function defined in section 11.8 Rewards Distribution Calculation of “A Formal Specification of the Cardano Ledger”.

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

where:
R = ((reserve * rho) + fees) * (1 - tau)
o = min(pool_stake / total_stake, z0) = z0 for fully saturated pool
s = pledge / total_stake
z0 = 1 / k
and the following are current protocol parameters:
k = 150
rho = 0.0022
a0 = 0.3
tau = .05

The idea is to replace s in the above equation with an n-root curve expression of pledge rather than the linear pledge value.

We use an expression called crossover to represent the point where the curve crosses the line and the benefit in the new and original equations is identical.
Because the a0 pledge benefit is spread over the pledge range from 0 to saturation there is a dependence on k and total_stake.
Since k and total_stake will likely change over time it is best to express crossover in terms of k and total_stake as follows:

crossover = total_stake / (k * crossover_factor)

where crossover_factor is any real number greater than or equal to 1.
So crossover_factor is essentially a divisor of the pool saturation amount.
For example, setting crossover_factor to 20 with k = 150 and total_stake = 31 billion gives a crossover of approximately 10.3 million.

Also, we can parameterize the n-root curve exponent.
This gives us:

s = pow(pledge, (1 / curve_root)) * pow(crossover, ((curve_root - 1) / curve_root)) / total_stake

The curve_root could be set to any integer greater than 0 and when set to 1 produces the current rewards equation.
The curve_root is n in n-root. For example, 1 = linear, 2 = square root, 3 = cube root, 4 = fourth root, etc.

By making this modification to the rewards equation we introduce two new protocol parameters, crossover_factor and curve_root, that need to be set thoughtfully.

The Test Cases section is as follows:

See rewards.php for some simple PHP code that allows you to try different values for crossover_factor and curve_root and compare the resulting rewards to the current equation.
For usage, run "php -f rewards.php help".

An interesting set of parameters as an example is:

curve_root = 3
crossover_factor = 8

Running "php -f rewards.php 3 8" produces:

Assumptions
Reserve: 14b
Total stake: 31.7b
Tx fees: 0
Fully Saturated Pool
Rewards available in epoch: 29.3m
Pool saturation: 211.3m

Curve root: 3
Crossover factor: 8
Crossover: 26.4m

Pledge Rewards Benefit Alt Rwd Alt Bnft
0k 150051 0% 150051 0%
10k 150053 0% 150458 0.27%
50k 150062 0.01% 150747 0.46%
100k 150073 0.01% 150928 0.58%
200k 150094 0.03% 151156 0.74%
500k 150158 0.07% 151551 1%
1m 150264 0.14% 151941 1.26%
2m 150477 0.28% 152432 1.59%
5m 151116 0.71% 153282 2.15%
10m 152181 1.42% 154122 2.71%
20m 154311 2.84% 155180 3.42%
50m 160702 7.1% 157012 4.64%
100m 171352 14.2% 158821 5.84%
211.3m 195067 30% 161305 7.5%

As you can see this gives meaningful pledge benefit rewards to pools pledging less than 1m ADA.

@vix-io
Copy link
Contributor

vix-io commented Sep 15, 2020

Filing this as a CIP was the appropriate thing to do - closing this ticket.

@vix-io vix-io closed this as completed Sep 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants