Skip to content

Instantly share code, notes, and snippets.

@mr-bat
Last active November 6, 2020 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mr-bat/0b8027114027df8d5b0a65ad51dd84a2 to your computer and use it in GitHub Desktop.
Save mr-bat/0b8027114027df8d5b0a65ad51dd84a2 to your computer and use it in GitHub Desktop.
Solution to hw 2 of CS291D
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;
}
}
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.
@mr-bat
Copy link
Author

mr-bat commented Nov 6, 2020

A copy of the homework description can be found here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment