Core Contracts

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

Excess Repayment Not Transferred Back to User in `LendingPool::_repay`

Summary

In the LendingPool::_repay function, when the repayment amount exceeds the user's debt, the excess is not refunded to the caller. The repayment is capped at the user's scaled debt, but there is no mechanism to return any excess funds to the caller, potentially leading to asset loss.

Vulnerability Details

The function repays a user's debt, but if the repayment amount exceeds the user's scaled debt, it is capped. However, the code does not handle the excess amount, meaning any overpayment is not returned to the caller.

function _repay(uint256 amount, address onBehalfOf) internal {
if (amount == 0) revert InvalidAmount();
if (onBehalfOf == address(0)) revert AddressCannotBeZero();
UserData storage user = userData[onBehalfOf];
// Update reserve state before repayment
ReserveLibrary.updateReserveState(reserve, rateData);
// Calculate the user's debt (for the onBehalfOf address)
uint256 userDebt = IDebtToken(reserve.reserveDebtTokenAddress).balanceOf(onBehalfOf);
uint256 userScaledDebt = userDebt.rayDiv(reserve.usageIndex);
// If amount is greater than userDebt, cap it at userDebt
@> uint256 actualRepayAmount = amount > userScaledDebt ? userScaledDebt : amount;
// @audit-issue debt is capped
uint256 scaledAmount = actualRepayAmount.rayDiv(reserve.usageIndex);
// Burn DebtTokens from the user whose debt is being repaid (onBehalfOf)
// is not actualRepayAmount because we want to allow paying extra dust and we will then cap there
@> (uint256 amountScaled, uint256 newTotalSupply, uint256 amountBurned, uint256 balanceIncrease) =
IDebtToken(reserve.reserveDebtTokenAddress).burn(onBehalfOf, amount, reserve.usageIndex);
// @audit-issue amount is burnt instead of actualRepayAmount
// Transfer reserve assets from the caller (msg.sender) to the reserve
IERC20(reserve.reserveAssetAddress).safeTransferFrom(msg.sender, reserve.reserveRTokenAddress, amountScaled);
reserve.totalUsage = newTotalSupply;
user.scaledDebtBalance -= amountBurned;
// Update liquidity and interest rates
ReserveLibrary.updateInterestRatesAndLiquidity(reserve, rateData, amountScaled, 0);
@> // function does not implement a way to return the excess amount
emit Repay(msg.sender, onBehalfOf, actualRepayAmount);
}

Impact

Callers who repay more than the user's debt may lose the excess funds, as they are not refunded.

Tools Used

Manual review

Recommendations

Implement a mechanism to refund any excess repayment to the caller. After the repayment amount is capped, the difference between the original repayment and the capped value should be returned to the caller to prevent loss of funds. Additionally, actualRepayAmount should be burned instead of amount.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 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.

Give us feedback!