fix: Use userIndex instead of absolute debt

This commit is contained in:
Lasse Herskind 2021-06-03 15:36:22 +02:00
parent fd38f1f4d8
commit c1ce8475de

View File

@ -58,10 +58,10 @@ contract StaticATokenLM is ERC20 {
uint256 public lifeTimeRewards; uint256 public lifeTimeRewards;
uint256 public lastRewardBlock; uint256 public lastRewardBlock;
// user => rewardDebt (in RAYs) // user => userIndex (in RAYs)
mapping(address => uint256) public rewardDebts; mapping(address => uint256) private _userIndex;
// user => unclaimedRewards (in RAYs) // user => unclaimedRewards (in RAYs)
mapping(address => uint256) public unclaimedRewards; mapping(address => uint256) private _unclaimedRewards;
IAaveIncentivesController internal _incentivesController; IAaveIncentivesController internal _incentivesController;
address public immutable currentRewardToken; address public immutable currentRewardToken;
@ -429,11 +429,11 @@ contract StaticATokenLM is ERC20 {
// Only enter when not minting or burning. // Only enter when not minting or burning.
if (from != address(0)) { if (from != address(0)) {
_updateUnclaimedRewards(from); _updateUnclaimedRewards(from);
_updateRewardDebt(from, balanceOf(from).sub(amount)); _updateUserIndex(from);
} }
if (to != address(0)) { if (to != address(0)) {
_updateUnclaimedRewards(to); _updateUnclaimedRewards(to);
_updateRewardDebt(to, balanceOf(to).add(amount)); _updateUserIndex(to);
} }
} }
@ -508,21 +508,18 @@ contract StaticATokenLM is ERC20 {
reward = totBal; reward = totBal;
} }
if (reward > 0) { if (reward > 0) {
unclaimedRewards[user] = 0; _unclaimedRewards[user] = 0;
IERC20(currentRewardToken).safeTransfer(user, reward); IERC20(currentRewardToken).safeTransfer(user, reward);
_updateRewardDebt(user, balance); _updateUserIndex(user);
} }
} }
/** /**
* @dev Update the rewardDebt for a user with balance as his balance * @dev Update the rewardDebt for a user with balance as his balance
* @param user The user to update * @param user The user to update
* @param balance The balance of the user
*/ */
function _updateRewardDebt(address user, uint256 balance) internal { function _updateUserIndex(address user) internal {
// If we round down here, we could underestimate the debt, thereby paying out too much. Better to overestimate. _userIndex[user] = rewardIndex;
uint256 rayBalance = balance.wadToRay();
rewardDebts[user] = rayBalance.rayMul(rewardIndex);
} }
/** /**
@ -533,7 +530,7 @@ contract StaticATokenLM is ERC20 {
uint256 balance = balanceOf(user); uint256 balance = balanceOf(user);
if (balance > 0) { if (balance > 0) {
uint256 pending = _getPendingRewards(user, balance, false); uint256 pending = _getPendingRewards(user, balance, false);
unclaimedRewards[user] = unclaimedRewards[user].add(pending); _unclaimedRewards[user] = _unclaimedRewards[user].add(pending);
} }
} }
@ -571,13 +568,8 @@ contract StaticATokenLM is ERC20 {
_rewardIndex = _rewardIndex.add((diff).rayDivNoRounding(_supply.wadToRay())); _rewardIndex = _rewardIndex.add((diff).rayDivNoRounding(_supply.wadToRay()));
} }
uint256 _reward = rayBalance.rayMulNoRounding(_rewardIndex); uint256 _reward = rayBalance.rayMulNoRounding(_rewardIndex.sub(_userIndex[user]));
uint256 _debt = rewardDebts[user]; return _reward;
if (_reward > _debt) {
// Safe because line above
return _reward - _debt;
}
return 0;
} }
/** /**
@ -592,7 +584,7 @@ contract StaticATokenLM is ERC20 {
uint256 balance, uint256 balance,
bool fresh bool fresh
) internal view returns (uint256) { ) internal view returns (uint256) {
uint256 reward = unclaimedRewards[user].add(_getPendingRewards(user, balance, fresh)); uint256 reward = _unclaimedRewards[user].add(_getPendingRewards(user, balance, fresh));
return reward.rayToWadNoRounding(); return reward.rayToWadNoRounding();
} }
@ -622,6 +614,6 @@ contract StaticATokenLM is ERC20 {
* @return The unclaimed amount of rewards in WAD * @return The unclaimed amount of rewards in WAD
*/ */
function getUnclaimedRewards(address user) public view returns (uint256) { function getUnclaimedRewards(address user) public view returns (uint256) {
return unclaimedRewards[user].rayToWadNoRounding(); return _unclaimedRewards[user].rayToWadNoRounding();
} }
} }