Bugfix/correct staking supply accounting (#1706)

* Added staking_supply_scale_factor field on RewardingParams

* Scaling the amount of tokens released to the circulating/staking supplies
This commit is contained in:
Jędrzej Stuczyński
2022-10-27 10:51:09 +01:00
committed by GitHub
parent d36e349cc6
commit 306e9b9dc2
7 changed files with 29 additions and 2 deletions
@@ -47,6 +47,14 @@ impl Percent {
self.0 == Decimal::zero()
}
pub fn zero() -> Self {
Self(Decimal::zero())
}
pub fn hundred() -> Self {
Self(Decimal::one())
}
pub fn from_percentage_value(value: u64) -> Result<Self, ContractsCommonError> {
Percent::new(Decimal::percent(value))
}
@@ -31,6 +31,7 @@ pub struct InitialRewardingParams {
pub initial_reward_pool: Decimal,
pub initial_staking_supply: Decimal,
pub staking_supply_scale_factor: Percent,
pub sybil_resistance: Percent,
pub active_set_work_factor: Decimal,
pub interval_pool_emission: Percent,
@@ -51,6 +52,7 @@ impl InitialRewardingParams {
interval: IntervalRewardParams {
reward_pool: self.initial_reward_pool,
staking_supply: self.initial_staking_supply,
staking_supply_scale_factor: self.staking_supply_scale_factor,
epoch_reward_budget,
stake_saturation_point,
sybil_resistance: self.sybil_resistance,
@@ -26,6 +26,11 @@ pub struct IntervalRewardParams {
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
pub staking_supply: Decimal,
/// Defines the percentage of stake needed to reach saturation for all of the nodes in the rewarded set.
/// Also known as `beta`.
#[cfg_attr(feature = "generate-ts", ts(type = "string"))]
pub staking_supply_scale_factor: Percent,
// computed values
/// Current value of the computed reward budget per epoch, per node.
/// It is expected to be constant throughout the interval.
@@ -40,7 +40,12 @@ impl Simulator {
if self.interval.current_interval_id() + 1 == updated.current_interval_id() {
let old = self.system_rewarding_params.interval;
let reward_pool = old.reward_pool - self.pending_reward_pool_emission;
let staking_supply = old.staking_supply + self.pending_reward_pool_emission;
let staking_supply = old.staking_supply
+ self
.system_rewarding_params
.interval
.staking_supply_scale_factor
* self.pending_reward_pool_emission;
let epoch_reward_budget = reward_pool
/ Decimal::from_atomics(self.interval.epochs_in_interval(), 0).unwrap()
* old.interval_pool_emission.value();
@@ -51,6 +56,7 @@ impl Simulator {
interval: IntervalRewardParams {
reward_pool,
staking_supply,
staking_supply_scale_factor: old.staking_supply_scale_factor,
epoch_reward_budget,
stake_saturation_point,
sybil_resistance: old.sybil_resistance,
@@ -209,6 +215,7 @@ mod tests {
interval: IntervalRewardParams {
reward_pool: Decimal::from_atomics(reward_pool, 0).unwrap(), // 250M * 1M (we're expressing it all in base tokens)
staking_supply: Decimal::from_atomics(staking_supply, 0).unwrap(), // 100M * 1M
staking_supply_scale_factor: Percent::hundred(),
epoch_reward_budget,
stake_saturation_point,
sybil_resistance: Percent::from_percentage_value(30).unwrap(),
@@ -537,6 +544,7 @@ mod tests {
interval: IntervalRewardParams {
reward_pool: Decimal::from_atomics(reward_pool, 0).unwrap(),
staking_supply: Decimal::from_atomics(staking_supply, 0).unwrap(),
staking_supply_scale_factor: Percent::hundred(),
epoch_reward_budget,
stake_saturation_point,
sybil_resistance: Percent::from_percentage_value(30).unwrap(),
+2
View File
@@ -497,6 +497,7 @@ mod tests {
initial_rewarding_params: InitialRewardingParams {
initial_reward_pool: Decimal::from_atomics(100_000_000_000_000u128, 0).unwrap(),
initial_staking_supply: Decimal::from_atomics(123_456_000_000_000u128, 0).unwrap(),
staking_supply_scale_factor: Percent::hundred(),
sybil_resistance: Percent::from_percentage_value(23).unwrap(),
active_set_work_factor: Decimal::from_atomics(10u32, 0).unwrap(),
interval_pool_emission: Percent::from_percentage_value(1).unwrap(),
@@ -535,6 +536,7 @@ mod tests {
interval: IntervalRewardParams {
reward_pool: Decimal::from_atomics(100_000_000_000_000u128, 0).unwrap(),
staking_supply: Decimal::from_atomics(123_456_000_000_000u128, 0).unwrap(),
staking_supply_scale_factor: Percent::hundred(),
epoch_reward_budget: expected_epoch_reward_budget,
stake_saturation_point: expected_stake_saturation_point,
sybil_resistance: Percent::from_percentage_value(23).unwrap(),
+2 -1
View File
@@ -20,7 +20,8 @@ pub(crate) fn apply_reward_pool_changes(
let reward_pool = rewarding_params.interval.reward_pool - pending_pool_change.removed
+ pending_pool_change.added;
let staking_supply = rewarding_params.interval.staking_supply + pending_pool_change.removed;
let staking_supply = rewarding_params.interval.staking_supply
+ rewarding_params.interval.staking_supply_scale_factor * pending_pool_change.removed;
let epoch_reward_budget = reward_pool
/ Decimal::from_atomics(interval.epochs_in_interval(), 0).unwrap()
* rewarding_params.interval.interval_pool_emission;
@@ -768,6 +768,7 @@ pub mod test_helpers {
InitialRewardingParams {
initial_reward_pool: Decimal::from_atomics(reward_pool, 0).unwrap(), // 250M * 1M (we're expressing it all in base tokens)
initial_staking_supply: Decimal::from_atomics(staking_supply, 0).unwrap(), // 100M * 1M
staking_supply_scale_factor: Percent::hundred(),
sybil_resistance: Percent::from_percentage_value(30).unwrap(),
active_set_work_factor: Decimal::from_atomics(10u32, 0).unwrap(),
interval_pool_emission: Percent::from_percentage_value(2).unwrap(),