sample.sol.txt 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. pragma solidity ^0.4.11;
  2. /// @title Voting with delegation.
  3. contract Ballot {
  4. // This declares a new complex type which will
  5. // be used for variables later.
  6. // It will represent a single voter.
  7. struct Voter {
  8. uint weight; // weight is accumulated by delegation
  9. bool voted; // if true, that person already voted
  10. address delegate; // person delegated to
  11. uint vote; // index of the voted proposal
  12. }
  13. // This is a type for a single proposal.
  14. struct Proposal {
  15. bytes32 name; // short name (up to 32 bytes)
  16. uint voteCount; // number of accumulated votes
  17. }
  18. address public chairperson;
  19. // This declares a state variable that
  20. // stores a `Voter` struct for each possible address.
  21. mapping(address => Voter) public voters;
  22. // A dynamically-sized array of `Proposal` structs.
  23. Proposal[] public proposals;
  24. /// Create a new ballot to choose one of `proposalNames`.
  25. function Ballot(bytes32[] proposalNames) {
  26. chairperson = msg.sender;
  27. voters[chairperson].weight = 1;
  28. // For each of the provided proposal names,
  29. // create a new proposal object and add it
  30. // to the end of the array.
  31. for (uint i = 0; i < proposalNames.length; i++) {
  32. // `Proposal({...})` creates a temporary
  33. // Proposal object and `proposals.push(...)`
  34. // appends it to the end of `proposals`.
  35. proposals.push(Proposal({
  36. name: proposalNames[i],
  37. voteCount: 0
  38. }));
  39. }
  40. }
  41. // Give `voter` the right to vote on this ballot.
  42. // May only be called by `chairperson`.
  43. function giveRightToVote(address voter) {
  44. // If the argument of `require` evaluates to `false`,
  45. // it terminates and reverts all changes to
  46. // the state and to Ether balances. It is often
  47. // a good idea to use this if functions are
  48. // called incorrectly. But watch out, this
  49. // will currently also consume all provided gas
  50. // (this is planned to change in the future).
  51. require((msg.sender == chairperson) && !voters[voter].voted && (voters[voter].weight == 0));
  52. voters[voter].weight = 1;
  53. }
  54. /// Delegate your vote to the voter `to`.
  55. function delegate(address to) {
  56. // assigns reference
  57. Voter sender = voters[msg.sender];
  58. require(!sender.voted);
  59. // Self-delegation is not allowed.
  60. require(to != msg.sender);
  61. // Forward the delegation as long as
  62. // `to` also delegated.
  63. // In general, such loops are very dangerous,
  64. // because if they run too long, they might
  65. // need more gas than is available in a block.
  66. // In this case, the delegation will not be executed,
  67. // but in other situations, such loops might
  68. // cause a contract to get "stuck" completely.
  69. while (voters[to].delegate != address(0)) {
  70. to = voters[to].delegate;
  71. // We found a loop in the delegation, not allowed.
  72. require(to != msg.sender);
  73. }
  74. // Since `sender` is a reference, this
  75. // modifies `voters[msg.sender].voted`
  76. sender.voted = true;
  77. sender.delegate = to;
  78. Voter delegate = voters[to];
  79. if (delegate.voted) {
  80. // If the delegate already voted,
  81. // directly add to the number of votes
  82. proposals[delegate.vote].voteCount += sender.weight;
  83. } else {
  84. // If the delegate did not vote yet,
  85. // add to her weight.
  86. delegate.weight += sender.weight;
  87. }
  88. }
  89. /// Give your vote (including votes delegated to you)
  90. /// to proposal `proposals[proposal].name`.
  91. function vote(uint proposal) {
  92. Voter sender = voters[msg.sender];
  93. require(!sender.voted);
  94. sender.voted = true;
  95. sender.vote = proposal;
  96. // If `proposal` is out of the range of the array,
  97. // this will throw automatically and revert all
  98. // changes.
  99. proposals[proposal].voteCount += sender.weight;
  100. }
  101. /// @dev Computes the winning proposal taking all
  102. /// previous votes into account.
  103. function winningProposal() constant
  104. returns (uint winningProposal)
  105. {
  106. uint winningVoteCount = 0;
  107. for (uint p = 0; p < proposals.length; p++) {
  108. if (proposals[p].voteCount > winningVoteCount) {
  109. winningVoteCount = proposals[p].voteCount;
  110. winningProposal = p;
  111. }
  112. }
  113. }
  114. // Calls winningProposal() function to get the index
  115. // of the winner contained in the proposals array and then
  116. // returns the name of the winner
  117. function winnerName() constant
  118. returns (bytes32 winnerName)
  119. {
  120. winnerName = proposals[winningProposal()].name;
  121. }
  122. }