penumbra_sdk_governance/
params.rs

1use anyhow::Context;
2use penumbra_sdk_num::Amount;
3use penumbra_sdk_proto::core::component::governance::v1 as pb;
4use penumbra_sdk_proto::DomainType;
5use serde::{Deserialize, Serialize};
6
7use crate::tally::Ratio;
8
9#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
10#[serde(
11    try_from = "pb::GovernanceParameters",
12    into = "pb::GovernanceParameters"
13)]
14pub struct GovernanceParameters {
15    /// The number of blocks during which a proposal is voted on.
16    pub proposal_voting_blocks: u64,
17    /// The deposit required to create a proposal.
18    pub proposal_deposit_amount: Amount,
19    /// The quorum required for a proposal to be considered valid, as a fraction of the total stake
20    /// weight of the network.
21    pub proposal_valid_quorum: Ratio,
22    /// The threshold for a proposal to pass voting, as a ratio of "yes" votes over "no" votes.
23    pub proposal_pass_threshold: Ratio,
24    /// The threshold for a proposal to be slashed, as a ratio of "no" votes over all total votes.
25    pub proposal_slash_threshold: Ratio,
26}
27
28impl DomainType for GovernanceParameters {
29    type Proto = pb::GovernanceParameters;
30}
31
32impl TryFrom<pb::GovernanceParameters> for GovernanceParameters {
33    type Error = anyhow::Error;
34
35    fn try_from(msg: pb::GovernanceParameters) -> anyhow::Result<Self> {
36        Ok(GovernanceParameters {
37            proposal_voting_blocks: msg.proposal_voting_blocks,
38            proposal_deposit_amount: msg
39                .proposal_deposit_amount
40                .ok_or_else(|| anyhow::anyhow!("missing proposal_deposit_amount"))?
41                .try_into()?,
42            proposal_valid_quorum: msg
43                .proposal_valid_quorum
44                .parse()
45                .context("couldn't parse proposal_valid_quorum")?,
46            proposal_pass_threshold: msg
47                .proposal_pass_threshold
48                .parse()
49                .context("couldn't parse proposal_pass_threshold")?,
50            proposal_slash_threshold: msg
51                .proposal_slash_threshold
52                .parse()
53                .context("couldn't parse proposal_slash_threshold")?,
54        })
55    }
56}
57
58impl From<GovernanceParameters> for pb::GovernanceParameters {
59    fn from(params: GovernanceParameters) -> Self {
60        pb::GovernanceParameters {
61            proposal_voting_blocks: params.proposal_voting_blocks,
62            proposal_deposit_amount: Some(params.proposal_deposit_amount.into()),
63            proposal_valid_quorum: params.proposal_valid_quorum.to_string(),
64            proposal_pass_threshold: params.proposal_pass_threshold.to_string(),
65            proposal_slash_threshold: params.proposal_slash_threshold.to_string(),
66        }
67    }
68}
69
70impl Default for GovernanceParameters {
71    fn default() -> Self {
72        Self {
73            // governance
74            proposal_voting_blocks: 17_280, // 24 hours, at a 5 second block time
75            proposal_deposit_amount: 10_000_000u64.into(), // 10,000,000 upenumbra = 10 penumbra
76            // governance parameters copied from cosmos hub
77            proposal_valid_quorum: Ratio::new(40, 100),
78            proposal_pass_threshold: Ratio::new(50, 100),
79            // slash threshold means if (no / no + yes + abstain) > slash_threshold, then proposal is slashed
80            proposal_slash_threshold: Ratio::new(80, 100),
81        }
82    }
83}