Core Contracts

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

borrow will possibly revert

Summary

The borrow function attempts to withdraw assets from a Curve vault to the LendingPool if the reserve lacks sufficient liquidity. However, after transferring assets amount - availableLiquidity to the user, the borrow function directly calls IRToken(reserve.reserveRTokenAddress).transferAsset(msg.sender, amount). This creates a mismatch.

Vulnerability Details

  • The borrow function attempts to replenish liquidity by withdrawing assets from a Curve vault to the borrower when the reserve is depleted. However, the borrowed assets are not credited to the reserve’s RToken contract. Instead, the function tries to transfer assets from the reserve via IRToken(reserve.reserveRTokenAddress).transferAsset(msg.sender, amount). Since will try to transfer the whole amount (not amount -requiredAmount), the transfer fails, causing transactions to revert and resulting in a DOS for borrowers.

function borrow(uint256 amount) external nonReentrant whenNotPaused onlyValidAmount(amount) {
...
// Ensure sufficient liquidity is available
_ensureLiquidity(amount); <@
...
// Transfer borrowed amount to user
IRToken(reserve.reserveRTokenAddress).transferAsset(msg.sender, amount); <@ audit
...
emit Borrow(msg.sender, amount);
}
function _ensureLiquidity(uint256 amount) internal {
// if curve vault is not set, do nothing
if (address(curveVault) == address(0)) {
return;
}
uint256 availableLiquidity = IERC20(reserve.reserveAssetAddress).balanceOf(reserve.reserveRTokenAddress);
if (availableLiquidity < amount) {
uint256 requiredAmount = amount - availableLiquidity;
// Withdraw required amount from the Curve vault
_withdrawFromVault(requiredAmount); <@
}
}

Impact

  • this issue will lead to DOS for borrowers

  • the same issue in withdraw function.

Tools Used

Manual audit

Recommendations

function _withdrawFromVault(uint256 amount) internal {
curveVault.withdraw(amount, address(this), msg.sender, 0, new address[](0)); // Fix : replace msg.sender with reserve.reserveRTokenAddress
totalVaultDeposits -= amount;
}
Updates

Lead Judging Commences

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

LendingPool::_depositIntoVault and _withdrawFromVault don't transfer tokens between RToken and LendingPool, breaking Curve vault interactions

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

LendingPool::_depositIntoVault and _withdrawFromVault don't transfer tokens between RToken and LendingPool, breaking Curve vault interactions

Support

FAQs

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