# Why is it called “quadratic” voting?

What’s “quadratic” about it? Do the votes somehow exhibit “multiplicative” behavior, relative to one another (since each person must subdivide their votes, so the final tally is more like ratios or proportional voting)?

• Julius H, please accept my answer if it was informative for you :) Commented Feb 10 at 15:00

Classic collective decision making (aka a "majority voting system") is oftenTimes vulnerable to a phenomenon of the "tyranny of the majority", hence the 2nd name.

Contrary to that, the quadratic voting mechanism (QV) was invented to solve that problem in the following way:

Consider for instance a situation when a minority cares more about a particular public good than the majority. They are allowed to influence the outcome by casting an unlimited amount of votes (contrary to only 1 vote / person in the traditional majority system).

The main difference here is that the price of a vote will quadratically increase, based on how many votes an individual has already casted.

Code example:

``````    pragma solidity >=0.4.25 <0.6.0;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "openzeppelin-solidity/contracts/access/roles/MinterRole.sol";

/**
* @title QVVoting
* @dev the manager for proposals / votes
*/
contract QVVoting is Ownable, MinterRole {
using SafeMath for uint256;

uint256 private _totalSupply;
string public symbol;
string public name;

event VoteCasted(address voter, uint ProposalID, uint256 weight);

event ProposalCreated(
uint256 ProposalID,
string description,
uint votingTimeInHours
);

enum ProposalStatus {IN_PROGRESS, TALLY, ENDED}

struct Proposal {
ProposalStatus status;
string description;
uint expirationTime;
}

struct Voter {
bool hasVoted;
bool vote;
uint256 weight;
}

mapping(uint256 => Proposal) public Proposals;
uint public ProposalCount;

constructor() public {
symbol = "QVV";
name = "QV Voting";
}

/**
* @dev Creates a new proposal.
* @param _description the text of the proposal
* @param _voteExpirationTime expiration time in minutes
*/
function createProposal(
string calldata _description,
uint _voteExpirationTime
) external onlyOwner returns (uint) {
require(_voteExpirationTime > 0, "The voting period cannot be 0");
ProposalCount++;

Proposal storage curProposal = Proposals[ProposalCount];
curProposal.creator = msg.sender;
curProposal.status = ProposalStatus.IN_PROGRESS;
curProposal.expirationTime = now + 60 * _voteExpirationTime * 1 seconds;
curProposal.description = _description;

emit ProposalCreated(
msg.sender,
ProposalCount,
_description,
_voteExpirationTime
);
return ProposalCount;
}

/**
* @dev sets a proposal to TALLY.
* @param _ProposalID the proposal id
*/
function setProposalToTally(uint _ProposalID)
external
validProposal(_ProposalID)
onlyOwner
{
require(
Proposals[_ProposalID].status == ProposalStatus.IN_PROGRESS,
"Vote is not in progress"
);
require(
now >= getProposalExpirationTime(_ProposalID),
"voting period has not expired"
);
Proposals[_ProposalID].status = ProposalStatus.TALLY;
}

/**
* @dev sets a proposal to ENDED.
* @param _ProposalID the proposal id
*/
function setProposalToEnded(uint _ProposalID)
external
validProposal(_ProposalID)
onlyOwner
{
require(
Proposals[_ProposalID].status == ProposalStatus.TALLY,
"Proposal should be in tally"
);
require(
now >= getProposalExpirationTime(_ProposalID),
"voting period has not expired"
);
Proposals[_ProposalID].status = ProposalStatus.ENDED;
}

/**
* @dev returns the status of a proposal
* @param _ProposalID the proposal id
*/
function getProposalStatus(uint _ProposalID)
public
view
validProposal(_ProposalID)
returns (ProposalStatus)
{
return Proposals[_ProposalID].status;
}

/**
* @dev returns a proposal expiration time
* @param _ProposalID the proposal id
*/
function getProposalExpirationTime(uint _ProposalID)
public
view
validProposal(_ProposalID)
returns (uint)
{
return Proposals[_ProposalID].expirationTime;
}

/**
* @dev counts the votes for a proposal. Returns (yeays, nays)
* @param _ProposalID the proposal id
*/
function countVotes(uint256 _ProposalID) public view returns (uint, uint) {

for (uint i = 0; i < voters.length; i++) {
bool vote = Proposals[_ProposalID].voterInfo[voter].vote;
uint256 weight = Proposals[_ProposalID].voterInfo[voter].weight;
if (vote == true) {
} else {
}
}

}

/**
* @dev casts a vote.
* @param _ProposalID the proposal id
* @param numTokens number of voice credits
* @param _vote true for yes, false for no
*/
function castVote(uint _ProposalID, uint numTokens, bool _vote)
external
validProposal(_ProposalID)
{
require(
getProposalStatus(_ProposalID) == ProposalStatus.IN_PROGRESS,
"proposal has expired."
);
require(
!userHasVoted(_ProposalID, msg.sender),
"user already voted on this proposal"
);
require(
getProposalExpirationTime(_ProposalID) > now,
"for this proposal, the voting time expired"
);

_balances[msg.sender] = _balances[msg.sender].sub(numTokens);

uint256 weight = sqrt(numTokens); // QV Vote

Proposal storage curproposal = Proposals[_ProposalID];

curproposal.voterInfo[msg.sender] = Voter({
hasVoted: true,
vote: _vote,
weight: weight
});

curproposal.voters.push(msg.sender);

emit VoteCasted(msg.sender, _ProposalID, weight);
}

/**
* @dev checks if a user has voted
* @param _ProposalID the proposal id
* @param _user the address of a voter
*/
internal
view
validProposal(_ProposalID)
returns (bool)
{
return (Proposals[_ProposalID].voterInfo[_user].hasVoted);
}

/**
* @dev checks if a proposal id is valid
* @param _ProposalID the proposal id
*/
modifier validProposal(uint _ProposalID) {
require(
_ProposalID > 0 && _ProposalID <= ProposalCount,
"Not a valid Proposal Id"
);
_;
}

/**
* @dev returns the square root (in int) of a number
* @param x the number (int)
*/
function sqrt(uint x) internal pure returns (uint y) {
uint z = (x + 1) / 2;
y = x;
while (z < y) {
y = z;
z = (x / z + z) / 2;
}
}

/**
* @dev minting more tokens for an account
*/
function mint(address account, uint256 amount) public onlyOwner {