From 2f0fc6ac154b893bf703ce22cc3ff8c1f3d0678b Mon Sep 17 00:00:00 2001 From: Jason Zhu Date: Thu, 7 May 2026 13:56:17 -0700 Subject: [PATCH] chore(nervous-system): Remove is_mission_70_voting_rewards_enabled flag Phase 1 (voting rewards / dissolve-delay bounds / 8YG bonus) landed on mainnet via #9923, so the gating flag has served its purpose. Inline the enabled branch at every call site, drop the flag definition and the Temporary helpers, and simplify the tests that previously exercised both branches. Co-Authored-By: Claude Opus 4.7 (1M context) --- rs/nns/governance/src/governance.rs | 35 +-- rs/nns/governance/src/governance/tests/mod.rs | 2 - rs/nns/governance/src/lib.rs | 23 -- rs/nns/governance/src/neuron/types.rs | 9 +- rs/nns/governance/src/neuron/types/tests.rs | 26 --- rs/nns/governance/src/neuron/voting_power.rs | 11 +- .../src/neuron/voting_power_tests.rs | 56 +---- .../src/neuron_store/metrics/tests.rs | 49 +---- .../src/neuron_store/voting_power.rs | 10 +- rs/nns/governance/src/reward/calculation.rs | 199 +++++------------- rs/nns/governance/src/voting.rs | 31 +-- rs/nns/governance/tests/governance.rs | 22 +- 12 files changed, 88 insertions(+), 385 deletions(-) diff --git a/rs/nns/governance/src/governance.rs b/rs/nns/governance/src/governance.rs index d3f3a87086c0..bc70e47732e7 100644 --- a/rs/nns/governance/src/governance.rs +++ b/rs/nns/governance/src/governance.rs @@ -14,8 +14,7 @@ use crate::{ HeapGovernanceData, XdrConversionRate, initialize_governance, reassemble_governance_proto, split_governance_proto, }, - is_comprehensive_neuron_list_enabled, is_mission_70_voting_rewards_enabled, - is_neuron_follow_restrictions_enabled, + is_comprehensive_neuron_list_enabled, is_neuron_follow_restrictions_enabled, neuron::{DissolveStateAndAge, Neuron, NeuronBuilder, Visibility}, neuron_data_validation::{NeuronDataValidationSummary, NeuronDataValidator}, neuron_store::{ @@ -305,15 +304,9 @@ pub const RELAXED_EIGHT_YEAR_GANG_MIN_DISSOLVE_DELAY_SECONDS: u64 = // its ICP must not be newly staked. This defines "sufficiently old staked ICP". pub const RELAXED_EIGHT_YEAR_GANG_MAX_AGING_SINCE_TIMESTAMP_SECONDS: u64 = 1_774_828_800; -/// Returns the maximum dissolve delay allowed for a neuron. After the flag is enabled, we can -/// replace `max_dissolve_delay_seconds()` with `MAX_DISSOLVE_DELAY_SECONDS` and set -/// `MAX_DISSOLVE_DELAY_SECONDS` to `MAX_DISSOLVE_DELAY_SECONDS_POST_MISSION_70`. +/// Returns the maximum dissolve delay allowed for a neuron. pub fn max_dissolve_delay_seconds() -> u64 { - if is_mission_70_voting_rewards_enabled() { - MAX_DISSOLVE_DELAY_SECONDS_POST_MISSION_70 - } else { - MAX_DISSOLVE_DELAY_SECONDS_PRE_MISSION_70 - } + MAX_DISSOLVE_DELAY_SECONDS_POST_MISSION_70 } impl GovernanceError { @@ -1368,11 +1361,10 @@ impl Governance { // Clamp all neuron dissolve delays to the Mission 70 maximum exactly once. // The snapshot serves as the idempotency guard: if it's already populated, // clamping has already run and we must not overwrite the pre-clamp record. - if is_mission_70_voting_rewards_enabled() - && governance - .heap_data - .neuron_id_to_pre_clamp_dissolve_state - .is_empty() + if governance + .heap_data + .neuron_id_to_pre_clamp_dissolve_state + .is_empty() { let now = governance.env.now(); governance.heap_data.neuron_id_to_pre_clamp_dissolve_state = governance @@ -4818,14 +4810,11 @@ impl Governance { } pub fn neuron_minimum_dissolve_delay_to_vote_seconds(&self) -> u64 { - let default = if is_mission_70_voting_rewards_enabled() { - VotingPowerEconomics::MISSION_70_DEFAULT_NEURON_MINIMUM_DISSOLVE_DELAY_TO_VOTE_SECONDS - } else { - VotingPowerEconomics::DEFAULT_NEURON_MINIMUM_DISSOLVE_DELAY_TO_VOTE_SECONDS - }; self.voting_power_economics() .neuron_minimum_dissolve_delay_to_vote_seconds - .unwrap_or(default) + .unwrap_or( + VotingPowerEconomics::MISSION_70_DEFAULT_NEURON_MINIMUM_DISSOLVE_DELAY_TO_VOTE_SECONDS, + ) } /// Reduces `neuron_minimum_dissolve_delay_to_vote_seconds` to 2 weeks if it is currently @@ -4834,10 +4823,6 @@ impl Governance { fn maybe_reduce_neuron_minimum_dissolve_delay_to_vote_seconds( heap_data: &mut HeapGovernanceData, ) { - if !is_mission_70_voting_rewards_enabled() { - return; - } - let Some(voting_power_economics) = heap_data .economics .as_mut() diff --git a/rs/nns/governance/src/governance/tests/mod.rs b/rs/nns/governance/src/governance/tests/mod.rs index b0f678c563f8..4b96b8448f81 100644 --- a/rs/nns/governance/src/governance/tests/mod.rs +++ b/rs/nns/governance/src/governance/tests/mod.rs @@ -1896,7 +1896,6 @@ fn test_maybe_set_relaxed_eight_year_gang_bonus_base() { #[test] fn test_post_upgrade_migrates_neuron_minimum_dissolve_delay_to_vote_seconds() { - let _mission70 = crate::temporarily_enable_mission_70_voting_rewards(); // Simulate the old production state: 6 months. let mut heap_data = HeapGovernanceData { economics: Some(NetworkEconomics { @@ -1930,7 +1929,6 @@ fn test_post_upgrade_migrates_neuron_minimum_dissolve_delay_to_vote_seconds() { #[test] #[should_panic(expected = "unexpectedly below 2 weeks")] fn test_post_upgrade_panics_if_neuron_minimum_dissolve_delay_to_vote_seconds_below_two_weeks() { - let _mission70 = crate::temporarily_enable_mission_70_voting_rewards(); let one_week_seconds = 7 * ONE_DAY_SECONDS; let mut heap_data = HeapGovernanceData { diff --git a/rs/nns/governance/src/lib.rs b/rs/nns/governance/src/lib.rs index 2aef49af163d..b98c7edc68c7 100644 --- a/rs/nns/governance/src/lib.rs +++ b/rs/nns/governance/src/lib.rs @@ -215,15 +215,6 @@ thread_local! { static ENABLE_SUBNET_SPLITTING_PROPOSALS: Cell = const { Cell::new(false) }; - - // The planned effects of enabling this flag include - // 1. Reduce max dissolve delay from 8 years to 2 years. This includes capping existing neurons via data migration. - // 2. Reduce voting rewards pool by approximately 36.71% (equivalently, scale by 0.6329 times). - // 3. Dissolve delay bonus: quadratic instead of linear, with a maximum of 3x instead of 2x. - // 4. Reduce the minimum dissolve delay needed to vote to 2 weeks instead of 6 months. - // 5. 8 year gang 10% bonus. - static ENABLE_MISSION_70_VOTING_REWARDS: Cell - = const { Cell::new(true) }; } thread_local! { @@ -308,20 +299,6 @@ pub fn are_subnet_splitting_proposals_enabled() -> bool { ENABLE_SUBNET_SPLITTING_PROPOSALS.get() } -pub fn is_mission_70_voting_rewards_enabled() -> bool { - ENABLE_MISSION_70_VOTING_REWARDS.get() -} - -#[cfg(any(test, feature = "canbench-rs", feature = "test"))] -pub fn temporarily_enable_mission_70_voting_rewards() -> Temporary { - Temporary::new(&ENABLE_MISSION_70_VOTING_REWARDS, true) -} - -#[cfg(any(test, feature = "canbench-rs", feature = "test"))] -pub fn temporarily_disable_mission_70_voting_rewards() -> Temporary { - Temporary::new(&ENABLE_MISSION_70_VOTING_REWARDS, false) -} - pub fn decoder_config() -> DecoderConfig { let mut config = DecoderConfig::new(); config.set_skipping_quota(DEFAULT_SKIPPING_QUOTA); diff --git a/rs/nns/governance/src/neuron/types.rs b/rs/nns/governance/src/neuron/types.rs index 2568d5118124..7d4ace8a9e82 100644 --- a/rs/nns/governance/src/neuron/types.rs +++ b/rs/nns/governance/src/neuron/types.rs @@ -1,7 +1,6 @@ use crate::{ DEFAULT_VOTING_POWER_REFRESHED_TIMESTAMP_SECONDS, governance::{LOG_PREFIX, MAX_NUM_HOT_KEYS_PER_NEURON, max_dissolve_delay_seconds}, - is_mission_70_voting_rewards_enabled, neuron::{ age_bonus_multiplier, combine_aged_stakes, dissolve_delay_bonus_multiplier, dissolve_state_and_age::DissolveStateAndAge, neuron_stake_e8s, @@ -380,11 +379,9 @@ impl Neuron { // 8 Year Gang bonus. Cap the bonus base to the current stake because // rejection fees can cause the bonus base to exceed stake_e8s. - if is_mission_70_voting_rewards_enabled() { - let eight_year_gang_bonus_base_e8s = self.eight_year_gang_bonus_base_e8s.min(stake_e8s); - potential_voting_power += - Decimal::from(eight_year_gang_bonus_base_e8s) / Decimal::from(10) * boost; - } + let eight_year_gang_bonus_base_e8s = self.eight_year_gang_bonus_base_e8s.min(stake_e8s); + potential_voting_power += + Decimal::from(eight_year_gang_bonus_base_e8s) / Decimal::from(10) * boost; // For DECIDING voting power. let adjustment_factor: Decimal = { diff --git a/rs/nns/governance/src/neuron/types/tests.rs b/rs/nns/governance/src/neuron/types/tests.rs index 223e7ea8713c..a46ac46f18af 100644 --- a/rs/nns/governance/src/neuron/types/tests.rs +++ b/rs/nns/governance/src/neuron/types/tests.rs @@ -6,7 +6,6 @@ use crate::{ self as pb, VotingPowerEconomics, manage_neuron::{Configure, SetDissolveTimestamp, StartDissolving, configure::Operation}, }, - temporarily_disable_mission_70_voting_rewards, temporarily_enable_mission_70_voting_rewards, }; use ic_cdk::println; use ic_nervous_system_common::{E8, ONE_MONTH_SECONDS, ONE_YEAR_SECONDS}; @@ -935,8 +934,6 @@ fn test_eight_year_gang_bonus_base_e8s_is_lost_after_dissolving() { #[test] fn test_eight_year_gang_bonus_is_capped_to_stake_e8s() { - let _restore_on_drop = temporarily_enable_mission_70_voting_rewards(); - let now = 123_456_789; // 100 ICP stake, 100 ICP bonus base, 50 ICP in fees from rejected proposals. @@ -958,26 +955,3 @@ fn test_eight_year_gang_bonus_is_capped_to_stake_e8s() { assert_eq!(neuron.potential_voting_power(now), 55 * E8); } - -#[test] -fn test_eight_year_gang_bonus_not_applied_when_mission_70_disabled() { - let _restore_on_drop = temporarily_disable_mission_70_voting_rewards(); - - let now = 123_456_789; - - // 100 ICP stake with a tagged 8y-gang bonus base, but mission 70 is disabled - // so the bonus must not be applied. With 0 dissolve delay and 0 age, both - // multipliers are 1.0, so potential_voting_power = 100 * 1 * 1 = 100 ICP. - let neuron = NeuronBuilder::new_for_test( - 1, - DissolveStateAndAge::NotDissolving { - dissolve_delay_seconds: 0, - aging_since_timestamp_seconds: now, - }, - ) - .with_cached_neuron_stake_e8s(100 * E8) - .with_eight_year_gang_bonus_base_e8s(100 * E8) - .build(); - - assert_eq!(neuron.potential_voting_power(now), 100 * E8); -} diff --git a/rs/nns/governance/src/neuron/voting_power.rs b/rs/nns/governance/src/neuron/voting_power.rs index e407367099f3..bbdcb8610e4d 100644 --- a/rs/nns/governance/src/neuron/voting_power.rs +++ b/rs/nns/governance/src/neuron/voting_power.rs @@ -1,7 +1,4 @@ -use crate::{ - governance::{MAX_NEURON_AGE_FOR_AGE_BONUS, max_dissolve_delay_seconds}, - is_mission_70_voting_rewards_enabled, -}; +use crate::governance::{MAX_NEURON_AGE_FOR_AGE_BONUS, max_dissolve_delay_seconds}; use rust_decimal::Decimal; /// Currently, only used by an integration test. @@ -13,11 +10,7 @@ pub fn dissolve_delay_bonus_multiplier(dissolve_delay_seconds: u64) -> Decimal { // t is (clamped) dissolve delay in units of max dissolve delay, so 0.0 <= t <= 1.0. let t = Decimal::from(dissolve_delay_seconds) / Decimal::from(max_dissolve_delay_seconds); - (if is_mission_70_voting_rewards_enabled() { - Decimal::from(2) * t * t - } else { - t - }) + Decimal::from(1) + Decimal::from(2) * t * t + Decimal::from(1) } pub(crate) fn age_bonus_multiplier(age_seconds: u64) -> Decimal { diff --git a/rs/nns/governance/src/neuron/voting_power_tests.rs b/rs/nns/governance/src/neuron/voting_power_tests.rs index 565d3f2d0ce4..a97335241e05 100644 --- a/rs/nns/governance/src/neuron/voting_power_tests.rs +++ b/rs/nns/governance/src/neuron/voting_power_tests.rs @@ -1,62 +1,8 @@ use super::*; -use crate::{ - temporarily_disable_mission_70_voting_rewards, temporarily_enable_mission_70_voting_rewards, -}; use ic_nervous_system_common::{ONE_MONTH_SECONDS, ONE_YEAR_SECONDS}; #[test] -fn test_dissolve_delay_bonus_multiplier_pre_mission_70() { - let _restore_on_drop = temporarily_disable_mission_70_voting_rewards(); - - // Test the endpoints. - assert_eq!(dissolve_delay_bonus_multiplier(0), Decimal::from(1)); - assert_eq!( - dissolve_delay_bonus_multiplier(8 * ONE_YEAR_SECONDS), - Decimal::from(2) - ); - - // Test intermediate points. - assert_eq!( - dissolve_delay_bonus_multiplier(ONE_YEAR_SECONDS), - Decimal::from(1) + Decimal::from(1) / Decimal::from(8) - ); - assert_eq!( - dissolve_delay_bonus_multiplier(2 * ONE_YEAR_SECONDS), - Decimal::from(1) + Decimal::from(2) / Decimal::from(8) - ); - assert_eq!( - dissolve_delay_bonus_multiplier(3 * ONE_YEAR_SECONDS), - Decimal::from(1) + Decimal::from(3) / Decimal::from(8) - ); - assert_eq!( - dissolve_delay_bonus_multiplier(4 * ONE_YEAR_SECONDS), - Decimal::from(1) + Decimal::from(4) / Decimal::from(8) - ); - assert_eq!( - dissolve_delay_bonus_multiplier(5 * ONE_YEAR_SECONDS), - Decimal::from(1) + Decimal::from(5) / Decimal::from(8) - ); - assert_eq!( - dissolve_delay_bonus_multiplier(6 * ONE_YEAR_SECONDS), - Decimal::from(1) + Decimal::from(6) / Decimal::from(8) - ); - assert_eq!( - dissolve_delay_bonus_multiplier(7 * ONE_YEAR_SECONDS), - Decimal::from(1) + Decimal::from(7) / Decimal::from(8) - ); - - // Test beyond max dissolve delay. (No neuron should have this, but we can - // and do defend against it by clamping.) - assert_eq!( - dissolve_delay_bonus_multiplier(15 * ONE_YEAR_SECONDS), - Decimal::from(2) - ); -} - -#[test] -fn test_dissolve_delay_bonus_multiplier_while_mission_70_is_engaged() { - let _restore_on_drop = temporarily_enable_mission_70_voting_rewards(); - +fn test_dissolve_delay_bonus_multiplier() { // Test the endpoints. assert_eq!(dissolve_delay_bonus_multiplier(0), Decimal::from(1)); assert_eq!( diff --git a/rs/nns/governance/src/neuron_store/metrics/tests.rs b/rs/nns/governance/src/neuron_store/metrics/tests.rs index bb5df00e264f..f163a3fe581d 100644 --- a/rs/nns/governance/src/neuron_store/metrics/tests.rs +++ b/rs/nns/governance/src/neuron_store/metrics/tests.rs @@ -1,7 +1,6 @@ use super::*; use crate::{ governance::max_dissolve_delay_seconds, - is_mission_70_voting_rewards_enabled, neuron::{DissolveStateAndAge, NeuronBuilder, dissolve_delay_bonus_multiplier}, pb::v1::{KnownNeuronData, MaturityDisbursement, NeuronType}, }; @@ -536,20 +535,10 @@ fn test_compute_neuron_metrics_non_self_authenticating() { // Step 3: Inspect results. // - // bucket_for_half_max: neuron_3 has a dissolve delay equal to max_dissolve_delay_seconds() / 2 - // (mapped to bucket 8 when the max is long, 2 when the max is short). - let bucket_for_half_max = if is_mission_70_voting_rewards_enabled() { - 2 - } else { - 8 - }; - // bucket_for_max: neuron_1 has a dissolve delay equal to max_dissolve_delay_seconds() - // (mapped to bucket 16 when the max is long, 4 when the max is short). - let bucket_for_max = if is_mission_70_voting_rewards_enabled() { - 4 - } else { - 16 - }; + // bucket_for_half_max: neuron_3 has a dissolve delay equal to max_dissolve_delay_seconds() / 2. + let bucket_for_half_max = 2; + // bucket_for_max: neuron_1 has a dissolve delay equal to max_dissolve_delay_seconds(). + let bucket_for_max = 4; assert_eq!( non_self_authenticating_controller_neuron_subset_metrics, @@ -720,20 +709,10 @@ fn test_compute_neuron_metrics_public_neurons() { // Step 3: Inspect results. // - // bucket_for_half_max: neuron_3 has a dissolve delay equal to max_dissolve_delay_seconds() / 2 - // (mapped to bucket 8 when the max is long, 2 when the max is short). - let bucket_for_half_max = if is_mission_70_voting_rewards_enabled() { - 2 - } else { - 8 - }; - // bucket_for_max: neuron_1 has a dissolve delay equal to max_dissolve_delay_seconds() - // (mapped to bucket 16 when the max is long, 4 when the max is short). - let bucket_for_max = if is_mission_70_voting_rewards_enabled() { - 4 - } else { - 16 - }; + // bucket_for_half_max: neuron_3 has a dissolve delay equal to max_dissolve_delay_seconds() / 2. + let bucket_for_half_max = 2; + // bucket_for_max: neuron_1 has a dissolve delay equal to max_dissolve_delay_seconds(). + let bucket_for_max = 4; assert_eq!( public_neuron_subset_metrics, @@ -895,15 +874,9 @@ fn test_compute_neuron_metrics_stale_and_expired_voting_power_neurons() { // Step 3: Inspect results. // - // All neurons are created with the maximum dissolve delay, and we bucket by - // that effective maximum: - // - Pre-mission-70: max dissolve delay is 8 years -> bucket 16 - // - Post-mission-70: max dissolve delay is clamped to 2 years -> bucket 4 - let bucket_for_max = if is_mission_70_voting_rewards_enabled() { - 4 - } else { - 16 - }; + // All neurons are created with the maximum dissolve delay (2 years), which + // maps to bucket 4. + let bucket_for_max = 4; assert_eq!( declining_voting_power_neuron_subset_metrics, diff --git a/rs/nns/governance/src/neuron_store/voting_power.rs b/rs/nns/governance/src/neuron_store/voting_power.rs index e4d7e6686fb2..e00d4d4184ad 100644 --- a/rs/nns/governance/src/neuron_store/voting_power.rs +++ b/rs/nns/governance/src/neuron_store/voting_power.rs @@ -3,7 +3,6 @@ use ic_nns_governance_api::Vote; use super::{NeuronStore, NeuronStoreError}; use crate::{ - is_mission_70_voting_rewards_enabled, neuron::Neuron, pb::v1::{Ballot, NeuronIdToVotingPowerMap, VotingPowerEconomics, VotingPowerTotal}, storage::neurons::NeuronSections, @@ -132,14 +131,11 @@ impl NeuronStore { let mut total_deciding_voting_power: u128 = 0; let mut total_potential_voting_power: u128 = 0; - let default_min_dissolve_delay = if is_mission_70_voting_rewards_enabled() { - VotingPowerEconomics::MISSION_70_DEFAULT_NEURON_MINIMUM_DISSOLVE_DELAY_TO_VOTE_SECONDS - } else { - VotingPowerEconomics::DEFAULT_NEURON_MINIMUM_DISSOLVE_DELAY_TO_VOTE_SECONDS - }; let min_dissolve_delay_seconds = voting_power_economics .neuron_minimum_dissolve_delay_to_vote_seconds - .unwrap_or(default_min_dissolve_delay); + .unwrap_or( + VotingPowerEconomics::MISSION_70_DEFAULT_NEURON_MINIMUM_DISSOLVE_DELAY_TO_VOTE_SECONDS, + ); let mut process_neuron = |neuron: &Neuron| { if neuron.is_inactive(now_seconds) diff --git a/rs/nns/governance/src/reward/calculation.rs b/rs/nns/governance/src/reward/calculation.rs index b71114eb542e..771bcad23d19 100644 --- a/rs/nns/governance/src/reward/calculation.rs +++ b/rs/nns/governance/src/reward/calculation.rs @@ -14,7 +14,7 @@ //! * Floating point makes code easier since the reward pool is specified as a //! fraction of the total ICP supply. -use crate::{is_mission_70_voting_rewards_enabled, pb::v1::RewardEvent}; +use crate::pb::v1::RewardEvent; use std::ops::{Add, Div, Mul, Sub}; // ---- NON-BOILERPLATE CODE STARTS HERE ---------------------------------- @@ -72,7 +72,7 @@ const REWARD_FLATTENING_DATE: IcTimestamp = IcTimestamp { }; // See https://x.com/dominic_w/status/2011156143796781481 . -const MISSION_70_VOTING_REWARDS_ADJUSTMENT_FACTOR: f64 = 0.6329; +const VOTING_REWARDS_ADJUSTMENT_FACTOR: f64 = 0.6329; /// Computes the reward to distribute, as a fraction of the ICP supply, for one /// day. @@ -97,15 +97,7 @@ pub fn rewards_pool_to_distribute_in_supply_fraction_for_one_day( let rate = FINAL_VOTING_REWARD_RELATIVE_RATE + variable_rate; - voting_rewards_adjustment_factor() * rate * ONE_DAY -} - -fn voting_rewards_adjustment_factor() -> f64 { - if is_mission_70_voting_rewards_enabled() { - MISSION_70_VOTING_REWARDS_ADJUSTMENT_FACTOR - } else { - 1.0 - } + VOTING_REWARDS_ADJUSTMENT_FACTOR * rate * ONE_DAY } impl RewardEvent { @@ -268,146 +260,61 @@ mod test { }}; } - mod mission_70_disabled { - use super::*; - use crate::temporarily_disable_mission_70_voting_rewards; - - #[test] - fn days_fully_after_flattening_produce_linear_reward() { - let _restore_on_drop = temporarily_disable_mission_70_voting_rewards(); - - assert_approx_eq!( - rewards_pool_to_distribute_in_supply_fraction_for_one_day(8 * 366), - 0.05 / 365.25 - ); - assert_approx_eq!( - rewards_pool_to_distribute_in_supply_fraction_for_one_day(8 * 366 + 5), - 0.05 / 365.25 - ); - assert_approx_eq!( - rewards_pool_to_distribute_in_supply_fraction_for_one_day(123456), - 0.05 / 365.25 - ); - } - - #[test] - fn reward_for_first_day() { - let _restore_on_drop = temporarily_disable_mission_70_voting_rewards(); - - assert_approx_eq!( - rewards_pool_to_distribute_in_supply_fraction_for_one_day(0), - 0.10 / 365.25 - ); - } - - #[test] - fn reward_for_entire_pre_flattening_interval_can_be_lower_and_upper_bounded() { - let _restore_on_drop = temporarily_disable_mission_70_voting_rewards(); - - let lower_bound = - (REWARD_FLATTENING_DATE - GENESIS) * FINAL_VOTING_REWARD_RELATIVE_RATE; - let upper_bound = - (REWARD_FLATTENING_DATE - GENESIS) * INITIAL_VOTING_REWARD_RELATIVE_RATE; - let actual = (0..(REWARD_FLATTENING_DATE.days_since_ic_genesis as u64)) - .map(rewards_pool_to_distribute_in_supply_fraction_for_one_day) - .sum(); - assert!(lower_bound < actual); - assert!(actual < upper_bound); - } - - #[test] - fn reward_is_convex_and_decreasing() { - let _restore_on_drop = temporarily_disable_mission_70_voting_rewards(); - - // Here we verify the convex inequality for all 3 consecutive days during the - // parabolic rate period. - for day in 0..(REWARD_FLATTENING_DATE.days_since_ic_genesis as u64) - 2 { - let a = rewards_pool_to_distribute_in_supply_fraction_for_one_day(day); - let b = rewards_pool_to_distribute_in_supply_fraction_for_one_day(day + 1); - let c = rewards_pool_to_distribute_in_supply_fraction_for_one_day(day + 2); - - let d1 = b - a; - let d2 = c - b; - - // Decreasing. - assert!(d1 < 0.0, "{day}: {a}, {b}, {c} ({d1} vs. {d2}"); - assert!(d2 < 0.0, "{day}: {a}, {b}, {c} ({d1} vs. {d2}"); - - // Convex. That is, the second decrease is not as large as the first. - assert!(d1.abs() > d2.abs(), "{day}: {a}, {b}, {c} ({d1} vs. {d2}"); - } - } - } // mod mission_70_disabled - - mod mission_70_enabled { - use super::*; - use crate::temporarily_enable_mission_70_voting_rewards; - - #[test] - fn days_fully_after_flattening_produce_linear_reward() { - let _restore_on_drop = temporarily_enable_mission_70_voting_rewards(); - - assert_approx_eq!( - rewards_pool_to_distribute_in_supply_fraction_for_one_day(8 * 366), - MISSION_70_VOTING_REWARDS_ADJUSTMENT_FACTOR * 0.05 / 365.25 - ); - assert_approx_eq!( - rewards_pool_to_distribute_in_supply_fraction_for_one_day(8 * 366 + 5), - MISSION_70_VOTING_REWARDS_ADJUSTMENT_FACTOR * 0.05 / 365.25 - ); - assert_approx_eq!( - rewards_pool_to_distribute_in_supply_fraction_for_one_day(123456), - MISSION_70_VOTING_REWARDS_ADJUSTMENT_FACTOR * 0.05 / 365.25 - ); - } - - #[test] - fn reward_for_first_day() { - let _restore_on_drop = temporarily_enable_mission_70_voting_rewards(); - - assert_approx_eq!( - rewards_pool_to_distribute_in_supply_fraction_for_one_day(0), - MISSION_70_VOTING_REWARDS_ADJUSTMENT_FACTOR * 0.10 / 365.25 - ); - } - - #[test] - fn reward_for_entire_pre_flattening_interval_can_be_lower_and_upper_bounded() { - let _restore_on_drop = temporarily_enable_mission_70_voting_rewards(); + #[test] + fn days_fully_after_flattening_produce_linear_reward() { + assert_approx_eq!( + rewards_pool_to_distribute_in_supply_fraction_for_one_day(8 * 366), + VOTING_REWARDS_ADJUSTMENT_FACTOR * 0.05 / 365.25 + ); + assert_approx_eq!( + rewards_pool_to_distribute_in_supply_fraction_for_one_day(8 * 366 + 5), + VOTING_REWARDS_ADJUSTMENT_FACTOR * 0.05 / 365.25 + ); + assert_approx_eq!( + rewards_pool_to_distribute_in_supply_fraction_for_one_day(123456), + VOTING_REWARDS_ADJUSTMENT_FACTOR * 0.05 / 365.25 + ); + } - let lower_bound = MISSION_70_VOTING_REWARDS_ADJUSTMENT_FACTOR - * ((REWARD_FLATTENING_DATE - GENESIS) * FINAL_VOTING_REWARD_RELATIVE_RATE); - let upper_bound = MISSION_70_VOTING_REWARDS_ADJUSTMENT_FACTOR - * ((REWARD_FLATTENING_DATE - GENESIS) * INITIAL_VOTING_REWARD_RELATIVE_RATE); - let actual = (0..(REWARD_FLATTENING_DATE.days_since_ic_genesis as u64)) - .map(rewards_pool_to_distribute_in_supply_fraction_for_one_day) - .sum(); - assert!(lower_bound < actual); - assert!(actual < upper_bound); - } + #[test] + fn reward_for_first_day() { + assert_approx_eq!( + rewards_pool_to_distribute_in_supply_fraction_for_one_day(0), + VOTING_REWARDS_ADJUSTMENT_FACTOR * 0.10 / 365.25 + ); + } - /// This is a copy & paste of the test in the sibling mission_70_disabled module. - #[test] - fn reward_is_convex_and_decreasing() { - let _restore_on_drop = temporarily_enable_mission_70_voting_rewards(); + #[test] + fn reward_for_entire_pre_flattening_interval_can_be_lower_and_upper_bounded() { + let lower_bound = VOTING_REWARDS_ADJUSTMENT_FACTOR + * ((REWARD_FLATTENING_DATE - GENESIS) * FINAL_VOTING_REWARD_RELATIVE_RATE); + let upper_bound = VOTING_REWARDS_ADJUSTMENT_FACTOR + * ((REWARD_FLATTENING_DATE - GENESIS) * INITIAL_VOTING_REWARD_RELATIVE_RATE); + let actual = (0..(REWARD_FLATTENING_DATE.days_since_ic_genesis as u64)) + .map(rewards_pool_to_distribute_in_supply_fraction_for_one_day) + .sum(); + assert!(lower_bound < actual); + assert!(actual < upper_bound); + } - // Here we verify the convex inequality for all 3 consecutive days during the - // parabolic rate period. - for day in 0..(REWARD_FLATTENING_DATE.days_since_ic_genesis as u64) - 2 { - let a = rewards_pool_to_distribute_in_supply_fraction_for_one_day(day); - let b = rewards_pool_to_distribute_in_supply_fraction_for_one_day(day + 1); - let c = rewards_pool_to_distribute_in_supply_fraction_for_one_day(day + 2); + #[test] + fn reward_is_convex_and_decreasing() { + // Here we verify the convex inequality for all 3 consecutive days during the + // parabolic rate period. + for day in 0..(REWARD_FLATTENING_DATE.days_since_ic_genesis as u64) - 2 { + let a = rewards_pool_to_distribute_in_supply_fraction_for_one_day(day); + let b = rewards_pool_to_distribute_in_supply_fraction_for_one_day(day + 1); + let c = rewards_pool_to_distribute_in_supply_fraction_for_one_day(day + 2); - let d1 = b - a; - let d2 = c - b; + let d1 = b - a; + let d2 = c - b; - // Decreasing. - assert!(d1 < 0.0, "{day}: {a}, {b}, {c} ({d1} vs. {d2}"); - assert!(d2 < 0.0, "{day}: {a}, {b}, {c} ({d1} vs. {d2}"); + // Decreasing. + assert!(d1 < 0.0, "{day}: {a}, {b}, {c} ({d1} vs. {d2}"); + assert!(d2 < 0.0, "{day}: {a}, {b}, {c} ({d1} vs. {d2}"); - // Convex. That is, the second decrease is not as large as the first. - assert!(d1.abs() > d2.abs(), "{day}: {a}, {b}, {c} ({d1} vs. {d2}"); - } + // Convex. That is, the second decrease is not as large as the first. + assert!(d1.abs() > d2.abs(), "{day}: {a}, {b}, {c} ({d1} vs. {d2}"); } - } // mod mission_70_enabled + } } diff --git a/rs/nns/governance/src/voting.rs b/rs/nns/governance/src/voting.rs index 99c467cdbbd8..bea0c44a56fc 100644 --- a/rs/nns/governance/src/voting.rs +++ b/rs/nns/governance/src/voting.rs @@ -602,8 +602,6 @@ mod test { VotingPowerEconomics, WaitForQuietState, proposal::Action, }, storage::with_voting_state_machines_mut, - temporarily_disable_mission_70_voting_rewards, - temporarily_enable_mission_70_voting_rewards, test_utils::{ ExpectedCallCanisterMethodCallArguments, MockEnvironment, StubCMC, StubIcpLedger, }, @@ -785,17 +783,6 @@ mod test { /// d. Neuron 7 does not have a ballot for proposal 1. All the other /// neurons do have ballots. #[test] - fn test_cast_vote_and_cascade_works_pre_mission_70() { - let _restore_on_drop = temporarily_disable_mission_70_voting_rewards(); - test_cast_vote_and_cascade_works(); - } - - #[test] - fn test_cast_vote_and_cascade_works_with_mission_70() { - let _restore_on_drop = temporarily_enable_mission_70_voting_rewards(); - test_cast_vote_and_cascade_works(); - } - fn test_cast_vote_and_cascade_works() { // Step 1: Prepare the world. @@ -1455,22 +1442,8 @@ mod test { } #[tokio::test] - async fn test_rewards_distribution_is_blocked_on_votes_not_cast_in_state_machine_pre_mission_70() - { - let _restore_on_drop = temporarily_disable_mission_70_voting_rewards(); - test_rewards_distribution_is_blocked_on_votes_not_cast_in_state_machine(5474).await; - } - - #[tokio::test] - async fn test_rewards_distribution_is_blocked_on_votes_not_cast_in_state_machine_with_mission_70() - { - let _restore_on_drop = temporarily_enable_mission_70_voting_rewards(); - test_rewards_distribution_is_blocked_on_votes_not_cast_in_state_machine(3464).await; - } - - async fn test_rewards_distribution_is_blocked_on_votes_not_cast_in_state_machine( - expected_neuron_1_maturity: u64, - ) { + async fn test_rewards_distribution_is_blocked_on_votes_not_cast_in_state_machine() { + let expected_neuron_1_maturity = 3464; let now = 1733433219; let topic = Topic::Governance; let environment = MockEnvironment::new( diff --git a/rs/nns/governance/tests/governance.rs b/rs/nns/governance/tests/governance.rs index b6b5212a04cd..3eafec2bec73 100644 --- a/rs/nns/governance/tests/governance.rs +++ b/rs/nns/governance/tests/governance.rs @@ -55,7 +55,6 @@ use ic_nns_governance::{ }, }, governance_proto_builder::GovernanceProtoBuilder, - is_mission_70_voting_rewards_enabled, pb::v1::{ AddOrRemoveNodeProvider, Ballot, BallotInfo, CreateServiceNervousSystem, Empty, ExecuteNnsFunction, Followees, GovernanceError, IdealMatchedParticipationFunction, @@ -2752,15 +2751,8 @@ async fn test_reward_event_proposals_last_longer_than_reward_period() { }); let expected_distributed_e8s_equivalent = (expected_available_e8s_equivalent as f64 * neuron_share) as u64; - // The value depends on the dissolve delay bonus: - // - With 2-year max (mission 70): 1 year → 50% bonus → higher voting power ratio → 16 - // - With 8-year max (pre mission 70): 1 year → 12.5% bonus → lower voting power ratio → 15 - let expected_value = if is_mission_70_voting_rewards_enabled() { - 16 - } else { - 15 - }; - assert_eq!(expected_distributed_e8s_equivalent, expected_value); + // 2-year max dissolve delay: 1 year → 50% dissolve delay bonus → expected 16. + assert_eq!(expected_distributed_e8s_equivalent, 16); assert_eq!( *gov.latest_reward_event(), RewardEvent { @@ -9482,15 +9474,7 @@ fn test_deciding_and_potential_voting_power() { neuron.potential_voting_power(START_TIMESTAMP_SECONDS) }) .unwrap(); - assert_eq!( - original_potential_voting_power, - cached_neuron_stake_e8s - * if is_mission_70_voting_rewards_enabled() { - 3 - } else { - 2 - }, - ); + assert_eq!(original_potential_voting_power, cached_neuron_stake_e8s * 3,); // Step 2: Call the code under test. let mut previous_timestamp_seconds = START_TIMESTAMP_SECONDS