Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Valid

User can keep on claiming rewards in the stabilityPool.sol

Summary

In the reward calculation in the StabilityPool.sol there is no concept of rewardDebt. This allows attackers to deposit+withdraw continously to keep on earning infinite rewards.

Vulnerability Details

The rewards (RAACTokens) in the stabilityPool is calculated as the ratio of users DeToken balance and the totalSupply multiplied with the raacToken.balanceOf(address(this). Thus if a user deposits and withdraws, he will get rewards, and no updation of his rewardDebt is done(such a variable is non-existant). So the same user can deposit his withdrawn RToken again and again withdraw to again get the same rewards. This can be done infinite number of times to drain the StabilityPool.

Each time the user deposits RToken, his deToken balance increases, so does the totalSupply, his rewards claimed each time is the same. Since there is no time factor/ rewardDebt included, only the deToken balance matters for rewards and this can be easily gamed by the process mentioned above.

function withdraw(uint256 deCRVUSDAmount) external nonReentrant whenNotPaused validAmount(deCRVUSDAmount) {
_update();
if (deToken.balanceOf(msg.sender) < deCRVUSDAmount) revert InsufficientBalance();
uint256 rcrvUSDAmount = calculateRcrvUSDAmount(deCRVUSDAmount);
uint256 raacRewards = calculateRaacRewards(msg.sender);
if (userDeposits[msg.sender] < rcrvUSDAmount) revert InsufficientBalance();
userDeposits[msg.sender] -= rcrvUSDAmount;
if (userDeposits[msg.sender] == 0) {
delete userDeposits[msg.sender];
}
deToken.burn(msg.sender, deCRVUSDAmount);
rToken.safeTransfer(msg.sender, rcrvUSDAmount);
if (raacRewards > 0) {
raacToken.safeTransfer(msg.sender, raacRewards);
}
emit Withdraw(msg.sender, rcrvUSDAmount, deCRVUSDAmount, raacRewards);
}
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;
}

Impact

Draining of RAAC Tokens in the stability Pool and thus other users wont receive their rewards.

Tools Used

manual review

Recommendations

Consider implementing some other system for reward distribution.

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

StabilityPool::calculateRaacRewards is vulnerable to just in time deposits

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.