Core Contracts

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

Interest Accrual During Grace Period Creates System Imbalance

Summary

The LendingPool continues to accrue interest on user debt during the liquidation grace period, potentially preventing users from recovering their positions and creating system-wide accounting imbalances.

Vulnerability Details

In LendingPool.sol:

uint256 public constant BASE_LIQUIDATION_GRACE_PERIOD = 3 days;
function finalizeLiquidation(address userAddress) external nonReentrant onlyStabilityPool {
if (block.timestamp <= liquidationStartTime[userAddress] + liquidationGracePeriod) {
revert GracePeriodNotExpired();
}
// Interest continues accruing during this period
ReserveLibrary.updateReserveState(reserve, rateData);
}
  • Interest continues accruing during the grace period

  • Users must repay the growing debt to close their liquidation

  • No mechanism to freeze or cap interest during this period

  • Grace period effectiveness is reduced by growing debt

Example Scenario:

  • Day 0: User position marked for liquidation
    Initial debt: 10,000 USDC
    Health factor below threshold

  • Day 3: Grace period ends
    Accrued interest: +50 USDC (at 6% APR)
    Final debt: 10,050 USDC
    User prepared 10,000 USDC but cannot close position

Impact

  • Increased user debt during grace period

  • System imbalances due to accrued interest

  • Potential unfair liquidations

  • Additional burden on stability providers

Tools Used

  • Manual code review

Recommendations

  • Implement Debt Freezing:

struct LiquidationInfo {
uint256 frozenDebt;
uint256 liquidationTime;
uint256 originalInterestRate;
}
function initiateLiquidation(address userAddress) external {
LiquidationInfo storage info = liquidationInfo[userAddress];
info.frozenDebt = getUserDebt(userAddress);
info.liquidationTime = block.timestamp;
info.originalInterestRate = getCurrentInterestRate();
emit LiquidationInitiated(userAddress, info.frozenDebt);
}
  • Use Frozen Debt for Repayment:

function closeLiquidation() external nonReentrant {
LiquidationInfo storage info = liquidationInfo[msg.sender];
require(block.timestamp <= info.liquidationTime + GRACE_PERIOD, "Grace period expired");
// Use frozen debt amount instead of current debt
uint256 repaymentAmount = info.frozenDebt;
_repay(repaymentAmount, msg.sender);
delete liquidationInfo[msg.sender];
emit LiquidationClosed(msg.sender);
}
Updates

Lead Judging Commences

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

StabilityPool::liquidateBorrower double-scales debt by multiplying already-scaled userDebt with usage index again, causing liquidations to fail

Support

FAQs

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