Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dandy Caramel Tortoise - Malicious lender can prevent borrower from repayment due to try/catch block revert #39

Open
sherlock-admin4 opened this issue Dec 10, 2024 · 1 comment
Labels
Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed

Comments

@sherlock-admin4
Copy link

Dandy Caramel Tortoise

High

Malicious lender can prevent borrower from repayment due to try/catch block revert

Summary

Insufficient validation for try/catch address will disallow borrower's from repaying their loans

Root Cause

A malicious lender can bypass the try/catch block covering the repayLoanCallback external call by selfdestructing loanRepaymentListener

        if (loanRepaymentListener != address(0)) {
            require(gasleft() >= 80000, "NR gas");  //fixes the 63/64 remaining issue
            try
                ILoanRepaymentListener(loanRepaymentListener).repayLoanCallback{
                    gas: 80000
                }( //limit gas costs to prevent lender preventing repayments
                    _bidId,
                    _msgSenderForMarket(bid.marketplaceId),
                    _payment.principal,
                    _payment.interest
                )

The try/catch block will revert if the call is made to a non-contract address. To avoid this a check for codesize > 0 is kept inside the setRepaymentListenerForBid function. But this can be bypassed by the lender selfdestructing the _listener in the same transaction which will delete the contract

https://github.com/sherlock-audit/2024-11-teller-finance-update/blob/0c8535728f97d37a4052d2a25909d28db886a422/teller-protocol-v2-audit-2024/packages/contracts/contracts/TellerV2.sol#L1287-L1301

    function setRepaymentListenerForBid(uint256 _bidId, address _listener) external {
        uint256 codeSize;
        assembly {
            codeSize := extcodesize(_listener) 
        }
        require(codeSize > 0, "Not a contract");
        address sender = _msgSenderForMarket(bids[_bidId].marketplaceId);


        require(
            sender == getLoanLender(_bidId),
            "Not lender"
        );


        repaymentListenerForBid[_bidId] = _listener;
     }

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

  1. Lender creates a contract which can selfdestruct itself
  2. Lender sets this address as the repaymentListener
  3. In the same tx, the lender destroys the contract
  4. Now the borrower cannot repay because the try/catch block will always revert

Impact

Borrowers will not be able to repay the loan allowing the lender to steal the collateral after the loan will default

PoC

No response

Mitigation

Use .call instead of the try/catch

@sherlock-admin3 sherlock-admin3 added Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed labels Dec 12, 2024
@sherlock-admin2
Copy link

The protocol team fixed this issue in the following PRs/commits:
teller-protocol/teller-protocol-v2-audit-2024#79

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed
Projects
None yet
Development

No branches or pull requests

3 participants