-
Notifications
You must be signed in to change notification settings - Fork 3
/
SecurityDAO.sol
236 lines (195 loc) · 7.31 KB
/
SecurityDAO.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
pragma solidity ^0.4.11;
contract StakePool
{
function getWeight(address _staker) constant returns (uint256);
function totalVotingWeight() constant returns (uint256);
}
contract SecurityDAO {
// TODO: add events
struct auditor {
address addr;
string github_profile; // link
string email_address; // email
uint256 karma;
uint256 error_coefficient;
uint256 last_contribution;
bool manager;
}
struct election {
address addr;
uint256 votes_for;
uint256 votes_against;
uint256 start_date;
uint256 end_date;
bool active;
}
struct report {
string gist_link; // Assigned by creator.
string gist_hash; // Assigned by creator.
address author; // Assigned by creator.
uint256 timestamp; // Assigned automatically.
bool revealed; // Assigned automatically.
uint256 errors; // Assigned by manager.
uint256 bytecode_length; // Assigned by manager.
address[] signers; // Assigned by manager.
}
mapping (address => auditor) public auditors;
mapping (address => election) public elections;
mapping (uint256 => report) public reports;
uint256 public total_reports;
uint256 public election_duration = 25 days;
uint256 public inactivity_period = 15 days;
address public stake_pool;
function become_manager()
{
require( (msg.sender == auditors[msg.sender].addr) && (auditors[msg.sender].manager == false) );
require(elections[msg.sender].end_date < now);
require(elections[msg.sender].active = false);
elections[msg.sender].start_date = block.timestamp;
elections[msg.sender].end_date = block.timestamp + election_duration;
elections[msg.sender].active = true;
}
function become_auditor(string _github, string _email)
{
require( auditors[msg.sender].addr == 0x00 );
auditors[msg.sender].addr = msg.sender;
auditors[msg.sender].github_profile = _github;
auditors[msg.sender].email_address = _email;
auditors[msg.sender].error_coefficient = 2;
}
function vote_manager(address _who, bool _for)
{
require( (elections[_who].active = true) && (elections[msg.sender].end_date < now) );
if(_for)
{
elections[_who].votes_for += StakePool(stake_pool).getWeight(msg.sender);
}
else
{
elections[_who].votes_against += StakePool(stake_pool).getWeight(msg.sender);
}
}
function evaluate_election(address _who)
{
require(elections[_who].active = true);
require(elections[_who].end_date < now);
if(evaluateElection(_who))
{
auditors[_who].manager = true;
}
elections[_who].active = false;
}
function evaluateElection(address _who) private constant returns (bool)
{
// Make sure that at least 50% of voters have confirmed their position.
require( (elections[_who].votes_for + elections[_who].votes_against) > StakePool(stake_pool).totalVotingWeight() / 2 );
if(elections[_who].votes_for > elections[_who].votes_against)
{
return true;
}
return false;
}
function submit_report(string _gist_hash)
{
// Submit a private report.
require(msg.sender == auditors[msg.sender].addr);
reports[total_reports].gist_hash = _gist_hash;
reports[total_reports].timestamp = now;
reports[total_reports].author = msg.sender;
total_reports++;
}
function sign_report(string _gist_hash, uint256 _errors, uint256 _bytecode_length, uint256 _report_id)
{
// Sign private report before revealing.
require(auditors[msg.sender].manager);
require(!reports[_report_id].revealed); // TODO: implement signing an already-existing reports by multiple managers
reports[_report_id].errors = _errors;
reports[_report_id].bytecode_length = _bytecode_length;
reports[_report_id].signers.push(msg.sender);
}
function reveal_report(string _gist_hash, string _gist_link, uint256 _report_id)
{
// NOTE: manager that knows the gist link can reveal it.
// Report author can reveal his own report as well.
require(!reports[_report_id].revealed);
require(sha256(sha256(_gist_link)) == sha256(_gist_hash)); // TODO: explicit type conversions not allowed. Refactor this.
reports[_report_id].gist_link = _gist_link;
auditors[reports[_report_id].author].error_coefficient += reports[_report_id].errors;
auditors[reports[_report_id].author].karma += reports[_report_id].bytecode_length;
if(auditors[msg.sender].manager)
{
auditors[reports[_report_id].author].last_contribution = now;
}
}
function active(address _auditor) constant returns (bool)
{
return ( now - auditors[_auditor].last_contribution ) > inactivity_period;
}
function getKarma(address _auditor) constant returns (uint256)
{
return ( auditors[_auditor].karma / auditors[_auditor].error_coefficient );
}
//------------------- DEBUGGING FUNCTIONS ------------------------------------------
address public owner;
uint256 public debug_autodisable = 6500000; // Block number.
function debug() public constant returns (bool)
{
return block.number > debug_autodisable;
}
modifier only_owner
{
require(msg.sender == owner);
_;
}
modifier only_debug
{
_;
assert(debug());
}
/*struct auditor {
address addr;
string github_profile; // link
string email_address; // email
uint256 karma;
uint256 error_coefficient;
bool manager;
}*/
function configure_auditor(address _addr, string _github, string _email, uint256 _karma, uint256 _error, bool _manager) only_debug only_owner
{
auditors[_addr].addr = _addr;
auditors[_addr].github_profile = _github;
auditors[_addr].email_address = _email;
auditors[_addr].karma = _karma;
auditors[_addr].error_coefficient = _error;
auditors[_addr].manager = _manager;
}
/*struct report {
string gist_link; // Assigned by creator.
string gist_hash; // Assigned by creator.
address author; // Assigned by creator.
uint256 timestamp; // Assigned automatically.
bool revealed; // Assigned automatically.
uint256 errors; // Assigned by manager.
uint256 bytecode_length; // Assigned by manager.
address[] signers; // Assigned by manager.
}*/
function configure_report(uint _id, string _gist_link, string _gist_hash, address _author, uint256 _errors, uint256 _bytecode_length) only_debug only_owner
{
reports[_id].gist_link = _gist_link;
reports[_id].gist_hash = _gist_hash;
reports[_id].author = _author;
reports[_id].errors = _errors;
reports[_id].bytecode_length = _bytecode_length;
}
function add_signer(uint _id, address _signer) only_debug only_owner
{
reports[_id].signers.push(_signer);
}
function reset_signers(uint _id) only_debug only_owner
{
delete reports[_id].signers;
}
// TODO: rollback actions of malitious managers through voting.
// TODO: debugging functions.
// TODO: payment autodistribution.
}