-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLiquidDem.sol
118 lines (100 loc) · 4.04 KB
/
LiquidDem.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
pragma solidity ^0.4.2;
contract token {
mapping (address => uint256) public balanceOf;
}
contract LiquidDemocracy {
token public votingToken;
bool underExecution;
address public appointee;
mapping (address => uint) public voterId;
mapping (address => uint256) public voteWeight;
uint public delegatedPercent;
uint public lastWeightCalculation;
uint public numberOfDelegationRounds;
uint public numberOfVotes;
DelegatedVote[] public delegatedVotes;
string public forbiddenFunction;
event NewAppointee(address newAppointee, bool changed);
struct DelegatedVote {
address nominee;
address voter;
}
function LiquidDemocracy(
address votingWeightToken,
string forbiddenFunctionCall,
uint percentLossInEachRound
) {
votingToken = token(votingWeightToken);
delegatedVotes.length++;
delegatedVotes[0] = DelegatedVote({nominee: 0, voter: 0});
forbiddenFunction = forbiddenFunctionCall;
delegatedPercent = 100 - percentLossInEachRound;
if (delegatedPercent > 100) delegatedPercent = 100;
}
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, uint valueInEther, bytes32 bytecode) {
if (msg.sender != appointee // If caller is the current appointee,
|| underExecution // // if the call is being executed,
|| bytes4(bytecode) == bytes4(sha3(forbiddenFunction)) // and it's not trying to do the forbidden function
|| numberOfDelegationRounds < 4 ) // and delegation has been calculated enough
throw;
underExecution = true;
if (!target.call.value(valueInEther * 1 ether)(bytecode)) { // Then execute the command.
throw;
}
else {
underExecution = false;
}
}
function calculateVotes() returns (address winner) {
address currentWinner = appointee;
uint currentMax = 0;
uint weight = 0;
DelegatedVote v = delegatedVotes[0];
if (now > lastWeightCalculation + 90 minutes) {
numberOfDelegationRounds = 0;
lastWeightCalculation = now;
// Distribute the initial weight
for (uint i=1; i< delegatedVotes.length; i++) {
voteWeight[delegatedVotes[i].nominee] = 0;
}
for (i=1; i< delegatedVotes.length; i++) {
voteWeight[delegatedVotes[i].voter] = votingToken.balanceOf(delegatedVotes[i].voter);
}
}
else {
numberOfDelegationRounds++;
uint lossRatio = 100 * delegatedPercent ** numberOfDelegationRounds / 100 ** numberOfDelegationRounds;
if (lossRatio > 0) {
for (i=1; i< delegatedVotes.length; i++){
v = delegatedVotes[i];
if (v.nominee != v.voter && voteWeight[v.voter] > 0) {
weight = voteWeight[v.voter] * lossRatio / 100;
voteWeight[v.voter] -= weight;
voteWeight[v.nominee] += weight;
}
if (numberOfDelegationRounds>3 && voteWeight[v.nominee] > currentMax) {
currentWinner = v.nominee;
currentMax = voteWeight[v.nominee];
}
}
}
}
if (numberOfDelegationRounds > 3) {
NewAppointee(currentWinner, appointee == currentWinner);
appointee = currentWinner;
}
return currentWinner;
}
}