-
Notifications
You must be signed in to change notification settings - Fork 349
/
governance.cairo
155 lines (129 loc) · 4.47 KB
/
governance.cairo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
%lang starknet
from starkware.cairo.common.bool import FALSE, TRUE
from starkware.cairo.common.cairo_builtins import HashBuiltin
from starkware.cairo.common.math import assert_not_equal, assert_not_zero
from starkware.starknet.common.syscalls import get_caller_address
@storage_var
func governance_initialized() -> (initialized: felt) {
}
@storage_var
func governors(account: felt) -> (active_governor: felt) {
}
@storage_var
func candidates(account: felt) -> (governance_candidate: felt) {
}
// Emitted upon nomination of a new governor.
@event
func governor_nominated(new_governor_nominee: felt, nominated_by: felt) {
}
// Emitted upon cancellation of a new govoernor nomination.
@event
func nomination_cancelled(cancelled_nominee: felt, cancelled_by: felt) {
}
// Emitted upon govoernor removal.
@event
func governor_removed(removed_governor: felt, removed_by: felt) {
}
// Emitted upon a new governor accepting governance.
@event
func governance_accepted(new_governor: felt) {
}
@view
func is_governor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
account: felt
) -> (is_governor_: felt) {
let (is_governor_) = governors.read(account=account);
return (is_governor_=is_governor_);
}
@external
func init_governance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
let (already_init: felt) = governance_initialized.read();
with_attr error_message("ALREADY_INITIALIZED") {
assert already_init = FALSE;
}
let (caller: felt) = get_caller_address();
// Prevent nomination of zero address.
with_attr error_message("ZERO_ADDRESS") {
assert_not_zero(caller);
}
governance_initialized.write(TRUE);
governors.write(account=caller, value=TRUE);
governor_nominated.emit(new_governor_nominee=caller, nominated_by=caller);
governance_accepted.emit(new_governor=caller);
return ();
}
@external
func nominate_new_governor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
nominee: felt
) {
only_governor();
// Check that the nominee is not already a governor.
let (is_governor_) = is_governor(nominee);
with_attr error_message("ALREADY_GOVERNOR") {
assert is_governor_ = FALSE;
}
// Prevent nomination of zero address.
with_attr error_message("ZERO_ADDRESS") {
assert_not_zero(nominee);
}
// Set the nominee as a candidate.
candidates.write(account=nominee, value=TRUE);
let (caller: felt) = get_caller_address();
governor_nominated.emit(new_governor_nominee=nominee, nominated_by=caller);
return ();
}
@external
func cancel_nomination{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
cancelee: felt
) {
only_governor();
// Quietly exit if not a candidate.
let (is_candidate) = candidates.read(account=cancelee);
if (is_candidate == FALSE) {
return ();
}
// Clear candidate flag and emit event.
candidates.write(account=cancelee, value=FALSE);
let (caller: felt) = get_caller_address();
nomination_cancelled.emit(cancelled_nominee=cancelee, cancelled_by=caller);
return ();
}
@external
func remove_governor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
removee: felt
) {
only_governor();
let (is_governor_) = is_governor(removee);
with_attr error_message("NOT_A_GOVERNOR") {
assert is_governor_ = TRUE;
}
let (caller: felt) = get_caller_address();
with_attr error_message("CANNOT_SELF_REMOVE") {
assert_not_equal(caller, removee);
}
governors.write(account=removee, value=FALSE);
governor_removed.emit(removed_governor=removee, removed_by=caller);
return ();
}
@external
func accept_governance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
let (caller: felt) = get_caller_address();
// Assert that the caller is a candidate.
let (is_candidate) = candidates.read(account=caller);
with_attr error_message("NOT_A_GOVERNANCE_CANDIDATE") {
assert is_candidate = TRUE;
}
// Clear candidate flag, and set governor flag.
candidates.write(account=caller, value=FALSE);
governors.write(account=caller, value=TRUE);
governance_accepted.emit(new_governor=caller);
return ();
}
func only_governor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() {
let (caller) = get_caller_address();
let (is_governor_) = is_governor(caller);
with_attr error_message("ONLY_GOVERNOR") {
assert is_governor_ = TRUE;
}
return ();
}