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

Allow describing proposals on-chain #36

Merged
merged 2 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 4 additions & 4 deletions src/airdrop_claim_check.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use starknet::{ContractAddress};
use governance::airdrop::{IAirdropDispatcher};
use starknet::{ContractAddress};

#[derive(Serde, Copy, Drop)]
struct CheckParams {
Expand All @@ -21,11 +21,11 @@ trait IAirdropClaimCheck<TContractState> {

#[starknet::contract]
mod AirdropClaimCheck {
use super::{IAirdropClaimCheck, IAirdropDispatcher, CheckParams, CheckResult};
use governance::airdrop::{IAirdropDispatcherTrait};
use governance::interfaces::erc20::{IERC20Dispatcher, IERC20DispatcherTrait};
use core::array::{SpanTrait};
use core::option::{OptionTrait};
use governance::airdrop::{IAirdropDispatcherTrait};
use governance::interfaces::erc20::{IERC20Dispatcher, IERC20DispatcherTrait};
use super::{IAirdropClaimCheck, IAirdropDispatcher, CheckParams, CheckResult};

#[storage]
struct Storage {}
Expand Down
22 changes: 21 additions & 1 deletion src/governor.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::array::{Array};
use core::byte_array::{ByteArray};
use core::integer::{u128_safe_divmod};
use core::option::{Option, OptionTrait};
use core::traits::{Into, TryInto};
Expand Down Expand Up @@ -49,6 +50,9 @@ pub trait IGovernor<TContractState> {
// Execute the given proposal.
fn execute(ref self: TContractState, call: Call) -> Span<felt252>;

// Attaches the given text to the proposal. Simply emits an event containing the proposal description.
fn describe(ref self: TContractState, id: felt252, description: ByteArray);

// Get the configuration for this governor contract.
fn get_staker(self: @TContractState) -> IStakerDispatcher;

Expand All @@ -68,7 +72,7 @@ pub mod Governor {
use starknet::{get_block_timestamp, get_caller_address, contract_address_const};
use super::{
IStakerDispatcher, ContractAddress, Array, IGovernor, Config, ProposalInfo, Call,
ExecutionState
ExecutionState, ByteArray
};


Expand All @@ -79,6 +83,12 @@ pub mod Governor {
pub call: Call,
}

#[derive(starknet::Event, Drop, Debug, PartialEq)]
pub struct Described {
pub id: felt252,
pub description: ByteArray,
}

#[derive(starknet::Event, Drop)]
pub struct Voted {
pub id: felt252,
Expand All @@ -101,6 +111,7 @@ pub mod Governor {
#[event]
enum Event {
Proposed: Proposed,
Described: Described,
Voted: Voted,
Canceled: Canceled,
Executed: Executed,
Expand Down Expand Up @@ -183,6 +194,15 @@ pub mod Governor {
id
}

fn describe(ref self: ContractState, id: felt252, description: ByteArray) {
let proposal = self.proposals.read(id);
assert(proposal.proposer.is_non_zero(), 'DOES_NOT_EXIST');
assert(proposal.proposer == get_caller_address(), 'NOT_PROPOSER');
assert(proposal.execution_state.executed.is_zero(), 'ALREADY_EXECUTED');
assert(proposal.execution_state.canceled.is_zero(), 'PROPOSAL_CANCELED');
self.emit(Described { id, description });
}

fn vote(ref self: ContractState, id: felt252, yea: bool) {
let mut proposal = self.proposals.read(id);

Expand Down
49 changes: 48 additions & 1 deletion src/governor_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ use governance::timelock_test::{single_call, transfer_call, deploy as deploy_tim
use starknet::account::{Call};
use starknet::{
get_contract_address, syscalls::deploy_syscall, ClassHash, contract_address_const,
ContractAddress, get_block_timestamp, testing::{set_block_timestamp, set_contract_address}
ContractAddress, get_block_timestamp,
testing::{set_block_timestamp, set_contract_address, pop_log}
};


Expand Down Expand Up @@ -250,6 +251,52 @@ fn test_anyone_can_vote() {
assert_eq!(proposal.nay, 0);
}

#[test]
fn test_describe_proposal_successful() {
let (staker, token, governor, _config) = setup();
let id = create_proposal(governor, token, staker);

set_contract_address(proposer());
governor
.describe(
id,
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
);
pop_log::<Governor::Proposed>(governor.contract_address).unwrap();
assert_eq!(
pop_log::<Governor::Described>(governor.contract_address).unwrap(),
Governor::Described {
id,
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
);
}

#[test]
#[should_panic(expected: ('NOT_PROPOSER', 'ENTRYPOINT_FAILED'))]
fn test_describe_proposal_fails_for_unknown_proposal() {
let (staker, token, governor, _config) = setup();
let id = create_proposal(governor, token, staker);
governor.describe(id, "I am not the proposer");
}

#[test]
#[should_panic(expected: ('PROPOSAL_CANCELED', 'ENTRYPOINT_FAILED'))]
fn test_describe_proposal_fails_if_canceled() {
let (staker, token, governor, _config) = setup();
let id = create_proposal(governor, token, staker);
set_contract_address(proposer());
governor.cancel(id);
governor.describe(id, "This proposal is canceled");
}

#[test]
#[should_panic(expected: ('DOES_NOT_EXIST', 'ENTRYPOINT_FAILED'))]
fn test_describe_proposal_fails_if_not_proposer() {
let (_staker, _token, governor, _config) = setup();
governor.describe(123, "This proposal does not exist");
}

#[test]
fn test_vote_no_staking_after_period_starts() {
let (staker, token, governor, config) = setup();
Expand Down
2 changes: 1 addition & 1 deletion src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod airdrop_claim_check;
pub mod airdrop;
mod airdrop_claim_check;

#[cfg(test)]
pub(crate) mod airdrop_test;
Expand Down
Loading