Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 219b6a1

Browse files
authored
Governance: Council Vote Threshold (#3135)
* wip: Replace proposal_cool_off_time with council_vote_threshold * wip: serialise governance vec * wip: cool off time * chore: create test to deserialize legacy config * wip: default council_vote_threshold from community_vote_threshold for legacy accounts * chore: fix chat compilation * feat: use community_vote_threshold for voting * feat: assert all voting thresholds are not disabled * chore: simplify tests without config mutation * feat: assert proposal is created for valid vote threshold * chore: update test name * chore: test_finalize_council_vote * chore: test_cast_council_vote * chore: test for disabled voter threshold * feat: Ensure GovernanceConfig reserved buffer is always empty * chore: change error name to AtLeastOneVoteThresholdRequired * chore: add comments * chore: Add VoteThreshold.Any comments
1 parent bcf7aa2 commit 219b6a1

File tree

15 files changed

+612
-73
lines changed

15 files changed

+612
-73
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

governance/chat/program/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "spl-governance-chat"
3-
version = "0.2.5"
3+
version = "0.2.6"
44
description = "Solana Program Library Governance Chat Program"
55
authors = ["Solana Maintainers <[email protected]>"]
66
repository = "https://github.com/solana-labs/solana-program-library"
@@ -21,7 +21,7 @@ serde = "1.0.127"
2121
serde_derive = "1.0.103"
2222
solana-program = "1.10.10"
2323
spl-token = { version = "3.3", path = "../../../token/program", features = [ "no-entrypoint" ] }
24-
spl-governance= { version = "2.2.4", path ="../../program", features = [ "no-entrypoint" ]}
24+
spl-governance= { version = "3.0.0", path ="../../program", features = [ "no-entrypoint" ]}
2525
spl-governance-tools= { version = "0.1.2", path ="../../tools"}
2626
spl-governance-addin-api= { version = "0.1.2", path ="../../addin-api"}
2727
thiserror = "1.0"

governance/chat/program/tests/program_test/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ impl GovernanceChatProgramTest {
185185
max_voting_time: 10,
186186
community_vote_threshold: VoteThreshold::YesVotePercentage(60),
187187
vote_tipping: spl_governance::state::enums::VoteTipping::Strict,
188-
proposal_cool_off_time: 0,
188+
council_vote_threshold: VoteThreshold::YesVotePercentage(10),
189+
reserved: [0; 2],
189190
};
190191

191192
let token_owner_record_address = get_token_owner_record_address(

governance/program/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "spl-governance"
3-
version = "2.2.4"
3+
version = "3.0.0"
44
description = "Solana Program Library Governance Program"
55
authors = ["Solana Maintainers <[email protected]>"]
66
repository = "https://github.com/solana-labs/solana-program-library"

governance/program/src/error.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,17 +246,17 @@ pub enum GovernanceError {
246246
#[error("Current token owner must sign transaction")]
247247
TokenOwnerMustSign,
248248

249-
/// Given VoteThresholdPercentageType is not supported
250-
#[error("Given VoteThresholdPercentageType is not supported")]
251-
VoteThresholdPercentageTypeNotSupported,
249+
/// Given VoteThresholdType is not supported
250+
#[error("Given VoteThresholdType is not supported")]
251+
VoteThresholdTypeNotSupported,
252252

253253
/// Given VoteWeightSource is not supported
254254
#[error("Given VoteWeightSource is not supported")]
255255
VoteWeightSourceNotSupported,
256256

257-
/// Proposal cool off time is not supported
258-
#[error("Proposal cool off time is not supported")]
259-
ProposalCoolOffTimeNotSupported,
257+
/// GoverningTokenMint not allowed to vote
258+
#[error("GoverningTokenMint not allowed to vote")]
259+
GoverningTokenMintNotAllowedToVote, // 560
260260

261261
/// Governance PDA must sign
262262
#[error("Governance PDA must sign")]
@@ -393,6 +393,14 @@ pub enum GovernanceError {
393393
/// GovernanceConfig change not allowed
394394
#[error("GovernanceConfig change not allowed")]
395395
GovernanceConfigChangeNotAllowed,
396+
397+
/// At least one VoteThreshold is required
398+
#[error("At least one VoteThreshold is required")]
399+
AtLeastOneVoteThresholdRequired,
400+
401+
/// Reserved buffer must be empty
402+
#[error("Reserved buffer must be empty")]
403+
ReservedBufferMustBeEmpty,
396404
}
397405

398406
impl PrintProgramError for GovernanceError {

governance/program/src/processor/process_cast_vote.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,14 @@ pub fn process_cast_vote(
143143
&realm_data,
144144
)?;
145145

146+
let vote_threshold =
147+
governance_data.resolve_vote_threshold(&realm_data, governing_token_mint_info.key)?;
148+
146149
if proposal_data.try_tip_vote(
147150
max_voter_weight,
148151
&governance_data.config,
149152
clock.unix_timestamp,
153+
&vote_threshold,
150154
)? {
151155
// Deserialize proposal owner and validate it's the actual owner of the proposal
152156
let mut proposal_owner_record_data = get_token_owner_record_data_for_proposal_owner(

governance/program/src/processor/process_create_proposal.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ pub fn process_create_proposal(
6464
let mut governance_data =
6565
get_governance_data_for_realm(program_id, governance_info, realm_info.key)?;
6666

67+
governance_data
68+
.assert_governing_token_mint_can_vote(&realm_data, governing_token_mint_info.key)?;
69+
6770
let mut proposal_owner_record_data = get_token_owner_record_data_for_realm(
6871
program_id,
6972
proposal_owner_record_info,

governance/program/src/processor/process_finalize_vote.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,14 @@ pub fn process_finalize_vote(program_id: &Pubkey, accounts: &[AccountInfo]) -> P
5454
&realm_data,
5555
)?;
5656

57+
let vote_threshold =
58+
governance_data.resolve_vote_threshold(&realm_data, governing_token_mint_info.key)?;
59+
5760
proposal_data.finalize_vote(
5861
max_voter_weight,
5962
&governance_data.config,
6063
clock.unix_timestamp,
64+
&vote_threshold,
6165
)?;
6266

6367
let mut proposal_owner_record_data = get_token_owner_record_data_for_proposal_owner(

governance/program/src/state/enums.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ impl Default for ProposalState {
137137
}
138138
}
139139

140-
/// The type of the vote threshold percentage used to resolve a vote on a Proposal
140+
/// The type of the vote threshold used to resolve a vote on a Proposal
141+
///
142+
/// Note: In the current version only YesVotePercentage and Disabled thresholds are supported
141143
#[repr(C)]
142144
#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
143145
pub enum VoteThreshold {
@@ -152,6 +154,20 @@ pub enum VoteThreshold {
152154
/// Once the quorum is achieved a simple majority (50%+1) of Yes votes is required for the vote to succeed
153155
/// Note: Quorum is not implemented in the current version
154156
QuorumPercentage(u8),
157+
158+
/// Disabled vote threshold indicates the given voting population (community or council) is not allowed to vote
159+
/// on proposals for the given Governance
160+
Disabled,
161+
//
162+
// Absolute vote threshold expressed in the voting mint units
163+
// It can be implemented once Solana runtime supports accounts resizing to accommodate u64 size extension
164+
// Alternatively we could use the reserved space if it becomes a priority
165+
// Absolute(u64)
166+
//
167+
// Vote threshold which is always accepted
168+
// It can be used in a setup where the only security gate is proposal creation
169+
// and once created it's automatically approved
170+
// Any
155171
}
156172

157173
/// The type of vote tipping to use on a Proposal.

0 commit comments

Comments
 (0)