-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: simple majority execution #534
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
mod vanilla; | ||
|
||
mod no_execution_simple_majority; | ||
mod simple_quorum; | ||
|
||
mod eth_relayer; |
46 changes: 46 additions & 0 deletions
46
starknet/src/execution_strategies/no_execution_simple_majority.cairo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/// Execution strategy that will not execute anything but ensure that the | ||
/// proposal is in the status `Accepted` or `VotingPeriodAccepted` by following | ||
/// the `SimpleMajority` rule (`votes_for > votes_against`). | ||
#[starknet::contract] | ||
mod NoExecutionSimpleMajorityExecutionStrategy { | ||
use sx::interfaces::{IExecutionStrategy}; | ||
use sx::types::{Proposal, ProposalStatus}; | ||
use sx::utils::simple_majority; | ||
|
||
#[storage] | ||
struct Storage {} | ||
|
||
#[external(v0)] | ||
impl NoExecutionSimpleMajorityExecutionStrategy of IExecutionStrategy<ContractState> { | ||
fn execute( | ||
ref self: ContractState, | ||
proposal: Proposal, | ||
votes_for: u256, | ||
votes_against: u256, | ||
votes_abstain: u256, | ||
payload: Array<felt252> | ||
) { | ||
let proposal_status = self | ||
.get_proposal_status(proposal, votes_for, votes_against, votes_abstain,); | ||
assert( | ||
(proposal_status == ProposalStatus::Accepted(())) | ||
| (proposal_status == ProposalStatus::VotingPeriodAccepted(())), | ||
'Invalid Proposal Status' | ||
); | ||
} | ||
|
||
fn get_proposal_status( | ||
self: @ContractState, | ||
proposal: Proposal, | ||
votes_for: u256, | ||
votes_against: u256, | ||
votes_abstain: u256, | ||
) -> ProposalStatus { | ||
simple_majority::get_proposal_status(@proposal, votes_for, votes_against, votes_abstain) | ||
} | ||
|
||
fn get_strategy_type(self: @ContractState) -> felt252 { | ||
'NoExecutionSimpleMajority' | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
use starknet::info; | ||
use sx::types::{Proposal, FinalizationStatus, ProposalStatus}; | ||
|
||
/// Returns the status of a proposal, according to a 'Simple Majority' rule. | ||
/// 'Simple Majority' is defined like so: a proposal is accepted if there are more `votes_for` than `votes_against`. | ||
/// So, a proposal will return Accepted if `max_end_timestamp` has been reached, and `votes_for > votes_agasint`. | ||
fn get_proposal_status( | ||
proposal: @Proposal, votes_for: u256, votes_against: u256, votes_abstain: u256, | ||
) -> ProposalStatus { | ||
let accepted = votes_for > votes_against; | ||
|
||
let timestamp = info::get_block_timestamp().try_into().unwrap(); | ||
if *proposal.finalization_status == FinalizationStatus::Cancelled(()) { | ||
ProposalStatus::Cancelled(()) | ||
} else if *proposal.finalization_status == FinalizationStatus::Executed(()) { | ||
ProposalStatus::Executed(()) | ||
} else if timestamp < *proposal.start_timestamp { | ||
ProposalStatus::VotingDelay(()) | ||
} else if timestamp < *proposal.max_end_timestamp { | ||
ProposalStatus::VotingPeriod(()) | ||
} else if accepted { | ||
ProposalStatus::Accepted(()) | ||
} else { | ||
ProposalStatus::Rejected(()) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::{get_proposal_status}; | ||
use sx::types::{Proposal, proposal::ProposalDefault, FinalizationStatus, ProposalStatus}; | ||
|
||
#[test] | ||
#[available_gas(10000000)] | ||
fn cancelled() { | ||
let mut proposal = ProposalDefault::default(); | ||
proposal.finalization_status = FinalizationStatus::Cancelled(()); | ||
let votes_for = 0; | ||
let votes_against = 0; | ||
let votes_abstain = 0; | ||
let result = get_proposal_status(@proposal, votes_for, votes_against, votes_abstain); | ||
assert(result == ProposalStatus::Cancelled(()), 'failed cancelled'); | ||
} | ||
|
||
#[test] | ||
#[available_gas(10000000)] | ||
fn executed() { | ||
let mut proposal = ProposalDefault::default(); | ||
proposal.finalization_status = FinalizationStatus::Executed(()); | ||
let votes_for = 0; | ||
let votes_against = 0; | ||
let votes_abstain = 0; | ||
let result = get_proposal_status(@proposal, votes_for, votes_against, votes_abstain); | ||
assert(result == ProposalStatus::Executed(()), 'failed executed'); | ||
} | ||
|
||
#[test] | ||
#[available_gas(10000000)] | ||
fn voting_delay() { | ||
let mut proposal = ProposalDefault::default(); | ||
proposal.start_timestamp = 42424242; | ||
let votes_for = 0; | ||
let votes_against = 0; | ||
let votes_abstain = 0; | ||
let result = get_proposal_status(@proposal, votes_for, votes_against, votes_abstain); | ||
assert(result == ProposalStatus::VotingDelay(()), 'failed voting_delay'); | ||
} | ||
|
||
#[test] | ||
#[available_gas(10000000)] | ||
fn voting_period() { | ||
let mut proposal = ProposalDefault::default(); | ||
proposal.min_end_timestamp = 42424242; | ||
proposal.max_end_timestamp = proposal.min_end_timestamp + 1; | ||
let votes_for = 0; | ||
let votes_against = 0; | ||
let votes_abstain = 0; | ||
let result = get_proposal_status(@proposal, votes_for, votes_against, votes_abstain); | ||
assert(result == ProposalStatus::VotingPeriod(()), 'failed min_end_timestamp'); | ||
} | ||
|
||
#[test] | ||
#[available_gas(10000000)] | ||
fn early_end_does_not_work() { | ||
let mut proposal = ProposalDefault::default(); | ||
proposal.max_end_timestamp = 10; | ||
let votes_for = 1; | ||
let votes_against = 0; | ||
let votes_abstain = 0; | ||
let result = get_proposal_status(@proposal, votes_for, votes_against, votes_abstain); | ||
assert(result == ProposalStatus::VotingPeriod(()), 'failed shortcut_accepted'); | ||
} | ||
|
||
#[test] | ||
#[available_gas(10000000)] | ||
fn balanced() { | ||
let mut proposal = ProposalDefault::default(); | ||
let votes_for = 42; | ||
let votes_against = 42; | ||
let votes_abstain = 0; | ||
let result = get_proposal_status(@proposal, votes_for, votes_against, votes_abstain); | ||
assert(result == ProposalStatus::Rejected(()), 'failed balanced'); | ||
} | ||
|
||
#[test] | ||
#[available_gas(10000000)] | ||
fn accepted() { | ||
let mut proposal = ProposalDefault::default(); | ||
let votes_for = 10; | ||
let votes_against = 9; | ||
let votes_abstain = 0; | ||
let result = get_proposal_status(@proposal, votes_for, votes_against, votes_abstain); | ||
assert(result == ProposalStatus::Accepted(()), 'failed accepted'); | ||
} | ||
|
||
#[test] | ||
#[available_gas(10000000)] | ||
fn accepted_with_abstains() { | ||
let mut proposal = ProposalDefault::default(); | ||
let votes_for = 2; | ||
let votes_against = 1; | ||
let votes_abstain = 10; | ||
let result = get_proposal_status(@proposal, votes_for, votes_against, votes_abstain); | ||
assert(result == ProposalStatus::Accepted(()), 'failed accepted abstains'); | ||
} | ||
|
||
#[test] | ||
#[available_gas(10000000)] | ||
fn rejected_only_againsts() { | ||
let mut proposal = ProposalDefault::default(); | ||
let votes_for = 0; | ||
let votes_against = 1; | ||
let votes_abstain = 0; | ||
let result = get_proposal_status(@proposal, votes_for, votes_against, votes_abstain); | ||
assert(result == ProposalStatus::Rejected(()), 'failed rejected'); | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we shouldnt have a
VotingPeriodAccepted
status with the strategyThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think just ignore
min_end_timestamp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm so the rationale behind that was:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the thing is min/max are space params they cant be set just for proposals with this strategy.
The goal of a 'simple majority' strategy is to find the majority of VP over the voting period. i dont think it would ever make sense to have an early end. So if spaces are using this execution strategy in combination with others, they would need to update space params often which would be annoying/ error prone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair enough ! f6ac7e0