Core Contracts

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

Because of wrong function call order of ResevePool User can loss full Asset

Summary

In RToken.sol contract Because of wrong function call order of ResevePool User will lost full asset. Because in burn function this line if (receiverOfUnderlying = address(this)) revert InvalidAddress();is missing.

Vulnerability Details

In RToken.sol contract in burn function read below comments...

function burn(
address from,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external override onlyReservePool returns (uint256, uint256, uint256) {
if (amount == 0) {
return (0, totalSupply(), 0);
}
uint256 userBalance = balanceOf(from);
_userState[from].index = index.toUint128();
if(amount > userBalance){
amount = userBalance;
}
uint256 amountScaled = amount.rayMul(index);
_userState[from].index = index.toUint128();
_burn(from, amount.toUint128());
@>> if (receiverOfUnderlying != address(this)) {
IERC20(_assetAddress).safeTransfer(receiverOfUnderlying, amount);
}
// if (receiverOfUnderlying != address(this)) that is true then it's ok
//if False then Underlying Asset will stay on this contract
emit Burn(from, receiverOfUnderlying, amount, index);
return (amount, totalSupply(), amount);
}

Above on line no 25 >> if (receiverOfUnderlying != address(this)) that is true then it's ok

if that condition is False then Underlying Asset will stay on this contract.

That Can be recoverable by rescueToken function .

There also have another function transferAccruedDustthat is basically tranfer all remaining asset from this (RToken.sol) contract to another address.

Carefully Read this ---

Now Assume that if (receiverOfUnderlying != address(this))conditon is false.

Then According logic Aseet will stay on this contract(RToken.sol).

Condition 1:-

  1. If Reservepool First call rescueTokento tranfer asset from this contract to reciever address[who burn token but don't receive asset].

  2. Then call transferAccruedDustfunction

In this condition all are working well.

Condition 2:-

  1. If Reservepool call transferAccruedDust function before rescueTokenthen then contract asset will be zero.

  2. In this condition User[who burn token but don't receive asset] will loss all his asset. That cannot be recovered.

  3. Because that Can not be recoverable from that contract again.

In this condition User Loss their Asset.

Impact

User can lose full Asset if there is single mistake on function call order.

Tools Used

Manual review

Recommendations

In RToken.sol contract in burn function . Add line no 11 to avoid this. And this also save your Gas cost. If line 11 is implement then there will no need of rescueTokenfunction.

function burn(
address from,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external override onlyReservePool returns (uint256, uint256, uint256) {
if (amount == 0) {
return (0, totalSupply(), 0);
}
//add this line of code to avoid this situation and avoid to use rescueToken Function
+ if (receiverOfUnderlying = address(this)) revert InvalidAddress();
uint256 userBalance = balanceOf(from);
_userState[from].index = index.toUint128();
if(amount > userBalance){
amount = userBalance;
}
uint256 amountScaled = amount.rayMul(index);
_userState[from].index = index.toUint128();
_burn(from, amount.toUint128());
if (receiverOfUnderlying != address(this)) {
IERC20(_assetAddress).safeTransfer(receiverOfUnderlying, amount);
}
emit Burn(from, receiverOfUnderlying, amount, index);
return (amount, totalSupply(), amount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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