Core Contracts

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

User can drain the StabilityPool and lendingPool because of incorrect transfer functions in RToken.sol

Summary

In the rToken transfer functions, the amount supplied is divided by the liquidation index and then again divided by the liquidation Index in the _update function too. Thus whenever transfer/transferFrom is called for amount = amount, the amount is not transferred to the recipient. Only amount/liquidationIndex is transferred. In the stability pool during deposit, the transfer functions are used which allow malicious users to drain the funds.

Vulnerability Details

Assume the following scenario:

  1. user calls the deposit function with amount = 1e18.

  2. the deposit function calls the transferfrom function which does amount.rayDiv(liquidationIndex) ~ 1e18/1e27 = 0

  3. and then further in the update function again divided by the liquidationIndex and finally internally transferring 0 to the stability Pool.

  4. But the stability Pool mints 1e18DeToken for the user and updates userDeposits with 1e18

  5. The user then calls the withdraw function, which will get him RAAC tokens depending on his userDeposits which is 1e18.
    This way by depositing 0 amount of RToken, the user can get an unlimited DeToken and RAACTokens.

  6. Further as his DeToken balance increases by a lot (> 1e54) his withdraw calls will get him RTokens (transfer function wont round down to 0 since balance is > 1e54) and thus can drain the LendingPool contract too.

Note: there is a difference in the division in the transfer and transferFrom functions too (different liquidation Indices used, this will cause some other impacts too like user losing funds with each deposit+withdraw, but this is not included in the report since the fix for this is to remove all the divisions in the transfer functions which will elimiate all the bugs)

function deposit(uint256 amount) external nonReentrant whenNotPaused validAmount(amount) {
_update();
rToken.safeTransferFrom(msg.sender, address(this), amount);
uint256 deCRVUSDAmount = calculateDeCRVUSDAmount(amount);
deToken.mint(msg.sender, deCRVUSDAmount);
userDeposits[msg.sender] += amount;
_mintRAACRewards();
emit Deposit(msg.sender, amount, deCRVUSDAmount);
}
function transferFrom(address sender, address recipient, uint256 amount) public override(ERC20, IERC20) returns (bool) {
uint256 scaledAmount = amount.rayDiv(_liquidityIndex);
// no need to divide
return super.transferFrom(sender, recipient, scaledAmount);
}
function _update(address from, address to, uint256 amount) internal override {
// Scale amount by normalized income for all operations (mint, burn, transfer)
uint256 scaledAmount = amount.rayDiv(ILendingPool(_reservePool).getNormalizedIncome());
// again divided
super._update(from, to, scaledAmount);
}

Impact

Loss of funds for other users and infinite supply of RAAC tokens thus infinite crvUSD from boost/guage etc.

Tools Used

manual review

Recommendations

make sure the balance of the stabilityPool is actually increasing, and also remove the divisions in the transfer functions in the RToken.
Note: this can be made into 2 bugs, 1 with fix being removing the divisions in the transfer functions and the other being ensuring the balance of the stabilityPool increases

(these are different issues since even after removing divisions in the transfer functions, the user can make the actual amount transferred = 0, because of the division in the update function which is important) I have included them in the same report since the attack paths are similar for both.Further anywhere the RAAC token is transferred this issue arises.

Updates

Lead Judging Commences

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

RToken::transfer and transferFrom double-scale amounts by dividing in both external functions and _update, causing users to transfer significantly less than intended

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

RToken::transfer and transferFrom double-scale amounts by dividing in both external functions and _update, causing users to transfer significantly less than intended

Appeal created

anonymousjoe Submitter
3 months ago
inallhonesty Lead Judge
3 months ago
inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

RToken::transfer and transferFrom double-scale amounts by dividing in both external functions and _update, causing users to transfer significantly less than intended

RToken::transfer uses getNormalizedIncome() while transferFrom uses _liquidityIndex, creating inconsistent transfer amounts depending on function used

Support

FAQs

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