Skip to content
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: add get_proposal_status #527

Merged
merged 6 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions starknet/src/execution_strategies/eth_relayer.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,16 @@ mod EthRelayerExecutionStrategy {

send_message_to_l1_syscall(l1_destination, message_payload);
}

fn get_proposal_status(
self: @TContractState,
proposal: Proposal,
votes_for: u256,
votes_against: u256,
votes_abstain: u256,
) -> ProposalStatus {
panic_with_felt252('unimplemented');
ProposalStatus::Cancelled(())
}
}
}
5 changes: 4 additions & 1 deletion starknet/src/execution_strategies/simple_quorum.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ mod SimpleQuorumExecutionStrategy {
proposal: @Proposal,
votes_for: u256,
votes_against: u256,
votes_abstain: u256
votes_abstain: u256,
) -> ProposalStatus {
let accepted = _quorum_reached(self._quorum.read(), votes_for, votes_against, votes_abstain)
& _supported(votes_for, votes_against);
Expand Down Expand Up @@ -67,3 +67,6 @@ mod SimpleQuorumExecutionStrategy {
votes_for > votes_against
}
}
// TODO: add unit tests for get_proposal_status
Orland0x marked this conversation as resolved.
Show resolved Hide resolved


24 changes: 17 additions & 7 deletions starknet/src/execution_strategies/vanilla.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,8 @@ mod VanillaExecutionStrategy {
votes_abstain: u256,
payload: Array<felt252>
) {
// TODO: this is probably wrong.
let mut state: SimpleQuorumExecutionStrategy::ContractState =
SimpleQuorumExecutionStrategy::unsafe_new_contract_state();

let proposal_status = SimpleQuorumExecutionStrategy::get_proposal_status(
@state, @proposal, votes_for, votes_against, votes_abstain
);
let proposal_status = self
.get_proposal_status(proposal, votes_for, votes_against, votes_abstain,);
assert(
(proposal_status == ProposalStatus::Accepted(()))
| (proposal_status == ProposalStatus::VotingPeriodAccepted(())),
Expand All @@ -44,6 +39,21 @@ mod VanillaExecutionStrategy {
self._num_executed.write(self._num_executed.read() + 1);
}

fn get_proposal_status(
self: @ContractState,
proposal: Proposal,
votes_for: u256,
votes_against: u256,
votes_abstain: u256,
) -> ProposalStatus {
let mut state: SimpleQuorumExecutionStrategy::ContractState =
SimpleQuorumExecutionStrategy::unsafe_new_contract_state();

SimpleQuorumExecutionStrategy::get_proposal_status(
@state, @proposal, votes_for, votes_against, votes_abstain,
)
}

fn get_strategy_type(self: @ContractState) -> felt252 {
'SimpleQuorumVanilla'
}
Expand Down
10 changes: 9 additions & 1 deletion starknet/src/interfaces/i_execution_strategy.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use sx::types::Proposal;
use sx::types::{Proposal, ProposalStatus};

#[starknet::interface]
trait IExecutionStrategy<TContractState> {
Expand All @@ -11,5 +11,13 @@ trait IExecutionStrategy<TContractState> {
payload: Array<felt252>
);

fn get_proposal_status(
self: @TContractState,
proposal: Proposal,
votes_for: u256,
votes_against: u256,
votes_abstain: u256,
) -> ProposalStatus;

fn get_strategy_type(self: @TContractState) -> felt252;
}
24 changes: 18 additions & 6 deletions starknet/src/space/space.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use starknet::{ClassHash, ContractAddress};
use sx::types::{UserAddress, Strategy, Proposal, IndexedStrategy, Choice, UpdateSettingsCalldata};
use sx::types::{
UserAddress, Strategy, Proposal, IndexedStrategy, Choice, UpdateSettingsCalldata, ProposalStatus
};

#[starknet::interface]
trait ISpace<TContractState> {
Expand All @@ -19,8 +21,7 @@ trait ISpace<TContractState> {
// #[view]
// fn vote_registry(proposal_id: u256, voter: ContractAddress) -> bool;
fn proposals(self: @TContractState, proposal_id: u256) -> Proposal;
// #[view]
// fn get_proposal_status(proposal_id: u256) -> u8;
fn get_proposal_status(self: @TContractState, proposal_id: u256) -> ProposalStatus;

// Owner Actions
fn update_settings(ref self: TContractState, input: UpdateSettingsCalldata);
Expand Down Expand Up @@ -85,8 +86,8 @@ mod Space {
},
types::{
UserAddress, Choice, FinalizationStatus, Strategy, IndexedStrategy, Proposal,
PackedProposal, IndexedStrategyTrait, IndexedStrategyImpl, UpdateSettingsCalldata,
NoUpdateTrait, NoUpdateString,
ProposalStatus, PackedProposal, IndexedStrategyTrait, IndexedStrategyImpl,
UpdateSettingsCalldata, NoUpdateTrait, NoUpdateString,
},
utils::{
reinitializable::{Reinitializable}, ReinitializableImpl, bits::BitSetter,
Expand All @@ -98,7 +99,6 @@ mod Space {
external::ownable::Ownable
};


#[storage]
struct Storage {
_min_voting_duration: u32,
Expand Down Expand Up @@ -583,6 +583,18 @@ mod Space {
self._proposals.read(proposal_id)
}

fn get_proposal_status(self: @ContractState, proposal_id: u256) -> ProposalStatus {
let proposal = self._proposals.read(proposal_id);
assert_proposal_exists(@proposal);

let votes_for = self._vote_power.read((proposal_id, Choice::For(())));
let votes_against = self._vote_power.read((proposal_id, Choice::Against(())));
let votes_abstain = self._vote_power.read((proposal_id, Choice::Abstain(())));

IExecutionStrategyDispatcher { contract_address: proposal.execution_strategy }
.get_proposal_status(proposal, votes_for, votes_against, votes_abstain)
}

fn update_settings(ref self: ContractState, input: UpdateSettingsCalldata) {
//TODO: temporary component syntax
let state = Ownable::unsafe_new_contract_state();
Expand Down
22 changes: 22 additions & 0 deletions starknet/src/tests/mocks/executor.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ mod ExecutorExecutionStrategy {
call_contract_syscall(tx.target, tx.selector, tx.data.span()).unwrap();
}

fn get_proposal_status(
self: @ContractState,
proposal: Proposal,
votes_for: u256,
votes_against: u256,
votes_abstain: u256,
) -> ProposalStatus {
panic_with_felt252('unimplemented');
ProposalStatus::Cancelled(())
}

fn get_strategy_type(self: @ContractState) -> felt252 {
'Executor'
}
Expand Down Expand Up @@ -62,6 +73,17 @@ mod ExecutorWithoutTxExecutionStrategy {
payload: Array<felt252>
) {}

fn get_proposal_status(
self: @ContractState,
proposal: Proposal,
votes_for: u256,
votes_against: u256,
votes_abstain: u256,
) -> ProposalStatus {
panic_with_felt252('unimplemented');
ProposalStatus::Cancelled(())
}

fn get_strategy_type(self: @ContractState) -> felt252 {
'ExecutorWithoutTx'
}
Expand Down
52 changes: 52 additions & 0 deletions starknet/src/tests/test_space.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod tests {
};
use sx::tests::utils::strategy_trait::{StrategyImpl};
use sx::utils::constants::{PROPOSE_SELECTOR, VOTE_SELECTOR, UPDATE_PROPOSAL_SELECTOR};
use traits::Default;

use Space::Space as SpaceImpl;

Expand Down Expand Up @@ -406,6 +407,57 @@ mod tests {
space.execute(u256_from_felt252(1), vanilla_execution_strategy.params.clone());
}

#[test]
#[available_gas(10000000000)]
fn get_proposal_status() {
let config = setup();
let (factory, space) = deploy(@config);

let authenticator = IVanillaAuthenticatorDispatcher {
contract_address: *config.authenticators.at(0),
};

let quorum = u256_from_felt252(1);
let mut constructor_calldata = array![];
quorum.serialize(ref constructor_calldata);

let (vanilla_execution_strategy_address, _) = deploy_syscall(
VanillaExecutionStrategy::TEST_CLASS_HASH.try_into().unwrap(),
0,
constructor_calldata.span(),
false
)
.unwrap();
let vanilla_execution_strategy = StrategyImpl::from_address(
vanilla_execution_strategy_address
);
let author = UserAddress::Starknet(contract_address_const::<0x5678>());
let mut propose_calldata = array![];
author.serialize(ref propose_calldata);
vanilla_execution_strategy.serialize(ref propose_calldata);
ArrayTrait::<felt252>::new().serialize(ref propose_calldata);
ArrayTrait::<felt252>::new().serialize(ref propose_calldata);

// Create Proposal
authenticator.authenticate(space.contract_address, PROPOSE_SELECTOR, propose_calldata);

// We don't check the proposal status, simply call to make sure it doesn't revert
space.get_proposal_status(1);
}

#[test]
#[available_gas(10000000000)]
#[should_panic(
expected: ('Unknown enum indicator:', 0, 'ENTRYPOINT_FAILED')
)] // #default not working the the `ProposalStatus` enum
// #[should_panic(expected: ('Proposal does not exist', 'ENTRYPOINT_FAILED'))] // replace with this once default works
fn get_proposal_status_invalid_proposal_id() {
let config = setup();
let (factory, space) = deploy(@config);

space.get_proposal_status(0);
}

#[test]
#[available_gas(10000000000)]
#[should_panic(expected: ('Proposal has been finalized', 'ENTRYPOINT_FAILED'))]
Expand Down
3 changes: 2 additions & 1 deletion starknet/src/types/proposal_status.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[derive(Copy, Drop, Serde, PartialEq)]
#[derive(Copy, Drop, Default, Serde, PartialEq)]
enum ProposalStatus {
#[default]
VotingDelay: (),
VotingPeriod: (),
VotingPeriodAccepted: (),
Expand Down
Loading