@@ -17,7 +17,8 @@ contract Competition {
1717 uint256 _suggestionsEndTime ,
1818 uint256 _endTime ,
1919 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
2122 );
2223
2324 event Redeem (
@@ -30,7 +31,7 @@ contract Competition {
3031 bytes32 indexed _proposalId ,
3132 uint256 indexed _suggestionId ,
3233 string _descriptionHash ,
33- address payable indexed _suggester
34+ address payable indexed _beneficiary
3435 );
3536
3637 event NewVote (
@@ -61,6 +62,7 @@ contract Competition {
6162 uint256 nativeTokenReward;
6263 uint256 externalTokenReward;
6364 uint256 [] topSuggestions;
65+ address admin;
6466 //mapping from suggestions totalVotes to the number of suggestions with the same totalVotes.
6567 mapping (uint256 => uint256 ) suggestionsPerVote;
6668 mapping (address => uint256 ) votesPerVoter;
@@ -69,7 +71,7 @@ contract Competition {
6971 struct Suggestion {
7072 uint256 totalVotes;
7173 bytes32 proposalId;
72- address payable suggester ;
74+ address payable beneficiary ;
7375 mapping (address => uint256 ) votes;
7476 }
7577
@@ -108,6 +110,10 @@ contract Competition {
108110 * _competitionParams[2] - _endTime competition end time
109111 * _competitionParams[3] - _maxNumberOfVotesPerVoter on how many suggestions a voter can vote
110112 * _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.
111117 * @return proposalId the proposal id.
112118 */
113119 function proposeCompetition (
@@ -116,7 +122,8 @@ contract Competition {
116122 uint [3 ] calldata _rewards ,
117123 IERC20 _externalToken ,
118124 uint256 [] calldata _rewardSplit ,
119- uint256 [5 ] calldata _competitionParams
125+ uint256 [5 ] calldata _competitionParams ,
126+ bool _proposerIsAdmin
120127 )
121128 external
122129 returns (bytes32 proposalId ) {
@@ -141,12 +148,7 @@ contract Competition {
141148 }
142149 require (totalRewardSplit == 100 , "total rewards split is not 100% " );
143150 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 );
150152 proposals[proposalId].numberOfWinners = numberOfWinners;
151153 proposals[proposalId].rewardSplit = _rewardSplit;
152154 proposals[proposalId].startTime = startTime;
@@ -158,7 +160,9 @@ contract Competition {
158160 proposals[proposalId].nativeTokenReward = _rewards[0 ];
159161 proposals[proposalId].ethReward = _rewards[1 ];
160162 proposals[proposalId].externalTokenReward = _rewards[2 ];
161-
163+ if (_proposerIsAdmin) {
164+ proposals[proposalId].admin = msg .sender ;
165+ }
162166 emit NewCompetitionProposal (
163167 proposalId,
164168 numberOfWinners,
@@ -168,31 +172,43 @@ contract Competition {
168172 proposals[proposalId].suggestionsEndTime,
169173 proposals[proposalId].endTime,
170174 proposals[proposalId].maxNumberOfVotesPerVoter,
171- contributionRewardExt
175+ contributionRewardExt,
176+ proposals[proposalId].admin
172177 );
173178 }
174179
175180 /**
176181 * @dev submit a competion suggestion
177182 * @param _proposalId the proposal id this suggestion is referring to.
178183 * @param _descriptionHash a descriptionHash of the suggestion.
184+ * @param _beneficiary the beneficiary of this suggestion.
179185 * @return suggestionId the suggestionId.
180186 */
181187 function suggest (
182188 bytes32 _proposalId ,
183- string calldata _descriptionHash
189+ string calldata _descriptionHash ,
190+ address payable _beneficiary
184191 )
185192 external
186193 returns (uint256 )
187194 {
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
189199 require (proposals[_proposalId].startTime <= now , "competition not started yet " );
190200 // solhint-disable-next-line not-rely-on-time
191201 require (proposals[_proposalId].suggestionsEndTime > now , "suggestions submition time is over " );
192202 suggestionsCounter = suggestionsCounter.add (1 );
193203 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);
196212 return suggestionsCounter;
197213 }
198214
@@ -231,23 +247,6 @@ contract Competition {
231247 return true ;
232248 }
233249
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-
251250 /**
252251 * @dev setSnapshotBlock set the block for the reputaion snapshot
253252 * @param _proposalId the proposal id
@@ -270,7 +269,7 @@ contract Competition {
270269 require (proposals[_proposalId].endTime < now , "competition is still on " );
271270 uint256 [] memory topSuggestions = proposals[_proposalId].topSuggestions;
272271 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 " );
274273 }
275274
276275 (, , , , , ,
@@ -291,6 +290,58 @@ contract Competition {
291290 _proposalId, address (avatar), nativeTokenRewardLeft);
292291 }
293292
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+
294345 /**
295346 * @dev getOrderedIndexOfSuggestion return the index of specific suggestion in the winners list.
296347 * @param _suggestionId suggestion id
@@ -348,56 +399,4 @@ contract Competition {
348399 }
349400 }
350401
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-
403402}
0 commit comments