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.

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

<?php

// 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";
3 Likes

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.