sherlock-audit / 2024-04-teller-finance-judging

10 stars 9 forks source link

blockchain555 - Invalid implementation of function `LenderCommitmentGroup_Smart.sol#liquidateDefaultedLoanWithIncentive()` #247

Closed sherlock-admin4 closed 4 months ago

sherlock-admin4 commented 4 months ago

blockchain555

high

Invalid implementation of function LenderCommitmentGroup_Smart.sol#liquidateDefaultedLoanWithIncentive()

Summary

Due to incorrect implementation of the LenderCommitmentGroup_Smart.sol#liquidateDefaultedLoanWithIncentive() function, the liquidator can seize the borrower's collateral free of charge.

Vulnerability Detail

In the LenderCommitmentGroup_Smart.sol#liquidateDefaultedLoanWithIncentive() function, the following operations are performed when _tokenAmountDifference <= 0.

    function liquidateDefaultedLoanWithIncentive(
        uint256 _bidId,
        int256 _tokenAmountDifference
    ) public bidIsActiveForGroup(_bidId) {
        uint256 amountDue = getAmountOwedForBid(_bidId, false);

        uint256 loanDefaultedTimeStamp = ITellerV2(TELLER_V2)
            .getLoanDefaultTimestamp(_bidId);

431:    int256 minAmountDifference = getMinimumAmountDifferenceToCloseDefaultedLoan(
432:            amountDue,
433:            loanDefaultedTimeStamp
434:        );

436:    require(
437:        _tokenAmountDifference >= minAmountDifference,
438:        "Insufficient tokenAmountDifference"
439:    );

        if (_tokenAmountDifference > 0) {
            SNIP...
        } else {

457:        uint256 tokensToGiveToSender = abs(_tokenAmountDifference);

459:        IERC20(principalToken).transferFrom(
460:            msg.sender,
461:            address(this),
462:            amountDue - tokensToGiveToSender
463:        );

        tokenDifferenceFromLiquidations -= int256(tokensToGiveToSender);

            totalPrincipalTokensRepaid += amountDue;
        }

        //this will give collateral to the caller
        ITellerV2(TELLER_V2).lenderCloseLoanWithRecipient(_bidId, msg.sender);
    }

27 hours after loan default, minAmountDifference returns -amountDue.

    function getMinimumAmountDifferenceToCloseDefaultedLoan(
        uint256 _amountOwed,
        uint256 _loanDefaultedTimestamp
    ) public view virtual returns (int256 amountDifference_) {
        require(
            _loanDefaultedTimestamp > 0,
            "Loan defaulted timestamp must be greater than zero"
        );
        require(
            block.timestamp > _loanDefaultedTimestamp,
            "Loan defaulted timestamp must be in the past"
        );

506:    uint256 secondsSinceDefaulted = block.timestamp -
507:        _loanDefaultedTimestamp;

509:    int256 incentiveMultiplier = int256(86400) -
510:        int256(secondsSinceDefaulted);

512:    if (incentiveMultiplier < -10000) {
513:        incentiveMultiplier = -10000;
514:    }

516:    amountDifference_ =
517:        (int256(_amountOwed) * incentiveMultiplier) /
518:        int256(10000);
    }

Therefore, if the liquidator sets the tokenAmountDifference to minAmountDifference, according to #L459 to #L463, the liquidator does not transfer funds.

amountDue - tokensToGiveToSender = 0

The TellerV2.sol#liquidateLoanFull() function is called 24 hours after loan default. When calling this function, the liquidator pays principal + interest to the lender and . However, due to the function implemented in above, the liquidator can seize the collateral free of charge without paying the corresponding principal.

Impact

The liquidator can seize the collateral free of charge without paying the corresponding principal.

Code Snippet

https://github.com/sherlock-audit/2024-04-teller-finance/blob/main/teller-protocol-v2-audit-2024/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol#L422-L472

Tool used

Manual Review

Recommendation

It is recommended that liquidators only call the TellerV2.sol#liquidateLoanFull() function after 24 hours of loan default.

nevillehuang commented 3 months ago

Invalid, duplicate of #151, auction functions as intended