Summary
Vulnerability Details
function getPendingRewards(address user) external view returns (uint256) {
return calculateRaacRewards(user);
}
function calculateRaacRewards(address user) public view returns (uint256) {
uint256 userDeposit = userDeposits[user];
uint256 totalDeposits = deToken.totalSupply();
uint256 totalRewards = raacToken.balanceOf(address(this));
if (totalDeposits < 1e6) return 0;
return (totalRewards * userDeposit) / totalDeposits;
}
-
When getPendingRewards() called for a User, it intrnally calls calculateRaacRewards()
-
Then calculateRaacRewards() calculate Reward based on following parameters
User deposits
Total deToken deposited in contract
Total current reward balance of the contract
Then based on simple formula it calculates reward for caller.
But here point is Total current reward balance of the contractmay not be updated
There is a separate function _update()which is used mint RAAC reward to contract timely
So before calling this function(calculateRaacRewards()) Caller should call _update()first to get appropriate Reward value.
So getPendingReward() should include _update()inside it before calculateRaacRewards()
function _update() internal {
_mintRAACRewards();
}
https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/pools/StabilityPool/StabilityPool.sol#L251-L268
https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/pools/StabilityPool/StabilityPool.sol#L437-L439
Impact
manual review
Tools Used
Recommendations
function calculateRaacRewards(address user) public returns (uint256) {
_update();
uint256 userDeposit = userDeposits[user];
uint256 totalDeposits = deToken.totalSupply();
uint256 totalRewards = raacToken.balanceOf(address(this));
if (totalDeposits < 1e6) return 0;
return (totalRewards * userDeposit) / totalDeposits;