Core Contracts

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

Missing to update the remaining rewards after redeem in MarketCreator.sol

Summary

In the contract contracts/core/pools/StabilityPool/MarketCreator.sol , functions redeemFromMarket() and calculateReward

The market.reward amount is not updated after a successful Redeemed event

This issue will case

  1. Unfair rewards distribution

  2. Pool's RAAC token drained -- because the total rewards to the participants will exceed the number when a Market created

function redeemFromMarket(uint256 marketId) external nonReentrant {
Market storage market = markets[marketId];
UserPosition storage position = userPositions[marketId][msg.sender];
require(position.exists, "No position found");
require(block.timestamp >= position.lockEndTime, "Lock duration has not passed");
uint256 amount = position.amount;
uint256 reward = calculateReward(marketId, amount);
market.totalDeposits -= amount;
delete userPositions[marketId][msg.sender];
market.quoteAsset.safeTransfer(msg.sender, amount);
raacToken.safeTransfer(msg.sender, reward);
emit Redeemed(marketId, msg.sender, amount, reward);
}
function calculateReward(uint256 marketId, uint256 amount) internal view returns (uint256) {
Market storage market = markets[marketId];
return (amount * market.reward) / market.totalDeposits;
}

Severity

High

Vulnerability Details

After the redeemFromMarket, the contract didn't update the latest market.rewards balance within the market.

This will cause the calculateReward() function using the same (wrong) market.reward number to calcuate rewards everytime.

A quick examaple to demonstrate this:

  • Given a Market with total reward 300 RAAC

  • Users Alice, Bob, Cindy deposits 100 USDC each (300 USDC in total)

  • In a fair condition, the RAAC rewards distribution should be 100 RAAC tokens to Alice, Bob, Cindy each.

However, based on the contract's calculations, the redeems will become the following:

Alice redeem

  • Reward: 100 * 300 / 300 = 100 RAAC Token

  • market.totalDeposits = 200 USDC

Bob redeem:

  • Reward: 100 * 300 / 200 = 150 RAAC (50 RAAC tokens more)

  • market.totalDeposits = 100 USDC

Cindy redeem:

  • Reward: 100 * 300 / 100 = 300 RAAC (200 RAAC tokens more)

  • market.totalDeposits = 0 USDC

The total RAAC token rewards are 100+150+200 = 450 RAAC tokens, which is more than the assumption 300 RAAC tokens.

Impact

A successful attack could result shows the following

  • Incorrect rewards distribution -- Being the last one the redeem and get the highest RAAC tokens

  • By doing this repeatively, an attacker could drain the RAAC Pool

Tools Used

Manual review

Recommendations

To solve the issue, using the actual reward balance to calculate the rewards

function redeemFromMarket(uint256 marketId) external nonReentrant {
Market storage market = markets[marketId];
UserPosition storage position = userPositions[marketId][msg.sender];
require(position.exists, "No position found");
require(block.timestamp >= position.lockEndTime, "Lock duration has not passed");
uint256 amount = position.amount;
uint256 reward = (amount * market.reward) / market.totalDeposits;
market.totalDeposits -= amount;
+ market.reward -= reward; // Make sure the reward gets update
delete userPositions[marketId][msg.sender];
market.quoteAsset.safeTransfer(msg.sender, amount);
raacToken.safeTransfer(msg.sender, reward);
emit Redeemed(marketId, msg.sender, amount, reward);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope
inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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

Give us feedback!