code-423n4 / 2023-12-initcapital-findings

3 stars 3 forks source link

Repayment or liquidation can be blocked if debt ceiling amount is decreased #5

Closed c4-bot-3 closed 8 months ago

c4-bot-3 commented 9 months ago

Lines of code

https://github.com/code-423n4/2023-12-initcapital/blob/a53e401529451b208095b3af11862984d0b32177/contracts/risk_manager/RiskManager.sol#L75

Vulnerability details

Impact

repayment or liquidation can be blocked if debt ceiling amount is decreased

Proof of Concept

When user repay the debt or if liquidator repay the debt

we are calling updateModeDebtShares, the debt is reduced

IRiskManager(riskManager).updateModeDebtShares(_mode, _pool, -sharesToRepay.toInt256());

this is calling

    function updateModeDebtShares(uint16 _mode, address _pool, int _deltaShares) external onlyCore {
        DebtCeilingInfo memory debtCeilingInfo = __modeDebtCeilingInfos[_mode][_pool];
        uint newDebtShares = (debtCeilingInfo.debtShares.toInt256() + _deltaShares).toUint256();
        if (_deltaShares > 0) {
            uint currentDebt = ILendingPool(_pool).debtShareToAmtCurrent(newDebtShares);
            _require(currentDebt <= debtCeilingInfo.ceilAmt, Errors.DEBT_CEILING_EXCEEDED);
        }
        __modeDebtCeilingInfos[_mode][_pool].debtShares = newDebtShares.toUint128();
    }

the transaction can revert in this line of code

 _require(currentDebt <= debtCeilingInfo.ceilAmt, Errors.DEBT_CEILING_EXCEEDED);

when the debt ceilling is adjusted

consider the case

the admin set debt ceiling to 1 miillion

the total debt for borrowing becomes 0.7 million

then admin decides to reduce debt ceilling to 0.5 million, the intention is to not let user create more debts via borrowing

but then after admin calling

   function setModeDebtCeilingInfo(uint16 _mode, address[] calldata _pools, uint128[] calldata _ceilAmts)
        external
        onlyGuardian
    {
        _require(_pools.length == _ceilAmts.length, Errors.ARRAY_LENGTH_MISMATCHED);
        for (uint i; i < _pools.length; i = i.uinc()) {
            __modeDebtCeilingInfos[_mode][_pools[i]].ceilAmt = _ceilAmts[i];
            emit SetModeDebtCeilingInfo(_mode, _pools[i], _ceilAmts[i]);
        }
    }

then user wants to repay the debt to reduce debt from 0.7 million to 0.6 million,

but because 0.6 million is greater than 0.5 million debt ceilling configuration

both liquidation and repayment revert and users are force to pay interest and incur more debts until liquidation after admin increase the debt ceiling amount

 _require(currentDebt <= debtCeilingInfo.ceilAmt, Errors.DEBT_CEILING_EXCEEDED);

Tools Used

Manual Review

Recommended Mitigation Steps

I think it is safe to skip this debt ceiling check when debt is decreased via repay

Assessed type

Invalid Validation

c4-judge commented 8 months ago

hansfriese marked the issue as primary issue

c4-sponsor commented 8 months ago

fez-init (sponsor) disputed

fez-init commented 8 months ago

In repay and liquidate functions, _deltaShares will be negative, so the if clause will not be entered.

JeffCX commented 8 months ago

Agree with sponsor

c4-judge commented 8 months ago

hansfriese marked the issue as unsatisfactory: Invalid