-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVoting.sol
164 lines (136 loc) · 4.6 KB
/
Voting.sol
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
156
157
158
159
160
161
162
163
164
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol";
/**
* @title Voting contrat: this contract allow a whitelist of voters to vote for their favorite proposition.
* @author Maxime AUBURTIN
* @notice You can use this contract for only the most basic simulation
* @dev All corner cases of a vote are not handled in this version also there is no egality, the first vote which has
* the maximum voices wins.
*/
contract Voting is Ownable {
/**
* Events
*/
event VoterRegistered(address voterAddress);
event WorkflowStatusChange(WorkflowStatus previousStatus, WorkflowStatus newStatus);
event ProposalRegistered(uint proposalId);
event Voted(address voter, uint proposalId);
/**
* Id of the winning proposal
*/
uint private winningProposalId;
/**
* Voter structure
*/
struct Voter {
bool isRegistered;
bool hasVoted;
uint votedProposalId;
}
/**
* Voters whitelist
*/
mapping (address => Voter) voters;
/**
* Modifier to allow only voters
*/
modifier onlyVoters() {
require(voters[msg.sender].isRegistered == true, "You are not a valid voter!");
_;
}
/**
* Modifier to only allow a unique vote
*/
modifier VoteOnce() {
require(voters[msg.sender].hasVoted == false, "You already voted!");
_;
}
/**
* Proposal structure
*/
struct Proposal {
uint id;
string description;
uint voteCount;
}
/**
* List of proposals and proposal counter to create proposal id
*/
Proposal[] proposals;
uint proposalIdCounter = 0;
/**
* Steps of the state machine
*/
enum WorkflowStatus {
RegisteringVoters,
ProposalsRegistrationStarted,
ProposalsRegistrationEnded,
VotingSessionStarted,
VotingSessionEnded,
VotesTallied
}
/**
* Current state machine state and modifiers for the state machine
*/
WorkflowStatus private currentVoteState;
modifier votesTallied() {
require(currentVoteState == WorkflowStatus.VotesTallied, "Votes need to be tallied in order to do that.");
_;
}
modifier votesNotTallied() {
require(currentVoteState != WorkflowStatus.VotesTallied, "Votes have been tallied. It is over. There is no next step!");
_;
}
modifier registeringVoters() {
require(currentVoteState == WorkflowStatus.RegisteringVoters, "You cannot register voters.");
_;
}
modifier registeringProposals() {
require(currentVoteState == WorkflowStatus.ProposalsRegistrationStarted, "You cannot register proposals.");
_;
}
modifier votingProposals() {
require(currentVoteState == WorkflowStatus.VotingSessionStarted, "You cannot vote proposals.");
_;
}
/**
* Contract code
*/
constructor() Ownable(msg.sender) {
currentVoteState = WorkflowStatus.RegisteringVoters;
}
function getVoteStep() external view returns (WorkflowStatus) {
return currentVoteState;
}
function nextVoteStep() external onlyOwner votesNotTallied {
WorkflowStatus previousState = currentVoteState;
currentVoteState = WorkflowStatus(uint(currentVoteState) + 1);
emit WorkflowStatusChange(previousState, currentVoteState);
}
function addVoter(address _address) external onlyOwner registeringVoters {
voters[_address].isRegistered = true;
emit VoterRegistered(_address);
}
function addProposal(string calldata _description) external onlyVoters registeringProposals {
proposals.push(Proposal(proposalIdCounter, _description, 0));
emit ProposalRegistered(proposalIdCounter++);
}
function voteForProposition(uint _proposalId) external onlyVoters votingProposals VoteOnce {
proposals[_proposalId].voteCount++;
voters[msg.sender].hasVoted = true;
voters[msg.sender].votedProposalId = proposals[_proposalId].id;
emit Voted(msg.sender, voters[msg.sender].votedProposalId);
}
function getWinner() external votesTallied returns (Proposal memory) {
uint maxVoteCount = 0;
for (uint i=0; i<proposals.length; i++) {
Proposal memory proposal = proposals[i];
if (proposal.voteCount > maxVoteCount) {
winningProposalId = proposal.id;
maxVoteCount = proposal.voteCount;
}
}
return proposals[winningProposalId];
}
}