pragmasolidity^0.5.2;import"openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol";import"openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol";contractRewardsisERC20Mintable,ERC20Detailed{usingSafeMathforuint256;uint256publicroundMask;uint256publiclastMintedBlockNumber;uint256publictotalParticipants=0;uint256publictokensPerBlock;uint256publicblockFreezeInterval;addresspublictokencontractAddress=address(this);mapping(address=>uint256)publicparticipantMask;/**
* @dev constructor, initializes variables.
* @param _tokensPerBlock The amount of token that will be released per block, entered in wei format (E.g. 1000000000000000000)
* @param _blockFreezeInterval The amount of blocks that need to pass (E.g. 1, 10, 100) before more tokens are brought into the ecosystem.
*/constructor(uint256_tokensPerBlock,uint256_blockFreezeInterval)publicERC20Detailed("Simple Token","SIM",18){lastMintedBlockNumber=block.number;tokensPerBlock=_tokensPerBlock;blockFreezeInterval=_blockFreezeInterval;}/**
* @dev Modifier to check if msg.sender is whitelisted as a minter.
*/modifierisAuthorized(){require(isMinter(msg.sender));_;}/**
* @dev Function to add participants in the network.
* @param _minter The address that will be able to mint tokens.
* @return A boolean that indicates if the operation was successful.
*/functionaddMinters(address_minter)externalreturns(bool){_addMinter(_minter);totalParticipants=totalParticipants.add(1);updateParticipantMask(_minter);returntrue;}/**
* @dev Function to remove participants in the network.
* @param _minter The address that will be unable to mint tokens.
* @return A boolean that indicates if the operation was successful.
*/functionremoveMinters(address_minter)externalreturns(bool){totalParticipants=totalParticipants.sub(1);_removeMinter(_minter);returntrue;}/**
* @dev Function to introduce new tokens in the network.
* @return A boolean that indicates if the operation was successful.
*/functiontrigger()externalisAuthorizedreturns(bool){boolres=readyToMint();if(res==false){returnfalse;}else{mintTokens();returntrue;}}/**
* @dev Function to withdraw rewarded tokens by a participant.
* @return A boolean that indicates if the operation was successful.
*/functionwithdraw()externalisAuthorizedreturns(bool){uint256amount=calculateRewards();require(amount>0);ERC20(tokencontractAddress).transfer(msg.sender,amount);}/**
* @dev Function to check if new tokens are ready to be minted.
* @return A boolean that indicates if the operation was successful.
*/functionreadyToMint()publicviewreturns(bool){uint256currentBlockNumber=block.number;uint256lastBlockNumber=lastMintedBlockNumber;if(currentBlockNumber>lastBlockNumber+blockFreezeInterval){returntrue;}else{returnfalse;}}/**
* @dev Function to calculate current rewards for a participant.
* @return A uint that returns the calculated rewards amount.
*/functioncalculateRewards()privatereturns(uint256){uint256playerMask=participantMask[msg.sender];uint256rewards=roundMask.sub(playerMask);updateParticipantMask(msg.sender);returnrewards;}/**
* @dev Function to mint new tokens into the economy.
* @return A boolean that indicates if the operation was successful.
*/functionmintTokens()privatereturns(bool){uint256currentBlockNumber=block.number;uint256tokenReleaseAmount=(currentBlockNumber.sub(lastMintedBlockNumber)).mul(tokensPerBlock);lastMintedBlockNumber=currentBlockNumber;mint(tokencontractAddress,tokenReleaseAmount);calculateTPP(tokenReleaseAmount);returntrue;}/**
* @dev Function to calculate TPP (token amount per participant).
* @return A boolean that indicates if the operation was successful.
*/functioncalculateTPP(uint256tokens)privatereturns(bool){uint256tpp=tokens.div(totalParticipants);updateRoundMask(tpp);returntrue;}/**
* @dev Function to update round mask.
* @return A boolean that indicates if the operation was successful.
*/functionupdateRoundMask(uint256tpp)privatereturns(bool){roundMask=roundMask.add(tpp);returntrue;}/**
* @dev Function to update participant mask (store the previous round mask)
* @return A boolean that indicates if the operation was successful.
*/functionupdateParticipantMask(addressparticipant)privatereturns(bool){uint256previousRoundMask=roundMask;participantMask[participant]=previousRoundMask;returntrue;}}