-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathballot.rb
85 lines (69 loc) · 2.3 KB
/
ballot.rb
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
####
# Liquid / Delegative Democracy
# Let's Vote (or Delegate Your Vote) on a Proposal
class Ballot < Contract
struct :Voter,
weight: UInt, # weight is accumulated by delegation
voted: Bool, # if true, that person already voted
vote: UInt, # index of the voted proposal
delegate: Address # person delegated to
struct :Proposal,
vote_count: UInt # number of accumulated votes
storage chairperson: Address,
voters: mapping( Address, Voter ),
proposals: array( Proposal )
## Create a new ballot with $(num_proposals) different proposals.
sig [UInt]
def constructor( num_proposals: )
@chairperson = msg.sender
@proposals.length = num_proposals
@voters[ @chairperson ].weight = 1
end
## Give $(to_voter) the right to vote on this ballot.
## May only be called by $(chairperson).
sig [Address]
def give_right_to_vote( to_voter: )
assert msg.sender == @chairperson, "only chairperson"
aasert @voters[to_voter].voted? == false, "voter already voted"
@voters[to_voter].weight = 1
end
## Delegate your vote to the voter $(to).
sig [Address]
def delegate( to: )
sender = @voters[msg.sender] # assigns reference
assert sender.voted? == false
while @voters[to].delegate != address(0) && @voters[to].delegate != msg.sender do
to = @voters[to].delegate
end
assert to != msg.sender
sender.voted = true
sender.delegate = to
delegate_to = @voters[to]
if delegate_to.voted
@proposals[delegate_to.vote].vote_count += sender.weight
else
delegate_to.weight += sender.weight
end
end
## Give a single vote to proposal $(to_proposal).
sig [UInt]
def vote( to_proposal: )
sender = @voters[msg.sender]
assert sender.voted? == false && to_proposal < @proposals.length
sender.voted = true
sender.vote = to_proposal
@proposals[to_proposal].vote_count += sender.weight
end
sig [], :view, returns: UInt
def winning_proposal
winning_vote_count = 0
winning_proposal = 0
@proposals.each_with_index do |proposal,i|
if proposal.vote_count > winning_vote_count
winning_vote_count = proposal.vote_count
winning_proposal = i
end
end
winning_proposal
end
end # class Ballot