Last active
November 17, 2018 10:47
-
-
Save MichalZalecki/51ae801bb2c485d65106a99189dacb44 to your computer and use it in GitHub Desktop.
Scalable Reward Distribution implementation based on http://batog.info/papers/scalable-reward-distribution.pdf paper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity 0.4.24; | |
import "github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol"; | |
/// @title Scalable Reward Distribution | |
/// @dev ref. http://batog.info/papers/scalable-reward-distribution.pdf | |
contract ScalableRewardDistribution { | |
using SafeMath for uint256; | |
/// @dev All active stake deposits | |
uint256 public T = 0; | |
/// @dev Stake coefficient | |
uint256 public S = 0; | |
uint256 public balance; | |
mapping (address => uint256) public stake; | |
mapping (address => uint256) public S0; | |
uint256 constant private PPB = 10**9; | |
uint256 constant private precision = PPB; | |
function deposit(address _address, uint256 _amount) public { | |
require(pendingReward(_address) == 0, "take profit before deposit"); | |
stake[_address] = stake[_address].add(_amount); | |
if (S0[_address] == 0) { | |
S0[_address] = S; | |
} | |
T = T.add(_amount); | |
emit Deposited(_address, _amount); | |
} | |
function distribute(uint256 _r) public { | |
require(T != 0, "no active stake deposits"); | |
uint256 divident = _r.mul(precision); | |
uint256 divisor = T; | |
require(divident > divisor, "reward too small to distribute"); | |
uint256 r = _r.mul(precision).div(divisor); | |
S = S.add(r); | |
balance = balance.add(_r); | |
emit Distributed(_r); | |
} | |
function pendingReward(address _address) public view returns (uint256) { | |
uint256 deposited = stake[_address]; | |
uint256 reward = deposited.mul(S.sub(S0[_address])); | |
return reward.div(precision); | |
} | |
/// @dev withdraws both stake and reward | |
// function withdraw(address _address) public { | |
// uint256 deposited = stake[_address]; | |
// uint256 reward = deposited.mul(S.sub(S0[_address])); | |
// T = T.sub(deposited); | |
// stake[_address] = 0; | |
// emit Withdrawed(deposited); | |
// emit Withdrawed(reward); | |
// emit Withdrawed(reward.div(precision)); | |
// } | |
/// @dev withdraws the reward | |
function takeProfit(address _address) public { | |
uint256 reward = pendingReward(_address); | |
require(reward > 0, "no profit to take"); | |
S0[_address] = S; | |
balance = balance.sub(reward); | |
emit Withdrawed(_address, reward); | |
} | |
event Withdrawed(address addr, uint256 value); | |
event Deposited(address addr, uint256 value); | |
event Distributed(uint256 value); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment