Skip to content

Commit

Permalink
Competition enhance (#710)
Browse files Browse the repository at this point in the history
* authorizedRepMinter : add burn functionality

* add _proposerIsAdmin

* rename ReputationAdmin

* bump v to 0.0.1-rc.39
  • Loading branch information
orenyodfat authored Jan 23, 2020
1 parent 0aaf2e7 commit 7facd80
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 217 deletions.
63 changes: 0 additions & 63 deletions contracts/schemes/AuthorizedMintRep.sol

This file was deleted.

171 changes: 85 additions & 86 deletions contracts/schemes/Competition.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ contract Competition {
uint256 _suggestionsEndTime,
uint256 _endTime,
uint256 _maxNumberOfVotesPerVoter,
address payable _contributionRewardExt //address of the contract to redeem from.
address payable _contributionRewardExt, //address of the contract to redeem from.
address _admin
);

event Redeem(
Expand All @@ -30,7 +31,7 @@ contract Competition {
bytes32 indexed _proposalId,
uint256 indexed _suggestionId,
string _descriptionHash,
address payable indexed _suggester
address payable indexed _beneficiary
);

event NewVote(
Expand Down Expand Up @@ -61,6 +62,7 @@ contract Competition {
uint256 nativeTokenReward;
uint256 externalTokenReward;
uint256[] topSuggestions;
address admin;
//mapping from suggestions totalVotes to the number of suggestions with the same totalVotes.
mapping(uint256=>uint256) suggestionsPerVote;
mapping(address=>uint256) votesPerVoter;
Expand All @@ -69,7 +71,7 @@ contract Competition {
struct Suggestion {
uint256 totalVotes;
bytes32 proposalId;
address payable suggester;
address payable beneficiary;
mapping(address=>uint256) votes;
}

Expand Down Expand Up @@ -108,6 +110,10 @@ contract Competition {
* _competitionParams[2] - _endTime competition end time
* _competitionParams[3] - _maxNumberOfVotesPerVoter on how many suggestions a voter can vote
* _competitionParams[4] - _suggestionsEndTime suggestion submition end time
* _proposerIsAdmin -
* true - proposer is an admin.
* false no admin.
* if admin is set, so only admin can suggest on this proposal.
* @return proposalId the proposal id.
*/
function proposeCompetition(
Expand All @@ -116,7 +122,8 @@ contract Competition {
uint[3] calldata _rewards,
IERC20 _externalToken,
uint256[] calldata _rewardSplit,
uint256[5] calldata _competitionParams
uint256[5] calldata _competitionParams,
bool _proposerIsAdmin
)
external
returns(bytes32 proposalId) {
Expand All @@ -141,12 +148,7 @@ contract Competition {
}
require(totalRewardSplit == 100, "total rewards split is not 100%");
proposalId = ContributionRewardExt(contributionRewardExt).proposeContributionReward(
_descriptionHash,
_reputationChange,
_rewards,
_externalToken,
contributionRewardExt,
msg.sender);
_descriptionHash, _reputationChange, _rewards, _externalToken, contributionRewardExt, msg.sender);
proposals[proposalId].numberOfWinners = numberOfWinners;
proposals[proposalId].rewardSplit = _rewardSplit;
proposals[proposalId].startTime = startTime;
Expand All @@ -158,7 +160,9 @@ contract Competition {
proposals[proposalId].nativeTokenReward = _rewards[0];
proposals[proposalId].ethReward = _rewards[1];
proposals[proposalId].externalTokenReward = _rewards[2];

if (_proposerIsAdmin) {
proposals[proposalId].admin = msg.sender;
}
emit NewCompetitionProposal(
proposalId,
numberOfWinners,
Expand All @@ -168,31 +172,43 @@ contract Competition {
proposals[proposalId].suggestionsEndTime,
proposals[proposalId].endTime,
proposals[proposalId].maxNumberOfVotesPerVoter,
contributionRewardExt
contributionRewardExt,
proposals[proposalId].admin
);
}

/**
* @dev submit a competion suggestion
* @param _proposalId the proposal id this suggestion is referring to.
* @param _descriptionHash a descriptionHash of the suggestion.
* @param _beneficiary the beneficiary of this suggestion.
* @return suggestionId the suggestionId.
*/
function suggest(
bytes32 _proposalId,
string calldata _descriptionHash
string calldata _descriptionHash,
address payable _beneficiary
)
external
returns(uint256)
{
// solhint-disable-next-line not-rely-on-time
if (proposals[_proposalId].admin != address(0)) {
require(proposals[_proposalId].admin == msg.sender, "only admin can suggest");
}
// solhint-disable-next-line not-rely-on-time
require(proposals[_proposalId].startTime <= now, "competition not started yet");
// solhint-disable-next-line not-rely-on-time
require(proposals[_proposalId].suggestionsEndTime > now, "suggestions submition time is over");
suggestionsCounter = suggestionsCounter.add(1);
suggestions[suggestionsCounter].proposalId = _proposalId;
suggestions[suggestionsCounter].suggester = msg.sender;
emit NewSuggestion(_proposalId, suggestionsCounter, _descriptionHash, msg.sender);
address payable beneficiary;
if (_beneficiary == address(0)) {
beneficiary = msg.sender;
} else {
beneficiary = _beneficiary;
}
suggestions[suggestionsCounter].beneficiary = beneficiary;
emit NewSuggestion(_proposalId, suggestionsCounter, _descriptionHash, beneficiary);
return suggestionsCounter;
}

Expand Down Expand Up @@ -231,23 +247,6 @@ contract Competition {
return true;
}

/**
* @dev redeem a winning suggestion reward
* @param _suggestionId suggestionId
* @param _beneficiary - the reward beneficiary.
* this parameter is take into account only if the msg.sender is the suggestion's suggester,
* otherwise the _beneficiary param is ignored and the beneficiary is suggestion's suggester.
*/
function redeem(uint256 _suggestionId, address payable _beneficiary) external {
address payable beneficiary = suggestions[_suggestionId].suggester;
if ((msg.sender == suggestions[_suggestionId].suggester) &&
(_beneficiary != address(0))) {
//only suggester can redeem to other address
beneficiary = _beneficiary;
}
_redeem(_suggestionId, beneficiary);
}

/**
* @dev setSnapshotBlock set the block for the reputaion snapshot
* @param _proposalId the proposal id
Expand All @@ -270,7 +269,7 @@ contract Competition {
require(proposals[_proposalId].endTime < now, "competition is still on");
uint256[] memory topSuggestions = proposals[_proposalId].topSuggestions;
for (uint256 i; i < topSuggestions.length; i++) {
require(suggestions[topSuggestions[i]].suggester == address(0), "not all winning suggestions redeemed");
require(suggestions[topSuggestions[i]].beneficiary == address(0), "not all winning suggestions redeemed");
}

(, , , , , ,
Expand All @@ -291,6 +290,58 @@ contract Competition {
_proposalId, address(avatar), nativeTokenRewardLeft);
}

/**
* @dev redeem a winning suggestion reward
* @param _suggestionId suggestionId
*/
function redeem(uint256 _suggestionId) public {
bytes32 proposalId = suggestions[_suggestionId].proposalId;
Proposal storage proposal = proposals[proposalId];
// solhint-disable-next-line not-rely-on-time
require(proposal.endTime < now, "competition is still on");
require(suggestions[_suggestionId].beneficiary != address(0),
"suggestion was already redeemed");
address payable beneficiary = suggestions[_suggestionId].beneficiary;
uint256 orderIndex = getOrderedIndexOfSuggestion(_suggestionId);
require(orderIndex < proposal.topSuggestions.length, "suggestion is not in winners list");
suggestions[_suggestionId].beneficiary = address(0);
uint256 rewardPercentage = 0;
uint256 numberOfTieSuggestions = proposal.suggestionsPerVote[suggestions[_suggestionId].totalVotes];
uint256 j;
//calc the reward percentage for this suggestion
for (j = orderIndex; j < (orderIndex+numberOfTieSuggestions) && j < proposal.numberOfWinners; j++) {
rewardPercentage = rewardPercentage.add(proposal.rewardSplit[j]);
}
rewardPercentage = rewardPercentage.div(numberOfTieSuggestions);
uint256 rewardPercentageLeft = 0;
if (proposal.topSuggestions.length < proposal.numberOfWinners) {
//if there are less winners than the proposal number of winners so divide the pre allocated
//left reward equally between the winners
for (j = proposal.topSuggestions.length; j < proposal.numberOfWinners; j++) {
rewardPercentageLeft = rewardPercentageLeft.add(proposal.rewardSplit[j]);
}
rewardPercentage =
rewardPercentage.add(rewardPercentageLeft.div(proposal.topSuggestions.length));
}
uint256 amount;
amount = proposal.externalTokenReward.mul(rewardPercentage).div(100);
ContributionRewardExt(contributionRewardExt).redeemExternalTokenByRewarder(
proposalId, beneficiary, amount);

amount = proposal.reputationReward.mul(rewardPercentage).div(100);
ContributionRewardExt(contributionRewardExt).redeemReputationByRewarder(
proposalId, beneficiary, amount);

amount = proposal.ethReward.mul(rewardPercentage).div(100);
ContributionRewardExt(contributionRewardExt).redeemEtherByRewarder(
proposalId, beneficiary, amount);

amount = proposal.nativeTokenReward.mul(rewardPercentage).div(100);
ContributionRewardExt(contributionRewardExt).redeemNativeTokenByRewarder(
proposalId, beneficiary, amount);
emit Redeem(proposalId, _suggestionId, rewardPercentage);
}

/**
* @dev getOrderedIndexOfSuggestion return the index of specific suggestion in the winners list.
* @param _suggestionId suggestion id
Expand Down Expand Up @@ -348,56 +399,4 @@ contract Competition {
}
}

/**
* @dev redeem a winning suggestion reward
* @param _suggestionId suggestionId
* @param _beneficiary - the reward beneficiary
*/
function _redeem(uint256 _suggestionId, address payable _beneficiary) private {
bytes32 proposalId = suggestions[_suggestionId].proposalId;
Proposal storage proposal = proposals[proposalId];
// solhint-disable-next-line not-rely-on-time
require(proposal.endTime < now, "competition is still on");
require(suggestions[_suggestionId].suggester != address(0),
"suggestion was already redeemed");
uint256 orderIndex = getOrderedIndexOfSuggestion(_suggestionId);
require(orderIndex < proposal.topSuggestions.length, "suggestion is not in winners list");
suggestions[_suggestionId].suggester = address(0);
uint256 rewardPercentage = 0;
uint256 numberOfTieSuggestions = proposal.suggestionsPerVote[suggestions[_suggestionId].totalVotes];
uint256 j;
//calc the reward percentage for this suggestion
for (j = orderIndex; j < (orderIndex+numberOfTieSuggestions) && j < proposal.numberOfWinners; j++) {
rewardPercentage = rewardPercentage.add(proposal.rewardSplit[j]);
}
rewardPercentage = rewardPercentage.div(numberOfTieSuggestions);
uint256 rewardPercentageLeft = 0;
if (proposal.topSuggestions.length < proposal.numberOfWinners) {
//if there are less winners than the proposal number of winners so divide the pre allocated
//left reward equally between the winners
for (j = proposal.topSuggestions.length; j < proposal.numberOfWinners; j++) {
rewardPercentageLeft = rewardPercentageLeft.add(proposal.rewardSplit[j]);
}
rewardPercentage =
rewardPercentage.add(rewardPercentageLeft.div(proposal.topSuggestions.length));
}
uint256 amount;
amount = proposal.externalTokenReward.mul(rewardPercentage).div(100);
ContributionRewardExt(contributionRewardExt).redeemExternalTokenByRewarder(
proposalId, _beneficiary, amount);

amount = proposal.reputationReward.mul(rewardPercentage).div(100);
ContributionRewardExt(contributionRewardExt).redeemReputationByRewarder(
proposalId, _beneficiary, amount);

amount = proposal.ethReward.mul(rewardPercentage).div(100);
ContributionRewardExt(contributionRewardExt).redeemEtherByRewarder(
proposalId, _beneficiary, amount);

amount = proposal.nativeTokenReward.mul(rewardPercentage).div(100);
ContributionRewardExt(contributionRewardExt).redeemNativeTokenByRewarder(
proposalId, _beneficiary, amount);
emit Redeem(proposalId, _suggestionId, rewardPercentage);
}

}
Loading

0 comments on commit 7facd80

Please sign in to comment.