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

Commit 7fdb082

Browse files
Governance: Implement Absolute max voter weight source (#3627)
* feat: Implement Absolute max voter weight source * chore: Rename max_vote_weight to max_voter_weight * chore: update comments * chore: test_try_tip_vote_with_reduced_absolute_mint_max_vote_weight_and_vote_overflow Co-authored-by: Jon Cinque <[email protected]>
1 parent e988b16 commit 7fdb082

File tree

12 files changed

+224
-90
lines changed

12 files changed

+224
-90
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use spl_governance::{
1010
deposit_governing_tokens,
1111
},
1212
state::{
13-
enums::{MintMaxVoteWeightSource, VoteThreshold},
13+
enums::{MintMaxVoterWeightSource, VoteThreshold},
1414
governance::{get_governance_address, GovernanceConfig},
1515
proposal::{get_proposal_address, VoteType},
1616
realm::{get_realm_address, GoverningTokenConfigAccountArgs},
@@ -125,7 +125,7 @@ impl GovernanceChatProgramTest {
125125
None,
126126
name.clone(),
127127
1,
128-
MintMaxVoteWeightSource::FULL_SUPPLY_FRACTION,
128+
MintMaxVoterWeightSource::FULL_SUPPLY_FRACTION,
129129
);
130130

131131
self.bench

governance/program/src/error.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -291,13 +291,13 @@ pub enum GovernanceError {
291291
#[error("Realm council mint change is not supported")]
292292
RealmCouncilMintChangeIsNotSupported,
293293

294-
/// Not supported mint max vote weight sourcef
295-
#[error("Not supported mint max vote weight source")]
296-
MintMaxVoteWeightSourceNotSupported,
294+
/// Invalid max voter weight absolute value
295+
#[error("Invalid max voter weight absolute value")]
296+
InvalidMaxVoterWeightAbsoluteValue,
297297

298-
/// Invalid max vote weight supply fraction
299-
#[error("Invalid max vote weight supply fraction")]
300-
InvalidMaxVoteWeightSupplyFraction,
298+
/// Invalid max voter weight supply fraction
299+
#[error("Invalid max voter weight supply fraction")]
300+
InvalidMaxVoterWeightSupplyFraction,
301301

302302
/// Owner doesn't have enough governing tokens to create Governance
303303
#[error("Owner doesn't have enough governing tokens to create Governance")]

governance/program/src/instruction.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::{
44
state::{
5-
enums::MintMaxVoteWeightSource,
5+
enums::MintMaxVoterWeightSource,
66
governance::{
77
get_governance_address, get_mint_governance_address, get_program_governance_address,
88
get_token_governance_address, GovernanceConfig,
@@ -522,7 +522,7 @@ pub fn create_realm(
522522
// Args
523523
name: String,
524524
min_community_weight_to_create_governance: u64,
525-
community_mint_max_vote_weight_source: MintMaxVoteWeightSource,
525+
community_mint_max_voter_weight_source: MintMaxVoterWeightSource,
526526
) -> Instruction {
527527
let realm_address = get_realm_address(program_id, &name);
528528
let community_token_holding_address =
@@ -563,7 +563,7 @@ pub fn create_realm(
563563
config_args: RealmConfigArgs {
564564
use_council_mint,
565565
min_community_weight_to_create_governance,
566-
community_mint_max_vote_weight_source,
566+
community_mint_max_voter_weight_source,
567567
community_token_config_args,
568568
council_token_config_args,
569569
},
@@ -1379,7 +1379,7 @@ pub fn set_realm_config(
13791379
council_token_config_args: Option<GoverningTokenConfigAccountArgs>,
13801380
// Args
13811381
min_community_weight_to_create_governance: u64,
1382-
community_mint_max_vote_weight_source: MintMaxVoteWeightSource,
1382+
community_mint_max_voter_weight_source: MintMaxVoterWeightSource,
13831383
) -> Instruction {
13841384
let mut accounts = vec![
13851385
AccountMeta::new(*realm, false),
@@ -1416,7 +1416,7 @@ pub fn set_realm_config(
14161416
config_args: RealmConfigArgs {
14171417
use_council_mint,
14181418
min_community_weight_to_create_governance,
1419-
community_mint_max_vote_weight_source,
1419+
community_mint_max_voter_weight_source,
14201420
community_token_config_args,
14211421
council_token_config_args,
14221422
},

governance/program/src/processor/process_create_realm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ pub fn process_create_realm(
132132
config: RealmConfig {
133133
council_mint: council_token_mint_address,
134134
reserved: [0; 6],
135-
community_mint_max_vote_weight_source: realm_config_args
136-
.community_mint_max_vote_weight_source,
135+
community_mint_max_voter_weight_source: realm_config_args
136+
.community_mint_max_voter_weight_source,
137137
min_community_weight_to_create_governance: realm_config_args
138138
.min_community_weight_to_create_governance,
139139
legacy1: 0,

governance/program/src/processor/process_set_realm_config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ pub fn process_set_realm_config(
121121
}
122122

123123
// Update RealmConfig (Realm.config field)
124-
realm_data.config.community_mint_max_vote_weight_source =
125-
realm_config_args.community_mint_max_vote_weight_source;
124+
realm_data.config.community_mint_max_voter_weight_source =
125+
realm_config_args.community_mint_max_voter_weight_source;
126126

127127
realm_data.config.min_community_weight_to_create_governance =
128128
realm_config_args.min_community_weight_to_create_governance;

governance/program/src/state/enums.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,21 +225,20 @@ pub enum InstructionExecutionFlags {
225225
/// The source of max vote weight used for voting
226226
/// Values below 100% mint supply can be used when the governing token is fully minted but not distributed yet
227227
#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)]
228-
pub enum MintMaxVoteWeightSource {
228+
pub enum MintMaxVoterWeightSource {
229229
/// Fraction (10^10 precision) of the governing mint supply is used as max vote weight
230230
/// The default is 100% (10^10) to use all available mint supply for voting
231231
SupplyFraction(u64),
232232

233-
/// Absolute value, irrelevant of the actual mint supply, is used as max vote weight
234-
/// Note: this option is not implemented in the current version
233+
/// Absolute value, irrelevant of the actual mint supply, is used as max voter weight
235234
Absolute(u64),
236235
}
237236

238-
impl MintMaxVoteWeightSource {
237+
impl MintMaxVoterWeightSource {
239238
/// Base for mint supply fraction calculation
240239
pub const SUPPLY_FRACTION_BASE: u64 = 10_000_000_000;
241240

242241
/// 100% of mint supply
243-
pub const FULL_SUPPLY_FRACTION: MintMaxVoteWeightSource =
244-
MintMaxVoteWeightSource::SupplyFraction(MintMaxVoteWeightSource::SUPPLY_FRACTION_BASE);
242+
pub const FULL_SUPPLY_FRACTION: MintMaxVoterWeightSource =
243+
MintMaxVoterWeightSource::SupplyFraction(MintMaxVoterWeightSource::SUPPLY_FRACTION_BASE);
245244
}

governance/program/src/state/proposal.rs

Lines changed: 136 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::{
2424
error::GovernanceError,
2525
state::{
2626
enums::{
27-
GovernanceAccountType, InstructionExecutionFlags, MintMaxVoteWeightSource,
27+
GovernanceAccountType, InstructionExecutionFlags, MintMaxVoterWeightSource,
2828
ProposalState, TransactionExecutionStatus, VoteThreshold, VoteTipping,
2929
},
3030
governance::GovernanceConfig,
@@ -432,26 +432,24 @@ impl ProposalV2 {
432432
return Ok(governing_token_mint_supply);
433433
}
434434

435-
match realm_data.config.community_mint_max_vote_weight_source {
436-
MintMaxVoteWeightSource::SupplyFraction(fraction) => {
437-
if fraction == MintMaxVoteWeightSource::SUPPLY_FRACTION_BASE {
435+
let max_voter_weight = match realm_data.config.community_mint_max_voter_weight_source {
436+
MintMaxVoterWeightSource::SupplyFraction(fraction) => {
437+
if fraction == MintMaxVoterWeightSource::SUPPLY_FRACTION_BASE {
438438
return Ok(governing_token_mint_supply);
439439
}
440440

441-
let max_voter_weight = (governing_token_mint_supply as u128)
441+
(governing_token_mint_supply as u128)
442442
.checked_mul(fraction as u128)
443443
.unwrap()
444-
.checked_div(MintMaxVoteWeightSource::SUPPLY_FRACTION_BASE as u128)
445-
.unwrap() as u64;
446-
447-
// When the fraction is used it's possible we can go over the calculated max_vote_weight
448-
// and we have to adjust it in case more votes have been cast
449-
Ok(self.coerce_max_voter_weight(max_voter_weight, vote_kind))
450-
}
451-
MintMaxVoteWeightSource::Absolute(_) => {
452-
Err(GovernanceError::VoteWeightSourceNotSupported.into())
444+
.checked_div(MintMaxVoterWeightSource::SUPPLY_FRACTION_BASE as u128)
445+
.unwrap() as u64
453446
}
454-
}
447+
MintMaxVoterWeightSource::Absolute(value) => value,
448+
};
449+
450+
// When the fraction or absolute value is used it's possible we can go over the calculated max_vote_weight
451+
// and we have to adjust it in case more votes have been cast
452+
Ok(self.coerce_max_voter_weight(max_voter_weight, vote_kind))
455453
}
456454

457455
/// Adjusts max voter weight to ensure it's not lower than total cast votes
@@ -1057,7 +1055,7 @@ mod test {
10571055
use solana_program::clock::Epoch;
10581056

10591057
use crate::state::{
1060-
enums::{MintMaxVoteWeightSource, VoteThreshold},
1058+
enums::{MintMaxVoterWeightSource, VoteThreshold},
10611059
legacy::ProposalV1,
10621060
realm::RealmConfig,
10631061
vote_record::VoteChoice,
@@ -1158,8 +1156,8 @@ mod test {
11581156
legacy1: 0,
11591157
legacy2: 0,
11601158

1161-
community_mint_max_vote_weight_source:
1162-
MintMaxVoteWeightSource::FULL_SUPPLY_FRACTION,
1159+
community_mint_max_voter_weight_source:
1160+
MintMaxVoterWeightSource::FULL_SUPPLY_FRACTION,
11631161
min_community_weight_to_create_governance: 10,
11641162
},
11651163
voting_proposal_count: 0,
@@ -1801,9 +1799,9 @@ mod test {
18011799
let vote_tipping = VoteTipping::Strict;
18021800

18031801
// reduce max vote weight to 100
1804-
realm.config.community_mint_max_vote_weight_source =
1805-
MintMaxVoteWeightSource::SupplyFraction(
1806-
MintMaxVoteWeightSource::SUPPLY_FRACTION_BASE / 2,
1802+
realm.config.community_mint_max_voter_weight_source =
1803+
MintMaxVoterWeightSource::SupplyFraction(
1804+
MintMaxVoterWeightSource::SUPPLY_FRACTION_BASE / 2,
18071805
);
18081806

18091807
let max_voter_weight = proposal
@@ -1834,6 +1832,57 @@ mod test {
18341832
assert_eq!(proposal.max_vote_weight, Some(100));
18351833
}
18361834

1835+
#[test]
1836+
fn test_try_tip_vote_with_reduced_absolute_community_mint_max_vote_weight() {
1837+
// Arrange
1838+
let mut proposal = create_test_proposal();
1839+
1840+
proposal.options[0].vote_weight = 60;
1841+
proposal.deny_vote_weight = Some(10);
1842+
1843+
proposal.state = ProposalState::Voting;
1844+
1845+
let current_timestamp = 15_i64;
1846+
1847+
let community_token_supply = 200;
1848+
1849+
let mut realm = create_test_realm();
1850+
let governing_token_mint = proposal.governing_token_mint;
1851+
let vote_kind = VoteKind::Electorate;
1852+
let vote_tipping = VoteTipping::Strict;
1853+
1854+
// set max vote weight to 100
1855+
realm.config.community_mint_max_voter_weight_source =
1856+
MintMaxVoterWeightSource::Absolute(community_token_supply / 2);
1857+
1858+
let max_voter_weight = proposal
1859+
.get_max_voter_weight_from_mint_supply(
1860+
&realm,
1861+
&governing_token_mint,
1862+
community_token_supply,
1863+
&vote_kind,
1864+
)
1865+
.unwrap();
1866+
1867+
let vote_threshold = &VoteThreshold::YesVotePercentage(60);
1868+
let vote_kind = VoteKind::Electorate;
1869+
1870+
// Act
1871+
proposal
1872+
.try_tip_vote(
1873+
max_voter_weight,
1874+
&vote_tipping,
1875+
current_timestamp,
1876+
vote_threshold,
1877+
&vote_kind,
1878+
)
1879+
.unwrap();
1880+
1881+
// Assert
1882+
assert_eq!(proposal.state, ProposalState::Succeeded);
1883+
assert_eq!(proposal.max_vote_weight, Some(100));
1884+
}
1885+
18371886
#[test]
18381887
fn test_try_tip_vote_with_reduced_community_mint_max_vote_weight_and_vote_overflow() {
18391888
// Arrange
@@ -1854,9 +1903,9 @@ mod test {
18541903
let vote_tipping = VoteTipping::Strict;
18551904

18561905
// reduce max vote weight to 100
1857-
realm.config.community_mint_max_vote_weight_source =
1858-
MintMaxVoteWeightSource::SupplyFraction(
1859-
MintMaxVoteWeightSource::SUPPLY_FRACTION_BASE / 2,
1906+
realm.config.community_mint_max_voter_weight_source =
1907+
MintMaxVoterWeightSource::SupplyFraction(
1908+
MintMaxVoterWeightSource::SUPPLY_FRACTION_BASE / 2,
18601909
);
18611910

18621911
// vote above reduced supply
@@ -1890,6 +1939,60 @@ mod test {
18901939
assert_eq!(proposal.max_vote_weight, Some(130));
18911940
}
18921941

1942+
#[test]
1943+
fn test_try_tip_vote_with_reduced_absolute_mint_max_vote_weight_and_vote_overflow() {
1944+
// Arrange
1945+
let mut proposal = create_test_proposal();
1946+
1947+
// no vote weight
1948+
proposal.deny_vote_weight = Some(10);
1949+
1950+
proposal.state = ProposalState::Voting;
1951+
1952+
let current_timestamp = 15_i64;
1953+
1954+
let community_token_supply = 200;
1955+
1956+
let mut realm = create_test_realm();
1957+
let governing_token_mint = proposal.governing_token_mint;
1958+
let vote_kind = VoteKind::Electorate;
1959+
let vote_tipping = VoteTipping::Strict;
1960+
1961+
// reduce max vote weight to 100
1962+
realm.config.community_mint_max_voter_weight_source =
1963+
MintMaxVoterWeightSource::Absolute(community_token_supply / 2);
1964+
1965+
// vote above reduced supply
1966+
// Yes vote weight
1967+
proposal.options[0].vote_weight = 120;
1968+
1969+
let max_voter_weight = proposal
1970+
.get_max_voter_weight_from_mint_supply(
1971+
&realm,
1972+
&governing_token_mint,
1973+
community_token_supply,
1974+
&vote_kind,
1975+
)
1976+
.unwrap();
1977+
1978+
let vote_threshold = VoteThreshold::YesVotePercentage(60);
1979+
1980+
// Act
1981+
proposal
1982+
.try_tip_vote(
1983+
max_voter_weight,
1984+
&vote_tipping,
1985+
current_timestamp,
1986+
&vote_threshold,
1987+
&vote_kind,
1988+
)
1989+
.unwrap();
1990+
1991+
// Assert
1992+
assert_eq!(proposal.state, ProposalState::Succeeded);
1993+
assert_eq!(proposal.max_vote_weight, Some(130)); // Deny Vote 10 + Approve Vote 120
1994+
}
1995+
18931996
#[test]
18941997
fn test_try_tip_vote_for_council_vote_with_reduced_community_mint_max_vote_weight() {
18951998
// Arrange
@@ -1909,9 +2012,9 @@ mod test {
19092012
let vote_kind = VoteKind::Electorate;
19102013
let vote_tipping = VoteTipping::Strict;
19112014

1912-
realm.config.community_mint_max_vote_weight_source =
1913-
MintMaxVoteWeightSource::SupplyFraction(
1914-
MintMaxVoteWeightSource::SUPPLY_FRACTION_BASE / 2,
2015+
realm.config.community_mint_max_voter_weight_source =
2016+
MintMaxVoterWeightSource::SupplyFraction(
2017+
MintMaxVoterWeightSource::SUPPLY_FRACTION_BASE / 2,
19152018
);
19162019
realm.config.council_mint = Some(proposal.governing_token_mint);
19172020

@@ -1961,9 +2064,9 @@ mod test {
19612064
let vote_kind = VoteKind::Electorate;
19622065

19632066
// reduce max vote weight to 100
1964-
realm.config.community_mint_max_vote_weight_source =
1965-
MintMaxVoteWeightSource::SupplyFraction(
1966-
MintMaxVoteWeightSource::SUPPLY_FRACTION_BASE / 2,
2067+
realm.config.community_mint_max_voter_weight_source =
2068+
MintMaxVoterWeightSource::SupplyFraction(
2069+
MintMaxVoterWeightSource::SUPPLY_FRACTION_BASE / 2,
19672070
);
19682071

19692072
let max_voter_weight = proposal
@@ -2012,9 +2115,9 @@ mod test {
20122115
let vote_kind = VoteKind::Electorate;
20132116

20142117
// reduce max vote weight to 100
2015-
realm.config.community_mint_max_vote_weight_source =
2016-
MintMaxVoteWeightSource::SupplyFraction(
2017-
MintMaxVoteWeightSource::SUPPLY_FRACTION_BASE / 2,
2118+
realm.config.community_mint_max_voter_weight_source =
2119+
MintMaxVoterWeightSource::SupplyFraction(
2120+
MintMaxVoterWeightSource::SUPPLY_FRACTION_BASE / 2,
20182121
);
20192122

20202123
// vote above reduced supply

0 commit comments

Comments
 (0)