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

Commit 2600963

Browse files
authored
Governance: Track proposals in Voting state for realms and governances (#2838)
* wip: add voting_proposal_count to Realm * feat: track voting proposal count when proposal enters voting state * chore: pass signatory or owner record * chore: rename assert_can_create_governance to assert_create_authority_can_create_governance * feat: decrease voting proposal count when proposal is canceled * chore: remove clock and rent accounts * chore: remove clock and rent * chore: remove rent and clock * chore: remove rent and clock * chore: remove clock * chore: remove rent * chore: remove rent * chore: remove rent * fix: decrease voting_proposal_count when proposal is finalised * fix: update voting_proposal_count when proposal vote is tipped * wip: add muted checks for ream and governance config change
1 parent 3a21fca commit 2600963

29 files changed

+355
-153
lines changed

governance/program/src/error.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ pub enum GovernanceError {
280280

281281
/// Realm authority must sign
282282
#[error("Realm authority must sign")]
283-
RealmAuthorityMustSign,
283+
RealmAuthorityMustSign, // 566
284284

285285
/// Invalid governing token holding account
286286
#[error("Invalid governing token holding account")]
@@ -290,7 +290,7 @@ pub enum GovernanceError {
290290
#[error("Realm council mint change is not supported")]
291291
RealmCouncilMintChangeIsNotSupported,
292292

293-
/// Not supported mint max vote weight source
293+
/// Not supported mint max vote weight sourcef
294294
#[error("Not supported mint max vote weight source")]
295295
MintMaxVoteWeightSourceNotSupported,
296296

@@ -385,6 +385,14 @@ pub enum GovernanceError {
385385
/// Not supported VoteType
386386
#[error("Not supported VoteType")]
387387
NotSupportedVoteType,
388+
389+
/// RealmConfig change not allowed
390+
#[error("RealmConfig change not allowed")]
391+
RealmConfigChangeNotAllowed,
392+
393+
/// GovernanceConfig change not allowed
394+
#[error("GovernanceConfig change not allowed")]
395+
GovernanceConfigChangeNotAllowed,
388396
}
389397

390398
impl PrintProgramError for GovernanceError {

governance/program/src/instruction.rs

Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,8 @@ pub enum GovernanceInstruction {
163163
/// 5. `[signer]` Governance Authority (Token Owner or Governance Delegate)
164164
/// 6. `[signer]` Payer
165165
/// 7. `[]` System program
166-
/// 8. `[]` Rent sysvar
167-
/// 9. `[]` Clock sysvar
168-
/// 10. `[]` Realm Config
169-
/// 11. `[]` Optional Voter Weight Record
166+
/// 8. `[]` Realm Config
167+
/// 9. `[]` Optional Voter Weight Record
170168
CreateProposal {
171169
#[allow(dead_code)]
172170
/// UTF-8 encoded name of the proposal
@@ -258,11 +256,11 @@ pub enum GovernanceInstruction {
258256

259257
/// Cancels Proposal by changing its state to Canceled
260258
///
261-
/// 0. `[writable]` Proposal account
262-
/// 1. `[writable]` TokenOwnerRecord account of the Proposal owner
263-
/// 2. `[signer]` Governance Authority (Token Owner or Governance Delegate)
264-
/// 3. `[]` Clock sysvar
265-
/// 4. `[]` Governance account
259+
/// 0. `[writable]` Realm account
260+
/// 1. `[writable]` Governance account
261+
/// 2. `[writable]` Proposal account
262+
/// 3. `[writable]` TokenOwnerRecord account of the Proposal owner
263+
/// 4. `[signer]` Governance Authority (Token Owner or Governance Delegate)
266264
CancelProposal,
267265

268266
/// Signs off Proposal indicating the Signatory approves the Proposal
@@ -271,20 +269,21 @@ pub enum GovernanceInstruction {
271269
/// it's entirely at the discretion of the Proposal owner
272270
/// If Proposal owner doesn't designate any signatories then can sign off the Proposal themself
273271
///
274-
/// 0. `[writable]` Proposal account
275-
/// 1. `[writable]` Signatory Record account
276-
/// 2. `[signer]` Signatory account signing off the Proposal
272+
/// 0. `[writable]` Realm account
273+
/// 1. `[writable]` Governance account
274+
/// 2. `[writable]` Proposal account
275+
/// 4. `[signer]` Signatory account signing off the Proposal
277276
/// Or Proposal owner if the owner hasn't appointed any signatories
278-
/// 3. `[]` Clock sysvar
279-
/// 4. `[]` Optional TokenOwnerRecord of the Proposal owner when self signing off the Proposal
277+
/// 5. `[]` Optional TokenOwnerRecord for the Proposal owner. Required when the owner signs off the Proposal
278+
/// 3. `[writable]` Optional Signatory Record account. Required when non owner sings off the Proposal
280279
SignOffProposal,
281280

282281
/// Uses your voter weight (deposited Community or Council tokens) to cast a vote on a Proposal
283282
/// By doing so you indicate you approve or disapprove of running the Proposal set of transactions
284283
/// If you tip the consensus then the transactions can begin to be run after their hold up time
285284
///
286-
/// 0. `[]` Realm account
287-
/// 1. `[]` Governance account
285+
/// 0. `[writable]` Realm account
286+
/// 1. `[writable]` Governance account
288287
/// 2. `[writable]` Proposal account
289288
/// 4. `[writable]` TokenOwnerRecord of the Proposal owner
290289
/// 3. `[writable]` TokenOwnerRecord of the voter. PDA seeds: ['governance',realm, governing_token_mint, governing_token_owner]
@@ -293,11 +292,9 @@ pub enum GovernanceInstruction {
293292
/// 6. `[]` Governing Token Mint
294293
/// 7. `[signer]` Payer
295294
/// 8. `[]` System program
296-
/// 9. `[]` Rent sysvar
297-
/// 10. `[]` Clock sysvar
298-
/// 11. `[]` Realm Config
299-
/// 12. `[]` Optional Voter Weight Record
300-
/// 13. `[]` Optional Max Voter Weight Record
295+
/// 9. `[]` Realm Config
296+
/// 10. `[]` Optional Voter Weight Record
297+
/// 11. `[]` Optional Max Voter Weight Record
301298
CastVote {
302299
#[allow(dead_code)]
303300
/// User's vote
@@ -306,14 +303,13 @@ pub enum GovernanceInstruction {
306303

307304
/// Finalizes vote in case the Vote was not automatically tipped within max_voting_time period
308305
///
309-
/// 0. `[]` Realm account
310-
/// 1. `[]` Governance account
306+
/// 0. `[writable]` Realm account
307+
/// 1. `[writable]` Governance account
311308
/// 2. `[writable]` Proposal account
312309
/// 3. `[writable]` TokenOwnerRecord of the Proposal owner
313310
/// 4. `[]` Governing Token Mint
314-
/// 5. `[]` Clock sysvar
315-
/// 6. `[]` Realm Config
316-
/// 7. `[]` Optional Max Voter Weight Record
311+
/// 5. `[]` Realm Config
312+
/// 6. `[]` Optional Max Voter Weight Record
317313
FinalizeVote {},
318314

319315
/// Relinquish Vote removes voter weight from a Proposal and removes it from voter's active votes
@@ -339,8 +335,7 @@ pub enum GovernanceInstruction {
339335
///
340336
/// 0. `[writable]` Proposal account
341337
/// 1. `[writable]` ProposalTransaction account you wish to execute
342-
/// 2. `[]` Clock sysvar
343-
/// 3+ Any extra accounts that are part of the transaction, in order
338+
/// 2+ Any extra accounts that are part of the transaction, in order
344339
ExecuteTransaction,
345340

346341
/// Creates Mint Governance account which governs a mint
@@ -414,7 +409,6 @@ pub enum GovernanceInstruction {
414409
/// 1. `[]` TokenOwnerRecord account of the Proposal owner
415410
/// 2. `[signer]` Governance Authority (Token Owner or Governance Delegate)
416411
/// 3. `[writable]` ProposalTransaction account to flag
417-
/// 4. `[]` Clock sysvar
418412
FlagTransactionError,
419413

420414
/// Sets new Realm authority
@@ -599,7 +593,6 @@ pub fn deposit_governing_tokens(
599593
AccountMeta::new(*payer, true),
600594
AccountMeta::new_readonly(system_program::id(), false),
601595
AccountMeta::new_readonly(spl_token::id(), false),
602-
AccountMeta::new_readonly(sysvar::rent::id(), false),
603596
];
604597

605598
let instruction = GovernanceInstruction::DepositGoverningTokens { amount };
@@ -713,7 +706,6 @@ pub fn create_governance(
713706
AccountMeta::new_readonly(*token_owner_record, false),
714707
AccountMeta::new(*payer, true),
715708
AccountMeta::new_readonly(system_program::id(), false),
716-
AccountMeta::new_readonly(sysvar::rent::id(), false),
717709
AccountMeta::new_readonly(*create_authority, true),
718710
];
719711

@@ -758,7 +750,6 @@ pub fn create_program_governance(
758750
AccountMeta::new(*payer, true),
759751
AccountMeta::new_readonly(bpf_loader_upgradeable::id(), false),
760752
AccountMeta::new_readonly(system_program::id(), false),
761-
AccountMeta::new_readonly(sysvar::rent::id(), false),
762753
AccountMeta::new_readonly(*create_authority, true),
763754
];
764755

@@ -803,7 +794,6 @@ pub fn create_mint_governance(
803794
AccountMeta::new(*payer, true),
804795
AccountMeta::new_readonly(spl_token::id(), false),
805796
AccountMeta::new_readonly(system_program::id(), false),
806-
AccountMeta::new_readonly(sysvar::rent::id(), false),
807797
AccountMeta::new_readonly(*create_authority, true),
808798
];
809799

@@ -848,7 +838,6 @@ pub fn create_token_governance(
848838
AccountMeta::new(*payer, true),
849839
AccountMeta::new_readonly(spl_token::id(), false),
850840
AccountMeta::new_readonly(system_program::id(), false),
851-
AccountMeta::new_readonly(sysvar::rent::id(), false),
852841
AccountMeta::new_readonly(*create_authority, true),
853842
];
854843

@@ -902,8 +891,6 @@ pub fn create_proposal(
902891
AccountMeta::new_readonly(*governance_authority, true),
903892
AccountMeta::new(*payer, true),
904893
AccountMeta::new_readonly(system_program::id(), false),
905-
AccountMeta::new_readonly(sysvar::rent::id(), false),
906-
AccountMeta::new_readonly(sysvar::clock::id(), false),
907894
];
908895

909896
with_realm_config_accounts(program_id, &mut accounts, realm, voter_weight_record, None);
@@ -943,7 +930,6 @@ pub fn add_signatory(
943930
AccountMeta::new(signatory_record_address, false),
944931
AccountMeta::new(*payer, true),
945932
AccountMeta::new_readonly(system_program::id(), false),
946-
AccountMeta::new_readonly(sysvar::rent::id(), false),
947933
];
948934

949935
let instruction = GovernanceInstruction::AddSignatory {
@@ -992,21 +978,25 @@ pub fn remove_signatory(
992978
pub fn sign_off_proposal(
993979
program_id: &Pubkey,
994980
// Accounts
981+
realm: &Pubkey,
982+
governance: &Pubkey,
995983
proposal: &Pubkey,
996984
signatory: &Pubkey,
997985
proposal_owner_record: Option<&Pubkey>,
998986
) -> Instruction {
999-
let signatory_record_address = get_signatory_record_address(program_id, proposal, signatory);
1000-
1001987
let mut accounts = vec![
988+
AccountMeta::new(*realm, false),
989+
AccountMeta::new(*governance, false),
1002990
AccountMeta::new(*proposal, false),
1003-
AccountMeta::new(signatory_record_address, false),
1004991
AccountMeta::new_readonly(*signatory, true),
1005-
AccountMeta::new_readonly(sysvar::clock::id(), false),
1006992
];
1007993

1008994
if let Some(proposal_owner_record) = proposal_owner_record {
1009995
accounts.push(AccountMeta::new_readonly(*proposal_owner_record, false))
996+
} else {
997+
let signatory_record_address =
998+
get_signatory_record_address(program_id, proposal, signatory);
999+
accounts.push(AccountMeta::new(signatory_record_address, false));
10101000
}
10111001

10121002
let instruction = GovernanceInstruction::SignOffProposal;
@@ -1040,8 +1030,8 @@ pub fn cast_vote(
10401030
get_vote_record_address(program_id, proposal, voter_token_owner_record);
10411031

10421032
let mut accounts = vec![
1043-
AccountMeta::new_readonly(*realm, false),
1044-
AccountMeta::new_readonly(*governance, false),
1033+
AccountMeta::new(*realm, false),
1034+
AccountMeta::new(*governance, false),
10451035
AccountMeta::new(*proposal, false),
10461036
AccountMeta::new(*proposal_owner_record, false),
10471037
AccountMeta::new(*voter_token_owner_record, false),
@@ -1050,8 +1040,6 @@ pub fn cast_vote(
10501040
AccountMeta::new_readonly(*governing_token_mint, false),
10511041
AccountMeta::new(*payer, true),
10521042
AccountMeta::new_readonly(system_program::id(), false),
1053-
AccountMeta::new_readonly(sysvar::rent::id(), false),
1054-
AccountMeta::new_readonly(sysvar::clock::id(), false),
10551043
];
10561044

10571045
with_realm_config_accounts(
@@ -1083,12 +1071,11 @@ pub fn finalize_vote(
10831071
max_voter_weight_record: Option<Pubkey>,
10841072
) -> Instruction {
10851073
let mut accounts = vec![
1086-
AccountMeta::new_readonly(*realm, false),
1087-
AccountMeta::new_readonly(*governance, false),
1074+
AccountMeta::new(*realm, false),
1075+
AccountMeta::new(*governance, false),
10881076
AccountMeta::new(*proposal, false),
10891077
AccountMeta::new(*proposal_owner_record, false),
10901078
AccountMeta::new_readonly(*governing_token_mint, false),
1091-
AccountMeta::new_readonly(sysvar::clock::id(), false),
10921079
];
10931080

10941081
with_realm_config_accounts(
@@ -1147,17 +1134,18 @@ pub fn relinquish_vote(
11471134
pub fn cancel_proposal(
11481135
program_id: &Pubkey,
11491136
// Accounts
1137+
realm: &Pubkey,
1138+
governance: &Pubkey,
11501139
proposal: &Pubkey,
11511140
proposal_owner_record: &Pubkey,
11521141
governance_authority: &Pubkey,
1153-
governance: &Pubkey,
11541142
) -> Instruction {
11551143
let accounts = vec![
1144+
AccountMeta::new(*realm, false),
1145+
AccountMeta::new(*governance, false),
11561146
AccountMeta::new(*proposal, false),
11571147
AccountMeta::new(*proposal_owner_record, false),
11581148
AccountMeta::new_readonly(*governance_authority, true),
1159-
AccountMeta::new_readonly(sysvar::clock::id(), false),
1160-
AccountMeta::new_readonly(*governance, false),
11611149
];
11621150

11631151
let instruction = GovernanceInstruction::CancelProposal {};
@@ -1258,7 +1246,6 @@ pub fn execute_transaction(
12581246
AccountMeta::new_readonly(*governance, false),
12591247
AccountMeta::new(*proposal, false),
12601248
AccountMeta::new(*proposal_transaction, false),
1261-
AccountMeta::new_readonly(sysvar::clock::id(), false),
12621249
AccountMeta::new_readonly(*instruction_program_id, false),
12631250
];
12641251

@@ -1306,7 +1293,6 @@ pub fn flag_transaction_error(
13061293
AccountMeta::new_readonly(*token_owner_record, false),
13071294
AccountMeta::new_readonly(*governance_authority, true),
13081295
AccountMeta::new(*proposal_transaction, false),
1309-
AccountMeta::new_readonly(sysvar::clock::id(), false),
13101296
];
13111297

13121298
let instruction = GovernanceInstruction::FlagTransactionError {};

governance/program/src/processor/process_add_signatory.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ pub fn process_add_signatory(
3333
let payer_info = next_account_info(account_info_iter)?; // 4
3434
let system_info = next_account_info(account_info_iter)?; // 5
3535

36-
let rent_sysvar_info = next_account_info(account_info_iter)?; // 6
37-
let rent = &Rent::from_account_info(rent_sysvar_info)?;
36+
let rent = Rent::get()?;
3837

3938
let mut proposal_data = get_proposal_data(program_id, proposal_info)?;
4039
proposal_data.assert_can_edit_signatories()?;
@@ -61,7 +60,7 @@ pub fn process_add_signatory(
6160
&get_signatory_record_address_seeds(proposal_info.key, &signatory),
6261
program_id,
6362
system_info,
64-
rent,
63+
&rent,
6564
)?;
6665

6766
proposal_data.signatories_count = proposal_data.signatories_count.checked_add(1).unwrap();

governance/program/src/processor/process_cancel_proposal.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,27 @@ use solana_program::{
1010
};
1111

1212
use crate::state::{
13-
enums::ProposalState, governance::get_governance_data,
14-
proposal::get_proposal_data_for_governance,
13+
enums::ProposalState, governance::get_governance_data_for_realm,
14+
proposal::get_proposal_data_for_governance, realm::get_realm_data,
1515
token_owner_record::get_token_owner_record_data_for_proposal_owner,
1616
};
1717

1818
/// Processes CancelProposal instruction
1919
pub fn process_cancel_proposal(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
2020
let account_info_iter = &mut accounts.iter();
2121

22-
let proposal_info = next_account_info(account_info_iter)?; // 0
23-
let proposal_owner_record_info = next_account_info(account_info_iter)?; // 1
24-
let governance_authority_info = next_account_info(account_info_iter)?; // 2
22+
let realm_info = next_account_info(account_info_iter)?; // 0
23+
let governance_info = next_account_info(account_info_iter)?; // 1
24+
let proposal_info = next_account_info(account_info_iter)?; // 2
25+
let proposal_owner_record_info = next_account_info(account_info_iter)?; // 3
26+
let governance_authority_info = next_account_info(account_info_iter)?; // 4
2527

26-
let clock_info = next_account_info(account_info_iter)?; // 3
27-
let clock = Clock::from_account_info(clock_info)?;
28+
let clock = Clock::get()?;
2829

29-
let governance_info = next_account_info(account_info_iter)?; // 4
30+
let mut realm_data = get_realm_data(program_id, realm_info)?;
3031

31-
let governance_data = get_governance_data(program_id, governance_info)?;
32+
let mut governance_data =
33+
get_governance_data_for_realm(program_id, governance_info, realm_info.key)?;
3234

3335
let mut proposal_data =
3436
get_proposal_data_for_governance(program_id, proposal_info, governance_info.key)?;
@@ -46,6 +48,19 @@ pub fn process_cancel_proposal(program_id: &Pubkey, accounts: &[AccountInfo]) ->
4648
proposal_owner_record_data.decrease_outstanding_proposal_count();
4749
proposal_owner_record_data.serialize(&mut *proposal_owner_record_info.data.borrow_mut())?;
4850

51+
if proposal_data.state == ProposalState::Voting {
52+
// Update Realm voting_proposal_count
53+
realm_data.voting_proposal_count = realm_data.voting_proposal_count.checked_sub(1).unwrap();
54+
realm_data.serialize(&mut *realm_info.data.borrow_mut())?;
55+
56+
// Update Governance voting_proposal_count
57+
governance_data.voting_proposal_count = governance_data
58+
.voting_proposal_count
59+
.checked_sub(1)
60+
.unwrap();
61+
governance_data.serialize(&mut *governance_info.data.borrow_mut())?;
62+
}
63+
4964
proposal_data.state = ProposalState::Cancelled;
5065
proposal_data.closed_at = Some(clock.unix_timestamp);
5166

0 commit comments

Comments
 (0)