Core Contracts

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

Approval Race Condition

Summary

In liquidateBorrower, you use crvUSDToken.approve(address(lendingPool), scaledUserDebt).

This can lead to race conditions where a malicious contract can front-run and change the allowance before finalizeLiquidation is executed.

Vulnerability Details

function liquidateBorrower(address userAddress) external onlyManagerOrOwner nonReentrant whenNotPaused {
_update();
// Get the user's debt from the LendingPool.
uint256 userDebt = lendingPool.getUserDebt(userAddress);
uint256 scaledUserDebt = WadRayMath.rayMul(userDebt, lendingPool.getNormalizedDebt());
if (userDebt == 0) revert InvalidAmount();
uint256 crvUSDBalance = crvUSDToken.balanceOf(address(this));
if (crvUSDBalance < scaledUserDebt) revert InsufficientBalance();
// Approve the LendingPool to transfer the debt amount
bool approveSuccess = crvUSDToken.approve(address(lendingPool), scaledUserDebt);
if (!approveSuccess) revert ApprovalFailed();
// Update lending pool state before liquidation
lendingPool.updateState();
// Call finalizeLiquidation on LendingPool
lendingPool.finalizeLiquidation(userAddress);
emit BorrowerLiquidated(userAddress, scaledUserDebt);
}

}

Impact

Tools Used

Recommendations

Instead of approve, use safeIncreaseAllowance and safeDecreaseAllowance from SafeERC20.

  • Alternatively, use permit if crvUSDToken supports EIP-2612.

  • Another safer pattern is to call transfer directly rather than approving beforehand.

crvUSDToken.safeIncreaseAllowance(address(lendingPool), scaledUserDebt);

lendingPool.finalizeLiquidation(userAddress);

crvUSDToken.safeDecreaseAllowance(address(lendingPool), scaledUserDebt);

Updates

Lead Judging Commences

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