-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsistema-de-voto.sol
151 lines (134 loc) · 5.46 KB
/
sistema-de-voto.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
// SPDX-License-Identifier: GPL-3.0
pragma solidity >0.6.99 <0.8.0;
/// @Título Votação com delegação.
contract Ballot {
// Isso declara um novo tipo complexo que irá
// ser usado para variáveis posteriormente.
// Representará um único eleitor.
struct Voter {
uint weight; // peso é acumulado por delegação
bool voted; // se for verdade, essa pessoa já votou
address delegate; // pessoa delegada a
uint vote; // índice da proposta votada
}
// Este é um tipo para uma única proposta.
struct Proposal {
bytes32 name; // short name (up to 32 bytes)
uint voteCount; // number of accumulated votes
}
address public chairperson;
// Isso declara uma variável de estado que
// armazena uma estrutura `Voter` para cada endereço possível.
mapping(address => Voter) public voters;
// Uma matriz de tamanho dinâmico de estruturas `Proposta`.
Proposal[] public proposals;
/// Crie uma nova cédula para escolher um dos `proposalNames`.
constructor(bytes32[] memory proposalNames) {
chairperson = msg.sender;
voters[chairperson].weight = 1;
// Para cada um dos nomes de proposta fornecidos,
// cria um novo objeto de proposta e o adiciona
// até o final da matriz.
for (uint i = 0; i < proposalNames.length; i++) {
// `Proposta ({...})` cria um temporário
// Objeto de proposta e `propostas.push (...)`
// anexa ao final de `propostas`.
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
// Dê ao `eleitor` o direito de votar nesta cédula.
// Só pode ser convocado pelo `presidente`.
function giveRightToVote(address voter) public {
// Se o primeiro argumento de `require` avalia
// para `false`, a execução termina e tudo
// muda para o estado e para equilíbrios Ether
// são revertidos.
// Isso costumava consumir todo o gás nas versões antigas do EVM, mas
// não mais.
// Muitas vezes é uma boa idéia usar `require` para verificar se
// funções são chamadas corretamente.
// Como um segundo argumento, você também pode fornecer um
// explicação sobre o que deu errado.
require(
msg.sender == chairperson,
"Only chairperson can give right to vote."
);
require(
!voters[voter].voted,
"The voter already voted."
);
require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
/// Delegar seu voto ao eleitor `a`.
function delegate(address to) public {
// atribui referência
Voter storage sender = voters[msg.sender];
require(!sender.voted, "You already voted.");
require(to != msg.sender, "Self-delegation is disallowed.");
// Encaminhe a delegação enquanto
// `to` também delegado.
// Em geral, esses loops são muito perigosos,
// porque se eles correrem muito tempo, eles podem
// precisa de mais gás do que o disponível em um bloco.
// Neste caso, a delegação não será executada,
// mas em outras situações, esses loops podem
// faz com que um contrato fique completamente "preso".
while (voters[to].delegate != address(0)) {
to = voters[to].delegate;
// Encontramos um loop na delegação, não permitido.
require(to != msg.sender, "Found loop in delegation.");
}
// Uma vez que `sender` é uma referência, este
// modifica `voters [msg.sender] .voted`
sender.voted = true;
sender.delegate = to;
Voter storage delegate_ = voters[to];
if (delegate_.voted) {
// Se o delegado já votou,
// adiciona diretamente ao número de votos
proposals[delegate_.vote].voteCount += sender.weight;
} else {
// Se o delegado não votou ainda,
// adicione ao peso dela.
delegate_.weight += sender.weight;
}
}
/// Dê o seu voto (incluindo votos delegados a você)
/// para a proposta `propostas [proposta] .nome`.
function vote(uint proposal) public {
Voter storage sender = voters[msg.sender];
require(sender.weight != 0, "Has no right to vote");
require(!sender.voted, "Already voted.");
sender.voted = true;
sender.vote = proposal;
// Se a `proposta` estiver fora do intervalo da matriz,
// isso vai lançar automaticamente e reverter todos
// alterar.
proposals[proposal].voteCount += sender.weight;
}
/// @dev Calcula a proposta vencedora levando todos
/// votos anteriores em conta.
function winningProposal() public view
returns (uint winningProposal_)
{
uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount;
winningProposal_ = p;
}
}
}
// Chama a função winProposal () para obter o índice
// do vencedor contido na matriz de propostas e então
// retorna o nome do vencedor
function winnerName() public view
returns (bytes32 winnerName_)
{
winnerName_ = proposals[winningProposal()].name;
}
}