Skip to content

Commit

Permalink
quadratic voting lib
Browse files Browse the repository at this point in the history
  • Loading branch information
peersky committed Nov 19, 2023
1 parent 03d597a commit b3fd1f0
Showing 1 changed file with 110 additions and 0 deletions.
110 changes: 110 additions & 0 deletions src/libraries/LibQuadraticVoting.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
error quadraticVotingError(string paramter, uint256 arg, uint256 arg2);

library LibQuadraticVoting {
struct qVotingStruct {
uint256 voteCredits;
uint256 maxQuadraticPoints;
uint256 minQuadraticPositons;
}

function precomputeValues(
uint256 voteCredits,
uint256 minExpectedVoteItems
) internal pure returns (qVotingStruct memory) {
qVotingStruct memory q;

q.maxQuadraticPoints = Math.sqrt(voteCredits);

// This block finds how many vote positions are needed to distribute all quadratic vote points.
uint256 iterator = 0;
uint256 accumulator = 0;
do {
iterator++;
accumulator += iterator ** 2;
} while (accumulator < voteCredits);
// This enforces requirement that all vote credits can indeed be spended (no leftovers)
if (accumulator != voteCredits)
revert quadraticVotingError("voteCredits bust be i^2 series", accumulator, voteCredits);
q.minQuadraticPositons = iterator;
// In order to spend all vote credits there must be at least minQuadraticPositons+1 (becuase proposer is also a player and cannot vote for himself)
if (minExpectedVoteItems <= q.minQuadraticPositons)
revert quadraticVotingError(
"Minimum Voting positions above min players",
q.minQuadraticPositons,
minExpectedVoteItems
);
q.voteCredits = voteCredits;
return q;
}

// function computeScoreByVPIndex(
// qVotingStruct memory q,
// uint256[][] memory VotersVotes,
// bool[] memory voterVoted,
// uint256 notVotedGivesEveyone,
// uint256 proposerIdx
// ) internal pure returns (uint256) {
// uint256 score = 0;
// for (uint256 i = 0; i < VotersVotes.length; i++) {
// // For each potential voter
// if (i != proposerIdx) {
// // Calculate scores only for cases when voter is not proposer
// uint256 creditsUsed = 0;
// uint256[] memory voterVotes = VotersVotes[i];

// if (!voterVoted[i]) {
// // Check if voter wasn't voting
// score += notVotedGivesEveyone; // Gives benefits to everyone but himself
// creditsUsed = q.voteCredits;
// } else {
// for (uint256 vi = 0; vi < voterVotes.length; vi++) {
// if (voterVotes[vi] != 0)
// revert quadraticVotingError("Voting for yourself not allowed", i, voterVotes[y]);
// score += voterVotes[proposerIdx];
// creditsUsed += voterVotes[proposerIdx] ** 2;
// }
// }

// if (creditsUsed > q.voteCredits)
// revert quadraticVotingError("Quadratic: vote credits overrun", q.voteCredits, creditsUsed);
// }
// }
// return score;
// }

function computeScoresByVPIndex(
qVotingStruct memory q,
uint256[][] memory VotersVotes,
bool[] memory voterVoted,
uint256 notVotedGivesEveyone,
uint256 proposalsLength
) internal pure returns (uint256[] memory) {
uint256[] memory scores = new uint256[](proposalsLength);
uint256[] memory creditsUsed = new uint256[](VotersVotes.length);

for (uint256 proposalIdx = 0; proposalIdx < proposalsLength; proposalIdx++) {
//For each proposal
scores[proposalIdx] = 0;
for (uint256 vi = 0; vi < VotersVotes.length; vi++) {
// For each potential voter
uint256[] memory voterVotes = VotersVotes[vi];
if (!voterVoted[vi]) {
// Check if voter wasn't voting
scores[proposalIdx] += notVotedGivesEveyone; // Gives benefits to everyone but himself
creditsUsed[vi] = q.voteCredits;
} else {
//If voter voted
scores[proposalIdx] += voterVotes[proposalIdx];
creditsUsed[vi] += voterVotes[proposalIdx] ** 2;
if (creditsUsed[vi] > q.voteCredits)
revert quadraticVotingError("Quadratic: vote credits overrun", q.voteCredits, creditsUsed[vi]);
}
}
}
return scores;
}
}

0 comments on commit b3fd1f0

Please sign in to comment.