Skip to content

Instantly share code, notes, and snippets.

@MichalZalecki
Last active November 17, 2018 10:47
Show Gist options
  • Save MichalZalecki/51ae801bb2c485d65106a99189dacb44 to your computer and use it in GitHub Desktop.
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
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