Skip to content

Latest commit

 

History

History
104 lines (80 loc) · 3.44 KB

014.md

File metadata and controls

104 lines (80 loc) · 3.44 KB

Bauer

medium

Reorg attack on bid creation without collateral can be used to steal funds

Summary

Attacker can steal funds via reorg attack if bid is accepted within a few blocks of being created

Vulnerability Detail

When creating a bid for a loan without collateral, the protocol generates bid id in a cumulative manner and store bid information into the mapping. An attacker can abuse this to steal funds via reorg. Assume borrower create a bid for a loan without collateral and accepted by a lender in the next block. This now allows an attacker to steal the funds via a reorg attack.They would maliciously insert their own transaction which they would use to create a bid with their own malicious parameters. This id is the same as the id created by the borrower before the reorg attack. Next, lender accept the bid and transfer tokens to malicious borrower.

function _submitBid(
        address _lendingToken,
        uint256 _marketplaceId,
        uint256 _principal,
        uint32 _duration,
        uint16 _APR,
        string calldata _metadataURI,
        address _receiver
    ) internal virtual returns (uint256 bidId_) {
        address sender = _msgSenderForMarket(_marketplaceId);

        (bool isVerified, ) = marketRegistry.isVerifiedBorrower(
            _marketplaceId,
            sender
        );

        require(isVerified, "Not verified borrower");

        require(
            !marketRegistry.isMarketClosed(_marketplaceId),
            "Market is closed"
        );

        // Set response bid ID.
        bidId_ = bidId;

        // Create and store our bid into the mapping
        Bid storage bid = bids[bidId];
        bid.borrower = sender;
        bid.receiver = _receiver != address(0) ? _receiver : bid.borrower;
        bid.marketplaceId = _marketplaceId;
        bid.loanDetails.lendingToken = ERC20(_lendingToken);
        bid.loanDetails.principal = _principal;
        bid.loanDetails.loanDuration = _duration;
        bid.loanDetails.timestamp = uint32(block.timestamp);

        // Set payment cycle type based on market setting (custom or monthly)
        (bid.terms.paymentCycle, bidPaymentCycleType[bidId]) = marketRegistry
            .getPaymentCycle(_marketplaceId);

        bid.terms.APR = _APR;

        bidDefaultDuration[bidId] = marketRegistry.getPaymentDefaultDuration(
            _marketplaceId
        );

        bidExpirationTime[bidId] = marketRegistry.getBidExpirationTime(
            _marketplaceId
        );

        bid.paymentType = marketRegistry.getPaymentType(_marketplaceId);

        bid.terms.paymentCycleAmount = V2Calculations
            .calculatePaymentCycleAmount(
                bid.paymentType,
                bidPaymentCycleType[bidId],
                _principal,
                _duration,
                bid.terms.paymentCycle,
                _APR
            );

        uris[bidId] = _metadataURI;
        bid.state = BidState.PENDING;

        emit SubmittedBid(
            bidId,
            bid.borrower,
            bid.receiver,
            keccak256(abi.encodePacked(_metadataURI))
        );

        // Store bid inside borrower bids mapping
        borrowerBids[bid.borrower].push(bidId);

        // Increment bid id counter
        bidId++;
    }

Impact

Attacker can steal funds via reorg.

Code Snippet

https://github.com/sherlock-audit/2023-03-teller/blob/main/teller-protocol-v2/packages/contracts/contracts/TellerV2.sol#L410

Tool used

Manual Review

Recommendation