中文 / English
In the governance of the public sphere, votes are needed to decide where the funds will be spent, and which projects will receive priority funding. For example, a city may allocate its budget for projects such as parks, hospitals, roads. Or a blockchain project funded by communities and institutions may allocate its budget for projects such as wallets, developer tools, document editing, hackathons, community podcasts, privacy agreements, etc.
There are usually two ways to vote: "one-person-one-vote" and "one-dollar-one-vote."
The nature of "one-person-one-vote" is that no matter how much you care about something, you can only vote for it once. In Vitalik's article, one-person-one-vote is: if you care about an issue (or a public good/project), the cost of your first vote is extremely low, but if you want to continue to contribute, the cost becomes infinitely high (because you only have one vote).
One-dollar-one-vote is a way to vote with money (or Token), people who care more about an issue can contribute more (provided you have enough money/tokens). For example, the PoS consensus implements this idea. This approach leads to the ability to buy influence.
Suppose a community wants to allocate its budget for two public infrastructure projects: a road and a garden on a street corner. Perhaps most people are more concerned about the road, but the rich man who lives on the corner is very concern about having a garden on the corner. The rich man will pay a lot of money, and as a result, projects that most people care about may lose out to projects that few people care about.
What if we want to take into account people's concerns about different issues at the same time, without completely "buying influence"? That's when you can use quadratic vote and quadratic fund.
Quadratic voting is a collective decision-making procedure which involves individuals allocating votes to express the degree of their preferences, rather than just the direction of their preferences. By doing so, quadratic voting seeks to address issues of voting paradox and majority rule. Quadratic voting works by allowing users to "pay" for additional votes on a given matter to express their support for given issues more strongly, resulting in voting outcomes that are aligned with the highest willingness to pay outcome, rather than just the outcome preferred by the majority regardless of the intensity of individual preferences. The payment for votes may be through either artificial or real currencies (e.g. with tokens distributed equally among voting members or with real money). Quadratic voting is a variant of cumulative voting in the class of cardinal voting. It differs from cumulative voting by altering "the cost" and "the vote" relation from linear to quadratic.
Quadratic voting is based upon market principles, where each voter is given a budget of vote credits that they have the personal decisions and delegation to spend in order to influence the outcome of a range of decisions. If a participant has a strong support for or against a specific decision, additional votes could be allocated to proportionally demonstrate the voter's support. A vote pricing rule determines the cost of additional votes, with each vote becoming increasingly more expensive. By increasing voter credit costs, this demonstrates an individual's support and interests toward the particular decision. If money is used, it is eventually cycled back to the voters based upon per capita. Both E Glen Weyl and Steven Lalley conducted research in which they claim to demonstrate that this decision-making policy expedites efficiency as the number of voters increases. The simplified formula on how quadratic voting functions is:
The formula in smart contracts is slightly different:
- voteTool quadratic vote
- FinancingTool quadratic fund
In both cases, the ID is obtained using hash
function hash(bytes memory _b) public pure returns (bytes32){
return keccak256(_b);
}
Since dynamic value types such as bytes
and string
will be hashed in the event indexed parameters, the hash value is directly used as the id value of the vote.
Address 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
means accepting ETH, and the other means accepting tokens.
Both Addresses are examples and can be modified as required.
Quadratic vote, the more votes, the more money needed.
Example: the first ticket 1ETH, the second ticket 2ETH, the third ticket 4ETH, the fourth ticket 8ETH...
Then the cost of the n-th vote is:
Using both eth and Token for voting is not implemented for now.
addProposal(uint256 _proposal) public onlyOwner
add proposalexpireProposal(uint256 _proposal) public onlyOwner
make proposal expired (Voters will no longer be able to vote)vote(uint256 _proposal, uint256 _n) public payable
votewithdraw() public onlyOwner
withdraw eth to voter
Each user vote on a proposal is the square root of the total amount ().
- Each green square represents the amount of a donation, the area of the large square C can be interpreted as the total grant pool amount, and the yellow area S can be interpreted as an externally supported grant pool. Now, the amount each contributor contributes is
c_i
, so the area of that big square isC=(sum(sqrt(c_i)))^2
, amount of mathS=C−sum(c_i)
- At any one time, if there is more than one contributor, then
C > sum(c_i)
- If S and the subsidy pool are not exactly the same, they can be allocated proportionally according to the yellow area
- Multiple small donations can result in large yellow acreage, allowing projects to win more funding allocations
/**
Formula interpretation provided by Harry:
Green:
project A: 1*1 = 1
project B:
user1: 4: length 2
user2: 16: length 4, total 6
user1: 12, total: 6 - 2 + sqrt(4+12) = 8
project C: 2*2=4
project D: 3*3=9
Total bottom length : 1+8+2+3=14
Total square area: 14*14 = 196
math amount = 196-(1+32+4+9) = 150
Finally:
A: 1 + 1/14 * 150 = 11.714285714
B: 32 + 8/14 * 150 = 117.714285714
C: 4 + 2/14 * 150 = 25.428571429
D: 9 + 3/14 * 150 = 41.142857143
*/
struct Proposal {
uint256 name;// proposal id
uint256 amount;// received amount
uint256 voteCount;
address owner;
address[] userAddrArr;// voter address
uint8 isEnd;// 0 not end, 1 ended
}
struct UserVote {// Each user will have one instance of each proposal
uint256 count;
uint256 amount;
}
Case: Each person can donate to multiple proposals within a certain period of time. A certain amount of time will be allocated to increase the donation time after the proposal complete. After confirming the complete completion, the proposal owner can claim the donation amount.
addProposal(uint256 _proposal) public onlyOwner
add new proposal, the code p.owner=msg.sender is wrongand can be modifiedvote(uint256 _proposal, uint256 _inAmount) public payable
vote and donateaddExtraAmount(address _maker, uint256 _inAmount) public payable
add money to subsidy, _maker is donatorwithdrawProposal(uint256 _proposal) public checkEnd
withdraw money after proposal endedfunction getResult(uint256 _proposal) public view returns (uint256, uint256)
View the current contribution amount/share of the proposal
-
install dependencies
yarn
-
compile contracts
npx hardhat compile
-
run test scripts
npx hardhat test