Last active
June 7, 2024 18:34
-
-
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.
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
// 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