Skip to content

Commit

Permalink
simplify reward and bonus calculations (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
brkomir authored and coolhill committed Jul 10, 2023
1 parent b8b344f commit 8c44ab1
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 35 deletions.
18 changes: 7 additions & 11 deletions src/staking/BonusTracker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,31 +62,27 @@ abstract contract BonusTracker is ERC4626, ReentrancyGuard {

/// @notice The amount of bonus tokens an account has accrued so far.
function bonusOf(address _account) external view returns (uint256) {
return _earnedBonus(_account, balanceOf[_account], _bonusPerToken(lastTimeBonusApplicable()), bonus[_account]);
return _earnedBonus(_account, _bonusPerToken(lastTimeBonusApplicable()));
}

function _earnedBonus(address account, uint256 accountBalance, uint256 bonusPerToken_, uint256 accountBonus)
internal
view
returns (uint256)
{
return accountBalance.mulDivDown(bonusPerToken_ - userBonusPerTokenPaid[account], PRECISION) + accountBonus;
function _earnedBonus(address _account, uint256 _bonusPerToken_) internal view returns (uint256) {
return balanceOf[_account].mulDivDown(_bonusPerToken_ - userBonusPerTokenPaid[_account], PRECISION)
+ bonus[_account];
}

function _bonusPerToken(uint256 lastTimeBonusApplicable_) internal view returns (uint256) {
return bonusPerTokenStored + (lastTimeBonusApplicable_ - lastBonusUpdateTime).mulDivDown(PRECISION, 365 days);
function _bonusPerToken(uint256 _lastTimeBonusApplicable_) internal view returns (uint256) {
return bonusPerTokenStored + (_lastTimeBonusApplicable_ - lastBonusUpdateTime).mulDivDown(PRECISION, 365 days);
}

function _updateBonus(address _account) internal {
// storage loads
uint256 accountBalance = balanceOf[_account];
uint64 lastTimeBonusApplicable_ = lastTimeBonusApplicable();
uint256 bonusPerToken_ = _bonusPerToken(lastTimeBonusApplicable_);

// accrue bonus
bonusPerTokenStored = bonusPerToken_;
lastBonusUpdateTime = lastTimeBonusApplicable_;
bonus[_account] = _earnedBonus(_account, accountBalance, bonusPerToken_, bonus[_account]);
bonus[_account] = _earnedBonus(_account, bonusPerToken_);
userBonusPerTokenPaid[_account] = bonusPerToken_;
}

Expand Down
38 changes: 14 additions & 24 deletions src/staking/RewardTracker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -171,18 +171,13 @@ contract RewardTracker is BonusTracker, DebtTracker, AccessControl {

/// @notice The amount of reward tokens each staked token has earned so far
function rewardPerToken() external view returns (uint256) {
return _calcRewardPerToken(totalSupply + totalBonus, lastTimeRewardApplicable(), rewardRate);
return _calcRewardPerToken(lastTimeRewardApplicable(), rewardRate);
}

/// @notice The amount of reward tokens an account has accrued so far. Does not
/// include already withdrawn rewards.
function earned(address _account) external view returns (uint256) {
return _earned(
_account,
balanceOf[_account] + multiplierPointsOf[_account],
_calcRewardPerToken(totalSupply + totalBonus, lastTimeRewardApplicable(), rewardRate),
rewards[_account]
);
return _earned(_account, _calcRewardPerToken(lastTimeRewardApplicable(), rewardRate));
}

/// @notice Starts a new reward distribution period. The reward tokens must have already
Expand Down Expand Up @@ -239,17 +234,15 @@ contract RewardTracker is BonusTracker, DebtTracker, AccessControl {

uint256 rewardRate_ = rewardRate;
uint64 periodFinish_ = periodFinish;
uint64 lastTimeRewardApplicable_ = block.timestamp < periodFinish_ ? uint64(block.timestamp) : periodFinish_;
uint64 lastTimeRewardApplicable_ = lastTimeRewardApplicable();
uint64 duration_ = duration;
uint256 totalSupply_ = totalSupply + totalBonus;

/// -----------------------------------------------------------------------
/// State updates
/// -----------------------------------------------------------------------

// accrue rewards
rewardPerTokenStored = _calcRewardPerToken(totalSupply_, lastTimeRewardApplicable_, rewardRate_);
lastUpdateTime = lastTimeRewardApplicable_;
rewardPerTokenStored = _calcRewardPerToken(lastTimeRewardApplicable_, rewardRate_);

// record new reward
uint256 reward = rewardBalanceCurrent - rewardBalanceStored_;
Expand Down Expand Up @@ -330,39 +323,36 @@ contract RewardTracker is BonusTracker, DebtTracker, AccessControl {
emit DebtPaid(msg.sender, debt);
}

function _earned(address _account, uint256 _accountBalance, uint256 rewardPerToken_, uint256 _accountRewards)
internal
view
returns (uint256)
{
function _earned(address _account, uint256 rewardPerToken_) internal view returns (uint256) {
uint256 accountBalance = balanceOf[_account] + multiplierPointsOf[_account];

return
_accountBalance.mulDivDown(rewardPerToken_ - userRewardPerTokenPaid[_account], PRECISION) + _accountRewards;
accountBalance.mulDivDown(rewardPerToken_ - userRewardPerTokenPaid[_account], PRECISION) + rewards[_account];
}

function _calcRewardPerToken(uint256 _totalSupply, uint256 _lastTimeRewardApplicable, uint256 _rewardRate)
function _calcRewardPerToken(uint256 _lastTimeRewardApplicable, uint256 _rewardRate)
internal
view
returns (uint256)
{
if (_totalSupply == 0) {
uint256 totalSupply_ = totalSupply + totalBonus;
if (totalSupply_ == 0) {
return rewardPerTokenStored;
}

return rewardPerTokenStored
+ _rewardRate.mulDivDown((_lastTimeRewardApplicable - lastUpdateTime) * PRECISION, _totalSupply);
+ _rewardRate.mulDivDown((_lastTimeRewardApplicable - lastUpdateTime) * PRECISION, totalSupply_);
}

function _updateReward(address _account) internal override {
// storage loads
uint256 accountBalance = balanceOf[_account] + multiplierPointsOf[_account];
uint64 lastTimeRewardApplicable_ = lastTimeRewardApplicable();
uint256 totalSupply_ = totalSupply + totalBonus;
uint256 rewardPerToken_ = _calcRewardPerToken(totalSupply_, lastTimeRewardApplicable_, rewardRate);
uint256 rewardPerToken_ = _calcRewardPerToken(lastTimeRewardApplicable_, rewardRate);

// accrue rewards
rewardPerTokenStored = rewardPerToken_;
lastUpdateTime = lastTimeRewardApplicable_;
rewards[_account] = _earned(_account, accountBalance, rewardPerToken_, rewards[_account]);
rewards[_account] = _earned(_account, rewardPerToken_);
userRewardPerTokenPaid[_account] = rewardPerToken_;
}

Expand Down

0 comments on commit 8c44ab1

Please sign in to comment.