sherlock-audit / 2024-09-predict-fun-judging

0 stars 0 forks source link

Cool Ash Ostrich - Malicious user can front-run refinancing to cause DOS #312

Open sherlock-admin2 opened 2 days ago

sherlock-admin2 commented 2 days ago

Cool Ash Ostrich

High

Malicious user can front-run refinancing to cause DOS

Summary

https://github.com/sherlock-audit/2024-09-predict-fun/blob/main/predict-dot-loan/contracts/PredictDotLoan.sol#L502-L530 A vulnerability exists in the refinancing function where a malicious user can front-run the transaction by toggling off the autoRefinancingEnabled flag for borrowers. This causes a denial of service (DoS) by preventing the refinancing process from completing, thereby hindering legitimate users from refinancing their loans.

Root Cause

toggleAutoRefinancingEnabled() can be called during auto-refinancing process.

Internal pre-conditions

External pre-conditions

No response

Attack Path

-The malicious user after toggling the auto-refinance on detects the pending transaction and quickly toggles off the autoRefinancingEnabled flag for the borrower. -When the refinance function executes, the check if (autoRefinancingEnabled[borrower] == 0) fails. -The transaction reverts with the error BorrowerDidNotEnableAutoRefinancing, preventing the refinancing process from completing for all the users involved. -protocol removes the malicious user from auto-refinance but before the transaction is eventually processed on chain the expected time for loan re-payment has passed and loan is called and seized by lender. Or the proposal matched to refinance loan has expired or withdrawn by the proposer

Impact

The refinancing process is disrupted, preventing legitimate users from refinancing their loans and a subsequent loss of funds

PoC

below is the refinance function which process auto-refinance in batches. the function checks if the autoRefinancingEnabled[borrower] == 0) which can be manipulated by a malicious borrower

function refinance(
        Refinancing[] calldata refinancings
    ) external nonReentrant whenNotPaused onlyRole(REFINANCIER_ROLE) {
        RefinancingResult[] memory results = new RefinancingResult[](refinancings.length);//
        for (uint256 i; i < refinancings.length; ++i) {
            Refinancing calldata refinancing = refinancings[i];//
            (uint256 id, Loan memory loan, uint256 protocolFee) = _refinance(refinancing);

            // Doing this check after the refinancing, but in realitiy
            // it does not matter because the transaction simulation would've
            // failed before it is submitted on-chain.
            address borrower = loan.borrower;
            if (autoRefinancingEnabled[borrower] == 0) {
                revert BorrowerDidNotEnableAutoRefinancing(borrower);
            }

            results[i] = RefinancingResult(
                hashProposal(refinancing.proposal),
                refinancing.loanId,
                id,
                loan.lender,
                loan.collateralAmount,
                loan.loanAmount,
                loan.interestRatePerSecond,
                loan.minimumDuration,
                protocolFee
            );
        }
        emit LoansRefinanced(results);
    }

here the malicious borrower toggles off auto-refinancing leading to revert of the whole transactions

 function toggleAutoRefinancingEnabled() external {
        uint256 preference = autoRefinancingEnabled[msg.sender] == 0 ? 1 : 0;//
        autoRefinancingEnabled[msg.sender] = preference;
        emit AutoRefinancingEnabledToggled(msg.sender, preference);
    }

Mitigation

Ensure that the autoRefinancingEnabled flag cannot be toggled during the execution of the refinancing transaction.