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

5 stars 4 forks source link

valuevalk - If question gets paused during an auction, the auction will still gain interest rate and potentially expire #246

Open sherlock-admin2 opened 1 month ago

sherlock-admin2 commented 1 month ago

valuevalk

High

If question gets paused during an auction, the auction will still gain interest rate and potentially expire

Summary

Lender decided to start an auction for a loan since borrower hasn't repaid, however if during the auction the question gets paused, this will result to loss of opportunity and higher interest rate for potential lenders willing to take the loan.

Vulnerability Details

Step 1. Lender decided to start an auction for a loan since borrower hasn't repaid.

Step 2. The question gets paused here, due to emergency.

Step 3. Lenders want to take the auctioned loan, however auction() function is now unusable as it uses _assertQuestionPriceUnavailable

    function auction(uint256 loanId) external nonReentrant whenNotPaused {
        Loan storage loan = loans[loanId];
        _assertLoanStatus(loan.status, LoanStatus.Called);
        _assertLenderIsNotBorrower(msg.sender, loan.borrower);
        _assertNewLenderIsNotTheSameAsOldLender(msg.sender, loan.lender);

        uint256 callTime = loan.callTime;
        uint256 timeElapsed = block.timestamp - callTime;

        _assertAuctionIsActive(timeElapsed);
@>>     _assertQuestionPriceUnavailable(loan.questionType, positionQuestion[loan.positionId]);
        ........

And this will result in AbnormalQuestionState(); being thrown, as Paused() is being thrown in getExpectedPayouts() which is called in _isBinaryOutcomeQuestionPriceAvailable

    function _assertBinaryOutcomeQuestionPriceUnavailable(address umaCtfAdapter, bytes32 questionId) private view {
@>>    (bool isAvailable, bytes4 umaError) = _isBinaryOutcomeQuestionPriceAvailable(umaCtfAdapter, questionId);
        // 0x579a4801 is the error code for PriceNotAvailable()
        if (isAvailable) {
            revert QuestionResolved();
        } else if (umaError != 0x579a4801) {
            // Reference: https://github.com/Polymarket/uma-ctf-adapter/blob/main/src/UmaCtfAdapter.sol#L145
@>>         revert AbnormalQuestionState();
        }
    }

Impact

Auctions cannot be ran again, the lender can lose/limit his opportunity for someone else to take on the loan. An auction only runs for a day

    uint256 private constant AUCTION_DURATION = 1 days;

And it gains interest rate every second because of _auctionCurrentInterestRatePerSecond to incentivize lenders to take auction faster, however if this happens during pause, where we also expect after it to still not have resolution, the lender will lose/limit its opportunity, as with higher interest rate lenders might think that borrower will never repay.

Recommendation

Consider allowing auctions to take place during a Pause() state, this should not mess up with flagging/resolving already resolved questions, because if we have a flagged question for emergency resolving we will have Flagged() instead of Paused() being thrown, as the Flagged() is checked first here

Or implement a mechanism to start an auction again.