Skip to content

Instantly share code, notes, and snippets.

@CeoFred
Last active June 7, 2024 18:34
Show Gist options
  • Save CeoFred/a82106560d461529bc57848f57c7bec4 to your computer and use it in GitHub Desktop.
Save CeoFred/a82106560d461529bc57848f57c7bec4 to your computer and use it in GitHub Desktop.
Quadratic Voting (QV) is a decision-making process that allows individuals to express the intensity of their preferences rather than just the direction of their vote. This smart contract implements the barest minimum expected for a quadratic voting system.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 <0.9.0;
contract QV {
struct VoteEntry {
address voter;
uint256 votes;
}
struct Proposal {
uint id;
uint voteCount;
uint endsAt;
VoteEntry[] voterEntries;
string name;
}
struct Voter {
uint creditBalance;
mapping(uint => uint) votes;
}
mapping(address => Voter) public voters;
mapping(uint => Proposal) public proposals;
uint public nextProposalId;
address public admin;
event ProposalCreated(uint id, string name);
event Voted(address indexed voter, uint proposalId, uint voteCount);
event CreditsPurchased(address indexed buyer, uint amount);
uint constant proposalLifeSpan = 1 days;
constructor() {
admin = msg.sender;
}
modifier onlyAdmin() {
require(msg.sender == admin, "only admin");
_;
}
function createProposal(string memory name) external onlyAdmin {
Proposal storage newProposal = proposals[nextProposalId];
newProposal.id = nextProposalId;
newProposal.name = name;
newProposal.voteCount = 0;
newProposal.endsAt = block.timestamp + proposalLifeSpan;
emit ProposalCreated(nextProposalId, name);
nextProposalId++;
}
function purchaseCredits() external payable {
require(msg.value > 0, "must send ether");
voters[msg.sender].creditBalance += msg.value;
emit CreditsPurchased(msg.sender, msg.value);
}
function quadraticCost(uint n) public pure returns(uint) {
return n ** 2;
}
function vote(uint proposalId, uint voteCount) external {
Voter storage voter = voters[msg.sender];
Proposal storage proposal = proposals[proposalId];
require(proposal.id == proposalId, "proposal does not exist");
uint cost = quadraticCost(voteCount);
require(voter.creditBalance >= cost, "not enough credits");
voter.creditBalance -= cost;
voter.votes[proposalId] += voteCount;
proposal.voteCount += voteCount;
proposal.voterEntries.push(VoteEntry({
voter: msg.sender,
votes: voteCount
}));
emit Voted(msg.sender, proposalId, voteCount);
}
function getProposal(uint proposalId) external view returns(uint, string memory, uint, VoteEntry[] memory, uint256) {
Proposal storage proposal = proposals[proposalId];
return (proposal.id, proposal.name, proposal.voteCount, proposal.voterEntries, proposal.endsAt);
}
function getCreditBalance(address voterAddress) external view returns(uint) {
return voters[voterAddress].creditBalance;
}
function getVotes(address voterAddress, uint proposalId) external view returns(uint) {
return voters[voterAddress].votes[proposalId];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment