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";