11use serde:: { Deserialize , Serialize } ;
22use thiserror:: Error ;
3-
3+ use std :: collections :: HashMap ;
44
55#[ derive( Debug , PartialEq , Eq , Clone , Serialize , Deserialize ) ]
66pub enum Role {
@@ -9,102 +9,164 @@ pub enum Role {
99 Admin ,
1010}
1111
12-
1312#[ derive( Debug , Clone , Serialize , Deserialize ) ]
1413pub struct UserIdentity {
15- pub address : String ,
14+ pub address : String ,
1615 pub role : Role ,
1716}
1817
19-
20- #[ cfg_attr( feature = "std" , derive( thiserror:: Error ) ) ]
21- pub enum GovernanceError {
22- #[ error( "You are not authorized to perform this action." ) ]
23- Unauthorized ,
24-
25- #[ error( "The requested proposal was not found." ) ]
26- ProposalNotFound ,
27-
28- #[ error( "Invalid operation." ) ]
29- InvalidOperation ,
18+ #[ derive( Debug , PartialEq , Eq , Clone , Serialize , Deserialize ) ]
19+ pub enum ProposalStatus {
20+ Active ,
21+ Accepted ,
22+ Rejected ,
23+ Expired ,
3024}
3125
32-
3326#[ derive( Debug , Clone , Serialize , Deserialize ) ]
3427pub struct Proposal {
3528 pub id : u64 ,
3629 pub title : String ,
3730 pub description : String ,
38- pub proposer : String ,
31+ pub proposer : String ,
3932 pub votes_for : u32 ,
4033 pub votes_against : u32 ,
34+ pub status : ProposalStatus ,
35+ pub end_time : u64 , // Unix timestamp for voting deadline
4136}
4237
38+ #[ derive( Debug , thiserror:: Error ) ]
39+ pub enum GovernanceError {
40+ #[ error( "You are not authorized to perform this action." ) ]
41+ Unauthorized ,
42+ #[ error( "The requested proposal was not found." ) ]
43+ ProposalNotFound ,
44+ #[ error( "Voting period has expired." ) ]
45+ VotingExpired ,
46+ #[ error( "User has already voted." ) ]
47+ AlreadyVoted ,
48+ #[ error( "Invalid end time for proposal." ) ]
49+ InvalidEndTime ,
50+ }
4351
4452pub struct GovernanceDAO {
4553 pub proposals : Vec < Proposal > ,
4654 proposal_counter : u64 ,
55+ user_roles : HashMap < String , Role > ,
56+ votes : HashMap < ( u64 , String ) , bool > ,
57+ quorum : u32 ,
4758}
4859
4960impl GovernanceDAO {
50-
51- pub fn new ( ) -> Self {
61+ pub fn new ( quorum : u32 ) -> Self {
5262 Self {
5363 proposals : Vec :: new ( ) ,
5464 proposal_counter : 0 ,
65+ user_roles : HashMap :: new ( ) ,
66+ votes : HashMap :: new ( ) ,
67+ quorum,
68+ }
69+ }
70+
71+ pub fn set_role ( & mut self , caller : & UserIdentity , user : UserIdentity ) -> Result < ( ) , GovernanceError > {
72+ if !matches ! ( caller. role, Role :: Admin ) {
73+ return Err ( GovernanceError :: Unauthorized ) ;
5574 }
75+ self . user_roles . insert ( user. address . clone ( ) , user. role ) ;
76+ Ok ( ( ) )
5677 }
5778
58-
5979 pub fn submit_proposal (
6080 & mut self ,
6181 user : & UserIdentity ,
6282 title : String ,
6383 description : String ,
84+ end_time : u64 ,
85+ current_time : u64 ,
6486 ) -> Result < ( ) , GovernanceError > {
65- if matches ! ( user. role, Role :: Tutor | Role :: Admin ) {
66- self . proposal_counter += 1 ;
67- let proposal = Proposal {
68- id : self . proposal_counter ,
69- title,
70- description,
71- proposer : user. address . clone ( ) ,
72- votes_for : 0 ,
73- votes_against : 0 ,
74- } ;
75- self . proposals . push ( proposal) ;
76- Ok ( ( ) )
77- } else {
78- Err ( GovernanceError :: Unauthorized )
87+ if !matches ! ( user. role, Role :: Tutor | Role :: Admin ) {
88+ return Err ( GovernanceError :: Unauthorized ) ;
89+ }
90+ if end_time <= current_time {
91+ return Err ( GovernanceError :: InvalidEndTime ) ;
7992 }
93+
94+ self . proposal_counter += 1 ;
95+ let proposal = Proposal {
96+ id : self . proposal_counter ,
97+ title,
98+ description,
99+ proposer : user. address . clone ( ) ,
100+ votes_for : 0 ,
101+ votes_against : 0 ,
102+ status : ProposalStatus :: Active ,
103+ end_time,
104+ } ;
105+ self . proposals . push ( proposal) ;
106+ Ok ( ( ) )
80107 }
81108
82-
83109 pub fn vote_on_proposal (
84110 & mut self ,
85111 user : & UserIdentity ,
86112 proposal_id : u64 ,
87- support : bool ,
113+ support : bool ,
114+ current_time : u64 ,
88115 ) -> Result < ( ) , GovernanceError > {
89- if matches ! ( user. role, Role :: Student | Role :: Tutor ) {
90- let proposal = self . proposals
91- . iter_mut ( )
92- . find ( |p| p. id == proposal_id)
93- . ok_or ( GovernanceError :: ProposalNotFound ) ?;
94-
95- if support {
96- proposal. votes_for += 1 ;
97- } else {
98- proposal. votes_against += 1 ;
99- }
100- Ok ( ( ) )
116+ if !matches ! ( user. role, Role :: Student | Role :: Tutor ) {
117+ return Err ( GovernanceError :: Unauthorized ) ;
118+ }
119+
120+ let proposal = self . proposals
121+ . iter_mut ( )
122+ . find ( |p| p. id == proposal_id)
123+ . ok_or ( GovernanceError :: ProposalNotFound ) ?;
124+
125+ if proposal. status != ProposalStatus :: Active {
126+ return Err ( GovernanceError :: VotingExpired ) ;
127+ }
128+ if current_time > proposal. end_time {
129+ return Err ( GovernanceError :: VotingExpired ) ;
130+ }
131+
132+ let vote_key = ( proposal_id, user. address . clone ( ) ) ;
133+ if self . votes . contains_key ( & vote_key) {
134+ return Err ( GovernanceError :: AlreadyVoted ) ;
135+ }
136+
137+ if support {
138+ proposal. votes_for += 1 ;
101139 } else {
102- Err ( GovernanceError :: Unauthorized )
140+ proposal . votes_against += 1 ;
103141 }
142+ self . votes . insert ( vote_key, support) ;
143+ Ok ( ( ) )
144+ }
145+
146+ pub fn finalize_proposal ( & mut self , proposal_id : u64 , current_time : u64 ) -> Result < ( ) , GovernanceError > {
147+ let proposal = self . proposals
148+ . iter_mut ( )
149+ . find ( |p| p. id == proposal_id)
150+ . ok_or ( GovernanceError :: ProposalNotFound ) ?;
151+
152+ if proposal. status != ProposalStatus :: Active {
153+ return Err ( GovernanceError :: VotingExpired ) ;
154+ }
155+ if current_time <= proposal. end_time {
156+ return Err ( GovernanceError :: VotingExpired ) ;
157+ }
158+
159+ let total_votes = proposal. votes_for + proposal. votes_against ;
160+ proposal. status = if total_votes >= self . quorum && proposal. votes_for > proposal. votes_against {
161+ ProposalStatus :: Accepted
162+ } else {
163+ ProposalStatus :: Rejected
164+ } ;
165+ Ok ( ( ) )
104166 }
105167
106-
107168 pub fn list_proposals ( & self ) -> & Vec < Proposal > {
108169 & self . proposals
109170 }
110171}
172+
0 commit comments