Core Contracts

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

Redundant State Updates in RToken's Burn Function Causing Unnecessary Gas Costs

Summary

The burn function in the RToken contract contains redundant state updates to the user's index value, resulting in unnecessary gas costs. The same value is written to storage twice within the same function execution. There is also a redundant calculation of uint256 amountScaled = amount.rayMul(index);
in the function.

Vulnerability Details

function burn(
address from,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external override onlyReservePool returns (uint256, uint256, uint256) {
// ...
_userState[from].index = index.toUint128(); // First update
if(amount > userBalance){
amount = userBalance;
}
uint256 amountScaled = amount.rayMul(index); // redundant calculation
_userState[from].index = index.toUint128(); //@audit Second identical update
_burn(from, amount.toUint128());
// ...
}

The liquidity index for a user is set twice with the same value (index.toUint128()) This redundancy results in an unnecessary SSTORE operation, increasing gas consumption. Each extra storage write incurs additional gas costs. In this case, the duplicate update of _userState[from].index does not alter the contract state but still costs extra gas.

Impact

The redundant state update leads to higher gas usage for the burn function

Tools Used

Manual code review

Recommendations

Remove the duplicate update and the so that the liquidity index is updated only once.

also remove the uint256 amountScaled = amount.rayMul(index);

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);
// Update the user's liquidity index only once
_userState[from].index = index.toUint128();
if(amount > userBalance) {
amount = userBalance;
}
_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 5 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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