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

Add Governor component #1180

Open
wants to merge 90 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
8277877
feat: add features
ericnordelo Sep 13, 2024
14b4b96
feat: remove access dual dispatchers (#1154)
ericnordelo Sep 25, 2024
485512f
feat: bump scarb
ericnordelo Sep 26, 2024
e9cd67d
feat: update CHANGELOG
ericnordelo Sep 26, 2024
762d9c9
Merge branch 'feat/bump-scarb-to-2.8.3' into feat/remove-mocks-from-r…
ericnordelo Sep 26, 2024
21b31d9
feat: add features
ericnordelo Sep 30, 2024
3ad8c7f
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into r…
ericnordelo Oct 2, 2024
b8a3ed5
feat: remove account dual dispatchers (#1168)
ericnordelo Oct 2, 2024
a4d5d77
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Oct 2, 2024
d44754c
feat: move mocks to test_common
ericnordelo Oct 3, 2024
094081c
Remove token dual dispatchers (#1175)
ericnordelo Oct 3, 2024
e738107
feat: update docs
ericnordelo Oct 4, 2024
75974fd
feat: update CHANGELOG
ericnordelo Oct 4, 2024
586357a
fix: typo
ericnordelo Oct 4, 2024
b2ba912
fix: mod
ericnordelo Oct 4, 2024
fe6d846
feat: remove unused imports
ericnordelo Oct 4, 2024
de11d9b
fix: README
ericnordelo Oct 4, 2024
57c9003
Merge branch 'docs/remove-dual-dispatchers' into feat/remove-mocks-fr…
ericnordelo Oct 4, 2024
55225bc
feat: move mocks into test_common
ericnordelo Oct 4, 2024
72451fa
feat: remove mocks from release target
ericnordelo Oct 4, 2024
fda9095
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Oct 6, 2024
f575ba8
fix: mock
ericnordelo Oct 6, 2024
86508c6
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Oct 7, 2024
1c5c522
fix: imports
ericnordelo Oct 7, 2024
420d364
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Oct 7, 2024
f14f635
feat: bumo scarb and remove assert_macros from manifest
ericnordelo Oct 7, 2024
8a763e0
feat: re-add assert_macros
ericnordelo Oct 7, 2024
46fd0ac
feat: add test target names
ericnordelo Oct 8, 2024
182f470
docs: update index
ericnordelo Oct 8, 2024
6d68bd0
feat: add interface
ericnordelo Oct 11, 2024
7117e98
feat: add double ended queue struct
ericnordelo Oct 11, 2024
5eb6f28
feat: add proposal core
ericnordelo Oct 11, 2024
200466a
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Oct 11, 2024
8b35ed1
+
ericnordelo Oct 16, 2024
8b30671
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Oct 16, 2024
bf74d7f
feat: add extension traits
ericnordelo Oct 16, 2024
1545036
feat: add hash_proposal
ericnordelo Oct 16, 2024
14f5792
feat: add state internal function
ericnordelo Oct 16, 2024
6097691
feat: add bytearray to utils
ericnordelo Oct 17, 2024
a7dbea2
fix: bytearray trait types
ericnordelo Oct 17, 2024
4fc97a0
feat: apply stash
ericnordelo Oct 18, 2024
6df91a8
feat: add propose mechanism
ericnordelo Oct 21, 2024
e7127f0
feat: add queue mechanism
ericnordelo Oct 21, 2024
aa121b6
feat: add execute and cancel
ericnordelo Oct 21, 2024
7f0fde6
feat: add main trait
ericnordelo Oct 22, 2024
df44b1c
feat: finish first extension
ericnordelo Oct 28, 2024
d7722c8
feat: add votes quorum fractional extension main logic
ericnordelo Oct 28, 2024
fab1a6d
feat: add settings extension
ericnordelo Oct 30, 2024
86d5954
feat: add governor votes extension
ericnordelo Oct 30, 2024
7335f0f
feat: add core execution extension
ericnordelo Oct 30, 2024
7e45786
feat: add timelock execution extension
ericnordelo Oct 30, 2024
50f29c8
refactor: dependencies
ericnordelo Nov 4, 2024
5ba4380
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Nov 4, 2024
c666a12
feat: add mock
ericnordelo Nov 4, 2024
e893503
fix: linter
ericnordelo Nov 4, 2024
941ea68
fix: comment
ericnordelo Nov 4, 2024
8774e59
feat: add some tests
ericnordelo Nov 6, 2024
a4ee53f
fix: linter
ericnordelo Nov 6, 2024
5b081ff
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Nov 8, 2024
001715d
refactor: comments
ericnordelo Nov 8, 2024
35e0319
fix: import path
ericnordelo Nov 8, 2024
42a70b5
fix: test
ericnordelo Nov 8, 2024
1d2e400
feat: add relay mechanism
ericnordelo Nov 8, 2024
baee816
fix: conditions
ericnordelo Nov 8, 2024
40ad6a3
feat: add more tests
ericnordelo Nov 11, 2024
f749245
fix: linter
ericnordelo Nov 11, 2024
2ec9098
feat: add more tests
ericnordelo Nov 11, 2024
b928ecf
feat: add more tests
ericnordelo Nov 11, 2024
2bc9961
Update packages/governance/src/governor/interface.cairo
ericnordelo Nov 12, 2024
f01ad5c
Update packages/governance/src/governor/interface.cairo
ericnordelo Nov 12, 2024
5feb157
Update packages/governance/src/governor/governor.cairo
ericnordelo Nov 12, 2024
c5fdf45
Update packages/governance/src/governor/governor.cairo
ericnordelo Nov 12, 2024
c717405
Update packages/governance/src/governor/governor.cairo
ericnordelo Nov 12, 2024
0152aa9
Update packages/governance/src/governor/proposal_core.cairo
ericnordelo Nov 12, 2024
1be0449
feat: apply review updates
ericnordelo Nov 12, 2024
502389f
Merge branch 'feat/governance2-#294' of github.com:ericnordelo/cairo-…
ericnordelo Nov 12, 2024
70a2785
fix: linter
ericnordelo Nov 12, 2024
3c67aac
fix: bytearray
ericnordelo Nov 12, 2024
81aced2
feat: add more tests
ericnordelo Nov 13, 2024
85b032c
feat: add more tests
ericnordelo Nov 14, 2024
8d96ff2
Update packages/utils/src/bytearray.cairo
ericnordelo Nov 14, 2024
b43bc0d
feat: apply review updates
ericnordelo Nov 14, 2024
f080f95
Merge branch 'feat/governance2-#294' of github.com:ericnordelo/cairo-…
ericnordelo Nov 14, 2024
4936537
Merge branch 'main' of github.com:OpenZeppelin/cairo-contracts into f…
ericnordelo Nov 14, 2024
bdcdec4
feat: add cast vote by sig
ericnordelo Nov 14, 2024
ffaac53
feat: add more tests
ericnordelo Nov 14, 2024
cd52a53
feat: add more tests
ericnordelo Nov 14, 2024
bbe27a9
fix: remove import
ericnordelo Nov 14, 2024
4944d6d
feat: add yet more tests
ericnordelo Nov 14, 2024
92cd728
feat: update CHANGELOG
ericnordelo Nov 15, 2024
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 Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,15 @@ dependencies = [

[[package]]
name = "snforge_scarb_plugin"
version = "0.31.0"
version = "0.32.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:1fce075fcbf7fce1b0935f6f9a034549704837fb221da212d3b6e9134cebfdaa"
checksum = "sha256:e5a0e80294b1f5f00955c614ee3fc94c843ff0d27935693c3598d0ac8d79250a"

[[package]]
name = "snforge_std"
version = "0.31.0"
version = "0.32.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:60ac980b297281f9a59a5f1668cb56bdea1b28fd2f8008008270f9a3c91ad3ba"
checksum = "sha256:0e3cb45c6276334fd142a77212f0592d55744f1c022b7a63f20bcd79d0ce3927"
dependencies = [
"snforge_scarb_plugin",
]
2 changes: 1 addition & 1 deletion Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ keywords = [
[workspace.dependencies]
assert_macros = "2.8.4"
starknet = "2.8.4"
snforge_std = "0.31.0"
snforge_std = "0.32.0"

[dependencies]
starknet.workspace = true
Expand Down
1 change: 1 addition & 0 deletions packages/governance/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ casm = false
name = "openzeppelin_governance_unittest"
build-external-contracts = [
"openzeppelin_test_common::mocks::account::SnakeAccountMock",
"openzeppelin_test_common::mocks::governor::GovernorMock",
"openzeppelin_test_common::mocks::timelock::TimelockControllerMock",
"openzeppelin_test_common::mocks::timelock::MockContract",
"openzeppelin_test_common::mocks::timelock::TimelockAttackerMock",
Expand Down
7 changes: 7 additions & 0 deletions packages/governance/src/governor.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub mod extensions;
pub mod governor;
pub mod interface;
pub mod proposal_core;

pub use governor::{GovernorComponent, DefaultConfig};
pub use proposal_core::ProposalCore;
14 changes: 14 additions & 0 deletions packages/governance/src/governor/extensions.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pub mod governor_core_execution;
pub mod governor_counting_simple;
pub mod governor_settings;
pub mod governor_timelock_execution;
pub mod governor_votes;
pub mod governor_votes_quorum_fraction;
pub mod interface;

pub use governor_core_execution::GovernorCoreExecutionComponent;
pub use governor_counting_simple::GovernorCountingSimpleComponent;
pub use governor_settings::GovernorSettingsComponent;
pub use governor_timelock_execution::GovernorTimelockExecutionComponent;
pub use governor_votes::GovernorVotesComponent;
pub use governor_votes_quorum_fraction::GovernorVotesQuorumFractionComponent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts for Cairo v0.19.0
// (governance/governor/extensions/governor_core_execution.cairo)

/// # GovernorCoreExecution Component
///
/// Extension of GovernorComponent providing an execution mechanism directly through
/// the Governor itself. For a timelocked execution mechanism, see
/// GovernorTimelockExecutionComponent.
#[starknet::component]
pub mod GovernorCoreExecutionComponent {
use crate::governor::GovernorComponent::{
InternalExtendedTrait, ComponentState as GovernorComponentState
};
use crate::governor::GovernorComponent;
use crate::governor::interface::ProposalState;
use openzeppelin_introspection::src5::SRC5Component;
use starknet::account::Call;
use starknet::{ContractAddress, SyscallResultTrait};

#[storage]
pub struct Storage {}

//
// Extensions
//

pub impl GovernorExecution<
TContractState,
+GovernorComponent::HasComponent<TContractState>,
+GovernorComponent::GovernorCountingTrait<TContractState>,
+GovernorComponent::GovernorSettingsTrait<TContractState>,
+GovernorComponent::GovernorVotesTrait<TContractState>,
+SRC5Component::HasComponent<TContractState>,
impl GovernorCoreExecution: HasComponent<TContractState>,
+Drop<TContractState>
> of GovernorComponent::GovernorExecutionTrait<TContractState> {
/// See `GovernorComponent::GovernorExecutionTrait::state`.
fn state(
self: @GovernorComponentState<TContractState>, proposal_id: felt252
) -> ProposalState {
self._state(proposal_id)
}

/// See `GovernorComponent::GovernorExecutionTrait::executor`.
fn executor(self: @GovernorComponentState<TContractState>) -> ContractAddress {
starknet::get_contract_address()
}

/// See `GovernorComponent::GovernorExecutionTrait::execute_operations`.
fn execute_operations(
ref self: GovernorComponentState<TContractState>,
proposal_id: felt252,
calls: Span<Call>,
description_hash: felt252
) {
for call in calls {
let Call { to, selector, calldata } = *call;
starknet::syscalls::call_contract_syscall(to, selector, calldata).unwrap_syscall();
};
}

/// See `GovernorComponent::GovernorExecutionTrait::queue_operations`.
fn queue_operations(
ref self: GovernorComponentState<TContractState>,
proposal_id: felt252,
calls: Span<Call>,
description_hash: felt252
) -> u64 {
0
}

/// See `GovernorComponent::GovernorExecutionTrait::proposal_needs_queuing`.
fn proposal_needs_queuing(
self: @GovernorComponentState<TContractState>, proposal_id: felt252
) -> bool {
false
}

/// See `GovernorComponent::GovernorExecutionTrait::cancel_operations`.
fn cancel_operations(
ref self: GovernorComponentState<TContractState>,
proposal_id: felt252,
description_hash: felt252
) {
self._cancel(proposal_id, description_hash);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts for Cairo v0.19.0
// (governance/governor/extensions/governor_counting_simple.cairo)

/// # GovernorCountingSimple Component
///
/// Extension of GovernorComponent for simple, 3 options, vote counting.
ericnordelo marked this conversation as resolved.
Show resolved Hide resolved
#[starknet::component]
pub mod GovernorCountingSimpleComponent {
use crate::governor::GovernorComponent::{
InternalTrait, ComponentState as GovernorComponentState
};
use crate::governor::GovernorComponent;
use openzeppelin_introspection::src5::SRC5Component;
use starknet::ContractAddress;
use starknet::storage::{Map, StoragePathEntry, StorageMapReadAccess, StorageMapWriteAccess};
use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess};

type ProposalId = felt252;
immrsd marked this conversation as resolved.
Show resolved Hide resolved

#[storage]
pub struct Storage {
pub Governor_proposals_votes: Map<ProposalId, ProposalVote>,
}

/// Supported vote types.
pub enum VoteType {
Against,
For,
Abstain,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Abstain,
Abstain

}

impl U8TryIntoVoteType of TryInto<u8, VoteType> {
fn try_into(self: u8) -> Option<VoteType> {
match self {
0 => Option::Some(VoteType::Against),
1 => Option::Some(VoteType::For),
2 => Option::Some(VoteType::Abstain),
_ => Option::None,
}
}
}

#[starknet::storage_node]
pub struct ProposalVote {
pub against_votes: u256,
pub for_votes: u256,
pub abstain_votes: u256,
pub has_voted: Map<ContractAddress, bool>
}

mod Errors {
pub const ALREADY_CAST_VOTE: felt252 = 'Already cast vote';
pub const INVALID_VOTE_TYPE: felt252 = 'Invalid vote type';
}

//
// Extensions
//

pub impl GovernorCounting<
TContractState,
+GovernorComponent::HasComponent<TContractState>,
+GovernorComponent::GovernorQuorumTrait<TContractState>,
+SRC5Component::HasComponent<TContractState>,
impl GovernorCountingSimple: HasComponent<TContractState>,
+Drop<TContractState>
> of GovernorComponent::GovernorCountingTrait<TContractState> {
/// See `GovernorComponent::GovernorCountingTrait::counting_mode`.
fn counting_mode(self: @GovernorComponentState<TContractState>) -> ByteArray {
return "support=bravo&quorum=for,abstain";
}

/// See `GovernorComponent::GovernorCountingTrait::count_vote`.
///
/// In this module, the support follows the `VoteType` enum (from Governor Bravo).
fn count_vote(
ref self: GovernorComponentState<TContractState>,
proposal_id: felt252,
account: ContractAddress,
support: u8,
total_weight: u256,
params: @ByteArray
) -> u256 {
let mut contract = self.get_contract_mut();
let mut this_component = GovernorCountingSimple::get_component_mut(ref contract);

let proposal_votes = this_component.Governor_proposals_votes.entry(proposal_id);
assert(!proposal_votes.has_voted.read(account), Errors::ALREADY_CAST_VOTE);

proposal_votes.has_voted.write(account, true);

let support: VoteType = support.try_into().expect(Errors::INVALID_VOTE_TYPE);
match support {
VoteType::Against => {
let current_votes = proposal_votes.against_votes.read();
proposal_votes.against_votes.write(current_votes + total_weight);
},
VoteType::For => {
let current_votes = proposal_votes.for_votes.read();
proposal_votes.for_votes.write(current_votes + total_weight);
},
VoteType::Abstain => {
let current_votes = proposal_votes.abstain_votes.read();
proposal_votes.abstain_votes.write(current_votes + total_weight);
}
}
total_weight
}

/// See `GovernorComponent::GovernorCountingTrait::has_voted`.
fn has_voted(
self: @GovernorComponentState<TContractState>,
proposal_id: felt252,
account: ContractAddress
) -> bool {
let contract = self.get_contract();
let this_component = GovernorCountingSimple::get_component(contract);
let proposal_votes = this_component.Governor_proposals_votes.entry(proposal_id);

proposal_votes.has_voted.read(account)
}

/// See `GovernorComponent::GovernorCountingTrait::quorum_reached`.
fn quorum_reached(
self: @GovernorComponentState<TContractState>, proposal_id: felt252
) -> bool {
let contract = self.get_contract();
let this_component = GovernorCountingSimple::get_component(contract);

let proposal_votes = this_component.Governor_proposals_votes.entry(proposal_id);
let snapshot = self._proposal_snapshot(proposal_id);

self.quorum(snapshot) <= proposal_votes.for_votes.read()
+ proposal_votes.abstain_votes.read()
}

/// See `GovernorComponent::GovernorCountingTrait::vote_succeeded`.
///
/// In this module, the `for_votes` must be strictly over the `against_votes`.
fn vote_succeeded(
self: @GovernorComponentState<TContractState>, proposal_id: felt252
) -> bool {
let contract = self.get_contract();
let this_component = GovernorCountingSimple::get_component(contract);
let proposal_votes = this_component.Governor_proposals_votes.entry(proposal_id);

proposal_votes.for_votes.read() > proposal_votes.against_votes.read()
}
}
}
Loading