Skip to content

Latest commit

 

History

History
94 lines (65 loc) · 4.21 KB

File metadata and controls

94 lines (65 loc) · 4.21 KB

Dandy Caramel Tortoise

Medium

ERC-777 reentrancy will allow an attacker to permenantly cause some assets to be non-loanable in a LenderGroup

Summary

ERC-777 reentrancy will allow an attacker to permenantly cause some assets to be non-loanable in a LenderGroup

Root Cause

In the readme the team has mentioned that they would like to know if any wierd token breaks their contract pools.

The repaymentListener is set after the loan is accepted

    function _acceptBidWithRepaymentListener(uint256 _bidId) internal {
        ITellerV2(TELLER_V2).lenderAcceptBid(_bidId); //this gives out the funds to the borrower

        // @audit repayment listener is set after the ERC777 token is transferred from the borrower
        ILoanRepaymentCallbacks(TELLER_V2).setRepaymentListenerForBid(
            _bidId,
            address(this)
        );

In case an ERC777 token is used as collateral/principal, the borrower can re-enter during the token deposit/token receival, and repay the loan

    function deployAndDeposit(uint256 _bidId) external onlyTellerV2 {
        if (isBidCollateralBacked(_bidId)) {
            (address proxyAddress, ) = _deployEscrow(_bidId);
            _escrows[_bidId] = proxyAddress;


            for (
                uint256 i;
                i < _bidCollaterals[_bidId].collateralAddresses.length();
                i++
            ) {
                // @audit re-enter here and repay loan
                _deposit(
                    _bidId,
                    _bidCollaterals[_bidId].collateralInfo[
                        _bidCollaterals[_bidId].collateralAddresses.at(i)
                    ]

When a loan is repaid, the repayLoanCallback function is supposed to be invoked in-order to increment the totalPrincipalTokensRepaid failure to do which will result in that much tokens forever being considered as still lended

    function repayLoanCallback(
        uint256 _bidId,
        address repayer,
        uint256 principalAmount,
        uint256 interestAmount
    ) external onlyTellerV2 whenForwarderNotPaused whenNotPaused bidIsActiveForGroup(_bidId) { 
        totalPrincipalTokensRepaid += principalAmount;
        totalInterestCollected += interestAmount;

Since in this case repayment listener has not been setup, the totalPrincipalTokensRepaid won't be incremented. This will cause these tokens to forever be non-lendable

Internal pre-conditions

  1. ERC777 should be used as a collateral

External pre-conditions

No response

Attack Path

  1. Pool is created with an ERC777 collateral and has 100 tokens balance
  2. Attacker calls acceptSmartCommitmentWithRecipient in the SmartCommitmentForwarder with 100 as the bid amount
  3. Attacker re-enters when transferring the token and invokes repayLoanFullWithoutCollateralWithdraw

Net result: totalPrincipalTokensLended == 100 totalPrincipalTokensRepaid == 0

Even though 100 amount has been repaid, causing this amount to be forever non-lendable

Impact

Attacker can cause assets of pool to be non-lendable

PoC

No response

Mitigation

Add nonReentrant modifier in repay functions and lenderAcceptBid function