Created
December 22, 2015 19:28
-
-
Save anonymous/b60d3f661a4dcf51f691 to your computer and use it in GitHub Desktop.
Created using soleditor: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://chriseth.github.io/browser-solidity?gist=
This file contains hidden or 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
/* | |
Liquid Democracy | |
Uses a token as voting weight, you can delegate that weight to anyone as your representative. | |
They can also delegate to other people, and this cycles until someone with more votes is apointed. | |
The person with more votes gets to execute any transaction in this contract's name. | |
Useful if the liquid democracy is set as `owner` of some other contract. | |
*/ | |
/* The token is used as a voting shares */ | |
contract token { mapping (address => uint256) public balanceOf; } | |
contract LiquidDemocracy { | |
token public votingToken; | |
address public apointee; | |
mapping (address => uint) public voterId; | |
uint public numberOfVotes; | |
DelegatedVote[] public delegatedVotes; | |
event NewApointee(address newApointee, bool changed); | |
struct DelegatedVote { | |
address nominee; | |
address voter; | |
} | |
function LiquidDemocracy(address votingWeightToken) { | |
votingToken = token(votingWeightToken); | |
delegatedVotes.length++; | |
delegatedVotes[0] = DelegatedVote({nominee: 0, voter: 0}); | |
} | |
function vote(address nominatedAddress) returns (uint voteIndex) { | |
if (voterId[msg.sender]== 0) { | |
voterId[msg.sender] = delegatedVotes.length; | |
numberOfVotes++; | |
voteIndex = delegatedVotes.length++; | |
numberOfVotes = voteIndex; | |
} else { | |
voteIndex = voterId[msg.sender]; | |
} | |
delegatedVotes[voteIndex] = DelegatedVote({nominee: nominatedAddress, voter: msg.sender}); | |
} | |
function execute(address target, bytes32 bytecode){ | |
if (msg.sender != apointee) throw; // If caller is the current apointee, | |
target.call.value(msg.value)(bytecode); // Then execute the command. | |
} | |
function calculateApointee(uint extraRoundsOfDelegation) returns (address winner){ | |
mapping (address => uint) temporaryWeight; | |
address currentWinner = apointee; | |
uint currentMax = 0; | |
uint weight = 0; | |
DelegatedVote v = delegatedVotes[0]; | |
// First, distribute the initial weight | |
for (uint i=1; i< delegatedVotes.length; i++){ | |
v = delegatedVotes[i]; | |
temporaryWeight[v.nominee] += votingToken.balanceOf(v.voter); | |
} | |
// then pass multiple times to calculate the final weight | |
for (uint n=0; n < extraRoundsOfDelegation+3; n++){ | |
for (i=1; i< delegatedVotes.length; i++){ | |
v = delegatedVotes[i]; | |
weight = temporaryWeight[v.voter]; | |
temporaryWeight[v.voter] = 0; | |
temporaryWeight[v.nominee] += weight; | |
} | |
} | |
// finally calculate the winner | |
for (i=1; i< delegatedVotes.length; i++){ | |
v = delegatedVotes[i]; | |
if (temporaryWeight[v.nominee] > currentMax) { | |
currentWinner = v.nominee; | |
currentMax = temporaryWeight[v.nominee]; | |
} | |
} | |
// set the winner and log | |
NewApointee(currentWinner, apointee == currentWinner); | |
apointee = currentWinner; | |
return currentWinner; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment