Changeset View
Changeset View
Standalone View
Standalone View
autotests/folding/test.sol.fold
- This file was added.
1 | // Solidity Sample File | ||||
---|---|---|---|---|---|
2 | // https://solidity.readthedocs.io/en/latest/solidity-by-example.html#voting | ||||
3 | | ||||
4 | pragma solidity >=0.4.22 <0.7.0; | ||||
5 | | ||||
6 | /// @title Voting with delegation. | ||||
7 | contract Ballot <beginfold id='1'>{</beginfold id='1'> | ||||
8 | // This declares a new complex type which will | ||||
9 | // be used for variables later. | ||||
10 | // It will represent a single voter. | ||||
11 | struct Voter <beginfold id='1'>{</beginfold id='1'> | ||||
12 | uint weight; // weight is accumulated by delegation | ||||
13 | bool voted; // if true, that person already voted | ||||
14 | address delegate; // person delegated to | ||||
15 | uint vote; // index of the voted proposal | ||||
16 | <endfold id='1'>}</endfold id='1'> | ||||
17 | | ||||
18 | // This is a type for a single proposal. | ||||
19 | struct Proposal <beginfold id='1'>{</beginfold id='1'> | ||||
20 | bytes32 name; // short name (up to 32 bytes) | ||||
21 | uint voteCount; // number of accumulated votes | ||||
22 | <endfold id='1'>}</endfold id='1'> | ||||
23 | | ||||
24 | address public chairperson; | ||||
25 | | ||||
26 | // This declares a state variable that | ||||
27 | // stores a `Voter` struct for each possible address. | ||||
28 | mapping(address => Voter) public voters; | ||||
29 | | ||||
30 | // A dynamically-sized array of `Proposal` structs. | ||||
31 | Proposal[] public proposals; | ||||
32 | | ||||
33 | /// Create a new ballot to choose one of `proposalNames`. | ||||
34 | constructor(bytes32[] memory proposalNames) public <beginfold id='1'>{</beginfold id='1'> | ||||
35 | chairperson = msg.sender; | ||||
36 | voters[chairperson].weight = 1; | ||||
37 | | ||||
38 | // For each of the provided proposal names, | ||||
39 | // create a new proposal object and add it | ||||
40 | // to the end of the array. | ||||
41 | for (uint i = 0; i < proposalNames.length; i++) <beginfold id='1'>{</beginfold id='1'> | ||||
42 | // `Proposal({...})` creates a temporary | ||||
43 | // Proposal object and `proposals.push(...)` | ||||
44 | // appends it to the end of `proposals`. | ||||
45 | proposals.push(Proposal(<beginfold id='1'>{</beginfold id='1'> | ||||
46 | name: proposalNames[i], | ||||
47 | voteCount: 0 | ||||
48 | <endfold id='1'>}</endfold id='1'>)); | ||||
49 | <endfold id='1'>}</endfold id='1'> | ||||
50 | <endfold id='1'>}</endfold id='1'> | ||||
51 | | ||||
52 | // Give `voter` the right to vote on this ballot. | ||||
53 | // May only be called by `chairperson`. | ||||
54 | function giveRightToVote(address voter) public <beginfold id='1'>{</beginfold id='1'> | ||||
55 | // If the first argument of `require` evaluates | ||||
56 | // to `false`, execution terminates and all | ||||
57 | // changes to the state and to Ether balances | ||||
58 | // are reverted. | ||||
59 | // This used to consume all gas in old EVM versions, but | ||||
60 | // not anymore. | ||||
61 | // It is often a good idea to use `require` to check if | ||||
62 | // functions are called correctly. | ||||
63 | // As a second argument, you can also provide an | ||||
64 | // explanation about what went wrong. | ||||
65 | require( | ||||
66 | msg.sender == chairperson, | ||||
67 | "Only chairperson can give right to vote." | ||||
68 | ); | ||||
69 | require( | ||||
70 | !voters[voter].voted, | ||||
71 | "The voter already voted." | ||||
72 | ); | ||||
73 | require(voters[voter].weight == 0); | ||||
74 | voters[voter].weight = 1; | ||||
75 | <endfold id='1'>}</endfold id='1'> | ||||
76 | | ||||
77 | /// Delegate your vote to the voter `to`. | ||||
78 | function delegate(address to) public <beginfold id='1'>{</beginfold id='1'> | ||||
79 | // assigns reference | ||||
80 | Voter storage sender = voters[msg.sender]; | ||||
81 | require(!sender.voted, "You already voted."); | ||||
82 | | ||||
83 | require(to != msg.sender, "Self-delegation is disallowed."); | ||||
84 | | ||||
85 | // Forward the delegation as long as | ||||
86 | // `to` also delegated. | ||||
87 | // In general, such loops are very dangerous, | ||||
88 | // because if they run too long, they might | ||||
89 | // need more gas than is available in a block. | ||||
90 | // In this case, the delegation will not be executed, | ||||
91 | // but in other situations, such loops might | ||||
92 | // cause a contract to get "stuck" completely. | ||||
93 | while (voters[to].delegate != address(0)) <beginfold id='1'>{</beginfold id='1'> | ||||
94 | to = voters[to].delegate; | ||||
95 | | ||||
96 | // We found a loop in the delegation, not allowed. | ||||
97 | require(to != msg.sender, "Found loop in delegation."); | ||||
98 | <endfold id='1'>}</endfold id='1'> | ||||
99 | | ||||
100 | // Since `sender` is a reference, this | ||||
101 | // modifies `voters[msg.sender].voted` | ||||
102 | sender.voted = true; | ||||
103 | sender.delegate = to; | ||||
104 | Voter storage delegate_ = voters[to]; | ||||
105 | if (delegate_.voted) <beginfold id='1'>{</beginfold id='1'> | ||||
106 | // If the delegate already voted, | ||||
107 | // directly add to the number of votes | ||||
108 | proposals[delegate_.vote].voteCount += sender.weight; | ||||
109 | <endfold id='1'>}</endfold id='1'> else <beginfold id='1'>{</beginfold id='1'> | ||||
110 | // If the delegate did not vote yet, | ||||
111 | // add to her weight. | ||||
112 | delegate_.weight += sender.weight; | ||||
113 | <endfold id='1'>}</endfold id='1'> | ||||
114 | <endfold id='1'>}</endfold id='1'> | ||||
115 | | ||||
116 | /// Give your vote (including votes delegated to you) | ||||
117 | /// to proposal `proposals[proposal].name`. | ||||
118 | function vote(uint proposal) public <beginfold id='1'>{</beginfold id='1'> | ||||
119 | Voter storage sender = voters[msg.sender]; | ||||
120 | require(sender.weight != 0, "Has no right to vote"); | ||||
121 | require(!sender.voted, "Already voted."); | ||||
122 | sender.voted = true; | ||||
123 | sender.vote = proposal; | ||||
124 | | ||||
125 | // If `proposal` is out of the range of the array, | ||||
126 | // this will throw automatically and revert all | ||||
127 | // changes. | ||||
128 | proposals[proposal].voteCount += sender.weight; | ||||
129 | <endfold id='1'>}</endfold id='1'> | ||||
130 | | ||||
131 | /// @dev Computes the winning proposal taking all | ||||
132 | /// previous votes into account. | ||||
133 | function winningProposal() public view | ||||
134 | returns (uint winningProposal_) | ||||
135 | <beginfold id='1'>{</beginfold id='1'> | ||||
136 | uint winningVoteCount = 0; | ||||
137 | for (uint p = 0; p < proposals.length; p++) <beginfold id='1'>{</beginfold id='1'> | ||||
138 | if (proposals[p].voteCount > winningVoteCount) <beginfold id='1'>{</beginfold id='1'> | ||||
139 | winningVoteCount = proposals[p].voteCount; | ||||
140 | winningProposal_ = p; | ||||
141 | <endfold id='1'>}</endfold id='1'> | ||||
142 | <endfold id='1'>}</endfold id='1'> | ||||
143 | <endfold id='1'>}</endfold id='1'> | ||||
144 | | ||||
145 | // Calls winningProposal() function to get the index | ||||
146 | // of the winner contained in the proposals array and then | ||||
147 | // returns the name of the winner | ||||
148 | function winnerName() public view | ||||
149 | returns (bytes32 winnerName_) | ||||
150 | <beginfold id='1'>{</beginfold id='1'> | ||||
151 | winnerName_ = proposals[winningProposal()].name; | ||||
152 | <endfold id='1'>}</endfold id='1'> | ||||
153 | <endfold id='1'>}</endfold id='1'> |