@@ -17,7 +17,8 @@ contract Competition {
17
17
uint256 _suggestionsEndTime ,
18
18
uint256 _endTime ,
19
19
uint256 _maxNumberOfVotesPerVoter ,
20
- address payable _contributionRewardExt //address of the contract to redeem from.
20
+ address payable _contributionRewardExt , //address of the contract to redeem from.
21
+ address _admin
21
22
);
22
23
23
24
event Redeem (
@@ -30,7 +31,7 @@ contract Competition {
30
31
bytes32 indexed _proposalId ,
31
32
uint256 indexed _suggestionId ,
32
33
string _descriptionHash ,
33
- address payable indexed _suggester
34
+ address payable indexed _beneficiary
34
35
);
35
36
36
37
event NewVote (
@@ -61,6 +62,7 @@ contract Competition {
61
62
uint256 nativeTokenReward;
62
63
uint256 externalTokenReward;
63
64
uint256 [] topSuggestions;
65
+ address admin;
64
66
//mapping from suggestions totalVotes to the number of suggestions with the same totalVotes.
65
67
mapping (uint256 => uint256 ) suggestionsPerVote;
66
68
mapping (address => uint256 ) votesPerVoter;
@@ -69,7 +71,7 @@ contract Competition {
69
71
struct Suggestion {
70
72
uint256 totalVotes;
71
73
bytes32 proposalId;
72
- address payable suggester ;
74
+ address payable beneficiary ;
73
75
mapping (address => uint256 ) votes;
74
76
}
75
77
@@ -108,6 +110,10 @@ contract Competition {
108
110
* _competitionParams[2] - _endTime competition end time
109
111
* _competitionParams[3] - _maxNumberOfVotesPerVoter on how many suggestions a voter can vote
110
112
* _competitionParams[4] - _suggestionsEndTime suggestion submition end time
113
+ * _proposerIsAdmin -
114
+ * true - proposer is an admin.
115
+ * false no admin.
116
+ * if admin is set, so only admin can suggest on this proposal.
111
117
* @return proposalId the proposal id.
112
118
*/
113
119
function proposeCompetition (
@@ -116,7 +122,8 @@ contract Competition {
116
122
uint [3 ] calldata _rewards ,
117
123
IERC20 _externalToken ,
118
124
uint256 [] calldata _rewardSplit ,
119
- uint256 [5 ] calldata _competitionParams
125
+ uint256 [5 ] calldata _competitionParams ,
126
+ bool _proposerIsAdmin
120
127
)
121
128
external
122
129
returns (bytes32 proposalId ) {
@@ -141,12 +148,7 @@ contract Competition {
141
148
}
142
149
require (totalRewardSplit == 100 , "total rewards split is not 100% " );
143
150
proposalId = ContributionRewardExt (contributionRewardExt).proposeContributionReward (
144
- _descriptionHash,
145
- _reputationChange,
146
- _rewards,
147
- _externalToken,
148
- contributionRewardExt,
149
- msg .sender );
151
+ _descriptionHash, _reputationChange, _rewards, _externalToken, contributionRewardExt, msg .sender );
150
152
proposals[proposalId].numberOfWinners = numberOfWinners;
151
153
proposals[proposalId].rewardSplit = _rewardSplit;
152
154
proposals[proposalId].startTime = startTime;
@@ -158,7 +160,9 @@ contract Competition {
158
160
proposals[proposalId].nativeTokenReward = _rewards[0 ];
159
161
proposals[proposalId].ethReward = _rewards[1 ];
160
162
proposals[proposalId].externalTokenReward = _rewards[2 ];
161
-
163
+ if (_proposerIsAdmin) {
164
+ proposals[proposalId].admin = msg .sender ;
165
+ }
162
166
emit NewCompetitionProposal (
163
167
proposalId,
164
168
numberOfWinners,
@@ -168,31 +172,43 @@ contract Competition {
168
172
proposals[proposalId].suggestionsEndTime,
169
173
proposals[proposalId].endTime,
170
174
proposals[proposalId].maxNumberOfVotesPerVoter,
171
- contributionRewardExt
175
+ contributionRewardExt,
176
+ proposals[proposalId].admin
172
177
);
173
178
}
174
179
175
180
/**
176
181
* @dev submit a competion suggestion
177
182
* @param _proposalId the proposal id this suggestion is referring to.
178
183
* @param _descriptionHash a descriptionHash of the suggestion.
184
+ * @param _beneficiary the beneficiary of this suggestion.
179
185
* @return suggestionId the suggestionId.
180
186
*/
181
187
function suggest (
182
188
bytes32 _proposalId ,
183
- string calldata _descriptionHash
189
+ string calldata _descriptionHash ,
190
+ address payable _beneficiary
184
191
)
185
192
external
186
193
returns (uint256 )
187
194
{
188
- // solhint-disable-next-line not-rely-on-time
195
+ if (proposals[_proposalId].admin != address (0 )) {
196
+ require (proposals[_proposalId].admin == msg .sender , "only admin can suggest " );
197
+ }
198
+ // solhint-disable-next-line not-rely-on-time
189
199
require (proposals[_proposalId].startTime <= now , "competition not started yet " );
190
200
// solhint-disable-next-line not-rely-on-time
191
201
require (proposals[_proposalId].suggestionsEndTime > now , "suggestions submition time is over " );
192
202
suggestionsCounter = suggestionsCounter.add (1 );
193
203
suggestions[suggestionsCounter].proposalId = _proposalId;
194
- suggestions[suggestionsCounter].suggester = msg .sender ;
195
- emit NewSuggestion (_proposalId, suggestionsCounter, _descriptionHash, msg .sender );
204
+ address payable beneficiary;
205
+ if (_beneficiary == address (0 )) {
206
+ beneficiary = msg .sender ;
207
+ } else {
208
+ beneficiary = _beneficiary;
209
+ }
210
+ suggestions[suggestionsCounter].beneficiary = beneficiary;
211
+ emit NewSuggestion (_proposalId, suggestionsCounter, _descriptionHash, beneficiary);
196
212
return suggestionsCounter;
197
213
}
198
214
@@ -231,23 +247,6 @@ contract Competition {
231
247
return true ;
232
248
}
233
249
234
- /**
235
- * @dev redeem a winning suggestion reward
236
- * @param _suggestionId suggestionId
237
- * @param _beneficiary - the reward beneficiary.
238
- * this parameter is take into account only if the msg.sender is the suggestion's suggester,
239
- * otherwise the _beneficiary param is ignored and the beneficiary is suggestion's suggester.
240
- */
241
- function redeem (uint256 _suggestionId , address payable _beneficiary ) external {
242
- address payable beneficiary = suggestions[_suggestionId].suggester;
243
- if ((msg .sender == suggestions[_suggestionId].suggester) &&
244
- (_beneficiary != address (0 ))) {
245
- //only suggester can redeem to other address
246
- beneficiary = _beneficiary;
247
- }
248
- _redeem (_suggestionId, beneficiary);
249
- }
250
-
251
250
/**
252
251
* @dev setSnapshotBlock set the block for the reputaion snapshot
253
252
* @param _proposalId the proposal id
@@ -270,7 +269,7 @@ contract Competition {
270
269
require (proposals[_proposalId].endTime < now , "competition is still on " );
271
270
uint256 [] memory topSuggestions = proposals[_proposalId].topSuggestions;
272
271
for (uint256 i; i < topSuggestions.length ; i++ ) {
273
- require (suggestions[topSuggestions[i]].suggester == address (0 ), "not all winning suggestions redeemed " );
272
+ require (suggestions[topSuggestions[i]].beneficiary == address (0 ), "not all winning suggestions redeemed " );
274
273
}
275
274
276
275
(, , , , , ,
@@ -291,6 +290,58 @@ contract Competition {
291
290
_proposalId, address (avatar), nativeTokenRewardLeft);
292
291
}
293
292
293
+ /**
294
+ * @dev redeem a winning suggestion reward
295
+ * @param _suggestionId suggestionId
296
+ */
297
+ function redeem (uint256 _suggestionId ) public {
298
+ bytes32 proposalId = suggestions[_suggestionId].proposalId;
299
+ Proposal storage proposal = proposals[proposalId];
300
+ // solhint-disable-next-line not-rely-on-time
301
+ require (proposal.endTime < now , "competition is still on " );
302
+ require (suggestions[_suggestionId].beneficiary != address (0 ),
303
+ "suggestion was already redeemed " );
304
+ address payable beneficiary = suggestions[_suggestionId].beneficiary;
305
+ uint256 orderIndex = getOrderedIndexOfSuggestion (_suggestionId);
306
+ require (orderIndex < proposal.topSuggestions.length , "suggestion is not in winners list " );
307
+ suggestions[_suggestionId].beneficiary = address (0 );
308
+ uint256 rewardPercentage = 0 ;
309
+ uint256 numberOfTieSuggestions = proposal.suggestionsPerVote[suggestions[_suggestionId].totalVotes];
310
+ uint256 j;
311
+ //calc the reward percentage for this suggestion
312
+ for (j = orderIndex; j < (orderIndex+ numberOfTieSuggestions) && j < proposal.numberOfWinners; j++ ) {
313
+ rewardPercentage = rewardPercentage.add (proposal.rewardSplit[j]);
314
+ }
315
+ rewardPercentage = rewardPercentage.div (numberOfTieSuggestions);
316
+ uint256 rewardPercentageLeft = 0 ;
317
+ if (proposal.topSuggestions.length < proposal.numberOfWinners) {
318
+ //if there are less winners than the proposal number of winners so divide the pre allocated
319
+ //left reward equally between the winners
320
+ for (j = proposal.topSuggestions.length ; j < proposal.numberOfWinners; j++ ) {
321
+ rewardPercentageLeft = rewardPercentageLeft.add (proposal.rewardSplit[j]);
322
+ }
323
+ rewardPercentage =
324
+ rewardPercentage.add (rewardPercentageLeft.div (proposal.topSuggestions.length ));
325
+ }
326
+ uint256 amount;
327
+ amount = proposal.externalTokenReward.mul (rewardPercentage).div (100 );
328
+ ContributionRewardExt (contributionRewardExt).redeemExternalTokenByRewarder (
329
+ proposalId, beneficiary, amount);
330
+
331
+ amount = proposal.reputationReward.mul (rewardPercentage).div (100 );
332
+ ContributionRewardExt (contributionRewardExt).redeemReputationByRewarder (
333
+ proposalId, beneficiary, amount);
334
+
335
+ amount = proposal.ethReward.mul (rewardPercentage).div (100 );
336
+ ContributionRewardExt (contributionRewardExt).redeemEtherByRewarder (
337
+ proposalId, beneficiary, amount);
338
+
339
+ amount = proposal.nativeTokenReward.mul (rewardPercentage).div (100 );
340
+ ContributionRewardExt (contributionRewardExt).redeemNativeTokenByRewarder (
341
+ proposalId, beneficiary, amount);
342
+ emit Redeem (proposalId, _suggestionId, rewardPercentage);
343
+ }
344
+
294
345
/**
295
346
* @dev getOrderedIndexOfSuggestion return the index of specific suggestion in the winners list.
296
347
* @param _suggestionId suggestion id
@@ -348,56 +399,4 @@ contract Competition {
348
399
}
349
400
}
350
401
351
- /**
352
- * @dev redeem a winning suggestion reward
353
- * @param _suggestionId suggestionId
354
- * @param _beneficiary - the reward beneficiary
355
- */
356
- function _redeem (uint256 _suggestionId , address payable _beneficiary ) private {
357
- bytes32 proposalId = suggestions[_suggestionId].proposalId;
358
- Proposal storage proposal = proposals[proposalId];
359
- // solhint-disable-next-line not-rely-on-time
360
- require (proposal.endTime < now , "competition is still on " );
361
- require (suggestions[_suggestionId].suggester != address (0 ),
362
- "suggestion was already redeemed " );
363
- uint256 orderIndex = getOrderedIndexOfSuggestion (_suggestionId);
364
- require (orderIndex < proposal.topSuggestions.length , "suggestion is not in winners list " );
365
- suggestions[_suggestionId].suggester = address (0 );
366
- uint256 rewardPercentage = 0 ;
367
- uint256 numberOfTieSuggestions = proposal.suggestionsPerVote[suggestions[_suggestionId].totalVotes];
368
- uint256 j;
369
- //calc the reward percentage for this suggestion
370
- for (j = orderIndex; j < (orderIndex+ numberOfTieSuggestions) && j < proposal.numberOfWinners; j++ ) {
371
- rewardPercentage = rewardPercentage.add (proposal.rewardSplit[j]);
372
- }
373
- rewardPercentage = rewardPercentage.div (numberOfTieSuggestions);
374
- uint256 rewardPercentageLeft = 0 ;
375
- if (proposal.topSuggestions.length < proposal.numberOfWinners) {
376
- //if there are less winners than the proposal number of winners so divide the pre allocated
377
- //left reward equally between the winners
378
- for (j = proposal.topSuggestions.length ; j < proposal.numberOfWinners; j++ ) {
379
- rewardPercentageLeft = rewardPercentageLeft.add (proposal.rewardSplit[j]);
380
- }
381
- rewardPercentage =
382
- rewardPercentage.add (rewardPercentageLeft.div (proposal.topSuggestions.length ));
383
- }
384
- uint256 amount;
385
- amount = proposal.externalTokenReward.mul (rewardPercentage).div (100 );
386
- ContributionRewardExt (contributionRewardExt).redeemExternalTokenByRewarder (
387
- proposalId, _beneficiary, amount);
388
-
389
- amount = proposal.reputationReward.mul (rewardPercentage).div (100 );
390
- ContributionRewardExt (contributionRewardExt).redeemReputationByRewarder (
391
- proposalId, _beneficiary, amount);
392
-
393
- amount = proposal.ethReward.mul (rewardPercentage).div (100 );
394
- ContributionRewardExt (contributionRewardExt).redeemEtherByRewarder (
395
- proposalId, _beneficiary, amount);
396
-
397
- amount = proposal.nativeTokenReward.mul (rewardPercentage).div (100 );
398
- ContributionRewardExt (contributionRewardExt).redeemNativeTokenByRewarder (
399
- proposalId, _beneficiary, amount);
400
- emit Redeem (proposalId, _suggestionId, rewardPercentage);
401
- }
402
-
403
402
}
0 commit comments