Core Contracts

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

Stale RAAC Rewards Calculation Due to Outdated totalRewards in calculateRaacRewards Function while called by getPendingRewards

## Summary

The getPendingRewards function in the StabilityPool contract calculates pending rewards for a user based on the current balance of the RAAC token in the contract (totalRewards = raacToken.balanceOf(address(this))). However, the contract fails to fetch the updated value for totalRewards value which shoud be updated for un-accounted time differnce from current timestamp to lastUpdatedtimestamp which new RAAC rewards will minted by the RaacMinter. This can lead to the use of outdated or stale data when calculating rewards, causing users to view fewer rewards than they are actually have.


## Vulnerability Details

  • Issue:

    • The function getPendingRewards relies on the totalRewards variable, which is calculated as the current balance of the RAAC token held by the contract.

    • However, the RAAC rewards are minted by the RaacMinter contract in the _mintRAACRewards function, which uses the tick() function to mint new rewards based on emissionRate and block timestamp.

    • Since getPendingRewards does not call _mintRAACRewards or update the rewards balance when it's called, it may return outdated totalRewards values due to Withdraw and deposit is not called for so long, leading to incorrect reward calculations for users. Specifically, the newly minted RAAC rewards are not reflected when getPendingRewards is called, meaning users will receive/view fewer rewards.

    • Affected Code:

      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)); // Outdated value
      if (totalDeposits < 1e6) return 0;
      return (totalRewards * userDeposit) / totalDeposits;
      }
    • Root Cause:
      The getPendingRewards function does not trigger the minting of new rewards, so it uses a potentially outdated value for totalRewards when calculating the rewards for the user.

    • Because the new Raac rewards which will be minted to the contract is dependent on time passed from last updated x emissions rate.


## Impact

  • Incorrect Rewards Calculation:
    Users may receive fewer RAAC rewards because the totalRewards value is not updated in real-time. This can lead to users not receiving the correct amount of rewards corresponding to the actual total supply of RAAC tokens in the contract.

  • Rewards Discrepancy:
    The rewards for users who interact with the system more frequently (e.g., deposit and withdraw) might be calculated correctly, but those who only query their pending rewards without interacting with the system may see a lower value than they are entitled to.

  • Dilution of Rewards Transparency:
    The rewards calculation may become unpredictable or inconsistent, especially when new rewards are minted periodically, but users rely on outdated totalRewards data to calculate their share.


## Tools Used

  • Manual Code Review


## Recommendations

  1. Update totalRewards When Calculating Pending Rewards:
    To ensure that the correct amount of RAAC rewards is used in the calculation, consider calling the _mintRAACRewards() function (or directly calling RaacMinter.tick()) inside the getPendingRewards function. This would update the totalRewards value by minting new rewards before calculating the pending rewards for the user.

    Example:

    function getPendingRewards(address user) external view returns (uint256) {
    // Ensure RAAC rewards are up-to-date
    _mintRAACRewards(); // Mint new RAAC rewards
    return calculateRaacRewards(user);
    }
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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