forked from blockchainsllc/DAO
-
Notifications
You must be signed in to change notification settings - Fork 1
/
DTHPool.sol
320 lines (240 loc) · 9.6 KB
/
DTHPool.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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*
This file is part of the DAO.
The DAO is free software: you can redistribute it and/or modify
it under the terms of the GNU lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The DAO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU lesser General Public License for more details.
You should have received a copy of the GNU lesser General Public License
along with the DAO. If not, see <http://www.gnu.org/licenses/>.
*/
import "./libs/oraclize.sol";
import "./Token.sol";
/////////////////////
// There is a solidity bug in the return parameters that it's not solved
// when the bug is solved, the import from DAO is more clean.
// In the meantime, a workaround proxy is defined
// Uncoment this line when error fixed
// import "./DAO.sol";
// Workaround proxy remove when fixed
contract DAO {
function proposals(uint _proposalID) returns(
address recipient,
uint amount,
uint descriptionIdx,
uint votingDeadline,
bool open,
bool proposalPassed,
bytes32 proposalHash,
uint proposalDeposit,
bool newCurator
);
function transfer(address _to, uint256 _amount) returns (bool success);
function transferFrom(address _from, address _to, uint256 _amount) returns (bool success);
function vote(
uint _proposalID,
bool _supportsProposal
) returns (uint _voteID);
function balanceOf(address _owner) constant returns (uint256 balance);
}
// End of workaround proxy
////////////////////
contract DTHPoolInterface {
// delegae url
string public delegateUrl;
// Max time the tokens can be blocked.
// The real voting in the DAO will be called in the last moment in order
// to block the tokens for the minimum time. This parameter defines the
// seconds before the voting period ends that the vote can be performed
uint maxTimeBlocked;
// Address of the delegate
address public delegate;
// The DAO contract
address public daoAddress;
struct ProposalStatus {
// True when the delegate sets the vote
bool voteSet;
// True if the proposal should ve voted
bool willVote;
// True if the proposal should be accepted.
bool suportProposal;
// True when the vote is performed;
bool executed;
// Proposal votingDeadline
uint votingDeadline;
// String set by the delegator with the motivation
string motivation;
}
// Statuses of the diferent proposal
mapping (uint => ProposalStatus) public proposalStatuses;
// Index of proposals by oraclizeId
mapping (bytes32 => uint) public oraclizeId2proposalId;
/// @dev Constructor setting the dao address and the delegate
/// @param _daoAddress address of the DAO
/// @param _delegate adddress of the delegate.
/// @param _maxTimeBlocked the maximum time the tokens will be blocked
/// @param _delegateName Name of the delegate
/// @param _delegateUrl Url of the delegate
/// @param _tokenSymbol token symbol.
// DTHPool(address _daoAddress, address _delegate, uint _maxTimeBlocked, string _delegateName, string _delegateUrl, string _tokenSymbol);
/// @notice send votes to this contract.
/// @param _amount Tokens that will be transfered to the pool.
/// @return Whether the transfer was successful or not
function delegateDAOTokens(uint _amount) returns (bool _success);
/// Returns DAO tokens to the original
/// @param _amount that will be transfered back to the owner.
/// @return Whether the transfer was successful or not
function undelegateDAOTokens(uint _amount) returns (bool _success);
/// @notice This method will be called by the delegate to publish what will
/// be his vote in a specific proposal.
/// @param _proposalID The proposal to set the vote.
/// @param _willVote true If the proposal will be voted.
/// @param _supportsProposal What will be the vote.
function setVoteIntention(
uint _proposalID,
bool _willVote,
bool _supportsProposal,
string _motivation
) returns (bool _success);
/// @notice This method will be doing the actual voting in the DAO
/// for the _proposalID
/// @param _proposalID The proposal to set the vote.
/// @return _finalized true if this vote Proposal must not be executed again.
function executeVote(uint _proposalID) returns (bool _finalized);
/// @notice This function is intended because if some body sends tokens
/// directly to this contract, the tokens can be sent to the delegate
function fixTokens() returns (bool _success);
/// @notice If some body sends ether to this contract, the delegate will be
/// able to extract it.
function getEther() returns (uint _amount);
/// @notice Called when some body delegates token to the pool
event Delegate(address indexed _from, uint256 _amount);
/// @notice Called when some body undelegates token to the pool
event Undelegate(address indexed _from, uint256 _amount);
/// @notice Called when the delegate set se vote intention
event VoteIntentionSet(uint indexed _proposalID, bool _willVote, bool _supportsProposal);
/// @notice Called when the vote is executed in the DAO
event VoteExecuted(uint indexed _proposalID);
}
contract DTHPool is DTHPoolInterface, Token, usingOraclize {
modifier onlyDelegate() {if (msg.sender != delegate) throw; _}
// DTHPool(address _daoAddress, address _delegate, uint _maxTimeBlocked, string _delegateName, string _delegateUrl, string _tokenSymbol);
function DTHPool(
address _daoAddress,
address _delegate,
uint _maxTimeBlocked,
string _delegateName,
string _delegateUrl,
string _tokenSymbol
) {
daoAddress = _daoAddress;
delegate = _delegate;
delegateUrl = _delegateUrl;
maxTimeBlocked = _maxTimeBlocked;
name = _delegateName;
symbol = _tokenSymbol;
decimals = 16;
oraclize_setNetwork(networkID_auto);
}
function delegateDAOTokens(uint _amount) returns (bool _success) {
DAO dao = DAO(daoAddress);
if (!dao.transferFrom(msg.sender, address(this), _amount)) {
throw;
}
balances[msg.sender] += _amount;
totalSupply += _amount;
Delegate(msg.sender, _amount);
return true;
}
function undelegateDAOTokens(uint _amount) returns (bool _success) {
DAO dao = DAO(daoAddress);
if (_amount > balances[msg.sender]) {
throw;
}
if (!dao.transfer(msg.sender, _amount)) {
throw;
}
balances[msg.sender] -= _amount;
totalSupply -= _amount;
Undelegate(msg.sender, _amount);
return true;
}
function setVoteIntention(
uint _proposalID,
bool _willVote,
bool _supportsProposal,
string _motivation
) onlyDelegate returns (bool _success) {
DAO dao = DAO(daoAddress);
ProposalStatus proposalStatus = proposalStatuses[_proposalID];
if (proposalStatus.voteSet) {
throw;
}
var (,,,votingDeadline, ,,,,newCurator) = dao.proposals(_proposalID);
if (votingDeadline < now || newCurator ) {
throw;
}
proposalStatus.voteSet = true;
proposalStatus.willVote = _willVote;
proposalStatus.suportProposal = _supportsProposal;
proposalStatus.votingDeadline = votingDeadline;
proposalStatus.motivation = _motivation;
VoteIntentionSet(_proposalID, _willVote, _supportsProposal);
if (!_willVote) {
proposalStatus.executed = true;
VoteExecuted(_proposalID);
}
bool finalized = executeVote(_proposalID);
if ((!finalized)&&(address(OAR) != 0)) {
bytes32 oraclizeId = oraclize_query(votingDeadline - maxTimeBlocked +15, "URL", "");
oraclizeId2proposalId[oraclizeId] = _proposalID;
}
return true;
}
function executeVote(uint _proposalID) returns (bool _finalized) {
DAO dao = DAO(daoAddress);
ProposalStatus proposalStatus = proposalStatuses[_proposalID];
if (!proposalStatus.voteSet
|| now > proposalStatus.votingDeadline
|| !proposalStatus.willVote
|| proposalStatus.executed) {
return true;
}
if (now < proposalStatus.votingDeadline - maxTimeBlocked) {
return false;
}
dao.vote(_proposalID, proposalStatus.suportProposal);
proposalStatus.executed = true;
VoteExecuted(_proposalID);
return true;
}
function __callback(bytes32 oid, string result) {
uint proposalId = oraclizeId2proposalId[oid];
executeVote(proposalId);
oraclizeId2proposalId[oid] = 0;
}
function fixTokens() returns (bool _success) {
DAO dao = DAO(daoAddress);
uint ownedTokens = dao.balanceOf(this);
if (ownedTokens < totalSupply) {
throw;
}
uint fixTokens = ownedTokens - totalSupply;
if (fixTokens == 0) {
return true;
}
balances[delegate] += fixTokens;
totalSupply += fixTokens;
return true;
}
function getEther() onlyDelegate returns (uint _amount) {
uint amount = this.balance;
if (!delegate.call.value(amount)()) {
throw;
}
return amount;
}
}