diff --git a/rs/nns/governance/src/governance.rs b/rs/nns/governance/src/governance.rs index 286d936b470e..2a258a054758 100644 --- a/rs/nns/governance/src/governance.rs +++ b/rs/nns/governance/src/governance.rs @@ -285,6 +285,12 @@ pub const MAX_NEURONS_FUND_PARTICIPANTS: u64 = 5_000; /// in the same limit. const NEURON_RATE_LIMITER_KEY: &str = "ADD_NEURON"; +/// The minimum dissolve delay (in seconds) a neuron must have to submit a +/// non-ManageNeuron proposal. This is intentionally decoupled from the voting +/// eligibility threshold (`neuron_minimum_dissolve_delay_to_vote_seconds`), +/// which can be lower. +pub const NEURON_MINIMUM_DISSOLVE_DELAY_TO_PROPOSE_SECONDS: u64 = 6 * ONE_MONTH_SECONDS; + // The maximum dissolve delay allowed for a neuron. pub const MAX_DISSOLVE_DELAY_SECONDS_PRE_MISSION_70: u64 = 8 * ONE_YEAR_SECONDS; pub const MAX_DISSOLVE_DELAY_SECONDS_POST_MISSION_70: u64 = 2 * ONE_YEAR_SECONDS; @@ -5226,18 +5232,16 @@ impl Governance { )); } - let min_dissolve_delay_seconds_to_vote = if action.manage_neuron().is_some() { + let min_dissolve_delay_seconds_to_propose = if action.manage_neuron().is_some() { 0 } else { - self.neuron_minimum_dissolve_delay_to_vote_seconds() + NEURON_MINIMUM_DISSOLVE_DELAY_TO_PROPOSE_SECONDS }; - // The proposer must be eligible to vote. This also ensures that the - // neuron cannot be dissolved until the proposal has been adopted or - // rejected. - if proposer_dissolve_delay_seconds < min_dissolve_delay_seconds_to_vote { + // The proposer must have sufficient dissolve delay to submit proposals. + if proposer_dissolve_delay_seconds < min_dissolve_delay_seconds_to_propose { return Err(GovernanceError::new_with_message( - ErrorType::InsufficientFunds, + ErrorType::PreconditionFailed, "Neuron's dissolve delay is too short.", )); } diff --git a/rs/nns/governance/src/network_economics.rs b/rs/nns/governance/src/network_economics.rs index 2e5ab6255d64..4f42d65ced0d 100644 --- a/rs/nns/governance/src/network_economics.rs +++ b/rs/nns/governance/src/network_economics.rs @@ -1,3 +1,4 @@ +use crate::governance::NEURON_MINIMUM_DISSOLVE_DELAY_TO_PROPOSE_SECONDS; use crate::pb::v1::{ NetworkEconomics, NeuronsFundEconomics, NeuronsFundMatchedFundingCurveCoefficients, VotingPowerEconomics, @@ -380,6 +381,16 @@ impl VotingPowerEconomics { ); defects.push(defect); } + + if delay > NEURON_MINIMUM_DISSOLVE_DELAY_TO_PROPOSE_SECONDS { + let defect = format!( + "neuron_minimum_dissolve_delay_to_vote_seconds ({:?}) must not exceed \ + the minimum dissolve delay required to submit proposals ({}).", + self.neuron_minimum_dissolve_delay_to_vote_seconds, + NEURON_MINIMUM_DISSOLVE_DELAY_TO_PROPOSE_SECONDS, + ); + defects.push(defect); + } } else { defects.push("neuron_minimum_dissolve_delay_to_vote_seconds must be set.".to_string()); } diff --git a/rs/nns/governance/src/network_economics_tests.rs b/rs/nns/governance/src/network_economics_tests.rs index 802d0e2f1678..0486269c2062 100644 --- a/rs/nns/governance/src/network_economics_tests.rs +++ b/rs/nns/governance/src/network_economics_tests.rs @@ -112,10 +112,18 @@ fn test_neuron_minimum_dissolve_delay_to_vote_seconds_bounds() { ), ( Some(UPPER_BOUND_SECONDS + 1), - Err(vec![format!( - "neuron_minimum_dissolve_delay_to_vote_seconds (Some({})) must be between two weeks and six months.", - UPPER_BOUND_SECONDS + 1 - )]), + Err(vec![ + format!( + "neuron_minimum_dissolve_delay_to_vote_seconds (Some({})) must be between two weeks and six months.", + UPPER_BOUND_SECONDS + 1 + ), + format!( + "neuron_minimum_dissolve_delay_to_vote_seconds (Some({})) must not exceed \ + the minimum dissolve delay required to submit proposals ({}).", + UPPER_BOUND_SECONDS + 1, + crate::governance::NEURON_MINIMUM_DISSOLVE_DELAY_TO_PROPOSE_SECONDS, + ), + ]), ), (Some(DEFAULT_SECONDS), Ok(())), (Some(LOWER_BOUND_SECONDS), Ok(())), diff --git a/rs/nns/governance/unreleased_changelog.md b/rs/nns/governance/unreleased_changelog.md index 50b21f2dccc3..ec471d76449c 100644 --- a/rs/nns/governance/unreleased_changelog.md +++ b/rs/nns/governance/unreleased_changelog.md @@ -13,6 +13,8 @@ on the process that this file is part of, see ## Changed +* The minimum dissolve delay required to submit non-manage-neuron proposals is now + a fixed 6 months, decoupled from the voting eligibility threshold which can be lower. * Mission 70 voting rewards adjustment has been re-calculated. Now: 63.29%. Before: 65.5%. ## Deprecated