Last active
November 6, 2020 07:09
-
-
Save mr-bat/0b8027114027df8d5b0a65ad51dd84a2 to your computer and use it in GitHub Desktop.
Solution to hw 2 of CS291D
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.22 <0.7.0; | |
/** | |
* @title QuadraticBallot | |
* @dev Implements voting process along with vote delegation | |
*/ | |
contract QuadraticBallot { | |
struct Voter { | |
bool voted; // if true, that person already voted | |
address delegate; // person delegated to | |
uint[] vote; // quadratic vote | |
uint weight; // weight of voter, NOTE: this is not the weight of the proposal | |
} | |
struct Proposal { | |
// If you can limit the length to a certain number of bytes, | |
// always use one of bytes1 to bytes32 because they are much cheaper | |
bytes32 name; // short name (up to 32 bytes) | |
uint voteCount; // number of accumulated votes | |
} | |
address public chairperson; | |
uint public budgetPerPerson; | |
mapping(address => Voter) public voters; | |
Proposal[] public proposals; | |
/** | |
* @dev Create a new ballot to choose one of 'proposalNames'. | |
* @param proposalNames names of proposals | |
* @param budget voting budget each voter has | |
*/ | |
constructor(bytes32[] memory proposalNames, uint budget) public { | |
chairperson = msg.sender; | |
budgetPerPerson = budget; | |
for (uint i = 0; i < proposalNames.length; i++) { | |
// 'Proposal({...})' creates a temporary | |
// Proposal object and 'proposals.push(...)' | |
// appends it to the end of 'proposals'. | |
proposals.push(Proposal({ | |
name: proposalNames[i], | |
voteCount: 0 | |
})); | |
} | |
} | |
/** | |
* @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'. | |
* @param voter address of voter | |
*/ | |
function assignVoter(address voter) public { | |
require( | |
msg.sender == chairperson, | |
"only the chairperson is eligible to give a person the right to vote." | |
); | |
// require(voter != address(0), "address-zero cannot be used."); | |
require(!voters[voter].voted, "voter has voted."); | |
require(voters[voter].weight == 0, "voter has already been given the right to vote."); | |
voters[voter].weight = 1; | |
} | |
/** | |
* @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'. | |
* @param proposal the credits of each proposal that the voter distributes | |
*/ | |
function vote(uint[] memory proposal) public { | |
require(proposal.length == proposals.length, "you should vote to exactly all of the proposals."); | |
Voter storage cur_voter = voters[msg.sender]; | |
require(!cur_voter.voted, "already voted."); | |
require(cur_voter.weight == 1, "voter does not have the right to vote."); | |
uint total_credits = 0; | |
for (uint i = 0; i < proposal.length; i++) { | |
total_credits += proposal[i] * proposal[i]; | |
} | |
require(total_credits <= budgetPerPerson, "you are exceeding your budget."); | |
cur_voter.voted = true; | |
for (uint i = 0; i < proposal.length; i++) { | |
cur_voter.vote.push(proposal[i]); | |
proposals[i].voteCount += proposal[i]; | |
} | |
} | |
/** | |
* @dev Computes the winning proposal taking all previous votes into account. | |
* @return winningProposal_ index of winning proposal in the proposals array | |
*/ | |
function winningProposal() public view | |
returns (uint winningProposal_) | |
{ | |
winningProposal_ = 0; | |
for (uint i = 0; i < proposals.length; i++) { | |
if (proposals[i].voteCount > proposals[winningProposal_].voteCount) { | |
winningProposal_ = i; | |
} | |
} | |
} | |
/** | |
* @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then | |
* @return winnerName_ the name of the winner | |
*/ | |
function winnerName() public view | |
returns (bytes32 winnerName_) | |
{ | |
winnerName_ = proposals[winningProposal()].name; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I believe such design is prone to the following issues: | |
* Votes will be public and any person can learn other people's votes. | |
* People can be put under pressure to vote for specific candidates. Since the votes are public, if you decide to vote based on your own preference, mischievous players would learn and can result to penalties in real life. | |
* Votes are gradually obtained and since they are public, a late voter can learn about the current results when voting and can vote accordingly to proposals with lower votes. Thereby, individuals can affect the final result of the election that is not possible in traditional elections. | |
* Deploying this system for real life scenarios is neither scalable nor cheap and would require a lot of technical knowledge. | |
* Either the infrastructure or the smart contract can be buggy and this would lead to disastrous outcomes. We should be very cautious about the codes and maybe we should use verifaction techniques or comprehensive testing to ensure safety. | |
* If the system is used in some form of auction, miners by refusing service to arbitrary users can change the results. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A copy of the homework description can be found here.